Pull USB/PHY/Thunderbolt driver updates from Greg KH: "Here is the big set of USB, PHY, and Thunderbolt driver updates for 5.10-rc1. Lots of tiny different things for these subsystems are in here, including: - phy driver updates - thunderbolt / USB 4 updates and additions - USB gadget driver updates - xhci fixes and updates - typec driver additions and updates - api conversions to various drivers for core kernel api changes - new USB control message functions to make it harder to get wrong, as found by syzbot (took 2 tries to get it right) - lots of tiny USB driver fixes and updates all over the place All of these have been in linux-next for a while, with the exception of the last "obviously correct" patch that updated a FALLTHROUGH comment that got merged last weekend" * tag 'usb-5.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (374 commits) usb: musb: gadget: Use fallthrough pseudo-keyword usb: typec: Add QCOM PMIC typec detection driver USB: serial: option: add Cellient MPL200 card usb: typec: tcpci_maxim: Add support for Sink FRS usb: typec: tcpci: Implement callbacks for FRS usb: typec: tcpm: Add support for Sink Fast Role SWAP(FRS) usb: typec: tcpci_maxim: Chip level TCPC driver usb: typec: tcpci: Add set_vbus tcpci callback usb: typec: tcpci: Add a getter method to retrieve tcpm_port reference usbip: vhci_hcd: fix calling usb_hcd_giveback_urb() with irqs enabled usb: cdc-acm: add quirk to blacklist ETAS ES58X devices USB: serial: ftdi_sio: use cur_altsetting for consistency USB: serial: option: Add Telit FT980-KS composition USB: core: remove polling for /sys/kernel/debug/usb/devices usb: typec: add support for STUSB160x Type-C controller family usb: typec: add typec_find_pwr_opmode usb: typec: hd3ss3220: Use OF graph API to get the connector fwnode dt-bindings: usb: renesas,usb3-peri: Document HS and SS data bus dt-bindings: usb: convert ti,hd3ss3220 bindings to json-schema usb: dwc2: Fix INTR OUT transfers in DDMA mode. ...
Unified · Split
| @@ -48,6 +48,22 @@ properties: · 47 unmodified lines | |||
| 48 | - compatible | 48 | - compatible |
| 49 | - "#clock-cells" | 49 | - "#clock-cells" |
| 50 | 50 | ||
| 51 | reset: | ||
| 52 | type: object | ||
| 53 | |||
| 54 | properties: | ||
| 55 | compatible: | ||
| 56 | const: raspberrypi,firmware-reset | ||
| 57 | |||
| 58 | "#reset-cells": | ||
| 59 | const: 1 | ||
| 60 | description: > | ||
| 61 | The argument is the ID of the firmware reset line to affect. | ||
| 62 | |||
| 63 | required: | ||
| 64 | - compatible | ||
| 65 | - "#reset-cells" | ||
| 66 | |||
| 51 | additionalProperties: false | 67 | additionalProperties: false |
| 52 | 68 | ||
| 53 | required: | 69 | required: |
| @@ -66,5 +82,10 @@ examples: · 12 unmodified lines | |||
| 66 | compatible = "raspberrypi,firmware-clocks"; | 82 | compatible = "raspberrypi,firmware-clocks"; |
| 67 | #clock-cells = <1>; | 83 | #clock-cells = <1>; |
| 68 | }; | 84 | }; |
| 85 | |||
| 86 | reset: reset { | ||
| 87 | compatible = "raspberrypi,firmware-reset"; | ||
| 88 | #reset-cells = <1>; | ||
| 89 | }; | ||
| 69 | }; | 90 | }; |
| 70 | ... | 91 | ... |
| @@ -1,7 +1,7 @@ | |||
| 1 | * Freescale i.MX8MQ USB3 PHY binding | 1 | * Freescale i.MX8MQ USB3 PHY binding |
| 2 | 2 | ||
| 3 | Required properties: | 3 | Required properties: |
| 4 | - compatible: Should be "fsl,imx8mq-usb-phy" | 4 | - compatible: Should be "fsl,imx8mq-usb-phy" or "fsl,imx8mp-usb-phy" |
| 5 | - #phys-cells: must be 0 (see phy-bindings.txt in this directory) | 5 | - #phys-cells: must be 0 (see phy-bindings.txt in this directory) |
| 6 | - reg: The base address and length of the registers | 6 | - reg: The base address and length of the registers |
| 7 | - clocks: phandles to the clocks for each clock listed in clock-names | 7 | - clocks: phandles to the clocks for each clock listed in clock-names |
| @@ -23,7 +23,9 @@ description: |+ · 22 unmodified lines | |||
| 23 | 23 | ||
| 24 | properties: | 24 | properties: |
| 25 | compatible: | 25 | compatible: |
| 26 | const: intel,lgm-emmc-phy | 26 | oneOf: |
| 27 | - const: intel,lgm-emmc-phy | ||
| 28 | - const: intel,keembay-emmc-phy | ||
| 27 | 29 | ||
| 28 | "#phy-cells": | 30 | "#phy-cells": |
| 29 | const: 0 | 31 | const: 0 |
| @@ -34,6 +36,10 @@ properties: · 4 unmodified lines | |||
| 34 | clocks: | 36 | clocks: |
| 35 | maxItems: 1 | 37 | maxItems: 1 |
| 36 | 38 | ||
| 39 | clock-names: | ||
| 40 | items: | ||
| 41 | - const: emmcclk | ||
| 42 | |||
| 37 | required: | 43 | required: |
| 38 | - "#phy-cells" | 44 | - "#phy-cells" |
| 39 | - compatible | 45 | - compatible |
| @@ -57,4 +63,13 @@ examples: · 17 unmodified lines | |||
| 57 | #phy-cells = <0>; | 63 | #phy-cells = <0>; |
| 58 | }; | 64 | }; |
| 59 | }; | 65 | }; |
| 66 | |||
| 67 | - | | ||
| 68 | phy@20290000 { | ||
| 69 | compatible = "intel,keembay-emmc-phy"; | ||
| 70 | reg = <0x20290000 0x54>; | ||
| 71 | clocks = <&emmc>; | ||
| 72 | clock-names = "emmcclk"; | ||
| 73 | #phy-cells = <0>; | ||
| 74 | }; | ||
| 60 | ... | 75 | ... |
| @@ -0,0 +1,58 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/phy/intel,lgm-usb-phy.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Intel LGM USB PHY Device Tree Bindings | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Vadivel Murugan Ramuthevar <vadivel.muruganx.ramuthevar@linux.intel.com> | ||
| 11 | |||
| 12 | properties: | ||
| 13 | compatible: | ||
| 14 | const: intel,lgm-usb-phy | ||
| 15 | |||
| 16 | reg: | ||
| 17 | maxItems: 1 | ||
| 18 | |||
| 19 | clocks: | ||
| 20 | maxItems: 1 | ||
| 21 | |||
| 22 | resets: | ||
| 23 | items: | ||
| 24 | - description: USB PHY and Host controller reset | ||
| 25 | - description: APB BUS reset | ||
| 26 | - description: General Hardware reset | ||
| 27 | |||
| 28 | reset-names: | ||
| 29 | items: | ||
| 30 | - const: phy | ||
| 31 | - const: apb | ||
| 32 | - const: phy31 | ||
| 33 | |||
| 34 | "#phy-cells": | ||
| 35 | const: 0 | ||
| 36 | |||
| 37 | required: | ||
| 38 | - compatible | ||
| 39 | - clocks | ||
| 40 | - reg | ||
| 41 | - resets | ||
| 42 | - reset-names | ||
| 43 | - "#phy-cells" | ||
| 44 | |||
| 45 | additionalProperties: false | ||
| 46 | |||
| 47 | examples: | ||
| 48 | - | | ||
| 49 | usb-phy@e7e00000 { | ||
| 50 | compatible = "intel,lgm-usb-phy"; | ||
| 51 | reg = <0xe7e00000 0x10000>; | ||
| 52 | clocks = <&cgu0 153>; | ||
| 53 | resets = <&rcu 0x70 0x24>, | ||
| 54 | <&rcu 0x70 0x26>, | ||
| 55 | <&rcu 0x70 0x28>; | ||
| 56 | reset-names = "phy", "apb", "phy31"; | ||
| 57 | #phy-cells = <0>; | ||
| 58 | }; | ||
| @@ -4,11 +4,13 @@ · 3 unmodified lines | |||
| 4 | $id: "http://devicetree.org/schemas/phy/phy-cadence-torrent.yaml#" | 4 | $id: "http://devicetree.org/schemas/phy/phy-cadence-torrent.yaml#" |
| 5 | $schema: "http://devicetree.org/meta-schemas/core.yaml#" | 5 | $schema: "http://devicetree.org/meta-schemas/core.yaml#" |
| 6 | 6 | ||
| 7 | title: Cadence Torrent SD0801 PHY binding for DisplayPort | 7 | title: Cadence Torrent SD0801 PHY binding |
| 8 | 8 | ||
| 9 | description: | 9 | description: |
| 10 | This binding describes the Cadence SD0801 PHY (also known as Torrent PHY) | 10 | This binding describes the Cadence SD0801 PHY (also known as Torrent PHY) |
| 11 | hardware included with the Cadence MHDP DisplayPort controller. | 11 | hardware included with the Cadence MHDP DisplayPort controller. Torrent |
| 12 | PHY also supports multilink multiprotocol combinations including protocols | ||
| 13 | such as PCIe, USB, SGMII, QSGMII etc. | ||
| 12 | 14 | ||
| 13 | maintainers: | 15 | maintainers: |
| 14 | - Swapnil Jakhade <sjakhade@cadence.com> | 16 | - Swapnil Jakhade <sjakhade@cadence.com> |
| @@ -49,13 +51,21 @@ properties: · 34 unmodified lines | |||
| 49 | - const: dptx_phy | 51 | - const: dptx_phy |
| 50 | 52 | ||
| 51 | resets: | 53 | resets: |
| 52 | maxItems: 1 | 54 | minItems: 1 |
| 53 | description: | 55 | maxItems: 2 |
| 54 | Torrent PHY reset. | 56 | items: |
| 55 | See Documentation/devicetree/bindings/reset/reset.txt | 57 | - description: Torrent PHY reset. |
| 58 | - description: Torrent APB reset. This is optional. | ||
| 59 | |||
| 60 | reset-names: | ||
| 61 | minItems: 1 | ||
| 62 | maxItems: 2 | ||
| 63 | items: | ||
| 64 | - const: torrent_reset | ||
| 65 | - const: torrent_apb | ||
| 56 | 66 | ||
| 57 | patternProperties: | 67 | patternProperties: |
| 58 | '^phy@[0-7]+$': | 68 | '^phy@[0-3]$': |
| 59 | type: object | 69 | type: object |
| 60 | description: | 70 | description: |
| 61 | Each group of PHY lanes with a single master lane should be represented as a sub-node. | 71 | Each group of PHY lanes with a single master lane should be represented as a sub-node. |
| @@ -63,6 +73,8 @@ patternProperties: · 1 unmodified line | |||
| 63 | reg: | 73 | reg: |
| 64 | description: | 74 | description: |
| 65 | The master lane number. This is the lowest numbered lane in the lane group. | 75 | The master lane number. This is the lowest numbered lane in the lane group. |
| 76 | minimum: 0 | ||
| 77 | maximum: 3 | ||
| 66 | 78 | ||
| 67 | resets: | 79 | resets: |
| 68 | minItems: 1 | 80 | minItems: 1 |
| @@ -78,15 +90,25 @@ patternProperties: · 9 unmodified lines | |||
| 78 | Specifies the type of PHY for which the group of PHY lanes is used. | 90 | Specifies the type of PHY for which the group of PHY lanes is used. |
| 79 | Refer include/dt-bindings/phy/phy.h. Constants from the header should be used. | 91 | Refer include/dt-bindings/phy/phy.h. Constants from the header should be used. |
| 80 | $ref: /schemas/types.yaml#/definitions/uint32 | 92 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 81 | enum: [1, 2, 3, 4, 5, 6] | 93 | minimum: 1 |
| 94 | maximum: 9 | ||
| 82 | 95 | ||
| 83 | cdns,num-lanes: | 96 | cdns,num-lanes: |
| 84 | description: | 97 | description: |
| 85 | Number of DisplayPort lanes. | 98 | Number of lanes. |
| 86 | $ref: /schemas/types.yaml#/definitions/uint32 | 99 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 87 | enum: [1, 2, 4] | 100 | enum: [1, 2, 3, 4] |
| 88 | default: 4 | 101 | default: 4 |
| 89 | 102 | ||
| 103 | cdns,ssc-mode: | ||
| 104 | description: | ||
| 105 | Specifies the Spread Spectrum Clocking mode used. It can be NO_SSC, | ||
| 106 | EXTERNAL_SSC or INTERNAL_SSC. | ||
| 107 | Refer include/dt-bindings/phy/phy-cadence-torrent.h for the constants to be used. | ||
| 108 | $ref: /schemas/types.yaml#/definitions/uint32 | ||
| 109 | enum: [0, 1, 2] | ||
| 110 | default: 0 | ||
| 111 | |||
| 90 | cdns,max-bit-rate: | 112 | cdns,max-bit-rate: |
| 91 | description: | 113 | description: |
| 92 | Maximum DisplayPort link bit rate to use, in Mbps | 114 | Maximum DisplayPort link bit rate to use, in Mbps |
| @@ -99,6 +121,7 @@ patternProperties: · 6 unmodified lines | |||
| 99 | - resets | 121 | - resets |
| 100 | - "#phy-cells" | 122 | - "#phy-cells" |
| 101 | - cdns,phy-type | 123 | - cdns,phy-type |
| 124 | - cdns,num-lanes | ||
| 102 | 125 | ||
| 103 | additionalProperties: false | 126 | additionalProperties: false |
| 104 | 127 | ||
| @@ -111,6 +134,7 @@ required: · 6 unmodified lines | |||
| 111 | - reg | 134 | - reg |
| 112 | - reg-names | 135 | - reg-names |
| 113 | - resets | 136 | - resets |
| 137 | - reset-names | ||
| 114 | 138 | ||
| 115 | additionalProperties: false | 139 | additionalProperties: false |
| 116 | 140 | ||
| @@ -128,18 +152,56 @@ examples: · 11 unmodified lines | |||
| 128 | <0xf0 0xfb030a00 0x0 0x00000040>; | 152 | <0xf0 0xfb030a00 0x0 0x00000040>; |
| 129 | reg-names = "torrent_phy", "dptx_phy"; | 153 | reg-names = "torrent_phy", "dptx_phy"; |
| 130 | resets = <&phyrst 0>; | 154 | resets = <&phyrst 0>; |
| 155 | reset-names = "torrent_reset"; | ||
| 131 | clocks = <&ref_clk>; | 156 | clocks = <&ref_clk>; |
| 132 | clock-names = "refclk"; | 157 | clock-names = "refclk"; |
| 133 | #address-cells = <1>; | 158 | #address-cells = <1>; |
| 134 | #size-cells = <0>; | 159 | #size-cells = <0>; |
| 135 | phy@0 { | 160 | phy@0 { |
| 136 | reg = <0>; | 161 | reg = <0>; |
| 137 | resets = <&phyrst 1>, <&phyrst 2>, | 162 | resets = <&phyrst 1>, <&phyrst 2>, |
| 138 | <&phyrst 3>, <&phyrst 4>; | 163 | <&phyrst 3>, <&phyrst 4>; |
| 139 | #phy-cells = <0>; | 164 | #phy-cells = <0>; |
| 140 | cdns,phy-type = <PHY_TYPE_DP>; | 165 | cdns,phy-type = <PHY_TYPE_DP>; |
| 141 | cdns,num-lanes = <4>; | 166 | cdns,num-lanes = <4>; |
| 142 | cdns,max-bit-rate = <8100>; | 167 | cdns,max-bit-rate = <8100>; |
| 168 | }; | ||
| 169 | }; | ||
| 170 | }; | ||
| 171 | - | | ||
| 172 | #include <dt-bindings/phy/phy.h> | ||
| 173 | #include <dt-bindings/phy/phy-cadence-torrent.h> | ||
| 174 | |||
| 175 | bus { | ||
| 176 | #address-cells = <2>; | ||
| 177 | #size-cells = <2>; | ||
| 178 | |||
| 179 | torrent-phy@f0fb500000 { | ||
| 180 | compatible = "cdns,torrent-phy"; | ||
| 181 | reg = <0xf0 0xfb500000 0x0 0x00100000>; | ||
| 182 | reg-names = "torrent_phy"; | ||
| 183 | resets = <&phyrst 0>, <&phyrst 1>; | ||
| 184 | reset-names = "torrent_reset", "torrent_apb"; | ||
| 185 | clocks = <&ref_clk>; | ||
| 186 | clock-names = "refclk"; | ||
| 187 | #address-cells = <1>; | ||
| 188 | #size-cells = <0>; | ||
| 189 | phy@0 { | ||
| 190 | reg = <0>; | ||
| 191 | resets = <&phyrst 2>, <&phyrst 3>; | ||
| 192 | #phy-cells = <0>; | ||
| 193 | cdns,phy-type = <PHY_TYPE_PCIE>; | ||
| 194 | cdns,num-lanes = <2>; | ||
| 195 | cdns,ssc-mode = <TORRENT_SERDES_NO_SSC>; | ||
| 196 | }; | ||
| 197 | |||
| 198 | phy@2 { | ||
| 199 | reg = <2>; | ||
| 200 | resets = <&phyrst 4>; | ||
| 201 | #phy-cells = <0>; | ||
| 202 | cdns,phy-type = <PHY_TYPE_SGMII>; | ||
| 203 | cdns,num-lanes = <1>; | ||
| 204 | cdns,ssc-mode = <TORRENT_SERDES_NO_SSC>; | ||
| 143 | }; | 205 | }; |
| 144 | }; | 206 | }; |
| 145 | }; | 207 | }; |
| @@ -13,17 +13,21 @@ maintainers: · 12 unmodified lines | |||
| 13 | properties: | 13 | properties: |
| 14 | compatible: | 14 | compatible: |
| 15 | enum: | 15 | enum: |
| 16 | - qcom,sc7180-qmp-usb3-dp-phy | ||
| 16 | - qcom,sc7180-qmp-usb3-phy | 17 | - qcom,sc7180-qmp-usb3-phy |
| 18 | - qcom,sdm845-qmp-usb3-dp-phy | ||
| 17 | - qcom,sdm845-qmp-usb3-phy | 19 | - qcom,sdm845-qmp-usb3-phy |
| 18 | reg: | 20 | reg: |
| 19 | items: | 21 | items: |
| 20 | - description: Address and length of PHY's common serdes block. | 22 | - description: Address and length of PHY's USB serdes block. |
| 21 | - description: Address and length of the DP_COM control block. | 23 | - description: Address and length of the DP_COM control block. |
| 24 | - description: Address and length of PHY's DP serdes block. | ||
| 22 | 25 | ||
| 23 | reg-names: | 26 | reg-names: |
| 24 | items: | 27 | items: |
| 25 | - const: reg-base | 28 | - const: usb |
| 26 | - const: dp_com | 29 | - const: dp_com |
| 30 | - const: dp | ||
| 27 | 31 | ||
| 28 | "#clock-cells": | 32 | "#clock-cells": |
| 29 | enum: [ 1, 2 ] | 33 | enum: [ 1, 2 ] |
| @@ -74,16 +78,74 @@ properties: · 44 unmodified lines | |||
| 74 | 78 | ||
| 75 | #Required nodes: | 79 | #Required nodes: |
| 76 | patternProperties: | 80 | patternProperties: |
| 77 | "^phy@[0-9a-f]+$": | 81 | "^usb3-phy@[0-9a-f]+$": |
| 78 | type: object | 82 | type: object |
| 79 | description: | 83 | description: |
| 80 | Each device node of QMP phy is required to have as many child nodes as | 84 | The USB3 PHY. |
| 81 | the number of lanes the PHY has. | 85 | |
| 86 | properties: | ||
| 87 | reg: | ||
| 88 | items: | ||
| 89 | - description: Address and length of TX. | ||
| 90 | - description: Address and length of RX. | ||
| 91 | - description: Address and length of PCS. | ||
| 92 | - description: Address and length of TX2. | ||
| 93 | - description: Address and length of RX2. | ||
| 94 | - description: Address and length of pcs_misc. | ||
| 95 | |||
| 96 | clocks: | ||
| 97 | items: | ||
| 98 | - description: pipe clock | ||
| 99 | |||
| 100 | clock-names: | ||
| 101 | items: | ||
| 102 | - const: pipe0 | ||
| 103 | |||
| 104 | clock-output-names: | ||
| 105 | items: | ||
| 106 | - const: usb3_phy_pipe_clk_src | ||
| 107 | |||
| 108 | '#clock-cells': | ||
| 109 | const: 0 | ||
| 110 | |||
| 111 | '#phy-cells': | ||
| 112 | const: 0 | ||
| 113 | |||
| 114 | required: | ||
| 115 | - reg | ||
| 116 | - clocks | ||
| 117 | - clock-names | ||
| 118 | - '#clock-cells' | ||
| 119 | - '#phy-cells' | ||
| 120 | |||
| 121 | "^dp-phy@[0-9a-f]+$": | ||
| 122 | type: object | ||
| 123 | description: | ||
| 124 | The DP PHY. | ||
| 125 | |||
| 126 | properties: | ||
| 127 | reg: | ||
| 128 | items: | ||
| 129 | - description: Address and length of TX. | ||
| 130 | - description: Address and length of RX. | ||
| 131 | - description: Address and length of PCS. | ||
| 132 | - description: Address and length of TX2. | ||
| 133 | - description: Address and length of RX2. | ||
| 134 | |||
| 135 | '#clock-cells': | ||
| 136 | const: 1 | ||
| 137 | |||
| 138 | '#phy-cells': | ||
| 139 | const: 0 | ||
| 140 | |||
| 141 | required: | ||
| 142 | - reg | ||
| 143 | - '#clock-cells' | ||
| 144 | - '#phy-cells' | ||
| 82 | 145 | ||
| 83 | required: | 146 | required: |
| 84 | - compatible | 147 | - compatible |
| 85 | - reg | 148 | - reg |
| 86 | - reg-names | ||
| 87 | - "#clock-cells" | 149 | - "#clock-cells" |
| 88 | - "#address-cells" | 150 | - "#address-cells" |
| 89 | - "#size-cells" | 151 | - "#size-cells" |
| @@ -101,14 +163,15 @@ examples: · 11 unmodified lines | |||
| 101 | - | | 163 | - | |
| 102 | #include <dt-bindings/clock/qcom,gcc-sdm845.h> | 164 | #include <dt-bindings/clock/qcom,gcc-sdm845.h> |
| 103 | usb_1_qmpphy: phy-wrapper@88e9000 { | 165 | usb_1_qmpphy: phy-wrapper@88e9000 { |
| 104 | compatible = "qcom,sdm845-qmp-usb3-phy"; | 166 | compatible = "qcom,sdm845-qmp-usb3-dp-phy"; |
| 105 | reg = <0x088e9000 0x18c>, | 167 | reg = <0x088e9000 0x18c>, |
| 106 | <0x088e8000 0x10>; | 168 | <0x088e8000 0x10>, |
| 107 | reg-names = "reg-base", "dp_com"; | 169 | <0x088ea000 0x40>; |
| 170 | reg-names = "usb", "dp_com", "dp"; | ||
| 108 | #clock-cells = <1>; | 171 | #clock-cells = <1>; |
| 109 | #address-cells = <1>; | 172 | #address-cells = <1>; |
| 110 | #size-cells = <1>; | 173 | #size-cells = <1>; |
| 111 | ranges = <0x0 0x088e9000 0x1000>; | 174 | ranges = <0x0 0x088e9000 0x2000>; |
| 112 | 175 | ||
| 113 | clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>, | 176 | clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>, |
| 114 | <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>, | 177 | <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>, |
| @@ -123,7 +186,7 @@ examples: · 8 unmodified lines | |||
| 123 | vdda-phy-supply = <&vdda_usb2_ss_1p2>; | 186 | vdda-phy-supply = <&vdda_usb2_ss_1p2>; |
| 124 | vdda-pll-supply = <&vdda_usb2_ss_core>; | 187 | vdda-pll-supply = <&vdda_usb2_ss_core>; |
| 125 | 188 | ||
| 126 | phy@200 { | 189 | usb3-phy@200 { |
| 127 | reg = <0x200 0x128>, | 190 | reg = <0x200 0x128>, |
| 128 | <0x400 0x200>, | 191 | <0x400 0x200>, |
| 129 | <0xc00 0x218>, | 192 | <0xc00 0x218>, |
| @@ -136,4 +199,14 @@ examples: · 6 unmodified lines | |||
| 136 | clock-names = "pipe0"; | 199 | clock-names = "pipe0"; |
| 137 | clock-output-names = "usb3_phy_pipe_clk_src"; | 200 | clock-output-names = "usb3_phy_pipe_clk_src"; |
| 138 | }; | 201 | }; |
| 202 | |||
| 203 | dp-phy@88ea200 { | ||
| 204 | reg = <0xa200 0x200>, | ||
| 205 | <0xa400 0x200>, | ||
| 206 | <0xaa00 0x200>, | ||
| 207 | <0xa600 0x200>, | ||
| 208 | <0xa800 0x200>; | ||
| 209 | #clock-cells = <1>; | ||
| 210 | #phy-cells = <0>; | ||
| 211 | }; | ||
| 139 | }; | 212 | }; |
| @@ -0,0 +1,76 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/phy/socionext,uniphier-ahci-phy.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Socionext UniPhier AHCI PHY | ||
| 8 | |||
| 9 | description: | | ||
| 10 | This describes the deivcetree bindings for PHY interfaces built into | ||
| 11 | AHCI controller implemented on Socionext UniPhier SoCs. | ||
| 12 | |||
| 13 | maintainers: | ||
| 14 | - Kunihiko Hayashi <hayashi.kunihiko@socionext.com> | ||
| 15 | |||
| 16 | properties: | ||
| 17 | compatible: | ||
| 18 | enum: | ||
| 19 | - socionext,uniphier-pxs2-ahci-phy | ||
| 20 | - socionext,uniphier-pxs3-ahci-phy | ||
| 21 | |||
| 22 | reg: | ||
| 23 | description: PHY register region (offset and length) | ||
| 24 | |||
| 25 | "#phy-cells": | ||
| 26 | const: 0 | ||
| 27 | |||
| 28 | clocks: | ||
| 29 | maxItems: 2 | ||
| 30 | |||
| 31 | clock-names: | ||
| 32 | oneOf: | ||
| 33 | - items: # for PXs2 | ||
| 34 | - const: link | ||
| 35 | - items: # for others | ||
| 36 | - const: link | ||
| 37 | - const: phy | ||
| 38 | |||
| 39 | resets: | ||
| 40 | maxItems: 2 | ||
| 41 | |||
| 42 | reset-names: | ||
| 43 | items: | ||
| 44 | - const: link | ||
| 45 | - const: phy | ||
| 46 | |||
| 47 | required: | ||
| 48 | - compatible | ||
| 49 | - reg | ||
| 50 | - "#phy-cells" | ||
| 51 | - clocks | ||
| 52 | - clock-names | ||
| 53 | - resets | ||
| 54 | - reset-names | ||
| 55 | |||
| 56 | additionalProperties: false | ||
| 57 | |||
| 58 | examples: | ||
| 59 | - | | ||
| 60 | ahci-glue@65700000 { | ||
| 61 | compatible = "socionext,uniphier-pxs3-ahci-glue", | ||
| 62 | "simple-mfd"; | ||
| 63 | #address-cells = <1>; | ||
| 64 | #size-cells = <1>; | ||
| 65 | ranges = <0 0x65700000 0x100>; | ||
| 66 | |||
| 67 | ahci_phy: phy@10 { | ||
| 68 | compatible = "socionext,uniphier-pxs3-ahci-phy"; | ||
| 69 | reg = <0x10 0x10>; | ||
| 70 | #phy-cells = <0>; | ||
| 71 | clock-names = "link", "phy"; | ||
| 72 | clocks = <&sys_clk 28>, <&sys_clk 30>; | ||
| 73 | reset-names = "link", "phy"; | ||
| 74 | resets = <&sys_rst 28>, <&sys_rst 30>; | ||
| 75 | }; | ||
| 76 | }; | ||
| @@ -0,0 +1,74 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/phy/ti,omap-usb2.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: OMAP USB2 PHY | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Kishon Vijay Abraham I <kishon@ti.com> | ||
| 11 | - Roger Quadros <rogerq@ti.com> | ||
| 12 | |||
| 13 | properties: | ||
| 14 | compatible: | ||
| 15 | oneOf: | ||
| 16 | - items: | ||
| 17 | - enum: | ||
| 18 | - ti,dra7x-usb2 | ||
| 19 | - ti,dra7x-usb2-phy2 | ||
| 20 | - ti,am654-usb2 | ||
| 21 | - enum: | ||
| 22 | - ti,omap-usb2 | ||
| 23 | - items: | ||
| 24 | - const: ti,am437x-usb2 | ||
| 25 | - items: | ||
| 26 | - const: ti,omap-usb2 | ||
| 27 | |||
| 28 | reg: | ||
| 29 | maxItems: 1 | ||
| 30 | |||
| 31 | "#phy-cells": | ||
| 32 | const: 0 | ||
| 33 | |||
| 34 | clocks: | ||
| 35 | minItems: 1 | ||
| 36 | items: | ||
| 37 | - description: wakeup clock | ||
| 38 | - description: reference clock | ||
| 39 | |||
| 40 | clock-names: | ||
| 41 | minItems: 1 | ||
| 42 | items: | ||
| 43 | - const: wkupclk | ||
| 44 | - const: refclk | ||
| 45 | |||
| 46 | syscon-phy-power: | ||
| 47 | $ref: /schemas/types.yaml#definitions/phandle-array | ||
| 48 | description: | ||
| 49 | phandle/offset pair. Phandle to the system control module and | ||
| 50 | register offset to power on/off the PHY. | ||
| 51 | |||
| 52 | ctrl-module: | ||
| 53 | $ref: /schemas/types.yaml#definitions/phandle | ||
| 54 | description: | ||
| 55 | (deprecated) phandle of the control module used by PHY driver | ||
| 56 | to power on the PHY. Use syscon-phy-power instead. | ||
| 57 | |||
| 58 | required: | ||
| 59 | - compatible | ||
| 60 | - reg | ||
| 61 | - "#phy-cells" | ||
| 62 | - clocks | ||
| 63 | - clock-names | ||
| 64 | |||
| 65 | examples: | ||
| 66 | - | | ||
| 67 | usb0_phy: phy@4100000 { | ||
| 68 | compatible = "ti,am654-usb2", "ti,omap-usb2"; | ||
| 69 | reg = <0x4100000 0x54>; | ||
| 70 | syscon-phy-power = <&scm_conf 0x4000>; | ||
| 71 | clocks = <&k3_clks 151 0>, <&k3_clks 151 1>; | ||
| 72 | clock-names = "wkupclk", "refclk"; | ||
| 73 | #phy-cells = <0>; | ||
| 74 | }; | ||
| @@ -45,9 +45,15 @@ properties: · 44 unmodified lines | |||
| 45 | ranges: true | 45 | ranges: true |
| 46 | 46 | ||
| 47 | assigned-clocks: | 47 | assigned-clocks: |
| 48 | minItems: 1 | ||
| 48 | maxItems: 2 | 49 | maxItems: 2 |
| 49 | 50 | ||
| 50 | assigned-clock-parents: | 51 | assigned-clock-parents: |
| 52 | minItems: 1 | ||
| 53 | maxItems: 2 | ||
| 54 | |||
| 55 | assigned-clock-rates: | ||
| 56 | minItems: 1 | ||
| 51 | maxItems: 2 | 57 | maxItems: 2 |
| 52 | 58 | ||
| 53 | typec-dir-gpios: | 59 | typec-dir-gpios: |
| @@ -119,9 +125,10 @@ patternProperties: · 65 unmodified lines | |||
| 119 | logic. | 125 | logic. |
| 120 | properties: | 126 | properties: |
| 121 | clocks: | 127 | clocks: |
| 128 | minItems: 2 | ||
| 122 | maxItems: 4 | 129 | maxItems: 4 |
| 123 | description: Phandle to four clock nodes representing the inputs to | 130 | description: Phandle to two (Torrent) or four (Sierra) clock nodes representing |
| 124 | refclk_dig | 131 | the inputs to refclk_dig |
| 125 | 132 | ||
| 126 | "#clock-cells": | 133 | "#clock-cells": |
| 127 | const: 0 | 134 | const: 0 |
| @@ -203,7 +210,7 @@ examples: · 75 unmodified lines | |||
| 203 | }; | 210 | }; |
| 204 | 211 | ||
| 205 | refclk-dig { | 212 | refclk-dig { |
| 206 | clocks = <&k3_clks 292 11>, <&k3_clks 292 0>, | 213 | clocks = <&k3_clks 292 11>, <&k3_clks 292 0>, |
| 207 | <&dummy_cmn_refclk>, <&dummy_cmn_refclk1>; | 214 | <&dummy_cmn_refclk>, <&dummy_cmn_refclk1>; |
| 208 | #clock-cells = <0>; | 215 | #clock-cells = <0>; |
| 209 | assigned-clocks = <&wiz0_refclk_dig>; | 216 | assigned-clocks = <&wiz0_refclk_dig>; |
| @@ -27,43 +27,6 @@ omap_control_usb: omap-control-usb@4a002300 { · 26 unmodified lines | |||
| 27 | reg-names = "otghs_control"; | 27 | reg-names = "otghs_control"; |
| 28 | }; | 28 | }; |
| 29 | 29 | ||
| 30 | OMAP USB2 PHY | ||
| 31 | |||
| 32 | Required properties: | ||
| 33 | - compatible: Should be "ti,omap-usb2" | ||
| 34 | Should be "ti,dra7x-usb2" for the 1st instance of USB2 PHY on | ||
| 35 | DRA7x | ||
| 36 | Should be "ti,dra7x-usb2-phy2" for the 2nd instance of USB2 PHY | ||
| 37 | in DRA7x | ||
| 38 | Should be "ti,am654-usb2" for the USB2 PHYs on AM654. | ||
| 39 | - reg : Address and length of the register set for the device. | ||
| 40 | - #phy-cells: determine the number of cells that should be given in the | ||
| 41 | phandle while referencing this phy. | ||
| 42 | - clocks: a list of phandles and clock-specifier pairs, one for each entry in | ||
| 43 | clock-names. | ||
| 44 | - clock-names: should include: | ||
| 45 | * "wkupclk" - wakeup clock. | ||
| 46 | * "refclk" - reference clock (optional). | ||
| 47 | |||
| 48 | Deprecated properties: | ||
| 49 | - ctrl-module : phandle of the control module used by PHY driver to power on | ||
| 50 | the PHY. | ||
| 51 | |||
| 52 | Recommended properies: | ||
| 53 | - syscon-phy-power : phandle/offset pair. Phandle to the system control | ||
| 54 | module and the register offset to power on/off the PHY. | ||
| 55 | |||
| 56 | This is usually a subnode of ocp2scp to which it is connected. | ||
| 57 | |||
| 58 | usb2phy@4a0ad080 { | ||
| 59 | compatible = "ti,omap-usb2"; | ||
| 60 | reg = <0x4a0ad080 0x58>; | ||
| 61 | ctrl-module = <&omap_control_usb>; | ||
| 62 | #phy-cells = <0>; | ||
| 63 | clocks = <&usb_phy_cm_clk32k>, <&usb_otg_ss_refclk960m>; | ||
| 64 | clock-names = "wkupclk", "refclk"; | ||
| 65 | }; | ||
| 66 | |||
| 67 | TI PIPE3 PHY | 30 | TI PIPE3 PHY |
| 68 | 31 | ||
| 69 | Required properties: | 32 | Required properties: |
| @@ -25,13 +25,14 @@ description: | · 24 unmodified lines | |||
| 25 | The Amlogic A1 embeds a DWC3 USB IP Core configured for USB2 in | 25 | The Amlogic A1 embeds a DWC3 USB IP Core configured for USB2 in |
| 26 | host-only mode. | 26 | host-only mode. |
| 27 | 27 | ||
| 28 | The Amlogic GXL & GXM SoCs doesn't embed an USB3 PHY. | 28 | The Amlogic GXL, GXM & AXG SoCs doesn't embed an USB3 PHY. |
| 29 | 29 | ||
| 30 | properties: | 30 | properties: |
| 31 | compatible: | 31 | compatible: |
| 32 | enum: | 32 | enum: |
| 33 | - amlogic,meson-gxl-usb-ctrl | 33 | - amlogic,meson-gxl-usb-ctrl |
| 34 | - amlogic,meson-gxm-usb-ctrl | 34 | - amlogic,meson-gxm-usb-ctrl |
| 35 | - amlogic,meson-axg-usb-ctrl | ||
| 35 | - amlogic,meson-g12a-usb-ctrl | 36 | - amlogic,meson-g12a-usb-ctrl |
| 36 | - amlogic,meson-a1-usb-ctrl | 37 | - amlogic,meson-a1-usb-ctrl |
| 37 | 38 | ||
| @@ -151,6 +152,25 @@ allOf: · 113 unmodified lines | |||
| 151 | 152 | ||
| 152 | required: | 153 | required: |
| 153 | - clock-names | 154 | - clock-names |
| 155 | - if: | ||
| 156 | properties: | ||
| 157 | compatible: | ||
| 158 | enum: | ||
| 159 | - amlogic,meson-axg-usb-ctrl | ||
| 160 | |||
| 161 | then: | ||
| 162 | properties: | ||
| 163 | phy-names: | ||
| 164 | items: | ||
| 165 | - const: usb2-phy1 # USB2 PHY1 if USBOTG_B port is used | ||
| 166 | clocks: | ||
| 167 | minItems: 2 | ||
| 168 | clock-names: | ||
| 169 | items: | ||
| 170 | - const: usb_ctrl | ||
| 171 | - const: ddr | ||
| 172 | required: | ||
| 173 | - clock-names | ||
| 154 | - if: | 174 | - if: |
| 155 | properties: | 175 | properties: |
| 156 | compatible: | 176 | compatible: |
| @@ -82,6 +82,7 @@ Required properties: · 81 unmodified lines | |||
| 82 | "atmel,at91sam9rl-udc" | 82 | "atmel,at91sam9rl-udc" |
| 83 | "atmel,at91sam9g45-udc" | 83 | "atmel,at91sam9g45-udc" |
| 84 | "atmel,sama5d3-udc" | 84 | "atmel,sama5d3-udc" |
| 85 | "microchip,sam9x60-udc" | ||
| 85 | - reg: Address and length of the register set for the device | 86 | - reg: Address and length of the register set for the device |
| 86 | - interrupts: Should contain usba interrupt | 87 | - interrupts: Should contain usba interrupt |
| 87 | - clocks: Should reference the peripheral and host clocks | 88 | - clocks: Should reference the peripheral and host clocks |
| @@ -0,0 +1,96 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/usb/cdns,usb3.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Cadence USBSS-DRD controller bindings | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Pawel Laszczak <pawell@cadence.com> | ||
| 11 | |||
| 12 | properties: | ||
| 13 | compatible: | ||
| 14 | const: cdns,usb3 | ||
| 15 | |||
| 16 | reg: | ||
| 17 | items: | ||
| 18 | - description: OTG controller registers | ||
| 19 | - description: XHCI Host controller registers | ||
| 20 | - description: DEVICE controller registers | ||
| 21 | |||
| 22 | reg-names: | ||
| 23 | items: | ||
| 24 | - const: otg | ||
| 25 | - const: xhci | ||
| 26 | - const: dev | ||
| 27 | |||
| 28 | interrupts: | ||
| 29 | items: | ||
| 30 | - description: OTG/DRD controller interrupt | ||
| 31 | - description: XHCI host controller interrupt | ||
| 32 | - description: Device controller interrupt | ||
| 33 | |||
| 34 | interrupt-names: | ||
| 35 | items: | ||
| 36 | - const: host | ||
| 37 | - const: peripheral | ||
| 38 | - const: otg | ||
| 39 | |||
| 40 | dr_mode: | ||
| 41 | enum: [host, otg, peripheral] | ||
| 42 | |||
| 43 | maximum-speed: | ||
| 44 | enum: [super-speed, high-speed, full-speed] | ||
| 45 | |||
| 46 | phys: | ||
| 47 | minItems: 1 | ||
| 48 | maxItems: 2 | ||
| 49 | |||
| 50 | phy-names: | ||
| 51 | minItems: 1 | ||
| 52 | maxItems: 2 | ||
| 53 | items: | ||
| 54 | anyOf: | ||
| 55 | - const: cdns3,usb2-phy | ||
| 56 | - const: cdns3,usb3-phy | ||
| 57 | |||
| 58 | cdns,on-chip-buff-size: | ||
| 59 | description: | ||
| 60 | size of memory intended as internal memory for endpoints | ||
| 61 | buffers expressed in KB | ||
| 62 | $ref: /schemas/types.yaml#/definitions/uint32 | ||
| 63 | |||
| 64 | cdns,phyrst-a-enable: | ||
| 65 | description: Enable resetting of PHY if Rx fail is detected | ||
| 66 | type: boolean | ||
| 67 | |||
| 68 | required: | ||
| 69 | - compatible | ||
| 70 | - reg | ||
| 71 | - reg-names | ||
| 72 | - interrupts | ||
| 73 | |||
| 74 | additionalProperties: false | ||
| 75 | |||
| 76 | examples: | ||
| 77 | - | | ||
| 78 | #include <dt-bindings/interrupt-controller/arm-gic.h> | ||
| 79 | bus { | ||
| 80 | #address-cells = <2>; | ||
| 81 | #size-cells = <2>; | ||
| 82 | |||
| 83 | usb@6000000 { | ||
| 84 | compatible = "cdns,usb3"; | ||
| 85 | reg = <0x00 0x6000000 0x00 0x10000>, | ||
| 86 | <0x00 0x6010000 0x00 0x10000>, | ||
| 87 | <0x00 0x6020000 0x00 0x10000>; | ||
| 88 | reg-names = "otg", "xhci", "dev"; | ||
| 89 | interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>, | ||
| 90 | <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>, | ||
| 91 | <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>; | ||
| 92 | interrupt-names = "host", "peripheral", "otg"; | ||
| 93 | maximum-speed = "super-speed"; | ||
| 94 | dr_mode = "otg"; | ||
| 95 | }; | ||
| 96 | }; | ||
| @@ -1,45 +0,0 @@ | |||
| 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 | }; | ||
| @@ -100,6 +100,15 @@ i.mx specific properties · 99 unmodified lines | |||
| 100 | It's recommended to specify the over current polarity. | 100 | It's recommended to specify the over current polarity. |
| 101 | - power-active-high: power signal polarity is active high | 101 | - power-active-high: power signal polarity is active high |
| 102 | - external-vbus-divider: enables off-chip resistor divider for Vbus | 102 | - external-vbus-divider: enables off-chip resistor divider for Vbus |
| 103 | - samsung,picophy-pre-emp-curr-control: HS Transmitter Pre-Emphasis Current | ||
| 104 | Control. This signal controls the amount of current sourced to the | ||
| 105 | USB_OTG*_DP and USB_OTG*_DN pins after a J-to-K or K-to-J transition. | ||
| 106 | The range is from 0x0 to 0x3, the default value is 0x1. | ||
| 107 | Details can refer to TXPREEMPAMPTUNE0 bits of USBNC_n_PHY_CFG1. | ||
| 108 | - samsung,picophy-dc-vol-level-adjust: HS DC Voltage Level Adjustment. | ||
| 109 | Adjust the high-speed transmitter DC level voltage. | ||
| 110 | The range is from 0x0 to 0xf, the default value is 0x3. | ||
| 111 | Details can refer to TXVREFTUNE0 bits of USBNC_n_PHY_CFG1. | ||
| 103 | 112 | ||
| 104 | Example: | 113 | Example: |
| 105 | 114 | ||
| @@ -39,6 +39,7 @@ properties: · 38 unmodified lines | |||
| 39 | - amlogic,meson-g12a-usb | 39 | - amlogic,meson-g12a-usb |
| 40 | - const: snps,dwc2 | 40 | - const: snps,dwc2 |
| 41 | - const: amcc,dwc-otg | 41 | - const: amcc,dwc-otg |
| 42 | - const: apm,apm82181-dwc-otg | ||
| 42 | - const: snps,dwc2 | 43 | - const: snps,dwc2 |
| 43 | - const: st,stm32f4x9-fsotg | 44 | - const: st,stm32f4x9-fsotg |
| 44 | - const: st,stm32f4x9-hsotg | 45 | - const: st,stm32f4x9-hsotg |
| @@ -102,6 +103,10 @@ properties: · 57 unmodified lines | |||
| 102 | dr_mode: | 103 | dr_mode: |
| 103 | enum: [host, peripheral, otg] | 104 | enum: [host, peripheral, otg] |
| 104 | 105 | ||
| 106 | usb-role-switch: | ||
| 107 | $ref: /schemas/types.yaml#/definitions/flag | ||
| 108 | description: Support role switch. | ||
| 109 | |||
| 105 | g-rx-fifo-size: | 110 | g-rx-fifo-size: |
| 106 | $ref: /schemas/types.yaml#/definitions/uint32 | 111 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 107 | description: size of rx fifo size in gadget mode. | 112 | description: size of rx fifo size in gadget mode. |
| @@ -78,6 +78,9 @@ Optional properties: · 77 unmodified lines | |||
| 78 | park mode are disabled. | 78 | park mode are disabled. |
| 79 | - snps,dis_metastability_quirk: when set, disable metastability workaround. | 79 | - snps,dis_metastability_quirk: when set, disable metastability workaround. |
| 80 | CAUTION: use only if you are absolutely sure of it. | 80 | CAUTION: use only if you are absolutely sure of it. |
| 81 | - snps,dis-split-quirk: when set, change the way URBs are handled by the | ||
| 82 | driver. Needed to avoid -EPROTO errors with usbhid | ||
| 83 | on some devices (Hikey 970). | ||
| 81 | - snps,is-utmi-l1-suspend: true when DWC3 asserts output signal | 84 | - snps,is-utmi-l1-suspend: true when DWC3 asserts output signal |
| 82 | utmi_l1_suspend_n, false when asserts utmi_sleep_n | 85 | utmi_l1_suspend_n, false when asserts utmi_sleep_n |
| 83 | - snps,hird-threshold: HIRD threshold | 86 | - snps,hird-threshold: HIRD threshold |
| @@ -0,0 +1,77 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/usb/intel,keembay-dwc3.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Intel Keem Bay DWC3 USB controller | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Wan Ahmad Zainie <wan.ahmad.zainie.wan.mohamad@intel.com> | ||
| 11 | |||
| 12 | properties: | ||
| 13 | compatible: | ||
| 14 | const: intel,keembay-dwc3 | ||
| 15 | |||
| 16 | clocks: | ||
| 17 | maxItems: 4 | ||
| 18 | |||
| 19 | clock-names: | ||
| 20 | items: | ||
| 21 | - const: async_master | ||
| 22 | - const: ref | ||
| 23 | - const: alt_ref | ||
| 24 | - const: suspend | ||
| 25 | |||
| 26 | ranges: true | ||
| 27 | |||
| 28 | '#address-cells': | ||
| 29 | enum: [ 1, 2 ] | ||
| 30 | |||
| 31 | '#size-cells': | ||
| 32 | enum: [ 1, 2 ] | ||
| 33 | |||
| 34 | # Required child node: | ||
| 35 | |||
| 36 | patternProperties: | ||
| 37 | "^dwc3@[0-9a-f]+$": | ||
| 38 | type: object | ||
| 39 | description: | ||
| 40 | A child node must exist to represent the core DWC3 IP block. | ||
| 41 | The content of the node is defined in dwc3.txt. | ||
| 42 | |||
| 43 | required: | ||
| 44 | - compatible | ||
| 45 | - clocks | ||
| 46 | - clock-names | ||
| 47 | - ranges | ||
| 48 | |||
| 49 | additionalProperties: false | ||
| 50 | |||
| 51 | examples: | ||
| 52 | - | | ||
| 53 | #include <dt-bindings/interrupt-controller/arm-gic.h> | ||
| 54 | #include <dt-bindings/interrupt-controller/irq.h> | ||
| 55 | #define KEEM_BAY_A53_AUX_USB | ||
| 56 | #define KEEM_BAY_A53_AUX_USB_REF | ||
| 57 | #define KEEM_BAY_A53_AUX_USB_ALT_REF | ||
| 58 | #define KEEM_BAY_A53_AUX_USB_SUSPEND | ||
| 59 | |||
| 60 | usb { | ||
| 61 | compatible = "intel,keembay-dwc3"; | ||
| 62 | clocks = <&scmi_clk KEEM_BAY_A53_AUX_USB>, | ||
| 63 | <&scmi_clk KEEM_BAY_A53_AUX_USB_REF>, | ||
| 64 | <&scmi_clk KEEM_BAY_A53_AUX_USB_ALT_REF>, | ||
| 65 | <&scmi_clk KEEM_BAY_A53_AUX_USB_SUSPEND>; | ||
| 66 | clock-names = "async_master", "ref", "alt_ref", "suspend"; | ||
| 67 | ranges; | ||
| 68 | #address-cells = <1>; | ||
| 69 | #size-cells = <1>; | ||
| 70 | |||
| 71 | dwc3@34000000 { | ||
| 72 | compatible = "snps,dwc3"; | ||
| 73 | reg = <0x34000000 0x10000>; | ||
| 74 | interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>; | ||
| 75 | dr_mode = "peripheral"; | ||
| 76 | }; | ||
| 77 | }; | ||
| @@ -0,0 +1,95 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: "http://devicetree.org/schemas/usb/mediatek,mt6360-tcpc.yaml#" | ||
| 5 | $schema: "http://devicetree.org/meta-schemas/core.yaml#" | ||
| 6 | |||
| 7 | title: Mediatek MT6360 Type-C Port Switch and Power Delivery controller DT bindings | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - ChiYuan Huang <cy_huang@richtek.com> | ||
| 11 | |||
| 12 | description: | | ||
| 13 | Mediatek MT6360 is a multi-functional device. It integrates charger, ADC, flash, RGB indicators, | ||
| 14 | regulators (BUCKs/LDOs), and TypeC Port Switch with Power Delivery controller. | ||
| 15 | This document only describes MT6360 Type-C Port Switch and Power Delivery controller. | ||
| 16 | |||
| 17 | properties: | ||
| 18 | compatible: | ||
| 19 | enum: | ||
| 20 | - mediatek,mt6360-tcpc | ||
| 21 | |||
| 22 | interrupts: | ||
| 23 | maxItems: 1 | ||
| 24 | |||
| 25 | interrupt-names: | ||
| 26 | items: | ||
| 27 | - const: PD_IRQB | ||
| 28 | |||
| 29 | connector: | ||
| 30 | type: object | ||
| 31 | $ref: ../connector/usb-connector.yaml# | ||
| 32 | description: | ||
| 33 | Properties for usb c connector. | ||
| 34 | |||
| 35 | additionalProperties: false | ||
| 36 | |||
| 37 | required: | ||
| 38 | - compatible | ||
| 39 | - interrupts | ||
| 40 | - interrupt-names | ||
| 41 | |||
| 42 | examples: | ||
| 43 | - | | ||
| 44 | #include <dt-bindings/interrupt-controller/irq.h> | ||
| 45 | #include <dt-bindings/usb/pd.h> | ||
| 46 | i2c0 { | ||
| 47 | #address-cells = <1>; | ||
| 48 | #size-cells = <0>; | ||
| 49 | |||
| 50 | mt6360@34 { | ||
| 51 | compatible = "mediatek,mt6360"; | ||
| 52 | reg = <0x34>; | ||
| 53 | tcpc { | ||
| 54 | compatible = "mediatek,mt6360-tcpc"; | ||
| 55 | interrupts-extended = <&gpio26 3 IRQ_TYPE_LEVEL_LOW>; | ||
| 56 | interrupt-names = "PD_IRQB"; | ||
| 57 | |||
| 58 | connector { | ||
| 59 | compatible = "usb-c-connector"; | ||
| 60 | label = "USB-C"; | ||
| 61 | data-role = "dual"; | ||
| 62 | power-role = "dual"; | ||
| 63 | try-power-role = "sink"; | ||
| 64 | source-pdos = <PDO_FIXED(5000, 1000, PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP)>; | ||
| 65 | sink-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP)>; | ||
| 66 | op-sink-microwatt = <10000000>; | ||
| 67 | |||
| 68 | ports { | ||
| 69 | #address-cells = <1>; | ||
| 70 | #size-cells = <0>; | ||
| 71 | |||
| 72 | port@0 { | ||
| 73 | reg = <0>; | ||
| 74 | endpoint { | ||
| 75 | remote-endpoint = <&usb_hs>; | ||
| 76 | }; | ||
| 77 | }; | ||
| 78 | port@1 { | ||
| 79 | reg = <1>; | ||
| 80 | endpoint { | ||
| 81 | remote-endpoint = <&usb_ss>; | ||
| 82 | }; | ||
| 83 | }; | ||
| 84 | port@2 { | ||
| 85 | reg = <2>; | ||
| 86 | endpoint { | ||
| 87 | remote-endpoint = <&dp_aux>; | ||
| 88 | }; | ||
| 89 | }; | ||
| 90 | }; | ||
| 91 | }; | ||
| 92 | }; | ||
| 93 | }; | ||
| 94 | }; | ||
| 95 | ... | ||
| @@ -30,6 +30,7 @@ properties: · 29 unmodified lines | |||
| 30 | - renesas,xhci-r8a774a1 # RZ/G2M | 30 | - renesas,xhci-r8a774a1 # RZ/G2M |
| 31 | - renesas,xhci-r8a774b1 # RZ/G2N | 31 | - renesas,xhci-r8a774b1 # RZ/G2N |
| 32 | - renesas,xhci-r8a774c0 # RZ/G2E | 32 | - renesas,xhci-r8a774c0 # RZ/G2E |
| 33 | - renesas,xhci-r8a774e1 # RZ/G2H | ||
| 33 | - renesas,xhci-r8a7795 # R-Car H3 | 34 | - renesas,xhci-r8a7795 # R-Car H3 |
| 34 | - renesas,xhci-r8a7796 # R-Car M3-W | 35 | - renesas,xhci-r8a7796 # R-Car M3-W |
| 35 | - renesas,xhci-r8a77961 # R-Car M3-W+ | 36 | - renesas,xhci-r8a77961 # R-Car M3-W+ |
| @@ -16,6 +16,7 @@ properties: · 15 unmodified lines | |||
| 16 | - renesas,r8a774a1-usb3-peri # RZ/G2M | 16 | - renesas,r8a774a1-usb3-peri # RZ/G2M |
| 17 | - renesas,r8a774b1-usb3-peri # RZ/G2N | 17 | - renesas,r8a774b1-usb3-peri # RZ/G2N |
| 18 | - renesas,r8a774c0-usb3-peri # RZ/G2E | 18 | - renesas,r8a774c0-usb3-peri # RZ/G2E |
| 19 | - renesas,r8a774e1-usb3-peri # RZ/G2H | ||
| 19 | - renesas,r8a7795-usb3-peri # R-Car H3 | 20 | - renesas,r8a7795-usb3-peri # R-Car H3 |
| 20 | - renesas,r8a7796-usb3-peri # R-Car M3-W | 21 | - renesas,r8a7796-usb3-peri # R-Car M3-W |
| 21 | - renesas,r8a77961-usb3-peri # R-Car M3-W+ | 22 | - renesas,r8a77961-usb3-peri # R-Car M3-W+ |
| @@ -52,11 +53,24 @@ properties: · 30 unmodified lines | |||
| 52 | $ref: /schemas/types.yaml#/definitions/phandle | 53 | $ref: /schemas/types.yaml#/definitions/phandle |
| 53 | description: phandle of a companion. | 54 | description: phandle of a companion. |
| 54 | 55 | ||
| 55 | port: | 56 | ports: |
| 56 | description: | | 57 | description: | |
| 57 | any connector to the data bus of this controller should be modelled | 58 | any connector to the data bus of this controller should be modelled |
| 58 | using the OF graph bindings specified, if the "usb-role-switch" | 59 | using the OF graph bindings specified, if the "usb-role-switch" |
| 59 | property is used. | 60 | property is used. |
| 61 | type: object | ||
| 62 | properties: | ||
| 63 | port@0: | ||
| 64 | type: object | ||
| 65 | description: High Speed (HS) data bus. | ||
| 66 | |||
| 67 | port@1: | ||
| 68 | type: object | ||
| 69 | description: Super Speed (SS) data bus. | ||
| 70 | |||
| 71 | required: | ||
| 72 | - port@0 | ||
| 73 | - port@1 | ||
| 60 | 74 | ||
| 61 | required: | 75 | required: |
| 62 | - compatible | 76 | - compatible |
| @@ -79,9 +93,20 @@ examples: · 16 unmodified lines | |||
| 79 | companion = <&xhci0>; | 93 | companion = <&xhci0>; |
| 80 | usb-role-switch; | 94 | usb-role-switch; |
| 81 | 95 | ||
| 82 | port { | 96 | ports { |
| 83 | usb3_role_switch: endpoint { | 97 | #address-cells = <1>; |
| 84 | remote-endpoint = <&hd3ss3220_ep>; | 98 | #size-cells = <0>; |
| 85 | }; | 99 | port@0 { |
| 100 | reg = <0>; | ||
| 101 | usb3_hs_ep: endpoint { | ||
| 102 | remote-endpoint = <&hs_ep>; | ||
| 103 | }; | ||
| 104 | }; | ||
| 105 | port@1 { | ||
| 106 | reg = <1>; | ||
| 107 | usb3_role_switch: endpoint { | ||
| 108 | remote-endpoint = <&hd3ss3220_out_ep>; | ||
| 109 | }; | ||
| 110 | }; | ||
| 86 | }; | 111 | }; |
| 87 | }; | 112 | }; |
| @@ -39,6 +39,7 @@ properties: · 38 unmodified lines | |||
| 39 | - renesas,usbhs-r8a774a1 # RZ/G2M | 39 | - renesas,usbhs-r8a774a1 # RZ/G2M |
| 40 | - renesas,usbhs-r8a774b1 # RZ/G2N | 40 | - renesas,usbhs-r8a774b1 # RZ/G2N |
| 41 | - renesas,usbhs-r8a774c0 # RZ/G2E | 41 | - renesas,usbhs-r8a774c0 # RZ/G2E |
| 42 | - renesas,usbhs-r8a774e1 # RZ/G2H | ||
| 42 | - renesas,usbhs-r8a7795 # R-Car H3 | 43 | - renesas,usbhs-r8a7795 # R-Car H3 |
| 43 | - renesas,usbhs-r8a7796 # R-Car M3-W | 44 | - renesas,usbhs-r8a7796 # R-Car M3-W |
| 44 | - renesas,usbhs-r8a77961 # R-Car M3-W+ | 45 | - renesas,usbhs-r8a77961 # R-Car M3-W+ |
| @@ -1,38 +0,0 @@ | |||
| 1 | TI HD3SS3220 TypeC DRP Port Controller. | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible: Must be "ti,hd3ss3220". | ||
| 5 | - reg: I2C slave address, must be 0x47 or 0x67 based on ADDR pin. | ||
| 6 | - interrupts: An interrupt specifier. | ||
| 7 | |||
| 8 | Required sub-node: | ||
| 9 | - connector: The "usb-c-connector" attached to the hd3ss3220 chip. The | ||
| 10 | bindings of the connector node are specified in: | ||
| 11 | |||
| 12 | Documentation/devicetree/bindings/connector/usb-connector.yaml | ||
| 13 | |||
| 14 | Example: | ||
| 15 | hd3ss3220@47 { | ||
| 16 | compatible = "ti,hd3ss3220"; | ||
| 17 | reg = <0x47>; | ||
| 18 | interrupt-parent = <&gpio6>; | ||
| 19 | interrupts = <3 IRQ_TYPE_LEVEL_LOW>; | ||
| 20 | |||
| 21 | connector { | ||
| 22 | compatible = "usb-c-connector"; | ||
| 23 | label = "USB-C"; | ||
| 24 | data-role = "dual"; | ||
| 25 | |||
| 26 | ports { | ||
| 27 | #address-cells = <1>; | ||
| 28 | #size-cells = <0>; | ||
| 29 | |||
| 30 | port@1 { | ||
| 31 | reg = <1>; | ||
| 32 | hd3ss3220_ep: endpoint { | ||
| 33 | remote-endpoint = <&usb3_role_switch>; | ||
| 34 | }; | ||
| 35 | }; | ||
| 36 | }; | ||
| 37 | }; | ||
| 38 | }; | ||
| @@ -0,0 +1,82 @@ | |||
| 1 | # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/usb/ti,hd3ss3220.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: TI HD3SS3220 TypeC DRP Port Controller | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Biju Das <biju.das.jz@bp.renesas.com> | ||
| 11 | |||
| 12 | description: |- | ||
| 13 | HD3SS3220 is a USB SuperSpeed (SS) 2:1 mux with DRP port controller. The device provides Channel | ||
| 14 | Configuration (CC) logic and 5V VCONN sourcing for ecosystems implementing USB Type-C. The | ||
| 15 | HD3SS3220 can be configured as a Downstream Facing Port (DFP), Upstream Facing Port (UFP) or a | ||
| 16 | Dual Role Port (DRP) making it ideal for any application. | ||
| 17 | |||
| 18 | properties: | ||
| 19 | compatible: | ||
| 20 | const: ti,hd3ss3220 | ||
| 21 | |||
| 22 | reg: | ||
| 23 | maxItems: 1 | ||
| 24 | |||
| 25 | interrupts: | ||
| 26 | maxItems: 1 | ||
| 27 | |||
| 28 | ports: | ||
| 29 | description: OF graph bindings (specified in bindings/graph.txt) that model | ||
| 30 | SS data bus to the SS capable connector. | ||
| 31 | type: object | ||
| 32 | properties: | ||
| 33 | port@0: | ||
| 34 | type: object | ||
| 35 | description: Super Speed (SS) MUX inputs connected to SS capable connector. | ||
| 36 | $ref: /connector/usb-connector.yaml#/properties/ports/properties/port@1 | ||
| 37 | |||
| 38 | port@1: | ||
| 39 | type: object | ||
| 40 | description: Output of 2:1 MUX connected to Super Speed (SS) data bus. | ||
| 41 | |||
| 42 | required: | ||
| 43 | - port@0 | ||
| 44 | - port@1 | ||
| 45 | |||
| 46 | required: | ||
| 47 | - compatible | ||
| 48 | - reg | ||
| 49 | - interrupts | ||
| 50 | |||
| 51 | additionalProperties: false | ||
| 52 | |||
| 53 | examples: | ||
| 54 | - | | ||
| 55 | i2c0 { | ||
| 56 | #address-cells = <1>; | ||
| 57 | #size-cells = <0>; | ||
| 58 | |||
| 59 | hd3ss3220@47 { | ||
| 60 | compatible = "ti,hd3ss3220"; | ||
| 61 | reg = <0x47>; | ||
| 62 | interrupt-parent = <&gpio6>; | ||
| 63 | interrupts = <3>; | ||
| 64 | |||
| 65 | ports { | ||
| 66 | #address-cells = <1>; | ||
| 67 | #size-cells = <0>; | ||
| 68 | port@0 { | ||
| 69 | reg = <0>; | ||
| 70 | hd3ss3220_in_ep: endpoint { | ||
| 71 | remote-endpoint = <&ss_ep>; | ||
| 72 | }; | ||
| 73 | }; | ||
| 74 | port@1 { | ||
| 75 | reg = <1>; | ||
| 76 | hd3ss3220_out_ep: endpoint { | ||
| 77 | remote-endpoint = <&usb3_role_switch>; | ||
| 78 | }; | ||
| 79 | }; | ||
| 80 | }; | ||
| 81 | }; | ||
| 82 | }; | ||
| @@ -3454,6 +3454,14 @@ F: drivers/bus/brcmstb_gisb.c · 3453 unmodified lines | |||
| 3454 | F: drivers/pci/controller/pcie-brcmstb.c | 3454 | F: drivers/pci/controller/pcie-brcmstb.c |
| 3455 | N: brcmstb | 3455 | N: brcmstb |
| 3456 | 3456 | ||
| 3457 | BROADCOM BDC DRIVER | ||
| 3458 | M: Al Cooper <alcooperx@gmail.com> | ||
| 3459 | L: linux-usb@vger.kernel.org | ||
| 3460 | L: bcm-kernel-feedback-list@broadcom.com | ||
| 3461 | S: Maintained | ||
| 3462 | F: Documentation/devicetree/bindings/usb/brcm,bdc.txt | ||
| 3463 | F: drivers/usb/gadget/udc/bdc/ | ||
| 3464 | |||
| 3457 | BROADCOM BMIPS CPUFREQ DRIVER | 3465 | BROADCOM BMIPS CPUFREQ DRIVER |
| 3458 | M: Markus Mayer <mmayer@broadcom.com> | 3466 | M: Markus Mayer <mmayer@broadcom.com> |
| 3459 | M: bcm-kernel-feedback-list@broadcom.com | 3467 | M: bcm-kernel-feedback-list@broadcom.com |
| @@ -3831,6 +3839,16 @@ S: Orphan · 371 unmodified lines | |||
| 3831 | F: Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt | 3839 | F: Documentation/devicetree/bindings/mtd/cadence-nand-controller.txt |
| 3832 | F: drivers/mtd/nand/raw/cadence-nand-controller.c | 3840 | F: drivers/mtd/nand/raw/cadence-nand-controller.c |
| 3833 | 3841 | ||
| 3842 | CADENCE USB3 DRD IP DRIVER | ||
| 3843 | M: Peter Chen <peter.chen@nxp.com> | ||
| 3844 | M: Pawel Laszczak <pawell@cadence.com> | ||
| 3845 | M: Roger Quadros <rogerq@ti.com> | ||
| 3846 | L: linux-usb@vger.kernel.org | ||
| 3847 | S: Maintained | ||
| 3848 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git | ||
| 3849 | F: Documentation/devicetree/bindings/usb/cdns-usb3.txt | ||
| 3850 | F: drivers/usb/cdns3/ | ||
| 3851 | |||
| 3834 | CADET FM/AM RADIO RECEIVER DRIVER | 3852 | CADET FM/AM RADIO RECEIVER DRIVER |
| 3835 | M: Hans Verkuil <hverkuil@xs4all.nl> | 3853 | M: Hans Verkuil <hverkuil@xs4all.nl> |
| 3836 | L: linux-media@vger.kernel.org | 3854 | L: linux-media@vger.kernel.org |
| @@ -11037,7 +11055,7 @@ F: net/dsa/tag_mtk.c · 7200 unmodified lines | |||
| 11037 | 11055 | ||
| 11038 | MEDIATEK USB3 DRD IP DRIVER | 11056 | MEDIATEK USB3 DRD IP DRIVER |
| 11039 | M: Chunfeng Yun <chunfeng.yun@mediatek.com> | 11057 | M: Chunfeng Yun <chunfeng.yun@mediatek.com> |
| 11040 | L: linux-usb@vger.kernel.org (moderated for non-subscribers) | 11058 | L: linux-usb@vger.kernel.org |
| 11041 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 11059 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 11042 | L: linux-mediatek@lists.infradead.org (moderated for non-subscribers) | 11060 | L: linux-mediatek@lists.infradead.org (moderated for non-subscribers) |
| 11043 | S: Maintained | 11061 | S: Maintained |
| @@ -563,6 +563,12 @@ · 562 unmodified lines | |||
| 563 | atmel,pins = <AT91_PIOD 18 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>; | 563 | atmel,pins = <AT91_PIOD 18 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>; |
| 564 | }; | 564 | }; |
| 565 | }; | 565 | }; |
| 566 | |||
| 567 | usb0 { | ||
| 568 | pinctrl_usba_vbus: usba_vbus { | ||
| 569 | atmel,pins = <AT91_PIOB 16 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>; | ||
| 570 | }; | ||
| 571 | }; | ||
| 566 | }; /* pinctrl */ | 572 | }; /* pinctrl */ |
| 567 | 573 | ||
| 568 | &pmc { | 574 | &pmc { |
| @@ -666,6 +672,13 @@ · 97 unmodified lines | |||
| 666 | }; | 672 | }; |
| 667 | }; | 673 | }; |
| 668 | 674 | ||
| 675 | &usb0 { | ||
| 676 | atmel,vbus-gpio = <&pioB 16 GPIO_ACTIVE_HIGH>; | ||
| 677 | pinctrl-names = "default"; | ||
| 678 | pinctrl-0 = <&pinctrl_usba_vbus>; | ||
| 679 | status = "okay"; | ||
| 680 | }; | ||
| 681 | |||
| 669 | &usb1 { | 682 | &usb1 { |
| 670 | num-ports = <3>; | 683 | num-ports = <3>; |
| 671 | atmel,vbus-gpio = <0 | 684 | atmel,vbus-gpio = <0 |
| @@ -4,6 +4,8 @@ · 3 unmodified lines | |||
| 4 | #include "bcm2835-rpi.dtsi" | 4 | #include "bcm2835-rpi.dtsi" |
| 5 | #include "bcm283x-rpi-usb-peripheral.dtsi" | 5 | #include "bcm283x-rpi-usb-peripheral.dtsi" |
| 6 | 6 | ||
| 7 | #include <dt-bindings/reset/raspberrypi,firmware-reset.h> | ||
| 8 | |||
| 7 | / { | 9 | / { |
| 8 | compatible = "raspberrypi,4-model-b", "brcm,bcm2711"; | 10 | compatible = "raspberrypi,4-model-b", "brcm,bcm2711"; |
| 9 | model = "Raspberry Pi 4 Model B"; | 11 | model = "Raspberry Pi 4 Model B"; |
| @@ -88,6 +90,11 @@ · 78 unmodified lines | |||
| 88 | ""; | 90 | ""; |
| 89 | status = "okay"; | 91 | status = "okay"; |
| 90 | }; | 92 | }; |
| 93 | |||
| 94 | reset: reset { | ||
| 95 | compatible = "raspberrypi,firmware-reset"; | ||
| 96 | #reset-cells = <1>; | ||
| 97 | }; | ||
| 91 | }; | 98 | }; |
| 92 | 99 | ||
| 93 | &gpio { | 100 | &gpio { |
| @@ -207,6 +214,21 @@ · 113 unmodified lines | |||
| 207 | }; | 214 | }; |
| 208 | }; | 215 | }; |
| 209 | 216 | ||
| 217 | &pcie0 { | ||
| 218 | pci@1,0 { | ||
| 219 | #address-cells = <3>; | ||
| 220 | #size-cells = <2>; | ||
| 221 | ranges; | ||
| 222 | |||
| 223 | reg = <0 0 0 0 0>; | ||
| 224 | |||
| 225 | usb@1,0 { | ||
| 226 | reg = <0x10000 0 0 0 0>; | ||
| 227 | resets = <&reset RASPBERRYPI_FIRMWARE_RESET_ID_USB>; | ||
| 228 | }; | ||
| 229 | }; | ||
| 230 | }; | ||
| 231 | |||
| 210 | /* uart0 communicates with the BT module */ | 232 | /* uart0 communicates with the BT module */ |
| 211 | &uart0 { | 233 | &uart0 { |
| 212 | pinctrl-names = "default"; | 234 | pinctrl-names = "default"; |
| @@ -69,6 +69,20 @@ · 68 unmodified lines | |||
| 69 | #size-cells = <1>; | 69 | #size-cells = <1>; |
| 70 | ranges; | 70 | ranges; |
| 71 | 71 | ||
| 72 | usb0: gadget@500000 { | ||
| 73 | #address-cells = <1>; | ||
| 74 | #size-cells = <0>; | ||
| 75 | compatible = "microchip,sam9x60-udc"; | ||
| 76 | reg = <0x00500000 0x100000 | ||
| 77 | 0xf803c000 0x400>; | ||
| 78 | interrupts = <23 IRQ_TYPE_LEVEL_HIGH 2>; | ||
| 79 | clocks = <&pmc PMC_TYPE_PERIPHERAL 23>, <&pmc PMC_TYPE_CORE PMC_UTMI>; | ||
| 80 | clock-names = "pclk", "hclk"; | ||
| 81 | assigned-clocks = <&pmc PMC_TYPE_CORE PMC_UTMI>; | ||
| 82 | assigned-clock-rates = <480000000>; | ||
| 83 | status = "disabled"; | ||
| 84 | }; | ||
| 85 | |||
| 72 | usb1: ohci@600000 { | 86 | usb1: ohci@600000 { |
| 73 | compatible = "atmel,at91rm9200-ohci", "usb-ohci"; | 87 | compatible = "atmel,at91rm9200-ohci", "usb-ohci"; |
| 74 | reg = <0x00600000 0x100000>; | 88 | reg = <0x00600000 0x100000>; |
| @@ -555,6 +555,7 @@ struct device *acpi_get_first_physical_node(struct acpi_device *adev) · 554 unmodified lines | |||
| 555 | mutex_unlock(physical_node_lock); | 555 | mutex_unlock(physical_node_lock); |
| 556 | return phys_dev; | 556 | return phys_dev; |
| 557 | } | 557 | } |
| 558 | EXPORT_SYMBOL_GPL(acpi_get_first_physical_node); | ||
| 558 | 559 | ||
| 559 | static struct acpi_device *acpi_primary_dev_companion(struct acpi_device *adev, | 560 | static struct acpi_device *acpi_primary_dev_companion(struct acpi_device *adev, |
| 560 | const struct device *dev) | 561 | const struct device *dev) |
| @@ -212,19 +212,16 @@ static int ath3k_load_firmware(struct usb_device *udev, · 211 unmodified lines | |||
| 212 | 212 | ||
| 213 | BT_DBG("udev %p", udev); | 213 | BT_DBG("udev %p", udev); |
| 214 | 214 | ||
| 215 | pipe = usb_sndctrlpipe(udev, 0); | ||
| 216 | |||
| 217 | send_buf = kmalloc(BULK_SIZE, GFP_KERNEL); | 215 | send_buf = kmalloc(BULK_SIZE, GFP_KERNEL); |
| 218 | if (!send_buf) { | 216 | if (!send_buf) { |
| 219 | BT_ERR("Can't allocate memory chunk for firmware"); | 217 | BT_ERR("Can't allocate memory chunk for firmware"); |
| 220 | return -ENOMEM; | 218 | return -ENOMEM; |
| 221 | } | 219 | } |
| 222 | 220 | ||
| 223 | memcpy(send_buf, firmware->data, FW_HDR_SIZE); | 221 | err = usb_control_msg_send(udev, 0, USB_REQ_DFU_DNLOAD, USB_TYPE_VENDOR, |
| 224 | err = usb_control_msg(udev, pipe, USB_REQ_DFU_DNLOAD, USB_TYPE_VENDOR, | 222 | 0, 0, firmware->data, FW_HDR_SIZE, |
| 225 | 0, 0, send_buf, FW_HDR_SIZE, | 223 | USB_CTRL_SET_TIMEOUT, GFP_KERNEL); |
| 226 | USB_CTRL_SET_TIMEOUT); | 224 | if (err) { |
| 227 | if (err < 0) { | ||
| 228 | BT_ERR("Can't change to loading configuration err"); | 225 | BT_ERR("Can't change to loading configuration err"); |
| 229 | goto error; | 226 | goto error; |
| 230 | } | 227 | } |
| @@ -259,44 +256,19 @@ error: · 28 unmodified lines | |||
| 259 | 256 | ||
| 260 | static int ath3k_get_state(struct usb_device *udev, unsigned char *state) | 257 | static int ath3k_get_state(struct usb_device *udev, unsigned char *state) |
| 261 | { | 258 | { |
| 262 | int ret, pipe = 0; | 259 | return usb_control_msg_recv(udev, 0, ATH3K_GETSTATE, |
| 263 | char *buf; | 260 | USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, |
| 264 | 261 | state, 1, USB_CTRL_SET_TIMEOUT, | |
| 265 | buf = kmalloc(sizeof(*buf), GFP_KERNEL); | 262 | GFP_KERNEL); |
| 266 | if (!buf) | ||
| 267 | return -ENOMEM; | ||
| 268 | |||
| 269 | pipe = usb_rcvctrlpipe(udev, 0); | ||
| 270 | ret = usb_control_msg(udev, pipe, ATH3K_GETSTATE, | ||
| 271 | USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, | ||
| 272 | buf, sizeof(*buf), USB_CTRL_SET_TIMEOUT); | ||
| 273 | |||
| 274 | *state = *buf; | ||
| 275 | kfree(buf); | ||
| 276 | |||
| 277 | return ret; | ||
| 278 | } | 263 | } |
| 279 | 264 | ||
| 280 | static int ath3k_get_version(struct usb_device *udev, | 265 | static int ath3k_get_version(struct usb_device *udev, |
| 281 | struct ath3k_version *version) | 266 | struct ath3k_version *version) |
| 282 | { | 267 | { |
| 283 | int ret, pipe = 0; | 268 | return usb_control_msg_recv(udev, 0, ATH3K_GETVERSION, |
| 284 | struct ath3k_version *buf; | 269 | USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, |
| 285 | const int size = sizeof(*buf); | 270 | version, sizeof(*version), USB_CTRL_SET_TIMEOUT, |
| 286 | 271 | GFP_KERNEL); | |
| 287 | buf = kmalloc(size, GFP_KERNEL); | ||
| 288 | if (!buf) | ||
| 289 | return -ENOMEM; | ||
| 290 | |||
| 291 | pipe = usb_rcvctrlpipe(udev, 0); | ||
| 292 | ret = usb_control_msg(udev, pipe, ATH3K_GETVERSION, | ||
| 293 | USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, | ||
| 294 | buf, size, USB_CTRL_SET_TIMEOUT); | ||
| 295 | |||
| 296 | memcpy(version, buf, size); | ||
| 297 | kfree(buf); | ||
| 298 | |||
| 299 | return ret; | ||
| 300 | } | 272 | } |
| 301 | 273 | ||
| 302 | static int ath3k_load_fwfile(struct usb_device *udev, | 274 | static int ath3k_load_fwfile(struct usb_device *udev, |
| @@ -316,13 +288,11 @@ static int ath3k_load_fwfile(struct usb_device *udev, · 13 unmodified lines | |||
| 316 | } | 288 | } |
| 317 | 289 | ||
| 318 | size = min_t(uint, count, FW_HDR_SIZE); | 290 | size = min_t(uint, count, FW_HDR_SIZE); |
| 319 | memcpy(send_buf, firmware->data, size); | ||
| 320 | 291 | ||
| 321 | pipe = usb_sndctrlpipe(udev, 0); | 292 | ret = usb_control_msg_send(udev, 0, ATH3K_DNLOAD, USB_TYPE_VENDOR, 0, 0, |
| 322 | ret = usb_control_msg(udev, pipe, ATH3K_DNLOAD, | 293 | firmware->data, size, USB_CTRL_SET_TIMEOUT, |
| 323 | USB_TYPE_VENDOR, 0, 0, send_buf, | 294 | GFP_KERNEL); |
| 324 | size, USB_CTRL_SET_TIMEOUT); | 295 | if (ret) { |
| 325 | if (ret < 0) { | ||
| 326 | BT_ERR("Can't change to loading configuration err"); | 296 | BT_ERR("Can't change to loading configuration err"); |
| 327 | kfree(send_buf); | 297 | kfree(send_buf); |
| 328 | return ret; | 298 | return ret; |
| @@ -355,23 +325,19 @@ static int ath3k_load_fwfile(struct usb_device *udev, · 26 unmodified lines | |||
| 355 | return 0; | 325 | return 0; |
| 356 | } | 326 | } |
| 357 | 327 | ||
| 358 | static int ath3k_switch_pid(struct usb_device *udev) | 328 | static void ath3k_switch_pid(struct usb_device *udev) |
| 359 | { | 329 | { |
| 360 | int pipe = 0; | 330 | usb_control_msg_send(udev, 0, USB_REG_SWITCH_VID_PID, USB_TYPE_VENDOR, |
| 361 | 331 | 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT, GFP_KERNEL); | |
| 362 | pipe = usb_sndctrlpipe(udev, 0); | ||
| 363 | return usb_control_msg(udev, pipe, USB_REG_SWITCH_VID_PID, | ||
| 364 | USB_TYPE_VENDOR, 0, 0, | ||
| 365 | NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
| 366 | } | 332 | } |
| 367 | 333 | ||
| 368 | static int ath3k_set_normal_mode(struct usb_device *udev) | 334 | static int ath3k_set_normal_mode(struct usb_device *udev) |
| 369 | { | 335 | { |
| 370 | unsigned char fw_state; | 336 | unsigned char fw_state; |
| 371 | int pipe = 0, ret; | 337 | int ret; |
| 372 | 338 | ||
| 373 | ret = ath3k_get_state(udev, &fw_state); | 339 | ret = ath3k_get_state(udev, &fw_state); |
| 374 | if (ret < 0) { | 340 | if (ret) { |
| 375 | BT_ERR("Can't get state to change to normal mode err"); | 341 | BT_ERR("Can't get state to change to normal mode err"); |
| 376 | return ret; | 342 | return ret; |
| 377 | } | 343 | } |
| @@ -381,10 +347,9 @@ static int ath3k_set_normal_mode(struct usb_device *udev) · 3 unmodified lines | |||
| 381 | return 0; | 347 | return 0; |
| 382 | } | 348 | } |
| 383 | 349 | ||
| 384 | pipe = usb_sndctrlpipe(udev, 0); | 350 | return usb_control_msg_send(udev, 0, ATH3K_SET_NORMAL_MODE, |
| 385 | return usb_control_msg(udev, pipe, ATH3K_SET_NORMAL_MODE, | 351 | USB_TYPE_VENDOR, 0, 0, NULL, 0, |
| 386 | USB_TYPE_VENDOR, 0, 0, | 352 | USB_CTRL_SET_TIMEOUT, GFP_KERNEL); |
| 387 | NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
| 388 | } | 353 | } |
| 389 | 354 | ||
| 390 | static int ath3k_load_patch(struct usb_device *udev) | 355 | static int ath3k_load_patch(struct usb_device *udev) |
| @@ -397,7 +362,7 @@ static int ath3k_load_patch(struct usb_device *udev) · 6 unmodified lines | |||
| 397 | int ret; | 362 | int ret; |
| 398 | 363 | ||
| 399 | ret = ath3k_get_state(udev, &fw_state); | 364 | ret = ath3k_get_state(udev, &fw_state); |
| 400 | if (ret < 0) { | 365 | if (ret) { |
| 401 | BT_ERR("Can't get state to change to load ram patch err"); | 366 | BT_ERR("Can't get state to change to load ram patch err"); |
| 402 | return ret; | 367 | return ret; |
| 403 | } | 368 | } |
| @@ -408,7 +373,7 @@ static int ath3k_load_patch(struct usb_device *udev) · 4 unmodified lines | |||
| 408 | } | 373 | } |
| 409 | 374 | ||
| 410 | ret = ath3k_get_version(udev, &fw_version); | 375 | ret = ath3k_get_version(udev, &fw_version); |
| 411 | if (ret < 0) { | 376 | if (ret) { |
| 412 | BT_ERR("Can't get version to change to load ram patch err"); | 377 | BT_ERR("Can't get version to change to load ram patch err"); |
| 413 | return ret; | 378 | return ret; |
| 414 | } | 379 | } |
| @@ -449,13 +414,13 @@ static int ath3k_load_syscfg(struct usb_device *udev) · 34 unmodified lines | |||
| 449 | int clk_value, ret; | 414 | int clk_value, ret; |
| 450 | 415 | ||
| 451 | ret = ath3k_get_state(udev, &fw_state); | 416 | ret = ath3k_get_state(udev, &fw_state); |
| 452 | if (ret < 0) { | 417 | if (ret) { |
| 453 | BT_ERR("Can't get state to change to load configuration err"); | 418 | BT_ERR("Can't get state to change to load configuration err"); |
| 454 | return -EBUSY; | 419 | return -EBUSY; |
| 455 | } | 420 | } |
| 456 | 421 | ||
| 457 | ret = ath3k_get_version(udev, &fw_version); | 422 | ret = ath3k_get_version(udev, &fw_version); |
| 458 | if (ret < 0) { | 423 | if (ret) { |
| 459 | BT_ERR("Can't get version to change to load ram patch err"); | 424 | BT_ERR("Can't get version to change to load ram patch err"); |
| 460 | return ret; | 425 | return ret; |
| 461 | } | 426 | } |
| @@ -529,7 +494,7 @@ static int ath3k_probe(struct usb_interface *intf, · 67 unmodified lines | |||
| 529 | return ret; | 494 | return ret; |
| 530 | } | 495 | } |
| 531 | ret = ath3k_set_normal_mode(udev); | 496 | ret = ath3k_set_normal_mode(udev); |
| 532 | if (ret < 0) { | 497 | if (ret) { |
| 533 | BT_ERR("Set normal mode failed"); | 498 | BT_ERR("Set normal mode failed"); |
| 534 | return ret; | 499 | return ret; |
| 535 | } | 500 | } |
| @@ -178,9 +178,8 @@ config ISCSI_IBFT · 177 unmodified lines | |||
| 178 | Otherwise, say N. | 178 | Otherwise, say N. |
| 179 | 179 | ||
| 180 | config RASPBERRYPI_FIRMWARE | 180 | config RASPBERRYPI_FIRMWARE |
| 181 | bool "Raspberry Pi Firmware Driver" | 181 | tristate "Raspberry Pi Firmware Driver" |
| 182 | depends on BCM2835_MBOX | 182 | depends on BCM2835_MBOX |
| 183 | default USB_PCI | ||
| 184 | help | 183 | help |
| 185 | This option enables support for communicating with the firmware on the | 184 | This option enables support for communicating with the firmware on the |
| 186 | Raspberry Pi. | 185 | Raspberry Pi. |
| @@ -12,8 +12,6 @@ · 11 unmodified lines | |||
| 12 | #include <linux/of_platform.h> | 12 | #include <linux/of_platform.h> |
| 13 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
| 14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
| 15 | #include <linux/pci.h> | ||
| 16 | #include <linux/delay.h> | ||
| 17 | #include <soc/bcm2835/raspberrypi-firmware.h> | 15 | #include <soc/bcm2835/raspberrypi-firmware.h> |
| 18 | 16 | ||
| 19 | #define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) | 17 | #define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) |
| @@ -21,8 +19,6 @@ · 1 unmodified line | |||
| 21 | #define MBOX_DATA28(msg) ((msg) & ~0xf) | 19 | #define MBOX_DATA28(msg) ((msg) & ~0xf) |
| 22 | #define MBOX_CHAN_PROPERTY 8 | 20 | #define MBOX_CHAN_PROPERTY 8 |
| 23 | 21 | ||
| 24 | #define VL805_PCI_CONFIG_VERSION_OFFSET 0x50 | ||
| 25 | |||
| 26 | static struct platform_device *rpi_hwmon; | 22 | static struct platform_device *rpi_hwmon; |
| 27 | static struct platform_device *rpi_clk; | 23 | static struct platform_device *rpi_clk; |
| 28 | 24 | ||
| @@ -301,63 +297,6 @@ struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node) · 272 unmodified lines | |||
| 301 | } | 297 | } |
| 302 | EXPORT_SYMBOL_GPL(rpi_firmware_get); | 298 | EXPORT_SYMBOL_GPL(rpi_firmware_get); |
| 303 | 299 | ||
| 304 | /* | ||
| 305 | * The Raspberry Pi 4 gets its USB functionality from VL805, a PCIe chip that | ||
| 306 | * implements xHCI. After a PCI reset, VL805's firmware may either be loaded | ||
| 307 | * directly from an EEPROM or, if not present, by the SoC's co-processor, | ||
| 308 | * VideoCore. RPi4's VideoCore OS contains both the non public firmware load | ||
| 309 | * logic and the VL805 firmware blob. This function triggers the aforementioned | ||
| 310 | * process. | ||
| 311 | */ | ||
| 312 | int rpi_firmware_init_vl805(struct pci_dev *pdev) | ||
| 313 | { | ||
| 314 | struct device_node *fw_np; | ||
| 315 | struct rpi_firmware *fw; | ||
| 316 | u32 dev_addr, version; | ||
| 317 | int ret; | ||
| 318 | |||
| 319 | fw_np = of_find_compatible_node(NULL, NULL, | ||
| 320 | "raspberrypi,bcm2835-firmware"); | ||
| 321 | if (!fw_np) | ||
| 322 | return 0; | ||
| 323 | |||
| 324 | fw = rpi_firmware_get(fw_np); | ||
| 325 | of_node_put(fw_np); | ||
| 326 | if (!fw) | ||
| 327 | return -ENODEV; | ||
| 328 | |||
| 329 | /* | ||
| 330 | * Make sure we don't trigger a firmware load unnecessarily. | ||
| 331 | * | ||
| 332 | * If something went wrong with PCI, this whole exercise would be | ||
| 333 | * futile as VideoCore expects from us a configured PCI bus. Just take | ||
| 334 | * the faulty version (likely ~0) and let xHCI's registration fail | ||
| 335 | * further down the line. | ||
| 336 | */ | ||
| 337 | pci_read_config_dword(pdev, VL805_PCI_CONFIG_VERSION_OFFSET, &version); | ||
| 338 | if (version) | ||
| 339 | goto exit; | ||
| 340 | |||
| 341 | dev_addr = pdev->bus->number << 20 | PCI_SLOT(pdev->devfn) << 15 | | ||
| 342 | PCI_FUNC(pdev->devfn) << 12; | ||
| 343 | |||
| 344 | ret = rpi_firmware_property(fw, RPI_FIRMWARE_NOTIFY_XHCI_RESET, | ||
| 345 | &dev_addr, sizeof(dev_addr)); | ||
| 346 | if (ret) | ||
| 347 | return ret; | ||
| 348 | |||
| 349 | /* Wait for vl805 to startup */ | ||
| 350 | usleep_range(200, 1000); | ||
| 351 | |||
| 352 | pci_read_config_dword(pdev, VL805_PCI_CONFIG_VERSION_OFFSET, | ||
| 353 | &version); | ||
| 354 | exit: | ||
| 355 | pci_info(pdev, "VL805 firmware version %08x\n", version); | ||
| 356 | |||
| 357 | return 0; | ||
| 358 | } | ||
| 359 | EXPORT_SYMBOL_GPL(rpi_firmware_init_vl805); | ||
| 360 | |||
| 361 | static const struct of_device_id rpi_firmware_of_match[] = { | 300 | static const struct of_device_id rpi_firmware_of_match[] = { |
| 362 | { .compatible = "raspberrypi,bcm2835-firmware", }, | 301 | { .compatible = "raspberrypi,bcm2835-firmware", }, |
| 363 | {}, | 302 | {}, |
| @@ -124,62 +124,31 @@ static void async_ctrl_callback(struct urb *urb) · 123 unmodified lines | |||
| 124 | 124 | ||
| 125 | static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data) | 125 | static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data) |
| 126 | { | 126 | { |
| 127 | u8 *buf; | 127 | return usb_control_msg_recv(pegasus->usb, 0, PEGASUS_REQ_GET_REGS, |
| 128 | int ret; | 128 | PEGASUS_REQT_READ, 0, indx, data, size, |
| 129 | 129 | 1000, GFP_NOIO); | |
| 130 | buf = kmalloc(size, GFP_NOIO); | ||
| 131 | if (!buf) | ||
| 132 | return -ENOMEM; | ||
| 133 | |||
| 134 | ret = usb_control_msg(pegasus->usb, usb_rcvctrlpipe(pegasus->usb, 0), | ||
| 135 | PEGASUS_REQ_GET_REGS, PEGASUS_REQT_READ, 0, | ||
| 136 | indx, buf, size, 1000); | ||
| 137 | if (ret < 0) | ||
| 138 | netif_dbg(pegasus, drv, pegasus->net, | ||
| 139 | "%s returned %d\n", __func__, ret); | ||
| 140 | else if (ret <= size) | ||
| 141 | memcpy(data, buf, ret); | ||
| 142 | kfree(buf); | ||
| 143 | return ret; | ||
| 144 | } | 130 | } |
| 145 | 131 | ||
| 146 | static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, | 132 | static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, |
| 147 | const void *data) | 133 | const void *data) |
| 148 | { | 134 | { |
| 149 | u8 *buf; | 135 | return usb_control_msg_send(pegasus->usb, 0, PEGASUS_REQ_SET_REGS, |
| 150 | int ret; | 136 | PEGASUS_REQT_WRITE, 0, indx, data, size, |
| 151 | 137 | 1000, GFP_NOIO); | |
| 152 | buf = kmemdup(data, size, GFP_NOIO); | ||
| 153 | if (!buf) | ||
| 154 | return -ENOMEM; | ||
| 155 | |||
| 156 | ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0), | ||
| 157 | PEGASUS_REQ_SET_REGS, PEGASUS_REQT_WRITE, 0, | ||
| 158 | indx, buf, size, 100); | ||
| 159 | if (ret < 0) | ||
| 160 | netif_dbg(pegasus, drv, pegasus->net, | ||
| 161 | "%s returned %d\n", __func__, ret); | ||
| 162 | kfree(buf); | ||
| 163 | return ret; | ||
| 164 | } | 138 | } |
| 165 | 139 | ||
| 140 | /* | ||
| 141 | * There is only one way to write to a single ADM8511 register and this is via | ||
| 142 | * specific control request. 'data' is ignored by the device, but it is here to | ||
| 143 | * not break the API. | ||
| 144 | */ | ||
| 166 | static int set_register(pegasus_t *pegasus, __u16 indx, __u8 data) | 145 | static int set_register(pegasus_t *pegasus, __u16 indx, __u8 data) |
| 167 | { | 146 | { |
| 168 | u8 *buf; | 147 | void *buf = &data; |
| 169 | int ret; | ||
| 170 | |||
| 171 | buf = kmemdup(&data, 1, GFP_NOIO); | ||
| 172 | if (!buf) | ||
| 173 | return -ENOMEM; | ||
| 174 | 148 | ||
| 175 | ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0), | 149 | return usb_control_msg_send(pegasus->usb, 0, PEGASUS_REQ_SET_REG, |
| 176 | PEGASUS_REQ_SET_REG, PEGASUS_REQT_WRITE, data, | 150 | PEGASUS_REQT_WRITE, data, indx, buf, 1, |
| 177 | indx, buf, 1, 1000); | 151 | 1000, GFP_NOIO); |
| 178 | if (ret < 0) | ||
| 179 | netif_dbg(pegasus, drv, pegasus->net, | ||
| 180 | "%s returned %d\n", __func__, ret); | ||
| 181 | kfree(buf); | ||
| 182 | return ret; | ||
| 183 | } | 152 | } |
| 184 | 153 | ||
| 185 | static int update_eth_regs_async(pegasus_t *pegasus) | 154 | static int update_eth_regs_async(pegasus_t *pegasus) |
| @@ -152,36 +152,16 @@ static const char driver_name [] = "rtl8150"; · 151 unmodified lines | |||
| 152 | */ | 152 | */ |
| 153 | static int get_registers(rtl8150_t * dev, u16 indx, u16 size, void *data) | 153 | static int get_registers(rtl8150_t * dev, u16 indx, u16 size, void *data) |
| 154 | { | 154 | { |
| 155 | void *buf; | 155 | return usb_control_msg_recv(dev->udev, 0, RTL8150_REQ_GET_REGS, |
| 156 | int ret; | 156 | RTL8150_REQT_READ, indx, 0, data, size, |
| 157 | 157 | 1000, GFP_NOIO); | |
| 158 | buf = kmalloc(size, GFP_NOIO); | ||
| 159 | if (!buf) | ||
| 160 | return -ENOMEM; | ||
| 161 | |||
| 162 | ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), | ||
| 163 | RTL8150_REQ_GET_REGS, RTL8150_REQT_READ, | ||
| 164 | indx, 0, buf, size, 500); | ||
| 165 | if (ret > 0 && ret <= size) | ||
| 166 | memcpy(data, buf, ret); | ||
| 167 | kfree(buf); | ||
| 168 | return ret; | ||
| 169 | } | 158 | } |
| 170 | 159 | ||
| 171 | static int set_registers(rtl8150_t * dev, u16 indx, u16 size, const void *data) | 160 | static int set_registers(rtl8150_t * dev, u16 indx, u16 size, const void *data) |
| 172 | { | 161 | { |
| 173 | void *buf; | 162 | return usb_control_msg_send(dev->udev, 0, RTL8150_REQ_SET_REGS, |
| 174 | int ret; | 163 | RTL8150_REQT_WRITE, indx, 0, data, size, |
| 175 | 164 | 1000, GFP_NOIO); | |
| 176 | buf = kmemdup(data, size, GFP_NOIO); | ||
| 177 | if (!buf) | ||
| 178 | return -ENOMEM; | ||
| 179 | |||
| 180 | ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), | ||
| 181 | RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE, | ||
| 182 | indx, 0, buf, size, 500); | ||
| 183 | kfree(buf); | ||
| 184 | return ret; | ||
| 185 | } | 165 | } |
| 186 | 166 | ||
| 187 | static void async_set_reg_cb(struct urb *urb) | 167 | static void async_set_reg_cb(struct urb *urb) |
| @@ -28,8 +28,6 @@ · 27 unmodified lines | |||
| 28 | #include <linux/string.h> | 28 | #include <linux/string.h> |
| 29 | #include <linux/types.h> | 29 | #include <linux/types.h> |
| 30 | 30 | ||
| 31 | #include <soc/bcm2835/raspberrypi-firmware.h> | ||
| 32 | |||
| 33 | #include "../pci.h" | 31 | #include "../pci.h" |
| 34 | 32 | ||
| 35 | /* BRCM_PCIE_CAP_REGS - Offset for the mandatory capability config regs */ | 33 | /* BRCM_PCIE_CAP_REGS - Offset for the mandatory capability config regs */ |
| @@ -931,24 +929,9 @@ static int brcm_pcie_probe(struct platform_device *pdev) · 895 unmodified lines | |||
| 931 | { | 929 | { |
| 932 | struct device_node *np = pdev->dev.of_node, *msi_np; | 930 | struct device_node *np = pdev->dev.of_node, *msi_np; |
| 933 | struct pci_host_bridge *bridge; | 931 | struct pci_host_bridge *bridge; |
| 934 | struct device_node *fw_np; | ||
| 935 | struct brcm_pcie *pcie; | 932 | struct brcm_pcie *pcie; |
| 936 | int ret; | 933 | int ret; |
| 937 | 934 | ||
| 938 | /* | ||
| 939 | * We have to wait for Raspberry Pi's firmware interface to be up as a | ||
| 940 | * PCI fixup, rpi_firmware_init_vl805(), depends on it. This driver's | ||
| 941 | * probe can race with the firmware interface's (see | ||
| 942 | * drivers/firmware/raspberrypi.c) and potentially break the PCI fixup. | ||
| 943 | */ | ||
| 944 | fw_np = of_find_compatible_node(NULL, NULL, | ||
| 945 | "raspberrypi,bcm2835-firmware"); | ||
| 946 | if (fw_np && !rpi_firmware_get(fw_np)) { | ||
| 947 | of_node_put(fw_np); | ||
| 948 | return -EPROBE_DEFER; | ||
| 949 | } | ||
| 950 | of_node_put(fw_np); | ||
| 951 | |||
| 952 | bridge = devm_pci_alloc_host_bridge(&pdev->dev, sizeof(*pcie)); | 935 | bridge = devm_pci_alloc_host_bridge(&pdev->dev, sizeof(*pcie)); |
| 953 | if (!bridge) | 936 | if (!bridge) |
| 954 | return -ENOMEM; | 937 | return -ENOMEM; |
| @@ -3673,63 +3673,6 @@ static void quirk_apple_poweroff_thunderbolt(struct pci_dev *dev) · 3672 unmodified lines | |||
| 3673 | DECLARE_PCI_FIXUP_SUSPEND_LATE(PCI_VENDOR_ID_INTEL, | 3673 | DECLARE_PCI_FIXUP_SUSPEND_LATE(PCI_VENDOR_ID_INTEL, |
| 3674 | PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C, | 3674 | PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C, |
| 3675 | quirk_apple_poweroff_thunderbolt); | 3675 | quirk_apple_poweroff_thunderbolt); |
| 3676 | |||
| 3677 | /* | ||
| 3678 | * Apple: Wait for the Thunderbolt controller to reestablish PCI tunnels | ||
| 3679 | * | ||
| 3680 | * During suspend the Thunderbolt controller is reset and all PCI | ||
| 3681 | * tunnels are lost. The NHI driver will try to reestablish all tunnels | ||
| 3682 | * during resume. We have to manually wait for the NHI since there is | ||
| 3683 | * no parent child relationship between the NHI and the tunneled | ||
| 3684 | * bridges. | ||
| 3685 | */ | ||
| 3686 | static void quirk_apple_wait_for_thunderbolt(struct pci_dev *dev) | ||
| 3687 | { | ||
| 3688 | struct pci_dev *sibling = NULL; | ||
| 3689 | struct pci_dev *nhi = NULL; | ||
| 3690 | |||
| 3691 | if (!x86_apple_machine) | ||
| 3692 | return; | ||
| 3693 | if (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM) | ||
| 3694 | return; | ||
| 3695 | |||
| 3696 | /* | ||
| 3697 | * Find the NHI and confirm that we are a bridge on the Thunderbolt | ||
| 3698 | * host controller and not on a Thunderbolt endpoint. | ||
| 3699 | */ | ||
| 3700 | sibling = pci_get_slot(dev->bus, 0x0); | ||
| 3701 | if (sibling == dev) | ||
| 3702 | goto out; /* we are the downstream bridge to the NHI */ | ||
| 3703 | if (!sibling || !sibling->subordinate) | ||
| 3704 | goto out; | ||
| 3705 | nhi = pci_get_slot(sibling->subordinate, 0x0); | ||
| 3706 | if (!nhi) | ||
| 3707 | goto out; | ||
| 3708 | if (nhi->vendor != PCI_VENDOR_ID_INTEL | ||
| 3709 | || (nhi->device != PCI_DEVICE_ID_INTEL_LIGHT_RIDGE && | ||
| 3710 | nhi->device != PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C && | ||
| 3711 | nhi->device != PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI && | ||
| 3712 | nhi->device != PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI) | ||
| 3713 | || nhi->class != PCI_CLASS_SYSTEM_OTHER << 8) | ||
| 3714 | goto out; | ||
| 3715 | pci_info(dev, "quirk: waiting for Thunderbolt to reestablish PCI tunnels...\n"); | ||
| 3716 | device_pm_wait_for_dev(&dev->dev, &nhi->dev); | ||
| 3717 | out: | ||
| 3718 | pci_dev_put(nhi); | ||
| 3719 | pci_dev_put(sibling); | ||
| 3720 | } | ||
| 3721 | DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, | ||
| 3722 | PCI_DEVICE_ID_INTEL_LIGHT_RIDGE, | ||
| 3723 | quirk_apple_wait_for_thunderbolt); | ||
| 3724 | DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, | ||
| 3725 | PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C, | ||
| 3726 | quirk_apple_wait_for_thunderbolt); | ||
| 3727 | DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, | ||
| 3728 | PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_BRIDGE, | ||
| 3729 | quirk_apple_wait_for_thunderbolt); | ||
| 3730 | DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, | ||
| 3731 | PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_BRIDGE, | ||
| 3732 | quirk_apple_wait_for_thunderbolt); | ||
| 3733 | #endif | 3676 | #endif |
| 3734 | 3677 | ||
| 3735 | /* | 3678 | /* |
| @@ -49,6 +49,17 @@ config PHY_XGENE · 48 unmodified lines | |||
| 49 | help | 49 | help |
| 50 | This option enables support for APM X-Gene SoC multi-purpose PHY. | 50 | This option enables support for APM X-Gene SoC multi-purpose PHY. |
| 51 | 51 | ||
| 52 | config USB_LGM_PHY | ||
| 53 | tristate "INTEL Lightning Mountain USB PHY Driver" | ||
| 54 | depends on USB_SUPPORT | ||
| 55 | select USB_PHY | ||
| 56 | select REGULATOR | ||
| 57 | select REGULATOR_FIXED_VOLTAGE | ||
| 58 | help | ||
| 59 | Enable this to support Intel DWC3 PHY USB phy. This driver provides | ||
| 60 | interface to interact with USB GEN-II and USB 3.x PHY that is part | ||
| 61 | of the Intel network SOC. | ||
| 62 | |||
| 52 | source "drivers/phy/allwinner/Kconfig" | 63 | source "drivers/phy/allwinner/Kconfig" |
| 53 | source "drivers/phy/amlogic/Kconfig" | 64 | source "drivers/phy/amlogic/Kconfig" |
| 54 | source "drivers/phy/broadcom/Kconfig" | 65 | source "drivers/phy/broadcom/Kconfig" |
| @@ -8,6 +8,7 @@ obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY) += phy-core-mipi-dphy.o · 7 unmodified lines | |||
| 8 | obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o | 8 | obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o |
| 9 | obj-$(CONFIG_PHY_XGENE) += phy-xgene.o | 9 | obj-$(CONFIG_PHY_XGENE) += phy-xgene.o |
| 10 | obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o | 10 | obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o |
| 11 | obj-$(CONFIG_USB_LGM_PHY) += phy-lgm-usb.o | ||
| 11 | obj-y += allwinner/ \ | 12 | obj-y += allwinner/ \ |
| 12 | amlogic/ \ | 13 | amlogic/ \ |
| 13 | broadcom/ \ | 14 | broadcom/ \ |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | |||
| 13 | #include <linux/bcma/bcma.h> | 13 | #include <linux/bcma/bcma.h> |
| 14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
| 15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
| 16 | #include <linux/iopoll.h> | ||
| 16 | #include <linux/mdio.h> | 17 | #include <linux/mdio.h> |
| 17 | #include <linux/module.h> | 18 | #include <linux/module.h> |
| 18 | #include <linux/of_address.h> | 19 | #include <linux/of_address.h> |
| @@ -258,29 +259,24 @@ static struct mdio_driver bcm_ns_usb3_mdio_driver = { · 239 unmodified lines | |||
| 258 | **************************************************/ | 259 | **************************************************/ |
| 259 | 260 | ||
| 260 | static int bcm_ns_usb3_wait_reg(struct bcm_ns_usb3 *usb3, void __iomem *addr, | 261 | static int bcm_ns_usb3_wait_reg(struct bcm_ns_usb3 *usb3, void __iomem *addr, |
| 261 | u32 mask, u32 value, unsigned long timeout) | 262 | u32 mask, u32 value, int usec) |
| 262 | { | 263 | { |
| 263 | unsigned long deadline = jiffies + timeout; | ||
| 264 | u32 val; | 264 | u32 val; |
| 265 | int ret; | ||
| 265 | 266 | ||
| 266 | do { | 267 | ret = readl_poll_timeout_atomic(addr, val, ((val & mask) == value), |
| 267 | val = readl(addr); | 268 | 10, usec); |
| 268 | if ((val & mask) == value) | 269 | if (ret) |
| 269 | return 0; | 270 | dev_err(usb3->dev, "Timeout waiting for register %p\n", addr); |
| 270 | cpu_relax(); | ||
| 271 | udelay(10); | ||
| 272 | } while (!time_after_eq(jiffies, deadline)); | ||
| 273 | 271 | ||
| 274 | dev_err(usb3->dev, "Timeout waiting for register %p\n", addr); | 272 | return ret; |
| 275 | |||
| 276 | return -EBUSY; | ||
| 277 | } | 273 | } |
| 278 | 274 | ||
| 279 | static inline int bcm_ns_usb3_mii_mng_wait_idle(struct bcm_ns_usb3 *usb3) | 275 | static inline int bcm_ns_usb3_mii_mng_wait_idle(struct bcm_ns_usb3 *usb3) |
| 280 | { | 276 | { |
| 281 | return bcm_ns_usb3_wait_reg(usb3, usb3->ccb_mii + BCMA_CCB_MII_MNG_CTL, | 277 | return bcm_ns_usb3_wait_reg(usb3, usb3->ccb_mii + BCMA_CCB_MII_MNG_CTL, |
| 282 | 0x0100, 0x0000, | 278 | 0x0100, 0x0000, |
| 283 | usecs_to_jiffies(BCM_NS_USB3_MII_MNG_TIMEOUT_US)); | 279 | BCM_NS_USB3_MII_MNG_TIMEOUT_US); |
| 284 | } | 280 | } |
| 285 | 281 | ||
| 286 | static int bcm_ns_usb3_platform_phy_write(struct bcm_ns_usb3 *usb3, u16 reg, | 282 | static int bcm_ns_usb3_platform_phy_write(struct bcm_ns_usb3 *usb3, u16 reg, |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | |||
| 18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
| 19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
| 20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
| 21 | #include <linux/iopoll.h> | ||
| 21 | #include <linux/irq.h> | 22 | #include <linux/irq.h> |
| 22 | #include <linux/mfd/syscon.h> | 23 | #include <linux/mfd/syscon.h> |
| 23 | #include <linux/module.h> | 24 | #include <linux/module.h> |
| @@ -87,17 +88,11 @@ static const unsigned int usb_extcon_cable[] = { · 63 unmodified lines | |||
| 87 | static inline int pll_lock_stat(u32 usb_reg, int reg_mask, | 88 | static inline int pll_lock_stat(u32 usb_reg, int reg_mask, |
| 88 | struct ns2_phy_driver *driver) | 89 | struct ns2_phy_driver *driver) |
| 89 | { | 90 | { |
| 90 | int retry = PLL_LOCK_RETRY; | ||
| 91 | u32 val; | 91 | u32 val; |
| 92 | 92 | ||
| 93 | do { | 93 | return readl_poll_timeout_atomic(driver->icfgdrd_regs + usb_reg, |
| 94 | udelay(1); | 94 | val, (val & reg_mask), 1, |
| 95 | val = readl(driver->icfgdrd_regs + usb_reg); | 95 | PLL_LOCK_RETRY); |
| 96 | if (val & reg_mask) | ||
| 97 | return 0; | ||
| 98 | } while (--retry > 0); | ||
| 99 | |||
| 100 | return -EBUSY; | ||
| 101 | } | 96 | } |
| 102 | 97 | ||
| 103 | static int ns2_drd_phy_init(struct phy *phy) | 98 | static int ns2_drd_phy_init(struct phy *phy) |
| @@ -5,6 +5,7 @@ · 4 unmodified lines | |||
| 5 | 5 | ||
| 6 | #include <linux/delay.h> | 6 | #include <linux/delay.h> |
| 7 | #include <linux/io.h> | 7 | #include <linux/io.h> |
| 8 | #include <linux/iopoll.h> | ||
| 8 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| 9 | #include <linux/of.h> | 10 | #include <linux/of.h> |
| 10 | #include <linux/phy/phy.h> | 11 | #include <linux/phy/phy.h> |
| @@ -109,19 +110,15 @@ static inline void bcm_usb_reg32_setbits(void __iomem *addr, uint32_t set) · 98 unmodified lines | |||
| 109 | 110 | ||
| 110 | static int bcm_usb_pll_lock_check(void __iomem *addr, u32 bit) | 111 | static int bcm_usb_pll_lock_check(void __iomem *addr, u32 bit) |
| 111 | { | 112 | { |
| 112 | int retry; | 113 | u32 data; |
| 113 | u32 rd_data; | 114 | int ret; |
| 114 | 115 | ||
| 115 | retry = PLL_LOCK_RETRY_COUNT; | 116 | ret = readl_poll_timeout_atomic(addr, data, (data & bit), 1, |
| 116 | do { | 117 | PLL_LOCK_RETRY_COUNT); |
| 117 | rd_data = readl(addr); | 118 | if (ret) |
| 118 | if (rd_data & bit) | 119 | pr_err("%s: FAIL\n", __func__); |
| 119 | return 0; | ||
| 120 | udelay(1); | ||
| 121 | } while (--retry > 0); | ||
| 122 | 120 | ||
| 123 | pr_err("%s: FAIL\n", __func__); | 121 | return ret; |
| 124 | return -ETIMEDOUT; | ||
| 125 | } | 122 | } |
| 126 | 123 | ||
| 127 | static int bcm_usb_ss_phy_init(struct bcm_usb_phy_cfg *phy_cfg) | 124 | static int bcm_usb_ss_phy_init(struct bcm_usb_phy_cfg *phy_cfg) |
| @@ -97,7 +97,7 @@ struct cdns_reg_pairs { · 96 unmodified lines | |||
| 97 | 97 | ||
| 98 | struct cdns_salvo_data { | 98 | struct cdns_salvo_data { |
| 99 | u8 reg_offset_shift; | 99 | u8 reg_offset_shift; |
| 100 | struct cdns_reg_pairs *init_sequence_val; | 100 | const struct cdns_reg_pairs *init_sequence_val; |
| 101 | u8 init_sequence_length; | 101 | u8 init_sequence_length; |
| 102 | }; | 102 | }; |
| 103 | 103 | ||
| @@ -126,7 +126,7 @@ static void cdns_salvo_write(struct cdns_salvo_phy *salvo_phy, · 22 unmodified lines | |||
| 126 | * Below bringup sequence pair are from Cadence PHY's User Guide | 126 | * Below bringup sequence pair are from Cadence PHY's User Guide |
| 127 | * and NXP platform tuning results. | 127 | * and NXP platform tuning results. |
| 128 | */ | 128 | */ |
| 129 | static struct cdns_reg_pairs cdns_nxp_sequence_pair[] = { | 129 | static const struct cdns_reg_pairs cdns_nxp_sequence_pair[] = { |
| 130 | {0x0830, PHY_PMA_CMN_CTRL1}, | 130 | {0x0830, PHY_PMA_CMN_CTRL1}, |
| 131 | {0x0010, TB_ADDR_CMN_DIAG_HSCLK_SEL}, | 131 | {0x0010, TB_ADDR_CMN_DIAG_HSCLK_SEL}, |
| 132 | {0x00f0, TB_ADDR_CMN_PLL0_VCOCAL_INIT_TMR}, | 132 | {0x00f0, TB_ADDR_CMN_PLL0_VCOCAL_INIT_TMR}, |
| @@ -217,7 +217,7 @@ static int cdns_salvo_phy_init(struct phy *phy) · 84 unmodified lines | |||
| 217 | return ret; | 217 | return ret; |
| 218 | 218 | ||
| 219 | for (i = 0; i < data->init_sequence_length; i++) { | 219 | for (i = 0; i < data->init_sequence_length; i++) { |
| 220 | struct cdns_reg_pairs *reg_pair = data->init_sequence_val + i; | 220 | const struct cdns_reg_pairs *reg_pair = data->init_sequence_val + i; |
| 221 | 221 | ||
| 222 | cdns_salvo_write(salvo_phy, reg_pair->off, reg_pair->val); | 222 | cdns_salvo_write(salvo_phy, reg_pair->off, reg_pair->val); |
| 223 | } | 223 | } |
| @@ -251,7 +251,7 @@ static int cdns_salvo_phy_power_off(struct phy *phy) · 27 unmodified lines | |||
| 251 | return 0; | 251 | return 0; |
| 252 | } | 252 | } |
| 253 | 253 | ||
| 254 | static struct phy_ops cdns_salvo_phy_ops = { | 254 | static const struct phy_ops cdns_salvo_phy_ops = { |
| 255 | .init = cdns_salvo_phy_init, | 255 | .init = cdns_salvo_phy_init, |
| 256 | .power_on = cdns_salvo_phy_power_on, | 256 | .power_on = cdns_salvo_phy_power_on, |
| 257 | .power_off = cdns_salvo_phy_power_off, | 257 | .power_off = cdns_salvo_phy_power_off, |
| @@ -172,10 +172,10 @@ struct cdns_sierra_data { · 171 unmodified lines | |||
| 172 | u32 pcie_ln_regs; | 172 | u32 pcie_ln_regs; |
| 173 | u32 usb_cmn_regs; | 173 | u32 usb_cmn_regs; |
| 174 | u32 usb_ln_regs; | 174 | u32 usb_ln_regs; |
| 175 | struct cdns_reg_pairs *pcie_cmn_vals; | 175 | const struct cdns_reg_pairs *pcie_cmn_vals; |
| 176 | struct cdns_reg_pairs *pcie_ln_vals; | 176 | const struct cdns_reg_pairs *pcie_ln_vals; |
| 177 | struct cdns_reg_pairs *usb_cmn_vals; | 177 | const struct cdns_reg_pairs *usb_cmn_vals; |
| 178 | struct cdns_reg_pairs *usb_ln_vals; | 178 | const struct cdns_reg_pairs *usb_ln_vals; |
| 179 | }; | 179 | }; |
| 180 | 180 | ||
| 181 | struct cdns_regmap_cdb_context { | 181 | struct cdns_regmap_cdb_context { |
| @@ -233,7 +233,7 @@ static int cdns_regmap_read(void *context, unsigned int reg, unsigned int *val) · 51 unmodified lines | |||
| 233 | .reg_read = cdns_regmap_read, \ | 233 | .reg_read = cdns_regmap_read, \ |
| 234 | } | 234 | } |
| 235 | 235 | ||
| 236 | static struct regmap_config cdns_sierra_lane_cdb_config[] = { | 236 | static const struct regmap_config cdns_sierra_lane_cdb_config[] = { |
| 237 | SIERRA_LANE_CDB_REGMAP_CONF("0"), | 237 | SIERRA_LANE_CDB_REGMAP_CONF("0"), |
| 238 | SIERRA_LANE_CDB_REGMAP_CONF("1"), | 238 | SIERRA_LANE_CDB_REGMAP_CONF("1"), |
| 239 | SIERRA_LANE_CDB_REGMAP_CONF("2"), | 239 | SIERRA_LANE_CDB_REGMAP_CONF("2"), |
| @@ -252,7 +252,7 @@ static struct regmap_config cdns_sierra_lane_cdb_config[] = { · 12 unmodified lines | |||
| 252 | SIERRA_LANE_CDB_REGMAP_CONF("15"), | 252 | SIERRA_LANE_CDB_REGMAP_CONF("15"), |
| 253 | }; | 253 | }; |
| 254 | 254 | ||
| 255 | static struct regmap_config cdns_sierra_common_cdb_config = { | 255 | static const struct regmap_config cdns_sierra_common_cdb_config = { |
| 256 | .name = "sierra_common_cdb", | 256 | .name = "sierra_common_cdb", |
| 257 | .reg_stride = 1, | 257 | .reg_stride = 1, |
| 258 | .fast_io = true, | 258 | .fast_io = true, |
| @@ -260,7 +260,7 @@ static struct regmap_config cdns_sierra_common_cdb_config = { · 1 unmodified line | |||
| 260 | .reg_read = cdns_regmap_read, | 260 | .reg_read = cdns_regmap_read, |
| 261 | }; | 261 | }; |
| 262 | 262 | ||
| 263 | static struct regmap_config cdns_sierra_phy_config_ctrl_config = { | 263 | static const struct regmap_config cdns_sierra_phy_config_ctrl_config = { |
| 264 | .name = "sierra_phy_config_ctrl", | 264 | .name = "sierra_phy_config_ctrl", |
| 265 | .reg_stride = 1, | 265 | .reg_stride = 1, |
| 266 | .fast_io = true, | 266 | .fast_io = true, |
| @@ -274,7 +274,7 @@ static int cdns_sierra_phy_init(struct phy *gphy) · 7 unmodified lines | |||
| 274 | struct cdns_sierra_phy *phy = dev_get_drvdata(gphy->dev.parent); | 274 | struct cdns_sierra_phy *phy = dev_get_drvdata(gphy->dev.parent); |
| 275 | struct regmap *regmap; | 275 | struct regmap *regmap; |
| 276 | int i, j; | 276 | int i, j; |
| 277 | struct cdns_reg_pairs *cmn_vals, *ln_vals; | 277 | const struct cdns_reg_pairs *cmn_vals, *ln_vals; |
| 278 | u32 num_cmn_regs, num_ln_regs; | 278 | u32 num_cmn_regs, num_ln_regs; |
| 279 | 279 | ||
| 280 | /* Initialise the PHY registers, unless auto configured */ | 280 | /* Initialise the PHY registers, unless auto configured */ |
| @@ -654,7 +654,7 @@ static int cdns_sierra_phy_remove(struct platform_device *pdev) · 373 unmodified lines | |||
| 654 | } | 654 | } |
| 655 | 655 | ||
| 656 | /* refclk100MHz_32b_PCIe_cmn_pll_ext_ssc */ | 656 | /* refclk100MHz_32b_PCIe_cmn_pll_ext_ssc */ |
| 657 | static struct cdns_reg_pairs cdns_pcie_cmn_regs_ext_ssc[] = { | 657 | static const struct cdns_reg_pairs cdns_pcie_cmn_regs_ext_ssc[] = { |
| 658 | {0x2106, SIERRA_CMN_PLLLC_LF_COEFF_MODE1_PREG}, | 658 | {0x2106, SIERRA_CMN_PLLLC_LF_COEFF_MODE1_PREG}, |
| 659 | {0x2106, SIERRA_CMN_PLLLC_LF_COEFF_MODE0_PREG}, | 659 | {0x2106, SIERRA_CMN_PLLLC_LF_COEFF_MODE0_PREG}, |
| 660 | {0x8A06, SIERRA_CMN_PLLLC_BWCAL_MODE1_PREG}, | 660 | {0x8A06, SIERRA_CMN_PLLLC_BWCAL_MODE1_PREG}, |
| @@ -663,7 +663,7 @@ static struct cdns_reg_pairs cdns_pcie_cmn_regs_ext_ssc[] = { · 2 unmodified lines | |||
| 663 | }; | 663 | }; |
| 664 | 664 | ||
| 665 | /* refclk100MHz_32b_PCIe_ln_ext_ssc */ | 665 | /* refclk100MHz_32b_PCIe_ln_ext_ssc */ |
| 666 | static struct cdns_reg_pairs cdns_pcie_ln_regs_ext_ssc[] = { | 666 | static const struct cdns_reg_pairs cdns_pcie_ln_regs_ext_ssc[] = { |
| 667 | {0x813E, SIERRA_CLKPATHCTRL_TMR_PREG}, | 667 | {0x813E, SIERRA_CLKPATHCTRL_TMR_PREG}, |
| 668 | {0x8047, SIERRA_RX_CREQ_FLTR_A_MODE3_PREG}, | 668 | {0x8047, SIERRA_RX_CREQ_FLTR_A_MODE3_PREG}, |
| 669 | {0x808F, SIERRA_RX_CREQ_FLTR_A_MODE2_PREG}, | 669 | {0x808F, SIERRA_RX_CREQ_FLTR_A_MODE2_PREG}, |
| @@ -674,7 +674,7 @@ static struct cdns_reg_pairs cdns_pcie_ln_regs_ext_ssc[] = { · 4 unmodified lines | |||
| 674 | }; | 674 | }; |
| 675 | 675 | ||
| 676 | /* refclk100MHz_20b_USB_cmn_pll_ext_ssc */ | 676 | /* refclk100MHz_20b_USB_cmn_pll_ext_ssc */ |
| 677 | static struct cdns_reg_pairs cdns_usb_cmn_regs_ext_ssc[] = { | 677 | static const struct cdns_reg_pairs cdns_usb_cmn_regs_ext_ssc[] = { |
| 678 | {0x2085, SIERRA_CMN_PLLLC_LF_COEFF_MODE1_PREG}, | 678 | {0x2085, SIERRA_CMN_PLLLC_LF_COEFF_MODE1_PREG}, |
| 679 | {0x2085, SIERRA_CMN_PLLLC_LF_COEFF_MODE0_PREG}, | 679 | {0x2085, SIERRA_CMN_PLLLC_LF_COEFF_MODE0_PREG}, |
| 680 | {0x0000, SIERRA_CMN_PLLLC_BWCAL_MODE0_PREG}, | 680 | {0x0000, SIERRA_CMN_PLLLC_BWCAL_MODE0_PREG}, |
| @@ -682,7 +682,7 @@ static struct cdns_reg_pairs cdns_usb_cmn_regs_ext_ssc[] = { · 1 unmodified line | |||
| 682 | }; | 682 | }; |
| 683 | 683 | ||
| 684 | /* refclk100MHz_20b_USB_ln_ext_ssc */ | 684 | /* refclk100MHz_20b_USB_ln_ext_ssc */ |
| 685 | static struct cdns_reg_pairs cdns_usb_ln_regs_ext_ssc[] = { | 685 | static const struct cdns_reg_pairs cdns_usb_ln_regs_ext_ssc[] = { |
| 686 | {0xFE0A, SIERRA_DET_STANDEC_A_PREG}, | 686 | {0xFE0A, SIERRA_DET_STANDEC_A_PREG}, |
| 687 | {0x000F, SIERRA_DET_STANDEC_B_PREG}, | 687 | {0x000F, SIERRA_DET_STANDEC_B_PREG}, |
| 688 | {0x55A5, SIERRA_DET_STANDEC_C_PREG}, | 688 | {0x55A5, SIERRA_DET_STANDEC_C_PREG}, |
| @@ -25,11 +25,14 @@ · 24 unmodified lines | |||
| 25 | #define REF_CLK_19_2MHz 19200000 | 25 | #define REF_CLK_19_2MHz 19200000 |
| 26 | #define REF_CLK_25MHz 25000000 | 26 | #define REF_CLK_25MHz 25000000 |
| 27 | 27 | ||
| 28 | #define DEFAULT_NUM_LANES 4 | ||
| 29 | #define MAX_NUM_LANES 4 | 28 | #define MAX_NUM_LANES 4 |
| 30 | #define DEFAULT_MAX_BIT_RATE 8100 /* in Mbps */ | 29 | #define DEFAULT_MAX_BIT_RATE 8100 /* in Mbps */ |
| 31 | 30 | ||
| 31 | #define NUM_SSC_MODE 3 | ||
| 32 | #define NUM_PHY_TYPE 6 | ||
| 33 | |||
| 32 | #define POLL_TIMEOUT_US 5000 | 34 | #define POLL_TIMEOUT_US 5000 |
| 35 | #define PLL_LOCK_TIMEOUT 100000 | ||
| 33 | 36 | ||
| 34 | #define TORRENT_COMMON_CDB_OFFSET 0x0 | 37 | #define TORRENT_COMMON_CDB_OFFSET 0x0 |
| 35 | 38 | ||
| @@ -79,6 +82,8 @@ · 43 unmodified lines | |||
| 79 | #define CMN_PLLSM0_PLLLOCK_TMR 0x002CU | 82 | #define CMN_PLLSM0_PLLLOCK_TMR 0x002CU |
| 80 | #define CMN_PLLSM1_PLLPRE_TMR 0x0032U | 83 | #define CMN_PLLSM1_PLLPRE_TMR 0x0032U |
| 81 | #define CMN_PLLSM1_PLLLOCK_TMR 0x0034U | 84 | #define CMN_PLLSM1_PLLLOCK_TMR 0x0034U |
| 85 | #define CMN_CDIAG_CDB_PWRI_OVRD 0x0041U | ||
| 86 | #define CMN_CDIAG_XCVRC_PWRI_OVRD 0x0047U | ||
| 82 | #define CMN_BGCAL_INIT_TMR 0x0064U | 87 | #define CMN_BGCAL_INIT_TMR 0x0064U |
| 83 | #define CMN_BGCAL_ITER_TMR 0x0065U | 88 | #define CMN_BGCAL_ITER_TMR 0x0065U |
| 84 | #define CMN_IBCAL_INIT_TMR 0x0074U | 89 | #define CMN_IBCAL_INIT_TMR 0x0074U |
| @@ -99,6 +104,14 @@ · 14 unmodified lines | |||
| 99 | #define CMN_PLL0_LOCK_REFCNT_START 0x009CU | 104 | #define CMN_PLL0_LOCK_REFCNT_START 0x009CU |
| 100 | #define CMN_PLL0_LOCK_PLLCNT_START 0x009EU | 105 | #define CMN_PLL0_LOCK_PLLCNT_START 0x009EU |
| 101 | #define CMN_PLL0_LOCK_PLLCNT_THR 0x009FU | 106 | #define CMN_PLL0_LOCK_PLLCNT_THR 0x009FU |
| 107 | #define CMN_PLL0_INTDIV_M1 0x00A0U | ||
| 108 | #define CMN_PLL0_FRACDIVH_M1 0x00A2U | ||
| 109 | #define CMN_PLL0_HIGH_THR_M1 0x00A3U | ||
| 110 | #define CMN_PLL0_DSM_DIAG_M1 0x00A4U | ||
| 111 | #define CMN_PLL0_SS_CTRL1_M1 0x00A8U | ||
| 112 | #define CMN_PLL0_SS_CTRL2_M1 0x00A9U | ||
| 113 | #define CMN_PLL0_SS_CTRL3_M1 0x00AAU | ||
| 114 | #define CMN_PLL0_SS_CTRL4_M1 0x00ABU | ||
| 102 | #define CMN_PLL1_VCOCAL_TCTRL 0x00C2U | 115 | #define CMN_PLL1_VCOCAL_TCTRL 0x00C2U |
| 103 | #define CMN_PLL1_VCOCAL_INIT_TMR 0x00C4U | 116 | #define CMN_PLL1_VCOCAL_INIT_TMR 0x00C4U |
| 104 | #define CMN_PLL1_VCOCAL_ITER_TMR 0x00C5U | 117 | #define CMN_PLL1_VCOCAL_ITER_TMR 0x00C5U |
| @@ -116,8 +129,10 @@ · 11 unmodified lines | |||
| 116 | #define CMN_PLL1_LOCK_REFCNT_START 0x00DCU | 129 | #define CMN_PLL1_LOCK_REFCNT_START 0x00DCU |
| 117 | #define CMN_PLL1_LOCK_PLLCNT_START 0x00DEU | 130 | #define CMN_PLL1_LOCK_PLLCNT_START 0x00DEU |
| 118 | #define CMN_PLL1_LOCK_PLLCNT_THR 0x00DFU | 131 | #define CMN_PLL1_LOCK_PLLCNT_THR 0x00DFU |
| 132 | #define CMN_TXPUCAL_TUNE 0x0103U | ||
| 119 | #define CMN_TXPUCAL_INIT_TMR 0x0104U | 133 | #define CMN_TXPUCAL_INIT_TMR 0x0104U |
| 120 | #define CMN_TXPUCAL_ITER_TMR 0x0105U | 134 | #define CMN_TXPUCAL_ITER_TMR 0x0105U |
| 135 | #define CMN_TXPDCAL_TUNE 0x010BU | ||
| 121 | #define CMN_TXPDCAL_INIT_TMR 0x010CU | 136 | #define CMN_TXPDCAL_INIT_TMR 0x010CU |
| 122 | #define CMN_TXPDCAL_ITER_TMR 0x010DU | 137 | #define CMN_TXPDCAL_ITER_TMR 0x010DU |
| 123 | #define CMN_RXCAL_INIT_TMR 0x0114U | 138 | #define CMN_RXCAL_INIT_TMR 0x0114U |
| @@ -131,24 +146,31 @@ · 7 unmodified lines | |||
| 131 | #define CMN_PDIAG_PLL0_CP_PADJ_M0 0x01A4U | 146 | #define CMN_PDIAG_PLL0_CP_PADJ_M0 0x01A4U |
| 132 | #define CMN_PDIAG_PLL0_CP_IADJ_M0 0x01A5U | 147 | #define CMN_PDIAG_PLL0_CP_IADJ_M0 0x01A5U |
| 133 | #define CMN_PDIAG_PLL0_FILT_PADJ_M0 0x01A6U | 148 | #define CMN_PDIAG_PLL0_FILT_PADJ_M0 0x01A6U |
| 149 | #define CMN_PDIAG_PLL0_CTRL_M1 0x01B0U | ||
| 150 | #define CMN_PDIAG_PLL0_CLK_SEL_M1 0x01B1U | ||
| 134 | #define CMN_PDIAG_PLL0_CP_PADJ_M1 0x01B4U | 151 | #define CMN_PDIAG_PLL0_CP_PADJ_M1 0x01B4U |
| 135 | #define CMN_PDIAG_PLL0_CP_IADJ_M1 0x01B5U | 152 | #define CMN_PDIAG_PLL0_CP_IADJ_M1 0x01B5U |
| 153 | #define CMN_PDIAG_PLL0_FILT_PADJ_M1 0x01B6U | ||
| 136 | #define CMN_PDIAG_PLL1_CTRL_M0 0x01C0U | 154 | #define CMN_PDIAG_PLL1_CTRL_M0 0x01C0U |
| 137 | #define CMN_PDIAG_PLL1_CLK_SEL_M0 0x01C1U | 155 | #define CMN_PDIAG_PLL1_CLK_SEL_M0 0x01C1U |
| 138 | #define CMN_PDIAG_PLL1_CP_PADJ_M0 0x01C4U | 156 | #define CMN_PDIAG_PLL1_CP_PADJ_M0 0x01C4U |
| 139 | #define CMN_PDIAG_PLL1_CP_IADJ_M0 0x01C5U | 157 | #define CMN_PDIAG_PLL1_CP_IADJ_M0 0x01C5U |
| 140 | #define CMN_PDIAG_PLL1_FILT_PADJ_M0 0x01C6U | 158 | #define CMN_PDIAG_PLL1_FILT_PADJ_M0 0x01C6U |
| 159 | #define CMN_DIAG_BIAS_OVRD1 0x01E1U | ||
| 141 | 160 | ||
| 142 | /* PMA TX Lane registers */ | 161 | /* PMA TX Lane registers */ |
| 143 | #define TX_TXCC_CTRL 0x0040U | 162 | #define TX_TXCC_CTRL 0x0040U |
| 144 | #define TX_TXCC_CPOST_MULT_00 0x004CU | 163 | #define TX_TXCC_CPOST_MULT_00 0x004CU |
| 164 | #define TX_TXCC_CPOST_MULT_01 0x004DU | ||
| 145 | #define TX_TXCC_MGNFS_MULT_000 0x0050U | 165 | #define TX_TXCC_MGNFS_MULT_000 0x0050U |
| 146 | #define DRV_DIAG_TX_DRV 0x00C6U | 166 | #define DRV_DIAG_TX_DRV 0x00C6U |
| 147 | #define XCVR_DIAG_PLLDRC_CTRL 0x00E5U | 167 | #define XCVR_DIAG_PLLDRC_CTRL 0x00E5U |
| 148 | #define XCVR_DIAG_HSCLK_SEL 0x00E6U | 168 | #define XCVR_DIAG_HSCLK_SEL 0x00E6U |
| 149 | #define XCVR_DIAG_HSCLK_DIV 0x00E7U | 169 | #define XCVR_DIAG_HSCLK_DIV 0x00E7U |
| 150 | #define XCVR_DIAG_BIDI_CTRL 0x00EAU | 170 | #define XCVR_DIAG_BIDI_CTRL 0x00EAU |
| 171 | #define XCVR_DIAG_PSC_OVRD 0x00EBU | ||
| 151 | #define TX_PSC_A0 0x0100U | 172 | #define TX_PSC_A0 0x0100U |
| 173 | #define TX_PSC_A1 0x0101U | ||
| 152 | #define TX_PSC_A2 0x0102U | 174 | #define TX_PSC_A2 0x0102U |
| 153 | #define TX_PSC_A3 0x0103U | 175 | #define TX_PSC_A3 0x0103U |
| 154 | #define TX_RCVDET_ST_TMR 0x0123U | 176 | #define TX_RCVDET_ST_TMR 0x0123U |
| @@ -157,23 +179,49 @@ · 2 unmodified lines | |||
| 157 | 179 | ||
| 158 | /* PMA RX Lane registers */ | 180 | /* PMA RX Lane registers */ |
| 159 | #define RX_PSC_A0 0x0000U | 181 | #define RX_PSC_A0 0x0000U |
| 182 | #define RX_PSC_A1 0x0001U | ||
| 160 | #define RX_PSC_A2 0x0002U | 183 | #define RX_PSC_A2 0x0002U |
| 161 | #define RX_PSC_A3 0x0003U | 184 | #define RX_PSC_A3 0x0003U |
| 162 | #define RX_PSC_CAL 0x0006U | 185 | #define RX_PSC_CAL 0x0006U |
| 186 | #define RX_CDRLF_CNFG 0x0080U | ||
| 187 | #define RX_CDRLF_CNFG3 0x0082U | ||
| 188 | #define RX_SIGDET_HL_FILT_TMR 0x0090U | ||
| 163 | #define RX_REE_GCSM1_CTRL 0x0108U | 189 | #define RX_REE_GCSM1_CTRL 0x0108U |
| 190 | #define RX_REE_GCSM1_EQENM_PH1 0x0109U | ||
| 191 | #define RX_REE_GCSM1_EQENM_PH2 0x010AU | ||
| 164 | #define RX_REE_GCSM2_CTRL 0x0110U | 192 | #define RX_REE_GCSM2_CTRL 0x0110U |
| 165 | #define RX_REE_PERGCSM_CTRL 0x0118U | 193 | #define RX_REE_PERGCSM_CTRL 0x0118U |
| 194 | #define RX_REE_ATTEN_THR 0x0149U | ||
| 195 | #define RX_REE_TAP1_CLIP 0x0171U | ||
| 196 | #define RX_REE_TAP2TON_CLIP 0x0172U | ||
| 197 | #define RX_REE_SMGM_CTRL1 0x0177U | ||
| 198 | #define RX_REE_SMGM_CTRL2 0x0178U | ||
| 199 | #define RX_DIAG_DFE_CTRL 0x01E0U | ||
| 200 | #define RX_DIAG_DFE_AMP_TUNE_2 0x01E2U | ||
| 201 | #define RX_DIAG_DFE_AMP_TUNE_3 0x01E3U | ||
| 202 | #define RX_DIAG_NQST_CTRL 0x01E5U | ||
| 203 | #define RX_DIAG_SIGDET_TUNE 0x01E8U | ||
| 204 | #define RX_DIAG_PI_RATE 0x01F4U | ||
| 205 | #define RX_DIAG_PI_CAP 0x01F5U | ||
| 206 | #define RX_DIAG_ACYA 0x01FFU | ||
| 166 | 207 | ||
| 167 | /* PHY PCS common registers */ | 208 | /* PHY PCS common registers */ |
| 168 | #define PHY_PLL_CFG 0x000EU | 209 | #define PHY_PLL_CFG 0x000EU |
| 210 | #define PHY_PIPE_USB3_GEN2_PRE_CFG0 0x0020U | ||
| 211 | #define PHY_PIPE_USB3_GEN2_POST_CFG0 0x0022U | ||
| 212 | #define PHY_PIPE_USB3_GEN2_POST_CFG1 0x0023U | ||
| 169 | 213 | ||
| 170 | /* PHY PMA common registers */ | 214 | /* PHY PMA common registers */ |
| 215 | #define PHY_PMA_CMN_CTRL1 0x0000U | ||
| 171 | #define PHY_PMA_CMN_CTRL2 0x0001U | 216 | #define PHY_PMA_CMN_CTRL2 0x0001U |
| 172 | #define PHY_PMA_PLL_RAW_CTRL 0x0003U | 217 | #define PHY_PMA_PLL_RAW_CTRL 0x0003U |
| 173 | 218 | ||
| 174 | static const struct reg_field phy_pll_cfg = | 219 | static const struct reg_field phy_pll_cfg = |
| 175 | REG_FIELD(PHY_PLL_CFG, 0, 1); | 220 | REG_FIELD(PHY_PLL_CFG, 0, 1); |
| 176 | 221 | ||
| 222 | static const struct reg_field phy_pma_cmn_ctrl_1 = | ||
| 223 | REG_FIELD(PHY_PMA_CMN_CTRL1, 0, 0); | ||
| 224 | |||
| 177 | static const struct reg_field phy_pma_cmn_ctrl_2 = | 225 | static const struct reg_field phy_pma_cmn_ctrl_2 = |
| 178 | REG_FIELD(PHY_PMA_CMN_CTRL2, 0, 7); | 226 | REG_FIELD(PHY_PMA_CMN_CTRL2, 0, 7); |
| 179 | 227 | ||
| @@ -183,14 +231,28 @@ static const struct reg_field phy_pma_pll_raw_ctrl = · 3 unmodified lines | |||
| 183 | static const struct reg_field phy_reset_ctrl = | 231 | static const struct reg_field phy_reset_ctrl = |
| 184 | REG_FIELD(PHY_RESET, 8, 8); | 232 | REG_FIELD(PHY_RESET, 8, 8); |
| 185 | 233 | ||
| 186 | static const struct of_device_id cdns_torrent_phy_of_match[]; | 234 | enum cdns_torrent_phy_type { |
| 235 | TYPE_NONE, | ||
| 236 | TYPE_DP, | ||
| 237 | TYPE_PCIE, | ||
| 238 | TYPE_SGMII, | ||
| 239 | TYPE_QSGMII, | ||
| 240 | TYPE_USB, | ||
| 241 | }; | ||
| 242 | |||
| 243 | enum cdns_torrent_ssc_mode { | ||
| 244 | NO_SSC, | ||
| 245 | EXTERNAL_SSC, | ||
| 246 | INTERNAL_SSC | ||
| 247 | }; | ||
| 187 | 248 | ||
| 188 | struct cdns_torrent_inst { | 249 | struct cdns_torrent_inst { |
| 189 | struct phy *phy; | 250 | struct phy *phy; |
| 190 | u32 mlane; | 251 | u32 mlane; |
| 191 | u32 phy_type; | 252 | enum cdns_torrent_phy_type phy_type; |
| 192 | u32 num_lanes; | 253 | u32 num_lanes; |
| 193 | struct reset_control *lnk_rst; | 254 | struct reset_control *lnk_rst; |
| 255 | enum cdns_torrent_ssc_mode ssc_mode; | ||
| 194 | }; | 256 | }; |
| 195 | 257 | ||
| 196 | struct cdns_torrent_phy { | 258 | struct cdns_torrent_phy { |
| @@ -198,11 +260,13 @@ struct cdns_torrent_phy { · 1 unmodified line | |||
| 198 | void __iomem *sd_base; /* SD0801 registers base */ | 260 | void __iomem *sd_base; /* SD0801 registers base */ |
| 199 | u32 max_bit_rate; /* Maximum link bit rate to use (in Mbps) */ | 261 | u32 max_bit_rate; /* Maximum link bit rate to use (in Mbps) */ |
| 200 | struct reset_control *phy_rst; | 262 | struct reset_control *phy_rst; |
| 263 | struct reset_control *apb_rst; | ||
| 201 | struct device *dev; | 264 | struct device *dev; |
| 202 | struct clk *clk; | 265 | struct clk *clk; |
| 203 | unsigned long ref_clk_rate; | 266 | unsigned long ref_clk_rate; |
| 204 | struct cdns_torrent_inst phys[MAX_NUM_LANES]; | 267 | struct cdns_torrent_inst phys[MAX_NUM_LANES]; |
| 205 | int nsubnodes; | 268 | int nsubnodes; |
| 269 | const struct cdns_torrent_data *init_data; | ||
| 206 | struct regmap *regmap; | 270 | struct regmap *regmap; |
| 207 | struct regmap *regmap_common_cdb; | 271 | struct regmap *regmap_common_cdb; |
| 208 | struct regmap *regmap_phy_pcs_common_cdb; | 272 | struct regmap *regmap_phy_pcs_common_cdb; |
| @@ -211,6 +275,7 @@ struct cdns_torrent_phy { · 2 unmodified lines | |||
| 211 | struct regmap *regmap_rx_lane_cdb[MAX_NUM_LANES]; | 275 | struct regmap *regmap_rx_lane_cdb[MAX_NUM_LANES]; |
| 212 | struct regmap *regmap_dptx_phy_reg; | 276 | struct regmap *regmap_dptx_phy_reg; |
| 213 | struct regmap_field *phy_pll_cfg; | 277 | struct regmap_field *phy_pll_cfg; |
| 278 | struct regmap_field *phy_pma_cmn_ctrl_1; | ||
| 214 | struct regmap_field *phy_pma_cmn_ctrl_2; | 279 | struct regmap_field *phy_pma_cmn_ctrl_2; |
| 215 | struct regmap_field *phy_pma_pll_raw_ctrl; | 280 | struct regmap_field *phy_pma_pll_raw_ctrl; |
| 216 | struct regmap_field *phy_reset_ctrl; | 281 | struct regmap_field *phy_reset_ctrl; |
| @@ -223,8 +288,8 @@ enum phy_powerstate { · 6 unmodified lines | |||
| 223 | POWERSTATE_A3 = 3, | 288 | POWERSTATE_A3 = 3, |
| 224 | }; | 289 | }; |
| 225 | 290 | ||
| 291 | static int cdns_torrent_phy_init(struct phy *phy); | ||
| 226 | static int cdns_torrent_dp_init(struct phy *phy); | 292 | static int cdns_torrent_dp_init(struct phy *phy); |
| 227 | static int cdns_torrent_dp_exit(struct phy *phy); | ||
| 228 | static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, | 293 | static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, |
| 229 | u32 num_lanes); | 294 | u32 num_lanes); |
| 230 | static | 295 | static |
| @@ -254,17 +319,38 @@ static int cdns_torrent_phy_on(struct phy *phy); · 23 unmodified lines | |||
| 254 | static int cdns_torrent_phy_off(struct phy *phy); | 319 | static int cdns_torrent_phy_off(struct phy *phy); |
| 255 | 320 | ||
| 256 | static const struct phy_ops cdns_torrent_phy_ops = { | 321 | static const struct phy_ops cdns_torrent_phy_ops = { |
| 257 | .init = cdns_torrent_dp_init, | 322 | .init = cdns_torrent_phy_init, |
| 258 | .exit = cdns_torrent_dp_exit, | ||
| 259 | .configure = cdns_torrent_dp_configure, | 323 | .configure = cdns_torrent_dp_configure, |
| 260 | .power_on = cdns_torrent_phy_on, | 324 | .power_on = cdns_torrent_phy_on, |
| 261 | .power_off = cdns_torrent_phy_off, | 325 | .power_off = cdns_torrent_phy_off, |
| 262 | .owner = THIS_MODULE, | 326 | .owner = THIS_MODULE, |
| 263 | }; | 327 | }; |
| 264 | 328 | ||
| 329 | struct cdns_reg_pairs { | ||
| 330 | u32 val; | ||
| 331 | u32 off; | ||
| 332 | }; | ||
| 333 | |||
| 334 | struct cdns_torrent_vals { | ||
| 335 | struct cdns_reg_pairs *reg_pairs; | ||
| 336 | u32 num_regs; | ||
| 337 | }; | ||
| 338 | |||
| 265 | struct cdns_torrent_data { | 339 | struct cdns_torrent_data { |
| 266 | u8 block_offset_shift; | 340 | u8 block_offset_shift; |
| 267 | u8 reg_offset_shift; | 341 | u8 reg_offset_shift; |
| 342 | struct cdns_torrent_vals *link_cmn_vals[NUM_PHY_TYPE][NUM_PHY_TYPE] | ||
| 343 | [NUM_SSC_MODE]; | ||
| 344 | struct cdns_torrent_vals *xcvr_diag_vals[NUM_PHY_TYPE][NUM_PHY_TYPE] | ||
| 345 | [NUM_SSC_MODE]; | ||
| 346 | struct cdns_torrent_vals *pcs_cmn_vals[NUM_PHY_TYPE][NUM_PHY_TYPE] | ||
| 347 | [NUM_SSC_MODE]; | ||
| 348 | struct cdns_torrent_vals *cmn_vals[NUM_PHY_TYPE][NUM_PHY_TYPE] | ||
| 349 | [NUM_SSC_MODE]; | ||
| 350 | struct cdns_torrent_vals *tx_ln_vals[NUM_PHY_TYPE][NUM_PHY_TYPE] | ||
| 351 | [NUM_SSC_MODE]; | ||
| 352 | struct cdns_torrent_vals *rx_ln_vals[NUM_PHY_TYPE][NUM_PHY_TYPE] | ||
| 353 | [NUM_SSC_MODE]; | ||
| 268 | }; | 354 | }; |
| 269 | 355 | ||
| 270 | struct cdns_regmap_cdb_context { | 356 | struct cdns_regmap_cdb_context { |
| @@ -331,21 +417,21 @@ static int cdns_regmap_dptx_read(void *context, unsigned int reg, · 60 unmodified lines | |||
| 331 | .reg_read = cdns_regmap_read, \ | 417 | .reg_read = cdns_regmap_read, \ |
| 332 | } | 418 | } |
| 333 | 419 | ||
| 334 | static struct regmap_config cdns_torrent_tx_lane_cdb_config[] = { | 420 | static const struct regmap_config cdns_torrent_tx_lane_cdb_config[] = { |
| 335 | TORRENT_TX_LANE_CDB_REGMAP_CONF("0"), | 421 | TORRENT_TX_LANE_CDB_REGMAP_CONF("0"), |
| 336 | TORRENT_TX_LANE_CDB_REGMAP_CONF("1"), | 422 | TORRENT_TX_LANE_CDB_REGMAP_CONF("1"), |
| 337 | TORRENT_TX_LANE_CDB_REGMAP_CONF("2"), | 423 | TORRENT_TX_LANE_CDB_REGMAP_CONF("2"), |
| 338 | TORRENT_TX_LANE_CDB_REGMAP_CONF("3"), | 424 | TORRENT_TX_LANE_CDB_REGMAP_CONF("3"), |
| 339 | }; | 425 | }; |
| 340 | 426 | ||
| 341 | static struct regmap_config cdns_torrent_rx_lane_cdb_config[] = { | 427 | static const struct regmap_config cdns_torrent_rx_lane_cdb_config[] = { |
| 342 | TORRENT_RX_LANE_CDB_REGMAP_CONF("0"), | 428 | TORRENT_RX_LANE_CDB_REGMAP_CONF("0"), |
| 343 | TORRENT_RX_LANE_CDB_REGMAP_CONF("1"), | 429 | TORRENT_RX_LANE_CDB_REGMAP_CONF("1"), |
| 344 | TORRENT_RX_LANE_CDB_REGMAP_CONF("2"), | 430 | TORRENT_RX_LANE_CDB_REGMAP_CONF("2"), |
| 345 | TORRENT_RX_LANE_CDB_REGMAP_CONF("3"), | 431 | TORRENT_RX_LANE_CDB_REGMAP_CONF("3"), |
| 346 | }; | 432 | }; |
| 347 | 433 | ||
| 348 | static struct regmap_config cdns_torrent_common_cdb_config = { | 434 | static const struct regmap_config cdns_torrent_common_cdb_config = { |
| 349 | .name = "torrent_common_cdb", | 435 | .name = "torrent_common_cdb", |
| 350 | .reg_stride = 1, | 436 | .reg_stride = 1, |
| 351 | .fast_io = true, | 437 | .fast_io = true, |
| @@ -353,7 +439,7 @@ static struct regmap_config cdns_torrent_common_cdb_config = { · 1 unmodified line | |||
| 353 | .reg_read = cdns_regmap_read, | 439 | .reg_read = cdns_regmap_read, |
| 354 | }; | 440 | }; |
| 355 | 441 | ||
| 356 | static struct regmap_config cdns_torrent_phy_pcs_cmn_cdb_config = { | 442 | static const struct regmap_config cdns_torrent_phy_pcs_cmn_cdb_config = { |
| 357 | .name = "torrent_phy_pcs_cmn_cdb", | 443 | .name = "torrent_phy_pcs_cmn_cdb", |
| 358 | .reg_stride = 1, | 444 | .reg_stride = 1, |
| 359 | .fast_io = true, | 445 | .fast_io = true, |
| @@ -361,7 +447,7 @@ static struct regmap_config cdns_torrent_phy_pcs_cmn_cdb_config = { · 1 unmodified line | |||
| 361 | .reg_read = cdns_regmap_read, | 447 | .reg_read = cdns_regmap_read, |
| 362 | }; | 448 | }; |
| 363 | 449 | ||
| 364 | static struct regmap_config cdns_torrent_phy_pma_cmn_cdb_config = { | 450 | static const struct regmap_config cdns_torrent_phy_pma_cmn_cdb_config = { |
| 365 | .name = "torrent_phy_pma_cmn_cdb", | 451 | .name = "torrent_phy_pma_cmn_cdb", |
| 366 | .reg_stride = 1, | 452 | .reg_stride = 1, |
| 367 | .fast_io = true, | 453 | .fast_io = true, |
| @@ -369,7 +455,7 @@ static struct regmap_config cdns_torrent_phy_pma_cmn_cdb_config = { · 1 unmodified line | |||
| 369 | .reg_read = cdns_regmap_read, | 455 | .reg_read = cdns_regmap_read, |
| 370 | }; | 456 | }; |
| 371 | 457 | ||
| 372 | static struct regmap_config cdns_torrent_dptx_phy_config = { | 458 | static const struct regmap_config cdns_torrent_dptx_phy_config = { |
| 373 | .name = "torrent_dptx_phy", | 459 | .name = "torrent_dptx_phy", |
| 374 | .reg_stride = 1, | 460 | .reg_stride = 1, |
| 375 | .fast_io = true, | 461 | .fast_io = true, |
| @@ -848,19 +934,6 @@ static int cdns_torrent_dp_init(struct phy *phy) · 472 unmodified lines | |||
| 848 | struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); | 934 | struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); |
| 849 | struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; | 935 | struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg; |
| 850 | 936 | ||
| 851 | ret = clk_prepare_enable(cdns_phy->clk); | ||
| 852 | if (ret) { | ||
| 853 | dev_err(cdns_phy->dev, "Failed to prepare ref clock\n"); | ||
| 854 | return ret; | ||
| 855 | } | ||
| 856 | |||
| 857 | cdns_phy->ref_clk_rate = clk_get_rate(cdns_phy->clk); | ||
| 858 | if (!(cdns_phy->ref_clk_rate)) { | ||
| 859 | dev_err(cdns_phy->dev, "Failed to get ref clock rate\n"); | ||
| 860 | clk_disable_unprepare(cdns_phy->clk); | ||
| 861 | return -EINVAL; | ||
| 862 | } | ||
| 863 | |||
| 864 | switch (cdns_phy->ref_clk_rate) { | 937 | switch (cdns_phy->ref_clk_rate) { |
| 865 | case REF_CLK_19_2MHz: | 938 | case REF_CLK_19_2MHz: |
| 866 | case REF_CLK_25MHz: | 939 | case REF_CLK_25MHz: |
| @@ -920,14 +993,6 @@ static int cdns_torrent_dp_init(struct phy *phy) · 53 unmodified lines | |||
| 920 | return ret; | 993 | return ret; |
| 921 | } | 994 | } |
| 922 | 995 | ||
| 923 | static int cdns_torrent_dp_exit(struct phy *phy) | ||
| 924 | { | ||
| 925 | struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); | ||
| 926 | |||
| 927 | clk_disable_unprepare(cdns_phy->clk); | ||
| 928 | return 0; | ||
| 929 | } | ||
| 930 | |||
| 931 | static | 996 | static |
| 932 | int cdns_torrent_dp_wait_pma_cmn_ready(struct cdns_torrent_phy *cdns_phy) | 997 | int cdns_torrent_dp_wait_pma_cmn_ready(struct cdns_torrent_phy *cdns_phy) |
| 933 | { | 998 | { |
| @@ -1543,15 +1608,34 @@ static int cdns_torrent_phy_on(struct phy *phy) · 609 unmodified lines | |||
| 1543 | { | 1608 | { |
| 1544 | struct cdns_torrent_inst *inst = phy_get_drvdata(phy); | 1609 | struct cdns_torrent_inst *inst = phy_get_drvdata(phy); |
| 1545 | struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); | 1610 | struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); |
| 1611 | u32 read_val; | ||
| 1546 | int ret; | 1612 | int ret; |
| 1547 | 1613 | ||
| 1548 | /* Take the PHY out of reset */ | 1614 | if (cdns_phy->nsubnodes == 1) { |
| 1549 | ret = reset_control_deassert(cdns_phy->phy_rst); | 1615 | /* Take the PHY lane group out of reset */ |
| 1550 | if (ret) | 1616 | reset_control_deassert(inst->lnk_rst); |
| 1617 | |||
| 1618 | /* Take the PHY out of reset */ | ||
| 1619 | ret = reset_control_deassert(cdns_phy->phy_rst); | ||
| 1620 | if (ret) | ||
| 1621 | return ret; | ||
| 1622 | } | ||
| 1623 | |||
| 1624 | /* | ||
| 1625 | * Wait for cmn_ready assertion | ||
| 1626 | * PHY_PMA_CMN_CTRL1[0] == 1 | ||
| 1627 | */ | ||
| 1628 | ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_1, | ||
| 1629 | read_val, read_val, 1000, | ||
| 1630 | PLL_LOCK_TIMEOUT); | ||
| 1631 | if (ret) { | ||
| 1632 | dev_err(cdns_phy->dev, "Timeout waiting for CMN ready\n"); | ||
| 1551 | return ret; | 1633 | return ret; |
| 1634 | } | ||
| 1635 | |||
| 1636 | mdelay(10); | ||
| 1552 | 1637 | ||
| 1553 | /* Take the PHY lane group out of reset */ | 1638 | return 0; |
| 1554 | return reset_control_deassert(inst->lnk_rst); | ||
| 1555 | } | 1639 | } |
| 1556 | 1640 | ||
| 1557 | static int cdns_torrent_phy_off(struct phy *phy) | 1641 | static int cdns_torrent_phy_off(struct phy *phy) |
| @@ -1560,6 +1644,9 @@ static int cdns_torrent_phy_off(struct phy *phy) · 2 unmodified lines | |||
| 1560 | struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); | 1644 | struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); |
| 1561 | int ret; | 1645 | int ret; |
| 1562 | 1646 | ||
| 1647 | if (cdns_phy->nsubnodes != 1) | ||
| 1648 | return 0; | ||
| 1649 | |||
| 1563 | ret = reset_control_assert(cdns_phy->phy_rst); | 1650 | ret = reset_control_assert(cdns_phy->phy_rst); |
| 1564 | if (ret) | 1651 | if (ret) |
| 1565 | return ret; | 1652 | return ret; |
| @@ -1585,7 +1672,24 @@ static struct regmap *cdns_regmap_init(struct device *dev, void __iomem *base, · 19 unmodified lines | |||
| 1585 | return devm_regmap_init(dev, NULL, ctx, config); | 1672 | return devm_regmap_init(dev, NULL, ctx, config); |
| 1586 | } | 1673 | } |
| 1587 | 1674 | ||
| 1588 | static int cdns_regfield_init(struct cdns_torrent_phy *cdns_phy) | 1675 | static int cdns_torrent_dp_regfield_init(struct cdns_torrent_phy *cdns_phy) |
| 1676 | { | ||
| 1677 | struct device *dev = cdns_phy->dev; | ||
| 1678 | struct regmap_field *field; | ||
| 1679 | struct regmap *regmap; | ||
| 1680 | |||
| 1681 | regmap = cdns_phy->regmap_dptx_phy_reg; | ||
| 1682 | field = devm_regmap_field_alloc(dev, regmap, phy_reset_ctrl); | ||
| 1683 | if (IS_ERR(field)) { | ||
| 1684 | dev_err(dev, "PHY_RESET reg field init failed\n"); | ||
| 1685 | return PTR_ERR(field); | ||
| 1686 | } | ||
| 1687 | cdns_phy->phy_reset_ctrl = field; | ||
| 1688 | |||
| 1689 | return 0; | ||
| 1690 | } | ||
| 1691 | |||
| 1692 | static int cdns_torrent_regfield_init(struct cdns_torrent_phy *cdns_phy) | ||
| 1589 | { | 1693 | { |
| 1590 | struct device *dev = cdns_phy->dev; | 1694 | struct device *dev = cdns_phy->dev; |
| 1591 | struct regmap_field *field; | 1695 | struct regmap_field *field; |
| @@ -1599,6 +1703,14 @@ static int cdns_regfield_init(struct cdns_torrent_phy *cdns_phy) · 7 unmodified lines | |||
| 1599 | } | 1703 | } |
| 1600 | cdns_phy->phy_pll_cfg = field; | 1704 | cdns_phy->phy_pll_cfg = field; |
| 1601 | 1705 | ||
| 1706 | regmap = cdns_phy->regmap_phy_pma_common_cdb; | ||
| 1707 | field = devm_regmap_field_alloc(dev, regmap, phy_pma_cmn_ctrl_1); | ||
| 1708 | if (IS_ERR(field)) { | ||
| 1709 | dev_err(dev, "PHY_PMA_CMN_CTRL1 reg field init failed\n"); | ||
| 1710 | return PTR_ERR(field); | ||
| 1711 | } | ||
| 1712 | cdns_phy->phy_pma_cmn_ctrl_1 = field; | ||
| 1713 | |||
| 1602 | regmap = cdns_phy->regmap_phy_pma_common_cdb; | 1714 | regmap = cdns_phy->regmap_phy_pma_common_cdb; |
| 1603 | field = devm_regmap_field_alloc(dev, regmap, phy_pma_cmn_ctrl_2); | 1715 | field = devm_regmap_field_alloc(dev, regmap, phy_pma_cmn_ctrl_2); |
| 1604 | if (IS_ERR(field)) { | 1716 | if (IS_ERR(field)) { |
| @@ -1615,28 +1727,44 @@ static int cdns_regfield_init(struct cdns_torrent_phy *cdns_phy) · 10 unmodified lines | |||
| 1615 | } | 1727 | } |
| 1616 | cdns_phy->phy_pma_pll_raw_ctrl = field; | 1728 | cdns_phy->phy_pma_pll_raw_ctrl = field; |
| 1617 | 1729 | ||
| 1618 | regmap = cdns_phy->regmap_dptx_phy_reg; | 1730 | return 0; |
| 1619 | field = devm_regmap_field_alloc(dev, regmap, phy_reset_ctrl); | 1731 | } |
| 1620 | if (IS_ERR(field)) { | 1732 | |
| 1621 | dev_err(dev, "PHY_RESET reg field init failed\n"); | 1733 | static int cdns_torrent_dp_regmap_init(struct cdns_torrent_phy *cdns_phy) |
| 1622 | return PTR_ERR(field); | 1734 | { |
| 1735 | void __iomem *base = cdns_phy->base; | ||
| 1736 | struct device *dev = cdns_phy->dev; | ||
| 1737 | struct regmap *regmap; | ||
| 1738 | u8 reg_offset_shift; | ||
| 1739 | u32 block_offset; | ||
| 1740 | |||
| 1741 | reg_offset_shift = cdns_phy->init_data->reg_offset_shift; | ||
| 1742 | |||
| 1743 | block_offset = TORRENT_DPTX_PHY_OFFSET; | ||
| 1744 | regmap = cdns_regmap_init(dev, base, block_offset, | ||
| 1745 | reg_offset_shift, | ||
| 1746 | &cdns_torrent_dptx_phy_config); | ||
| 1747 | if (IS_ERR(regmap)) { | ||
| 1748 | dev_err(dev, "Failed to init DPTX PHY regmap\n"); | ||
| 1749 | return PTR_ERR(regmap); | ||
| 1623 | } | 1750 | } |
| 1624 | cdns_phy->phy_reset_ctrl = field; | 1751 | cdns_phy->regmap_dptx_phy_reg = regmap; |
| 1625 | 1752 | ||
| 1626 | return 0; | 1753 | return 0; |
| 1627 | } | 1754 | } |
| 1628 | 1755 | ||
| 1629 | static int cdns_regmap_init_torrent_dp(struct cdns_torrent_phy *cdns_phy, | 1756 | static int cdns_torrent_regmap_init(struct cdns_torrent_phy *cdns_phy) |
| 1630 | void __iomem *sd_base, | ||
| 1631 | void __iomem *base, | ||
| 1632 | u8 block_offset_shift, | ||
| 1633 | u8 reg_offset_shift) | ||
| 1634 | { | 1757 | { |
| 1758 | void __iomem *sd_base = cdns_phy->sd_base; | ||
| 1759 | u8 block_offset_shift, reg_offset_shift; | ||
| 1635 | struct device *dev = cdns_phy->dev; | 1760 | struct device *dev = cdns_phy->dev; |
| 1636 | struct regmap *regmap; | 1761 | struct regmap *regmap; |
| 1637 | u32 block_offset; | 1762 | u32 block_offset; |
| 1638 | int i; | 1763 | int i; |
| 1639 | 1764 | ||
| 1765 | block_offset_shift = cdns_phy->init_data->block_offset_shift; | ||
| 1766 | reg_offset_shift = cdns_phy->init_data->reg_offset_shift; | ||
| 1767 | |||
| 1640 | for (i = 0; i < MAX_NUM_LANES; i++) { | 1768 | for (i = 0; i < MAX_NUM_LANES; i++) { |
| 1641 | block_offset = TORRENT_TX_LANE_CDB_OFFSET(i, block_offset_shift, | 1769 | block_offset = TORRENT_TX_LANE_CDB_OFFSET(i, block_offset_shift, |
| 1642 | reg_offset_shift); | 1770 | reg_offset_shift); |
| @@ -1691,43 +1819,282 @@ static int cdns_regmap_init_torrent_dp(struct cdns_torrent_phy *cdns_phy, · 48 unmodified lines | |||
| 1691 | } | 1819 | } |
| 1692 | cdns_phy->regmap_phy_pma_common_cdb = regmap; | 1820 | cdns_phy->regmap_phy_pma_common_cdb = regmap; |
| 1693 | 1821 | ||
| 1694 | block_offset = TORRENT_DPTX_PHY_OFFSET; | 1822 | return 0; |
| 1695 | regmap = cdns_regmap_init(dev, base, block_offset, | 1823 | } |
| 1696 | reg_offset_shift, | 1824 | |
| 1697 | &cdns_torrent_dptx_phy_config); | 1825 | static int cdns_torrent_phy_init(struct phy *phy) |
| 1698 | if (IS_ERR(regmap)) { | 1826 | { |
| 1699 | dev_err(dev, "Failed to init DPTX PHY regmap\n"); | 1827 | struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent); |
| 1700 | return PTR_ERR(regmap); | 1828 | const struct cdns_torrent_data *init_data = cdns_phy->init_data; |
| 1829 | struct cdns_torrent_vals *cmn_vals, *tx_ln_vals, *rx_ln_vals; | ||
| 1830 | struct cdns_torrent_vals *link_cmn_vals, *xcvr_diag_vals; | ||
| 1831 | struct cdns_torrent_inst *inst = phy_get_drvdata(phy); | ||
| 1832 | enum cdns_torrent_phy_type phy_type = inst->phy_type; | ||
| 1833 | enum cdns_torrent_ssc_mode ssc = inst->ssc_mode; | ||
| 1834 | struct cdns_torrent_vals *pcs_cmn_vals; | ||
| 1835 | struct cdns_reg_pairs *reg_pairs; | ||
| 1836 | struct regmap *regmap; | ||
| 1837 | u32 num_regs; | ||
| 1838 | int i, j; | ||
| 1839 | |||
| 1840 | if (cdns_phy->nsubnodes > 1) | ||
| 1841 | return 0; | ||
| 1842 | |||
| 1843 | if (phy_type == TYPE_DP) | ||
| 1844 | return cdns_torrent_dp_init(phy); | ||
| 1845 | |||
| 1846 | /** | ||
| 1847 | * Spread spectrum generation is not required or supported | ||
| 1848 | * for SGMII/QSGMII | ||
| 1849 | */ | ||
| 1850 | if (phy_type == TYPE_SGMII || phy_type == TYPE_QSGMII) | ||
| 1851 | ssc = NO_SSC; | ||
| 1852 | |||
| 1853 | /* PHY configuration specific registers for single link */ | ||
| 1854 | link_cmn_vals = init_data->link_cmn_vals[phy_type][TYPE_NONE][ssc]; | ||
| 1855 | if (link_cmn_vals) { | ||
| 1856 | reg_pairs = link_cmn_vals->reg_pairs; | ||
| 1857 | num_regs = link_cmn_vals->num_regs; | ||
| 1858 | regmap = cdns_phy->regmap_common_cdb; | ||
| 1859 | |||
| 1860 | /** | ||
| 1861 | * First array value in link_cmn_vals must be of | ||
| 1862 | * PHY_PLL_CFG register | ||
| 1863 | */ | ||
| 1864 | regmap_field_write(cdns_phy->phy_pll_cfg, reg_pairs[0].val); | ||
| 1865 | |||
| 1866 | for (i = 1; i < num_regs; i++) | ||
| 1867 | regmap_write(regmap, reg_pairs[i].off, | ||
| 1868 | reg_pairs[i].val); | ||
| 1869 | } | ||
| 1870 | |||
| 1871 | xcvr_diag_vals = init_data->xcvr_diag_vals[phy_type][TYPE_NONE][ssc]; | ||
| 1872 | if (xcvr_diag_vals) { | ||
| 1873 | reg_pairs = xcvr_diag_vals->reg_pairs; | ||
| 1874 | num_regs = xcvr_diag_vals->num_regs; | ||
| 1875 | for (i = 0; i < inst->num_lanes; i++) { | ||
| 1876 | regmap = cdns_phy->regmap_tx_lane_cdb[i + inst->mlane]; | ||
| 1877 | for (j = 0; j < num_regs; j++) | ||
| 1878 | regmap_write(regmap, reg_pairs[j].off, | ||
| 1879 | reg_pairs[j].val); | ||
| 1880 | } | ||
| 1881 | } | ||
| 1882 | |||
| 1883 | /* PHY PCS common registers configurations */ | ||
| 1884 | pcs_cmn_vals = init_data->pcs_cmn_vals[phy_type][TYPE_NONE][ssc]; | ||
| 1885 | if (pcs_cmn_vals) { | ||
| 1886 | reg_pairs = pcs_cmn_vals->reg_pairs; | ||
| 1887 | num_regs = pcs_cmn_vals->num_regs; | ||
| 1888 | regmap = cdns_phy->regmap_phy_pcs_common_cdb; | ||
| 1889 | for (i = 0; i < num_regs; i++) | ||
| 1890 | regmap_write(regmap, reg_pairs[i].off, | ||
| 1891 | reg_pairs[i].val); | ||
| 1892 | } | ||
| 1893 | |||
| 1894 | /* PMA common registers configurations */ | ||
| 1895 | cmn_vals = init_data->cmn_vals[phy_type][TYPE_NONE][ssc]; | ||
| 1896 | if (cmn_vals) { | ||
| 1897 | reg_pairs = cmn_vals->reg_pairs; | ||
| 1898 | num_regs = cmn_vals->num_regs; | ||
| 1899 | regmap = cdns_phy->regmap_common_cdb; | ||
| 1900 | for (i = 0; i < num_regs; i++) | ||
| 1901 | regmap_write(regmap, reg_pairs[i].off, | ||
| 1902 | reg_pairs[i].val); | ||
| 1903 | } | ||
| 1904 | |||
| 1905 | /* PMA TX lane registers configurations */ | ||
| 1906 | tx_ln_vals = init_data->tx_ln_vals[phy_type][TYPE_NONE][ssc]; | ||
| 1907 | if (tx_ln_vals) { | ||
| 1908 | reg_pairs = tx_ln_vals->reg_pairs; | ||
| 1909 | num_regs = tx_ln_vals->num_regs; | ||
| 1910 | for (i = 0; i < inst->num_lanes; i++) { | ||
| 1911 | regmap = cdns_phy->regmap_tx_lane_cdb[i + inst->mlane]; | ||
| 1912 | for (j = 0; j < num_regs; j++) | ||
| 1913 | regmap_write(regmap, reg_pairs[j].off, | ||
| 1914 | reg_pairs[j].val); | ||
| 1915 | } | ||
| 1916 | } | ||
| 1917 | |||
| 1918 | /* PMA RX lane registers configurations */ | ||
| 1919 | rx_ln_vals = init_data->rx_ln_vals[phy_type][TYPE_NONE][ssc]; | ||
| 1920 | if (rx_ln_vals) { | ||
| 1921 | reg_pairs = rx_ln_vals->reg_pairs; | ||
| 1922 | num_regs = rx_ln_vals->num_regs; | ||
| 1923 | for (i = 0; i < inst->num_lanes; i++) { | ||
| 1924 | regmap = cdns_phy->regmap_rx_lane_cdb[i + inst->mlane]; | ||
| 1925 | for (j = 0; j < num_regs; j++) | ||
| 1926 | regmap_write(regmap, reg_pairs[j].off, | ||
| 1927 | reg_pairs[j].val); | ||
| 1928 | } | ||
| 1701 | } | 1929 | } |
| 1702 | cdns_phy->regmap_dptx_phy_reg = regmap; | 1930 | |
| 1931 | return 0; | ||
| 1932 | } | ||
| 1933 | |||
| 1934 | static | ||
| 1935 | int cdns_torrent_phy_configure_multilink(struct cdns_torrent_phy *cdns_phy) | ||
| 1936 | { | ||
| 1937 | const struct cdns_torrent_data *init_data = cdns_phy->init_data; | ||
| 1938 | struct cdns_torrent_vals *cmn_vals, *tx_ln_vals, *rx_ln_vals; | ||
| 1939 | struct cdns_torrent_vals *link_cmn_vals, *xcvr_diag_vals; | ||
| 1940 | enum cdns_torrent_phy_type phy_t1, phy_t2, tmp_phy_type; | ||
| 1941 | struct cdns_torrent_vals *pcs_cmn_vals; | ||
| 1942 | int i, j, node, mlane, num_lanes, ret; | ||
| 1943 | struct cdns_reg_pairs *reg_pairs; | ||
| 1944 | enum cdns_torrent_ssc_mode ssc; | ||
| 1945 | struct regmap *regmap; | ||
| 1946 | u32 num_regs; | ||
| 1947 | |||
| 1948 | /* Maximum 2 links (subnodes) are supported */ | ||
| 1949 | if (cdns_phy->nsubnodes != 2) | ||
| 1950 | return -EINVAL; | ||
| 1951 | |||
| 1952 | phy_t1 = cdns_phy->phys[0].phy_type; | ||
| 1953 | phy_t2 = cdns_phy->phys[1].phy_type; | ||
| 1954 | |||
| 1955 | /** | ||
| 1956 | * First configure the PHY for first link with phy_t1. Get the array | ||
| 1957 | * values as [phy_t1][phy_t2][ssc]. | ||
| 1958 | */ | ||
| 1959 | for (node = 0; node < cdns_phy->nsubnodes; node++) { | ||
| 1960 | if (node == 1) { | ||
| 1961 | /** | ||
| 1962 | * If first link with phy_t1 is configured, then | ||
| 1963 | * configure the PHY for second link with phy_t2. | ||
| 1964 | * Get the array values as [phy_t2][phy_t1][ssc]. | ||
| 1965 | */ | ||
| 1966 | tmp_phy_type = phy_t1; | ||
| 1967 | phy_t1 = phy_t2; | ||
| 1968 | phy_t2 = tmp_phy_type; | ||
| 1969 | } | ||
| 1970 | |||
| 1971 | mlane = cdns_phy->phys[node].mlane; | ||
| 1972 | ssc = cdns_phy->phys[node].ssc_mode; | ||
| 1973 | num_lanes = cdns_phy->phys[node].num_lanes; | ||
| 1974 | |||
| 1975 | /** | ||
| 1976 | * PHY configuration specific registers: | ||
| 1977 | * link_cmn_vals depend on combination of PHY types being | ||
| 1978 | * configured and are common for both PHY types, so array | ||
| 1979 | * values should be same for [phy_t1][phy_t2][ssc] and | ||
| 1980 | * [phy_t2][phy_t1][ssc]. | ||
| 1981 | * xcvr_diag_vals also depend on combination of PHY types | ||
| 1982 | * being configured, but these can be different for particular | ||
| 1983 | * PHY type and are per lane. | ||
| 1984 | */ | ||
| 1985 | link_cmn_vals = init_data->link_cmn_vals[phy_t1][phy_t2][ssc]; | ||
| 1986 | if (link_cmn_vals) { | ||
| 1987 | reg_pairs = link_cmn_vals->reg_pairs; | ||
| 1988 | num_regs = link_cmn_vals->num_regs; | ||
| 1989 | regmap = cdns_phy->regmap_common_cdb; | ||
| 1990 | |||
| 1991 | /** | ||
| 1992 | * First array value in link_cmn_vals must be of | ||
| 1993 | * PHY_PLL_CFG register | ||
| 1994 | */ | ||
| 1995 | regmap_field_write(cdns_phy->phy_pll_cfg, | ||
| 1996 | reg_pairs[0].val); | ||
| 1997 | |||
| 1998 | for (i = 1; i < num_regs; i++) | ||
| 1999 | regmap_write(regmap, reg_pairs[i].off, | ||
| 2000 | reg_pairs[i].val); | ||
| 2001 | } | ||
| 2002 | |||
| 2003 | xcvr_diag_vals = init_data->xcvr_diag_vals[phy_t1][phy_t2][ssc]; | ||
| 2004 | if (xcvr_diag_vals) { | ||
| 2005 | reg_pairs = xcvr_diag_vals->reg_pairs; | ||
| 2006 | num_regs = xcvr_diag_vals->num_regs; | ||
| 2007 | for (i = 0; i < num_lanes; i++) { | ||
| 2008 | regmap = cdns_phy->regmap_tx_lane_cdb[i + mlane]; | ||
| 2009 | for (j = 0; j < num_regs; j++) | ||
| 2010 | regmap_write(regmap, reg_pairs[j].off, | ||
| 2011 | reg_pairs[j].val); | ||
| 2012 | } | ||
| 2013 | } | ||
| 2014 | |||
| 2015 | /* PHY PCS common registers configurations */ | ||
| 2016 | pcs_cmn_vals = init_data->pcs_cmn_vals[phy_t1][phy_t2][ssc]; | ||
| 2017 | if (pcs_cmn_vals) { | ||
| 2018 | reg_pairs = pcs_cmn_vals->reg_pairs; | ||
| 2019 | num_regs = pcs_cmn_vals->num_regs; | ||
| 2020 | regmap = cdns_phy->regmap_phy_pcs_common_cdb; | ||
| 2021 | for (i = 0; i < num_regs; i++) | ||
| 2022 | regmap_write(regmap, reg_pairs[i].off, | ||
| 2023 | reg_pairs[i].val); | ||
| 2024 | } | ||
| 2025 | |||
| 2026 | /* PMA common registers configurations */ | ||
| 2027 | cmn_vals = init_data->cmn_vals[phy_t1][phy_t2][ssc]; | ||
| 2028 | if (cmn_vals) { | ||
| 2029 | reg_pairs = cmn_vals->reg_pairs; | ||
| 2030 | num_regs = cmn_vals->num_regs; | ||
| 2031 | regmap = cdns_phy->regmap_common_cdb; | ||
| 2032 | for (i = 0; i < num_regs; i++) | ||
| 2033 | regmap_write(regmap, reg_pairs[i].off, | ||
| 2034 | reg_pairs[i].val); | ||
| 2035 | } | ||
| 2036 | |||
| 2037 | /* PMA TX lane registers configurations */ | ||
| 2038 | tx_ln_vals = init_data->tx_ln_vals[phy_t1][phy_t2][ssc]; | ||
| 2039 | if (tx_ln_vals) { | ||
| 2040 | reg_pairs = tx_ln_vals->reg_pairs; | ||
| 2041 | num_regs = tx_ln_vals->num_regs; | ||
| 2042 | for (i = 0; i < num_lanes; i++) { | ||
| 2043 | regmap = cdns_phy->regmap_tx_lane_cdb[i + mlane]; | ||
| 2044 | for (j = 0; j < num_regs; j++) | ||
| 2045 | regmap_write(regmap, reg_pairs[j].off, | ||
| 2046 | reg_pairs[j].val); | ||
| 2047 | } | ||
| 2048 | } | ||
| 2049 | |||
| 2050 | /* PMA RX lane registers configurations */ | ||
| 2051 | rx_ln_vals = init_data->rx_ln_vals[phy_t1][phy_t2][ssc]; | ||
| 2052 | if (rx_ln_vals) { | ||
| 2053 | reg_pairs = rx_ln_vals->reg_pairs; | ||
| 2054 | num_regs = rx_ln_vals->num_regs; | ||
| 2055 | for (i = 0; i < num_lanes; i++) { | ||
| 2056 | regmap = cdns_phy->regmap_rx_lane_cdb[i + mlane]; | ||
| 2057 | for (j = 0; j < num_regs; j++) | ||
| 2058 | regmap_write(regmap, reg_pairs[j].off, | ||
| 2059 | reg_pairs[j].val); | ||
| 2060 | } | ||
| 2061 | } | ||
| 2062 | |||
| 2063 | reset_control_deassert(cdns_phy->phys[node].lnk_rst); | ||
| 2064 | } | ||
| 2065 | |||
| 2066 | /* Take the PHY out of reset */ | ||
| 2067 | ret = reset_control_deassert(cdns_phy->phy_rst); | ||
| 2068 | if (ret) | ||
| 2069 | return ret; | ||
| 1703 | 2070 | ||
| 1704 | return 0; | 2071 | return 0; |
| 1705 | } | 2072 | } |
| 1706 | 2073 | ||
| 1707 | static int cdns_torrent_phy_probe(struct platform_device *pdev) | 2074 | static int cdns_torrent_phy_probe(struct platform_device *pdev) |
| 1708 | { | 2075 | { |
| 1709 | struct resource *regs; | ||
| 1710 | struct cdns_torrent_phy *cdns_phy; | 2076 | struct cdns_torrent_phy *cdns_phy; |
| 1711 | struct device *dev = &pdev->dev; | 2077 | struct device *dev = &pdev->dev; |
| 1712 | struct phy_provider *phy_provider; | 2078 | struct phy_provider *phy_provider; |
| 1713 | const struct of_device_id *match; | 2079 | const struct cdns_torrent_data *data; |
| 1714 | struct cdns_torrent_data *data; | ||
| 1715 | struct device_node *child; | 2080 | struct device_node *child; |
| 1716 | int ret, subnodes, node = 0, i; | 2081 | int ret, subnodes, node = 0, i; |
| 2082 | u32 total_num_lanes = 0; | ||
| 2083 | u8 init_dp_regmap = 0; | ||
| 2084 | u32 phy_type; | ||
| 1717 | 2085 | ||
| 1718 | /* Get init data for this PHY */ | 2086 | /* Get init data for this PHY */ |
| 1719 | match = of_match_device(cdns_torrent_phy_of_match, dev); | 2087 | data = of_device_get_match_data(dev); |
| 1720 | if (!match) | 2088 | if (!data) |
| 1721 | return -EINVAL; | 2089 | return -EINVAL; |
| 1722 | 2090 | ||
| 1723 | data = (struct cdns_torrent_data *)match->data; | ||
| 1724 | |||
| 1725 | cdns_phy = devm_kzalloc(dev, sizeof(*cdns_phy), GFP_KERNEL); | 2091 | cdns_phy = devm_kzalloc(dev, sizeof(*cdns_phy), GFP_KERNEL); |
| 1726 | if (!cdns_phy) | 2092 | if (!cdns_phy) |
| 1727 | return -ENOMEM; | 2093 | return -ENOMEM; |
| 1728 | 2094 | ||
| 1729 | dev_set_drvdata(dev, cdns_phy); | 2095 | dev_set_drvdata(dev, cdns_phy); |
| 1730 | cdns_phy->dev = dev; | 2096 | cdns_phy->dev = dev; |
| 2097 | cdns_phy->init_data = data; | ||
| 1731 | 2098 | ||
| 1732 | cdns_phy->phy_rst = devm_reset_control_get_exclusive_by_index(dev, 0); | 2099 | cdns_phy->phy_rst = devm_reset_control_get_exclusive_by_index(dev, 0); |
| 1733 | if (IS_ERR(cdns_phy->phy_rst)) { | 2100 | if (IS_ERR(cdns_phy->phy_rst)) { |
| @@ -1736,14 +2103,20 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev) · 2 unmodified lines | |||
| 1736 | return PTR_ERR(cdns_phy->phy_rst); | 2103 | return PTR_ERR(cdns_phy->phy_rst); |
| 1737 | } | 2104 | } |
| 1738 | 2105 | ||
| 2106 | cdns_phy->apb_rst = devm_reset_control_get_optional(dev, "torrent_apb"); | ||
| 2107 | if (IS_ERR(cdns_phy->apb_rst)) { | ||
| 2108 | dev_err(dev, "%s: failed to get apb reset\n", | ||
| 2109 | dev->of_node->full_name); | ||
| 2110 | return PTR_ERR(cdns_phy->apb_rst); | ||
| 2111 | } | ||
| 2112 | |||
| 1739 | cdns_phy->clk = devm_clk_get(dev, "refclk"); | 2113 | cdns_phy->clk = devm_clk_get(dev, "refclk"); |
| 1740 | if (IS_ERR(cdns_phy->clk)) { | 2114 | if (IS_ERR(cdns_phy->clk)) { |
| 1741 | dev_err(dev, "phy ref clock not found\n"); | 2115 | dev_err(dev, "phy ref clock not found\n"); |
| 1742 | return PTR_ERR(cdns_phy->clk); | 2116 | return PTR_ERR(cdns_phy->clk); |
| 1743 | } | 2117 | } |
| 1744 | 2118 | ||
| 1745 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 2119 | cdns_phy->sd_base = devm_platform_ioremap_resource(pdev, 0); |
| 1746 | cdns_phy->sd_base = devm_ioremap_resource(&pdev->dev, regs); | ||
| 1747 | if (IS_ERR(cdns_phy->sd_base)) | 2120 | if (IS_ERR(cdns_phy->sd_base)) |
| 1748 | return PTR_ERR(cdns_phy->sd_base); | 2121 | return PTR_ERR(cdns_phy->sd_base); |
| 1749 | 2122 | ||
| @@ -1751,14 +2124,39 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev) · 1 unmodified line | |||
| 1751 | if (subnodes == 0) { | 2124 | if (subnodes == 0) { |
| 1752 | dev_err(dev, "No available link subnodes found\n"); | 2125 | dev_err(dev, "No available link subnodes found\n"); |
| 1753 | return -EINVAL; | 2126 | return -EINVAL; |
| 1754 | } else if (subnodes != 1) { | 2127 | } |
| 1755 | dev_err(dev, "Driver supports only one link subnode.\n"); | 2128 | |
| 2129 | ret = cdns_torrent_regmap_init(cdns_phy); | ||
| 2130 | if (ret) | ||
| 2131 | return ret; | ||
| 2132 | |||
| 2133 | ret = cdns_torrent_regfield_init(cdns_phy); | ||
| 2134 | if (ret) | ||
| 2135 | return ret; | ||
| 2136 | |||
| 2137 | ret = clk_prepare_enable(cdns_phy->clk); | ||
| 2138 | if (ret) { | ||
| 2139 | dev_err(cdns_phy->dev, "Failed to prepare ref clock\n"); | ||
| 2140 | return ret; | ||
| 2141 | } | ||
| 2142 | |||
| 2143 | cdns_phy->ref_clk_rate = clk_get_rate(cdns_phy->clk); | ||
| 2144 | if (!(cdns_phy->ref_clk_rate)) { | ||
| 2145 | dev_err(cdns_phy->dev, "Failed to get ref clock rate\n"); | ||
| 2146 | clk_disable_unprepare(cdns_phy->clk); | ||
| 1756 | return -EINVAL; | 2147 | return -EINVAL; |
| 1757 | } | 2148 | } |
| 1758 | 2149 | ||
| 2150 | /* Enable APB */ | ||
| 2151 | reset_control_deassert(cdns_phy->apb_rst); | ||
| 2152 | |||
| 1759 | for_each_available_child_of_node(dev->of_node, child) { | 2153 | for_each_available_child_of_node(dev->of_node, child) { |
| 1760 | struct phy *gphy; | 2154 | struct phy *gphy; |
| 1761 | 2155 | ||
| 2156 | /* PHY subnode name must be 'phy'. */ | ||
| 2157 | if (!(of_node_name_eq(child, "phy"))) | ||
| 2158 | continue; | ||
| 2159 | |||
| 1762 | cdns_phy->phys[node].lnk_rst = | 2160 | cdns_phy->phys[node].lnk_rst = |
| 1763 | of_reset_control_array_get_exclusive(child); | 2161 | of_reset_control_array_get_exclusive(child); |
| 1764 | if (IS_ERR(cdns_phy->phys[node].lnk_rst)) { | 2162 | if (IS_ERR(cdns_phy->phys[node].lnk_rst)) { |
| @@ -1776,27 +2174,57 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev) · 11 unmodified lines | |||
| 1776 | goto put_child; | 2174 | goto put_child; |
| 1777 | } | 2175 | } |
| 1778 | 2176 | ||
| 1779 | if (cdns_phy->phys[node].mlane != 0) { | 2177 | if (of_property_read_u32(child, "cdns,phy-type", &phy_type)) { |
| 1780 | dev_err(dev, | 2178 | dev_err(dev, "%s: No \"cdns,phy-type\"-property.\n", |
| 1781 | "%s: Driver supports only lane-0 as master lane.\n", | ||
| 1782 | child->full_name); | 2179 | child->full_name); |
| 1783 | ret = -EINVAL; | 2180 | ret = -EINVAL; |
| 1784 | goto put_child; | 2181 | goto put_child; |
| 1785 | } | 2182 | } |
| 1786 | 2183 | ||
| 1787 | if (of_property_read_u32(child, "cdns,phy-type", | 2184 | switch (phy_type) { |
| 1788 | &cdns_phy->phys[node].phy_type)) { | 2185 | case PHY_TYPE_PCIE: |
| 1789 | dev_err(dev, "%s: No \"cdns,phy-type\"-property.\n", | 2186 | cdns_phy->phys[node].phy_type = TYPE_PCIE; |
| 2187 | break; | ||
| 2188 | case PHY_TYPE_DP: | ||
| 2189 | cdns_phy->phys[node].phy_type = TYPE_DP; | ||
| 2190 | break; | ||
| 2191 | case PHY_TYPE_SGMII: | ||
| 2192 | cdns_phy->phys[node].phy_type = TYPE_SGMII; | ||
| 2193 | break; | ||
| 2194 | case PHY_TYPE_QSGMII: | ||
| 2195 | cdns_phy->phys[node].phy_type = TYPE_QSGMII; | ||
| 2196 | break; | ||
| 2197 | case PHY_TYPE_USB3: | ||
| 2198 | cdns_phy->phys[node].phy_type = TYPE_USB; | ||
| 2199 | break; | ||
| 2200 | default: | ||
| 2201 | dev_err(dev, "Unsupported protocol\n"); | ||
| 2202 | ret = -EINVAL; | ||
| 2203 | goto put_child; | ||
| 2204 | } | ||
| 2205 | |||
| 2206 | if (of_property_read_u32(child, "cdns,num-lanes", | ||
| 2207 | &cdns_phy->phys[node].num_lanes)) { | ||
| 2208 | dev_err(dev, "%s: No \"cdns,num-lanes\"-property.\n", | ||
| 1790 | child->full_name); | 2209 | child->full_name); |
| 1791 | ret = -EINVAL; | 2210 | ret = -EINVAL; |
| 1792 | goto put_child; | 2211 | goto put_child; |
| 1793 | } | 2212 | } |
| 1794 | 2213 | ||
| 1795 | cdns_phy->phys[node].num_lanes = DEFAULT_NUM_LANES; | 2214 | total_num_lanes += cdns_phy->phys[node].num_lanes; |
| 1796 | of_property_read_u32(child, "cdns,num-lanes", | 2215 | |
| 1797 | &cdns_phy->phys[node].num_lanes); | 2216 | /* Get SSC mode */ |
| 2217 | cdns_phy->phys[node].ssc_mode = NO_SSC; | ||
| 2218 | of_property_read_u32(child, "cdns,ssc-mode", | ||
| 2219 | &cdns_phy->phys[node].ssc_mode); | ||
| 2220 | |||
| 2221 | gphy = devm_phy_create(dev, child, &cdns_torrent_phy_ops); | ||
| 2222 | if (IS_ERR(gphy)) { | ||
| 2223 | ret = PTR_ERR(gphy); | ||
| 2224 | goto put_child; | ||
| 2225 | } | ||
| 1798 | 2226 | ||
| 1799 | if (cdns_phy->phys[node].phy_type == PHY_TYPE_DP) { | 2227 | if (cdns_phy->phys[node].phy_type == TYPE_DP) { |
| 1800 | switch (cdns_phy->phys[node].num_lanes) { | 2228 | switch (cdns_phy->phys[node].num_lanes) { |
| 1801 | case 1: | 2229 | case 1: |
| 1802 | case 2: | 2230 | case 2: |
| @@ -1833,30 +2261,34 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev) · 30 unmodified lines | |||
| 1833 | } | 2261 | } |
| 1834 | 2262 | ||
| 1835 | /* DPTX registers */ | 2263 | /* DPTX registers */ |
| 1836 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 2264 | cdns_phy->base = devm_platform_ioremap_resource(pdev, 1); |
| 1837 | cdns_phy->base = devm_ioremap_resource(&pdev->dev, | ||
| 1838 | regs); | ||
| 1839 | if (IS_ERR(cdns_phy->base)) { | 2265 | if (IS_ERR(cdns_phy->base)) { |
| 1840 | ret = PTR_ERR(cdns_phy->base); | 2266 | ret = PTR_ERR(cdns_phy->base); |
| 1841 | goto put_child; | 2267 | goto put_child; |
| 1842 | } | 2268 | } |
| 1843 | 2269 | ||
| 1844 | gphy = devm_phy_create(dev, child, | 2270 | if (!init_dp_regmap) { |
| 1845 | &cdns_torrent_phy_ops); | 2271 | ret = cdns_torrent_dp_regmap_init(cdns_phy); |
| 1846 | if (IS_ERR(gphy)) { | 2272 | if (ret) |
| 1847 | ret = PTR_ERR(gphy); | 2273 | goto put_child; |
| 1848 | goto put_child; | 2274 | |
| 2275 | ret = cdns_torrent_dp_regfield_init(cdns_phy); | ||
| 2276 | if (ret) | ||
| 2277 | goto put_child; | ||
| 2278 | |||
| 2279 | init_dp_regmap++; | ||
| 1849 | } | 2280 | } |
| 1850 | 2281 | ||
| 1851 | dev_info(dev, "%d lanes, max bit rate %d.%03d Gbps\n", | 2282 | dev_info(dev, "%d lanes, max bit rate %d.%03d Gbps\n", |
| 1852 | cdns_phy->phys[node].num_lanes, | 2283 | cdns_phy->phys[node].num_lanes, |
| 1853 | cdns_phy->max_bit_rate / 1000, | 2284 | cdns_phy->max_bit_rate / 1000, |
| 1854 | cdns_phy->max_bit_rate % 1000); | 2285 | cdns_phy->max_bit_rate % 1000); |
| 1855 | } else { | 2286 | |
| 1856 | dev_err(dev, "Driver supports only PHY_TYPE_DP\n"); | 2287 | gphy->attrs.bus_width = cdns_phy->phys[node].num_lanes; |
| 1857 | ret = -ENOTSUPP; | 2288 | gphy->attrs.max_link_rate = cdns_phy->max_bit_rate; |
| 1858 | goto put_child; | 2289 | gphy->attrs.mode = PHY_MODE_DP; |
| 1859 | } | 2290 | } |
| 2291 | |||
| 1860 | cdns_phy->phys[node].phy = gphy; | 2292 | cdns_phy->phys[node].phy = gphy; |
| 1861 | phy_set_drvdata(gphy, &cdns_phy->phys[node]); | 2293 | phy_set_drvdata(gphy, &cdns_phy->phys[node]); |
| 1862 | 2294 | ||
| @@ -1864,16 +2296,16 @@ static int cdns_torrent_phy_probe(struct platform_device *pdev) · 1 unmodified line | |||
| 1864 | } | 2296 | } |
| 1865 | cdns_phy->nsubnodes = node; | 2297 | cdns_phy->nsubnodes = node; |
| 1866 | 2298 | ||
| 1867 | ret = cdns_regmap_init_torrent_dp(cdns_phy, cdns_phy->sd_base, | 2299 | if (total_num_lanes > MAX_NUM_LANES) { |
| 1868 | cdns_phy->base, | 2300 | dev_err(dev, "Invalid lane configuration\n"); |
| 1869 | data->block_offset_shift, | ||
| 1870 | data->reg_offset_shift); | ||
| 1871 | if (ret) | ||
| 1872 | goto put_lnk_rst; | 2301 | goto put_lnk_rst; |
| 2302 | } | ||
| 1873 | 2303 | ||
| 1874 | ret = cdns_regfield_init(cdns_phy); | 2304 | if (cdns_phy->nsubnodes > 1) { |
| 1875 | if (ret) | 2305 | ret = cdns_torrent_phy_configure_multilink(cdns_phy); |
| 1876 | goto put_lnk_rst; | 2306 | if (ret) |
| 2307 | goto put_lnk_rst; | ||
| 2308 | } | ||
| 1877 | 2309 | ||
| 1878 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | 2310 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); |
| 1879 | if (IS_ERR(phy_provider)) { | 2311 | if (IS_ERR(phy_provider)) { |
| @@ -1889,6 +2321,8 @@ put_lnk_rst: · 9 unmodified lines | |||
| 1889 | for (i = 0; i < node; i++) | 2321 | for (i = 0; i < node; i++) |
| 1890 | reset_control_put(cdns_phy->phys[i].lnk_rst); | 2322 | reset_control_put(cdns_phy->phys[i].lnk_rst); |
| 1891 | of_node_put(child); | 2323 | of_node_put(child); |
| 2324 | reset_control_assert(cdns_phy->apb_rst); | ||
| 2325 | clk_disable_unprepare(cdns_phy->clk); | ||
| 1892 | return ret; | 2326 | return ret; |
| 1893 | } | 2327 | } |
| 1894 | 2328 | ||
| @@ -1898,22 +2332,1505 @@ static int cdns_torrent_phy_remove(struct platform_device *pdev) · 3 unmodified lines | |||
| 1898 | int i; | 2332 | int i; |
| 1899 | 2333 | ||
| 1900 | reset_control_assert(cdns_phy->phy_rst); | 2334 | reset_control_assert(cdns_phy->phy_rst); |
| 2335 | reset_control_assert(cdns_phy->apb_rst); | ||
| 1901 | for (i = 0; i < cdns_phy->nsubnodes; i++) { | 2336 | for (i = 0; i < cdns_phy->nsubnodes; i++) { |
| 1902 | reset_control_assert(cdns_phy->phys[i].lnk_rst); | 2337 | reset_control_assert(cdns_phy->phys[i].lnk_rst); |
| 1903 | reset_control_put(cdns_phy->phys[i].lnk_rst); | 2338 | reset_control_put(cdns_phy->phys[i].lnk_rst); |
| 1904 | } | 2339 | } |
| 1905 | 2340 | ||
| 2341 | clk_disable_unprepare(cdns_phy->clk); | ||
| 2342 | |||
| 1906 | return 0; | 2343 | return 0; |
| 1907 | } | 2344 | } |
| 1908 | 2345 | ||
| 2346 | /* USB and SGMII/QSGMII link configuration */ | ||
| 2347 | static struct cdns_reg_pairs usb_sgmii_link_cmn_regs[] = { | ||
| 2348 | {0x0002, PHY_PLL_CFG}, | ||
| 2349 | {0x8600, CMN_PDIAG_PLL0_CLK_SEL_M0}, | ||
| 2350 | {0x0601, CMN_PDIAG_PLL1_CLK_SEL_M0} | ||
| 2351 | }; | ||
| 2352 | |||
| 2353 | static struct cdns_reg_pairs usb_sgmii_xcvr_diag_ln_regs[] = { | ||
| 2354 | {0x0000, XCVR_DIAG_HSCLK_SEL}, | ||
| 2355 | {0x0001, XCVR_DIAG_HSCLK_DIV}, | ||
| 2356 | {0x0041, XCVR_DIAG_PLLDRC_CTRL} | ||
| 2357 | }; | ||
| 2358 | |||
| 2359 | static struct cdns_reg_pairs sgmii_usb_xcvr_diag_ln_regs[] = { | ||
| 2360 | {0x0011, XCVR_DIAG_HSCLK_SEL}, | ||
| 2361 | {0x0003, XCVR_DIAG_HSCLK_DIV}, | ||
| 2362 | {0x009B, XCVR_DIAG_PLLDRC_CTRL} | ||
| 2363 | }; | ||
| 2364 | |||
| 2365 | static struct cdns_torrent_vals usb_sgmii_link_cmn_vals = { | ||
| 2366 | .reg_pairs = usb_sgmii_link_cmn_regs, | ||
| 2367 | .num_regs = ARRAY_SIZE(usb_sgmii_link_cmn_regs), | ||
| 2368 | }; | ||
| 2369 | |||
| 2370 | static struct cdns_torrent_vals usb_sgmii_xcvr_diag_ln_vals = { | ||
| 2371 | .reg_pairs = usb_sgmii_xcvr_diag_ln_regs, | ||
| 2372 | .num_regs = ARRAY_SIZE(usb_sgmii_xcvr_diag_ln_regs), | ||
| 2373 | }; | ||
| 2374 | |||
| 2375 | static struct cdns_torrent_vals sgmii_usb_xcvr_diag_ln_vals = { | ||
| 2376 | .reg_pairs = sgmii_usb_xcvr_diag_ln_regs, | ||
| 2377 | .num_regs = ARRAY_SIZE(sgmii_usb_xcvr_diag_ln_regs), | ||
| 2378 | }; | ||
| 2379 | |||
| 2380 | /* PCIe and USB Unique SSC link configuration */ | ||
| 2381 | static struct cdns_reg_pairs pcie_usb_link_cmn_regs[] = { | ||
| 2382 | {0x0003, PHY_PLL_CFG}, | ||
| 2383 | {0x0601, CMN_PDIAG_PLL0_CLK_SEL_M0}, | ||
| 2384 | {0x0400, CMN_PDIAG_PLL0_CLK_SEL_M1}, | ||
| 2385 | {0x8600, CMN_PDIAG_PLL1_CLK_SEL_M0} | ||
| 2386 | }; | ||
| 2387 | |||
| 2388 | static struct cdns_reg_pairs pcie_usb_xcvr_diag_ln_regs[] = { | ||
| 2389 | {0x0000, XCVR_DIAG_HSCLK_SEL}, | ||
| 2390 | {0x0001, XCVR_DIAG_HSCLK_DIV}, | ||
| 2391 | {0x0012, XCVR_DIAG_PLLDRC_CTRL} | ||
| 2392 | }; | ||
| 2393 | |||
| 2394 | static struct cdns_reg_pairs usb_pcie_xcvr_diag_ln_regs[] = { | ||
| 2395 | {0x0011, XCVR_DIAG_HSCLK_SEL}, | ||
| 2396 | {0x0001, XCVR_DIAG_HSCLK_DIV}, | ||
| 2397 | {0x00C9, XCVR_DIAG_PLLDRC_CTRL} | ||
| 2398 | }; | ||
| 2399 | |||
| 2400 | static struct cdns_torrent_vals pcie_usb_link_cmn_vals = { | ||
| 2401 | .reg_pairs = pcie_usb_link_cmn_regs, | ||
| 2402 | .num_regs = ARRAY_SIZE(pcie_usb_link_cmn_regs), | ||
| 2403 | }; | ||
| 2404 | |||
| 2405 | static struct cdns_torrent_vals pcie_usb_xcvr_diag_ln_vals = { | ||
| 2406 | .reg_pairs = pcie_usb_xcvr_diag_ln_regs, | ||
| 2407 | .num_regs = ARRAY_SIZE(pcie_usb_xcvr_diag_ln_regs), | ||
| 2408 | }; | ||
| 2409 | |||
| 2410 | static struct cdns_torrent_vals usb_pcie_xcvr_diag_ln_vals = { | ||
| 2411 | .reg_pairs = usb_pcie_xcvr_diag_ln_regs, | ||
| 2412 | .num_regs = ARRAY_SIZE(usb_pcie_xcvr_diag_ln_regs), | ||
| 2413 | }; | ||
| 2414 | |||
| 2415 | /* USB 100 MHz Ref clk, internal SSC */ | ||
| 2416 | static struct cdns_reg_pairs usb_100_int_ssc_cmn_regs[] = { | ||
| 2417 | {0x0004, CMN_PLL0_DSM_DIAG_M0}, | ||
| 2418 | {0x0004, CMN_PLL0_DSM_DIAG_M1}, | ||
| 2419 | {0x0004, CMN_PLL1_DSM_DIAG_M0}, | ||
| 2420 | {0x0509, CMN_PDIAG_PLL0_CP_PADJ_M0}, | ||
| 2421 | {0x0509, CMN_PDIAG_PLL0_CP_PADJ_M1}, | ||
| 2422 | {0x0509, CMN_PDIAG_PLL1_CP_PADJ_M0}, | ||
| 2423 | {0x0F00, CMN_PDIAG_PLL0_CP_IADJ_M0}, | ||
| 2424 | {0x0F00, CMN_PDIAG_PLL0_CP_IADJ_M1}, | ||
| 2425 | {0x0F00, CMN_PDIAG_PLL1_CP_IADJ_M0}, | ||
| 2426 | {0x0F08, CMN_PDIAG_PLL0_FILT_PADJ_M0}, | ||
| 2427 | {0x0F08, CMN_PDIAG_PLL0_FILT_PADJ_M1}, | ||
| 2428 | {0x0F08, CMN_PDIAG_PLL1_FILT_PADJ_M0}, | ||
| 2429 | {0x0064, CMN_PLL0_INTDIV_M0}, | ||
| 2430 | {0x0050, CMN_PLL0_INTDIV_M1}, | ||
| 2431 | {0x0064, CMN_PLL1_INTDIV_M0}, | ||
| 2432 | {0x0002, CMN_PLL0_FRACDIVH_M0}, | ||
| 2433 | {0x0002, CMN_PLL0_FRACDIVH_M1}, | ||
| 2434 | {0x0002, CMN_PLL1_FRACDIVH_M0}, | ||
| 2435 | {0x0044, CMN_PLL0_HIGH_THR_M0}, | ||
| 2436 | {0x0036, CMN_PLL0_HIGH_THR_M1}, | ||
| 2437 | {0x0044, CMN_PLL1_HIGH_THR_M0}, | ||
| 2438 | {0x0002, CMN_PDIAG_PLL0_CTRL_M0}, | ||
| 2439 | {0x0002, CMN_PDIAG_PLL0_CTRL_M1}, | ||
| 2440 | {0x0002, CMN_PDIAG_PLL1_CTRL_M0}, | ||
| 2441 | {0x0001, CMN_PLL0_SS_CTRL1_M0}, | ||
| 2442 | {0x0001, CMN_PLL0_SS_CTRL1_M1}, | ||
| 2443 | {0x0001, CMN_PLL1_SS_CTRL1_M0}, | ||
| 2444 | {0x011B, CMN_PLL0_SS_CTRL2_M0}, | ||
| 2445 | {0x011B, CMN_PLL0_SS_CTRL2_M1}, | ||
| 2446 | {0x011B, CMN_PLL1_SS_CTRL2_M0}, | ||
| 2447 | {0x006E, CMN_PLL0_SS_CTRL3_M0}, | ||
| 2448 | {0x0058, CMN_PLL0_SS_CTRL3_M1}, | ||
| 2449 | {0x006E, CMN_PLL1_SS_CTRL3_M0}, | ||
| 2450 | {0x000E, CMN_PLL0_SS_CTRL4_M0}, | ||
| 2451 | {0x0012, CMN_PLL0_SS_CTRL4_M1}, | ||
| 2452 | {0x000E, CMN_PLL1_SS_CTRL4_M0}, | ||
| 2453 | {0x0C5E, CMN_PLL0_VCOCAL_REFTIM_START}, | ||
| 2454 | {0x0C5E, CMN_PLL1_VCOCAL_REFTIM_START}, | ||
| 2455 | {0x0C56, CMN_PLL0_VCOCAL_PLLCNT_START}, | ||
| 2456 | {0x0C56, CMN_PLL1_VCOCAL_PLLCNT_START}, | ||
| 2457 | {0x0003, CMN_PLL0_VCOCAL_TCTRL}, | ||
| 2458 | {0x0003, CMN_PLL1_VCOCAL_TCTRL}, | ||
| 2459 | {0x00C7, CMN_PLL0_LOCK_REFCNT_START}, | ||
| 2460 | {0x00C7, CMN_PLL1_LOCK_REFCNT_START}, | ||
| 2461 | {0x00C7, CMN_PLL0_LOCK_PLLCNT_START}, | ||
| 2462 | {0x00C7, CMN_PLL1_LOCK_PLLCNT_START}, | ||
| 2463 | {0x0005, CMN_PLL0_LOCK_PLLCNT_THR}, | ||
| 2464 | {0x0005, CMN_PLL1_LOCK_PLLCNT_THR}, | ||
| 2465 | {0x8200, CMN_CDIAG_CDB_PWRI_OVRD}, | ||
| 2466 | {0x8200, CMN_CDIAG_XCVRC_PWRI_OVRD} | ||
| 2467 | }; | ||
| 2468 | |||
| 2469 | static struct cdns_torrent_vals usb_100_int_ssc_cmn_vals = { | ||
| 2470 | .reg_pairs = usb_100_int_ssc_cmn_regs, | ||
| 2471 | .num_regs = ARRAY_SIZE(usb_100_int_ssc_cmn_regs), | ||
| 2472 | }; | ||
| 2473 | |||
| 2474 | /* Single USB link configuration */ | ||
| 2475 | static struct cdns_reg_pairs sl_usb_link_cmn_regs[] = { | ||
| 2476 | {0x0000, PHY_PLL_CFG}, | ||
| 2477 | {0x8600, CMN_PDIAG_PLL0_CLK_SEL_M0} | ||
| 2478 | }; | ||
| 2479 | |||
| 2480 | static struct cdns_reg_pairs sl_usb_xcvr_diag_ln_regs[] = { | ||
| 2481 | {0x0000, XCVR_DIAG_HSCLK_SEL}, | ||
| 2482 | {0x0001, XCVR_DIAG_HSCLK_DIV}, | ||
| 2483 | {0x0041, XCVR_DIAG_PLLDRC_CTRL} | ||
| 2484 | }; | ||
| 2485 | |||
| 2486 | static struct cdns_torrent_vals sl_usb_link_cmn_vals = { | ||
| 2487 | .reg_pairs = sl_usb_link_cmn_regs, | ||
| 2488 | .num_regs = ARRAY_SIZE(sl_usb_link_cmn_regs), | ||
| 2489 | }; | ||
| 2490 | |||
| 2491 | static struct cdns_torrent_vals sl_usb_xcvr_diag_ln_vals = { | ||
| 2492 | .reg_pairs = sl_usb_xcvr_diag_ln_regs, | ||
| 2493 | .num_regs = ARRAY_SIZE(sl_usb_xcvr_diag_ln_regs), | ||
| 2494 | }; | ||
| 2495 | |||
| 2496 | /* USB PHY PCS common configuration */ | ||
| 2497 | static struct cdns_reg_pairs usb_phy_pcs_cmn_regs[] = { | ||
| 2498 | {0x0A0A, PHY_PIPE_USB3_GEN2_PRE_CFG0}, | ||
| 2499 | {0x1000, PHY_PIPE_USB3_GEN2_POST_CFG0}, | ||
| 2500 | {0x0010, PHY_PIPE_USB3_GEN2_POST_CFG1} | ||
| 2501 | }; | ||
| 2502 | |||
| 2503 | static struct cdns_torrent_vals usb_phy_pcs_cmn_vals = { | ||
| 2504 | .reg_pairs = usb_phy_pcs_cmn_regs, | ||
| 2505 | .num_regs = ARRAY_SIZE(usb_phy_pcs_cmn_regs), | ||
| 2506 | }; | ||
| 2507 | |||
| 2508 | /* USB 100 MHz Ref clk, no SSC */ | ||
| 2509 | static struct cdns_reg_pairs usb_100_no_ssc_cmn_regs[] = { | ||
| 2510 | {0x0003, CMN_PLL0_VCOCAL_TCTRL}, | ||
| 2511 | {0x0003, CMN_PLL1_VCOCAL_TCTRL}, | ||
| 2512 | {0x8200, CMN_CDIAG_CDB_PWRI_OVRD}, | ||
| 2513 | {0x8200, CMN_CDIAG_XCVRC_PWRI_OVRD} | ||
| 2514 | }; | ||
| 2515 | |||
| 2516 | static struct cdns_reg_pairs usb_100_no_ssc_tx_ln_regs[] = { | ||
| 2517 | {0x02FF, TX_PSC_A0}, | ||
| 2518 | {0x06AF, TX_PSC_A1}, | ||
| 2519 | {0x06AE, TX_PSC_A2}, | ||
| 2520 | {0x06AE, TX_PSC_A3}, | ||
| 2521 | {0x2A82, TX_TXCC_CTRL}, | ||
| 2522 | {0x0014, TX_TXCC_CPOST_MULT_01}, | ||
| 2523 | {0x0003, XCVR_DIAG_PSC_OVRD} | ||
| 2524 | }; | ||
| 2525 | |||
| 2526 | static struct cdns_reg_pairs usb_100_no_ssc_rx_ln_regs[] = { | ||
| 2527 | {0x0D1D, RX_PSC_A0}, | ||
| 2528 | {0x0D1D, RX_PSC_A1}, | ||
| 2529 | {0x0D00, RX_PSC_A2}, | ||
| 2530 | {0x0500, RX_PSC_A3}, | ||
| 2531 | {0x0013, RX_SIGDET_HL_FILT_TMR}, | ||
| 2532 | {0x0000, RX_REE_GCSM1_CTRL}, | ||
| 2533 | {0x0C02, RX_REE_ATTEN_THR}, | ||
| 2534 | {0x0330, RX_REE_SMGM_CTRL1}, | ||
| 2535 | {0x0300, RX_REE_SMGM_CTRL2}, | ||
| 2536 | {0x0019, RX_REE_TAP1_CLIP}, | ||
| 2537 | {0x0019, RX_REE_TAP2TON_CLIP}, | ||
| 2538 | {0x1004, RX_DIAG_SIGDET_TUNE}, | ||
| 2539 | {0x00F9, RX_DIAG_NQST_CTRL}, | ||
| 2540 | {0x0C01, RX_DIAG_DFE_AMP_TUNE_2}, | ||
| 2541 | {0x0002, RX_DIAG_DFE_AMP_TUNE_3}, | ||
| 2542 | {0x0000, RX_DIAG_PI_CAP}, | ||
| 2543 | {0x0031, RX_DIAG_PI_RATE}, | ||
| 2544 | {0x0001, RX_DIAG_ACYA}, | ||
| 2545 | {0x018C, RX_CDRLF_CNFG}, | ||
| 2546 | {0x0003, RX_CDRLF_CNFG3} | ||
| 2547 | }; | ||
| 2548 | |||
| 2549 | static struct cdns_torrent_vals usb_100_no_ssc_cmn_vals = { | ||
| 2550 | .reg_pairs = usb_100_no_ssc_cmn_regs, | ||
| 2551 | .num_regs = ARRAY_SIZE(usb_100_no_ssc_cmn_regs), | ||
| 2552 | }; | ||
| 2553 | |||
| 2554 | static struct cdns_torrent_vals usb_100_no_ssc_tx_ln_vals = { | ||
| 2555 | .reg_pairs = usb_100_no_ssc_tx_ln_regs, | ||
| 2556 | .num_regs = ARRAY_SIZE(usb_100_no_ssc_tx_ln_regs), | ||
| 2557 | }; | ||
| 2558 | |||
| 2559 | static struct cdns_torrent_vals usb_100_no_ssc_rx_ln_vals = { | ||
| 2560 | .reg_pairs = usb_100_no_ssc_rx_ln_regs, | ||
| 2561 | .num_regs = ARRAY_SIZE(usb_100_no_ssc_rx_ln_regs), | ||
| 2562 | }; | ||
| 2563 | |||
| 2564 | /* Single link USB, 100 MHz Ref clk, internal SSC */ | ||
| 2565 | static struct cdns_reg_pairs sl_usb_100_int_ssc_cmn_regs[] = { | ||
| 2566 | {0x0004, CMN_PLL0_DSM_DIAG_M0}, | ||
| 2567 | {0x0004, CMN_PLL1_DSM_DIAG_M0}, | ||
| 2568 | {0x0509, CMN_PDIAG_PLL0_CP_PADJ_M0}, | ||
| 2569 | {0x0509, CMN_PDIAG_PLL1_CP_PADJ_M0}, | ||
| 2570 | {0x0F00, CMN_PDIAG_PLL0_CP_IADJ_M0}, | ||
| 2571 | {0x0F00, CMN_PDIAG_PLL1_CP_IADJ_M0}, | ||
| 2572 | {0x0F08, CMN_PDIAG_PLL0_FILT_PADJ_M0}, | ||
| 2573 | {0x0F08, CMN_PDIAG_PLL1_FILT_PADJ_M0}, | ||
| 2574 | {0x0064, CMN_PLL0_INTDIV_M0}, | ||
| 2575 | {0x0064, CMN_PLL1_INTDIV_M0}, | ||
| 2576 | {0x0002, CMN_PLL0_FRACDIVH_M0}, | ||
| 2577 | {0x0002, CMN_PLL1_FRACDIVH_M0}, | ||
| 2578 | {0x0044, CMN_PLL0_HIGH_THR_M0}, | ||
| 2579 | {0x0044, CMN_PLL1_HIGH_THR_M0}, | ||
| 2580 | {0x0002, CMN_PDIAG_PLL0_CTRL_M0}, | ||
| 2581 | {0x0002, CMN_PDIAG_PLL1_CTRL_M0}, | ||
| 2582 | {0x0001, CMN_PLL0_SS_CTRL1_M0}, | ||
| 2583 | {0x0001, CMN_PLL1_SS_CTRL1_M0}, | ||
| 2584 | {0x011B, CMN_PLL0_SS_CTRL2_M0}, | ||
| 2585 | {0x011B, CMN_PLL1_SS_CTRL2_M0}, | ||
| 2586 | {0x006E, CMN_PLL0_SS_CTRL3_M0}, | ||
| 2587 | {0x006E, CMN_PLL1_SS_CTRL3_M0}, | ||
| 2588 | {0x000E, CMN_PLL0_SS_CTRL4_M0}, | ||
| 2589 | {0x000E, CMN_PLL1_SS_CTRL4_M0}, | ||
| 2590 | {0x0C5E, CMN_PLL0_VCOCAL_REFTIM_START}, | ||
| 2591 | {0x0C5E, CMN_PLL1_VCOCAL_REFTIM_START}, | ||
| 2592 | {0x0C56, CMN_PLL0_VCOCAL_PLLCNT_START}, | ||
| 2593 | {0x0C56, CMN_PLL1_VCOCAL_PLLCNT_START}, | ||
| 2594 | {0x0003, CMN_PLL0_VCOCAL_TCTRL}, | ||
| 2595 | {0x0003, CMN_PLL1_VCOCAL_TCTRL}, | ||
| 2596 | {0x00C7, CMN_PLL0_LOCK_REFCNT_START}, | ||
| 2597 | {0x00C7, CMN_PLL1_LOCK_REFCNT_START}, | ||
| 2598 | {0x00C7, CMN_PLL0_LOCK_PLLCNT_START}, | ||
| 2599 | {0x00C7, CMN_PLL1_LOCK_PLLCNT_START}, | ||
| 2600 | {0x0005, CMN_PLL0_LOCK_PLLCNT_THR}, | ||
| 2601 | {0x0005, CMN_PLL1_LOCK_PLLCNT_THR}, | ||
| 2602 | {0x8200, CMN_CDIAG_CDB_PWRI_OVRD}, | ||
| 2603 | {0x8200, CMN_CDIAG_XCVRC_PWRI_OVRD} | ||
| 2604 | }; | ||
| 2605 | |||
| 2606 | static struct cdns_torrent_vals sl_usb_100_int_ssc_cmn_vals = { | ||
| 2607 | .reg_pairs = sl_usb_100_int_ssc_cmn_regs, | ||
| 2608 | .num_regs = ARRAY_SIZE(sl_usb_100_int_ssc_cmn_regs), | ||
| 2609 | }; | ||
| 2610 | |||
| 2611 | /* PCIe and SGMII/QSGMII Unique SSC link configuration */ | ||
| 2612 | static struct cdns_reg_pairs pcie_sgmii_link_cmn_regs[] = { | ||
| 2613 | {0x0003, PHY_PLL_CFG}, | ||
| 2614 | {0x0601, CMN_PDIAG_PLL0_CLK_SEL_M0}, | ||
| 2615 | {0x0400, CMN_PDIAG_PLL0_CLK_SEL_M1}, | ||
| 2616 | {0x0601, CMN_PDIAG_PLL1_CLK_SEL_M0} | ||
| 2617 | }; | ||
| 2618 | |||
| 2619 | static struct cdns_reg_pairs pcie_sgmii_xcvr_diag_ln_regs[] = { | ||
| 2620 | {0x0000, XCVR_DIAG_HSCLK_SEL}, | ||
| 2621 | {0x0001, XCVR_DIAG_HSCLK_DIV}, | ||
| 2622 | {0x0012, XCVR_DIAG_PLLDRC_CTRL} | ||
| 2623 | }; | ||
| 2624 | |||
| 2625 | static struct cdns_reg_pairs sgmii_pcie_xcvr_diag_ln_regs[] = { | ||
| 2626 | {0x0011, XCVR_DIAG_HSCLK_SEL}, | ||
| 2627 | {0x0003, XCVR_DIAG_HSCLK_DIV}, | ||
| 2628 | {0x009B, XCVR_DIAG_PLLDRC_CTRL} | ||
| 2629 | }; | ||
| 2630 | |||
| 2631 | static struct cdns_torrent_vals pcie_sgmii_link_cmn_vals = { | ||
| 2632 | .reg_pairs = pcie_sgmii_link_cmn_regs, | ||
| 2633 | .num_regs = ARRAY_SIZE(pcie_sgmii_link_cmn_regs), | ||
| 2634 | }; | ||
| 2635 | |||
| 2636 | static struct cdns_torrent_vals pcie_sgmii_xcvr_diag_ln_vals = { | ||
| 2637 | .reg_pairs = pcie_sgmii_xcvr_diag_ln_regs, | ||
| 2638 | .num_regs = ARRAY_SIZE(pcie_sgmii_xcvr_diag_ln_regs), | ||
| 2639 | }; | ||
| 2640 | |||
| 2641 | static struct cdns_torrent_vals sgmii_pcie_xcvr_diag_ln_vals = { | ||
| 2642 | .reg_pairs = sgmii_pcie_xcvr_diag_ln_regs, | ||
| 2643 | .num_regs = ARRAY_SIZE(sgmii_pcie_xcvr_diag_ln_regs), | ||
| 2644 | }; | ||
| 2645 | |||
| 2646 | /* SGMII 100 MHz Ref clk, no SSC */ | ||
| 2647 | static struct cdns_reg_pairs sgmii_100_no_ssc_cmn_regs[] = { | ||
| 2648 | {0x0003, CMN_PLL0_VCOCAL_TCTRL}, | ||
| 2649 | {0x0003, CMN_PLL1_VCOCAL_TCTRL}, | ||
| 2650 | {0x3700, CMN_DIAG_BIAS_OVRD1}, | ||
| 2651 | {0x0008, CMN_TXPUCAL_TUNE}, | ||
| 2652 | {0x0008, CMN_TXPDCAL_TUNE} | ||
| 2653 | }; | ||
| 2654 | |||
| 2655 | static struct cdns_reg_pairs sgmii_100_no_ssc_tx_ln_regs[] = { | ||
| 2656 | {0x00F3, TX_PSC_A0}, | ||
| 2657 | {0x04A2, TX_PSC_A2}, | ||
| 2658 | {0x04A2, TX_PSC_A3}, | ||
| 2659 | {0x0000, TX_TXCC_CPOST_MULT_00}, | ||
| 2660 | {0x00B3, DRV_DIAG_TX_DRV} | ||
| 2661 | }; | ||
| 2662 | |||
| 2663 | static struct cdns_reg_pairs sgmii_100_no_ssc_rx_ln_regs[] = { | ||
| 2664 | {0x091D, RX_PSC_A0}, | ||
| 2665 | {0x0900, RX_PSC_A2}, | ||
| 2666 | {0x0100, RX_PSC_A3}, | ||
| 2667 | {0x03C7, RX_REE_GCSM1_EQENM_PH1}, | ||
| 2668 | {0x01C7, RX_REE_GCSM1_EQENM_PH2}, | ||
| 2669 | {0x0000, RX_DIAG_DFE_CTRL}, | ||
| 2670 | {0x0019, RX_REE_TAP1_CLIP}, | ||
| 2671 | {0x0019, RX_REE_TAP2TON_CLIP}, | ||
| 2672 | {0x0098, RX_DIAG_NQST_CTRL}, | ||
| 2673 | {0x0C01, RX_DIAG_DFE_AMP_TUNE_2}, | ||
| 2674 | {0x0000, RX_DIAG_DFE_AMP_TUNE_3}, | ||
| 2675 | {0x0000, RX_DIAG_PI_CAP}, | ||
| 2676 | {0x0010, RX_DIAG_PI_RATE}, | ||
| 2677 | {0x0001, RX_DIAG_ACYA}, | ||
| 2678 | {0x018C, RX_CDRLF_CNFG}, | ||
| 2679 | }; | ||
| 2680 | |||
| 2681 | static struct cdns_torrent_vals sgmii_100_no_ssc_cmn_vals = { | ||
| 2682 | .reg_pairs = sgmii_100_no_ssc_cmn_regs, | ||
| 2683 | .num_regs = ARRAY_SIZE(sgmii_100_no_ssc_cmn_regs), | ||
| 2684 | }; | ||
| 2685 | |||
| 2686 | static struct cdns_torrent_vals sgmii_100_no_ssc_tx_ln_vals = { | ||
| 2687 | .reg_pairs = sgmii_100_no_ssc_tx_ln_regs, | ||
| 2688 | .num_regs = ARRAY_SIZE(sgmii_100_no_ssc_tx_ln_regs), | ||
| 2689 | }; | ||
| 2690 | |||
| 2691 | static struct cdns_torrent_vals sgmii_100_no_ssc_rx_ln_vals = { | ||
| 2692 | .reg_pairs = sgmii_100_no_ssc_rx_ln_regs, | ||
| 2693 | .num_regs = ARRAY_SIZE(sgmii_100_no_ssc_rx_ln_regs), | ||
| 2694 | }; | ||
| 2695 | |||
| 2696 | /* SGMII 100 MHz Ref clk, internal SSC */ | ||
| 2697 | static struct cdns_reg_pairs sgmii_100_int_ssc_cmn_regs[] = { | ||
| 2698 | {0x0004, CMN_PLL0_DSM_DIAG_M0}, | ||
| 2699 | {0x0004, CMN_PLL0_DSM_DIAG_M1}, | ||
| 2700 | {0x0004, CMN_PLL1_DSM_DIAG_M0}, | ||
| 2701 | {0x0509, CMN_PDIAG_PLL0_CP_PADJ_M0}, | ||
| 2702 | {0x0509, CMN_PDIAG_PLL0_CP_PADJ_M1}, | ||
| 2703 | {0x0509, CMN_PDIAG_PLL1_CP_PADJ_M0}, | ||
| 2704 | {0x0F00, CMN_PDIAG_PLL0_CP_IADJ_M0}, | ||
| 2705 | {0x0F00, CMN_PDIAG_PLL0_CP_IADJ_M1}, | ||
| 2706 | {0x0F00, CMN_PDIAG_PLL1_CP_IADJ_M0}, | ||
| 2707 | {0x0F08, CMN_PDIAG_PLL0_FILT_PADJ_M0}, | ||
| 2708 | {0x0F08, CMN_PDIAG_PLL0_FILT_PADJ_M1}, | ||
| 2709 | {0x0F08, CMN_PDIAG_PLL1_FILT_PADJ_M0}, | ||
| 2710 | {0x0064, CMN_PLL0_INTDIV_M0}, | ||
| 2711 | {0x0050, CMN_PLL0_INTDIV_M1}, | ||
| 2712 | {0x0064, CMN_PLL1_INTDIV_M0}, | ||
| 2713 | {0x0002, CMN_PLL0_FRACDIVH_M0}, | ||
| 2714 | {0x0002, CMN_PLL0_FRACDIVH_M1}, | ||
| 2715 | {0x0002, CMN_PLL1_FRACDIVH_M0}, | ||
| 2716 | {0x0044, CMN_PLL0_HIGH_THR_M0}, | ||
| 2717 | {0x0036, CMN_PLL0_HIGH_THR_M1}, | ||
| 2718 | {0x0044, CMN_PLL1_HIGH_THR_M0}, | ||
| 2719 | {0x0002, CMN_PDIAG_PLL0_CTRL_M0}, | ||
| 2720 | {0x0002, CMN_PDIAG_PLL0_CTRL_M1}, | ||
| 2721 | {0x0002, CMN_PDIAG_PLL1_CTRL_M0}, | ||
| 2722 | {0x0001, CMN_PLL0_SS_CTRL1_M0}, | ||
| 2723 | {0x0001, CMN_PLL0_SS_CTRL1_M1}, | ||
| 2724 | {0x0001, CMN_PLL1_SS_CTRL1_M0}, | ||
| 2725 | {0x011B, CMN_PLL0_SS_CTRL2_M0}, | ||
| 2726 | {0x011B, CMN_PLL0_SS_CTRL2_M1}, | ||
| 2727 | {0x011B, CMN_PLL1_SS_CTRL2_M0}, | ||
| 2728 | {0x006E, CMN_PLL0_SS_CTRL3_M0}, | ||
| 2729 | {0x0058, CMN_PLL0_SS_CTRL3_M1}, | ||
| 2730 | {0x006E, CMN_PLL1_SS_CTRL3_M0}, | ||
| 2731 | {0x000E, CMN_PLL0_SS_CTRL4_M0}, | ||
| 2732 | {0x0012, CMN_PLL0_SS_CTRL4_M1}, | ||
| 2733 | {0x000E, CMN_PLL1_SS_CTRL4_M0}, | ||
| 2734 | {0x0C5E, CMN_PLL0_VCOCAL_REFTIM_START}, | ||
| 2735 | {0x0C5E, CMN_PLL1_VCOCAL_REFTIM_START}, | ||
| 2736 | {0x0C56, CMN_PLL0_VCOCAL_PLLCNT_START}, | ||
| 2737 | {0x0C56, CMN_PLL1_VCOCAL_PLLCNT_START}, | ||
| 2738 | {0x0003, CMN_PLL0_VCOCAL_TCTRL}, | ||
| 2739 | {0x0003, CMN_PLL1_VCOCAL_TCTRL}, | ||
| 2740 | {0x00C7, CMN_PLL0_LOCK_REFCNT_START}, | ||
| 2741 | {0x00C7, CMN_PLL1_LOCK_REFCNT_START}, | ||
| 2742 | {0x00C7, CMN_PLL0_LOCK_PLLCNT_START}, | ||
| 2743 | {0x00C7, CMN_PLL1_LOCK_PLLCNT_START}, | ||
| 2744 | {0x0005, CMN_PLL0_LOCK_PLLCNT_THR}, | ||
| 2745 | {0x0005, CMN_PLL1_LOCK_PLLCNT_THR}, | ||
| 2746 | {0x3700, CMN_DIAG_BIAS_OVRD1}, | ||
| 2747 | {0x0008, CMN_TXPUCAL_TUNE}, | ||
| 2748 | {0x0008, CMN_TXPDCAL_TUNE} | ||
| 2749 | }; | ||
| 2750 | |||
| 2751 | static struct cdns_torrent_vals sgmii_100_int_ssc_cmn_vals = { | ||
| 2752 | .reg_pairs = sgmii_100_int_ssc_cmn_regs, | ||
| 2753 | .num_regs = ARRAY_SIZE(sgmii_100_int_ssc_cmn_regs), | ||
| 2754 | }; | ||
| 2755 | |||
| 2756 | /* QSGMII 100 MHz Ref clk, no SSC */ | ||
| 2757 | static struct cdns_reg_pairs qsgmii_100_no_ssc_cmn_regs[] = { | ||
| 2758 | {0x0003, CMN_PLL0_VCOCAL_TCTRL}, | ||
| 2759 | {0x0003, CMN_PLL1_VCOCAL_TCTRL} | ||
| 2760 | }; | ||
| 2761 | |||
| 2762 | static struct cdns_reg_pairs qsgmii_100_no_ssc_tx_ln_regs[] = { | ||
| 2763 | {0x00F3, TX_PSC_A0}, | ||
| 2764 | {0x04A2, TX_PSC_A2}, | ||
| 2765 | {0x04A2, TX_PSC_A3}, | ||
| 2766 | {0x0000, TX_TXCC_CPOST_MULT_00}, | ||
| 2767 | {0x0003, DRV_DIAG_TX_DRV} | ||
| 2768 | }; | ||
| 2769 | |||
| 2770 | static struct cdns_reg_pairs qsgmii_100_no_ssc_rx_ln_regs[] = { | ||
| 2771 | {0x091D, RX_PSC_A0}, | ||
| 2772 | {0x0900, RX_PSC_A2}, | ||
| 2773 | {0x0100, RX_PSC_A3}, | ||
| 2774 | {0x03C7, RX_REE_GCSM1_EQENM_PH1}, | ||
| 2775 | {0x01C7, RX_REE_GCSM1_EQENM_PH2}, | ||
| 2776 | {0x0000, RX_DIAG_DFE_CTRL}, | ||
| 2777 | {0x0019, RX_REE_TAP1_CLIP}, | ||
| 2778 | {0x0019, RX_REE_TAP2TON_CLIP}, | ||
| 2779 | {0x0098, RX_DIAG_NQST_CTRL}, | ||
| 2780 | {0x0C01, RX_DIAG_DFE_AMP_TUNE_2}, | ||
| 2781 | {0x0000, RX_DIAG_DFE_AMP_TUNE_3}, | ||
| 2782 | {0x0000, RX_DIAG_PI_CAP}, | ||
| 2783 | {0x0010, RX_DIAG_PI_RATE}, | ||
| 2784 | {0x0001, RX_DIAG_ACYA}, | ||
| 2785 | {0x018C, RX_CDRLF_CNFG}, | ||
| 2786 | }; | ||
| 2787 | |||
| 2788 | static struct cdns_torrent_vals qsgmii_100_no_ssc_cmn_vals = { | ||
| 2789 | .reg_pairs = qsgmii_100_no_ssc_cmn_regs, | ||
| 2790 | .num_regs = ARRAY_SIZE(qsgmii_100_no_ssc_cmn_regs), | ||
| 2791 | }; | ||
| 2792 | |||
| 2793 | static struct cdns_torrent_vals qsgmii_100_no_ssc_tx_ln_vals = { | ||
| 2794 | .reg_pairs = qsgmii_100_no_ssc_tx_ln_regs, | ||
| 2795 | .num_regs = ARRAY_SIZE(qsgmii_100_no_ssc_tx_ln_regs), | ||
| 2796 | }; | ||
| 2797 | |||
| 2798 | static struct cdns_torrent_vals qsgmii_100_no_ssc_rx_ln_vals = { | ||
| 2799 | .reg_pairs = qsgmii_100_no_ssc_rx_ln_regs, | ||
| 2800 | .num_regs = ARRAY_SIZE(qsgmii_100_no_ssc_rx_ln_regs), | ||
| 2801 | }; | ||
| 2802 | |||
| 2803 | /* QSGMII 100 MHz Ref clk, internal SSC */ | ||
| 2804 | static struct cdns_reg_pairs qsgmii_100_int_ssc_cmn_regs[] = { | ||
| 2805 | {0x0004, CMN_PLL0_DSM_DIAG_M0}, | ||
| 2806 | {0x0004, CMN_PLL0_DSM_DIAG_M1}, | ||
| 2807 | {0x0004, CMN_PLL1_DSM_DIAG_M0}, | ||
| 2808 | {0x0509, CMN_PDIAG_PLL0_CP_PADJ_M0}, | ||
| 2809 | {0x0509, CMN_PDIAG_PLL0_CP_PADJ_M1}, | ||
| 2810 | {0x0509, CMN_PDIAG_PLL1_CP_PADJ_M0}, | ||
| 2811 | {0x0F00, CMN_PDIAG_PLL0_CP_IADJ_M0}, | ||
| 2812 | {0x0F00, CMN_PDIAG_PLL0_CP_IADJ_M1}, | ||
| 2813 | {0x0F00, CMN_PDIAG_PLL1_CP_IADJ_M0}, | ||
| 2814 | {0x0F08, CMN_PDIAG_PLL0_FILT_PADJ_M0}, | ||
| 2815 | {0x0F08, CMN_PDIAG_PLL0_FILT_PADJ_M1}, | ||
| 2816 | {0x0F08, CMN_PDIAG_PLL1_FILT_PADJ_M0}, | ||
| 2817 | {0x0064, CMN_PLL0_INTDIV_M0}, | ||
| 2818 | {0x0050, CMN_PLL0_INTDIV_M1}, | ||
| 2819 | {0x0064, CMN_PLL1_INTDIV_M0}, | ||
| 2820 | {0x0002, CMN_PLL0_FRACDIVH_M0}, | ||
| 2821 | {0x0002, CMN_PLL0_FRACDIVH_M1}, | ||
| 2822 | {0x0002, CMN_PLL1_FRACDIVH_M0}, | ||
| 2823 | {0x0044, CMN_PLL0_HIGH_THR_M0}, | ||
| 2824 | {0x0036, CMN_PLL0_HIGH_THR_M1}, | ||
| 2825 | {0x0044, CMN_PLL1_HIGH_THR_M0}, | ||
| 2826 | {0x0002, CMN_PDIAG_PLL0_CTRL_M0}, | ||
| 2827 | {0x0002, CMN_PDIAG_PLL0_CTRL_M1}, | ||
| 2828 | {0x0002, CMN_PDIAG_PLL1_CTRL_M0}, | ||
| 2829 | {0x0001, CMN_PLL0_SS_CTRL1_M0}, | ||
| 2830 | {0x0001, CMN_PLL0_SS_CTRL1_M1}, | ||
| 2831 | {0x0001, CMN_PLL1_SS_CTRL1_M0}, | ||
| 2832 | {0x011B, CMN_PLL0_SS_CTRL2_M0}, | ||
| 2833 | {0x011B, CMN_PLL0_SS_CTRL2_M1}, | ||
| 2834 | {0x011B, CMN_PLL1_SS_CTRL2_M0}, | ||
| 2835 | {0x006E, CMN_PLL0_SS_CTRL3_M0}, | ||
| 2836 | {0x0058, CMN_PLL0_SS_CTRL3_M1}, | ||
| 2837 | {0x006E, CMN_PLL1_SS_CTRL3_M0}, | ||
| 2838 | {0x000E, CMN_PLL0_SS_CTRL4_M0}, | ||
| 2839 | {0x0012, CMN_PLL0_SS_CTRL4_M1}, | ||
| 2840 | {0x000E, CMN_PLL1_SS_CTRL4_M0}, | ||
| 2841 | {0x0C5E, CMN_PLL0_VCOCAL_REFTIM_START}, | ||
| 2842 | {0x0C5E, CMN_PLL1_VCOCAL_REFTIM_START}, | ||
| 2843 | {0x0C56, CMN_PLL0_VCOCAL_PLLCNT_START}, | ||
| 2844 | {0x0C56, CMN_PLL1_VCOCAL_PLLCNT_START}, | ||
| 2845 | {0x0003, CMN_PLL0_VCOCAL_TCTRL}, | ||
| 2846 | {0x0003, CMN_PLL1_VCOCAL_TCTRL}, | ||
| 2847 | {0x00C7, CMN_PLL0_LOCK_REFCNT_START}, | ||
| 2848 | {0x00C7, CMN_PLL1_LOCK_REFCNT_START}, | ||
| 2849 | {0x00C7, CMN_PLL0_LOCK_PLLCNT_START}, | ||
| 2850 | {0x00C7, CMN_PLL1_LOCK_PLLCNT_START}, | ||
| 2851 | {0x0005, CMN_PLL0_LOCK_PLLCNT_THR}, | ||
| 2852 | {0x0005, CMN_PLL1_LOCK_PLLCNT_THR} | ||
| 2853 | }; | ||
| 2854 | |||
| 2855 | static struct cdns_torrent_vals qsgmii_100_int_ssc_cmn_vals = { | ||
| 2856 | .reg_pairs = qsgmii_100_int_ssc_cmn_regs, | ||
| 2857 | .num_regs = ARRAY_SIZE(qsgmii_100_int_ssc_cmn_regs), | ||
| 2858 | }; | ||
| 2859 | |||
| 2860 | /* Single SGMII/QSGMII link configuration */ | ||
| 2861 | static struct cdns_reg_pairs sl_sgmii_link_cmn_regs[] = { | ||
| 2862 | {0x0000, PHY_PLL_CFG}, | ||
| 2863 | {0x0601, CMN_PDIAG_PLL0_CLK_SEL_M0} | ||
| 2864 | }; | ||
| 2865 | |||
| 2866 | static struct cdns_reg_pairs sl_sgmii_xcvr_diag_ln_regs[] = { | ||
| 2867 | {0x0000, XCVR_DIAG_HSCLK_SEL}, | ||
| 2868 | {0x0003, XCVR_DIAG_HSCLK_DIV}, | ||
| 2869 | {0x0013, XCVR_DIAG_PLLDRC_CTRL} | ||
| 2870 | }; | ||
| 2871 | |||
| 2872 | static struct cdns_torrent_vals sl_sgmii_link_cmn_vals = { | ||
| 2873 | .reg_pairs = sl_sgmii_link_cmn_regs, | ||
| 2874 | .num_regs = ARRAY_SIZE(sl_sgmii_link_cmn_regs), | ||
| 2875 | }; | ||
| 2876 | |||
| 2877 | static struct cdns_torrent_vals sl_sgmii_xcvr_diag_ln_vals = { | ||
| 2878 | .reg_pairs = sl_sgmii_xcvr_diag_ln_regs, | ||
| 2879 | .num_regs = ARRAY_SIZE(sl_sgmii_xcvr_diag_ln_regs), | ||
| 2880 | }; | ||
| 2881 | |||
| 2882 | /* Multi link PCIe, 100 MHz Ref clk, internal SSC */ | ||
| 2883 | static struct cdns_reg_pairs pcie_100_int_ssc_cmn_regs[] = { | ||
| 2884 | {0x0004, CMN_PLL0_DSM_DIAG_M0}, | ||
| 2885 | {0x0004, CMN_PLL0_DSM_DIAG_M1}, | ||
| 2886 | {0x0004, CMN_PLL1_DSM_DIAG_M0}, | ||
| 2887 | {0x0509, CMN_PDIAG_PLL0_CP_PADJ_M0}, | ||
| 2888 | {0x0509, CMN_PDIAG_PLL0_CP_PADJ_M1}, | ||
| 2889 | {0x0509, CMN_PDIAG_PLL1_CP_PADJ_M0}, | ||
| 2890 | {0x0F00, CMN_PDIAG_PLL0_CP_IADJ_M0}, | ||
| 2891 | {0x0F00, CMN_PDIAG_PLL0_CP_IADJ_M1}, | ||
| 2892 | {0x0F00, CMN_PDIAG_PLL1_CP_IADJ_M0}, | ||
| 2893 | {0x0F08, CMN_PDIAG_PLL0_FILT_PADJ_M0}, | ||
| 2894 | {0x0F08, CMN_PDIAG_PLL0_FILT_PADJ_M1}, | ||
| 2895 | {0x0F08, CMN_PDIAG_PLL1_FILT_PADJ_M0}, | ||
| 2896 | {0x0064, CMN_PLL0_INTDIV_M0}, | ||
| 2897 | {0x0050, CMN_PLL0_INTDIV_M1}, | ||
| 2898 | {0x0064, CMN_PLL1_INTDIV_M0}, | ||
| 2899 | {0x0002, CMN_PLL0_FRACDIVH_M0}, | ||
| 2900 | {0x0002, CMN_PLL0_FRACDIVH_M1}, | ||
| 2901 | {0x0002, CMN_PLL1_FRACDIVH_M0}, | ||
| 2902 | {0x0044, CMN_PLL0_HIGH_THR_M0}, | ||
| 2903 | {0x0036, CMN_PLL0_HIGH_THR_M1}, | ||
| 2904 | {0x0044, CMN_PLL1_HIGH_THR_M0}, | ||
| 2905 | {0x0002, CMN_PDIAG_PLL0_CTRL_M0}, | ||
| 2906 | {0x0002, CMN_PDIAG_PLL0_CTRL_M1}, | ||
| 2907 | {0x0002, CMN_PDIAG_PLL1_CTRL_M0}, | ||
| 2908 | {0x0001, CMN_PLL0_SS_CTRL1_M0}, | ||
| 2909 | {0x0001, CMN_PLL0_SS_CTRL1_M1}, | ||
| 2910 | {0x0001, CMN_PLL1_SS_CTRL1_M0}, | ||
| 2911 | {0x011B, CMN_PLL0_SS_CTRL2_M0}, | ||
| 2912 | {0x011B, CMN_PLL0_SS_CTRL2_M1}, | ||
| 2913 | {0x011B, CMN_PLL1_SS_CTRL2_M0}, | ||
| 2914 | {0x006E, CMN_PLL0_SS_CTRL3_M0}, | ||
| 2915 | {0x0058, CMN_PLL0_SS_CTRL3_M1}, | ||
| 2916 | {0x006E, CMN_PLL1_SS_CTRL3_M0}, | ||
| 2917 | {0x000E, CMN_PLL0_SS_CTRL4_M0}, | ||
| 2918 | {0x0012, CMN_PLL0_SS_CTRL4_M1}, | ||
| 2919 | {0x000E, CMN_PLL1_SS_CTRL4_M0}, | ||
| 2920 | {0x0C5E, CMN_PLL0_VCOCAL_REFTIM_START}, | ||
| 2921 | {0x0C5E, CMN_PLL1_VCOCAL_REFTIM_START}, | ||
| 2922 | {0x0C56, CMN_PLL0_VCOCAL_PLLCNT_START}, | ||
| 2923 | {0x0C56, CMN_PLL1_VCOCAL_PLLCNT_START}, | ||
| 2924 | {0x0003, CMN_PLL0_VCOCAL_TCTRL}, | ||
| 2925 | {0x0003, CMN_PLL1_VCOCAL_TCTRL}, | ||
| 2926 | {0x00C7, CMN_PLL0_LOCK_REFCNT_START}, | ||
| 2927 | {0x00C7, CMN_PLL1_LOCK_REFCNT_START}, | ||
| 2928 | {0x00C7, CMN_PLL0_LOCK_PLLCNT_START}, | ||
| 2929 | {0x00C7, CMN_PLL1_LOCK_PLLCNT_START}, | ||
| 2930 | {0x0005, CMN_PLL0_LOCK_PLLCNT_THR}, | ||
| 2931 | {0x0005, CMN_PLL1_LOCK_PLLCNT_THR} | ||
| 2932 | }; | ||
| 2933 | |||
| 2934 | static struct cdns_torrent_vals pcie_100_int_ssc_cmn_vals = { | ||
| 2935 | .reg_pairs = pcie_100_int_ssc_cmn_regs, | ||
| 2936 | .num_regs = ARRAY_SIZE(pcie_100_int_ssc_cmn_regs), | ||
| 2937 | }; | ||
| 2938 | |||
| 2939 | /* Single link PCIe, 100 MHz Ref clk, internal SSC */ | ||
| 2940 | static struct cdns_reg_pairs sl_pcie_100_int_ssc_cmn_regs[] = { | ||
| 2941 | {0x0004, CMN_PLL0_DSM_DIAG_M0}, | ||
| 2942 | {0x0004, CMN_PLL0_DSM_DIAG_M1}, | ||
| 2943 | {0x0004, CMN_PLL1_DSM_DIAG_M0}, | ||
| 2944 | {0x0509, CMN_PDIAG_PLL0_CP_PADJ_M0}, | ||
| 2945 | {0x0509, CMN_PDIAG_PLL0_CP_PADJ_M1}, | ||
| 2946 | {0x0509, CMN_PDIAG_PLL1_CP_PADJ_M0}, | ||
| 2947 | {0x0F00, CMN_PDIAG_PLL0_CP_IADJ_M0}, | ||
| 2948 | {0x0F00, CMN_PDIAG_PLL0_CP_IADJ_M1}, | ||
| 2949 | {0x0F00, CMN_PDIAG_PLL1_CP_IADJ_M0}, | ||
| 2950 | {0x0F08, CMN_PDIAG_PLL0_FILT_PADJ_M0}, | ||
| 2951 | {0x0F08, CMN_PDIAG_PLL0_FILT_PADJ_M1}, | ||
| 2952 | {0x0F08, CMN_PDIAG_PLL1_FILT_PADJ_M0}, | ||
| 2953 | {0x0064, CMN_PLL0_INTDIV_M0}, | ||
| 2954 | {0x0050, CMN_PLL0_INTDIV_M1}, | ||
| 2955 | {0x0050, CMN_PLL1_INTDIV_M0}, | ||
| 2956 | {0x0002, CMN_PLL0_FRACDIVH_M0}, | ||
| 2957 | {0x0002, CMN_PLL0_FRACDIVH_M1}, | ||
| 2958 | {0x0002, CMN_PLL1_FRACDIVH_M0}, | ||
| 2959 | {0x0044, CMN_PLL0_HIGH_THR_M0}, | ||
| 2960 | {0x0036, CMN_PLL0_HIGH_THR_M1}, | ||
| 2961 | {0x0036, CMN_PLL1_HIGH_THR_M0}, | ||
| 2962 | {0x0002, CMN_PDIAG_PLL0_CTRL_M0}, | ||
| 2963 | {0x0002, CMN_PDIAG_PLL0_CTRL_M1}, | ||
| 2964 | {0x0002, CMN_PDIAG_PLL1_CTRL_M0}, | ||
| 2965 | {0x0001, CMN_PLL0_SS_CTRL1_M0}, | ||
| 2966 | {0x0001, CMN_PLL0_SS_CTRL1_M1}, | ||
| 2967 | {0x0001, CMN_PLL1_SS_CTRL1_M0}, | ||
| 2968 | {0x011B, CMN_PLL0_SS_CTRL2_M0}, | ||
| 2969 | {0x011B, CMN_PLL0_SS_CTRL2_M1}, | ||
| 2970 | {0x011B, CMN_PLL1_SS_CTRL2_M0}, | ||
| 2971 | {0x006E, CMN_PLL0_SS_CTRL3_M0}, | ||
| 2972 | {0x0058, CMN_PLL0_SS_CTRL3_M1}, | ||
| 2973 | {0x0058, CMN_PLL1_SS_CTRL3_M0}, | ||
| 2974 | {0x000E, CMN_PLL0_SS_CTRL4_M0}, | ||
| 2975 | {0x0012, CMN_PLL0_SS_CTRL4_M1}, | ||
| 2976 | {0x0012, CMN_PLL1_SS_CTRL4_M0}, | ||
| 2977 | {0x0C5E, CMN_PLL0_VCOCAL_REFTIM_START}, | ||
| 2978 | {0x0C5E, CMN_PLL1_VCOCAL_REFTIM_START}, | ||
| 2979 | {0x0C56, CMN_PLL0_VCOCAL_PLLCNT_START}, | ||
| 2980 | {0x0C56, CMN_PLL1_VCOCAL_PLLCNT_START}, | ||
| 2981 | {0x0003, CMN_PLL0_VCOCAL_TCTRL}, | ||
| 2982 | {0x0003, CMN_PLL1_VCOCAL_TCTRL}, | ||
| 2983 | {0x00C7, CMN_PLL0_LOCK_REFCNT_START}, | ||
| 2984 | {0x00C7, CMN_PLL1_LOCK_REFCNT_START}, | ||
| 2985 | {0x00C7, CMN_PLL0_LOCK_PLLCNT_START}, | ||
| 2986 | {0x00C7, CMN_PLL1_LOCK_PLLCNT_START}, | ||
| 2987 | {0x0005, CMN_PLL0_LOCK_PLLCNT_THR}, | ||
| 2988 | {0x0005, CMN_PLL1_LOCK_PLLCNT_THR} | ||
| 2989 | }; | ||
| 2990 | |||
| 2991 | static struct cdns_torrent_vals sl_pcie_100_int_ssc_cmn_vals = { | ||
| 2992 | .reg_pairs = sl_pcie_100_int_ssc_cmn_regs, | ||
| 2993 | .num_regs = ARRAY_SIZE(sl_pcie_100_int_ssc_cmn_regs), | ||
| 2994 | }; | ||
| 2995 | |||
| 2996 | /* PCIe, 100 MHz Ref clk, no SSC & external SSC */ | ||
| 2997 | static struct cdns_reg_pairs pcie_100_ext_no_ssc_cmn_regs[] = { | ||
| 2998 | {0x0003, CMN_PLL0_VCOCAL_TCTRL}, | ||
| 2999 | {0x0003, CMN_PLL1_VCOCAL_TCTRL} | ||
| 3000 | }; | ||
| 3001 | |||
| 3002 | static struct cdns_reg_pairs pcie_100_ext_no_ssc_rx_ln_regs[] = { | ||
| 3003 | {0x0019, RX_REE_TAP1_CLIP}, | ||
| 3004 | {0x0019, RX_REE_TAP2TON_CLIP}, | ||
| 3005 | {0x0001, RX_DIAG_ACYA} | ||
| 3006 | }; | ||
| 3007 | |||
| 3008 | static struct cdns_torrent_vals pcie_100_no_ssc_cmn_vals = { | ||
| 3009 | .reg_pairs = pcie_100_ext_no_ssc_cmn_regs, | ||
| 3010 | .num_regs = ARRAY_SIZE(pcie_100_ext_no_ssc_cmn_regs), | ||
| 3011 | }; | ||
| 3012 | |||
| 3013 | static struct cdns_torrent_vals pcie_100_no_ssc_rx_ln_vals = { | ||
| 3014 | .reg_pairs = pcie_100_ext_no_ssc_rx_ln_regs, | ||
| 3015 | .num_regs = ARRAY_SIZE(pcie_100_ext_no_ssc_rx_ln_regs), | ||
| 3016 | }; | ||
| 3017 | |||
| 1909 | static const struct cdns_torrent_data cdns_map_torrent = { | 3018 | static const struct cdns_torrent_data cdns_map_torrent = { |
| 1910 | .block_offset_shift = 0x2, | 3019 | .block_offset_shift = 0x2, |
| 1911 | .reg_offset_shift = 0x2, | 3020 | .reg_offset_shift = 0x2, |
| 3021 | .link_cmn_vals = { | ||
| 3022 | [TYPE_PCIE] = { | ||
| 3023 | [TYPE_NONE] = { | ||
| 3024 | [NO_SSC] = NULL, | ||
| 3025 | [EXTERNAL_SSC] = NULL, | ||
| 3026 | [INTERNAL_SSC] = NULL, | ||
| 3027 | }, | ||
| 3028 | [TYPE_SGMII] = { | ||
| 3029 | [NO_SSC] = &pcie_sgmii_link_cmn_vals, | ||
| 3030 | [EXTERNAL_SSC] = &pcie_sgmii_link_cmn_vals, | ||
| 3031 | [INTERNAL_SSC] = &pcie_sgmii_link_cmn_vals, | ||
| 3032 | }, | ||
| 3033 | [TYPE_QSGMII] = { | ||
| 3034 | [NO_SSC] = &pcie_sgmii_link_cmn_vals, | ||
| 3035 | [EXTERNAL_SSC] = &pcie_sgmii_link_cmn_vals, | ||
| 3036 | [INTERNAL_SSC] = &pcie_sgmii_link_cmn_vals, | ||
| 3037 | }, | ||
| 3038 | [TYPE_USB] = { | ||
| 3039 | [NO_SSC] = &pcie_usb_link_cmn_vals, | ||
| 3040 | [EXTERNAL_SSC] = &pcie_usb_link_cmn_vals, | ||
| 3041 | [INTERNAL_SSC] = &pcie_usb_link_cmn_vals, | ||
| 3042 | }, | ||
| 3043 | }, | ||
| 3044 | [TYPE_SGMII] = { | ||
| 3045 | [TYPE_NONE] = { | ||
| 3046 | [NO_SSC] = &sl_sgmii_link_cmn_vals, | ||
| 3047 | }, | ||
| 3048 | [TYPE_PCIE] = { | ||
| 3049 | [NO_SSC] = &pcie_sgmii_link_cmn_vals, | ||
| 3050 | [EXTERNAL_SSC] = &pcie_sgmii_link_cmn_vals, | ||
| 3051 | [INTERNAL_SSC] = &pcie_sgmii_link_cmn_vals, | ||
| 3052 | }, | ||
| 3053 | [TYPE_USB] = { | ||
| 3054 | [NO_SSC] = &usb_sgmii_link_cmn_vals, | ||
| 3055 | [EXTERNAL_SSC] = &usb_sgmii_link_cmn_vals, | ||
| 3056 | [INTERNAL_SSC] = &usb_sgmii_link_cmn_vals, | ||
| 3057 | }, | ||
| 3058 | }, | ||
| 3059 | [TYPE_QSGMII] = { | ||
| 3060 | [TYPE_NONE] = { | ||
| 3061 | [NO_SSC] = &sl_sgmii_link_cmn_vals, | ||
| 3062 | }, | ||
| 3063 | [TYPE_PCIE] = { | ||
| 3064 | [NO_SSC] = &pcie_sgmii_link_cmn_vals, | ||
| 3065 | [EXTERNAL_SSC] = &pcie_sgmii_link_cmn_vals, | ||
| 3066 | [INTERNAL_SSC] = &pcie_sgmii_link_cmn_vals, | ||
| 3067 | }, | ||
| 3068 | [TYPE_USB] = { | ||
| 3069 | [NO_SSC] = &usb_sgmii_link_cmn_vals, | ||
| 3070 | [EXTERNAL_SSC] = &usb_sgmii_link_cmn_vals, | ||
| 3071 | [INTERNAL_SSC] = &usb_sgmii_link_cmn_vals, | ||
| 3072 | }, | ||
| 3073 | }, | ||
| 3074 | [TYPE_USB] = { | ||
| 3075 | [TYPE_NONE] = { | ||
| 3076 | [NO_SSC] = &sl_usb_link_cmn_vals, | ||
| 3077 | [EXTERNAL_SSC] = &sl_usb_link_cmn_vals, | ||
| 3078 | [INTERNAL_SSC] = &sl_usb_link_cmn_vals, | ||
| 3079 | }, | ||
| 3080 | [TYPE_PCIE] = { | ||
| 3081 | [NO_SSC] = &pcie_usb_link_cmn_vals, | ||
| 3082 | [EXTERNAL_SSC] = &pcie_usb_link_cmn_vals, | ||
| 3083 | [INTERNAL_SSC] = &pcie_usb_link_cmn_vals, | ||
| 3084 | }, | ||
| 3085 | [TYPE_SGMII] = { | ||
| 3086 | [NO_SSC] = &usb_sgmii_link_cmn_vals, | ||
| 3087 | [EXTERNAL_SSC] = &usb_sgmii_link_cmn_vals, | ||
| 3088 | [INTERNAL_SSC] = &usb_sgmii_link_cmn_vals, | ||
| 3089 | }, | ||
| 3090 | [TYPE_QSGMII] = { | ||
| 3091 | [NO_SSC] = &usb_sgmii_link_cmn_vals, | ||
| 3092 | [EXTERNAL_SSC] = &usb_sgmii_link_cmn_vals, | ||
| 3093 | [INTERNAL_SSC] = &usb_sgmii_link_cmn_vals, | ||
| 3094 | }, | ||
| 3095 | }, | ||
| 3096 | }, | ||
| 3097 | .xcvr_diag_vals = { | ||
| 3098 | [TYPE_PCIE] = { | ||
| 3099 | [TYPE_NONE] = { | ||
| 3100 | [NO_SSC] = NULL, | ||
| 3101 | [EXTERNAL_SSC] = NULL, | ||
| 3102 | [INTERNAL_SSC] = NULL, | ||
| 3103 | }, | ||
| 3104 | [TYPE_SGMII] = { | ||
| 3105 | [NO_SSC] = &pcie_sgmii_xcvr_diag_ln_vals, | ||
| 3106 | [EXTERNAL_SSC] = &pcie_sgmii_xcvr_diag_ln_vals, | ||
| 3107 | [INTERNAL_SSC] = &pcie_sgmii_xcvr_diag_ln_vals, | ||
| 3108 | }, | ||
| 3109 | [TYPE_QSGMII] = { | ||
| 3110 | [NO_SSC] = &pcie_sgmii_xcvr_diag_ln_vals, | ||
| 3111 | [EXTERNAL_SSC] = &pcie_sgmii_xcvr_diag_ln_vals, | ||
| 3112 | [INTERNAL_SSC] = &pcie_sgmii_xcvr_diag_ln_vals, | ||
| 3113 | }, | ||
| 3114 | [TYPE_USB] = { | ||
| 3115 | [NO_SSC] = &pcie_usb_xcvr_diag_ln_vals, | ||
| 3116 | [EXTERNAL_SSC] = &pcie_usb_xcvr_diag_ln_vals, | ||
| 3117 | [INTERNAL_SSC] = &pcie_usb_xcvr_diag_ln_vals, | ||
| 3118 | }, | ||
| 3119 | }, | ||
| 3120 | [TYPE_SGMII] = { | ||
| 3121 | [TYPE_NONE] = { | ||
| 3122 | [NO_SSC] = &sl_sgmii_xcvr_diag_ln_vals, | ||
| 3123 | }, | ||
| 3124 | [TYPE_PCIE] = { | ||
| 3125 | [NO_SSC] = &sgmii_pcie_xcvr_diag_ln_vals, | ||
| 3126 | [EXTERNAL_SSC] = &sgmii_pcie_xcvr_diag_ln_vals, | ||
| 3127 | [INTERNAL_SSC] = &sgmii_pcie_xcvr_diag_ln_vals, | ||
| 3128 | }, | ||
| 3129 | [TYPE_USB] = { | ||
| 3130 | [NO_SSC] = &sgmii_usb_xcvr_diag_ln_vals, | ||
| 3131 | [EXTERNAL_SSC] = &sgmii_usb_xcvr_diag_ln_vals, | ||
| 3132 | [INTERNAL_SSC] = &sgmii_usb_xcvr_diag_ln_vals, | ||
| 3133 | }, | ||
| 3134 | }, | ||
| 3135 | [TYPE_QSGMII] = { | ||
| 3136 | [TYPE_NONE] = { | ||
| 3137 | [NO_SSC] = &sl_sgmii_xcvr_diag_ln_vals, | ||
| 3138 | }, | ||
| 3139 | [TYPE_PCIE] = { | ||
| 3140 | [NO_SSC] = &sgmii_pcie_xcvr_diag_ln_vals, | ||
| 3141 | [EXTERNAL_SSC] = &sgmii_pcie_xcvr_diag_ln_vals, | ||
| 3142 | [INTERNAL_SSC] = &sgmii_pcie_xcvr_diag_ln_vals, | ||
| 3143 | }, | ||
| 3144 | [TYPE_USB] = { | ||
| 3145 | [NO_SSC] = &sgmii_usb_xcvr_diag_ln_vals, | ||
| 3146 | [EXTERNAL_SSC] = &sgmii_usb_xcvr_diag_ln_vals, | ||
| 3147 | [INTERNAL_SSC] = &sgmii_usb_xcvr_diag_ln_vals, | ||
| 3148 | }, | ||
| 3149 | }, | ||
| 3150 | [TYPE_USB] = { | ||
| 3151 | [TYPE_NONE] = { | ||
| 3152 | [NO_SSC] = &sl_usb_xcvr_diag_ln_vals, | ||
| 3153 | [EXTERNAL_SSC] = &sl_usb_xcvr_diag_ln_vals, | ||
| 3154 | [INTERNAL_SSC] = &sl_usb_xcvr_diag_ln_vals, | ||
| 3155 | }, | ||
| 3156 | [TYPE_PCIE] = { | ||
| 3157 | [NO_SSC] = &usb_pcie_xcvr_diag_ln_vals, | ||
| 3158 | [EXTERNAL_SSC] = &usb_pcie_xcvr_diag_ln_vals, | ||
| 3159 | [INTERNAL_SSC] = &usb_pcie_xcvr_diag_ln_vals, | ||
| 3160 | }, | ||
| 3161 | [TYPE_SGMII] = { | ||
| 3162 | [NO_SSC] = &usb_sgmii_xcvr_diag_ln_vals, | ||
| 3163 | [EXTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals, | ||
| 3164 | [INTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals, | ||
| 3165 | }, | ||
| 3166 | [TYPE_QSGMII] = { | ||
| 3167 | [NO_SSC] = &usb_sgmii_xcvr_diag_ln_vals, | ||
| 3168 | [EXTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals, | ||
| 3169 | [INTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals, | ||
| 3170 | }, | ||
| 3171 | }, | ||
| 3172 | }, | ||
| 3173 | .pcs_cmn_vals = { | ||
| 3174 | [TYPE_USB] = { | ||
| 3175 | [TYPE_NONE] = { | ||
| 3176 | [NO_SSC] = &usb_phy_pcs_cmn_vals, | ||
| 3177 | [EXTERNAL_SSC] = &usb_phy_pcs_cmn_vals, | ||
| 3178 | [INTERNAL_SSC] = &usb_phy_pcs_cmn_vals, | ||
| 3179 | }, | ||
| 3180 | [TYPE_PCIE] = { | ||
| 3181 | [NO_SSC] = &usb_phy_pcs_cmn_vals, | ||
| 3182 | [EXTERNAL_SSC] = &usb_phy_pcs_cmn_vals, | ||
| 3183 | [INTERNAL_SSC] = &usb_phy_pcs_cmn_vals, | ||
| 3184 | }, | ||
| 3185 | [TYPE_SGMII] = { | ||
| 3186 | [NO_SSC] = &usb_phy_pcs_cmn_vals, | ||
| 3187 | [EXTERNAL_SSC] = &usb_phy_pcs_cmn_vals, | ||
| 3188 | [INTERNAL_SSC] = &usb_phy_pcs_cmn_vals, | ||
| 3189 | }, | ||
| 3190 | [TYPE_QSGMII] = { | ||
| 3191 | [NO_SSC] = &usb_phy_pcs_cmn_vals, | ||
| 3192 | [EXTERNAL_SSC] = &usb_phy_pcs_cmn_vals, | ||
| 3193 | [INTERNAL_SSC] = &usb_phy_pcs_cmn_vals, | ||
| 3194 | }, | ||
| 3195 | }, | ||
| 3196 | }, | ||
| 3197 | .cmn_vals = { | ||
| 3198 | [TYPE_PCIE] = { | ||
| 3199 | [TYPE_NONE] = { | ||
| 3200 | [NO_SSC] = &pcie_100_no_ssc_cmn_vals, | ||
| 3201 | [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, | ||
| 3202 | [INTERNAL_SSC] = &sl_pcie_100_int_ssc_cmn_vals, | ||
| 3203 | }, | ||
| 3204 | [TYPE_SGMII] = { | ||
| 3205 | [NO_SSC] = &pcie_100_no_ssc_cmn_vals, | ||
| 3206 | [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, | ||
| 3207 | [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals, | ||
| 3208 | }, | ||
| 3209 | [TYPE_QSGMII] = { | ||
| 3210 | [NO_SSC] = &pcie_100_no_ssc_cmn_vals, | ||
| 3211 | [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, | ||
| 3212 | [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals, | ||
| 3213 | }, | ||
| 3214 | [TYPE_USB] = { | ||
| 3215 | [NO_SSC] = &pcie_100_no_ssc_cmn_vals, | ||
| 3216 | [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, | ||
| 3217 | [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals, | ||
| 3218 | }, | ||
| 3219 | }, | ||
| 3220 | [TYPE_SGMII] = { | ||
| 3221 | [TYPE_NONE] = { | ||
| 3222 | [NO_SSC] = &sgmii_100_no_ssc_cmn_vals, | ||
| 3223 | }, | ||
| 3224 | [TYPE_PCIE] = { | ||
| 3225 | [NO_SSC] = &sgmii_100_no_ssc_cmn_vals, | ||
| 3226 | [EXTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals, | ||
| 3227 | [INTERNAL_SSC] = &sgmii_100_int_ssc_cmn_vals, | ||
| 3228 | }, | ||
| 3229 | [TYPE_USB] = { | ||
| 3230 | [NO_SSC] = &sgmii_100_no_ssc_cmn_vals, | ||
| 3231 | [EXTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals, | ||
| 3232 | [INTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals, | ||
| 3233 | }, | ||
| 3234 | }, | ||
| 3235 | [TYPE_QSGMII] = { | ||
| 3236 | [TYPE_NONE] = { | ||
| 3237 | [NO_SSC] = &qsgmii_100_no_ssc_cmn_vals, | ||
| 3238 | }, | ||
| 3239 | [TYPE_PCIE] = { | ||
| 3240 | [NO_SSC] = &qsgmii_100_no_ssc_cmn_vals, | ||
| 3241 | [EXTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals, | ||
| 3242 | [INTERNAL_SSC] = &qsgmii_100_int_ssc_cmn_vals, | ||
| 3243 | }, | ||
| 3244 | [TYPE_USB] = { | ||
| 3245 | [NO_SSC] = &qsgmii_100_no_ssc_cmn_vals, | ||
| 3246 | [EXTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals, | ||
| 3247 | [INTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals, | ||
| 3248 | }, | ||
| 3249 | }, | ||
| 3250 | [TYPE_USB] = { | ||
| 3251 | [TYPE_NONE] = { | ||
| 3252 | [NO_SSC] = &usb_100_no_ssc_cmn_vals, | ||
| 3253 | [EXTERNAL_SSC] = &usb_100_no_ssc_cmn_vals, | ||
| 3254 | [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals, | ||
| 3255 | }, | ||
| 3256 | [TYPE_PCIE] = { | ||
| 3257 | [NO_SSC] = &usb_100_no_ssc_cmn_vals, | ||
| 3258 | [EXTERNAL_SSC] = &usb_100_no_ssc_cmn_vals, | ||
| 3259 | [INTERNAL_SSC] = &usb_100_int_ssc_cmn_vals, | ||
| 3260 | }, | ||
| 3261 | [TYPE_SGMII] = { | ||
| 3262 | [NO_SSC] = &usb_100_no_ssc_cmn_vals, | ||
| 3263 | [EXTERNAL_SSC] = &usb_100_no_ssc_cmn_vals, | ||
| 3264 | [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals, | ||
| 3265 | }, | ||
| 3266 | [TYPE_QSGMII] = { | ||
| 3267 | [NO_SSC] = &usb_100_no_ssc_cmn_vals, | ||
| 3268 | [EXTERNAL_SSC] = &usb_100_no_ssc_cmn_vals, | ||
| 3269 | [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals, | ||
| 3270 | }, | ||
| 3271 | }, | ||
| 3272 | }, | ||
| 3273 | .tx_ln_vals = { | ||
| 3274 | [TYPE_PCIE] = { | ||
| 3275 | [TYPE_NONE] = { | ||
| 3276 | [NO_SSC] = NULL, | ||
| 3277 | [EXTERNAL_SSC] = NULL, | ||
| 3278 | [INTERNAL_SSC] = NULL, | ||
| 3279 | }, | ||
| 3280 | [TYPE_SGMII] = { | ||
| 3281 | [NO_SSC] = NULL, | ||
| 3282 | [EXTERNAL_SSC] = NULL, | ||
| 3283 | [INTERNAL_SSC] = NULL, | ||
| 3284 | }, | ||
| 3285 | [TYPE_QSGMII] = { | ||
| 3286 | [NO_SSC] = NULL, | ||
| 3287 | [EXTERNAL_SSC] = NULL, | ||
| 3288 | [INTERNAL_SSC] = NULL, | ||
| 3289 | }, | ||
| 3290 | [TYPE_USB] = { | ||
| 3291 | [NO_SSC] = NULL, | ||
| 3292 | [EXTERNAL_SSC] = NULL, | ||
| 3293 | [INTERNAL_SSC] = NULL, | ||
| 3294 | }, | ||
| 3295 | }, | ||
| 3296 | [TYPE_SGMII] = { | ||
| 3297 | [TYPE_NONE] = { | ||
| 3298 | [NO_SSC] = &sgmii_100_no_ssc_tx_ln_vals, | ||
| 3299 | }, | ||
| 3300 | [TYPE_PCIE] = { | ||
| 3301 | [NO_SSC] = &sgmii_100_no_ssc_tx_ln_vals, | ||
| 3302 | [EXTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals, | ||
| 3303 | [INTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals, | ||
| 3304 | }, | ||
| 3305 | [TYPE_USB] = { | ||
| 3306 | [NO_SSC] = &sgmii_100_no_ssc_tx_ln_vals, | ||
| 3307 | [EXTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals, | ||
| 3308 | [INTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals, | ||
| 3309 | }, | ||
| 3310 | }, | ||
| 3311 | [TYPE_QSGMII] = { | ||
| 3312 | [TYPE_NONE] = { | ||
| 3313 | [NO_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, | ||
| 3314 | }, | ||
| 3315 | [TYPE_PCIE] = { | ||
| 3316 | [NO_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, | ||
| 3317 | [EXTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, | ||
| 3318 | [INTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, | ||
| 3319 | }, | ||
| 3320 | [TYPE_USB] = { | ||
| 3321 | [NO_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, | ||
| 3322 | [EXTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, | ||
| 3323 | [INTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, | ||
| 3324 | }, | ||
| 3325 | }, | ||
| 3326 | [TYPE_USB] = { | ||
| 3327 | [TYPE_NONE] = { | ||
| 3328 | [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, | ||
| 3329 | [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, | ||
| 3330 | [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, | ||
| 3331 | }, | ||
| 3332 | [TYPE_PCIE] = { | ||
| 3333 | [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, | ||
| 3334 | [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, | ||
| 3335 | [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, | ||
| 3336 | }, | ||
| 3337 | [TYPE_SGMII] = { | ||
| 3338 | [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, | ||
| 3339 | [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, | ||
| 3340 | [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, | ||
| 3341 | }, | ||
| 3342 | [TYPE_QSGMII] = { | ||
| 3343 | [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, | ||
| 3344 | [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, | ||
| 3345 | [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, | ||
| 3346 | }, | ||
| 3347 | }, | ||
| 3348 | }, | ||
| 3349 | .rx_ln_vals = { | ||
| 3350 | [TYPE_PCIE] = { | ||
| 3351 | [TYPE_NONE] = { | ||
| 3352 | [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, | ||
| 3353 | [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, | ||
| 3354 | [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, | ||
| 3355 | }, | ||
| 3356 | [TYPE_SGMII] = { | ||
| 3357 | [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, | ||
| 3358 | [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, | ||
| 3359 | [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, | ||
| 3360 | }, | ||
| 3361 | [TYPE_QSGMII] = { | ||
| 3362 | [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, | ||
| 3363 | [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, | ||
| 3364 | [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, | ||
| 3365 | }, | ||
| 3366 | [TYPE_USB] = { | ||
| 3367 | [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, | ||
| 3368 | [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, | ||
| 3369 | [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, | ||
| 3370 | }, | ||
| 3371 | }, | ||
| 3372 | [TYPE_SGMII] = { | ||
| 3373 | [TYPE_NONE] = { | ||
| 3374 | [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals, | ||
| 3375 | }, | ||
| 3376 | [TYPE_PCIE] = { | ||
| 3377 | [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals, | ||
| 3378 | [EXTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals, | ||
| 3379 | [INTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals, | ||
| 3380 | }, | ||
| 3381 | [TYPE_USB] = { | ||
| 3382 | [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals, | ||
| 3383 | [EXTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals, | ||
| 3384 | [INTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals, | ||
| 3385 | }, | ||
| 3386 | }, | ||
| 3387 | [TYPE_QSGMII] = { | ||
| 3388 | [TYPE_NONE] = { | ||
| 3389 | [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, | ||
| 3390 | }, | ||
| 3391 | [TYPE_PCIE] = { | ||
| 3392 | [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, | ||
| 3393 | [EXTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, | ||
| 3394 | [INTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, | ||
| 3395 | }, | ||
| 3396 | [TYPE_USB] = { | ||
| 3397 | [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, | ||
| 3398 | [EXTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, | ||
| 3399 | [INTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, | ||
| 3400 | }, | ||
| 3401 | }, | ||
| 3402 | [TYPE_USB] = { | ||
| 3403 | [TYPE_NONE] = { | ||
| 3404 | [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, | ||
| 3405 | [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, | ||
| 3406 | [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, | ||
| 3407 | }, | ||
| 3408 | [TYPE_PCIE] = { | ||
| 3409 | [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, | ||
| 3410 | [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, | ||
| 3411 | [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, | ||
| 3412 | }, | ||
| 3413 | [TYPE_SGMII] = { | ||
| 3414 | [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, | ||
| 3415 | [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, | ||
| 3416 | [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, | ||
| 3417 | }, | ||
| 3418 | [TYPE_QSGMII] = { | ||
| 3419 | [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, | ||
| 3420 | [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, | ||
| 3421 | [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, | ||
| 3422 | }, | ||
| 3423 | }, | ||
| 3424 | }, | ||
| 1912 | }; | 3425 | }; |
| 1913 | 3426 | ||
| 1914 | static const struct cdns_torrent_data ti_j721e_map_torrent = { | 3427 | static const struct cdns_torrent_data ti_j721e_map_torrent = { |
| 1915 | .block_offset_shift = 0x0, | 3428 | .block_offset_shift = 0x0, |
| 1916 | .reg_offset_shift = 0x1, | 3429 | .reg_offset_shift = 0x1, |
| 3430 | .link_cmn_vals = { | ||
| 3431 | [TYPE_PCIE] = { | ||
| 3432 | [TYPE_NONE] = { | ||
| 3433 | [NO_SSC] = NULL, | ||
| 3434 | [EXTERNAL_SSC] = NULL, | ||
| 3435 | [INTERNAL_SSC] = NULL, | ||
| 3436 | }, | ||
| 3437 | [TYPE_SGMII] = { | ||
| 3438 | [NO_SSC] = &pcie_sgmii_link_cmn_vals, | ||
| 3439 | [EXTERNAL_SSC] = &pcie_sgmii_link_cmn_vals, | ||
| 3440 | [INTERNAL_SSC] = &pcie_sgmii_link_cmn_vals, | ||
| 3441 | }, | ||
| 3442 | [TYPE_QSGMII] = { | ||
| 3443 | [NO_SSC] = &pcie_sgmii_link_cmn_vals, | ||
| 3444 | [EXTERNAL_SSC] = &pcie_sgmii_link_cmn_vals, | ||
| 3445 | [INTERNAL_SSC] = &pcie_sgmii_link_cmn_vals, | ||
| 3446 | }, | ||
| 3447 | [TYPE_USB] = { | ||
| 3448 | [NO_SSC] = &pcie_usb_link_cmn_vals, | ||
| 3449 | [EXTERNAL_SSC] = &pcie_usb_link_cmn_vals, | ||
| 3450 | [INTERNAL_SSC] = &pcie_usb_link_cmn_vals, | ||
| 3451 | }, | ||
| 3452 | }, | ||
| 3453 | [TYPE_SGMII] = { | ||
| 3454 | [TYPE_NONE] = { | ||
| 3455 | [NO_SSC] = &sl_sgmii_link_cmn_vals, | ||
| 3456 | }, | ||
| 3457 | [TYPE_PCIE] = { | ||
| 3458 | [NO_SSC] = &pcie_sgmii_link_cmn_vals, | ||
| 3459 | [EXTERNAL_SSC] = &pcie_sgmii_link_cmn_vals, | ||
| 3460 | [INTERNAL_SSC] = &pcie_sgmii_link_cmn_vals, | ||
| 3461 | }, | ||
| 3462 | [TYPE_USB] = { | ||
| 3463 | [NO_SSC] = &usb_sgmii_link_cmn_vals, | ||
| 3464 | [EXTERNAL_SSC] = &usb_sgmii_link_cmn_vals, | ||
| 3465 | [INTERNAL_SSC] = &usb_sgmii_link_cmn_vals, | ||
| 3466 | }, | ||
| 3467 | }, | ||
| 3468 | [TYPE_QSGMII] = { | ||
| 3469 | [TYPE_NONE] = { | ||
| 3470 | [NO_SSC] = &sl_sgmii_link_cmn_vals, | ||
| 3471 | }, | ||
| 3472 | [TYPE_PCIE] = { | ||
| 3473 | [NO_SSC] = &pcie_sgmii_link_cmn_vals, | ||
| 3474 | [EXTERNAL_SSC] = &pcie_sgmii_link_cmn_vals, | ||
| 3475 | [INTERNAL_SSC] = &pcie_sgmii_link_cmn_vals, | ||
| 3476 | }, | ||
| 3477 | [TYPE_USB] = { | ||
| 3478 | [NO_SSC] = &usb_sgmii_link_cmn_vals, | ||
| 3479 | [EXTERNAL_SSC] = &usb_sgmii_link_cmn_vals, | ||
| 3480 | [INTERNAL_SSC] = &usb_sgmii_link_cmn_vals, | ||
| 3481 | }, | ||
| 3482 | }, | ||
| 3483 | [TYPE_USB] = { | ||
| 3484 | [TYPE_NONE] = { | ||
| 3485 | [NO_SSC] = &sl_usb_link_cmn_vals, | ||
| 3486 | [EXTERNAL_SSC] = &sl_usb_link_cmn_vals, | ||
| 3487 | [INTERNAL_SSC] = &sl_usb_link_cmn_vals, | ||
| 3488 | }, | ||
| 3489 | [TYPE_PCIE] = { | ||
| 3490 | [NO_SSC] = &pcie_usb_link_cmn_vals, | ||
| 3491 | [EXTERNAL_SSC] = &pcie_usb_link_cmn_vals, | ||
| 3492 | [INTERNAL_SSC] = &pcie_usb_link_cmn_vals, | ||
| 3493 | }, | ||
| 3494 | [TYPE_SGMII] = { | ||
| 3495 | [NO_SSC] = &usb_sgmii_link_cmn_vals, | ||
| 3496 | [EXTERNAL_SSC] = &usb_sgmii_link_cmn_vals, | ||
| 3497 | [INTERNAL_SSC] = &usb_sgmii_link_cmn_vals, | ||
| 3498 | }, | ||
| 3499 | [TYPE_QSGMII] = { | ||
| 3500 | [NO_SSC] = &usb_sgmii_link_cmn_vals, | ||
| 3501 | [EXTERNAL_SSC] = &usb_sgmii_link_cmn_vals, | ||
| 3502 | [INTERNAL_SSC] = &usb_sgmii_link_cmn_vals, | ||
| 3503 | }, | ||
| 3504 | }, | ||
| 3505 | }, | ||
| 3506 | .xcvr_diag_vals = { | ||
| 3507 | [TYPE_PCIE] = { | ||
| 3508 | [TYPE_NONE] = { | ||
| 3509 | [NO_SSC] = NULL, | ||
| 3510 | [EXTERNAL_SSC] = NULL, | ||
| 3511 | [INTERNAL_SSC] = NULL, | ||
| 3512 | }, | ||
| 3513 | [TYPE_SGMII] = { | ||
| 3514 | [NO_SSC] = &pcie_sgmii_xcvr_diag_ln_vals, | ||
| 3515 | [EXTERNAL_SSC] = &pcie_sgmii_xcvr_diag_ln_vals, | ||
| 3516 | [INTERNAL_SSC] = &pcie_sgmii_xcvr_diag_ln_vals, | ||
| 3517 | }, | ||
| 3518 | [TYPE_QSGMII] = { | ||
| 3519 | [NO_SSC] = &pcie_sgmii_xcvr_diag_ln_vals, | ||
| 3520 | [EXTERNAL_SSC] = &pcie_sgmii_xcvr_diag_ln_vals, | ||
| 3521 | [INTERNAL_SSC] = &pcie_sgmii_xcvr_diag_ln_vals, | ||
| 3522 | }, | ||
| 3523 | [TYPE_USB] = { | ||
| 3524 | [NO_SSC] = &pcie_usb_xcvr_diag_ln_vals, | ||
| 3525 | [EXTERNAL_SSC] = &pcie_usb_xcvr_diag_ln_vals, | ||
| 3526 | [INTERNAL_SSC] = &pcie_usb_xcvr_diag_ln_vals, | ||
| 3527 | }, | ||
| 3528 | }, | ||
| 3529 | [TYPE_SGMII] = { | ||
| 3530 | [TYPE_NONE] = { | ||
| 3531 | [NO_SSC] = &sl_sgmii_xcvr_diag_ln_vals, | ||
| 3532 | }, | ||
| 3533 | [TYPE_PCIE] = { | ||
| 3534 | [NO_SSC] = &sgmii_pcie_xcvr_diag_ln_vals, | ||
| 3535 | [EXTERNAL_SSC] = &sgmii_pcie_xcvr_diag_ln_vals, | ||
| 3536 | [INTERNAL_SSC] = &sgmii_pcie_xcvr_diag_ln_vals, | ||
| 3537 | }, | ||
| 3538 | [TYPE_USB] = { | ||
| 3539 | [NO_SSC] = &sgmii_usb_xcvr_diag_ln_vals, | ||
| 3540 | [EXTERNAL_SSC] = &sgmii_usb_xcvr_diag_ln_vals, | ||
| 3541 | [INTERNAL_SSC] = &sgmii_usb_xcvr_diag_ln_vals, | ||
| 3542 | }, | ||
| 3543 | }, | ||
| 3544 | [TYPE_QSGMII] = { | ||
| 3545 | [TYPE_NONE] = { | ||
| 3546 | [NO_SSC] = &sl_sgmii_xcvr_diag_ln_vals, | ||
| 3547 | }, | ||
| 3548 | [TYPE_PCIE] = { | ||
| 3549 | [NO_SSC] = &sgmii_pcie_xcvr_diag_ln_vals, | ||
| 3550 | [EXTERNAL_SSC] = &sgmii_pcie_xcvr_diag_ln_vals, | ||
| 3551 | [INTERNAL_SSC] = &sgmii_pcie_xcvr_diag_ln_vals, | ||
| 3552 | }, | ||
| 3553 | [TYPE_USB] = { | ||
| 3554 | [NO_SSC] = &sgmii_usb_xcvr_diag_ln_vals, | ||
| 3555 | [EXTERNAL_SSC] = &sgmii_usb_xcvr_diag_ln_vals, | ||
| 3556 | [INTERNAL_SSC] = &sgmii_usb_xcvr_diag_ln_vals, | ||
| 3557 | }, | ||
| 3558 | }, | ||
| 3559 | [TYPE_USB] = { | ||
| 3560 | [TYPE_NONE] = { | ||
| 3561 | [NO_SSC] = &sl_usb_xcvr_diag_ln_vals, | ||
| 3562 | [EXTERNAL_SSC] = &sl_usb_xcvr_diag_ln_vals, | ||
| 3563 | [INTERNAL_SSC] = &sl_usb_xcvr_diag_ln_vals, | ||
| 3564 | }, | ||
| 3565 | [TYPE_PCIE] = { | ||
| 3566 | [NO_SSC] = &usb_pcie_xcvr_diag_ln_vals, | ||
| 3567 | [EXTERNAL_SSC] = &usb_pcie_xcvr_diag_ln_vals, | ||
| 3568 | [INTERNAL_SSC] = &usb_pcie_xcvr_diag_ln_vals, | ||
| 3569 | }, | ||
| 3570 | [TYPE_SGMII] = { | ||
| 3571 | [NO_SSC] = &usb_sgmii_xcvr_diag_ln_vals, | ||
| 3572 | [EXTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals, | ||
| 3573 | [INTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals, | ||
| 3574 | }, | ||
| 3575 | [TYPE_QSGMII] = { | ||
| 3576 | [NO_SSC] = &usb_sgmii_xcvr_diag_ln_vals, | ||
| 3577 | [EXTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals, | ||
| 3578 | [INTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals, | ||
| 3579 | }, | ||
| 3580 | }, | ||
| 3581 | }, | ||
| 3582 | .pcs_cmn_vals = { | ||
| 3583 | [TYPE_USB] = { | ||
| 3584 | [TYPE_NONE] = { | ||
| 3585 | [NO_SSC] = &usb_phy_pcs_cmn_vals, | ||
| 3586 | [EXTERNAL_SSC] = &usb_phy_pcs_cmn_vals, | ||
| 3587 | [INTERNAL_SSC] = &usb_phy_pcs_cmn_vals, | ||
| 3588 | }, | ||
| 3589 | [TYPE_PCIE] = { | ||
| 3590 | [NO_SSC] = &usb_phy_pcs_cmn_vals, | ||
| 3591 | [EXTERNAL_SSC] = &usb_phy_pcs_cmn_vals, | ||
| 3592 | [INTERNAL_SSC] = &usb_phy_pcs_cmn_vals, | ||
| 3593 | }, | ||
| 3594 | [TYPE_SGMII] = { | ||
| 3595 | [NO_SSC] = &usb_phy_pcs_cmn_vals, | ||
| 3596 | [EXTERNAL_SSC] = &usb_phy_pcs_cmn_vals, | ||
| 3597 | [INTERNAL_SSC] = &usb_phy_pcs_cmn_vals, | ||
| 3598 | }, | ||
| 3599 | [TYPE_QSGMII] = { | ||
| 3600 | [NO_SSC] = &usb_phy_pcs_cmn_vals, | ||
| 3601 | [EXTERNAL_SSC] = &usb_phy_pcs_cmn_vals, | ||
| 3602 | [INTERNAL_SSC] = &usb_phy_pcs_cmn_vals, | ||
| 3603 | }, | ||
| 3604 | }, | ||
| 3605 | }, | ||
| 3606 | .cmn_vals = { | ||
| 3607 | [TYPE_PCIE] = { | ||
| 3608 | [TYPE_NONE] = { | ||
| 3609 | [NO_SSC] = &pcie_100_no_ssc_cmn_vals, | ||
| 3610 | [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, | ||
| 3611 | [INTERNAL_SSC] = &sl_pcie_100_int_ssc_cmn_vals, | ||
| 3612 | }, | ||
| 3613 | [TYPE_SGMII] = { | ||
| 3614 | [NO_SSC] = &pcie_100_no_ssc_cmn_vals, | ||
| 3615 | [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, | ||
| 3616 | [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals, | ||
| 3617 | }, | ||
| 3618 | [TYPE_QSGMII] = { | ||
| 3619 | [NO_SSC] = &pcie_100_no_ssc_cmn_vals, | ||
| 3620 | [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, | ||
| 3621 | [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals, | ||
| 3622 | }, | ||
| 3623 | [TYPE_USB] = { | ||
| 3624 | [NO_SSC] = &pcie_100_no_ssc_cmn_vals, | ||
| 3625 | [EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals, | ||
| 3626 | [INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals, | ||
| 3627 | }, | ||
| 3628 | }, | ||
| 3629 | [TYPE_SGMII] = { | ||
| 3630 | [TYPE_NONE] = { | ||
| 3631 | [NO_SSC] = &sgmii_100_no_ssc_cmn_vals, | ||
| 3632 | }, | ||
| 3633 | [TYPE_PCIE] = { | ||
| 3634 | [NO_SSC] = &sgmii_100_no_ssc_cmn_vals, | ||
| 3635 | [EXTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals, | ||
| 3636 | [INTERNAL_SSC] = &sgmii_100_int_ssc_cmn_vals, | ||
| 3637 | }, | ||
| 3638 | [TYPE_USB] = { | ||
| 3639 | [NO_SSC] = &sgmii_100_no_ssc_cmn_vals, | ||
| 3640 | [EXTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals, | ||
| 3641 | [INTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals, | ||
| 3642 | }, | ||
| 3643 | }, | ||
| 3644 | [TYPE_QSGMII] = { | ||
| 3645 | [TYPE_NONE] = { | ||
| 3646 | [NO_SSC] = &qsgmii_100_no_ssc_cmn_vals, | ||
| 3647 | }, | ||
| 3648 | [TYPE_PCIE] = { | ||
| 3649 | [NO_SSC] = &qsgmii_100_no_ssc_cmn_vals, | ||
| 3650 | [EXTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals, | ||
| 3651 | [INTERNAL_SSC] = &qsgmii_100_int_ssc_cmn_vals, | ||
| 3652 | }, | ||
| 3653 | [TYPE_USB] = { | ||
| 3654 | [NO_SSC] = &qsgmii_100_no_ssc_cmn_vals, | ||
| 3655 | [EXTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals, | ||
| 3656 | [INTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals, | ||
| 3657 | }, | ||
| 3658 | }, | ||
| 3659 | [TYPE_USB] = { | ||
| 3660 | [TYPE_NONE] = { | ||
| 3661 | [NO_SSC] = &usb_100_no_ssc_cmn_vals, | ||
| 3662 | [EXTERNAL_SSC] = &usb_100_no_ssc_cmn_vals, | ||
| 3663 | [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals, | ||
| 3664 | }, | ||
| 3665 | [TYPE_PCIE] = { | ||
| 3666 | [NO_SSC] = &usb_100_no_ssc_cmn_vals, | ||
| 3667 | [EXTERNAL_SSC] = &usb_100_no_ssc_cmn_vals, | ||
| 3668 | [INTERNAL_SSC] = &usb_100_int_ssc_cmn_vals, | ||
| 3669 | }, | ||
| 3670 | [TYPE_SGMII] = { | ||
| 3671 | [NO_SSC] = &usb_100_no_ssc_cmn_vals, | ||
| 3672 | [EXTERNAL_SSC] = &usb_100_no_ssc_cmn_vals, | ||
| 3673 | [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals, | ||
| 3674 | }, | ||
| 3675 | [TYPE_QSGMII] = { | ||
| 3676 | [NO_SSC] = &usb_100_no_ssc_cmn_vals, | ||
| 3677 | [EXTERNAL_SSC] = &usb_100_no_ssc_cmn_vals, | ||
| 3678 | [INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals, | ||
| 3679 | }, | ||
| 3680 | }, | ||
| 3681 | }, | ||
| 3682 | .tx_ln_vals = { | ||
| 3683 | [TYPE_PCIE] = { | ||
| 3684 | [TYPE_NONE] = { | ||
| 3685 | [NO_SSC] = NULL, | ||
| 3686 | [EXTERNAL_SSC] = NULL, | ||
| 3687 | [INTERNAL_SSC] = NULL, | ||
| 3688 | }, | ||
| 3689 | [TYPE_SGMII] = { | ||
| 3690 | [NO_SSC] = NULL, | ||
| 3691 | [EXTERNAL_SSC] = NULL, | ||
| 3692 | [INTERNAL_SSC] = NULL, | ||
| 3693 | }, | ||
| 3694 | [TYPE_QSGMII] = { | ||
| 3695 | [NO_SSC] = NULL, | ||
| 3696 | [EXTERNAL_SSC] = NULL, | ||
| 3697 | [INTERNAL_SSC] = NULL, | ||
| 3698 | }, | ||
| 3699 | [TYPE_USB] = { | ||
| 3700 | [NO_SSC] = NULL, | ||
| 3701 | [EXTERNAL_SSC] = NULL, | ||
| 3702 | [INTERNAL_SSC] = NULL, | ||
| 3703 | }, | ||
| 3704 | }, | ||
| 3705 | [TYPE_SGMII] = { | ||
| 3706 | [TYPE_NONE] = { | ||
| 3707 | [NO_SSC] = &sgmii_100_no_ssc_tx_ln_vals, | ||
| 3708 | }, | ||
| 3709 | [TYPE_PCIE] = { | ||
| 3710 | [NO_SSC] = &sgmii_100_no_ssc_tx_ln_vals, | ||
| 3711 | [EXTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals, | ||
| 3712 | [INTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals, | ||
| 3713 | }, | ||
| 3714 | [TYPE_USB] = { | ||
| 3715 | [NO_SSC] = &sgmii_100_no_ssc_tx_ln_vals, | ||
| 3716 | [EXTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals, | ||
| 3717 | [INTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals, | ||
| 3718 | }, | ||
| 3719 | }, | ||
| 3720 | [TYPE_QSGMII] = { | ||
| 3721 | [TYPE_NONE] = { | ||
| 3722 | [NO_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, | ||
| 3723 | }, | ||
| 3724 | [TYPE_PCIE] = { | ||
| 3725 | [NO_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, | ||
| 3726 | [EXTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, | ||
| 3727 | [INTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, | ||
| 3728 | }, | ||
| 3729 | [TYPE_USB] = { | ||
| 3730 | [NO_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, | ||
| 3731 | [EXTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, | ||
| 3732 | [INTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals, | ||
| 3733 | }, | ||
| 3734 | }, | ||
| 3735 | [TYPE_USB] = { | ||
| 3736 | [TYPE_NONE] = { | ||
| 3737 | [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, | ||
| 3738 | [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, | ||
| 3739 | [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, | ||
| 3740 | }, | ||
| 3741 | [TYPE_PCIE] = { | ||
| 3742 | [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, | ||
| 3743 | [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, | ||
| 3744 | [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, | ||
| 3745 | }, | ||
| 3746 | [TYPE_SGMII] = { | ||
| 3747 | [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, | ||
| 3748 | [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, | ||
| 3749 | [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, | ||
| 3750 | }, | ||
| 3751 | [TYPE_QSGMII] = { | ||
| 3752 | [NO_SSC] = &usb_100_no_ssc_tx_ln_vals, | ||
| 3753 | [EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, | ||
| 3754 | [INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals, | ||
| 3755 | }, | ||
| 3756 | }, | ||
| 3757 | }, | ||
| 3758 | .rx_ln_vals = { | ||
| 3759 | [TYPE_PCIE] = { | ||
| 3760 | [TYPE_NONE] = { | ||
| 3761 | [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, | ||
| 3762 | [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, | ||
| 3763 | [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, | ||
| 3764 | }, | ||
| 3765 | [TYPE_SGMII] = { | ||
| 3766 | [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, | ||
| 3767 | [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, | ||
| 3768 | [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, | ||
| 3769 | }, | ||
| 3770 | [TYPE_QSGMII] = { | ||
| 3771 | [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, | ||
| 3772 | [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, | ||
| 3773 | [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, | ||
| 3774 | }, | ||
| 3775 | [TYPE_USB] = { | ||
| 3776 | [NO_SSC] = &pcie_100_no_ssc_rx_ln_vals, | ||
| 3777 | [EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, | ||
| 3778 | [INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals, | ||
| 3779 | }, | ||
| 3780 | }, | ||
| 3781 | [TYPE_SGMII] = { | ||
| 3782 | [TYPE_NONE] = { | ||
| 3783 | [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals, | ||
| 3784 | }, | ||
| 3785 | [TYPE_PCIE] = { | ||
| 3786 | [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals, | ||
| 3787 | [EXTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals, | ||
| 3788 | [INTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals, | ||
| 3789 | }, | ||
| 3790 | [TYPE_USB] = { | ||
| 3791 | [NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals, | ||
| 3792 | [EXTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals, | ||
| 3793 | [INTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals, | ||
| 3794 | }, | ||
| 3795 | }, | ||
| 3796 | [TYPE_QSGMII] = { | ||
| 3797 | [TYPE_NONE] = { | ||
| 3798 | [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, | ||
| 3799 | }, | ||
| 3800 | [TYPE_PCIE] = { | ||
| 3801 | [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, | ||
| 3802 | [EXTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, | ||
| 3803 | [INTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, | ||
| 3804 | }, | ||
| 3805 | [TYPE_USB] = { | ||
| 3806 | [NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, | ||
| 3807 | [EXTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, | ||
| 3808 | [INTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals, | ||
| 3809 | }, | ||
| 3810 | }, | ||
| 3811 | [TYPE_USB] = { | ||
| 3812 | [TYPE_NONE] = { | ||
| 3813 | [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, | ||
| 3814 | [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, | ||
| 3815 | [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, | ||
| 3816 | }, | ||
| 3817 | [TYPE_PCIE] = { | ||
| 3818 | [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, | ||
| 3819 | [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, | ||
| 3820 | [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, | ||
| 3821 | }, | ||
| 3822 | [TYPE_SGMII] = { | ||
| 3823 | [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, | ||
| 3824 | [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, | ||
| 3825 | [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, | ||
| 3826 | }, | ||
| 3827 | [TYPE_QSGMII] = { | ||
| 3828 | [NO_SSC] = &usb_100_no_ssc_rx_ln_vals, | ||
| 3829 | [EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, | ||
| 3830 | [INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals, | ||
| 3831 | }, | ||
| 3832 | }, | ||
| 3833 | }, | ||
| 1917 | }; | 3834 | }; |
| 1918 | 3835 | ||
| 1919 | static const struct of_device_id cdns_torrent_phy_of_match[] = { | 3836 | static const struct of_device_id cdns_torrent_phy_of_match[] = { |
| @@ -1,15 +1,20 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0+ | 1 | // SPDX-License-Identifier: GPL-2.0+ |
| 2 | /* Copyright (c) 2017 NXP. */ | 2 | /* Copyright (c) 2017 NXP. */ |
| 3 | 3 | ||
| 4 | #include <linux/bitfield.h> | ||
| 4 | #include <linux/clk.h> | 5 | #include <linux/clk.h> |
| 6 | #include <linux/delay.h> | ||
| 5 | #include <linux/io.h> | 7 | #include <linux/io.h> |
| 6 | #include <linux/module.h> | 8 | #include <linux/module.h> |
| 9 | #include <linux/of_platform.h> | ||
| 7 | #include <linux/phy/phy.h> | 10 | #include <linux/phy/phy.h> |
| 8 | #include <linux/platform_device.h> | 11 | #include <linux/platform_device.h> |
| 9 | #include <linux/regulator/consumer.h> | 12 | #include <linux/regulator/consumer.h> |
| 10 | 13 | ||
| 11 | #define PHY_CTRL0 0x0 | 14 | #define PHY_CTRL0 0x0 |
| 12 | #define PHY_CTRL0_REF_SSP_EN BIT(2) | 15 | #define PHY_CTRL0_REF_SSP_EN BIT(2) |
| 16 | #define PHY_CTRL0_FSEL_MASK GENMASK(10, 5) | ||
| 17 | #define PHY_CTRL0_FSEL_24M 0x2a | ||
| 13 | 18 | ||
| 14 | #define PHY_CTRL1 0x4 | 19 | #define PHY_CTRL1 0x4 |
| 15 | #define PHY_CTRL1_RESET BIT(0) | 20 | #define PHY_CTRL1_RESET BIT(0) |
| @@ -20,6 +25,11 @@ · 4 unmodified lines | |||
| 20 | 25 | ||
| 21 | #define PHY_CTRL2 0x8 | 26 | #define PHY_CTRL2 0x8 |
| 22 | #define PHY_CTRL2_TXENABLEN0 BIT(8) | 27 | #define PHY_CTRL2_TXENABLEN0 BIT(8) |
| 28 | #define PHY_CTRL2_OTG_DISABLE BIT(9) | ||
| 29 | |||
| 30 | #define PHY_CTRL6 0x18 | ||
| 31 | #define PHY_CTRL6_ALT_CLK_EN BIT(1) | ||
| 32 | #define PHY_CTRL6_ALT_CLK_SEL BIT(0) | ||
| 23 | 33 | ||
| 24 | struct imx8mq_usb_phy { | 34 | struct imx8mq_usb_phy { |
| 25 | struct phy *phy; | 35 | struct phy *phy; |
| @@ -54,6 +64,44 @@ static int imx8mq_usb_phy_init(struct phy *phy) · 28 unmodified lines | |||
| 54 | return 0; | 64 | return 0; |
| 55 | } | 65 | } |
| 56 | 66 | ||
| 67 | static int imx8mp_usb_phy_init(struct phy *phy) | ||
| 68 | { | ||
| 69 | struct imx8mq_usb_phy *imx_phy = phy_get_drvdata(phy); | ||
| 70 | u32 value; | ||
| 71 | |||
| 72 | /* USB3.0 PHY signal fsel for 24M ref */ | ||
| 73 | value = readl(imx_phy->base + PHY_CTRL0); | ||
| 74 | value &= ~PHY_CTRL0_FSEL_MASK; | ||
| 75 | value |= FIELD_PREP(PHY_CTRL0_FSEL_MASK, PHY_CTRL0_FSEL_24M); | ||
| 76 | writel(value, imx_phy->base + PHY_CTRL0); | ||
| 77 | |||
| 78 | /* Disable alt_clk_en and use internal MPLL clocks */ | ||
| 79 | value = readl(imx_phy->base + PHY_CTRL6); | ||
| 80 | value &= ~(PHY_CTRL6_ALT_CLK_SEL | PHY_CTRL6_ALT_CLK_EN); | ||
| 81 | writel(value, imx_phy->base + PHY_CTRL6); | ||
| 82 | |||
| 83 | value = readl(imx_phy->base + PHY_CTRL1); | ||
| 84 | value &= ~(PHY_CTRL1_VDATSRCENB0 | PHY_CTRL1_VDATDETENB0); | ||
| 85 | value |= PHY_CTRL1_RESET | PHY_CTRL1_ATERESET; | ||
| 86 | writel(value, imx_phy->base + PHY_CTRL1); | ||
| 87 | |||
| 88 | value = readl(imx_phy->base + PHY_CTRL0); | ||
| 89 | value |= PHY_CTRL0_REF_SSP_EN; | ||
| 90 | writel(value, imx_phy->base + PHY_CTRL0); | ||
| 91 | |||
| 92 | value = readl(imx_phy->base + PHY_CTRL2); | ||
| 93 | value |= PHY_CTRL2_TXENABLEN0 | PHY_CTRL2_OTG_DISABLE; | ||
| 94 | writel(value, imx_phy->base + PHY_CTRL2); | ||
| 95 | |||
| 96 | udelay(10); | ||
| 97 | |||
| 98 | value = readl(imx_phy->base + PHY_CTRL1); | ||
| 99 | value &= ~(PHY_CTRL1_RESET | PHY_CTRL1_ATERESET); | ||
| 100 | writel(value, imx_phy->base + PHY_CTRL1); | ||
| 101 | |||
| 102 | return 0; | ||
| 103 | } | ||
| 104 | |||
| 57 | static int imx8mq_phy_power_on(struct phy *phy) | 105 | static int imx8mq_phy_power_on(struct phy *phy) |
| 58 | { | 106 | { |
| 59 | struct imx8mq_usb_phy *imx_phy = phy_get_drvdata(phy); | 107 | struct imx8mq_usb_phy *imx_phy = phy_get_drvdata(phy); |
| @@ -76,19 +124,36 @@ static int imx8mq_phy_power_off(struct phy *phy) · 16 unmodified lines | |||
| 76 | return 0; | 124 | return 0; |
| 77 | } | 125 | } |
| 78 | 126 | ||
| 79 | static struct phy_ops imx8mq_usb_phy_ops = { | 127 | static const struct phy_ops imx8mq_usb_phy_ops = { |
| 80 | .init = imx8mq_usb_phy_init, | 128 | .init = imx8mq_usb_phy_init, |
| 81 | .power_on = imx8mq_phy_power_on, | 129 | .power_on = imx8mq_phy_power_on, |
| 82 | .power_off = imx8mq_phy_power_off, | 130 | .power_off = imx8mq_phy_power_off, |
| 83 | .owner = THIS_MODULE, | 131 | .owner = THIS_MODULE, |
| 84 | }; | 132 | }; |
| 85 | 133 | ||
| 134 | static struct phy_ops imx8mp_usb_phy_ops = { | ||
| 135 | .init = imx8mp_usb_phy_init, | ||
| 136 | .power_on = imx8mq_phy_power_on, | ||
| 137 | .power_off = imx8mq_phy_power_off, | ||
| 138 | .owner = THIS_MODULE, | ||
| 139 | }; | ||
| 140 | |||
| 141 | static const struct of_device_id imx8mq_usb_phy_of_match[] = { | ||
| 142 | {.compatible = "fsl,imx8mq-usb-phy", | ||
| 143 | .data = &imx8mq_usb_phy_ops,}, | ||
| 144 | {.compatible = "fsl,imx8mp-usb-phy", | ||
| 145 | .data = &imx8mp_usb_phy_ops,}, | ||
| 146 | { } | ||
| 147 | }; | ||
| 148 | MODULE_DEVICE_TABLE(of, imx8mq_usb_phy_of_match); | ||
| 149 | |||
| 86 | static int imx8mq_usb_phy_probe(struct platform_device *pdev) | 150 | static int imx8mq_usb_phy_probe(struct platform_device *pdev) |
| 87 | { | 151 | { |
| 88 | struct phy_provider *phy_provider; | 152 | struct phy_provider *phy_provider; |
| 89 | struct device *dev = &pdev->dev; | 153 | struct device *dev = &pdev->dev; |
| 90 | struct imx8mq_usb_phy *imx_phy; | 154 | struct imx8mq_usb_phy *imx_phy; |
| 91 | struct resource *res; | 155 | struct resource *res; |
| 156 | const struct phy_ops *phy_ops; | ||
| 92 | 157 | ||
| 93 | imx_phy = devm_kzalloc(dev, sizeof(*imx_phy), GFP_KERNEL); | 158 | imx_phy = devm_kzalloc(dev, sizeof(*imx_phy), GFP_KERNEL); |
| 94 | if (!imx_phy) | 159 | if (!imx_phy) |
| @@ -105,7 +170,11 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev) · 10 unmodified lines | |||
| 105 | if (IS_ERR(imx_phy->base)) | 170 | if (IS_ERR(imx_phy->base)) |
| 106 | return PTR_ERR(imx_phy->base); | 171 | return PTR_ERR(imx_phy->base); |
| 107 | 172 | ||
| 108 | imx_phy->phy = devm_phy_create(dev, NULL, &imx8mq_usb_phy_ops); | 173 | phy_ops = of_device_get_match_data(dev); |
| 174 | if (!phy_ops) | ||
| 175 | return -EINVAL; | ||
| 176 | |||
| 177 | imx_phy->phy = devm_phy_create(dev, NULL, phy_ops); | ||
| 109 | if (IS_ERR(imx_phy->phy)) | 178 | if (IS_ERR(imx_phy->phy)) |
| 110 | return PTR_ERR(imx_phy->phy); | 179 | return PTR_ERR(imx_phy->phy); |
| 111 | 180 | ||
| @@ -120,12 +189,6 @@ static int imx8mq_usb_phy_probe(struct platform_device *pdev) · 8 unmodified lines | |||
| 120 | return PTR_ERR_OR_ZERO(phy_provider); | 189 | return PTR_ERR_OR_ZERO(phy_provider); |
| 121 | } | 190 | } |
| 122 | 191 | ||
| 123 | static const struct of_device_id imx8mq_usb_phy_of_match[] = { | ||
| 124 | {.compatible = "fsl,imx8mq-usb-phy",}, | ||
| 125 | { }, | ||
| 126 | }; | ||
| 127 | MODULE_DEVICE_TABLE(of, imx8mq_usb_phy_of_match); | ||
| 128 | |||
| 129 | static struct platform_driver imx8mq_usb_phy_driver = { | 192 | static struct platform_driver imx8mq_usb_phy_driver = { |
| 130 | .probe = imx8mq_usb_phy_probe, | 193 | .probe = imx8mq_usb_phy_probe, |
| 131 | .driver = { | 194 | .driver = { |
| @@ -161,7 +161,7 @@ out: · 160 unmodified lines | |||
| 161 | return ret; | 161 | return ret; |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | static struct phy_ops hi3660_phy_ops = { | 164 | static const struct phy_ops hi3660_phy_ops = { |
| 165 | .init = hi3660_phy_init, | 165 | .init = hi3660_phy_init, |
| 166 | .exit = hi3660_phy_exit, | 166 | .exit = hi3660_phy_exit, |
| 167 | .owner = THIS_MODULE, | 167 | .owner = THIS_MODULE, |
| @@ -1,9 +1,21 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | # | 2 | # |
| 3 | # Phy drivers for Intel Lightning Mountain(LGM) platform | 3 | # Phy drivers for Intel platforms |
| 4 | # | 4 | # |
| 5 | config PHY_INTEL_COMBO | 5 | config PHY_INTEL_KEEMBAY_EMMC |
| 6 | bool "Intel ComboPHY driver" | 6 | tristate "Intel Keem Bay EMMC PHY driver" |
| 7 | depends on (OF && ARM64) || COMPILE_TEST | ||
| 8 | depends on HAS_IOMEM | ||
| 9 | select GENERIC_PHY | ||
| 10 | select REGMAP_MMIO | ||
| 11 | help | ||
| 12 | Choose this option if you have an Intel Keem Bay SoC. | ||
| 13 | |||
| 14 | To compile this driver as a module, choose M here: the module | ||
| 15 | will be called phy-keembay-emmc.ko. | ||
| 16 | |||
| 17 | config PHY_INTEL_LGM_COMBO | ||
| 18 | bool "Intel Lightning Mountain ComboPHY driver" | ||
| 7 | depends on X86 || COMPILE_TEST | 19 | depends on X86 || COMPILE_TEST |
| 8 | depends on OF && HAS_IOMEM | 20 | depends on OF && HAS_IOMEM |
| 9 | select MFD_SYSCON | 21 | select MFD_SYSCON |
| @@ -16,8 +28,8 @@ config PHY_INTEL_COMBO · 6 unmodified lines | |||
| 16 | chipsets which provides PHYs for various controllers, EMAC, | 28 | chipsets which provides PHYs for various controllers, EMAC, |
| 17 | SATA and PCIe. | 29 | SATA and PCIe. |
| 18 | 30 | ||
| 19 | config PHY_INTEL_EMMC | 31 | config PHY_INTEL_LGM_EMMC |
| 20 | tristate "Intel EMMC PHY driver" | 32 | tristate "Intel Lightning Mountain EMMC PHY driver" |
| 21 | depends on X86 || COMPILE_TEST | 33 | depends on X86 || COMPILE_TEST |
| 22 | select GENERIC_PHY | 34 | select GENERIC_PHY |
| 23 | help | 35 | help |
| @@ -1,3 +1,4 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | obj-$(CONFIG_PHY_INTEL_COMBO) += phy-intel-combo.o | 2 | obj-$(CONFIG_PHY_INTEL_KEEMBAY_EMMC) += phy-intel-keembay-emmc.o |
| 3 | obj-$(CONFIG_PHY_INTEL_EMMC) += phy-intel-emmc.o | 3 | obj-$(CONFIG_PHY_INTEL_LGM_COMBO) += phy-intel-lgm-combo.o |
| 4 | obj-$(CONFIG_PHY_INTEL_LGM_EMMC) += phy-intel-lgm-emmc.o | ||
| @@ -0,0 +1,307 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * Intel Keem Bay eMMC PHY driver | ||
| 4 | * Copyright (C) 2020 Intel Corporation | ||
| 5 | */ | ||
| 6 | |||
| 7 | #include <linux/bitfield.h> | ||
| 8 | #include <linux/clk.h> | ||
| 9 | #include <linux/delay.h> | ||
| 10 | #include <linux/mfd/syscon.h> | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/of.h> | ||
| 13 | #include <linux/of_address.h> | ||
| 14 | #include <linux/phy/phy.h> | ||
| 15 | #include <linux/platform_device.h> | ||
| 16 | #include <linux/regmap.h> | ||
| 17 | |||
| 18 | /* eMMC/SD/SDIO core/phy configuration registers */ | ||
| 19 | #define PHY_CFG_0 0x24 | ||
| 20 | #define SEL_DLY_TXCLK_MASK BIT(29) | ||
| 21 | #define OTAP_DLY_ENA_MASK BIT(27) | ||
| 22 | #define OTAP_DLY_SEL_MASK GENMASK(26, 23) | ||
| 23 | #define DLL_EN_MASK BIT(10) | ||
| 24 | #define PWR_DOWN_MASK BIT(0) | ||
| 25 | |||
| 26 | #define PHY_CFG_2 0x2c | ||
| 27 | #define SEL_FREQ_MASK GENMASK(12, 10) | ||
| 28 | |||
| 29 | #define PHY_STAT 0x40 | ||
| 30 | #define CAL_DONE_MASK BIT(6) | ||
| 31 | #define IS_CALDONE(x) ((x) & CAL_DONE_MASK) | ||
| 32 | #define DLL_RDY_MASK BIT(5) | ||
| 33 | #define IS_DLLRDY(x) ((x) & DLL_RDY_MASK) | ||
| 34 | |||
| 35 | /* From ACS_eMMC51_16nFFC_RO1100_Userguide_v1p0.pdf p17 */ | ||
| 36 | #define FREQSEL_200M_170M 0x0 | ||
| 37 | #define FREQSEL_170M_140M 0x1 | ||
| 38 | #define FREQSEL_140M_110M 0x2 | ||
| 39 | #define FREQSEL_110M_80M 0x3 | ||
| 40 | #define FREQSEL_80M_50M 0x4 | ||
| 41 | |||
| 42 | struct keembay_emmc_phy { | ||
| 43 | struct regmap *syscfg; | ||
| 44 | struct clk *emmcclk; | ||
| 45 | }; | ||
| 46 | |||
| 47 | static const struct regmap_config keembay_regmap_config = { | ||
| 48 | .reg_bits = 32, | ||
| 49 | .val_bits = 32, | ||
| 50 | .reg_stride = 4, | ||
| 51 | }; | ||
| 52 | |||
| 53 | static int keembay_emmc_phy_power(struct phy *phy, bool on_off) | ||
| 54 | { | ||
| 55 | struct keembay_emmc_phy *priv = phy_get_drvdata(phy); | ||
| 56 | unsigned int caldone; | ||
| 57 | unsigned int dllrdy; | ||
| 58 | unsigned int freqsel; | ||
| 59 | unsigned int mhz; | ||
| 60 | int ret; | ||
| 61 | |||
| 62 | /* | ||
| 63 | * Keep phyctrl_pdb and phyctrl_endll low to allow | ||
| 64 | * initialization of CALIO state M/C DFFs | ||
| 65 | */ | ||
| 66 | ret = regmap_update_bits(priv->syscfg, PHY_CFG_0, PWR_DOWN_MASK, | ||
| 67 | FIELD_PREP(PWR_DOWN_MASK, 0)); | ||
| 68 | if (ret) { | ||
| 69 | dev_err(&phy->dev, "CALIO power down bar failed: %d\n", ret); | ||
| 70 | return ret; | ||
| 71 | } | ||
| 72 | |||
| 73 | ret = regmap_update_bits(priv->syscfg, PHY_CFG_0, DLL_EN_MASK, | ||
| 74 | FIELD_PREP(DLL_EN_MASK, 0)); | ||
| 75 | if (ret) { | ||
| 76 | dev_err(&phy->dev, "turn off the dll failed: %d\n", ret); | ||
| 77 | return ret; | ||
| 78 | } | ||
| 79 | |||
| 80 | /* Already finish power off above */ | ||
| 81 | if (!on_off) | ||
| 82 | return 0; | ||
| 83 | |||
| 84 | mhz = DIV_ROUND_CLOSEST(clk_get_rate(priv->emmcclk), 1000000); | ||
| 85 | if (mhz <= 200 && mhz >= 170) | ||
| 86 | freqsel = FREQSEL_200M_170M; | ||
| 87 | else if (mhz <= 170 && mhz >= 140) | ||
| 88 | freqsel = FREQSEL_170M_140M; | ||
| 89 | else if (mhz <= 140 && mhz >= 110) | ||
| 90 | freqsel = FREQSEL_140M_110M; | ||
| 91 | else if (mhz <= 110 && mhz >= 80) | ||
| 92 | freqsel = FREQSEL_110M_80M; | ||
| 93 | else if (mhz <= 80 && mhz >= 50) | ||
| 94 | freqsel = FREQSEL_80M_50M; | ||
| 95 | else | ||
| 96 | freqsel = 0x0; | ||
| 97 | |||
| 98 | if (mhz < 50 || mhz > 200) | ||
| 99 | dev_warn(&phy->dev, "Unsupported rate: %d MHz\n", mhz); | ||
| 100 | |||
| 101 | /* | ||
| 102 | * According to the user manual, calpad calibration | ||
| 103 | * cycle takes more than 2us without the minimal recommended | ||
| 104 | * value, so we may need a little margin here | ||
| 105 | */ | ||
| 106 | udelay(5); | ||
| 107 | |||
| 108 | ret = regmap_update_bits(priv->syscfg, PHY_CFG_0, PWR_DOWN_MASK, | ||
| 109 | FIELD_PREP(PWR_DOWN_MASK, 1)); | ||
| 110 | if (ret) { | ||
| 111 | dev_err(&phy->dev, "CALIO power down bar failed: %d\n", ret); | ||
| 112 | return ret; | ||
| 113 | } | ||
| 114 | |||
| 115 | /* | ||
| 116 | * According to the user manual, it asks driver to wait 5us for | ||
| 117 | * calpad busy trimming. However it is documented that this value is | ||
| 118 | * PVT(A.K.A. process, voltage and temperature) relevant, so some | ||
| 119 | * failure cases are found which indicates we should be more tolerant | ||
| 120 | * to calpad busy trimming. | ||
| 121 | */ | ||
| 122 | ret = regmap_read_poll_timeout(priv->syscfg, PHY_STAT, | ||
| 123 | caldone, IS_CALDONE(caldone), | ||
| 124 | 0, 50); | ||
| 125 | if (ret) { | ||
| 126 | dev_err(&phy->dev, "caldone failed, ret=%d\n", ret); | ||
| 127 | return ret; | ||
| 128 | } | ||
| 129 | |||
| 130 | /* Set the frequency of the DLL operation */ | ||
| 131 | ret = regmap_update_bits(priv->syscfg, PHY_CFG_2, SEL_FREQ_MASK, | ||
| 132 | FIELD_PREP(SEL_FREQ_MASK, freqsel)); | ||
| 133 | if (ret) { | ||
| 134 | dev_err(&phy->dev, "set the frequency of dll failed:%d\n", ret); | ||
| 135 | return ret; | ||
| 136 | } | ||
| 137 | |||
| 138 | /* Turn on the DLL */ | ||
| 139 | ret = regmap_update_bits(priv->syscfg, PHY_CFG_0, DLL_EN_MASK, | ||
| 140 | FIELD_PREP(DLL_EN_MASK, 1)); | ||
| 141 | if (ret) { | ||
| 142 | dev_err(&phy->dev, "turn on the dll failed: %d\n", ret); | ||
| 143 | return ret; | ||
| 144 | } | ||
| 145 | |||
| 146 | /* | ||
| 147 | * We turned on the DLL even though the rate was 0 because we the | ||
| 148 | * clock might be turned on later. ...but we can't wait for the DLL | ||
| 149 | * to lock when the rate is 0 because it will never lock with no | ||
| 150 | * input clock. | ||
| 151 | * | ||
| 152 | * Technically we should be checking the lock later when the clock | ||
| 153 | * is turned on, but for now we won't. | ||
| 154 | */ | ||
| 155 | if (mhz == 0) | ||
| 156 | return 0; | ||
| 157 | |||
| 158 | /* | ||
| 159 | * After enabling analog DLL circuits docs say that we need 10.2 us if | ||
| 160 | * our source clock is at 50 MHz and that lock time scales linearly | ||
| 161 | * with clock speed. If we are powering on the PHY and the card clock | ||
| 162 | * is super slow (like 100kHz) this could take as long as 5.1 ms as | ||
| 163 | * per the math: 10.2 us * (50000000 Hz / 100000 Hz) => 5.1 ms | ||
| 164 | * hopefully we won't be running at 100 kHz, but we should still make | ||
| 165 | * sure we wait long enough. | ||
| 166 | * | ||
| 167 | * NOTE: There appear to be corner cases where the DLL seems to take | ||
| 168 | * extra long to lock for reasons that aren't understood. In some | ||
| 169 | * extreme cases we've seen it take up to over 10ms (!). We'll be | ||
| 170 | * generous and give it 50ms. | ||
| 171 | */ | ||
| 172 | ret = regmap_read_poll_timeout(priv->syscfg, PHY_STAT, | ||
| 173 | dllrdy, IS_DLLRDY(dllrdy), | ||
| 174 | 0, 50 * USEC_PER_MSEC); | ||
| 175 | if (ret) | ||
| 176 | dev_err(&phy->dev, "dllrdy failed, ret=%d\n", ret); | ||
| 177 | |||
| 178 | return ret; | ||
| 179 | } | ||
| 180 | |||
| 181 | static int keembay_emmc_phy_init(struct phy *phy) | ||
| 182 | { | ||
| 183 | struct keembay_emmc_phy *priv = phy_get_drvdata(phy); | ||
| 184 | |||
| 185 | /* | ||
| 186 | * We purposely get the clock here and not in probe to avoid the | ||
| 187 | * circular dependency problem. We expect: | ||
| 188 | * - PHY driver to probe | ||
| 189 | * - SDHCI driver to start probe | ||
| 190 | * - SDHCI driver to register it's clock | ||
| 191 | * - SDHCI driver to get the PHY | ||
| 192 | * - SDHCI driver to init the PHY | ||
| 193 | * | ||
| 194 | * The clock is optional, so upon any error just return it like | ||
| 195 | * any other error to user. | ||
| 196 | */ | ||
| 197 | priv->emmcclk = clk_get_optional(&phy->dev, "emmcclk"); | ||
| 198 | |||
| 199 | return PTR_ERR_OR_ZERO(priv->emmcclk); | ||
| 200 | } | ||
| 201 | |||
| 202 | static int keembay_emmc_phy_exit(struct phy *phy) | ||
| 203 | { | ||
| 204 | struct keembay_emmc_phy *priv = phy_get_drvdata(phy); | ||
| 205 | |||
| 206 | clk_put(priv->emmcclk); | ||
| 207 | |||
| 208 | return 0; | ||
| 209 | }; | ||
| 210 | |||
| 211 | static int keembay_emmc_phy_power_on(struct phy *phy) | ||
| 212 | { | ||
| 213 | struct keembay_emmc_phy *priv = phy_get_drvdata(phy); | ||
| 214 | int ret; | ||
| 215 | |||
| 216 | /* Delay chain based txclk: enable */ | ||
| 217 | ret = regmap_update_bits(priv->syscfg, PHY_CFG_0, SEL_DLY_TXCLK_MASK, | ||
| 218 | FIELD_PREP(SEL_DLY_TXCLK_MASK, 1)); | ||
| 219 | if (ret) { | ||
| 220 | dev_err(&phy->dev, "ERROR: delay chain txclk set: %d\n", ret); | ||
| 221 | return ret; | ||
| 222 | } | ||
| 223 | |||
| 224 | /* Output tap delay: enable */ | ||
| 225 | ret = regmap_update_bits(priv->syscfg, PHY_CFG_0, OTAP_DLY_ENA_MASK, | ||
| 226 | FIELD_PREP(OTAP_DLY_ENA_MASK, 1)); | ||
| 227 | if (ret) { | ||
| 228 | dev_err(&phy->dev, "ERROR: output tap delay set: %d\n", ret); | ||
| 229 | return ret; | ||
| 230 | } | ||
| 231 | |||
| 232 | /* Output tap delay */ | ||
| 233 | ret = regmap_update_bits(priv->syscfg, PHY_CFG_0, OTAP_DLY_SEL_MASK, | ||
| 234 | FIELD_PREP(OTAP_DLY_SEL_MASK, 2)); | ||
| 235 | if (ret) { | ||
| 236 | dev_err(&phy->dev, "ERROR: output tap delay select: %d\n", ret); | ||
| 237 | return ret; | ||
| 238 | } | ||
| 239 | |||
| 240 | /* Power up eMMC phy analog blocks */ | ||
| 241 | return keembay_emmc_phy_power(phy, true); | ||
| 242 | } | ||
| 243 | |||
| 244 | static int keembay_emmc_phy_power_off(struct phy *phy) | ||
| 245 | { | ||
| 246 | /* Power down eMMC phy analog blocks */ | ||
| 247 | return keembay_emmc_phy_power(phy, false); | ||
| 248 | } | ||
| 249 | |||
| 250 | static const struct phy_ops ops = { | ||
| 251 | .init = keembay_emmc_phy_init, | ||
| 252 | .exit = keembay_emmc_phy_exit, | ||
| 253 | .power_on = keembay_emmc_phy_power_on, | ||
| 254 | .power_off = keembay_emmc_phy_power_off, | ||
| 255 | .owner = THIS_MODULE, | ||
| 256 | }; | ||
| 257 | |||
| 258 | static int keembay_emmc_phy_probe(struct platform_device *pdev) | ||
| 259 | { | ||
| 260 | struct device *dev = &pdev->dev; | ||
| 261 | struct device_node *np = dev->of_node; | ||
| 262 | struct keembay_emmc_phy *priv; | ||
| 263 | struct phy *generic_phy; | ||
| 264 | struct phy_provider *phy_provider; | ||
| 265 | void __iomem *base; | ||
| 266 | |||
| 267 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
| 268 | if (!priv) | ||
| 269 | return -ENOMEM; | ||
| 270 | |||
| 271 | base = devm_platform_ioremap_resource(pdev, 0); | ||
| 272 | if (IS_ERR(base)) | ||
| 273 | return PTR_ERR(base); | ||
| 274 | |||
| 275 | priv->syscfg = devm_regmap_init_mmio(dev, base, &keembay_regmap_config); | ||
| 276 | if (IS_ERR(priv->syscfg)) | ||
| 277 | return PTR_ERR(priv->syscfg); | ||
| 278 | |||
| 279 | generic_phy = devm_phy_create(dev, np, &ops); | ||
| 280 | if (IS_ERR(generic_phy)) | ||
| 281 | return dev_err_probe(dev, PTR_ERR(generic_phy), | ||
| 282 | "failed to create PHY\n"); | ||
| 283 | |||
| 284 | phy_set_drvdata(generic_phy, priv); | ||
| 285 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | ||
| 286 | |||
| 287 | return PTR_ERR_OR_ZERO(phy_provider); | ||
| 288 | } | ||
| 289 | |||
| 290 | static const struct of_device_id keembay_emmc_phy_dt_ids[] = { | ||
| 291 | { .compatible = "intel,keembay-emmc-phy" }, | ||
| 292 | {} | ||
| 293 | }; | ||
| 294 | MODULE_DEVICE_TABLE(of, keembay_emmc_phy_dt_ids); | ||
| 295 | |||
| 296 | static struct platform_driver keembay_emmc_phy_driver = { | ||
| 297 | .probe = keembay_emmc_phy_probe, | ||
| 298 | .driver = { | ||
| 299 | .name = "keembay-emmc-phy", | ||
| 300 | .of_match_table = keembay_emmc_phy_dt_ids, | ||
| 301 | }, | ||
| 302 | }; | ||
| 303 | module_platform_driver(keembay_emmc_phy_driver); | ||
| 304 | |||
| 305 | MODULE_AUTHOR("Wan Ahmad Zainie <wan.ahmad.zainie.wan.mohamad@intel.com>"); | ||
| 306 | MODULE_DESCRIPTION("Intel Keem Bay eMMC PHY driver"); | ||
| 307 | MODULE_LICENSE("GPL v2"); | ||
File renamed without changes.
File renamed without changes.
| @@ -141,7 +141,7 @@ static int ltq_rcu_usb2_phy_power_off(struct phy *phy) · 140 unmodified lines | |||
| 141 | return 0; | 141 | return 0; |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | static struct phy_ops ltq_rcu_usb2_phy_ops = { | 144 | static const struct phy_ops ltq_rcu_usb2_phy_ops = { |
| 145 | .init = ltq_rcu_usb2_phy_init, | 145 | .init = ltq_rcu_usb2_phy_init, |
| 146 | .power_on = ltq_rcu_usb2_phy_power_on, | 146 | .power_on = ltq_rcu_usb2_phy_power_on, |
| 147 | .power_off = ltq_rcu_usb2_phy_power_off, | 147 | .power_off = ltq_rcu_usb2_phy_power_off, |
| @@ -349,7 +349,7 @@ static int ltq_vrx200_pcie_phy_power_off(struct phy *phy) · 348 unmodified lines | |||
| 349 | return 0; | 349 | return 0; |
| 350 | } | 350 | } |
| 351 | 351 | ||
| 352 | static struct phy_ops ltq_vrx200_pcie_phy_ops = { | 352 | static const struct phy_ops ltq_vrx200_pcie_phy_ops = { |
| 353 | .init = ltq_vrx200_pcie_phy_init, | 353 | .init = ltq_vrx200_pcie_phy_init, |
| 354 | .exit = ltq_vrx200_pcie_phy_exit, | 354 | .exit = ltq_vrx200_pcie_phy_exit, |
| 355 | .power_on = ltq_vrx200_pcie_phy_power_on, | 355 | .power_on = ltq_vrx200_pcie_phy_power_on, |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | |||
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | #include <linux/of.h> | 13 | #include <linux/of.h> |
| 14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
| 15 | #include <linux/iopoll.h> | ||
| 15 | #include <linux/err.h> | 16 | #include <linux/err.h> |
| 16 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
| 17 | #include <linux/module.h> | 18 | #include <linux/module.h> |
| @@ -44,15 +45,12 @@ struct mv_hsic_phy { · 26 unmodified lines | |||
| 44 | struct clk *clk; | 45 | struct clk *clk; |
| 45 | }; | 46 | }; |
| 46 | 47 | ||
| 47 | static bool wait_for_reg(void __iomem *reg, u32 mask, unsigned long timeout) | 48 | static int wait_for_reg(void __iomem *reg, u32 mask, u32 ms) |
| 48 | { | 49 | { |
| 49 | timeout += jiffies; | 50 | u32 val; |
| 50 | while (time_is_after_eq_jiffies(timeout)) { | 51 | |
| 51 | if ((readl(reg) & mask) == mask) | 52 | return readl_poll_timeout(reg, val, ((val & mask) == mask), |
| 52 | return true; | 53 | 1000, 1000 * ms); |
| 53 | msleep(1); | ||
| 54 | } | ||
| 55 | return false; | ||
| 56 | } | 54 | } |
| 57 | 55 | ||
| 58 | static int mv_hsic_phy_init(struct phy *phy) | 56 | static int mv_hsic_phy_init(struct phy *phy) |
| @@ -60,6 +58,7 @@ static int mv_hsic_phy_init(struct phy *phy) · 1 unmodified line | |||
| 60 | struct mv_hsic_phy *mv_phy = phy_get_drvdata(phy); | 58 | struct mv_hsic_phy *mv_phy = phy_get_drvdata(phy); |
| 61 | struct platform_device *pdev = mv_phy->pdev; | 59 | struct platform_device *pdev = mv_phy->pdev; |
| 62 | void __iomem *base = mv_phy->base; | 60 | void __iomem *base = mv_phy->base; |
| 61 | int ret; | ||
| 63 | 62 | ||
| 64 | clk_prepare_enable(mv_phy->clk); | 63 | clk_prepare_enable(mv_phy->clk); |
| 65 | 64 | ||
| @@ -75,14 +74,14 @@ static int mv_hsic_phy_init(struct phy *phy) · 9 unmodified lines | |||
| 75 | base + PHY_28NM_HSIC_PLL_CTRL2); | 74 | base + PHY_28NM_HSIC_PLL_CTRL2); |
| 76 | 75 | ||
| 77 | /* Make sure PHY PLL is locked */ | 76 | /* Make sure PHY PLL is locked */ |
| 78 | if (!wait_for_reg(base + PHY_28NM_HSIC_PLL_CTRL2, | 77 | ret = wait_for_reg(base + PHY_28NM_HSIC_PLL_CTRL2, |
| 79 | PHY_28NM_HSIC_H2S_PLL_LOCK, HZ / 10)) { | 78 | PHY_28NM_HSIC_H2S_PLL_LOCK, 100); |
| 79 | if (ret) { | ||
| 80 | dev_err(&pdev->dev, "HSIC PHY PLL not locked after 100mS."); | 80 | dev_err(&pdev->dev, "HSIC PHY PLL not locked after 100mS."); |
| 81 | clk_disable_unprepare(mv_phy->clk); | 81 | clk_disable_unprepare(mv_phy->clk); |
| 82 | return -ETIMEDOUT; | ||
| 83 | } | 82 | } |
| 84 | 83 | ||
| 85 | return 0; | 84 | return ret; |
| 86 | } | 85 | } |
| 87 | 86 | ||
| 88 | static int mv_hsic_phy_power_on(struct phy *phy) | 87 | static int mv_hsic_phy_power_on(struct phy *phy) |
| @@ -91,6 +90,7 @@ static int mv_hsic_phy_power_on(struct phy *phy) · 2 unmodified lines | |||
| 91 | struct platform_device *pdev = mv_phy->pdev; | 90 | struct platform_device *pdev = mv_phy->pdev; |
| 92 | void __iomem *base = mv_phy->base; | 91 | void __iomem *base = mv_phy->base; |
| 93 | u32 reg; | 92 | u32 reg; |
| 93 | int ret; | ||
| 94 | 94 | ||
| 95 | reg = readl(base + PHY_28NM_HSIC_CTRL); | 95 | reg = readl(base + PHY_28NM_HSIC_CTRL); |
| 96 | /* Avoid SE0 state when resume for some device will take it as reset */ | 96 | /* Avoid SE0 state when resume for some device will take it as reset */ |
| @@ -108,20 +108,20 @@ static int mv_hsic_phy_power_on(struct phy *phy) · 11 unmodified lines | |||
| 108 | */ | 108 | */ |
| 109 | 109 | ||
| 110 | /* Make sure PHY Calibration is ready */ | 110 | /* Make sure PHY Calibration is ready */ |
| 111 | if (!wait_for_reg(base + PHY_28NM_HSIC_IMPCAL_CAL, | 111 | ret = wait_for_reg(base + PHY_28NM_HSIC_IMPCAL_CAL, |
| 112 | PHY_28NM_HSIC_H2S_IMPCAL_DONE, HZ / 10)) { | 112 | PHY_28NM_HSIC_H2S_IMPCAL_DONE, 100); |
| 113 | if (ret) { | ||
| 113 | dev_warn(&pdev->dev, "HSIC PHY READY not set after 100mS."); | 114 | dev_warn(&pdev->dev, "HSIC PHY READY not set after 100mS."); |
| 114 | return -ETIMEDOUT; | 115 | return ret; |
| 115 | } | 116 | } |
| 116 | 117 | ||
| 117 | /* Waiting for HSIC connect int*/ | 118 | /* Waiting for HSIC connect int*/ |
| 118 | if (!wait_for_reg(base + PHY_28NM_HSIC_INT, | 119 | ret = wait_for_reg(base + PHY_28NM_HSIC_INT, |
| 119 | PHY_28NM_HSIC_CONNECT_INT, HZ / 5)) { | 120 | PHY_28NM_HSIC_CONNECT_INT, 200); |
| 121 | if (ret) | ||
| 120 | dev_warn(&pdev->dev, "HSIC wait for connect interrupt timeout."); | 122 | dev_warn(&pdev->dev, "HSIC wait for connect interrupt timeout."); |
| 121 | return -ETIMEDOUT; | ||
| 122 | } | ||
| 123 | 123 | ||
| 124 | return 0; | 124 | return ret; |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | static int mv_hsic_phy_power_off(struct phy *phy) | 127 | static int mv_hsic_phy_power_off(struct phy *phy) |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | |||
| 13 | #include <linux/of.h> | 13 | #include <linux/of.h> |
| 14 | #include <linux/of_device.h> | 14 | #include <linux/of_device.h> |
| 15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
| 16 | #include <linux/iopoll.h> | ||
| 16 | #include <linux/err.h> | 17 | #include <linux/err.h> |
| 17 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
| 18 | #include <linux/module.h> | 19 | #include <linux/module.h> |
| @@ -138,15 +139,12 @@ struct mv_usb2_phy { · 119 unmodified lines | |||
| 138 | struct clk *clk; | 139 | struct clk *clk; |
| 139 | }; | 140 | }; |
| 140 | 141 | ||
| 141 | static bool wait_for_reg(void __iomem *reg, u32 mask, unsigned long timeout) | 142 | static int wait_for_reg(void __iomem *reg, u32 mask, u32 ms) |
| 142 | { | 143 | { |
| 143 | timeout += jiffies; | 144 | u32 val; |
| 144 | while (time_is_after_eq_jiffies(timeout)) { | 145 | |
| 145 | if ((readl(reg) & mask) == mask) | 146 | return readl_poll_timeout(reg, val, ((val & mask) == mask), |
| 146 | return true; | 147 | 1000, 1000 * ms); |
| 147 | msleep(1); | ||
| 148 | } | ||
| 149 | return false; | ||
| 150 | } | 148 | } |
| 151 | 149 | ||
| 152 | static int mv_usb2_phy_28nm_init(struct phy *phy) | 150 | static int mv_usb2_phy_28nm_init(struct phy *phy) |
| @@ -208,24 +206,23 @@ static int mv_usb2_phy_28nm_init(struct phy *phy) · 55 unmodified lines | |||
| 208 | */ | 206 | */ |
| 209 | 207 | ||
| 210 | /* Make sure PHY Calibration is ready */ | 208 | /* Make sure PHY Calibration is ready */ |
| 211 | if (!wait_for_reg(base + PHY_28NM_CAL_REG, | 209 | ret = wait_for_reg(base + PHY_28NM_CAL_REG, |
| 212 | PHY_28NM_PLL_PLLCAL_DONE | PHY_28NM_PLL_IMPCAL_DONE, | 210 | PHY_28NM_PLL_PLLCAL_DONE | PHY_28NM_PLL_IMPCAL_DONE, |
| 213 | HZ / 10)) { | 211 | 100); |
| 212 | if (ret) { | ||
| 214 | dev_warn(&pdev->dev, "USB PHY PLL calibrate not done after 100mS."); | 213 | dev_warn(&pdev->dev, "USB PHY PLL calibrate not done after 100mS."); |
| 215 | ret = -ETIMEDOUT; | ||
| 216 | goto err_clk; | 214 | goto err_clk; |
| 217 | } | 215 | } |
| 218 | if (!wait_for_reg(base + PHY_28NM_RX_REG1, | 216 | ret = wait_for_reg(base + PHY_28NM_RX_REG1, |
| 219 | PHY_28NM_RX_SQCAL_DONE, HZ / 10)) { | 217 | PHY_28NM_RX_SQCAL_DONE, 100); |
| 218 | if (ret) { | ||
| 220 | dev_warn(&pdev->dev, "USB PHY RX SQ calibrate not done after 100mS."); | 219 | dev_warn(&pdev->dev, "USB PHY RX SQ calibrate not done after 100mS."); |
| 221 | ret = -ETIMEDOUT; | ||
| 222 | goto err_clk; | 220 | goto err_clk; |
| 223 | } | 221 | } |
| 224 | /* Make sure PHY PLL is ready */ | 222 | /* Make sure PHY PLL is ready */ |
| 225 | if (!wait_for_reg(base + PHY_28NM_PLL_REG0, | 223 | ret = wait_for_reg(base + PHY_28NM_PLL_REG0, PHY_28NM_PLL_READY, 100); |
| 226 | PHY_28NM_PLL_READY, HZ / 10)) { | 224 | if (ret) { |
| 227 | dev_warn(&pdev->dev, "PLL_READY not set after 100mS."); | 225 | dev_warn(&pdev->dev, "PLL_READY not set after 100mS."); |
| 228 | ret = -ETIMEDOUT; | ||
| 229 | goto err_clk; | 226 | goto err_clk; |
| 230 | } | 227 | } |
| 231 | 228 | ||
| @@ -0,0 +1,284 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Intel LGM USB PHY driver | ||
| 4 | * | ||
| 5 | * Copyright (C) 2020 Intel Corporation. | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include <linux/bitfield.h> | ||
| 9 | #include <linux/delay.h> | ||
| 10 | #include <linux/iopoll.h> | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/of.h> | ||
| 13 | #include <linux/platform_device.h> | ||
| 14 | #include <linux/regulator/consumer.h> | ||
| 15 | #include <linux/reset.h> | ||
| 16 | #include <linux/usb/phy.h> | ||
| 17 | #include <linux/workqueue.h> | ||
| 18 | |||
| 19 | #define CTRL1_OFFSET 0x14 | ||
| 20 | #define SRAM_EXT_LD_DONE BIT(25) | ||
| 21 | #define SRAM_INIT_DONE BIT(26) | ||
| 22 | |||
| 23 | #define TCPC_OFFSET 0x1014 | ||
| 24 | #define TCPC_MUX_CTL GENMASK(1, 0) | ||
| 25 | #define MUX_NC 0 | ||
| 26 | #define MUX_USB 1 | ||
| 27 | #define MUX_DP 2 | ||
| 28 | #define MUX_USBDP 3 | ||
| 29 | #define TCPC_FLIPPED BIT(2) | ||
| 30 | #define TCPC_LOW_POWER_EN BIT(3) | ||
| 31 | #define TCPC_VALID BIT(4) | ||
| 32 | #define TCPC_CONN \ | ||
| 33 | (TCPC_VALID | FIELD_PREP(TCPC_MUX_CTL, MUX_USB)) | ||
| 34 | #define TCPC_DISCONN \ | ||
| 35 | (TCPC_VALID | FIELD_PREP(TCPC_MUX_CTL, MUX_NC) | TCPC_LOW_POWER_EN) | ||
| 36 | |||
| 37 | static const char *const PHY_RESETS[] = { "phy31", "phy", }; | ||
| 38 | static const char *const CTL_RESETS[] = { "apb", "ctrl", }; | ||
| 39 | |||
| 40 | struct tca_apb { | ||
| 41 | struct reset_control *resets[ARRAY_SIZE(PHY_RESETS)]; | ||
| 42 | struct regulator *vbus; | ||
| 43 | struct work_struct wk; | ||
| 44 | struct usb_phy phy; | ||
| 45 | |||
| 46 | bool regulator_enabled; | ||
| 47 | bool phy_initialized; | ||
| 48 | bool connected; | ||
| 49 | }; | ||
| 50 | |||
| 51 | static int get_flipped(struct tca_apb *ta, bool *flipped) | ||
| 52 | { | ||
| 53 | union extcon_property_value property; | ||
| 54 | int ret; | ||
| 55 | |||
| 56 | ret = extcon_get_property(ta->phy.edev, EXTCON_USB_HOST, | ||
| 57 | EXTCON_PROP_USB_TYPEC_POLARITY, &property); | ||
| 58 | if (ret) { | ||
| 59 | dev_err(ta->phy.dev, "no polarity property from extcon\n"); | ||
| 60 | return ret; | ||
| 61 | } | ||
| 62 | |||
| 63 | *flipped = property.intval; | ||
| 64 | |||
| 65 | return 0; | ||
| 66 | } | ||
| 67 | |||
| 68 | static int phy_init(struct usb_phy *phy) | ||
| 69 | { | ||
| 70 | struct tca_apb *ta = container_of(phy, struct tca_apb, phy); | ||
| 71 | void __iomem *ctrl1 = phy->io_priv + CTRL1_OFFSET; | ||
| 72 | int val, ret, i; | ||
| 73 | |||
| 74 | if (ta->phy_initialized) | ||
| 75 | return 0; | ||
| 76 | |||
| 77 | for (i = 0; i < ARRAY_SIZE(PHY_RESETS); i++) | ||
| 78 | reset_control_deassert(ta->resets[i]); | ||
| 79 | |||
| 80 | ret = readl_poll_timeout(ctrl1, val, val & SRAM_INIT_DONE, 10, 10 * 1000); | ||
| 81 | if (ret) { | ||
| 82 | dev_err(ta->phy.dev, "SRAM init failed, 0x%x\n", val); | ||
| 83 | return ret; | ||
| 84 | } | ||
| 85 | |||
| 86 | writel(readl(ctrl1) | SRAM_EXT_LD_DONE, ctrl1); | ||
| 87 | |||
| 88 | ta->phy_initialized = true; | ||
| 89 | if (!ta->phy.edev) { | ||
| 90 | writel(TCPC_CONN, ta->phy.io_priv + TCPC_OFFSET); | ||
| 91 | return phy->set_vbus(phy, true); | ||
| 92 | } | ||
| 93 | |||
| 94 | schedule_work(&ta->wk); | ||
| 95 | |||
| 96 | return ret; | ||
| 97 | } | ||
| 98 | |||
| 99 | static void phy_shutdown(struct usb_phy *phy) | ||
| 100 | { | ||
| 101 | struct tca_apb *ta = container_of(phy, struct tca_apb, phy); | ||
| 102 | int i; | ||
| 103 | |||
| 104 | if (!ta->phy_initialized) | ||
| 105 | return; | ||
| 106 | |||
| 107 | ta->phy_initialized = false; | ||
| 108 | flush_work(&ta->wk); | ||
| 109 | ta->phy.set_vbus(&ta->phy, false); | ||
| 110 | |||
| 111 | ta->connected = false; | ||
| 112 | writel(TCPC_DISCONN, ta->phy.io_priv + TCPC_OFFSET); | ||
| 113 | |||
| 114 | for (i = 0; i < ARRAY_SIZE(PHY_RESETS); i++) | ||
| 115 | reset_control_assert(ta->resets[i]); | ||
| 116 | } | ||
| 117 | |||
| 118 | static int phy_set_vbus(struct usb_phy *phy, int on) | ||
| 119 | { | ||
| 120 | struct tca_apb *ta = container_of(phy, struct tca_apb, phy); | ||
| 121 | int ret; | ||
| 122 | |||
| 123 | if (!!on == ta->regulator_enabled) | ||
| 124 | return 0; | ||
| 125 | |||
| 126 | if (on) | ||
| 127 | ret = regulator_enable(ta->vbus); | ||
| 128 | else | ||
| 129 | ret = regulator_disable(ta->vbus); | ||
| 130 | |||
| 131 | if (!ret) | ||
| 132 | ta->regulator_enabled = on; | ||
| 133 | |||
| 134 | dev_dbg(ta->phy.dev, "set vbus: %d\n", on); | ||
| 135 | return ret; | ||
| 136 | } | ||
| 137 | |||
| 138 | static void tca_work(struct work_struct *work) | ||
| 139 | { | ||
| 140 | struct tca_apb *ta = container_of(work, struct tca_apb, wk); | ||
| 141 | bool connected; | ||
| 142 | bool flipped = false; | ||
| 143 | u32 val; | ||
| 144 | int ret; | ||
| 145 | |||
| 146 | ret = get_flipped(ta, &flipped); | ||
| 147 | if (ret) | ||
| 148 | return; | ||
| 149 | |||
| 150 | connected = extcon_get_state(ta->phy.edev, EXTCON_USB_HOST); | ||
| 151 | if (connected == ta->connected) | ||
| 152 | return; | ||
| 153 | |||
| 154 | ta->connected = connected; | ||
| 155 | if (connected) { | ||
| 156 | val = TCPC_CONN; | ||
| 157 | if (flipped) | ||
| 158 | val |= TCPC_FLIPPED; | ||
| 159 | dev_dbg(ta->phy.dev, "connected%s\n", flipped ? " flipped" : ""); | ||
| 160 | } else { | ||
| 161 | val = TCPC_DISCONN; | ||
| 162 | dev_dbg(ta->phy.dev, "disconnected\n"); | ||
| 163 | } | ||
| 164 | |||
| 165 | writel(val, ta->phy.io_priv + TCPC_OFFSET); | ||
| 166 | |||
| 167 | ret = ta->phy.set_vbus(&ta->phy, connected); | ||
| 168 | if (ret) | ||
| 169 | dev_err(ta->phy.dev, "failed to set VBUS\n"); | ||
| 170 | } | ||
| 171 | |||
| 172 | static int id_notifier(struct notifier_block *nb, unsigned long event, void *ptr) | ||
| 173 | { | ||
| 174 | struct tca_apb *ta = container_of(nb, struct tca_apb, phy.id_nb); | ||
| 175 | |||
| 176 | if (ta->phy_initialized) | ||
| 177 | schedule_work(&ta->wk); | ||
| 178 | |||
| 179 | return NOTIFY_DONE; | ||
| 180 | } | ||
| 181 | |||
| 182 | static int vbus_notifier(struct notifier_block *nb, unsigned long evnt, void *ptr) | ||
| 183 | { | ||
| 184 | return NOTIFY_DONE; | ||
| 185 | } | ||
| 186 | |||
| 187 | static int phy_probe(struct platform_device *pdev) | ||
| 188 | { | ||
| 189 | struct reset_control *resets[ARRAY_SIZE(CTL_RESETS)]; | ||
| 190 | struct device *dev = &pdev->dev; | ||
| 191 | struct usb_phy *phy; | ||
| 192 | struct tca_apb *ta; | ||
| 193 | int i; | ||
| 194 | |||
| 195 | ta = devm_kzalloc(dev, sizeof(*ta), GFP_KERNEL); | ||
| 196 | if (!ta) | ||
| 197 | return -ENOMEM; | ||
| 198 | |||
| 199 | platform_set_drvdata(pdev, ta); | ||
| 200 | INIT_WORK(&ta->wk, tca_work); | ||
| 201 | |||
| 202 | phy = &ta->phy; | ||
| 203 | phy->dev = dev; | ||
| 204 | phy->label = dev_name(dev); | ||
| 205 | phy->type = USB_PHY_TYPE_USB3; | ||
| 206 | phy->init = phy_init; | ||
| 207 | phy->shutdown = phy_shutdown; | ||
| 208 | phy->set_vbus = phy_set_vbus; | ||
| 209 | phy->id_nb.notifier_call = id_notifier; | ||
| 210 | phy->vbus_nb.notifier_call = vbus_notifier; | ||
| 211 | |||
| 212 | phy->io_priv = devm_platform_ioremap_resource(pdev, 0); | ||
| 213 | if (IS_ERR(phy->io_priv)) | ||
| 214 | return PTR_ERR(phy->io_priv); | ||
| 215 | |||
| 216 | ta->vbus = devm_regulator_get(dev, "vbus"); | ||
| 217 | if (IS_ERR(ta->vbus)) | ||
| 218 | return PTR_ERR(ta->vbus); | ||
| 219 | |||
| 220 | for (i = 0; i < ARRAY_SIZE(CTL_RESETS); i++) { | ||
| 221 | resets[i] = devm_reset_control_get_exclusive(dev, CTL_RESETS[i]); | ||
| 222 | if (IS_ERR(resets[i])) { | ||
| 223 | dev_err(dev, "%s reset not found\n", CTL_RESETS[i]); | ||
| 224 | return PTR_ERR(resets[i]); | ||
| 225 | } | ||
| 226 | } | ||
| 227 | |||
| 228 | for (i = 0; i < ARRAY_SIZE(PHY_RESETS); i++) { | ||
| 229 | ta->resets[i] = devm_reset_control_get_exclusive(dev, PHY_RESETS[i]); | ||
| 230 | if (IS_ERR(ta->resets[i])) { | ||
| 231 | dev_err(dev, "%s reset not found\n", PHY_RESETS[i]); | ||
| 232 | return PTR_ERR(ta->resets[i]); | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 236 | for (i = 0; i < ARRAY_SIZE(CTL_RESETS); i++) | ||
| 237 | reset_control_assert(resets[i]); | ||
| 238 | |||
| 239 | for (i = 0; i < ARRAY_SIZE(PHY_RESETS); i++) | ||
| 240 | reset_control_assert(ta->resets[i]); | ||
| 241 | /* | ||
| 242 | * Out-of-band reset of the controller after PHY reset will cause | ||
| 243 | * controller malfunctioning, so we should use in-band controller | ||
| 244 | * reset only and leave the controller de-asserted here. | ||
| 245 | */ | ||
| 246 | for (i = 0; i < ARRAY_SIZE(CTL_RESETS); i++) | ||
| 247 | reset_control_deassert(resets[i]); | ||
| 248 | |||
| 249 | /* Need to wait at least 20us after de-assert the controller */ | ||
| 250 | usleep_range(20, 100); | ||
| 251 | |||
| 252 | return usb_add_phy_dev(phy); | ||
| 253 | } | ||
| 254 | |||
| 255 | static int phy_remove(struct platform_device *pdev) | ||
| 256 | { | ||
| 257 | struct tca_apb *ta = platform_get_drvdata(pdev); | ||
| 258 | |||
| 259 | usb_remove_phy(&ta->phy); | ||
| 260 | |||
| 261 | return 0; | ||
| 262 | } | ||
| 263 | |||
| 264 | static const struct of_device_id intel_usb_phy_dt_ids[] = { | ||
| 265 | { .compatible = "intel,lgm-usb-phy" }, | ||
| 266 | { } | ||
| 267 | }; | ||
| 268 | MODULE_DEVICE_TABLE(of, intel_usb_phy_dt_ids); | ||
| 269 | |||
| 270 | static struct platform_driver lgm_phy_driver = { | ||
| 271 | .driver = { | ||
| 272 | .name = "lgm-usb-phy", | ||
| 273 | .of_match_table = intel_usb_phy_dt_ids, | ||
| 274 | }, | ||
| 275 | .probe = phy_probe, | ||
| 276 | .remove = phy_remove, | ||
| 277 | }; | ||
| 278 | |||
| 279 | module_platform_driver(lgm_phy_driver); | ||
| 280 | |||
| 281 | MODULE_DESCRIPTION("Intel LGM USB PHY driver"); | ||
| 282 | MODULE_AUTHOR("Li Yin <yin1.li@intel.com>"); | ||
| 283 | MODULE_AUTHOR("Vadivel Murugan R <vadivel.muruganx.ramuthevar@linux.intel.com>"); | ||
| 284 | MODULE_LICENSE("GPL v2"); | ||
| @@ -4,6 +4,7 @@ · 3 unmodified lines | |||
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include <linux/io.h> | 6 | #include <linux/io.h> |
| 7 | #include <linux/iopoll.h> | ||
| 7 | #include <linux/kernel.h> | 8 | #include <linux/kernel.h> |
| 8 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| 9 | #include <linux/of.h> | 10 | #include <linux/of.h> |
| @@ -72,18 +73,12 @@ struct qcom_apq8064_sata_phy { · 62 unmodified lines | |||
| 72 | }; | 73 | }; |
| 73 | 74 | ||
| 74 | /* Helper function to do poll and timeout */ | 75 | /* Helper function to do poll and timeout */ |
| 75 | static int read_poll_timeout(void __iomem *addr, u32 mask) | 76 | static int poll_timeout(void __iomem *addr, u32 mask) |
| 76 | { | 77 | { |
| 77 | unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS); | 78 | u32 val; |
| 78 | 79 | ||
| 79 | do { | 80 | return readl_relaxed_poll_timeout(addr, val, (val & mask), |
| 80 | if (readl_relaxed(addr) & mask) | 81 | DELAY_INTERVAL_US, TIMEOUT_MS * 1000); |
| 81 | return 0; | ||
| 82 | |||
| 83 | usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50); | ||
| 84 | } while (!time_after(jiffies, timeout)); | ||
| 85 | |||
| 86 | return (readl_relaxed(addr) & mask) ? 0 : -ETIMEDOUT; | ||
| 87 | } | 82 | } |
| 88 | 83 | ||
| 89 | static int qcom_apq8064_sata_phy_init(struct phy *generic_phy) | 84 | static int qcom_apq8064_sata_phy_init(struct phy *generic_phy) |
| @@ -137,21 +132,21 @@ static int qcom_apq8064_sata_phy_init(struct phy *generic_phy) · 47 unmodified lines | |||
| 137 | writel_relaxed(0x05, base + UNIPHY_PLL_LKDET_CFG2); | 132 | writel_relaxed(0x05, base + UNIPHY_PLL_LKDET_CFG2); |
| 138 | 133 | ||
| 139 | /* PLL Lock wait */ | 134 | /* PLL Lock wait */ |
| 140 | ret = read_poll_timeout(base + UNIPHY_PLL_STATUS, UNIPHY_PLL_LOCK); | 135 | ret = poll_timeout(base + UNIPHY_PLL_STATUS, UNIPHY_PLL_LOCK); |
| 141 | if (ret) { | 136 | if (ret) { |
| 142 | dev_err(phy->dev, "poll timeout UNIPHY_PLL_STATUS\n"); | 137 | dev_err(phy->dev, "poll timeout UNIPHY_PLL_STATUS\n"); |
| 143 | return ret; | 138 | return ret; |
| 144 | } | 139 | } |
| 145 | 140 | ||
| 146 | /* TX Calibration */ | 141 | /* TX Calibration */ |
| 147 | ret = read_poll_timeout(base + SATA_PHY_TX_IMCAL_STAT, SATA_PHY_TX_CAL); | 142 | ret = poll_timeout(base + SATA_PHY_TX_IMCAL_STAT, SATA_PHY_TX_CAL); |
| 148 | if (ret) { | 143 | if (ret) { |
| 149 | dev_err(phy->dev, "poll timeout SATA_PHY_TX_IMCAL_STAT\n"); | 144 | dev_err(phy->dev, "poll timeout SATA_PHY_TX_IMCAL_STAT\n"); |
| 150 | return ret; | 145 | return ret; |
| 151 | } | 146 | } |
| 152 | 147 | ||
| 153 | /* RX Calibration */ | 148 | /* RX Calibration */ |
| 154 | ret = read_poll_timeout(base + SATA_PHY_RX_IMCAL_STAT, SATA_PHY_RX_CAL); | 149 | ret = poll_timeout(base + SATA_PHY_RX_IMCAL_STAT, SATA_PHY_RX_CAL); |
| 155 | if (ret) { | 150 | if (ret) { |
| 156 | dev_err(phy->dev, "poll timeout SATA_PHY_RX_IMCAL_STAT\n"); | 151 | dev_err(phy->dev, "poll timeout SATA_PHY_RX_IMCAL_STAT\n"); |
| 157 | return ret; | 152 | return ret; |
| @@ -48,7 +48,7 @@ static int ipq4019_ss_phy_power_on(struct phy *_phy) · 47 unmodified lines | |||
| 48 | return 0; | 48 | return 0; |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | static struct phy_ops ipq4019_usb_ss_phy_ops = { | 51 | static const struct phy_ops ipq4019_usb_ss_phy_ops = { |
| 52 | .power_on = ipq4019_ss_phy_power_on, | 52 | .power_on = ipq4019_ss_phy_power_on, |
| 53 | .power_off = ipq4019_ss_phy_power_off, | 53 | .power_off = ipq4019_ss_phy_power_off, |
| 54 | }; | 54 | }; |
| @@ -80,7 +80,7 @@ static int ipq4019_hs_phy_power_on(struct phy *_phy) · 25 unmodified lines | |||
| 80 | return 0; | 80 | return 0; |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | static struct phy_ops ipq4019_usb_hs_phy_ops = { | 83 | static const struct phy_ops ipq4019_usb_hs_phy_ops = { |
| 84 | .power_on = ipq4019_hs_phy_power_on, | 84 | .power_on = ipq4019_hs_phy_power_on, |
| 85 | .power_off = ipq4019_hs_phy_power_off, | 85 | .power_off = ipq4019_hs_phy_power_off, |
| 86 | }; | 86 | }; |
| @@ -946,6 +946,88 @@ static const struct qmp_phy_init_tbl qmp_v3_usb3_tx_tbl[] = { · 945 unmodified lines | |||
| 946 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x06), | 946 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x06), |
| 947 | }; | 947 | }; |
| 948 | 948 | ||
| 949 | static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl[] = { | ||
| 950 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), | ||
| 951 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x37), | ||
| 952 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), | ||
| 953 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_ENABLE1, 0x0e), | ||
| 954 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x06), | ||
| 955 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), | ||
| 956 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x02), | ||
| 957 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0x00), | ||
| 958 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), | ||
| 959 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), | ||
| 960 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), | ||
| 961 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), | ||
| 962 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a), | ||
| 963 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), | ||
| 964 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_CTRL, 0x00), | ||
| 965 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x3f), | ||
| 966 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x1f), | ||
| 967 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), | ||
| 968 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), | ||
| 969 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), | ||
| 970 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), | ||
| 971 | }; | ||
| 972 | |||
| 973 | static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl_rbr[] = { | ||
| 974 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x0c), | ||
| 975 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x69), | ||
| 976 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x80), | ||
| 977 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x07), | ||
| 978 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x6f), | ||
| 979 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x08), | ||
| 980 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x00), | ||
| 981 | }; | ||
| 982 | |||
| 983 | static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl_hbr[] = { | ||
| 984 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x04), | ||
| 985 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x69), | ||
| 986 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x80), | ||
| 987 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x07), | ||
| 988 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x0f), | ||
| 989 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0e), | ||
| 990 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x00), | ||
| 991 | }; | ||
| 992 | |||
| 993 | static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl_hbr2[] = { | ||
| 994 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00), | ||
| 995 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x8c), | ||
| 996 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x00), | ||
| 997 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x0a), | ||
| 998 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x1f), | ||
| 999 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x1c), | ||
| 1000 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x00), | ||
| 1001 | }; | ||
| 1002 | |||
| 1003 | static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl_hbr3[] = { | ||
| 1004 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x03), | ||
| 1005 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x69), | ||
| 1006 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x80), | ||
| 1007 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x07), | ||
| 1008 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x2f), | ||
| 1009 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x2a), | ||
| 1010 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x08), | ||
| 1011 | }; | ||
| 1012 | |||
| 1013 | static const struct qmp_phy_init_tbl qmp_v3_dp_tx_tbl[] = { | ||
| 1014 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_TRANSCEIVER_BIAS_EN, 0x1a), | ||
| 1015 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_VMODE_CTRL1, 0x40), | ||
| 1016 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_PRE_STALL_LDO_BOOST_EN, 0x30), | ||
| 1017 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_INTERFACE_SELECT, 0x3d), | ||
| 1018 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_CLKBUF_ENABLE, 0x0f), | ||
| 1019 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_RESET_TSYNC_EN, 0x03), | ||
| 1020 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_TRAN_DRVR_EMP_EN, 0x03), | ||
| 1021 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_PARRATE_REC_DETECT_IDLE_EN, 0x00), | ||
| 1022 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_INTERFACE_MODE, 0x00), | ||
| 1023 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_BAND, 0x4), | ||
| 1024 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_POL_INV, 0x0a), | ||
| 1025 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_DRV_LVL, 0x38), | ||
| 1026 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_EMP_POST1_LVL, 0x20), | ||
| 1027 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x06), | ||
| 1028 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x07), | ||
| 1029 | }; | ||
| 1030 | |||
| 949 | static const struct qmp_phy_init_tbl qmp_v3_usb3_rx_tbl[] = { | 1031 | static const struct qmp_phy_init_tbl qmp_v3_usb3_rx_tbl[] = { |
| 950 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), | 1032 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), |
| 951 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), | 1033 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), |
| @@ -1761,6 +1843,16 @@ struct qmp_phy_cfg { · 809 unmodified lines | |||
| 1761 | const struct qmp_phy_init_tbl *pcs_misc_tbl; | 1843 | const struct qmp_phy_init_tbl *pcs_misc_tbl; |
| 1762 | int pcs_misc_tbl_num; | 1844 | int pcs_misc_tbl_num; |
| 1763 | 1845 | ||
| 1846 | /* Init sequence for DP PHY block link rates */ | ||
| 1847 | const struct qmp_phy_init_tbl *serdes_tbl_rbr; | ||
| 1848 | int serdes_tbl_rbr_num; | ||
| 1849 | const struct qmp_phy_init_tbl *serdes_tbl_hbr; | ||
| 1850 | int serdes_tbl_hbr_num; | ||
| 1851 | const struct qmp_phy_init_tbl *serdes_tbl_hbr2; | ||
| 1852 | int serdes_tbl_hbr2_num; | ||
| 1853 | const struct qmp_phy_init_tbl *serdes_tbl_hbr3; | ||
| 1854 | int serdes_tbl_hbr3_num; | ||
| 1855 | |||
| 1764 | /* clock ids to be requested */ | 1856 | /* clock ids to be requested */ |
| 1765 | const char * const *clk_list; | 1857 | const char * const *clk_list; |
| 1766 | int num_clks; | 1858 | int num_clks; |
| @@ -1797,10 +1889,17 @@ struct qmp_phy_cfg { · 30 unmodified lines | |||
| 1797 | bool no_pcs_sw_reset; | 1889 | bool no_pcs_sw_reset; |
| 1798 | }; | 1890 | }; |
| 1799 | 1891 | ||
| 1892 | struct qmp_phy_combo_cfg { | ||
| 1893 | const struct qmp_phy_cfg *usb_cfg; | ||
| 1894 | const struct qmp_phy_cfg *dp_cfg; | ||
| 1895 | }; | ||
| 1896 | |||
| 1800 | /** | 1897 | /** |
| 1801 | * struct qmp_phy - per-lane phy descriptor | 1898 | * struct qmp_phy - per-lane phy descriptor |
| 1802 | * | 1899 | * |
| 1803 | * @phy: generic phy | 1900 | * @phy: generic phy |
| 1901 | * @cfg: phy specific configuration | ||
| 1902 | * @serdes: iomapped memory space for phy's serdes (i.e. PLL) | ||
| 1804 | * @tx: iomapped memory space for lane's tx | 1903 | * @tx: iomapped memory space for lane's tx |
| 1805 | * @rx: iomapped memory space for lane's rx | 1904 | * @rx: iomapped memory space for lane's rx |
| 1806 | * @pcs: iomapped memory space for lane's pcs | 1905 | * @pcs: iomapped memory space for lane's pcs |
| @@ -1811,9 +1910,12 @@ struct qmp_phy_cfg { · 4 unmodified lines | |||
| 1811 | * @index: lane index | 1910 | * @index: lane index |
| 1812 | * @qmp: QMP phy to which this lane belongs | 1911 | * @qmp: QMP phy to which this lane belongs |
| 1813 | * @lane_rst: lane's reset controller | 1912 | * @lane_rst: lane's reset controller |
| 1913 | * @mode: current PHY mode | ||
| 1814 | */ | 1914 | */ |
| 1815 | struct qmp_phy { | 1915 | struct qmp_phy { |
| 1816 | struct phy *phy; | 1916 | struct phy *phy; |
| 1917 | const struct qmp_phy_cfg *cfg; | ||
| 1918 | void __iomem *serdes; | ||
| 1817 | void __iomem *tx; | 1919 | void __iomem *tx; |
| 1818 | void __iomem *rx; | 1920 | void __iomem *rx; |
| 1819 | void __iomem *pcs; | 1921 | void __iomem *pcs; |
| @@ -1824,43 +1926,45 @@ struct qmp_phy { · 4 unmodified lines | |||
| 1824 | unsigned int index; | 1926 | unsigned int index; |
| 1825 | struct qcom_qmp *qmp; | 1927 | struct qcom_qmp *qmp; |
| 1826 | struct reset_control *lane_rst; | 1928 | struct reset_control *lane_rst; |
| 1929 | enum phy_mode mode; | ||
| 1930 | unsigned int dp_aux_cfg; | ||
| 1931 | struct phy_configure_opts_dp dp_opts; | ||
| 1932 | struct qmp_phy_dp_clks *dp_clks; | ||
| 1933 | }; | ||
| 1934 | |||
| 1935 | struct qmp_phy_dp_clks { | ||
| 1936 | struct qmp_phy *qphy; | ||
| 1937 | struct clk_hw dp_link_hw; | ||
| 1938 | struct clk_hw dp_pixel_hw; | ||
| 1827 | }; | 1939 | }; |
| 1828 | 1940 | ||
| 1829 | /** | 1941 | /** |
| 1830 | * struct qcom_qmp - structure holding QMP phy block attributes | 1942 | * struct qcom_qmp - structure holding QMP phy block attributes |
| 1831 | * | 1943 | * |
| 1832 | * @dev: device | 1944 | * @dev: device |
| 1833 | * @serdes: iomapped memory space for phy's serdes | ||
| 1834 | * @dp_com: iomapped memory space for phy's dp_com control block | 1945 | * @dp_com: iomapped memory space for phy's dp_com control block |
| 1835 | * | 1946 | * |
| 1836 | * @clks: array of clocks required by phy | 1947 | * @clks: array of clocks required by phy |
| 1837 | * @resets: array of resets required by phy | 1948 | * @resets: array of resets required by phy |
| 1838 | * @vregs: regulator supplies bulk data | 1949 | * @vregs: regulator supplies bulk data |
| 1839 | * | 1950 | * |
| 1840 | * @cfg: phy specific configuration | ||
| 1841 | * @phys: array of per-lane phy descriptors | 1951 | * @phys: array of per-lane phy descriptors |
| 1842 | * @phy_mutex: mutex lock for PHY common block initialization | 1952 | * @phy_mutex: mutex lock for PHY common block initialization |
| 1843 | * @init_count: phy common block initialization count | 1953 | * @init_count: phy common block initialization count |
| 1844 | * @phy_initialized: indicate if PHY has been initialized | ||
| 1845 | * @mode: current PHY mode | ||
| 1846 | * @ufs_reset: optional UFS PHY reset handle | 1954 | * @ufs_reset: optional UFS PHY reset handle |
| 1847 | */ | 1955 | */ |
| 1848 | struct qcom_qmp { | 1956 | struct qcom_qmp { |
| 1849 | struct device *dev; | 1957 | struct device *dev; |
| 1850 | void __iomem *serdes; | ||
| 1851 | void __iomem *dp_com; | 1958 | void __iomem *dp_com; |
| 1852 | 1959 | ||
| 1853 | struct clk_bulk_data *clks; | 1960 | struct clk_bulk_data *clks; |
| 1854 | struct reset_control **resets; | 1961 | struct reset_control **resets; |
| 1855 | struct regulator_bulk_data *vregs; | 1962 | struct regulator_bulk_data *vregs; |
| 1856 | 1963 | ||
| 1857 | const struct qmp_phy_cfg *cfg; | ||
| 1858 | struct qmp_phy **phys; | 1964 | struct qmp_phy **phys; |
| 1859 | 1965 | ||
| 1860 | struct mutex phy_mutex; | 1966 | struct mutex phy_mutex; |
| 1861 | int init_count; | 1967 | int init_count; |
| 1862 | bool phy_initialized; | ||
| 1863 | enum phy_mode mode; | ||
| 1864 | 1968 | ||
| 1865 | struct reset_control *ufs_reset; | 1969 | struct reset_control *ufs_reset; |
| 1866 | }; | 1970 | }; |
| @@ -2203,6 +2307,41 @@ static const struct qmp_phy_cfg sc7180_usb3phy_cfg = { · 336 unmodified lines | |||
| 2203 | .is_dual_lane_phy = true, | 2307 | .is_dual_lane_phy = true, |
| 2204 | }; | 2308 | }; |
| 2205 | 2309 | ||
| 2310 | static const struct qmp_phy_cfg sc7180_dpphy_cfg = { | ||
| 2311 | .type = PHY_TYPE_DP, | ||
| 2312 | .nlanes = 1, | ||
| 2313 | |||
| 2314 | .serdes_tbl = qmp_v3_dp_serdes_tbl, | ||
| 2315 | .serdes_tbl_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl), | ||
| 2316 | .tx_tbl = qmp_v3_dp_tx_tbl, | ||
| 2317 | .tx_tbl_num = ARRAY_SIZE(qmp_v3_dp_tx_tbl), | ||
| 2318 | |||
| 2319 | .serdes_tbl_rbr = qmp_v3_dp_serdes_tbl_rbr, | ||
| 2320 | .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_rbr), | ||
| 2321 | .serdes_tbl_hbr = qmp_v3_dp_serdes_tbl_hbr, | ||
| 2322 | .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_hbr), | ||
| 2323 | .serdes_tbl_hbr2 = qmp_v3_dp_serdes_tbl_hbr2, | ||
| 2324 | .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_hbr2), | ||
| 2325 | .serdes_tbl_hbr3 = qmp_v3_dp_serdes_tbl_hbr3, | ||
| 2326 | .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_hbr3), | ||
| 2327 | |||
| 2328 | .clk_list = qmp_v3_phy_clk_l, | ||
| 2329 | .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), | ||
| 2330 | .reset_list = sc7180_usb3phy_reset_l, | ||
| 2331 | .num_resets = ARRAY_SIZE(sc7180_usb3phy_reset_l), | ||
| 2332 | .vreg_list = qmp_phy_vreg_l, | ||
| 2333 | .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), | ||
| 2334 | .regs = qmp_v3_usb3phy_regs_layout, | ||
| 2335 | |||
| 2336 | .has_phy_dp_com_ctrl = true, | ||
| 2337 | .is_dual_lane_phy = true, | ||
| 2338 | }; | ||
| 2339 | |||
| 2340 | static const struct qmp_phy_combo_cfg sc7180_usb3dpphy_cfg = { | ||
| 2341 | .usb_cfg = &sc7180_usb3phy_cfg, | ||
| 2342 | .dp_cfg = &sc7180_dpphy_cfg, | ||
| 2343 | }; | ||
| 2344 | |||
| 2206 | static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = { | 2345 | static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = { |
| 2207 | .type = PHY_TYPE_USB3, | 2346 | .type = PHY_TYPE_USB3, |
| 2208 | .nlanes = 1, | 2347 | .nlanes = 1, |
| @@ -2479,11 +2618,300 @@ static void qcom_qmp_phy_configure(void __iomem *base, · 270 unmodified lines | |||
| 2479 | qcom_qmp_phy_configure_lane(base, regs, tbl, num, 0xff); | 2618 | qcom_qmp_phy_configure_lane(base, regs, tbl, num, 0xff); |
| 2480 | } | 2619 | } |
| 2481 | 2620 | ||
| 2621 | static int qcom_qmp_phy_serdes_init(struct qmp_phy *qphy) | ||
| 2622 | { | ||
| 2623 | struct qcom_qmp *qmp = qphy->qmp; | ||
| 2624 | const struct qmp_phy_cfg *cfg = qphy->cfg; | ||
| 2625 | void __iomem *serdes = qphy->serdes; | ||
| 2626 | const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; | ||
| 2627 | const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl; | ||
| 2628 | int serdes_tbl_num = cfg->serdes_tbl_num; | ||
| 2629 | int ret; | ||
| 2630 | |||
| 2631 | qcom_qmp_phy_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); | ||
| 2632 | |||
| 2633 | if (cfg->type == PHY_TYPE_DP) { | ||
| 2634 | switch (dp_opts->link_rate) { | ||
| 2635 | case 1620: | ||
| 2636 | qcom_qmp_phy_configure(serdes, cfg->regs, | ||
| 2637 | cfg->serdes_tbl_rbr, | ||
| 2638 | cfg->serdes_tbl_rbr_num); | ||
| 2639 | break; | ||
| 2640 | case 2700: | ||
| 2641 | qcom_qmp_phy_configure(serdes, cfg->regs, | ||
| 2642 | cfg->serdes_tbl_hbr, | ||
| 2643 | cfg->serdes_tbl_hbr_num); | ||
| 2644 | break; | ||
| 2645 | case 5400: | ||
| 2646 | qcom_qmp_phy_configure(serdes, cfg->regs, | ||
| 2647 | cfg->serdes_tbl_hbr2, | ||
| 2648 | cfg->serdes_tbl_hbr2_num); | ||
| 2649 | break; | ||
| 2650 | case 8100: | ||
| 2651 | qcom_qmp_phy_configure(serdes, cfg->regs, | ||
| 2652 | cfg->serdes_tbl_hbr3, | ||
| 2653 | cfg->serdes_tbl_hbr3_num); | ||
| 2654 | break; | ||
| 2655 | default: | ||
| 2656 | /* Other link rates aren't supported */ | ||
| 2657 | return -EINVAL; | ||
| 2658 | } | ||
| 2659 | } | ||
| 2660 | |||
| 2661 | |||
| 2662 | if (cfg->has_phy_com_ctrl) { | ||
| 2663 | void __iomem *status; | ||
| 2664 | unsigned int mask, val; | ||
| 2665 | |||
| 2666 | qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], SW_RESET); | ||
| 2667 | qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL], | ||
| 2668 | SERDES_START | PCS_START); | ||
| 2669 | |||
| 2670 | status = serdes + cfg->regs[QPHY_COM_PCS_READY_STATUS]; | ||
| 2671 | mask = cfg->mask_com_pcs_ready; | ||
| 2672 | |||
| 2673 | ret = readl_poll_timeout(status, val, (val & mask), 10, | ||
| 2674 | PHY_INIT_COMPLETE_TIMEOUT); | ||
| 2675 | if (ret) { | ||
| 2676 | dev_err(qmp->dev, | ||
| 2677 | "phy common block init timed-out\n"); | ||
| 2678 | return ret; | ||
| 2679 | } | ||
| 2680 | } | ||
| 2681 | |||
| 2682 | return 0; | ||
| 2683 | } | ||
| 2684 | |||
| 2685 | static void qcom_qmp_phy_dp_aux_init(struct qmp_phy *qphy) | ||
| 2686 | { | ||
| 2687 | writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | | ||
| 2688 | DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN, | ||
| 2689 | qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL); | ||
| 2690 | |||
| 2691 | /* Turn on BIAS current for PHY/PLL */ | ||
| 2692 | writel(QSERDES_V3_COM_BIAS_EN | QSERDES_V3_COM_BIAS_EN_MUX | | ||
| 2693 | QSERDES_V3_COM_CLKBUF_L_EN | QSERDES_V3_COM_EN_SYSCLK_TX_SEL, | ||
| 2694 | qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN); | ||
| 2695 | |||
| 2696 | writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL); | ||
| 2697 | |||
| 2698 | writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | | ||
| 2699 | DP_PHY_PD_CTL_LANE_0_1_PWRDN | | ||
| 2700 | DP_PHY_PD_CTL_LANE_2_3_PWRDN | DP_PHY_PD_CTL_PLL_PWRDN | | ||
| 2701 | DP_PHY_PD_CTL_DP_CLAMP_EN, | ||
| 2702 | qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL); | ||
| 2703 | |||
| 2704 | writel(QSERDES_V3_COM_BIAS_EN | | ||
| 2705 | QSERDES_V3_COM_BIAS_EN_MUX | QSERDES_V3_COM_CLKBUF_R_EN | | ||
| 2706 | QSERDES_V3_COM_CLKBUF_L_EN | QSERDES_V3_COM_EN_SYSCLK_TX_SEL | | ||
| 2707 | QSERDES_V3_COM_CLKBUF_RX_DRIVE_L, | ||
| 2708 | qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN); | ||
| 2709 | |||
| 2710 | writel(0x00, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG0); | ||
| 2711 | writel(0x13, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG1); | ||
| 2712 | writel(0x24, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG2); | ||
| 2713 | writel(0x00, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG3); | ||
| 2714 | writel(0x0a, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG4); | ||
| 2715 | writel(0x26, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG5); | ||
| 2716 | writel(0x0a, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG6); | ||
| 2717 | writel(0x03, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG7); | ||
| 2718 | writel(0xbb, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG8); | ||
| 2719 | writel(0x03, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG9); | ||
| 2720 | qphy->dp_aux_cfg = 0; | ||
| 2721 | |||
| 2722 | writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK | | ||
| 2723 | PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK | | ||
| 2724 | PHY_AUX_REQ_ERR_MASK, | ||
| 2725 | qphy->pcs + QSERDES_V3_DP_PHY_AUX_INTERRUPT_MASK); | ||
| 2726 | } | ||
| 2727 | |||
| 2728 | static const u8 qmp_dp_v3_pre_emphasis_hbr_rbr[4][4] = { | ||
| 2729 | { 0x00, 0x0c, 0x14, 0x19 }, | ||
| 2730 | { 0x00, 0x0b, 0x12, 0xff }, | ||
| 2731 | { 0x00, 0x0b, 0xff, 0xff }, | ||
| 2732 | { 0x04, 0xff, 0xff, 0xff } | ||
| 2733 | }; | ||
| 2734 | |||
| 2735 | static const u8 qmp_dp_v3_voltage_swing_hbr_rbr[4][4] = { | ||
| 2736 | { 0x08, 0x0f, 0x16, 0x1f }, | ||
| 2737 | { 0x11, 0x1e, 0x1f, 0xff }, | ||
| 2738 | { 0x19, 0x1f, 0xff, 0xff }, | ||
| 2739 | { 0x1f, 0xff, 0xff, 0xff } | ||
| 2740 | }; | ||
| 2741 | |||
| 2742 | static void qcom_qmp_phy_configure_dp_tx(struct qmp_phy *qphy) | ||
| 2743 | { | ||
| 2744 | const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; | ||
| 2745 | unsigned int v_level = 0, p_level = 0; | ||
| 2746 | u32 bias_en, drvr_en; | ||
| 2747 | u8 voltage_swing_cfg, pre_emphasis_cfg; | ||
| 2748 | int i; | ||
| 2749 | |||
| 2750 | for (i = 0; i < dp_opts->lanes; i++) { | ||
| 2751 | v_level = max(v_level, dp_opts->voltage[i]); | ||
| 2752 | p_level = max(p_level, dp_opts->pre[i]); | ||
| 2753 | } | ||
| 2754 | |||
| 2755 | if (dp_opts->lanes == 1) { | ||
| 2756 | bias_en = 0x3e; | ||
| 2757 | drvr_en = 0x13; | ||
| 2758 | } else { | ||
| 2759 | bias_en = 0x3f; | ||
| 2760 | drvr_en = 0x10; | ||
| 2761 | } | ||
| 2762 | |||
| 2763 | voltage_swing_cfg = qmp_dp_v3_voltage_swing_hbr_rbr[v_level][p_level]; | ||
| 2764 | pre_emphasis_cfg = qmp_dp_v3_pre_emphasis_hbr_rbr[v_level][p_level]; | ||
| 2765 | |||
| 2766 | /* TODO: Move check to config check */ | ||
| 2767 | if (voltage_swing_cfg == 0xFF && pre_emphasis_cfg == 0xFF) | ||
| 2768 | return; | ||
| 2769 | |||
| 2770 | /* Enable MUX to use Cursor values from these registers */ | ||
| 2771 | voltage_swing_cfg |= DP_PHY_TXn_TX_DRV_LVL_MUX_EN; | ||
| 2772 | pre_emphasis_cfg |= DP_PHY_TXn_TX_EMP_POST1_LVL_MUX_EN; | ||
| 2773 | |||
| 2774 | writel(voltage_swing_cfg, qphy->tx + QSERDES_V3_TX_TX_DRV_LVL); | ||
| 2775 | writel(pre_emphasis_cfg, qphy->tx + QSERDES_V3_TX_TX_EMP_POST1_LVL); | ||
| 2776 | writel(voltage_swing_cfg, qphy->tx2 + QSERDES_V3_TX_TX_DRV_LVL); | ||
| 2777 | writel(pre_emphasis_cfg, qphy->tx2 + QSERDES_V3_TX_TX_EMP_POST1_LVL); | ||
| 2778 | |||
| 2779 | writel(drvr_en, qphy->tx + QSERDES_V3_TX_HIGHZ_DRVR_EN); | ||
| 2780 | writel(bias_en, qphy->tx + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); | ||
| 2781 | writel(drvr_en, qphy->tx2 + QSERDES_V3_TX_HIGHZ_DRVR_EN); | ||
| 2782 | writel(bias_en, qphy->tx2 + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); | ||
| 2783 | } | ||
| 2784 | |||
| 2785 | static int qcom_qmp_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts) | ||
| 2786 | { | ||
| 2787 | const struct phy_configure_opts_dp *dp_opts = &opts->dp; | ||
| 2788 | struct qmp_phy *qphy = phy_get_drvdata(phy); | ||
| 2789 | |||
| 2790 | memcpy(&qphy->dp_opts, dp_opts, sizeof(*dp_opts)); | ||
| 2791 | if (qphy->dp_opts.set_voltages) { | ||
| 2792 | qcom_qmp_phy_configure_dp_tx(qphy); | ||
| 2793 | qphy->dp_opts.set_voltages = 0; | ||
| 2794 | } | ||
| 2795 | |||
| 2796 | return 0; | ||
| 2797 | } | ||
| 2798 | |||
| 2799 | static int qcom_qmp_phy_configure_dp_phy(struct qmp_phy *qphy) | ||
| 2800 | { | ||
| 2801 | const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks; | ||
| 2802 | const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; | ||
| 2803 | u32 val, phy_vco_div, status; | ||
| 2804 | unsigned long pixel_freq; | ||
| 2805 | |||
| 2806 | val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | | ||
| 2807 | DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN; | ||
| 2808 | |||
| 2809 | /* | ||
| 2810 | * TODO: Assume orientation is CC1 for now and two lanes, need to | ||
| 2811 | * use type-c connector to understand orientation and lanes. | ||
| 2812 | * | ||
| 2813 | * Otherwise val changes to be like below if this code understood | ||
| 2814 | * the orientation of the type-c cable. | ||
| 2815 | * | ||
| 2816 | * if (lane_cnt == 4 || orientation == ORIENTATION_CC2) | ||
| 2817 | * val |= DP_PHY_PD_CTL_LANE_0_1_PWRDN; | ||
| 2818 | * if (lane_cnt == 4 || orientation == ORIENTATION_CC1) | ||
| 2819 | * val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN; | ||
| 2820 | * if (orientation == ORIENTATION_CC2) | ||
| 2821 | * writel(0x4c, qphy->pcs + QSERDES_V3_DP_PHY_MODE); | ||
| 2822 | */ | ||
| 2823 | val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN; | ||
| 2824 | writel(val, qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL); | ||
| 2825 | |||
| 2826 | writel(0x5c, qphy->pcs + QSERDES_V3_DP_PHY_MODE); | ||
| 2827 | writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX0_TX1_LANE_CTL); | ||
| 2828 | writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX2_TX3_LANE_CTL); | ||
| 2829 | |||
| 2830 | switch (dp_opts->link_rate) { | ||
| 2831 | case 1620: | ||
| 2832 | phy_vco_div = 0x1; | ||
| 2833 | pixel_freq = 1620000000UL / 2; | ||
| 2834 | break; | ||
| 2835 | case 2700: | ||
| 2836 | phy_vco_div = 0x1; | ||
| 2837 | pixel_freq = 2700000000UL / 2; | ||
| 2838 | break; | ||
| 2839 | case 5400: | ||
| 2840 | phy_vco_div = 0x2; | ||
| 2841 | pixel_freq = 5400000000UL / 4; | ||
| 2842 | break; | ||
| 2843 | case 8100: | ||
| 2844 | phy_vco_div = 0x0; | ||
| 2845 | pixel_freq = 8100000000UL / 6; | ||
| 2846 | break; | ||
| 2847 | default: | ||
| 2848 | /* Other link rates aren't supported */ | ||
| 2849 | return -EINVAL; | ||
| 2850 | } | ||
| 2851 | writel(phy_vco_div, qphy->pcs + QSERDES_V3_DP_PHY_VCO_DIV); | ||
| 2852 | |||
| 2853 | clk_set_rate(dp_clks->dp_link_hw.clk, dp_opts->link_rate * 100000); | ||
| 2854 | clk_set_rate(dp_clks->dp_pixel_hw.clk, pixel_freq); | ||
| 2855 | |||
| 2856 | writel(0x04, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG2); | ||
| 2857 | writel(0x01, qphy->pcs + QSERDES_V3_DP_PHY_CFG); | ||
| 2858 | writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_CFG); | ||
| 2859 | writel(0x01, qphy->pcs + QSERDES_V3_DP_PHY_CFG); | ||
| 2860 | writel(0x09, qphy->pcs + QSERDES_V3_DP_PHY_CFG); | ||
| 2861 | |||
| 2862 | writel(0x20, qphy->serdes + QSERDES_V3_COM_RESETSM_CNTRL); | ||
| 2863 | |||
| 2864 | if (readl_poll_timeout(qphy->serdes + QSERDES_V3_COM_C_READY_STATUS, | ||
| 2865 | status, | ||
| 2866 | ((status & BIT(0)) > 0), | ||
| 2867 | 500, | ||
| 2868 | 10000)) | ||
| 2869 | return -ETIMEDOUT; | ||
| 2870 | |||
| 2871 | writel(0x19, qphy->pcs + QSERDES_V3_DP_PHY_CFG); | ||
| 2872 | |||
| 2873 | if (readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS, | ||
| 2874 | status, | ||
| 2875 | ((status & BIT(1)) > 0), | ||
| 2876 | 500, | ||
| 2877 | 10000)) | ||
| 2878 | return -ETIMEDOUT; | ||
| 2879 | |||
| 2880 | writel(0x18, qphy->pcs + QSERDES_V3_DP_PHY_CFG); | ||
| 2881 | udelay(2000); | ||
| 2882 | writel(0x19, qphy->pcs + QSERDES_V3_DP_PHY_CFG); | ||
| 2883 | |||
| 2884 | return readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS, | ||
| 2885 | status, | ||
| 2886 | ((status & BIT(1)) > 0), | ||
| 2887 | 500, | ||
| 2888 | 10000); | ||
| 2889 | } | ||
| 2890 | |||
| 2891 | /* | ||
| 2892 | * We need to calibrate the aux setting here as many times | ||
| 2893 | * as the caller tries | ||
| 2894 | */ | ||
| 2895 | static int qcom_qmp_dp_phy_calibrate(struct phy *phy) | ||
| 2896 | { | ||
| 2897 | struct qmp_phy *qphy = phy_get_drvdata(phy); | ||
| 2898 | const u8 cfg1_settings[] = { 0x13, 0x23, 0x1d }; | ||
| 2899 | u8 val; | ||
| 2900 | |||
| 2901 | qphy->dp_aux_cfg++; | ||
| 2902 | qphy->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings); | ||
| 2903 | val = cfg1_settings[qphy->dp_aux_cfg]; | ||
| 2904 | |||
| 2905 | writel(val, qphy->pcs + QSERDES_V3_DP_PHY_AUX_CFG1); | ||
| 2906 | |||
| 2907 | return 0; | ||
| 2908 | } | ||
| 2909 | |||
| 2482 | static int qcom_qmp_phy_com_init(struct qmp_phy *qphy) | 2910 | static int qcom_qmp_phy_com_init(struct qmp_phy *qphy) |
| 2483 | { | 2911 | { |
| 2484 | struct qcom_qmp *qmp = qphy->qmp; | 2912 | struct qcom_qmp *qmp = qphy->qmp; |
| 2485 | const struct qmp_phy_cfg *cfg = qmp->cfg; | 2913 | const struct qmp_phy_cfg *cfg = qphy->cfg; |
| 2486 | void __iomem *serdes = qmp->serdes; | 2914 | void __iomem *serdes = qphy->serdes; |
| 2487 | void __iomem *pcs = qphy->pcs; | 2915 | void __iomem *pcs = qphy->pcs; |
| 2488 | void __iomem *dp_com = qmp->dp_com; | 2916 | void __iomem *dp_com = qmp->dp_com; |
| 2489 | int ret, i; | 2917 | int ret, i; |
| @@ -2514,7 +2942,7 @@ static int qcom_qmp_phy_com_init(struct qmp_phy *qphy) · 24 unmodified lines | |||
| 2514 | ret = reset_control_deassert(qmp->resets[i]); | 2942 | ret = reset_control_deassert(qmp->resets[i]); |
| 2515 | if (ret) { | 2943 | if (ret) { |
| 2516 | dev_err(qmp->dev, "%s reset deassert failed\n", | 2944 | dev_err(qmp->dev, "%s reset deassert failed\n", |
| 2517 | qmp->cfg->reset_list[i]); | 2945 | qphy->cfg->reset_list[i]); |
| 2518 | goto err_rst; | 2946 | goto err_rst; |
| 2519 | } | 2947 | } |
| 2520 | } | 2948 | } |
| @@ -2533,6 +2961,9 @@ static int qcom_qmp_phy_com_init(struct qmp_phy *qphy) · 12 unmodified lines | |||
| 2533 | SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | | 2961 | SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | |
| 2534 | SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET); | 2962 | SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET); |
| 2535 | 2963 | ||
| 2964 | /* Default type-c orientation, i.e CC1 */ | ||
| 2965 | qphy_setbits(dp_com, QPHY_V3_DP_COM_TYPEC_CTRL, 0x02); | ||
| 2966 | |||
| 2536 | qphy_setbits(dp_com, QPHY_V3_DP_COM_PHY_MODE_CTRL, | 2967 | qphy_setbits(dp_com, QPHY_V3_DP_COM_PHY_MODE_CTRL, |
| 2537 | USB3_MODE | DP_MODE); | 2968 | USB3_MODE | DP_MODE); |
| 2538 | 2969 | ||
| @@ -2540,6 +2971,9 @@ static int qcom_qmp_phy_com_init(struct qmp_phy *qphy) · 1 unmodified line | |||
| 2540 | qphy_clrbits(dp_com, QPHY_V3_DP_COM_RESET_OVRD_CTRL, | 2971 | qphy_clrbits(dp_com, QPHY_V3_DP_COM_RESET_OVRD_CTRL, |
| 2541 | SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | | 2972 | SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | |
| 2542 | SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET); | 2973 | SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET); |
| 2974 | |||
| 2975 | qphy_clrbits(dp_com, QPHY_V3_DP_COM_SWI_CTRL, 0x03); | ||
| 2976 | qphy_clrbits(dp_com, QPHY_V3_DP_COM_SW_RESET, SW_RESET); | ||
| 2543 | } | 2977 | } |
| 2544 | 2978 | ||
| 2545 | if (cfg->has_phy_com_ctrl) { | 2979 | if (cfg->has_phy_com_ctrl) { |
| @@ -2555,36 +2989,10 @@ static int qcom_qmp_phy_com_init(struct qmp_phy *qphy) · 9 unmodified lines | |||
| 2555 | cfg->pwrdn_ctrl); | 2989 | cfg->pwrdn_ctrl); |
| 2556 | } | 2990 | } |
| 2557 | 2991 | ||
| 2558 | /* Serdes configuration */ | ||
| 2559 | qcom_qmp_phy_configure(serdes, cfg->regs, cfg->serdes_tbl, | ||
| 2560 | cfg->serdes_tbl_num); | ||
| 2561 | |||
| 2562 | if (cfg->has_phy_com_ctrl) { | ||
| 2563 | void __iomem *status; | ||
| 2564 | unsigned int mask, val; | ||
| 2565 | |||
| 2566 | qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], SW_RESET); | ||
| 2567 | qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL], | ||
| 2568 | SERDES_START | PCS_START); | ||
| 2569 | |||
| 2570 | status = serdes + cfg->regs[QPHY_COM_PCS_READY_STATUS]; | ||
| 2571 | mask = cfg->mask_com_pcs_ready; | ||
| 2572 | |||
| 2573 | ret = readl_poll_timeout(status, val, (val & mask), 10, | ||
| 2574 | PHY_INIT_COMPLETE_TIMEOUT); | ||
| 2575 | if (ret) { | ||
| 2576 | dev_err(qmp->dev, | ||
| 2577 | "phy common block init timed-out\n"); | ||
| 2578 | goto err_com_init; | ||
| 2579 | } | ||
| 2580 | } | ||
| 2581 | |||
| 2582 | mutex_unlock(&qmp->phy_mutex); | 2992 | mutex_unlock(&qmp->phy_mutex); |
| 2583 | 2993 | ||
| 2584 | return 0; | 2994 | return 0; |
| 2585 | 2995 | ||
| 2586 | err_com_init: | ||
| 2587 | clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); | ||
| 2588 | err_rst: | 2996 | err_rst: |
| 2589 | while (++i < cfg->num_resets) | 2997 | while (++i < cfg->num_resets) |
| 2590 | reset_control_assert(qmp->resets[i]); | 2998 | reset_control_assert(qmp->resets[i]); |
| @@ -2596,10 +3004,11 @@ err_reg_enable: · 5 unmodified lines | |||
| 2596 | return ret; | 3004 | return ret; |
| 2597 | } | 3005 | } |
| 2598 | 3006 | ||
| 2599 | static int qcom_qmp_phy_com_exit(struct qcom_qmp *qmp) | 3007 | static int qcom_qmp_phy_com_exit(struct qmp_phy *qphy) |
| 2600 | { | 3008 | { |
| 2601 | const struct qmp_phy_cfg *cfg = qmp->cfg; | 3009 | struct qcom_qmp *qmp = qphy->qmp; |
| 2602 | void __iomem *serdes = qmp->serdes; | 3010 | const struct qmp_phy_cfg *cfg = qphy->cfg; |
| 3011 | void __iomem *serdes = qphy->serdes; | ||
| 2603 | int i = cfg->num_resets; | 3012 | int i = cfg->num_resets; |
| 2604 | 3013 | ||
| 2605 | mutex_lock(&qmp->phy_mutex); | 3014 | mutex_lock(&qmp->phy_mutex); |
| @@ -2630,20 +3039,12 @@ static int qcom_qmp_phy_com_exit(struct qcom_qmp *qmp) · 24 unmodified lines | |||
| 2630 | return 0; | 3039 | return 0; |
| 2631 | } | 3040 | } |
| 2632 | 3041 | ||
| 2633 | static int qcom_qmp_phy_enable(struct phy *phy) | 3042 | static int qcom_qmp_phy_init(struct phy *phy) |
| 2634 | { | 3043 | { |
| 2635 | struct qmp_phy *qphy = phy_get_drvdata(phy); | 3044 | struct qmp_phy *qphy = phy_get_drvdata(phy); |
| 2636 | struct qcom_qmp *qmp = qphy->qmp; | 3045 | struct qcom_qmp *qmp = qphy->qmp; |
| 2637 | const struct qmp_phy_cfg *cfg = qmp->cfg; | 3046 | const struct qmp_phy_cfg *cfg = qphy->cfg; |
| 2638 | void __iomem *tx = qphy->tx; | ||
| 2639 | void __iomem *rx = qphy->rx; | ||
| 2640 | void __iomem *pcs = qphy->pcs; | ||
| 2641 | void __iomem *pcs_misc = qphy->pcs_misc; | ||
| 2642 | void __iomem *dp_com = qmp->dp_com; | ||
| 2643 | void __iomem *status; | ||
| 2644 | unsigned int mask, val, ready; | ||
| 2645 | int ret; | 3047 | int ret; |
| 2646 | |||
| 2647 | dev_vdbg(qmp->dev, "Initializing QMP phy\n"); | 3048 | dev_vdbg(qmp->dev, "Initializing QMP phy\n"); |
| 2648 | 3049 | ||
| 2649 | if (cfg->no_pcs_sw_reset) { | 3050 | if (cfg->no_pcs_sw_reset) { |
| @@ -2670,13 +3071,34 @@ static int qcom_qmp_phy_enable(struct phy *phy) · 20 unmodified lines | |||
| 2670 | 3071 | ||
| 2671 | ret = reset_control_assert(qmp->ufs_reset); | 3072 | ret = reset_control_assert(qmp->ufs_reset); |
| 2672 | if (ret) | 3073 | if (ret) |
| 2673 | goto err_lane_rst; | 3074 | return ret; |
| 2674 | } | 3075 | } |
| 2675 | 3076 | ||
| 2676 | ret = qcom_qmp_phy_com_init(qphy); | 3077 | ret = qcom_qmp_phy_com_init(qphy); |
| 2677 | if (ret) | 3078 | if (ret) |
| 2678 | return ret; | 3079 | return ret; |
| 2679 | 3080 | ||
| 3081 | if (cfg->type == PHY_TYPE_DP) | ||
| 3082 | qcom_qmp_phy_dp_aux_init(qphy); | ||
| 3083 | |||
| 3084 | return 0; | ||
| 3085 | } | ||
| 3086 | |||
| 3087 | static int qcom_qmp_phy_power_on(struct phy *phy) | ||
| 3088 | { | ||
| 3089 | struct qmp_phy *qphy = phy_get_drvdata(phy); | ||
| 3090 | struct qcom_qmp *qmp = qphy->qmp; | ||
| 3091 | const struct qmp_phy_cfg *cfg = qphy->cfg; | ||
| 3092 | void __iomem *tx = qphy->tx; | ||
| 3093 | void __iomem *rx = qphy->rx; | ||
| 3094 | void __iomem *pcs = qphy->pcs; | ||
| 3095 | void __iomem *pcs_misc = qphy->pcs_misc; | ||
| 3096 | void __iomem *status; | ||
| 3097 | unsigned int mask, val, ready; | ||
| 3098 | int ret; | ||
| 3099 | |||
| 3100 | qcom_qmp_phy_serdes_init(qphy); | ||
| 3101 | |||
| 2680 | if (cfg->has_lane_rst) { | 3102 | if (cfg->has_lane_rst) { |
| 2681 | ret = reset_control_deassert(qphy->lane_rst); | 3103 | ret = reset_control_deassert(qphy->lane_rst); |
| 2682 | if (ret) { | 3104 | if (ret) { |
| @@ -2700,13 +3122,23 @@ static int qcom_qmp_phy_enable(struct phy *phy) · 17 unmodified lines | |||
| 2700 | qcom_qmp_phy_configure_lane(qphy->tx2, cfg->regs, | 3122 | qcom_qmp_phy_configure_lane(qphy->tx2, cfg->regs, |
| 2701 | cfg->tx_tbl, cfg->tx_tbl_num, 2); | 3123 | cfg->tx_tbl, cfg->tx_tbl_num, 2); |
| 2702 | 3124 | ||
| 3125 | /* Configure special DP tx tunings */ | ||
| 3126 | if (cfg->type == PHY_TYPE_DP) | ||
| 3127 | qcom_qmp_phy_configure_dp_tx(qphy); | ||
| 3128 | |||
| 2703 | qcom_qmp_phy_configure_lane(rx, cfg->regs, | 3129 | qcom_qmp_phy_configure_lane(rx, cfg->regs, |
| 2704 | cfg->rx_tbl, cfg->rx_tbl_num, 1); | 3130 | cfg->rx_tbl, cfg->rx_tbl_num, 1); |
| 3131 | |||
| 2705 | if (cfg->is_dual_lane_phy) | 3132 | if (cfg->is_dual_lane_phy) |
| 2706 | qcom_qmp_phy_configure_lane(qphy->rx2, cfg->regs, | 3133 | qcom_qmp_phy_configure_lane(qphy->rx2, cfg->regs, |
| 2707 | cfg->rx_tbl, cfg->rx_tbl_num, 2); | 3134 | cfg->rx_tbl, cfg->rx_tbl_num, 2); |
| 2708 | 3135 | ||
| 2709 | qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); | 3136 | /* Configure link rate, swing, etc. */ |
| 3137 | if (cfg->type == PHY_TYPE_DP) | ||
| 3138 | qcom_qmp_phy_configure_dp_phy(qphy); | ||
| 3139 | else | ||
| 3140 | qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); | ||
| 3141 | |||
| 2710 | ret = reset_control_deassert(qmp->ufs_reset); | 3142 | ret = reset_control_deassert(qmp->ufs_reset); |
| 2711 | if (ret) | 3143 | if (ret) |
| 2712 | goto err_lane_rst; | 3144 | goto err_lane_rst; |
| @@ -2724,102 +3156,129 @@ static int qcom_qmp_phy_enable(struct phy *phy) · 11 unmodified lines | |||
| 2724 | if (cfg->has_pwrdn_delay) | 3156 | if (cfg->has_pwrdn_delay) |
| 2725 | usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max); | 3157 | usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max); |
| 2726 | 3158 | ||
| 2727 | /* Pull PHY out of reset state */ | 3159 | if (cfg->type != PHY_TYPE_DP) { |
| 2728 | if (!cfg->no_pcs_sw_reset) | 3160 | /* Pull PHY out of reset state */ |
| 2729 | qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); | 3161 | if (!cfg->no_pcs_sw_reset) |
| 2730 | 3162 | qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); | |
| 2731 | if (cfg->has_phy_dp_com_ctrl) | 3163 | /* start SerDes and Phy-Coding-Sublayer */ |
| 2732 | qphy_clrbits(dp_com, QPHY_V3_DP_COM_SW_RESET, SW_RESET); | 3164 | qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); |
| 2733 | 3165 | ||
| 2734 | /* start SerDes and Phy-Coding-Sublayer */ | 3166 | if (cfg->type == PHY_TYPE_UFS) { |
| 2735 | qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); | 3167 | status = pcs + cfg->regs[QPHY_PCS_READY_STATUS]; |
| 2736 | 3168 | mask = PCS_READY; | |
| 2737 | if (cfg->type == PHY_TYPE_UFS) { | 3169 | ready = PCS_READY; |
| 2738 | status = pcs + cfg->regs[QPHY_PCS_READY_STATUS]; | 3170 | } else { |
| 2739 | mask = PCS_READY; | 3171 | status = pcs + cfg->regs[QPHY_PCS_STATUS]; |
| 2740 | ready = PCS_READY; | 3172 | mask = PHYSTATUS; |
| 2741 | } else { | 3173 | ready = 0; |
| 2742 | status = pcs + cfg->regs[QPHY_PCS_STATUS]; | 3174 | } |
| 2743 | mask = PHYSTATUS; | ||
| 2744 | ready = 0; | ||
| 2745 | } | ||
| 2746 | 3175 | ||
| 2747 | ret = readl_poll_timeout(status, val, (val & mask) == ready, 10, | 3176 | ret = readl_poll_timeout(status, val, (val & mask) == ready, 10, |
| 2748 | PHY_INIT_COMPLETE_TIMEOUT); | 3177 | PHY_INIT_COMPLETE_TIMEOUT); |
| 2749 | if (ret) { | 3178 | if (ret) { |
| 2750 | dev_err(qmp->dev, "phy initialization timed-out\n"); | 3179 | dev_err(qmp->dev, "phy initialization timed-out\n"); |
| 2751 | goto err_pcs_ready; | 3180 | goto err_pcs_ready; |
| 3181 | } | ||
| 2752 | } | 3182 | } |
| 2753 | qmp->phy_initialized = true; | ||
| 2754 | return 0; | 3183 | return 0; |
| 2755 | 3184 | ||
| 2756 | err_pcs_ready: | 3185 | err_pcs_ready: |
| 2757 | reset_control_assert(qmp->ufs_reset); | ||
| 2758 | clk_disable_unprepare(qphy->pipe_clk); | 3186 | clk_disable_unprepare(qphy->pipe_clk); |
| 2759 | err_clk_enable: | 3187 | err_clk_enable: |
| 2760 | if (cfg->has_lane_rst) | 3188 | if (cfg->has_lane_rst) |
| 2761 | reset_control_assert(qphy->lane_rst); | 3189 | reset_control_assert(qphy->lane_rst); |
| 2762 | err_lane_rst: | 3190 | err_lane_rst: |
| 2763 | qcom_qmp_phy_com_exit(qmp); | ||
| 2764 | |||
| 2765 | return ret; | 3191 | return ret; |
| 2766 | } | 3192 | } |
| 2767 | 3193 | ||
| 2768 | static int qcom_qmp_phy_disable(struct phy *phy) | 3194 | static int qcom_qmp_phy_power_off(struct phy *phy) |
| 2769 | { | 3195 | { |
| 2770 | struct qmp_phy *qphy = phy_get_drvdata(phy); | 3196 | struct qmp_phy *qphy = phy_get_drvdata(phy); |
| 2771 | struct qcom_qmp *qmp = qphy->qmp; | 3197 | const struct qmp_phy_cfg *cfg = qphy->cfg; |
| 2772 | const struct qmp_phy_cfg *cfg = qmp->cfg; | ||
| 2773 | 3198 | ||
| 2774 | clk_disable_unprepare(qphy->pipe_clk); | 3199 | clk_disable_unprepare(qphy->pipe_clk); |
| 2775 | 3200 | ||
| 2776 | /* PHY reset */ | 3201 | if (cfg->type == PHY_TYPE_DP) { |
| 2777 | if (!cfg->no_pcs_sw_reset) | 3202 | /* Assert DP PHY power down */ |
| 2778 | qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); | 3203 | writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL); |
| 3204 | } else { | ||
| 3205 | /* PHY reset */ | ||
| 3206 | if (!cfg->no_pcs_sw_reset) | ||
| 3207 | qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); | ||
| 2779 | 3208 | ||
| 2780 | /* stop SerDes and Phy-Coding-Sublayer */ | 3209 | /* stop SerDes and Phy-Coding-Sublayer */ |
| 2781 | qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); | 3210 | qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); |
| 2782 | 3211 | ||
| 2783 | /* Put PHY into POWER DOWN state: active low */ | 3212 | /* Put PHY into POWER DOWN state: active low */ |
| 2784 | if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) { | 3213 | if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) { |
| 2785 | qphy_clrbits(qphy->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], | 3214 | qphy_clrbits(qphy->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], |
| 2786 | cfg->pwrdn_ctrl); | 3215 | cfg->pwrdn_ctrl); |
| 2787 | } else { | 3216 | } else { |
| 2788 | qphy_clrbits(qphy->pcs, QPHY_POWER_DOWN_CONTROL, | 3217 | qphy_clrbits(qphy->pcs, QPHY_POWER_DOWN_CONTROL, |
| 2789 | cfg->pwrdn_ctrl); | 3218 | cfg->pwrdn_ctrl); |
| 3219 | } | ||
| 2790 | } | 3220 | } |
| 2791 | 3221 | ||
| 3222 | return 0; | ||
| 3223 | } | ||
| 3224 | |||
| 3225 | static int qcom_qmp_phy_exit(struct phy *phy) | ||
| 3226 | { | ||
| 3227 | struct qmp_phy *qphy = phy_get_drvdata(phy); | ||
| 3228 | const struct qmp_phy_cfg *cfg = qphy->cfg; | ||
| 3229 | |||
| 2792 | if (cfg->has_lane_rst) | 3230 | if (cfg->has_lane_rst) |
| 2793 | reset_control_assert(qphy->lane_rst); | 3231 | reset_control_assert(qphy->lane_rst); |
| 2794 | 3232 | ||
| 2795 | qcom_qmp_phy_com_exit(qmp); | 3233 | qcom_qmp_phy_com_exit(qphy); |
| 2796 | |||
| 2797 | qmp->phy_initialized = false; | ||
| 2798 | 3234 | ||
| 2799 | return 0; | 3235 | return 0; |
| 2800 | } | 3236 | } |
| 2801 | 3237 | ||
| 3238 | static int qcom_qmp_phy_enable(struct phy *phy) | ||
| 3239 | { | ||
| 3240 | int ret; | ||
| 3241 | |||
| 3242 | ret = qcom_qmp_phy_init(phy); | ||
| 3243 | if (ret) | ||
| 3244 | return ret; | ||
| 3245 | |||
| 3246 | ret = qcom_qmp_phy_power_on(phy); | ||
| 3247 | if (ret) | ||
| 3248 | qcom_qmp_phy_exit(phy); | ||
| 3249 | |||
| 3250 | return ret; | ||
| 3251 | } | ||
| 3252 | |||
| 3253 | static int qcom_qmp_phy_disable(struct phy *phy) | ||
| 3254 | { | ||
| 3255 | int ret; | ||
| 3256 | |||
| 3257 | ret = qcom_qmp_phy_power_off(phy); | ||
| 3258 | if (ret) | ||
| 3259 | return ret; | ||
| 3260 | return qcom_qmp_phy_exit(phy); | ||
| 3261 | } | ||
| 3262 | |||
| 2802 | static int qcom_qmp_phy_set_mode(struct phy *phy, | 3263 | static int qcom_qmp_phy_set_mode(struct phy *phy, |
| 2803 | enum phy_mode mode, int submode) | 3264 | enum phy_mode mode, int submode) |
| 2804 | { | 3265 | { |
| 2805 | struct qmp_phy *qphy = phy_get_drvdata(phy); | 3266 | struct qmp_phy *qphy = phy_get_drvdata(phy); |
| 2806 | struct qcom_qmp *qmp = qphy->qmp; | ||
| 2807 | 3267 | ||
| 2808 | qmp->mode = mode; | 3268 | qphy->mode = mode; |
| 2809 | 3269 | ||
| 2810 | return 0; | 3270 | return 0; |
| 2811 | } | 3271 | } |
| 2812 | 3272 | ||
| 2813 | static void qcom_qmp_phy_enable_autonomous_mode(struct qmp_phy *qphy) | 3273 | static void qcom_qmp_phy_enable_autonomous_mode(struct qmp_phy *qphy) |
| 2814 | { | 3274 | { |
| 2815 | struct qcom_qmp *qmp = qphy->qmp; | 3275 | const struct qmp_phy_cfg *cfg = qphy->cfg; |
| 2816 | const struct qmp_phy_cfg *cfg = qmp->cfg; | ||
| 2817 | void __iomem *pcs = qphy->pcs; | 3276 | void __iomem *pcs = qphy->pcs; |
| 2818 | void __iomem *pcs_misc = qphy->pcs_misc; | 3277 | void __iomem *pcs_misc = qphy->pcs_misc; |
| 2819 | u32 intr_mask; | 3278 | u32 intr_mask; |
| 2820 | 3279 | ||
| 2821 | if (qmp->mode == PHY_MODE_USB_HOST_SS || | 3280 | if (qphy->mode == PHY_MODE_USB_HOST_SS || |
| 2822 | qmp->mode == PHY_MODE_USB_DEVICE_SS) | 3281 | qphy->mode == PHY_MODE_USB_DEVICE_SS) |
| 2823 | intr_mask = ARCVR_DTCT_EN | ALFPS_DTCT_EN; | 3282 | intr_mask = ARCVR_DTCT_EN | ALFPS_DTCT_EN; |
| 2824 | else | 3283 | else |
| 2825 | intr_mask = ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL; | 3284 | intr_mask = ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL; |
| @@ -2842,8 +3301,7 @@ static void qcom_qmp_phy_enable_autonomous_mode(struct qmp_phy *qphy) · 16 unmodified lines | |||
| 2842 | 3301 | ||
| 2843 | static void qcom_qmp_phy_disable_autonomous_mode(struct qmp_phy *qphy) | 3302 | static void qcom_qmp_phy_disable_autonomous_mode(struct qmp_phy *qphy) |
| 2844 | { | 3303 | { |
| 2845 | struct qcom_qmp *qmp = qphy->qmp; | 3304 | const struct qmp_phy_cfg *cfg = qphy->cfg; |
| 2846 | const struct qmp_phy_cfg *cfg = qmp->cfg; | ||
| 2847 | void __iomem *pcs = qphy->pcs; | 3305 | void __iomem *pcs = qphy->pcs; |
| 2848 | void __iomem *pcs_misc = qphy->pcs_misc; | 3306 | void __iomem *pcs_misc = qphy->pcs_misc; |
| 2849 | 3307 | ||
| @@ -2863,15 +3321,15 @@ static int __maybe_unused qcom_qmp_phy_runtime_suspend(struct device *dev) · 13 unmodified lines | |||
| 2863 | { | 3321 | { |
| 2864 | struct qcom_qmp *qmp = dev_get_drvdata(dev); | 3322 | struct qcom_qmp *qmp = dev_get_drvdata(dev); |
| 2865 | struct qmp_phy *qphy = qmp->phys[0]; | 3323 | struct qmp_phy *qphy = qmp->phys[0]; |
| 2866 | const struct qmp_phy_cfg *cfg = qmp->cfg; | 3324 | const struct qmp_phy_cfg *cfg = qphy->cfg; |
| 2867 | 3325 | ||
| 2868 | dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qmp->mode); | 3326 | dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qphy->mode); |
| 2869 | 3327 | ||
| 2870 | /* Supported only for USB3 PHY */ | 3328 | /* Supported only for USB3 PHY and luckily USB3 is the first phy */ |
| 2871 | if (cfg->type != PHY_TYPE_USB3) | 3329 | if (cfg->type != PHY_TYPE_USB3) |
| 2872 | return 0; | 3330 | return 0; |
| 2873 | 3331 | ||
| 2874 | if (!qmp->phy_initialized) { | 3332 | if (!qmp->init_count) { |
| 2875 | dev_vdbg(dev, "PHY not initialized, bailing out\n"); | 3333 | dev_vdbg(dev, "PHY not initialized, bailing out\n"); |
| 2876 | return 0; | 3334 | return 0; |
| 2877 | } | 3335 | } |
| @@ -2888,16 +3346,16 @@ static int __maybe_unused qcom_qmp_phy_runtime_resume(struct device *dev) · 10 unmodified lines | |||
| 2888 | { | 3346 | { |
| 2889 | struct qcom_qmp *qmp = dev_get_drvdata(dev); | 3347 | struct qcom_qmp *qmp = dev_get_drvdata(dev); |
| 2890 | struct qmp_phy *qphy = qmp->phys[0]; | 3348 | struct qmp_phy *qphy = qmp->phys[0]; |
| 2891 | const struct qmp_phy_cfg *cfg = qmp->cfg; | 3349 | const struct qmp_phy_cfg *cfg = qphy->cfg; |
| 2892 | int ret = 0; | 3350 | int ret = 0; |
| 2893 | 3351 | ||
| 2894 | dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qmp->mode); | 3352 | dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qphy->mode); |
| 2895 | 3353 | ||
| 2896 | /* Supported only for USB3 PHY */ | 3354 | /* Supported only for USB3 PHY and luckily USB3 is the first phy */ |
| 2897 | if (cfg->type != PHY_TYPE_USB3) | 3355 | if (cfg->type != PHY_TYPE_USB3) |
| 2898 | return 0; | 3356 | return 0; |
| 2899 | 3357 | ||
| 2900 | if (!qmp->phy_initialized) { | 3358 | if (!qmp->init_count) { |
| 2901 | dev_vdbg(dev, "PHY not initialized, bailing out\n"); | 3359 | dev_vdbg(dev, "PHY not initialized, bailing out\n"); |
| 2902 | return 0; | 3360 | return 0; |
| 2903 | } | 3361 | } |
| @@ -2920,10 +3378,10 @@ static int __maybe_unused qcom_qmp_phy_runtime_resume(struct device *dev) · 16 unmodified lines | |||
| 2920 | return 0; | 3378 | return 0; |
| 2921 | } | 3379 | } |
| 2922 | 3380 | ||
| 2923 | static int qcom_qmp_phy_vreg_init(struct device *dev) | 3381 | static int qcom_qmp_phy_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg) |
| 2924 | { | 3382 | { |
| 2925 | struct qcom_qmp *qmp = dev_get_drvdata(dev); | 3383 | struct qcom_qmp *qmp = dev_get_drvdata(dev); |
| 2926 | int num = qmp->cfg->num_vregs; | 3384 | int num = cfg->num_vregs; |
| 2927 | int i; | 3385 | int i; |
| 2928 | 3386 | ||
| 2929 | qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL); | 3387 | qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL); |
| @@ -2931,24 +3389,24 @@ static int qcom_qmp_phy_vreg_init(struct device *dev) · 1 unmodified line | |||
| 2931 | return -ENOMEM; | 3389 | return -ENOMEM; |
| 2932 | 3390 | ||
| 2933 | for (i = 0; i < num; i++) | 3391 | for (i = 0; i < num; i++) |
| 2934 | qmp->vregs[i].supply = qmp->cfg->vreg_list[i]; | 3392 | qmp->vregs[i].supply = cfg->vreg_list[i]; |
| 2935 | 3393 | ||
| 2936 | return devm_regulator_bulk_get(dev, num, qmp->vregs); | 3394 | return devm_regulator_bulk_get(dev, num, qmp->vregs); |
| 2937 | } | 3395 | } |
| 2938 | 3396 | ||
| 2939 | static int qcom_qmp_phy_reset_init(struct device *dev) | 3397 | static int qcom_qmp_phy_reset_init(struct device *dev, const struct qmp_phy_cfg *cfg) |
| 2940 | { | 3398 | { |
| 2941 | struct qcom_qmp *qmp = dev_get_drvdata(dev); | 3399 | struct qcom_qmp *qmp = dev_get_drvdata(dev); |
| 2942 | int i; | 3400 | int i; |
| 2943 | 3401 | ||
| 2944 | qmp->resets = devm_kcalloc(dev, qmp->cfg->num_resets, | 3402 | qmp->resets = devm_kcalloc(dev, cfg->num_resets, |
| 2945 | sizeof(*qmp->resets), GFP_KERNEL); | 3403 | sizeof(*qmp->resets), GFP_KERNEL); |
| 2946 | if (!qmp->resets) | 3404 | if (!qmp->resets) |
| 2947 | return -ENOMEM; | 3405 | return -ENOMEM; |
| 2948 | 3406 | ||
| 2949 | for (i = 0; i < qmp->cfg->num_resets; i++) { | 3407 | for (i = 0; i < cfg->num_resets; i++) { |
| 2950 | struct reset_control *rst; | 3408 | struct reset_control *rst; |
| 2951 | const char *name = qmp->cfg->reset_list[i]; | 3409 | const char *name = cfg->reset_list[i]; |
| 2952 | 3410 | ||
| 2953 | rst = devm_reset_control_get(dev, name); | 3411 | rst = devm_reset_control_get(dev, name); |
| 2954 | if (IS_ERR(rst)) { | 3412 | if (IS_ERR(rst)) { |
| @@ -2961,10 +3419,10 @@ static int qcom_qmp_phy_reset_init(struct device *dev) · 6 unmodified lines | |||
| 2961 | return 0; | 3419 | return 0; |
| 2962 | } | 3420 | } |
| 2963 | 3421 | ||
| 2964 | static int qcom_qmp_phy_clk_init(struct device *dev) | 3422 | static int qcom_qmp_phy_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg) |
| 2965 | { | 3423 | { |
| 2966 | struct qcom_qmp *qmp = dev_get_drvdata(dev); | 3424 | struct qcom_qmp *qmp = dev_get_drvdata(dev); |
| 2967 | int num = qmp->cfg->num_clks; | 3425 | int num = cfg->num_clks; |
| 2968 | int i; | 3426 | int i; |
| 2969 | 3427 | ||
| 2970 | qmp->clks = devm_kcalloc(dev, num, sizeof(*qmp->clks), GFP_KERNEL); | 3428 | qmp->clks = devm_kcalloc(dev, num, sizeof(*qmp->clks), GFP_KERNEL); |
| @@ -2972,12 +3430,12 @@ static int qcom_qmp_phy_clk_init(struct device *dev) · 1 unmodified line | |||
| 2972 | return -ENOMEM; | 3430 | return -ENOMEM; |
| 2973 | 3431 | ||
| 2974 | for (i = 0; i < num; i++) | 3432 | for (i = 0; i < num; i++) |
| 2975 | qmp->clks[i].id = qmp->cfg->clk_list[i]; | 3433 | qmp->clks[i].id = cfg->clk_list[i]; |
| 2976 | 3434 | ||
| 2977 | return devm_clk_bulk_get(dev, num, qmp->clks); | 3435 | return devm_clk_bulk_get(dev, num, qmp->clks); |
| 2978 | } | 3436 | } |
| 2979 | 3437 | ||
| 2980 | static void phy_pipe_clk_release_provider(void *res) | 3438 | static void phy_clk_release_provider(void *res) |
| 2981 | { | 3439 | { |
| 2982 | of_clk_del_provider(res); | 3440 | of_clk_del_provider(res); |
| 2983 | } | 3441 | } |
| @@ -3006,12 +3464,6 @@ static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np) · 22 unmodified lines | |||
| 3006 | struct clk_init_data init = { }; | 3464 | struct clk_init_data init = { }; |
| 3007 | int ret; | 3465 | int ret; |
| 3008 | 3466 | ||
| 3009 | if ((qmp->cfg->type != PHY_TYPE_USB3) && | ||
| 3010 | (qmp->cfg->type != PHY_TYPE_PCIE)) { | ||
| 3011 | /* not all phys register pipe clocks, so return success */ | ||
| 3012 | return 0; | ||
| 3013 | } | ||
| 3014 | |||
| 3015 | ret = of_property_read_string(np, "clock-output-names", &init.name); | 3467 | ret = of_property_read_string(np, "clock-output-names", &init.name); |
| 3016 | if (ret) { | 3468 | if (ret) { |
| 3017 | dev_err(qmp->dev, "%pOFn: No clock-output-names\n", np); | 3469 | dev_err(qmp->dev, "%pOFn: No clock-output-names\n", np); |
| @@ -3040,9 +3492,202 @@ static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np) · 22 unmodified lines | |||
| 3040 | * Roll a devm action because the clock provider is the child node, but | 3492 | * Roll a devm action because the clock provider is the child node, but |
| 3041 | * the child node is not actually a device. | 3493 | * the child node is not actually a device. |
| 3042 | */ | 3494 | */ |
| 3043 | ret = devm_add_action(qmp->dev, phy_pipe_clk_release_provider, np); | 3495 | ret = devm_add_action(qmp->dev, phy_clk_release_provider, np); |
| 3496 | if (ret) | ||
| 3497 | phy_clk_release_provider(np); | ||
| 3498 | |||
| 3499 | return ret; | ||
| 3500 | } | ||
| 3501 | |||
| 3502 | /* | ||
| 3503 | * Display Port PLL driver block diagram for branch clocks | ||
| 3504 | * | ||
| 3505 | * +------------------------------+ | ||
| 3506 | * | DP_VCO_CLK | | ||
| 3507 | * | | | ||
| 3508 | * | +-------------------+ | | ||
| 3509 | * | | (DP PLL/VCO) | | | ||
| 3510 | * | +---------+---------+ | | ||
| 3511 | * | v | | ||
| 3512 | * | +----------+-----------+ | | ||
| 3513 | * | | hsclk_divsel_clk_src | | | ||
| 3514 | * | +----------+-----------+ | | ||
| 3515 | * +------------------------------+ | ||
| 3516 | * | | ||
| 3517 | * +---------<---------v------------>----------+ | ||
| 3518 | * | | | ||
| 3519 | * +--------v----------------+ | | ||
| 3520 | * | dp_phy_pll_link_clk | | | ||
| 3521 | * | link_clk | | | ||
| 3522 | * +--------+----------------+ | | ||
| 3523 | * | | | ||
| 3524 | * | | | ||
| 3525 | * v v | ||
| 3526 | * Input to DISPCC block | | ||
| 3527 | * for link clk, crypto clk | | ||
| 3528 | * and interface clock | | ||
| 3529 | * | | ||
| 3530 | * | | ||
| 3531 | * +--------<------------+-----------------+---<---+ | ||
| 3532 | * | | | | ||
| 3533 | * +----v---------+ +--------v-----+ +--------v------+ | ||
| 3534 | * | vco_divided | | vco_divided | | vco_divided | | ||
| 3535 | * | _clk_src | | _clk_src | | _clk_src | | ||
| 3536 | * | | | | | | | ||
| 3537 | * |divsel_six | | divsel_two | | divsel_four | | ||
| 3538 | * +-------+------+ +-----+--------+ +--------+------+ | ||
| 3539 | * | | | | ||
| 3540 | * v---->----------v-------------<------v | ||
| 3541 | * | | ||
| 3542 | * +----------+-----------------+ | ||
| 3543 | * | dp_phy_pll_vco_div_clk | | ||
| 3544 | * +---------+------------------+ | ||
| 3545 | * | | ||
| 3546 | * v | ||
| 3547 | * Input to DISPCC block | ||
| 3548 | * for DP pixel clock | ||
| 3549 | * | ||
| 3550 | */ | ||
| 3551 | static int qcom_qmp_dp_pixel_clk_determine_rate(struct clk_hw *hw, | ||
| 3552 | struct clk_rate_request *req) | ||
| 3553 | { | ||
| 3554 | switch (req->rate) { | ||
| 3555 | case 1620000000UL / 2: | ||
| 3556 | case 2700000000UL / 2: | ||
| 3557 | /* 5.4 and 8.1 GHz are same link rate as 2.7GHz, i.e. div 4 and div 6 */ | ||
| 3558 | return 0; | ||
| 3559 | default: | ||
| 3560 | return -EINVAL; | ||
| 3561 | } | ||
| 3562 | } | ||
| 3563 | |||
| 3564 | static unsigned long | ||
| 3565 | qcom_qmp_dp_pixel_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) | ||
| 3566 | { | ||
| 3567 | const struct qmp_phy_dp_clks *dp_clks; | ||
| 3568 | const struct qmp_phy *qphy; | ||
| 3569 | const struct phy_configure_opts_dp *dp_opts; | ||
| 3570 | |||
| 3571 | dp_clks = container_of(hw, struct qmp_phy_dp_clks, dp_pixel_hw); | ||
| 3572 | qphy = dp_clks->qphy; | ||
| 3573 | dp_opts = &qphy->dp_opts; | ||
| 3574 | |||
| 3575 | switch (dp_opts->link_rate) { | ||
| 3576 | case 1620: | ||
| 3577 | return 1620000000UL / 2; | ||
| 3578 | case 2700: | ||
| 3579 | return 2700000000UL / 2; | ||
| 3580 | case 5400: | ||
| 3581 | return 5400000000UL / 4; | ||
| 3582 | case 8100: | ||
| 3583 | return 8100000000UL / 6; | ||
| 3584 | default: | ||
| 3585 | return 0; | ||
| 3586 | } | ||
| 3587 | } | ||
| 3588 | |||
| 3589 | static const struct clk_ops qcom_qmp_dp_pixel_clk_ops = { | ||
| 3590 | .determine_rate = qcom_qmp_dp_pixel_clk_determine_rate, | ||
| 3591 | .recalc_rate = qcom_qmp_dp_pixel_clk_recalc_rate, | ||
| 3592 | }; | ||
| 3593 | |||
| 3594 | static int qcom_qmp_dp_link_clk_determine_rate(struct clk_hw *hw, | ||
| 3595 | struct clk_rate_request *req) | ||
| 3596 | { | ||
| 3597 | switch (req->rate) { | ||
| 3598 | case 162000000: | ||
| 3599 | case 270000000: | ||
| 3600 | case 540000000: | ||
| 3601 | case 810000000: | ||
| 3602 | return 0; | ||
| 3603 | default: | ||
| 3604 | return -EINVAL; | ||
| 3605 | } | ||
| 3606 | } | ||
| 3607 | |||
| 3608 | static unsigned long | ||
| 3609 | qcom_qmp_dp_link_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) | ||
| 3610 | { | ||
| 3611 | const struct qmp_phy_dp_clks *dp_clks; | ||
| 3612 | const struct qmp_phy *qphy; | ||
| 3613 | const struct phy_configure_opts_dp *dp_opts; | ||
| 3614 | |||
| 3615 | dp_clks = container_of(hw, struct qmp_phy_dp_clks, dp_link_hw); | ||
| 3616 | qphy = dp_clks->qphy; | ||
| 3617 | dp_opts = &qphy->dp_opts; | ||
| 3618 | |||
| 3619 | switch (dp_opts->link_rate) { | ||
| 3620 | case 1620: | ||
| 3621 | case 2700: | ||
| 3622 | case 5400: | ||
| 3623 | case 8100: | ||
| 3624 | return dp_opts->link_rate * 100000; | ||
| 3625 | default: | ||
| 3626 | return 0; | ||
| 3627 | } | ||
| 3628 | } | ||
| 3629 | |||
| 3630 | static const struct clk_ops qcom_qmp_dp_link_clk_ops = { | ||
| 3631 | .determine_rate = qcom_qmp_dp_link_clk_determine_rate, | ||
| 3632 | .recalc_rate = qcom_qmp_dp_link_clk_recalc_rate, | ||
| 3633 | }; | ||
| 3634 | |||
| 3635 | static struct clk_hw * | ||
| 3636 | qcom_qmp_dp_clks_hw_get(struct of_phandle_args *clkspec, void *data) | ||
| 3637 | { | ||
| 3638 | struct qmp_phy_dp_clks *dp_clks = data; | ||
| 3639 | unsigned int idx = clkspec->args[0]; | ||
| 3640 | |||
| 3641 | if (idx >= 2) { | ||
| 3642 | pr_err("%s: invalid index %u\n", __func__, idx); | ||
| 3643 | return ERR_PTR(-EINVAL); | ||
| 3644 | } | ||
| 3645 | |||
| 3646 | if (idx == 0) | ||
| 3647 | return &dp_clks->dp_link_hw; | ||
| 3648 | |||
| 3649 | return &dp_clks->dp_pixel_hw; | ||
| 3650 | } | ||
| 3651 | |||
| 3652 | static int phy_dp_clks_register(struct qcom_qmp *qmp, struct qmp_phy *qphy, | ||
| 3653 | struct device_node *np) | ||
| 3654 | { | ||
| 3655 | struct clk_init_data init = { }; | ||
| 3656 | struct qmp_phy_dp_clks *dp_clks; | ||
| 3657 | int ret; | ||
| 3658 | |||
| 3659 | dp_clks = devm_kzalloc(qmp->dev, sizeof(*dp_clks), GFP_KERNEL); | ||
| 3660 | if (!dp_clks) | ||
| 3661 | return -ENOMEM; | ||
| 3662 | |||
| 3663 | dp_clks->qphy = qphy; | ||
| 3664 | qphy->dp_clks = dp_clks; | ||
| 3665 | |||
| 3666 | init.ops = &qcom_qmp_dp_link_clk_ops; | ||
| 3667 | init.name = "qmp_dp_phy_pll_link_clk"; | ||
| 3668 | dp_clks->dp_link_hw.init = &init; | ||
| 3669 | ret = devm_clk_hw_register(qmp->dev, &dp_clks->dp_link_hw); | ||
| 3670 | if (ret) | ||
| 3671 | return ret; | ||
| 3672 | |||
| 3673 | init.ops = &qcom_qmp_dp_pixel_clk_ops; | ||
| 3674 | init.name = "qmp_dp_phy_pll_vco_div_clk"; | ||
| 3675 | dp_clks->dp_pixel_hw.init = &init; | ||
| 3676 | ret = devm_clk_hw_register(qmp->dev, &dp_clks->dp_pixel_hw); | ||
| 3677 | if (ret) | ||
| 3678 | return ret; | ||
| 3679 | |||
| 3680 | ret = of_clk_add_hw_provider(np, qcom_qmp_dp_clks_hw_get, dp_clks); | ||
| 3681 | if (ret) | ||
| 3682 | return ret; | ||
| 3683 | |||
| 3684 | /* | ||
| 3685 | * Roll a devm action because the clock provider is the child node, but | ||
| 3686 | * the child node is not actually a device. | ||
| 3687 | */ | ||
| 3688 | ret = devm_add_action(qmp->dev, phy_clk_release_provider, np); | ||
| 3044 | if (ret) | 3689 | if (ret) |
| 3045 | phy_pipe_clk_release_provider(np); | 3690 | phy_clk_release_provider(np); |
| 3046 | 3691 | ||
| 3047 | return ret; | 3692 | return ret; |
| 3048 | } | 3693 | } |
| @@ -3054,6 +3699,17 @@ static const struct phy_ops qcom_qmp_phy_gen_ops = { · 5 unmodified lines | |||
| 3054 | .owner = THIS_MODULE, | 3699 | .owner = THIS_MODULE, |
| 3055 | }; | 3700 | }; |
| 3056 | 3701 | ||
| 3702 | static const struct phy_ops qcom_qmp_phy_dp_ops = { | ||
| 3703 | .init = qcom_qmp_phy_init, | ||
| 3704 | .configure = qcom_qmp_dp_phy_configure, | ||
| 3705 | .power_on = qcom_qmp_phy_power_on, | ||
| 3706 | .calibrate = qcom_qmp_dp_phy_calibrate, | ||
| 3707 | .power_off = qcom_qmp_phy_power_off, | ||
| 3708 | .exit = qcom_qmp_phy_exit, | ||
| 3709 | .set_mode = qcom_qmp_phy_set_mode, | ||
| 3710 | .owner = THIS_MODULE, | ||
| 3711 | }; | ||
| 3712 | |||
| 3057 | static const struct phy_ops qcom_qmp_pcie_ufs_ops = { | 3713 | static const struct phy_ops qcom_qmp_pcie_ufs_ops = { |
| 3058 | .power_on = qcom_qmp_phy_enable, | 3714 | .power_on = qcom_qmp_phy_enable, |
| 3059 | .power_off = qcom_qmp_phy_disable, | 3715 | .power_off = qcom_qmp_phy_disable, |
| @@ -3062,12 +3718,13 @@ static const struct phy_ops qcom_qmp_pcie_ufs_ops = { · 2 unmodified lines | |||
| 3062 | }; | 3718 | }; |
| 3063 | 3719 | ||
| 3064 | static | 3720 | static |
| 3065 | int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id) | 3721 | int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, |
| 3722 | void __iomem *serdes, const struct qmp_phy_cfg *cfg) | ||
| 3066 | { | 3723 | { |
| 3067 | struct qcom_qmp *qmp = dev_get_drvdata(dev); | 3724 | struct qcom_qmp *qmp = dev_get_drvdata(dev); |
| 3068 | struct phy *generic_phy; | 3725 | struct phy *generic_phy; |
| 3069 | struct qmp_phy *qphy; | 3726 | struct qmp_phy *qphy; |
| 3070 | const struct phy_ops *ops = &qcom_qmp_phy_gen_ops; | 3727 | const struct phy_ops *ops; |
| 3071 | char prop_name[MAX_PROP_NAME]; | 3728 | char prop_name[MAX_PROP_NAME]; |
| 3072 | int ret; | 3729 | int ret; |
| 3073 | 3730 | ||
| @@ -3075,6 +3732,8 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id) · 1 unmodified line | |||
| 3075 | if (!qphy) | 3732 | if (!qphy) |
| 3076 | return -ENOMEM; | 3733 | return -ENOMEM; |
| 3077 | 3734 | ||
| 3735 | qphy->cfg = cfg; | ||
| 3736 | qphy->serdes = serdes; | ||
| 3078 | /* | 3737 | /* |
| 3079 | * Get memory resources for each phy lane: | 3738 | * Get memory resources for each phy lane: |
| 3080 | * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2. | 3739 | * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2. |
| @@ -3099,7 +3758,7 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id) · 18 unmodified lines | |||
| 3099 | * back to old legacy behavior of assuming they can be reached at an | 3758 | * back to old legacy behavior of assuming they can be reached at an |
| 3100 | * offset from the first lane. | 3759 | * offset from the first lane. |
| 3101 | */ | 3760 | */ |
| 3102 | if (qmp->cfg->is_dual_lane_phy) { | 3761 | if (cfg->is_dual_lane_phy) { |
| 3103 | qphy->tx2 = of_iomap(np, 3); | 3762 | qphy->tx2 = of_iomap(np, 3); |
| 3104 | qphy->rx2 = of_iomap(np, 4); | 3763 | qphy->rx2 = of_iomap(np, 4); |
| 3105 | if (!qphy->tx2 || !qphy->rx2) { | 3764 | if (!qphy->tx2 || !qphy->rx2) { |
| @@ -3132,8 +3791,8 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id) · 26 unmodified lines | |||
| 3132 | snprintf(prop_name, sizeof(prop_name), "pipe%d", id); | 3791 | snprintf(prop_name, sizeof(prop_name), "pipe%d", id); |
| 3133 | qphy->pipe_clk = of_clk_get_by_name(np, prop_name); | 3792 | qphy->pipe_clk = of_clk_get_by_name(np, prop_name); |
| 3134 | if (IS_ERR(qphy->pipe_clk)) { | 3793 | if (IS_ERR(qphy->pipe_clk)) { |
| 3135 | if (qmp->cfg->type == PHY_TYPE_PCIE || | 3794 | if (cfg->type == PHY_TYPE_PCIE || |
| 3136 | qmp->cfg->type == PHY_TYPE_USB3) { | 3795 | cfg->type == PHY_TYPE_USB3) { |
| 3137 | ret = PTR_ERR(qphy->pipe_clk); | 3796 | ret = PTR_ERR(qphy->pipe_clk); |
| 3138 | if (ret != -EPROBE_DEFER) | 3797 | if (ret != -EPROBE_DEFER) |
| 3139 | dev_err(dev, | 3798 | dev_err(dev, |
| @@ -3145,7 +3804,7 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id) · 5 unmodified lines | |||
| 3145 | } | 3804 | } |
| 3146 | 3805 | ||
| 3147 | /* Get lane reset, if any */ | 3806 | /* Get lane reset, if any */ |
| 3148 | if (qmp->cfg->has_lane_rst) { | 3807 | if (cfg->has_lane_rst) { |
| 3149 | snprintf(prop_name, sizeof(prop_name), "lane%d", id); | 3808 | snprintf(prop_name, sizeof(prop_name), "lane%d", id); |
| 3150 | qphy->lane_rst = of_reset_control_get(np, prop_name); | 3809 | qphy->lane_rst = of_reset_control_get(np, prop_name); |
| 3151 | if (IS_ERR(qphy->lane_rst)) { | 3810 | if (IS_ERR(qphy->lane_rst)) { |
| @@ -3154,8 +3813,12 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id) · 2 unmodified lines | |||
| 3154 | } | 3813 | } |
| 3155 | } | 3814 | } |
| 3156 | 3815 | ||
| 3157 | if (qmp->cfg->type == PHY_TYPE_UFS || qmp->cfg->type == PHY_TYPE_PCIE) | 3816 | if (cfg->type == PHY_TYPE_UFS || cfg->type == PHY_TYPE_PCIE) |
| 3158 | ops = &qcom_qmp_pcie_ufs_ops; | 3817 | ops = &qcom_qmp_pcie_ufs_ops; |
| 3818 | else if (cfg->type == PHY_TYPE_DP) | ||
| 3819 | ops = &qcom_qmp_phy_dp_ops; | ||
| 3820 | else | ||
| 3821 | ops = &qcom_qmp_phy_gen_ops; | ||
| 3159 | 3822 | ||
| 3160 | generic_phy = devm_phy_create(dev, np, ops); | 3823 | generic_phy = devm_phy_create(dev, np, ops); |
| 3161 | if (IS_ERR(generic_phy)) { | 3824 | if (IS_ERR(generic_phy)) { |
| @@ -3198,6 +3861,9 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = { · 36 unmodified lines | |||
| 3198 | }, { | 3861 | }, { |
| 3199 | .compatible = "qcom,sc7180-qmp-usb3-phy", | 3862 | .compatible = "qcom,sc7180-qmp-usb3-phy", |
| 3200 | .data = &sc7180_usb3phy_cfg, | 3863 | .data = &sc7180_usb3phy_cfg, |
| 3864 | }, { | ||
| 3865 | .compatible = "qcom,sc7180-qmp-usb3-dp-phy", | ||
| 3866 | /* It's a combo phy */ | ||
| 3201 | }, { | 3867 | }, { |
| 3202 | .compatible = "qcom,sdm845-qhp-pcie-phy", | 3868 | .compatible = "qcom,sdm845-qhp-pcie-phy", |
| 3203 | .data = &sdm845_qhp_pciephy_cfg, | 3869 | .data = &sdm845_qhp_pciephy_cfg, |
| @@ -3239,6 +3905,14 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = { · 35 unmodified lines | |||
| 3239 | }; | 3905 | }; |
| 3240 | MODULE_DEVICE_TABLE(of, qcom_qmp_phy_of_match_table); | 3906 | MODULE_DEVICE_TABLE(of, qcom_qmp_phy_of_match_table); |
| 3241 | 3907 | ||
| 3908 | static const struct of_device_id qcom_qmp_combo_phy_of_match_table[] = { | ||
| 3909 | { | ||
| 3910 | .compatible = "qcom,sc7180-qmp-usb3-dp-phy", | ||
| 3911 | .data = &sc7180_usb3dpphy_cfg, | ||
| 3912 | }, | ||
| 3913 | { } | ||
| 3914 | }; | ||
| 3915 | |||
| 3242 | static const struct dev_pm_ops qcom_qmp_phy_pm_ops = { | 3916 | static const struct dev_pm_ops qcom_qmp_phy_pm_ops = { |
| 3243 | SET_RUNTIME_PM_OPS(qcom_qmp_phy_runtime_suspend, | 3917 | SET_RUNTIME_PM_OPS(qcom_qmp_phy_runtime_suspend, |
| 3244 | qcom_qmp_phy_runtime_resume, NULL) | 3918 | qcom_qmp_phy_runtime_resume, NULL) |
| @@ -3248,11 +3922,16 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev) · 3 unmodified lines | |||
| 3248 | { | 3922 | { |
| 3249 | struct qcom_qmp *qmp; | 3923 | struct qcom_qmp *qmp; |
| 3250 | struct device *dev = &pdev->dev; | 3924 | struct device *dev = &pdev->dev; |
| 3251 | struct resource *res; | ||
| 3252 | struct device_node *child; | 3925 | struct device_node *child; |
| 3253 | struct phy_provider *phy_provider; | 3926 | struct phy_provider *phy_provider; |
| 3254 | void __iomem *base; | 3927 | void __iomem *serdes; |
| 3255 | int num, id; | 3928 | void __iomem *usb_serdes; |
| 3929 | void __iomem *dp_serdes; | ||
| 3930 | const struct qmp_phy_combo_cfg *combo_cfg = NULL; | ||
| 3931 | const struct qmp_phy_cfg *cfg = NULL; | ||
| 3932 | const struct qmp_phy_cfg *usb_cfg = NULL; | ||
| 3933 | const struct qmp_phy_cfg *dp_cfg = NULL; | ||
| 3934 | int num, id, expected_phys; | ||
| 3256 | int ret; | 3935 | int ret; |
| 3257 | 3936 | ||
| 3258 | qmp = devm_kzalloc(dev, sizeof(*qmp), GFP_KERNEL); | 3937 | qmp = devm_kzalloc(dev, sizeof(*qmp), GFP_KERNEL); |
| @@ -3263,40 +3942,57 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev) · 4 unmodified lines | |||
| 3263 | dev_set_drvdata(dev, qmp); | 3942 | dev_set_drvdata(dev, qmp); |
| 3264 | 3943 | ||
| 3265 | /* Get the specific init parameters of QMP phy */ | 3944 | /* Get the specific init parameters of QMP phy */ |
| 3266 | qmp->cfg = of_device_get_match_data(dev); | 3945 | cfg = of_device_get_match_data(dev); |
| 3267 | if (!qmp->cfg) | 3946 | if (!cfg) { |
| 3268 | return -EINVAL; | 3947 | const struct of_device_id *match; |
| 3269 | 3948 | ||
| 3270 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 3949 | match = of_match_device(qcom_qmp_combo_phy_of_match_table, dev); |
| 3271 | base = devm_ioremap_resource(dev, res); | 3950 | if (!match) |
| 3272 | if (IS_ERR(base)) | 3951 | return -EINVAL; |
| 3273 | return PTR_ERR(base); | 3952 | |
| 3953 | combo_cfg = match->data; | ||
| 3954 | if (!combo_cfg) | ||
| 3955 | return -EINVAL; | ||
| 3956 | |||
| 3957 | usb_cfg = combo_cfg->usb_cfg; | ||
| 3958 | cfg = usb_cfg; /* Setup clks and regulators */ | ||
| 3959 | } | ||
| 3274 | 3960 | ||
| 3275 | /* per PHY serdes; usually located at base address */ | 3961 | /* per PHY serdes; usually located at base address */ |
| 3276 | qmp->serdes = base; | 3962 | usb_serdes = serdes = devm_platform_ioremap_resource(pdev, 0); |
| 3963 | if (IS_ERR(serdes)) | ||
| 3964 | return PTR_ERR(serdes); | ||
| 3277 | 3965 | ||
| 3278 | /* per PHY dp_com; if PHY has dp_com control block */ | 3966 | /* per PHY dp_com; if PHY has dp_com control block */ |
| 3279 | if (qmp->cfg->has_phy_dp_com_ctrl) { | 3967 | if (combo_cfg || cfg->has_phy_dp_com_ctrl) { |
| 3280 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | 3968 | qmp->dp_com = devm_platform_ioremap_resource(pdev, 1); |
| 3281 | "dp_com"); | 3969 | if (IS_ERR(qmp->dp_com)) |
| 3282 | base = devm_ioremap_resource(dev, res); | 3970 | return PTR_ERR(qmp->dp_com); |
| 3283 | if (IS_ERR(base)) | 3971 | } |
| 3284 | return PTR_ERR(base); | 3972 | |
| 3285 | 3973 | if (combo_cfg) { | |
| 3286 | qmp->dp_com = base; | 3974 | /* Only two serdes for combo PHY */ |
| 3975 | dp_serdes = devm_platform_ioremap_resource(pdev, 2); | ||
| 3976 | if (IS_ERR(dp_serdes)) | ||
| 3977 | return PTR_ERR(dp_serdes); | ||
| 3978 | |||
| 3979 | dp_cfg = combo_cfg->dp_cfg; | ||
| 3980 | expected_phys = 2; | ||
| 3981 | } else { | ||
| 3982 | expected_phys = cfg->nlanes; | ||
| 3287 | } | 3983 | } |
| 3288 | 3984 | ||
| 3289 | mutex_init(&qmp->phy_mutex); | 3985 | mutex_init(&qmp->phy_mutex); |
| 3290 | 3986 | ||
| 3291 | ret = qcom_qmp_phy_clk_init(dev); | 3987 | ret = qcom_qmp_phy_clk_init(dev, cfg); |
| 3292 | if (ret) | 3988 | if (ret) |
| 3293 | return ret; | 3989 | return ret; |
| 3294 | 3990 | ||
| 3295 | ret = qcom_qmp_phy_reset_init(dev); | 3991 | ret = qcom_qmp_phy_reset_init(dev, cfg); |
| 3296 | if (ret) | 3992 | if (ret) |
| 3297 | return ret; | 3993 | return ret; |
| 3298 | 3994 | ||
| 3299 | ret = qcom_qmp_phy_vreg_init(dev); | 3995 | ret = qcom_qmp_phy_vreg_init(dev, cfg); |
| 3300 | if (ret) { | 3996 | if (ret) { |
| 3301 | if (ret != -EPROBE_DEFER) | 3997 | if (ret != -EPROBE_DEFER) |
| 3302 | dev_err(dev, "failed to get regulator supplies: %d\n", | 3998 | dev_err(dev, "failed to get regulator supplies: %d\n", |
| @@ -3306,14 +4002,13 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev) · 3 unmodified lines | |||
| 3306 | 4002 | ||
| 3307 | num = of_get_available_child_count(dev->of_node); | 4003 | num = of_get_available_child_count(dev->of_node); |
| 3308 | /* do we have a rogue child node ? */ | 4004 | /* do we have a rogue child node ? */ |
| 3309 | if (num > qmp->cfg->nlanes) | 4005 | if (num > expected_phys) |
| 3310 | return -EINVAL; | 4006 | return -EINVAL; |
| 3311 | 4007 | ||
| 3312 | qmp->phys = devm_kcalloc(dev, num, sizeof(*qmp->phys), GFP_KERNEL); | 4008 | qmp->phys = devm_kcalloc(dev, num, sizeof(*qmp->phys), GFP_KERNEL); |
| 3313 | if (!qmp->phys) | 4009 | if (!qmp->phys) |
| 3314 | return -ENOMEM; | 4010 | return -ENOMEM; |
| 3315 | 4011 | ||
| 3316 | id = 0; | ||
| 3317 | pm_runtime_set_active(dev); | 4012 | pm_runtime_set_active(dev); |
| 3318 | pm_runtime_enable(dev); | 4013 | pm_runtime_enable(dev); |
| 3319 | /* | 4014 | /* |
| @@ -3322,9 +4017,18 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev) · 2 unmodified lines | |||
| 3322 | */ | 4017 | */ |
| 3323 | pm_runtime_forbid(dev); | 4018 | pm_runtime_forbid(dev); |
| 3324 | 4019 | ||
| 4020 | id = 0; | ||
| 3325 | for_each_available_child_of_node(dev->of_node, child) { | 4021 | for_each_available_child_of_node(dev->of_node, child) { |
| 4022 | if (of_node_name_eq(child, "dp-phy")) { | ||
| 4023 | cfg = dp_cfg; | ||
| 4024 | serdes = dp_serdes; | ||
| 4025 | } else if (of_node_name_eq(child, "usb3-phy")) { | ||
| 4026 | cfg = usb_cfg; | ||
| 4027 | serdes = usb_serdes; | ||
| 4028 | } | ||
| 4029 | |||
| 3326 | /* Create per-lane phy */ | 4030 | /* Create per-lane phy */ |
| 3327 | ret = qcom_qmp_phy_create(dev, child, id); | 4031 | ret = qcom_qmp_phy_create(dev, child, id, serdes, cfg); |
| 3328 | if (ret) { | 4032 | if (ret) { |
| 3329 | dev_err(dev, "failed to create lane%d phy, %d\n", | 4033 | dev_err(dev, "failed to create lane%d phy, %d\n", |
| 3330 | id, ret); | 4034 | id, ret); |
| @@ -3335,11 +4039,20 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev) · 4 unmodified lines | |||
| 3335 | * Register the pipe clock provided by phy. | 4039 | * Register the pipe clock provided by phy. |
| 3336 | * See function description to see details of this pipe clock. | 4040 | * See function description to see details of this pipe clock. |
| 3337 | */ | 4041 | */ |
| 3338 | ret = phy_pipe_clk_register(qmp, child); | 4042 | if (cfg->type == PHY_TYPE_USB3 || cfg->type == PHY_TYPE_PCIE) { |
| 3339 | if (ret) { | 4043 | ret = phy_pipe_clk_register(qmp, child); |
| 3340 | dev_err(qmp->dev, | 4044 | if (ret) { |
| 3341 | "failed to register pipe clock source\n"); | 4045 | dev_err(qmp->dev, |
| 3342 | goto err_node_put; | 4046 | "failed to register pipe clock source\n"); |
| 4047 | goto err_node_put; | ||
| 4048 | } | ||
| 4049 | } else if (cfg->type == PHY_TYPE_DP) { | ||
| 4050 | ret = phy_dp_clks_register(qmp, qmp->phys[id], child); | ||
| 4051 | if (ret) { | ||
| 4052 | dev_err(qmp->dev, | ||
| 4053 | "failed to register DP clock source\n"); | ||
| 4054 | goto err_node_put; | ||
| 4055 | } | ||
| 3343 | } | 4056 | } |
| 3344 | id++; | 4057 | id++; |
| 3345 | } | 4058 | } |
| @@ -137,6 +137,9 @@ · 136 unmodified lines | |||
| 137 | #define QPHY_V3_DP_COM_RESET_OVRD_CTRL 0x1c | 137 | #define QPHY_V3_DP_COM_RESET_OVRD_CTRL 0x1c |
| 138 | 138 | ||
| 139 | /* Only for QMP V3 PHY - QSERDES COM registers */ | 139 | /* Only for QMP V3 PHY - QSERDES COM registers */ |
| 140 | #define QSERDES_V3_COM_ATB_SEL1 0x000 | ||
| 141 | #define QSERDES_V3_COM_ATB_SEL2 0x004 | ||
| 142 | #define QSERDES_V3_COM_FREQ_UPDATE 0x008 | ||
| 140 | #define QSERDES_V3_COM_BG_TIMER 0x00c | 143 | #define QSERDES_V3_COM_BG_TIMER 0x00c |
| 141 | #define QSERDES_V3_COM_SSC_EN_CENTER 0x010 | 144 | #define QSERDES_V3_COM_SSC_EN_CENTER 0x010 |
| 142 | #define QSERDES_V3_COM_SSC_ADJ_PER1 0x014 | 145 | #define QSERDES_V3_COM_SSC_ADJ_PER1 0x014 |
| @@ -146,6 +149,13 @@ · 3 unmodified lines | |||
| 146 | #define QSERDES_V3_COM_SSC_STEP_SIZE1 0x024 | 149 | #define QSERDES_V3_COM_SSC_STEP_SIZE1 0x024 |
| 147 | #define QSERDES_V3_COM_SSC_STEP_SIZE2 0x028 | 150 | #define QSERDES_V3_COM_SSC_STEP_SIZE2 0x028 |
| 148 | #define QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN 0x034 | 151 | #define QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN 0x034 |
| 152 | # define QSERDES_V3_COM_BIAS_EN 0x0001 | ||
| 153 | # define QSERDES_V3_COM_BIAS_EN_MUX 0x0002 | ||
| 154 | # define QSERDES_V3_COM_CLKBUF_R_EN 0x0004 | ||
| 155 | # define QSERDES_V3_COM_CLKBUF_L_EN 0x0008 | ||
| 156 | # define QSERDES_V3_COM_EN_SYSCLK_TX_SEL 0x0010 | ||
| 157 | # define QSERDES_V3_COM_CLKBUF_RX_DRIVE_L 0x0020 | ||
| 158 | # define QSERDES_V3_COM_CLKBUF_RX_DRIVE_R 0x0040 | ||
| 149 | #define QSERDES_V3_COM_CLK_ENABLE1 0x038 | 159 | #define QSERDES_V3_COM_CLK_ENABLE1 0x038 |
| 150 | #define QSERDES_V3_COM_SYS_CLK_CTRL 0x03c | 160 | #define QSERDES_V3_COM_SYS_CLK_CTRL 0x03c |
| 151 | #define QSERDES_V3_COM_SYSCLK_BUF_ENABLE 0x040 | 161 | #define QSERDES_V3_COM_SYSCLK_BUF_ENABLE 0x040 |
| @@ -207,12 +217,36 @@ · 55 unmodified lines | |||
| 207 | #define QSERDES_V3_COM_CMN_MODE 0x184 | 217 | #define QSERDES_V3_COM_CMN_MODE 0x184 |
| 208 | 218 | ||
| 209 | /* Only for QMP V3 PHY - TX registers */ | 219 | /* Only for QMP V3 PHY - TX registers */ |
| 220 | #define QSERDES_V3_TX_BIST_MODE_LANENO 0x000 | ||
| 221 | #define QSERDES_V3_TX_CLKBUF_ENABLE 0x008 | ||
| 222 | #define QSERDES_V3_TX_TX_EMP_POST1_LVL 0x00c | ||
| 223 | # define DP_PHY_TXn_TX_EMP_POST1_LVL_MASK 0x001f | ||
| 224 | # define DP_PHY_TXn_TX_EMP_POST1_LVL_MUX_EN 0x0020 | ||
| 225 | |||
| 226 | #define QSERDES_V3_TX_TX_DRV_LVL 0x01c | ||
| 227 | # define DP_PHY_TXn_TX_DRV_LVL_MASK 0x001f | ||
| 228 | # define DP_PHY_TXn_TX_DRV_LVL_MUX_EN 0x0020 | ||
| 229 | |||
| 230 | #define QSERDES_V3_TX_RESET_TSYNC_EN 0x024 | ||
| 231 | #define QSERDES_V3_TX_PRE_STALL_LDO_BOOST_EN 0x028 | ||
| 232 | |||
| 233 | #define QSERDES_V3_TX_TX_BAND 0x02c | ||
| 234 | #define QSERDES_V3_TX_SLEW_CNTL 0x030 | ||
| 235 | #define QSERDES_V3_TX_INTERFACE_SELECT 0x034 | ||
| 236 | #define QSERDES_V3_TX_RES_CODE_LANE_TX 0x03c | ||
| 237 | #define QSERDES_V3_TX_RES_CODE_LANE_RX 0x040 | ||
| 210 | #define QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX 0x044 | 238 | #define QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX 0x044 |
| 211 | #define QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX 0x048 | 239 | #define QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX 0x048 |
| 212 | #define QSERDES_V3_TX_DEBUG_BUS_SEL 0x058 | 240 | #define QSERDES_V3_TX_DEBUG_BUS_SEL 0x058 |
| 241 | #define QSERDES_V3_TX_TRANSCEIVER_BIAS_EN 0x05c | ||
| 213 | #define QSERDES_V3_TX_HIGHZ_DRVR_EN 0x060 | 242 | #define QSERDES_V3_TX_HIGHZ_DRVR_EN 0x060 |
| 243 | #define QSERDES_V3_TX_TX_POL_INV 0x064 | ||
| 244 | #define QSERDES_V3_TX_PARRATE_REC_DETECT_IDLE_EN 0x068 | ||
| 214 | #define QSERDES_V3_TX_LANE_MODE_1 0x08c | 245 | #define QSERDES_V3_TX_LANE_MODE_1 0x08c |
| 215 | #define QSERDES_V3_TX_RCV_DETECT_LVL_2 0x0a4 | 246 | #define QSERDES_V3_TX_RCV_DETECT_LVL_2 0x0a4 |
| 247 | #define QSERDES_V3_TX_TRAN_DRVR_EMP_EN 0x0c0 | ||
| 248 | #define QSERDES_V3_TX_TX_INTERFACE_MODE 0x0c4 | ||
| 249 | #define QSERDES_V3_TX_VMODE_CTRL1 0x0f0 | ||
| 216 | 250 | ||
| 217 | /* Only for QMP V3 PHY - RX registers */ | 251 | /* Only for QMP V3 PHY - RX registers */ |
| 218 | #define QSERDES_V3_RX_UCDR_FO_GAIN 0x008 | 252 | #define QSERDES_V3_RX_UCDR_FO_GAIN 0x008 |
| @@ -315,6 +349,52 @@ · 96 unmodified lines | |||
| 315 | #define QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG4 0x5c | 349 | #define QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG4 0x5c |
| 316 | #define QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG5 0x60 | 350 | #define QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG5 0x60 |
| 317 | 351 | ||
| 352 | /* Only for QMP V3 PHY - DP PHY registers */ | ||
| 353 | #define QSERDES_V3_DP_PHY_REVISION_ID0 0x000 | ||
| 354 | #define QSERDES_V3_DP_PHY_REVISION_ID1 0x004 | ||
| 355 | #define QSERDES_V3_DP_PHY_REVISION_ID2 0x008 | ||
| 356 | #define QSERDES_V3_DP_PHY_REVISION_ID3 0x00c | ||
| 357 | #define QSERDES_V3_DP_PHY_CFG 0x010 | ||
| 358 | #define QSERDES_V3_DP_PHY_PD_CTL 0x018 | ||
| 359 | # define DP_PHY_PD_CTL_PWRDN 0x001 | ||
| 360 | # define DP_PHY_PD_CTL_PSR_PWRDN 0x002 | ||
| 361 | # define DP_PHY_PD_CTL_AUX_PWRDN 0x004 | ||
| 362 | # define DP_PHY_PD_CTL_LANE_0_1_PWRDN 0x008 | ||
| 363 | # define DP_PHY_PD_CTL_LANE_2_3_PWRDN 0x010 | ||
| 364 | # define DP_PHY_PD_CTL_PLL_PWRDN 0x020 | ||
| 365 | # define DP_PHY_PD_CTL_DP_CLAMP_EN 0x040 | ||
| 366 | #define QSERDES_V3_DP_PHY_MODE 0x01c | ||
| 367 | #define QSERDES_V3_DP_PHY_AUX_CFG0 0x020 | ||
| 368 | #define QSERDES_V3_DP_PHY_AUX_CFG1 0x024 | ||
| 369 | #define QSERDES_V3_DP_PHY_AUX_CFG2 0x028 | ||
| 370 | #define QSERDES_V3_DP_PHY_AUX_CFG3 0x02c | ||
| 371 | #define QSERDES_V3_DP_PHY_AUX_CFG4 0x030 | ||
| 372 | #define QSERDES_V3_DP_PHY_AUX_CFG5 0x034 | ||
| 373 | #define QSERDES_V3_DP_PHY_AUX_CFG6 0x038 | ||
| 374 | #define QSERDES_V3_DP_PHY_AUX_CFG7 0x03c | ||
| 375 | #define QSERDES_V3_DP_PHY_AUX_CFG8 0x040 | ||
| 376 | #define QSERDES_V3_DP_PHY_AUX_CFG9 0x044 | ||
| 377 | |||
| 378 | #define QSERDES_V3_DP_PHY_AUX_INTERRUPT_MASK 0x048 | ||
| 379 | # define PHY_AUX_STOP_ERR_MASK 0x01 | ||
| 380 | # define PHY_AUX_DEC_ERR_MASK 0x02 | ||
| 381 | # define PHY_AUX_SYNC_ERR_MASK 0x04 | ||
| 382 | # define PHY_AUX_ALIGN_ERR_MASK 0x08 | ||
| 383 | # define PHY_AUX_REQ_ERR_MASK 0x10 | ||
| 384 | |||
| 385 | #define QSERDES_V3_DP_PHY_AUX_INTERRUPT_CLEAR 0x04c | ||
| 386 | #define QSERDES_V3_DP_PHY_AUX_BIST_CFG 0x050 | ||
| 387 | |||
| 388 | #define QSERDES_V3_DP_PHY_VCO_DIV 0x064 | ||
| 389 | #define QSERDES_V3_DP_PHY_TX0_TX1_LANE_CTL 0x06c | ||
| 390 | #define QSERDES_V3_DP_PHY_TX2_TX3_LANE_CTL 0x088 | ||
| 391 | |||
| 392 | #define QSERDES_V3_DP_PHY_SPARE0 0x0ac | ||
| 393 | #define DP_PHY_SPARE0_MASK 0x0f | ||
| 394 | #define DP_PHY_SPARE0_ORIENTATION_INFO_SHIFT 0x04(0x0004) | ||
| 395 | |||
| 396 | #define QSERDES_V3_DP_PHY_STATUS 0x0c0 | ||
| 397 | |||
| 318 | /* Only for QMP V4 PHY - QSERDES COM registers */ | 398 | /* Only for QMP V4 PHY - QSERDES COM registers */ |
| 319 | #define QSERDES_V4_COM_SSC_EN_CENTER 0x010 | 399 | #define QSERDES_V4_COM_SSC_EN_CENTER 0x010 |
| 320 | #define QSERDES_V4_COM_SSC_PER1 0x01c | 400 | #define QSERDES_V4_COM_SSC_PER1 0x01c |
| @@ -142,7 +142,7 @@ static int ralink_usb_phy_power_off(struct phy *_phy) · 141 unmodified lines | |||
| 142 | return 0; | 142 | return 0; |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | static struct phy_ops ralink_usb_phy_ops = { | 145 | static const struct phy_ops ralink_usb_phy_ops = { |
| 146 | .power_on = ralink_usb_phy_power_on, | 146 | .power_on = ralink_usb_phy_power_on, |
| 147 | .power_off = ralink_usb_phy_power_off, | 147 | .power_off = ralink_usb_phy_power_off, |
| 148 | .owner = THIS_MODULE, | 148 | .owner = THIS_MODULE, |
| @@ -9,6 +9,18 @@ config PHY_ROCKCHIP_DP · 8 unmodified lines | |||
| 9 | help | 9 | help |
| 10 | Enable this to support the Rockchip Display Port PHY. | 10 | Enable this to support the Rockchip Display Port PHY. |
| 11 | 11 | ||
| 12 | config PHY_ROCKCHIP_DPHY_RX0 | ||
| 13 | tristate "Rockchip MIPI Synopsys DPHY RX0 driver" | ||
| 14 | depends on ARCH_ROCKCHIP || COMPILE_TEST | ||
| 15 | select GENERIC_PHY_MIPI_DPHY | ||
| 16 | select GENERIC_PHY | ||
| 17 | help | ||
| 18 | Enable this to support the Rockchip MIPI Synopsys DPHY RX0 | ||
| 19 | associated to the Rockchip ISP module present in RK3399 SoCs. | ||
| 20 | |||
| 21 | To compile this driver as a module, choose M here: the module | ||
| 22 | will be called phy-rockchip-dphy-rx0. | ||
| 23 | |||
| 12 | config PHY_ROCKCHIP_EMMC | 24 | config PHY_ROCKCHIP_EMMC |
| 13 | tristate "Rockchip EMMC PHY Driver" | 25 | tristate "Rockchip EMMC PHY Driver" |
| 14 | depends on ARCH_ROCKCHIP && OF | 26 | depends on ARCH_ROCKCHIP && OF |
| @@ -1,5 +1,6 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | obj-$(CONFIG_PHY_ROCKCHIP_DP) += phy-rockchip-dp.o | 2 | obj-$(CONFIG_PHY_ROCKCHIP_DP) += phy-rockchip-dp.o |
| 3 | obj-$(CONFIG_PHY_ROCKCHIP_DPHY_RX0) += phy-rockchip-dphy-rx0.o | ||
| 3 | obj-$(CONFIG_PHY_ROCKCHIP_EMMC) += phy-rockchip-emmc.o | 4 | obj-$(CONFIG_PHY_ROCKCHIP_EMMC) += phy-rockchip-emmc.o |
| 4 | obj-$(CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY) += phy-rockchip-inno-dsidphy.o | 5 | obj-$(CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY) += phy-rockchip-inno-dsidphy.o |
| 5 | obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI) += phy-rockchip-inno-hdmi.o | 6 | obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI) += phy-rockchip-inno-hdmi.o |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | |||
| 16 | */ | 16 | */ |
| 17 | 17 | ||
| 18 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
| 19 | #include <linux/delay.h> | ||
| 19 | #include <linux/io.h> | 20 | #include <linux/io.h> |
| 20 | #include <linux/mfd/syscon.h> | 21 | #include <linux/mfd/syscon.h> |
| 21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | |||
| 16 | #include <linux/of.h> | 16 | #include <linux/of.h> |
| 17 | #include <linux/of_address.h> | 17 | #include <linux/of_address.h> |
| 18 | #include <linux/of_device.h> | 18 | #include <linux/of_device.h> |
| 19 | #include <linux/iopoll.h> | ||
| 19 | #include <linux/phy/phy.h> | 20 | #include <linux/phy/phy.h> |
| 20 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
| 21 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
| @@ -556,41 +557,25 @@ static int exynos5_usbdrd_phy_power_off(struct phy *phy) · 534 unmodified lines | |||
| 556 | static int crport_handshake(struct exynos5_usbdrd_phy *phy_drd, | 557 | static int crport_handshake(struct exynos5_usbdrd_phy *phy_drd, |
| 557 | u32 val, u32 cmd) | 558 | u32 val, u32 cmd) |
| 558 | { | 559 | { |
| 559 | u32 usec = 100; | ||
| 560 | unsigned int result; | 560 | unsigned int result; |
| 561 | int err; | ||
| 561 | 562 | ||
| 562 | writel(val | cmd, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0); | 563 | writel(val | cmd, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0); |
| 563 | 564 | ||
| 564 | do { | 565 | err = readl_poll_timeout(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1, |
| 565 | result = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1); | 566 | result, (result & PHYREG1_CR_ACK), 1, 100); |
| 566 | if (result & PHYREG1_CR_ACK) | 567 | if (err == -ETIMEDOUT) { |
| 567 | break; | 568 | dev_err(phy_drd->dev, "CRPORT handshake timeout1 (0x%08x)\n", val); |
| 568 | 569 | return err; | |
| 569 | udelay(1); | ||
| 570 | } while (usec-- > 0); | ||
| 571 | |||
| 572 | if (!usec) { | ||
| 573 | dev_err(phy_drd->dev, | ||
| 574 | "CRPORT handshake timeout1 (0x%08x)\n", val); | ||
| 575 | return -ETIME; | ||
| 576 | } | 570 | } |
| 577 | 571 | ||
| 578 | usec = 100; | ||
| 579 | |||
| 580 | writel(val, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0); | 572 | writel(val, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0); |
| 581 | 573 | ||
| 582 | do { | 574 | err = readl_poll_timeout(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1, |
| 583 | result = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1); | 575 | result, !(result & PHYREG1_CR_ACK), 1, 100); |
| 584 | if (!(result & PHYREG1_CR_ACK)) | 576 | if (err == -ETIMEDOUT) { |
| 585 | break; | 577 | dev_err(phy_drd->dev, "CRPORT handshake timeout2 (0x%08x)\n", val); |
| 586 | 578 | return err; | |
| 587 | udelay(1); | ||
| 588 | } while (usec-- > 0); | ||
| 589 | |||
| 590 | if (!usec) { | ||
| 591 | dev_err(phy_drd->dev, | ||
| 592 | "CRPORT handshake timeout2 (0x%08x)\n", val); | ||
| 593 | return -ETIME; | ||
| 594 | } | 579 | } |
| 595 | 580 | ||
| 596 | return 0; | 581 | return 0; |
| @@ -268,7 +268,7 @@ static int samsung_ufs_phy_exit(struct phy *phy) · 267 unmodified lines | |||
| 268 | return 0; | 268 | return 0; |
| 269 | } | 269 | } |
| 270 | 270 | ||
| 271 | static struct phy_ops samsung_ufs_phy_ops = { | 271 | static const struct phy_ops samsung_ufs_phy_ops = { |
| 272 | .init = samsung_ufs_phy_init, | 272 | .init = samsung_ufs_phy_init, |
| 273 | .exit = samsung_ufs_phy_exit, | 273 | .exit = samsung_ufs_phy_exit, |
| 274 | .power_on = samsung_ufs_phy_power_on, | 274 | .power_on = samsung_ufs_phy_power_on, |
| @@ -34,3 +34,13 @@ config PHY_UNIPHIER_PCIE · 33 unmodified lines | |||
| 34 | help | 34 | help |
| 35 | Enable this to support PHY implemented in PCIe controller | 35 | Enable this to support PHY implemented in PCIe controller |
| 36 | on UniPhier SoCs. This driver supports LD20 and PXs3 SoCs. | 36 | on UniPhier SoCs. This driver supports LD20 and PXs3 SoCs. |
| 37 | |||
| 38 | config PHY_UNIPHIER_AHCI | ||
| 39 | tristate "UniPhier AHCI PHY driver" | ||
| 40 | depends on ARCH_UNIPHIER || COMPILE_TEST | ||
| 41 | depends on OF && HAS_IOMEM | ||
| 42 | default SATA_AHCI_PLATFORM | ||
| 43 | select GENERIC_PHY | ||
| 44 | help | ||
| 45 | Enable this to support PHY implemented in AHCI controller | ||
| 46 | on UniPhier SoCs. This driver supports PXs2 and PXs3 SoCs. | ||
| @@ -6,3 +6,4 @@ · 5 unmodified lines | |||
| 6 | obj-$(CONFIG_PHY_UNIPHIER_USB2) += phy-uniphier-usb2.o | 6 | obj-$(CONFIG_PHY_UNIPHIER_USB2) += phy-uniphier-usb2.o |
| 7 | obj-$(CONFIG_PHY_UNIPHIER_USB3) += phy-uniphier-usb3hs.o phy-uniphier-usb3ss.o | 7 | obj-$(CONFIG_PHY_UNIPHIER_USB3) += phy-uniphier-usb3hs.o phy-uniphier-usb3ss.o |
| 8 | obj-$(CONFIG_PHY_UNIPHIER_PCIE) += phy-uniphier-pcie.o | 8 | obj-$(CONFIG_PHY_UNIPHIER_PCIE) += phy-uniphier-pcie.o |
| 9 | obj-$(CONFIG_PHY_UNIPHIER_AHCI) += phy-uniphier-ahci.o | ||
| @@ -0,0 +1,321 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * phy-uniphier-ahci.c - PHY driver for UniPhier AHCI controller | ||
| 4 | * Copyright 2016-2020, Socionext Inc. | ||
| 5 | * Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com> | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include <linux/bitfield.h> | ||
| 9 | #include <linux/bitops.h> | ||
| 10 | #include <linux/clk.h> | ||
| 11 | #include <linux/iopoll.h> | ||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/of.h> | ||
| 14 | #include <linux/of_platform.h> | ||
| 15 | #include <linux/phy/phy.h> | ||
| 16 | #include <linux/platform_device.h> | ||
| 17 | #include <linux/reset.h> | ||
| 18 | |||
| 19 | struct uniphier_ahciphy_priv { | ||
| 20 | struct device *dev; | ||
| 21 | void __iomem *base; | ||
| 22 | struct clk *clk, *clk_parent; | ||
| 23 | struct reset_control *rst, *rst_parent; | ||
| 24 | const struct uniphier_ahciphy_soc_data *data; | ||
| 25 | }; | ||
| 26 | |||
| 27 | struct uniphier_ahciphy_soc_data { | ||
| 28 | int (*init)(struct uniphier_ahciphy_priv *priv); | ||
| 29 | int (*power_on)(struct uniphier_ahciphy_priv *priv); | ||
| 30 | int (*power_off)(struct uniphier_ahciphy_priv *priv); | ||
| 31 | bool is_ready_high; | ||
| 32 | bool is_phy_clk; | ||
| 33 | }; | ||
| 34 | |||
| 35 | /* for PXs2/PXs3 */ | ||
| 36 | #define CKCTRL 0x0 | ||
| 37 | #define CKCTRL_P0_READY BIT(15) | ||
| 38 | #define CKCTRL_P0_RESET BIT(10) | ||
| 39 | #define CKCTRL_REF_SSP_EN BIT(9) | ||
| 40 | #define TXCTRL0 0x4 | ||
| 41 | #define TXCTRL0_AMP_G3_MASK GENMASK(22, 16) | ||
| 42 | #define TXCTRL0_AMP_G2_MASK GENMASK(14, 8) | ||
| 43 | #define TXCTRL0_AMP_G1_MASK GENMASK(6, 0) | ||
| 44 | #define TXCTRL1 0x8 | ||
| 45 | #define TXCTRL1_DEEMPH_G3_MASK GENMASK(21, 16) | ||
| 46 | #define TXCTRL1_DEEMPH_G2_MASK GENMASK(13, 8) | ||
| 47 | #define TXCTRL1_DEEMPH_G1_MASK GENMASK(5, 0) | ||
| 48 | #define RXCTRL 0xc | ||
| 49 | #define RXCTRL_LOS_LVL_MASK GENMASK(20, 16) | ||
| 50 | #define RXCTRL_LOS_BIAS_MASK GENMASK(10, 8) | ||
| 51 | #define RXCTRL_RX_EQ_MASK GENMASK(2, 0) | ||
| 52 | |||
| 53 | static void uniphier_ahciphy_pxs2_enable(struct uniphier_ahciphy_priv *priv, | ||
| 54 | bool enable) | ||
| 55 | { | ||
| 56 | u32 val; | ||
| 57 | |||
| 58 | val = readl(priv->base + CKCTRL); | ||
| 59 | |||
| 60 | if (enable) { | ||
| 61 | val |= CKCTRL_REF_SSP_EN; | ||
| 62 | writel(val, priv->base + CKCTRL); | ||
| 63 | val &= ~CKCTRL_P0_RESET; | ||
| 64 | writel(val, priv->base + CKCTRL); | ||
| 65 | } else { | ||
| 66 | val |= CKCTRL_P0_RESET; | ||
| 67 | writel(val, priv->base + CKCTRL); | ||
| 68 | val &= ~CKCTRL_REF_SSP_EN; | ||
| 69 | writel(val, priv->base + CKCTRL); | ||
| 70 | } | ||
| 71 | } | ||
| 72 | |||
| 73 | static int uniphier_ahciphy_pxs2_power_on(struct uniphier_ahciphy_priv *priv) | ||
| 74 | { | ||
| 75 | int ret; | ||
| 76 | u32 val; | ||
| 77 | |||
| 78 | uniphier_ahciphy_pxs2_enable(priv, true); | ||
| 79 | |||
| 80 | /* wait until PLL is ready */ | ||
| 81 | if (priv->data->is_ready_high) | ||
| 82 | ret = readl_poll_timeout(priv->base + CKCTRL, val, | ||
| 83 | (val & CKCTRL_P0_READY), 200, 400); | ||
| 84 | else | ||
| 85 | ret = readl_poll_timeout(priv->base + CKCTRL, val, | ||
| 86 | !(val & CKCTRL_P0_READY), 200, 400); | ||
| 87 | if (ret) { | ||
| 88 | dev_err(priv->dev, "Failed to check whether PHY PLL is ready\n"); | ||
| 89 | uniphier_ahciphy_pxs2_enable(priv, false); | ||
| 90 | } | ||
| 91 | |||
| 92 | return ret; | ||
| 93 | } | ||
| 94 | |||
| 95 | static int uniphier_ahciphy_pxs2_power_off(struct uniphier_ahciphy_priv *priv) | ||
| 96 | { | ||
| 97 | uniphier_ahciphy_pxs2_enable(priv, false); | ||
| 98 | |||
| 99 | return 0; | ||
| 100 | } | ||
| 101 | |||
| 102 | static int uniphier_ahciphy_pxs3_init(struct uniphier_ahciphy_priv *priv) | ||
| 103 | { | ||
| 104 | int i; | ||
| 105 | u32 val; | ||
| 106 | |||
| 107 | /* setup port parameter */ | ||
| 108 | val = readl(priv->base + TXCTRL0); | ||
| 109 | val &= ~TXCTRL0_AMP_G3_MASK; | ||
| 110 | val |= FIELD_PREP(TXCTRL0_AMP_G3_MASK, 0x73); | ||
| 111 | val &= ~TXCTRL0_AMP_G2_MASK; | ||
| 112 | val |= FIELD_PREP(TXCTRL0_AMP_G2_MASK, 0x46); | ||
| 113 | val &= ~TXCTRL0_AMP_G1_MASK; | ||
| 114 | val |= FIELD_PREP(TXCTRL0_AMP_G1_MASK, 0x42); | ||
| 115 | writel(val, priv->base + TXCTRL0); | ||
| 116 | |||
| 117 | val = readl(priv->base + TXCTRL1); | ||
| 118 | val &= ~TXCTRL1_DEEMPH_G3_MASK; | ||
| 119 | val |= FIELD_PREP(TXCTRL1_DEEMPH_G3_MASK, 0x23); | ||
| 120 | val &= ~TXCTRL1_DEEMPH_G2_MASK; | ||
| 121 | val |= FIELD_PREP(TXCTRL1_DEEMPH_G2_MASK, 0x05); | ||
| 122 | val &= ~TXCTRL1_DEEMPH_G1_MASK; | ||
| 123 | val |= FIELD_PREP(TXCTRL1_DEEMPH_G1_MASK, 0x05); | ||
| 124 | |||
| 125 | val = readl(priv->base + RXCTRL); | ||
| 126 | val &= ~RXCTRL_LOS_LVL_MASK; | ||
| 127 | val |= FIELD_PREP(RXCTRL_LOS_LVL_MASK, 0x9); | ||
| 128 | val &= ~RXCTRL_LOS_BIAS_MASK; | ||
| 129 | val |= FIELD_PREP(RXCTRL_LOS_BIAS_MASK, 0x2); | ||
| 130 | val &= ~RXCTRL_RX_EQ_MASK; | ||
| 131 | val |= FIELD_PREP(RXCTRL_RX_EQ_MASK, 0x1); | ||
| 132 | |||
| 133 | /* dummy read 25 times to make a wait time for the phy to stabilize */ | ||
| 134 | for (i = 0; i < 25; i++) | ||
| 135 | readl(priv->base + CKCTRL); | ||
| 136 | |||
| 137 | return 0; | ||
| 138 | } | ||
| 139 | |||
| 140 | static int uniphier_ahciphy_init(struct phy *phy) | ||
| 141 | { | ||
| 142 | struct uniphier_ahciphy_priv *priv = phy_get_drvdata(phy); | ||
| 143 | int ret; | ||
| 144 | |||
| 145 | ret = clk_prepare_enable(priv->clk_parent); | ||
| 146 | if (ret) | ||
| 147 | return ret; | ||
| 148 | |||
| 149 | ret = reset_control_deassert(priv->rst_parent); | ||
| 150 | if (ret) | ||
| 151 | goto out_clk_disable; | ||
| 152 | |||
| 153 | if (priv->data->init) { | ||
| 154 | ret = priv->data->init(priv); | ||
| 155 | if (ret) | ||
| 156 | goto out_rst_assert; | ||
| 157 | } | ||
| 158 | |||
| 159 | return 0; | ||
| 160 | |||
| 161 | out_rst_assert: | ||
| 162 | reset_control_assert(priv->rst_parent); | ||
| 163 | out_clk_disable: | ||
| 164 | clk_disable_unprepare(priv->clk_parent); | ||
| 165 | |||
| 166 | return ret; | ||
| 167 | } | ||
| 168 | |||
| 169 | static int uniphier_ahciphy_exit(struct phy *phy) | ||
| 170 | { | ||
| 171 | struct uniphier_ahciphy_priv *priv = phy_get_drvdata(phy); | ||
| 172 | |||
| 173 | reset_control_assert(priv->rst_parent); | ||
| 174 | clk_disable_unprepare(priv->clk_parent); | ||
| 175 | |||
| 176 | return 0; | ||
| 177 | } | ||
| 178 | |||
| 179 | static int uniphier_ahciphy_power_on(struct phy *phy) | ||
| 180 | { | ||
| 181 | struct uniphier_ahciphy_priv *priv = phy_get_drvdata(phy); | ||
| 182 | int ret = 0; | ||
| 183 | |||
| 184 | ret = clk_prepare_enable(priv->clk); | ||
| 185 | if (ret) | ||
| 186 | return ret; | ||
| 187 | |||
| 188 | ret = reset_control_deassert(priv->rst); | ||
| 189 | if (ret) | ||
| 190 | goto out_clk_disable; | ||
| 191 | |||
| 192 | if (priv->data->power_on) { | ||
| 193 | ret = priv->data->power_on(priv); | ||
| 194 | if (ret) | ||
| 195 | goto out_reset_assert; | ||
| 196 | } | ||
| 197 | |||
| 198 | return 0; | ||
| 199 | |||
| 200 | out_reset_assert: | ||
| 201 | reset_control_assert(priv->rst); | ||
| 202 | out_clk_disable: | ||
| 203 | clk_disable_unprepare(priv->clk); | ||
| 204 | |||
| 205 | return ret; | ||
| 206 | } | ||
| 207 | |||
| 208 | static int uniphier_ahciphy_power_off(struct phy *phy) | ||
| 209 | { | ||
| 210 | struct uniphier_ahciphy_priv *priv = phy_get_drvdata(phy); | ||
| 211 | int ret = 0; | ||
| 212 | |||
| 213 | if (priv->data->power_off) | ||
| 214 | ret = priv->data->power_off(priv); | ||
| 215 | |||
| 216 | reset_control_assert(priv->rst); | ||
| 217 | clk_disable_unprepare(priv->clk); | ||
| 218 | |||
| 219 | return ret; | ||
| 220 | } | ||
| 221 | |||
| 222 | static const struct phy_ops uniphier_ahciphy_ops = { | ||
| 223 | .init = uniphier_ahciphy_init, | ||
| 224 | .exit = uniphier_ahciphy_exit, | ||
| 225 | .power_on = uniphier_ahciphy_power_on, | ||
| 226 | .power_off = uniphier_ahciphy_power_off, | ||
| 227 | .owner = THIS_MODULE, | ||
| 228 | }; | ||
| 229 | |||
| 230 | static int uniphier_ahciphy_probe(struct platform_device *pdev) | ||
| 231 | { | ||
| 232 | struct device *dev = &pdev->dev; | ||
| 233 | struct uniphier_ahciphy_priv *priv; | ||
| 234 | struct phy *phy; | ||
| 235 | struct phy_provider *phy_provider; | ||
| 236 | |||
| 237 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
| 238 | if (!priv) | ||
| 239 | return -ENOMEM; | ||
| 240 | |||
| 241 | priv->dev = dev; | ||
| 242 | priv->data = of_device_get_match_data(dev); | ||
| 243 | if (WARN_ON(!priv->data)) | ||
| 244 | return -EINVAL; | ||
| 245 | |||
| 246 | priv->base = devm_platform_ioremap_resource(pdev, 0); | ||
| 247 | if (IS_ERR(priv->base)) | ||
| 248 | return PTR_ERR(priv->base); | ||
| 249 | |||
| 250 | priv->clk_parent = devm_clk_get(dev, "link"); | ||
| 251 | if (IS_ERR(priv->clk_parent)) | ||
| 252 | return PTR_ERR(priv->clk_parent); | ||
| 253 | |||
| 254 | if (priv->data->is_phy_clk) { | ||
| 255 | priv->clk = devm_clk_get(dev, "phy"); | ||
| 256 | if (IS_ERR(priv->clk)) | ||
| 257 | return PTR_ERR(priv->clk); | ||
| 258 | } | ||
| 259 | |||
| 260 | priv->rst_parent = devm_reset_control_get_shared(dev, "link"); | ||
| 261 | if (IS_ERR(priv->rst_parent)) | ||
| 262 | return PTR_ERR(priv->rst_parent); | ||
| 263 | |||
| 264 | priv->rst = devm_reset_control_get_shared(dev, "phy"); | ||
| 265 | if (IS_ERR(priv->rst)) | ||
| 266 | return PTR_ERR(priv->rst); | ||
| 267 | |||
| 268 | phy = devm_phy_create(dev, dev->of_node, &uniphier_ahciphy_ops); | ||
| 269 | if (IS_ERR(phy)) { | ||
| 270 | dev_err(dev, "failed to create phy\n"); | ||
| 271 | return PTR_ERR(phy); | ||
| 272 | } | ||
| 273 | |||
| 274 | phy_set_drvdata(phy, priv); | ||
| 275 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | ||
| 276 | if (IS_ERR(phy_provider)) | ||
| 277 | return PTR_ERR(phy_provider); | ||
| 278 | |||
| 279 | return 0; | ||
| 280 | } | ||
| 281 | |||
| 282 | static const struct uniphier_ahciphy_soc_data uniphier_pxs2_data = { | ||
| 283 | .power_on = uniphier_ahciphy_pxs2_power_on, | ||
| 284 | .power_off = uniphier_ahciphy_pxs2_power_off, | ||
| 285 | .is_ready_high = false, | ||
| 286 | .is_phy_clk = false, | ||
| 287 | }; | ||
| 288 | |||
| 289 | static const struct uniphier_ahciphy_soc_data uniphier_pxs3_data = { | ||
| 290 | .init = uniphier_ahciphy_pxs3_init, | ||
| 291 | .power_on = uniphier_ahciphy_pxs2_power_on, | ||
| 292 | .power_off = uniphier_ahciphy_pxs2_power_off, | ||
| 293 | .is_ready_high = true, | ||
| 294 | .is_phy_clk = true, | ||
| 295 | }; | ||
| 296 | |||
| 297 | static const struct of_device_id uniphier_ahciphy_match[] = { | ||
| 298 | { | ||
| 299 | .compatible = "socionext,uniphier-pxs2-ahci-phy", | ||
| 300 | .data = &uniphier_pxs2_data, | ||
| 301 | }, | ||
| 302 | { | ||
| 303 | .compatible = "socionext,uniphier-pxs3-ahci-phy", | ||
| 304 | .data = &uniphier_pxs3_data, | ||
| 305 | }, | ||
| 306 | { /* Sentinel */ }, | ||
| 307 | }; | ||
| 308 | MODULE_DEVICE_TABLE(of, uniphier_ahciphy_match); | ||
| 309 | |||
| 310 | static struct platform_driver uniphier_ahciphy_driver = { | ||
| 311 | .probe = uniphier_ahciphy_probe, | ||
| 312 | .driver = { | ||
| 313 | .name = "uniphier-ahci-phy", | ||
| 314 | .of_match_table = uniphier_ahciphy_match, | ||
| 315 | }, | ||
| 316 | }; | ||
| 317 | module_platform_driver(uniphier_ahciphy_driver); | ||
| 318 | |||
| 319 | MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>"); | ||
| 320 | MODULE_DESCRIPTION("UniPhier PHY driver for AHCI controller"); | ||
| 321 | MODULE_LICENSE("GPL v2"); | ||
| @@ -19,15 +19,38 @@ · 18 unmodified lines | |||
| 19 | #include <linux/pm_runtime.h> | 19 | #include <linux/pm_runtime.h> |
| 20 | #include <linux/regmap.h> | 20 | #include <linux/regmap.h> |
| 21 | 21 | ||
| 22 | #define CMU_R004 0x4 | ||
| 23 | #define CMU_R060 0x60 | ||
| 22 | #define CMU_R07C 0x7c | 24 | #define CMU_R07C 0x7c |
| 23 | 25 | #define CMU_R088 0x88 | |
| 26 | #define CMU_R0D0 0xd0 | ||
| 27 | #define CMU_R0E8 0xe8 | ||
| 28 | |||
| 29 | #define LANE_R048 0x248 | ||
| 30 | #define LANE_R058 0x258 | ||
| 31 | #define LANE_R06c 0x26c | ||
| 32 | #define LANE_R070 0x270 | ||
| 33 | #define LANE_R070 0x270 | ||
| 34 | #define LANE_R19C 0x39c | ||
| 35 | |||
| 36 | #define COMLANE_R004 0xa04 | ||
| 24 | #define COMLANE_R138 0xb38 | 37 | #define COMLANE_R138 0xb38 |
| 25 | #define VERSION 0x70 | 38 | #define VERSION_VAL 0x70 |
| 26 | 39 | ||
| 27 | #define COMLANE_R190 0xb90 | 40 | #define COMLANE_R190 0xb90 |
| 28 | |||
| 29 | #define COMLANE_R194 0xb94 | 41 | #define COMLANE_R194 0xb94 |
| 30 | 42 | ||
| 43 | #define COMRXEQ_R004 0x1404 | ||
| 44 | #define COMRXEQ_R008 0x1408 | ||
| 45 | #define COMRXEQ_R00C 0x140c | ||
| 46 | #define COMRXEQ_R014 0x1414 | ||
| 47 | #define COMRXEQ_R018 0x1418 | ||
| 48 | #define COMRXEQ_R01C 0x141c | ||
| 49 | #define COMRXEQ_R04C 0x144c | ||
| 50 | #define COMRXEQ_R088 0x1488 | ||
| 51 | #define COMRXEQ_R094 0x1494 | ||
| 52 | #define COMRXEQ_R098 0x1498 | ||
| 53 | |||
| 31 | #define SERDES_CTRL 0x1fd0 | 54 | #define SERDES_CTRL 0x1fd0 |
| 32 | 55 | ||
| 33 | #define WIZ_LANEXCTL_STS 0x1fe0 | 56 | #define WIZ_LANEXCTL_STS 0x1fe0 |
| @@ -80,27 +103,136 @@ static const struct regmap_config serdes_am654_regmap_config = { · 46 unmodified lines | |||
| 80 | .max_register = 0x1ffc, | 103 | .max_register = 0x1ffc, |
| 81 | }; | 104 | }; |
| 82 | 105 | ||
| 83 | static const struct reg_field cmu_master_cdn_o = REG_FIELD(CMU_R07C, 24, 24); | 106 | enum serdes_am654_fields { |
| 84 | static const struct reg_field config_version = REG_FIELD(COMLANE_R138, 16, 23); | 107 | /* CMU PLL Control */ |
| 85 | static const struct reg_field l1_master_cdn_o = REG_FIELD(COMLANE_R190, 9, 9); | 108 | CMU_PLL_CTRL, |
| 86 | static const struct reg_field cmu_ok_i_0 = REG_FIELD(COMLANE_R194, 19, 19); | 109 | |
| 87 | static const struct reg_field por_en = REG_FIELD(SERDES_CTRL, 29, 29); | 110 | LANE_PLL_CTRL_RXEQ_RXIDLE, |
| 88 | static const struct reg_field tx0_enable = REG_FIELD(WIZ_LANEXCTL_STS, 29, 31); | 111 | |
| 89 | static const struct reg_field rx0_enable = REG_FIELD(WIZ_LANEXCTL_STS, 13, 15); | 112 | /* CMU VCO bias current and VREG setting */ |
| 90 | static const struct reg_field pll_enable = REG_FIELD(WIZ_PLL_CTRL, 29, 31); | 113 | AHB_PMA_CM_VCO_VBIAS_VREG, |
| 91 | static const struct reg_field pll_ok = REG_FIELD(WIZ_PLL_CTRL, 28, 28); | 114 | AHB_PMA_CM_VCO_BIAS_VREG, |
| 115 | |||
| 116 | AHB_PMA_CM_SR, | ||
| 117 | AHB_SSC_GEN_Z_O_20_13, | ||
| 118 | |||
| 119 | /* AHB PMA Lane Configuration */ | ||
| 120 | AHB_PMA_LN_AGC_THSEL_VREGH, | ||
| 121 | |||
| 122 | /* AGC and Signal detect threshold for Gen3 */ | ||
| 123 | AHB_PMA_LN_GEN3_AGC_SD_THSEL, | ||
| 124 | |||
| 125 | AHB_PMA_LN_RX_SELR_GEN3, | ||
| 126 | AHB_PMA_LN_TX_DRV, | ||
| 127 | |||
| 128 | /* CMU Master Reset */ | ||
| 129 | CMU_MASTER_CDN, | ||
| 130 | |||
| 131 | /* P2S ring buffer initial startup pointer difference */ | ||
| 132 | P2S_RBUF_PTR_DIFF, | ||
| 133 | |||
| 134 | CONFIG_VERSION, | ||
| 135 | |||
| 136 | /* Lane 1 Master Reset */ | ||
| 137 | L1_MASTER_CDN, | ||
| 138 | |||
| 139 | /* CMU OK Status */ | ||
| 140 | CMU_OK_I_0, | ||
| 141 | |||
| 142 | /* Mid-speed initial calibration control */ | ||
| 143 | COMRXEQ_MS_INIT_CTRL_7_0, | ||
| 144 | |||
| 145 | /* High-speed initial calibration control */ | ||
| 146 | COMRXEQ_HS_INIT_CAL_7_0, | ||
| 147 | |||
| 148 | /* Mid-speed recalibration control */ | ||
| 149 | COMRXEQ_MS_RECAL_CTRL_7_0, | ||
| 150 | |||
| 151 | /* High-speed recalibration control */ | ||
| 152 | COMRXEQ_HS_RECAL_CTRL_7_0, | ||
| 153 | |||
| 154 | /* ATT configuration */ | ||
| 155 | COMRXEQ_CSR_ATT_CONFIG, | ||
| 156 | |||
| 157 | /* Edge based boost adaptation window length */ | ||
| 158 | COMRXEQ_CSR_EBSTADAPT_WIN_LEN, | ||
| 159 | |||
| 160 | /* COMRXEQ control 3 & 4 */ | ||
| 161 | COMRXEQ_CTRL_3_4, | ||
| 162 | |||
| 163 | /* COMRXEQ control 14, 15 and 16*/ | ||
| 164 | COMRXEQ_CTRL_14_15_16, | ||
| 165 | |||
| 166 | /* Threshold for errors in pattern data */ | ||
| 167 | COMRXEQ_CSR_DLEV_ERR_THRESH, | ||
| 168 | |||
| 169 | /* COMRXEQ control 25 */ | ||
| 170 | COMRXEQ_CTRL_25, | ||
| 171 | |||
| 172 | /* Mid-speed rate change calibration control */ | ||
| 173 | CSR_RXEQ_RATE_CHANGE_CAL_RUN_RATE2_O, | ||
| 174 | |||
| 175 | /* High-speed rate change calibration control */ | ||
| 176 | COMRXEQ_HS_RCHANGE_CTRL_7_0, | ||
| 177 | |||
| 178 | /* Serdes reset */ | ||
| 179 | POR_EN, | ||
| 180 | |||
| 181 | /* Tx Enable Value */ | ||
| 182 | TX0_ENABLE, | ||
| 183 | |||
| 184 | /* Rx Enable Value */ | ||
| 185 | RX0_ENABLE, | ||
| 186 | |||
| 187 | /* PLL Enable Value */ | ||
| 188 | PLL_ENABLE, | ||
| 189 | |||
| 190 | /* PLL ready for use */ | ||
| 191 | PLL_OK, | ||
| 192 | |||
| 193 | /* sentinel */ | ||
| 194 | MAX_FIELDS | ||
| 195 | |||
| 196 | }; | ||
| 197 | |||
| 198 | static const struct reg_field serdes_am654_reg_fields[] = { | ||
| 199 | [CMU_PLL_CTRL] = REG_FIELD(CMU_R004, 8, 15), | ||
| 200 | [AHB_PMA_CM_VCO_VBIAS_VREG] = REG_FIELD(CMU_R060, 8, 15), | ||
| 201 | [CMU_MASTER_CDN] = REG_FIELD(CMU_R07C, 24, 31), | ||
| 202 | [AHB_PMA_CM_VCO_BIAS_VREG] = REG_FIELD(CMU_R088, 24, 31), | ||
| 203 | [AHB_PMA_CM_SR] = REG_FIELD(CMU_R0D0, 24, 31), | ||
| 204 | [AHB_SSC_GEN_Z_O_20_13] = REG_FIELD(CMU_R0E8, 8, 15), | ||
| 205 | [LANE_PLL_CTRL_RXEQ_RXIDLE] = REG_FIELD(LANE_R048, 8, 15), | ||
| 206 | [AHB_PMA_LN_AGC_THSEL_VREGH] = REG_FIELD(LANE_R058, 16, 23), | ||
| 207 | [AHB_PMA_LN_GEN3_AGC_SD_THSEL] = REG_FIELD(LANE_R06c, 0, 7), | ||
| 208 | [AHB_PMA_LN_RX_SELR_GEN3] = REG_FIELD(LANE_R070, 16, 23), | ||
| 209 | [AHB_PMA_LN_TX_DRV] = REG_FIELD(LANE_R19C, 16, 23), | ||
| 210 | [P2S_RBUF_PTR_DIFF] = REG_FIELD(COMLANE_R004, 0, 7), | ||
| 211 | [CONFIG_VERSION] = REG_FIELD(COMLANE_R138, 16, 23), | ||
| 212 | [L1_MASTER_CDN] = REG_FIELD(COMLANE_R190, 8, 15), | ||
| 213 | [CMU_OK_I_0] = REG_FIELD(COMLANE_R194, 19, 19), | ||
| 214 | [COMRXEQ_MS_INIT_CTRL_7_0] = REG_FIELD(COMRXEQ_R004, 24, 31), | ||
| 215 | [COMRXEQ_HS_INIT_CAL_7_0] = REG_FIELD(COMRXEQ_R008, 0, 7), | ||
| 216 | [COMRXEQ_MS_RECAL_CTRL_7_0] = REG_FIELD(COMRXEQ_R00C, 8, 15), | ||
| 217 | [COMRXEQ_HS_RECAL_CTRL_7_0] = REG_FIELD(COMRXEQ_R00C, 16, 23), | ||
| 218 | [COMRXEQ_CSR_ATT_CONFIG] = REG_FIELD(COMRXEQ_R014, 16, 23), | ||
| 219 | [COMRXEQ_CSR_EBSTADAPT_WIN_LEN] = REG_FIELD(COMRXEQ_R018, 16, 23), | ||
| 220 | [COMRXEQ_CTRL_3_4] = REG_FIELD(COMRXEQ_R01C, 8, 15), | ||
| 221 | [COMRXEQ_CTRL_14_15_16] = REG_FIELD(COMRXEQ_R04C, 0, 7), | ||
| 222 | [COMRXEQ_CSR_DLEV_ERR_THRESH] = REG_FIELD(COMRXEQ_R088, 16, 23), | ||
| 223 | [COMRXEQ_CTRL_25] = REG_FIELD(COMRXEQ_R094, 24, 31), | ||
| 224 | [CSR_RXEQ_RATE_CHANGE_CAL_RUN_RATE2_O] = REG_FIELD(COMRXEQ_R098, 8, 15), | ||
| 225 | [COMRXEQ_HS_RCHANGE_CTRL_7_0] = REG_FIELD(COMRXEQ_R098, 16, 23), | ||
| 226 | [POR_EN] = REG_FIELD(SERDES_CTRL, 29, 29), | ||
| 227 | [TX0_ENABLE] = REG_FIELD(WIZ_LANEXCTL_STS, 29, 31), | ||
| 228 | [RX0_ENABLE] = REG_FIELD(WIZ_LANEXCTL_STS, 13, 15), | ||
| 229 | [PLL_ENABLE] = REG_FIELD(WIZ_PLL_CTRL, 29, 31), | ||
| 230 | [PLL_OK] = REG_FIELD(WIZ_PLL_CTRL, 28, 28), | ||
| 231 | }; | ||
| 92 | 232 | ||
| 93 | struct serdes_am654 { | 233 | struct serdes_am654 { |
| 94 | struct regmap *regmap; | 234 | struct regmap *regmap; |
| 95 | struct regmap_field *cmu_master_cdn_o; | 235 | struct regmap_field *fields[MAX_FIELDS]; |
| 96 | struct regmap_field *config_version; | ||
| 97 | struct regmap_field *l1_master_cdn_o; | ||
| 98 | struct regmap_field *cmu_ok_i_0; | ||
| 99 | struct regmap_field *por_en; | ||
| 100 | struct regmap_field *tx0_enable; | ||
| 101 | struct regmap_field *rx0_enable; | ||
| 102 | struct regmap_field *pll_enable; | ||
| 103 | struct regmap_field *pll_ok; | ||
| 104 | 236 | ||
| 105 | struct device *dev; | 237 | struct device *dev; |
| 106 | struct mux_control *control; | 238 | struct mux_control *control; |
| @@ -116,12 +248,12 @@ static int serdes_am654_enable_pll(struct serdes_am654 *phy) · 9 unmodified lines | |||
| 116 | int ret; | 248 | int ret; |
| 117 | u32 val; | 249 | u32 val; |
| 118 | 250 | ||
| 119 | ret = regmap_field_write(phy->pll_enable, PLL_ENABLE_STATE); | 251 | ret = regmap_field_write(phy->fields[PLL_ENABLE], PLL_ENABLE_STATE); |
| 120 | if (ret) | 252 | if (ret) |
| 121 | return ret; | 253 | return ret; |
| 122 | 254 | ||
| 123 | return regmap_field_read_poll_timeout(phy->pll_ok, val, val, 1000, | 255 | return regmap_field_read_poll_timeout(phy->fields[PLL_OK], val, val, |
| 124 | PLL_LOCK_TIME); | 256 | 1000, PLL_LOCK_TIME); |
| 125 | } | 257 | } |
| 126 | 258 | ||
| 127 | static void serdes_am654_disable_pll(struct serdes_am654 *phy) | 259 | static void serdes_am654_disable_pll(struct serdes_am654 *phy) |
| @@ -129,41 +261,39 @@ static void serdes_am654_disable_pll(struct serdes_am654 *phy) · 1 unmodified line | |||
| 129 | struct device *dev = phy->dev; | 261 | struct device *dev = phy->dev; |
| 130 | int ret; | 262 | int ret; |
| 131 | 263 | ||
| 132 | ret = regmap_field_write(phy->pll_enable, PLL_DISABLE_STATE); | 264 | ret = regmap_field_write(phy->fields[PLL_ENABLE], PLL_DISABLE_STATE); |
| 133 | if (ret) | 265 | if (ret) |
| 134 | dev_err(dev, "Failed to disable PLL\n"); | 266 | dev_err(dev, "Failed to disable PLL\n"); |
| 135 | } | 267 | } |
| 136 | 268 | ||
| 137 | static int serdes_am654_enable_txrx(struct serdes_am654 *phy) | 269 | static int serdes_am654_enable_txrx(struct serdes_am654 *phy) |
| 138 | { | 270 | { |
| 139 | int ret; | 271 | int ret = 0; |
| 140 | 272 | ||
| 141 | /* Enable TX */ | 273 | /* Enable TX */ |
| 142 | ret = regmap_field_write(phy->tx0_enable, TX0_ENABLE_STATE); | 274 | ret |= regmap_field_write(phy->fields[TX0_ENABLE], TX0_ENABLE_STATE); |
| 143 | if (ret) | ||
| 144 | return ret; | ||
| 145 | 275 | ||
| 146 | /* Enable RX */ | 276 | /* Enable RX */ |
| 147 | ret = regmap_field_write(phy->rx0_enable, RX0_ENABLE_STATE); | 277 | ret |= regmap_field_write(phy->fields[RX0_ENABLE], RX0_ENABLE_STATE); |
| 278 | |||
| 148 | if (ret) | 279 | if (ret) |
| 149 | return ret; | 280 | return -EIO; |
| 150 | 281 | ||
| 151 | return 0; | 282 | return 0; |
| 152 | } | 283 | } |
| 153 | 284 | ||
| 154 | static int serdes_am654_disable_txrx(struct serdes_am654 *phy) | 285 | static int serdes_am654_disable_txrx(struct serdes_am654 *phy) |
| 155 | { | 286 | { |
| 156 | int ret; | 287 | int ret = 0; |
| 157 | 288 | ||
| 158 | /* Disable TX */ | 289 | /* Disable TX */ |
| 159 | ret = regmap_field_write(phy->tx0_enable, TX0_DISABLE_STATE); | 290 | ret |= regmap_field_write(phy->fields[TX0_ENABLE], TX0_DISABLE_STATE); |
| 160 | if (ret) | ||
| 161 | return ret; | ||
| 162 | 291 | ||
| 163 | /* Disable RX */ | 292 | /* Disable RX */ |
| 164 | ret = regmap_field_write(phy->rx0_enable, RX0_DISABLE_STATE); | 293 | ret |= regmap_field_write(phy->fields[RX0_ENABLE], RX0_DISABLE_STATE); |
| 294 | |||
| 165 | if (ret) | 295 | if (ret) |
| 166 | return ret; | 296 | return -EIO; |
| 167 | 297 | ||
| 168 | return 0; | 298 | return 0; |
| 169 | } | 299 | } |
| @@ -187,8 +317,8 @@ static int serdes_am654_power_on(struct phy *x) · 17 unmodified lines | |||
| 187 | return ret; | 317 | return ret; |
| 188 | } | 318 | } |
| 189 | 319 | ||
| 190 | return regmap_field_read_poll_timeout(phy->cmu_ok_i_0, val, val, | 320 | return regmap_field_read_poll_timeout(phy->fields[CMU_OK_I_0], val, |
| 191 | SLEEP_TIME, PLL_LOCK_TIME); | 321 | val, SLEEP_TIME, PLL_LOCK_TIME); |
| 192 | } | 322 | } |
| 193 | 323 | ||
| 194 | static int serdes_am654_power_off(struct phy *x) | 324 | static int serdes_am654_power_off(struct phy *x) |
| @@ -286,19 +416,37 @@ static int serdes_am654_usb3_init(struct serdes_am654 *phy) · 91 unmodified lines | |||
| 286 | 416 | ||
| 287 | static int serdes_am654_pcie_init(struct serdes_am654 *phy) | 417 | static int serdes_am654_pcie_init(struct serdes_am654 *phy) |
| 288 | { | 418 | { |
| 289 | int ret; | 419 | int ret = 0; |
| 290 | |||
| 291 | ret = regmap_field_write(phy->config_version, VERSION); | ||
| 292 | if (ret) | ||
| 293 | return ret; | ||
| 294 | 420 | ||
| 295 | ret = regmap_field_write(phy->cmu_master_cdn_o, 0x1); | 421 | ret |= regmap_field_write(phy->fields[CMU_PLL_CTRL], 0x2); |
| 296 | if (ret) | 422 | ret |= regmap_field_write(phy->fields[AHB_PMA_CM_VCO_VBIAS_VREG], 0x98); |
| 297 | return ret; | 423 | ret |= regmap_field_write(phy->fields[AHB_PMA_CM_VCO_BIAS_VREG], 0x98); |
| 424 | ret |= regmap_field_write(phy->fields[AHB_PMA_CM_SR], 0x45); | ||
| 425 | ret |= regmap_field_write(phy->fields[AHB_SSC_GEN_Z_O_20_13], 0xe); | ||
| 426 | ret |= regmap_field_write(phy->fields[LANE_PLL_CTRL_RXEQ_RXIDLE], 0x5); | ||
| 427 | ret |= regmap_field_write(phy->fields[AHB_PMA_LN_AGC_THSEL_VREGH], 0x83); | ||
| 428 | ret |= regmap_field_write(phy->fields[AHB_PMA_LN_GEN3_AGC_SD_THSEL], 0x83); | ||
| 429 | ret |= regmap_field_write(phy->fields[AHB_PMA_LN_RX_SELR_GEN3], 0x81); | ||
| 430 | ret |= regmap_field_write(phy->fields[AHB_PMA_LN_TX_DRV], 0x3b); | ||
| 431 | ret |= regmap_field_write(phy->fields[P2S_RBUF_PTR_DIFF], 0x3); | ||
| 432 | ret |= regmap_field_write(phy->fields[CONFIG_VERSION], VERSION_VAL); | ||
| 433 | ret |= regmap_field_write(phy->fields[COMRXEQ_MS_INIT_CTRL_7_0], 0xf); | ||
| 434 | ret |= regmap_field_write(phy->fields[COMRXEQ_HS_INIT_CAL_7_0], 0x4f); | ||
| 435 | ret |= regmap_field_write(phy->fields[COMRXEQ_MS_RECAL_CTRL_7_0], 0xf); | ||
| 436 | ret |= regmap_field_write(phy->fields[COMRXEQ_HS_RECAL_CTRL_7_0], 0x4f); | ||
| 437 | ret |= regmap_field_write(phy->fields[COMRXEQ_CSR_ATT_CONFIG], 0x7); | ||
| 438 | ret |= regmap_field_write(phy->fields[COMRXEQ_CSR_EBSTADAPT_WIN_LEN], 0x7f); | ||
| 439 | ret |= regmap_field_write(phy->fields[COMRXEQ_CTRL_3_4], 0xf); | ||
| 440 | ret |= regmap_field_write(phy->fields[COMRXEQ_CTRL_14_15_16], 0x9a); | ||
| 441 | ret |= regmap_field_write(phy->fields[COMRXEQ_CSR_DLEV_ERR_THRESH], 0x32); | ||
| 442 | ret |= regmap_field_write(phy->fields[COMRXEQ_CTRL_25], 0x80); | ||
| 443 | ret |= regmap_field_write(phy->fields[CSR_RXEQ_RATE_CHANGE_CAL_RUN_RATE2_O], 0xf); | ||
| 444 | ret |= regmap_field_write(phy->fields[COMRXEQ_HS_RCHANGE_CTRL_7_0], 0x4f); | ||
| 445 | ret |= regmap_field_write(phy->fields[CMU_MASTER_CDN], 0x1); | ||
| 446 | ret |= regmap_field_write(phy->fields[L1_MASTER_CDN], 0x2); | ||
| 298 | 447 | ||
| 299 | ret = regmap_field_write(phy->l1_master_cdn_o, 0x1); | ||
| 300 | if (ret) | 448 | if (ret) |
| 301 | return ret; | 449 | return -EIO; |
| 302 | 450 | ||
| 303 | return 0; | 451 | return 0; |
| 304 | } | 452 | } |
| @@ -320,20 +468,19 @@ static int serdes_am654_init(struct phy *x) · 15 unmodified lines | |||
| 320 | static int serdes_am654_reset(struct phy *x) | 468 | static int serdes_am654_reset(struct phy *x) |
| 321 | { | 469 | { |
| 322 | struct serdes_am654 *phy = phy_get_drvdata(x); | 470 | struct serdes_am654 *phy = phy_get_drvdata(x); |
| 323 | int ret; | 471 | int ret = 0; |
| 324 | 472 | ||
| 325 | serdes_am654_disable_pll(phy); | 473 | serdes_am654_disable_pll(phy); |
| 326 | serdes_am654_disable_txrx(phy); | 474 | serdes_am654_disable_txrx(phy); |
| 327 | 475 | ||
| 328 | ret = regmap_field_write(phy->por_en, 0x1); | 476 | ret |= regmap_field_write(phy->fields[POR_EN], 0x1); |
| 329 | if (ret) | ||
| 330 | return ret; | ||
| 331 | 477 | ||
| 332 | mdelay(1); | 478 | mdelay(1); |
| 333 | 479 | ||
| 334 | ret = regmap_field_write(phy->por_en, 0x0); | 480 | ret |= regmap_field_write(phy->fields[POR_EN], 0x0); |
| 481 | |||
| 335 | if (ret) | 482 | if (ret) |
| 336 | return ret; | 483 | return -EIO; |
| 337 | 484 | ||
| 338 | return 0; | 485 | return 0; |
| 339 | } | 486 | } |
| @@ -587,66 +734,16 @@ static int serdes_am654_regfield_init(struct serdes_am654 *am654_phy) · 247 unmodified lines | |||
| 587 | { | 734 | { |
| 588 | struct regmap *regmap = am654_phy->regmap; | 735 | struct regmap *regmap = am654_phy->regmap; |
| 589 | struct device *dev = am654_phy->dev; | 736 | struct device *dev = am654_phy->dev; |
| 737 | int i; | ||
| 590 | 738 | ||
| 591 | am654_phy->cmu_master_cdn_o = devm_regmap_field_alloc(dev, regmap, | 739 | for (i = 0; i < MAX_FIELDS; i++) { |
| 592 | cmu_master_cdn_o); | 740 | am654_phy->fields[i] = devm_regmap_field_alloc(dev, |
| 593 | if (IS_ERR(am654_phy->cmu_master_cdn_o)) { | 741 | regmap, |
| 594 | dev_err(dev, "CMU_MASTER_CDN_O reg field init failed\n"); | 742 | serdes_am654_reg_fields[i]); |
| 595 | return PTR_ERR(am654_phy->cmu_master_cdn_o); | 743 | if (IS_ERR(am654_phy->fields[i])) { |
| 596 | } | 744 | dev_err(dev, "Unable to allocate regmap field %d\n", i); |
| 597 | 745 | return PTR_ERR(am654_phy->fields[i]); | |
| 598 | am654_phy->config_version = devm_regmap_field_alloc(dev, regmap, | 746 | } |
| 599 | config_version); | ||
| 600 | if (IS_ERR(am654_phy->config_version)) { | ||
| 601 | dev_err(dev, "CONFIG_VERSION reg field init failed\n"); | ||
| 602 | return PTR_ERR(am654_phy->config_version); | ||
| 603 | } | ||
| 604 | |||
| 605 | am654_phy->l1_master_cdn_o = devm_regmap_field_alloc(dev, regmap, | ||
| 606 | l1_master_cdn_o); | ||
| 607 | if (IS_ERR(am654_phy->l1_master_cdn_o)) { | ||
| 608 | dev_err(dev, "L1_MASTER_CDN_O reg field init failed\n"); | ||
| 609 | return PTR_ERR(am654_phy->l1_master_cdn_o); | ||
| 610 | } | ||
| 611 | |||
| 612 | am654_phy->cmu_ok_i_0 = devm_regmap_field_alloc(dev, regmap, | ||
| 613 | cmu_ok_i_0); | ||
| 614 | if (IS_ERR(am654_phy->cmu_ok_i_0)) { | ||
| 615 | dev_err(dev, "CMU_OK_I_0 reg field init failed\n"); | ||
| 616 | return PTR_ERR(am654_phy->cmu_ok_i_0); | ||
| 617 | } | ||
| 618 | |||
| 619 | am654_phy->por_en = devm_regmap_field_alloc(dev, regmap, por_en); | ||
| 620 | if (IS_ERR(am654_phy->por_en)) { | ||
| 621 | dev_err(dev, "POR_EN reg field init failed\n"); | ||
| 622 | return PTR_ERR(am654_phy->por_en); | ||
| 623 | } | ||
| 624 | |||
| 625 | am654_phy->tx0_enable = devm_regmap_field_alloc(dev, regmap, | ||
| 626 | tx0_enable); | ||
| 627 | if (IS_ERR(am654_phy->tx0_enable)) { | ||
| 628 | dev_err(dev, "TX0_ENABLE reg field init failed\n"); | ||
| 629 | return PTR_ERR(am654_phy->tx0_enable); | ||
| 630 | } | ||
| 631 | |||
| 632 | am654_phy->rx0_enable = devm_regmap_field_alloc(dev, regmap, | ||
| 633 | rx0_enable); | ||
| 634 | if (IS_ERR(am654_phy->rx0_enable)) { | ||
| 635 | dev_err(dev, "RX0_ENABLE reg field init failed\n"); | ||
| 636 | return PTR_ERR(am654_phy->rx0_enable); | ||
| 637 | } | ||
| 638 | |||
| 639 | am654_phy->pll_enable = devm_regmap_field_alloc(dev, regmap, | ||
| 640 | pll_enable); | ||
| 641 | if (IS_ERR(am654_phy->pll_enable)) { | ||
| 642 | dev_err(dev, "PLL_ENABLE reg field init failed\n"); | ||
| 643 | return PTR_ERR(am654_phy->pll_enable); | ||
| 644 | } | ||
| 645 | |||
| 646 | am654_phy->pll_ok = devm_regmap_field_alloc(dev, regmap, pll_ok); | ||
| 647 | if (IS_ERR(am654_phy->pll_ok)) { | ||
| 648 | dev_err(dev, "PLL_OK reg field init failed\n"); | ||
| 649 | return PTR_ERR(am654_phy->pll_ok); | ||
| 650 | } | 747 | } |
| 651 | 748 | ||
| 652 | return 0; | 749 | return 0; |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | |||
| 11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
| 12 | #include <linux/mfd/syscon.h> | 12 | #include <linux/mfd/syscon.h> |
| 13 | #include <linux/of.h> | 13 | #include <linux/of.h> |
| 14 | #include <linux/of_address.h> | ||
| 14 | #include <linux/of_net.h> | 15 | #include <linux/of_net.h> |
| 15 | #include <linux/phy.h> | 16 | #include <linux/phy.h> |
| 16 | #include <linux/phy/phy.h> | 17 | #include <linux/phy/phy.h> |
| @@ -22,7 +23,7 @@ · 5 unmodified lines | |||
| 22 | #define AM33XX_GMII_SEL_MODE_RGMII 2 | 23 | #define AM33XX_GMII_SEL_MODE_RGMII 2 |
| 23 | 24 | ||
| 24 | enum { | 25 | enum { |
| 25 | PHY_GMII_SEL_PORT_MODE, | 26 | PHY_GMII_SEL_PORT_MODE = 0, |
| 26 | PHY_GMII_SEL_RGMII_ID_MODE, | 27 | PHY_GMII_SEL_RGMII_ID_MODE, |
| 27 | PHY_GMII_SEL_RMII_IO_CLK_EN, | 28 | PHY_GMII_SEL_RMII_IO_CLK_EN, |
| 28 | PHY_GMII_SEL_LAST, | 29 | PHY_GMII_SEL_LAST, |
| @@ -41,6 +42,7 @@ struct phy_gmii_sel_soc_data { · 12 unmodified lines | |||
| 41 | u32 num_ports; | 42 | u32 num_ports; |
| 42 | u32 features; | 43 | u32 features; |
| 43 | const struct reg_field (*regfields)[PHY_GMII_SEL_LAST]; | 44 | const struct reg_field (*regfields)[PHY_GMII_SEL_LAST]; |
| 45 | bool use_of_data; | ||
| 44 | }; | 46 | }; |
| 45 | 47 | ||
| 46 | struct phy_gmii_sel_priv { | 48 | struct phy_gmii_sel_priv { |
| @@ -49,6 +51,8 @@ struct phy_gmii_sel_priv { · 2 unmodified lines | |||
| 49 | struct regmap *regmap; | 51 | struct regmap *regmap; |
| 50 | struct phy_provider *phy_provider; | 52 | struct phy_provider *phy_provider; |
| 51 | struct phy_gmii_sel_phy_priv *if_phys; | 53 | struct phy_gmii_sel_phy_priv *if_phys; |
| 54 | u32 num_ports; | ||
| 55 | u32 reg_offset; | ||
| 52 | }; | 56 | }; |
| 53 | 57 | ||
| 54 | static int phy_gmii_sel_mode(struct phy *phy, enum phy_mode mode, int submode) | 58 | static int phy_gmii_sel_mode(struct phy *phy, enum phy_mode mode, int submode) |
| @@ -147,13 +151,9 @@ static const · 92 unmodified lines | |||
| 147 | struct reg_field phy_gmii_sel_fields_dra7[][PHY_GMII_SEL_LAST] = { | 151 | struct reg_field phy_gmii_sel_fields_dra7[][PHY_GMII_SEL_LAST] = { |
| 148 | { | 152 | { |
| 149 | [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x554, 0, 1), | 153 | [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x554, 0, 1), |
| 150 | [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD((~0), 0, 0), | ||
| 151 | [PHY_GMII_SEL_RMII_IO_CLK_EN] = REG_FIELD((~0), 0, 0), | ||
| 152 | }, | 154 | }, |
| 153 | { | 155 | { |
| 154 | [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x554, 4, 5), | 156 | [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x554, 4, 5), |
| 155 | [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD((~0), 0, 0), | ||
| 156 | [PHY_GMII_SEL_RMII_IO_CLK_EN] = REG_FIELD((~0), 0, 0), | ||
| 157 | }, | 157 | }, |
| 158 | }; | 158 | }; |
| 159 | 159 | ||
| @@ -172,16 +172,19 @@ struct phy_gmii_sel_soc_data phy_gmii_sel_soc_dm814 = { · 12 unmodified lines | |||
| 172 | 172 | ||
| 173 | static const | 173 | static const |
| 174 | struct reg_field phy_gmii_sel_fields_am654[][PHY_GMII_SEL_LAST] = { | 174 | struct reg_field phy_gmii_sel_fields_am654[][PHY_GMII_SEL_LAST] = { |
| 175 | { | 175 | { [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x0, 0, 2), }, |
| 176 | [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x4040, 0, 1), | 176 | { [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x4, 0, 2), }, |
| 177 | [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD((~0), 0, 0), | 177 | { [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x8, 0, 2), }, |
| 178 | [PHY_GMII_SEL_RMII_IO_CLK_EN] = REG_FIELD((~0), 0, 0), | 178 | { [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0xC, 0, 2), }, |
| 179 | }, | 179 | { [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x10, 0, 2), }, |
| 180 | { [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x14, 0, 2), }, | ||
| 181 | { [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x18, 0, 2), }, | ||
| 182 | { [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x1C, 0, 2), }, | ||
| 180 | }; | 183 | }; |
| 181 | 184 | ||
| 182 | static const | 185 | static const |
| 183 | struct phy_gmii_sel_soc_data phy_gmii_sel_soc_am654 = { | 186 | struct phy_gmii_sel_soc_data phy_gmii_sel_soc_am654 = { |
| 184 | .num_ports = 1, | 187 | .use_of_data = true, |
| 185 | .regfields = phy_gmii_sel_fields_am654, | 188 | .regfields = phy_gmii_sel_fields_am654, |
| 186 | }; | 189 | }; |
| 187 | 190 | ||
| @@ -228,7 +231,7 @@ static struct phy *phy_gmii_sel_of_xlate(struct device *dev, · 40 unmodified lines | |||
| 228 | if (priv->soc_data->features & BIT(PHY_GMII_SEL_RMII_IO_CLK_EN) && | 231 | if (priv->soc_data->features & BIT(PHY_GMII_SEL_RMII_IO_CLK_EN) && |
| 229 | args->args_count < 2) | 232 | args->args_count < 2) |
| 230 | return ERR_PTR(-EINVAL); | 233 | return ERR_PTR(-EINVAL); |
| 231 | if (phy_id > priv->soc_data->num_ports) | 234 | if (phy_id > priv->num_ports) |
| 232 | return ERR_PTR(-EINVAL); | 235 | return ERR_PTR(-EINVAL); |
| 233 | if (phy_id != priv->if_phys[phy_id - 1].id) | 236 | if (phy_id != priv->if_phys[phy_id - 1].id) |
| 234 | return ERR_PTR(-EINVAL); | 237 | return ERR_PTR(-EINVAL); |
| @@ -242,68 +245,97 @@ static struct phy *phy_gmii_sel_of_xlate(struct device *dev, · 7 unmodified lines | |||
| 242 | return priv->if_phys[phy_id].if_phy; | 245 | return priv->if_phys[phy_id].if_phy; |
| 243 | } | 246 | } |
| 244 | 247 | ||
| 245 | static int phy_gmii_sel_init_ports(struct phy_gmii_sel_priv *priv) | 248 | static int phy_gmii_init_phy(struct phy_gmii_sel_priv *priv, int port, |
| 249 | struct phy_gmii_sel_phy_priv *if_phy) | ||
| 246 | { | 250 | { |
| 247 | const struct phy_gmii_sel_soc_data *soc_data = priv->soc_data; | 251 | const struct phy_gmii_sel_soc_data *soc_data = priv->soc_data; |
| 248 | struct device *dev = priv->dev; | 252 | struct device *dev = priv->dev; |
| 253 | const struct reg_field *fields; | ||
| 254 | struct regmap_field *regfield; | ||
| 255 | struct reg_field field; | ||
| 256 | int ret; | ||
| 257 | |||
| 258 | if_phy->id = port; | ||
| 259 | if_phy->priv = priv; | ||
| 260 | |||
| 261 | fields = soc_data->regfields[port - 1]; | ||
| 262 | field = *fields++; | ||
| 263 | field.reg += priv->reg_offset; | ||
| 264 | dev_dbg(dev, "%s field %x %d %d\n", __func__, | ||
| 265 | field.reg, field.msb, field.lsb); | ||
| 266 | |||
| 267 | regfield = devm_regmap_field_alloc(dev, priv->regmap, field); | ||
| 268 | if (IS_ERR(regfield)) | ||
| 269 | return PTR_ERR(regfield); | ||
| 270 | if_phy->fields[PHY_GMII_SEL_PORT_MODE] = regfield; | ||
| 271 | |||
| 272 | field = *fields++; | ||
| 273 | field.reg += priv->reg_offset; | ||
| 274 | if (soc_data->features & BIT(PHY_GMII_SEL_RGMII_ID_MODE)) { | ||
| 275 | regfield = devm_regmap_field_alloc(dev, | ||
| 276 | priv->regmap, | ||
| 277 | field); | ||
| 278 | if (IS_ERR(regfield)) | ||
| 279 | return PTR_ERR(regfield); | ||
| 280 | if_phy->fields[PHY_GMII_SEL_RGMII_ID_MODE] = regfield; | ||
| 281 | dev_dbg(dev, "%s field %x %d %d\n", __func__, | ||
| 282 | field.reg, field.msb, field.lsb); | ||
| 283 | } | ||
| 284 | |||
| 285 | field = *fields; | ||
| 286 | field.reg += priv->reg_offset; | ||
| 287 | if (soc_data->features & BIT(PHY_GMII_SEL_RMII_IO_CLK_EN)) { | ||
| 288 | regfield = devm_regmap_field_alloc(dev, | ||
| 289 | priv->regmap, | ||
| 290 | field); | ||
| 291 | if (IS_ERR(regfield)) | ||
| 292 | return PTR_ERR(regfield); | ||
| 293 | if_phy->fields[PHY_GMII_SEL_RMII_IO_CLK_EN] = regfield; | ||
| 294 | dev_dbg(dev, "%s field %x %d %d\n", __func__, | ||
| 295 | field.reg, field.msb, field.lsb); | ||
| 296 | } | ||
| 297 | |||
| 298 | if_phy->if_phy = devm_phy_create(dev, | ||
| 299 | priv->dev->of_node, | ||
| 300 | &phy_gmii_sel_ops); | ||
| 301 | if (IS_ERR(if_phy->if_phy)) { | ||
| 302 | ret = PTR_ERR(if_phy->if_phy); | ||
| 303 | dev_err(dev, "Failed to create phy%d %d\n", port, ret); | ||
| 304 | return ret; | ||
| 305 | } | ||
| 306 | phy_set_drvdata(if_phy->if_phy, if_phy); | ||
| 307 | |||
| 308 | return 0; | ||
| 309 | } | ||
| 310 | |||
| 311 | static int phy_gmii_sel_init_ports(struct phy_gmii_sel_priv *priv) | ||
| 312 | { | ||
| 313 | const struct phy_gmii_sel_soc_data *soc_data = priv->soc_data; | ||
| 249 | struct phy_gmii_sel_phy_priv *if_phys; | 314 | struct phy_gmii_sel_phy_priv *if_phys; |
| 250 | int i, num_ports, ret; | 315 | struct device *dev = priv->dev; |
| 316 | int i, ret; | ||
| 251 | 317 | ||
| 252 | num_ports = priv->soc_data->num_ports; | 318 | if (soc_data->use_of_data) { |
| 319 | const __be32 *offset; | ||
| 320 | u64 size; | ||
| 253 | 321 | ||
| 254 | if_phys = devm_kcalloc(priv->dev, num_ports, | 322 | offset = of_get_address(dev->of_node, 0, &size, NULL); |
| 323 | priv->num_ports = size / sizeof(u32); | ||
| 324 | if (!priv->num_ports) | ||
| 325 | return -EINVAL; | ||
| 326 | priv->reg_offset = __be32_to_cpu(*offset); | ||
| 327 | } | ||
| 328 | |||
| 329 | if_phys = devm_kcalloc(dev, priv->num_ports, | ||
| 255 | sizeof(*if_phys), GFP_KERNEL); | 330 | sizeof(*if_phys), GFP_KERNEL); |
| 256 | if (!if_phys) | 331 | if (!if_phys) |
| 257 | return -ENOMEM; | 332 | return -ENOMEM; |
| 258 | dev_dbg(dev, "%s %d\n", __func__, num_ports); | 333 | dev_dbg(dev, "%s %d\n", __func__, priv->num_ports); |
| 259 | |||
| 260 | for (i = 0; i < num_ports; i++) { | ||
| 261 | const struct reg_field *field; | ||
| 262 | struct regmap_field *regfield; | ||
| 263 | 334 | ||
| 264 | if_phys[i].id = i + 1; | 335 | for (i = 0; i < priv->num_ports; i++) { |
| 265 | if_phys[i].priv = priv; | 336 | ret = phy_gmii_init_phy(priv, i + 1, &if_phys[i]); |
| 266 | 337 | if (ret) | |
| 267 | field = &soc_data->regfields[i][PHY_GMII_SEL_PORT_MODE]; | ||
| 268 | dev_dbg(dev, "%s field %x %d %d\n", __func__, | ||
| 269 | field->reg, field->msb, field->lsb); | ||
| 270 | |||
| 271 | regfield = devm_regmap_field_alloc(dev, priv->regmap, *field); | ||
| 272 | if (IS_ERR(regfield)) | ||
| 273 | return PTR_ERR(regfield); | ||
| 274 | if_phys[i].fields[PHY_GMII_SEL_PORT_MODE] = regfield; | ||
| 275 | |||
| 276 | field = &soc_data->regfields[i][PHY_GMII_SEL_RGMII_ID_MODE]; | ||
| 277 | if (field->reg != (~0)) { | ||
| 278 | regfield = devm_regmap_field_alloc(dev, | ||
| 279 | priv->regmap, | ||
| 280 | *field); | ||
| 281 | if (IS_ERR(regfield)) | ||
| 282 | return PTR_ERR(regfield); | ||
| 283 | if_phys[i].fields[PHY_GMII_SEL_RGMII_ID_MODE] = | ||
| 284 | regfield; | ||
| 285 | } | ||
| 286 | |||
| 287 | field = &soc_data->regfields[i][PHY_GMII_SEL_RMII_IO_CLK_EN]; | ||
| 288 | if (field->reg != (~0)) { | ||
| 289 | regfield = devm_regmap_field_alloc(dev, | ||
| 290 | priv->regmap, | ||
| 291 | *field); | ||
| 292 | if (IS_ERR(regfield)) | ||
| 293 | return PTR_ERR(regfield); | ||
| 294 | if_phys[i].fields[PHY_GMII_SEL_RMII_IO_CLK_EN] = | ||
| 295 | regfield; | ||
| 296 | } | ||
| 297 | |||
| 298 | if_phys[i].if_phy = devm_phy_create(dev, | ||
| 299 | priv->dev->of_node, | ||
| 300 | &phy_gmii_sel_ops); | ||
| 301 | if (IS_ERR(if_phys[i].if_phy)) { | ||
| 302 | ret = PTR_ERR(if_phys[i].if_phy); | ||
| 303 | dev_err(dev, "Failed to create phy%d %d\n", i, ret); | ||
| 304 | return ret; | 338 | return ret; |
| 305 | } | ||
| 306 | phy_set_drvdata(if_phys[i].if_phy, &if_phys[i]); | ||
| 307 | } | 339 | } |
| 308 | 340 | ||
| 309 | priv->if_phys = if_phys; | 341 | priv->if_phys = if_phys; |
| @@ -328,6 +360,7 @@ static int phy_gmii_sel_probe(struct platform_device *pdev) · 18 unmodified lines | |||
| 328 | 360 | ||
| 329 | priv->dev = &pdev->dev; | 361 | priv->dev = &pdev->dev; |
| 330 | priv->soc_data = of_id->data; | 362 | priv->soc_data = of_id->data; |
| 363 | priv->num_ports = priv->soc_data->num_ports; | ||
| 331 | 364 | ||
| 332 | priv->regmap = syscon_node_to_regmap(node->parent); | 365 | priv->regmap = syscon_node_to_regmap(node->parent); |
| 333 | if (IS_ERR(priv->regmap)) { | 366 | if (IS_ERR(priv->regmap)) { |
| @@ -20,7 +20,6 @@ · 19 unmodified lines | |||
| 20 | #include <linux/pm_runtime.h> | 20 | #include <linux/pm_runtime.h> |
| 21 | #include <linux/regmap.h> | 21 | #include <linux/regmap.h> |
| 22 | #include <linux/reset-controller.h> | 22 | #include <linux/reset-controller.h> |
| 23 | #include <dt-bindings/phy/phy.h> | ||
| 24 | 23 | ||
| 25 | #define WIZ_SERDES_CTRL 0x404 | 24 | #define WIZ_SERDES_CTRL 0x404 |
| 26 | #define WIZ_SERDES_TOP_CTRL 0x408 | 25 | #define WIZ_SERDES_TOP_CTRL 0x408 |
| @@ -6,23 +6,23 @@ · 5 unmodified lines | |||
| 6 | * Author: Kishon Vijay Abraham I <kishon@ti.com> | 6 | * Author: Kishon Vijay Abraham I <kishon@ti.com> |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #include <linux/module.h> | ||
| 10 | #include <linux/platform_device.h> | ||
| 11 | #include <linux/slab.h> | ||
| 12 | #include <linux/of.h> | ||
| 13 | #include <linux/io.h> | ||
| 14 | #include <linux/phy/omap_usb.h> | ||
| 15 | #include <linux/usb/phy_companion.h> | ||
| 16 | #include <linux/clk.h> | 9 | #include <linux/clk.h> |
| 17 | #include <linux/err.h> | ||
| 18 | #include <linux/pm_runtime.h> | ||
| 19 | #include <linux/delay.h> | 10 | #include <linux/delay.h> |
| 11 | #include <linux/err.h> | ||
| 12 | #include <linux/io.h> | ||
| 13 | #include <linux/mfd/syscon.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/of.h> | ||
| 16 | #include <linux/of_platform.h> | ||
| 20 | #include <linux/phy/omap_control_phy.h> | 17 | #include <linux/phy/omap_control_phy.h> |
| 18 | #include <linux/phy/omap_usb.h> | ||
| 21 | #include <linux/phy/phy.h> | 19 | #include <linux/phy/phy.h> |
| 22 | #include <linux/mfd/syscon.h> | 20 | #include <linux/platform_device.h> |
| 21 | #include <linux/pm_runtime.h> | ||
| 23 | #include <linux/regmap.h> | 22 | #include <linux/regmap.h> |
| 24 | #include <linux/of_platform.h> | 23 | #include <linux/slab.h> |
| 25 | #include <linux/sys_soc.h> | 24 | #include <linux/sys_soc.h> |
| 25 | #include <linux/usb/phy_companion.h> | ||
| 26 | 26 | ||
| 27 | #define USB2PHY_ANA_CONFIG1 0x4c | 27 | #define USB2PHY_ANA_CONFIG1 0x4c |
| 28 | #define USB2PHY_DISCON_BYP_LATCH BIT(31) | 28 | #define USB2PHY_DISCON_BYP_LATCH BIT(31) |
| @@ -89,7 +89,7 @@ static inline void omap_usb_writel(void __iomem *addr, unsigned int offset, · 60 unmodified lines | |||
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | /** | 91 | /** |
| 92 | * omap_usb2_set_comparator - links the comparator present in the sytem with | 92 | * omap_usb2_set_comparator - links the comparator present in the system with |
| 93 | * this phy | 93 | * this phy |
| 94 | * @comparator - the companion phy(comparator) for this phy | 94 | * @comparator - the companion phy(comparator) for this phy |
| 95 | * | 95 | * |
| @@ -142,7 +142,7 @@ static int omap_usb_set_host(struct usb_otg *otg, struct usb_bus *host) · 46 unmodified lines | |||
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | static int omap_usb_set_peripheral(struct usb_otg *otg, | 144 | static int omap_usb_set_peripheral(struct usb_otg *otg, |
| 145 | struct usb_gadget *gadget) | 145 | struct usb_gadget *gadget) |
| 146 | { | 146 | { |
| 147 | otg->gadget = gadget; | 147 | otg->gadget = gadget; |
| 148 | if (!gadget) | 148 | if (!gadget) |
| @@ -409,7 +409,7 @@ static int omap_usb2_probe(struct platform_device *pdev) · 260 unmodified lines | |||
| 409 | return PTR_ERR(phy->phy_base); | 409 | return PTR_ERR(phy->phy_base); |
| 410 | 410 | ||
| 411 | phy->syscon_phy_power = syscon_regmap_lookup_by_phandle(node, | 411 | phy->syscon_phy_power = syscon_regmap_lookup_by_phandle(node, |
| 412 | "syscon-phy-power"); | 412 | "syscon-phy-power"); |
| 413 | if (IS_ERR(phy->syscon_phy_power)) { | 413 | if (IS_ERR(phy->syscon_phy_power)) { |
| 414 | dev_dbg(&pdev->dev, | 414 | dev_dbg(&pdev->dev, |
| 415 | "can't get syscon-phy-power, using control device\n"); | 415 | "can't get syscon-phy-power, using control device\n"); |
| @@ -438,7 +438,6 @@ static int omap_usb2_probe(struct platform_device *pdev) · 22 unmodified lines | |||
| 438 | } | 438 | } |
| 439 | } | 439 | } |
| 440 | 440 | ||
| 441 | |||
| 442 | phy->wkupclk = devm_clk_get(phy->dev, "wkupclk"); | 441 | phy->wkupclk = devm_clk_get(phy->dev, "wkupclk"); |
| 443 | if (IS_ERR(phy->wkupclk)) { | 442 | if (IS_ERR(phy->wkupclk)) { |
| 444 | if (PTR_ERR(phy->wkupclk) == -EPROBE_DEFER) | 443 | if (PTR_ERR(phy->wkupclk) == -EPROBE_DEFER) |
| @@ -452,10 +451,10 @@ static int omap_usb2_probe(struct platform_device *pdev) · 7 unmodified lines | |||
| 452 | if (PTR_ERR(phy->wkupclk) != -EPROBE_DEFER) | 451 | if (PTR_ERR(phy->wkupclk) != -EPROBE_DEFER) |
| 453 | dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n"); | 452 | dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n"); |
| 454 | return PTR_ERR(phy->wkupclk); | 453 | return PTR_ERR(phy->wkupclk); |
| 455 | } else { | ||
| 456 | dev_warn(&pdev->dev, | ||
| 457 | "found usb_phy_cm_clk32k, please fix DTS\n"); | ||
| 458 | } | 454 | } |
| 455 | |||
| 456 | dev_warn(&pdev->dev, | ||
| 457 | "found usb_phy_cm_clk32k, please fix DTS\n"); | ||
| 459 | } | 458 | } |
| 460 | 459 | ||
| 461 | phy->optclk = devm_clk_get(phy->dev, "refclk"); | 460 | phy->optclk = devm_clk_get(phy->dev, "refclk"); |
| @@ -504,7 +503,6 @@ static int omap_usb2_probe(struct platform_device *pdev) · 42 unmodified lines | |||
| 504 | return PTR_ERR(phy_provider); | 503 | return PTR_ERR(phy_provider); |
| 505 | } | 504 | } |
| 506 | 505 | ||
| 507 | |||
| 508 | usb_add_phy_dev(&phy->phy); | 506 | usb_add_phy_dev(&phy->phy); |
| 509 | 507 | ||
| 510 | return 0; | 508 | return 0; |
| @@ -140,6 +140,17 @@ config RESET_QCOM_PDC · 139 unmodified lines | |||
| 140 | to control reset signals provided by PDC for Modem, Compute, | 140 | to control reset signals provided by PDC for Modem, Compute, |
| 141 | Display, GPU, Debug, AOP, Sensors, Audio, SP and APPS. | 141 | Display, GPU, Debug, AOP, Sensors, Audio, SP and APPS. |
| 142 | 142 | ||
| 143 | config RESET_RASPBERRYPI | ||
| 144 | tristate "Raspberry Pi 4 Firmware Reset Driver" | ||
| 145 | depends on RASPBERRYPI_FIRMWARE || (RASPBERRYPI_FIRMWARE=n && COMPILE_TEST) | ||
| 146 | default USB_XHCI_PCI | ||
| 147 | help | ||
| 148 | Raspberry Pi 4's co-processor controls some of the board's HW | ||
| 149 | initialization process, but it's up to Linux to trigger it when | ||
| 150 | relevant. This driver provides a reset controller capable of | ||
| 151 | interfacing with RPi4's co-processor and model these firmware | ||
| 152 | initialization routines as reset lines. | ||
| 153 | |||
| 143 | config RESET_SCMI | 154 | config RESET_SCMI |
| 144 | tristate "Reset driver controlled via ARM SCMI interface" | 155 | tristate "Reset driver controlled via ARM SCMI interface" |
| 145 | depends on ARM_SCMI_PROTOCOL || COMPILE_TEST | 156 | depends on ARM_SCMI_PROTOCOL || COMPILE_TEST |
| @@ -21,6 +21,7 @@ obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o · 20 unmodified lines | |||
| 21 | obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o | 21 | obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o |
| 22 | obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o | 22 | obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o |
| 23 | obj-$(CONFIG_RESET_QCOM_PDC) += reset-qcom-pdc.o | 23 | obj-$(CONFIG_RESET_QCOM_PDC) += reset-qcom-pdc.o |
| 24 | obj-$(CONFIG_RESET_RASPBERRYPI) += reset-raspberrypi.o | ||
| 24 | obj-$(CONFIG_RESET_SCMI) += reset-scmi.o | 25 | obj-$(CONFIG_RESET_SCMI) += reset-scmi.o |
| 25 | obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o | 26 | obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o |
| 26 | obj-$(CONFIG_RESET_STM32MP157) += reset-stm32mp1.o | 27 | obj-$(CONFIG_RESET_STM32MP157) += reset-stm32mp1.o |
| @@ -0,0 +1,122 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Raspberry Pi 4 firmware reset driver | ||
| 4 | * | ||
| 5 | * Copyright (C) 2020 Nicolas Saenz Julienne <nsaenzjulienne@suse.de> | ||
| 6 | */ | ||
| 7 | #include <linux/delay.h> | ||
| 8 | #include <linux/device.h> | ||
| 9 | #include <linux/module.h> | ||
| 10 | #include <linux/of.h> | ||
| 11 | #include <linux/platform_device.h> | ||
| 12 | #include <linux/reset-controller.h> | ||
| 13 | #include <soc/bcm2835/raspberrypi-firmware.h> | ||
| 14 | #include <dt-bindings/reset/raspberrypi,firmware-reset.h> | ||
| 15 | |||
| 16 | struct rpi_reset { | ||
| 17 | struct reset_controller_dev rcdev; | ||
| 18 | struct rpi_firmware *fw; | ||
| 19 | }; | ||
| 20 | |||
| 21 | static inline struct rpi_reset *to_rpi(struct reset_controller_dev *rcdev) | ||
| 22 | { | ||
| 23 | return container_of(rcdev, struct rpi_reset, rcdev); | ||
| 24 | } | ||
| 25 | |||
| 26 | static int rpi_reset_reset(struct reset_controller_dev *rcdev, unsigned long id) | ||
| 27 | { | ||
| 28 | struct rpi_reset *priv = to_rpi(rcdev); | ||
| 29 | u32 dev_addr; | ||
| 30 | int ret; | ||
| 31 | |||
| 32 | switch (id) { | ||
| 33 | case RASPBERRYPI_FIRMWARE_RESET_ID_USB: | ||
| 34 | /* | ||
| 35 | * The Raspberry Pi 4 gets its USB functionality from VL805, a | ||
| 36 | * PCIe chip that implements xHCI. After a PCI reset, VL805's | ||
| 37 | * firmware may either be loaded directly from an EEPROM or, if | ||
| 38 | * not present, by the SoC's co-processor, VideoCore. rpi's | ||
| 39 | * VideoCore OS contains both the non public firmware load | ||
| 40 | * logic and the VL805 firmware blob. This triggers the | ||
| 41 | * aforementioned process. | ||
| 42 | * | ||
| 43 | * The pci device address is expected is expected by the | ||
| 44 | * firmware encoded like this: | ||
| 45 | * | ||
| 46 | * PCI_BUS << 20 | PCI_SLOT << 15 | PCI_FUNC << 12 | ||
| 47 | * | ||
| 48 | * But since rpi's PCIe is hardwired, we know the address in | ||
| 49 | * advance. | ||
| 50 | */ | ||
| 51 | dev_addr = 0x100000; | ||
| 52 | ret = rpi_firmware_property(priv->fw, RPI_FIRMWARE_NOTIFY_XHCI_RESET, | ||
| 53 | &dev_addr, sizeof(dev_addr)); | ||
| 54 | if (ret) | ||
| 55 | return ret; | ||
| 56 | |||
| 57 | /* Wait for vl805 to startup */ | ||
| 58 | usleep_range(200, 1000); | ||
| 59 | break; | ||
| 60 | |||
| 61 | default: | ||
| 62 | return -EINVAL; | ||
| 63 | } | ||
| 64 | |||
| 65 | return 0; | ||
| 66 | } | ||
| 67 | |||
| 68 | static const struct reset_control_ops rpi_reset_ops = { | ||
| 69 | .reset = rpi_reset_reset, | ||
| 70 | }; | ||
| 71 | |||
| 72 | static int rpi_reset_probe(struct platform_device *pdev) | ||
| 73 | { | ||
| 74 | struct device *dev = &pdev->dev; | ||
| 75 | struct rpi_firmware *fw; | ||
| 76 | struct device_node *np; | ||
| 77 | struct rpi_reset *priv; | ||
| 78 | |||
| 79 | np = of_get_parent(dev->of_node); | ||
| 80 | if (!np) { | ||
| 81 | dev_err(dev, "Missing firmware node\n"); | ||
| 82 | return -ENOENT; | ||
| 83 | } | ||
| 84 | |||
| 85 | fw = rpi_firmware_get(np); | ||
| 86 | of_node_put(np); | ||
| 87 | if (!fw) | ||
| 88 | return -EPROBE_DEFER; | ||
| 89 | |||
| 90 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
| 91 | if (!priv) | ||
| 92 | return -ENOMEM; | ||
| 93 | |||
| 94 | dev_set_drvdata(dev, priv); | ||
| 95 | |||
| 96 | priv->fw = fw; | ||
| 97 | priv->rcdev.owner = THIS_MODULE; | ||
| 98 | priv->rcdev.nr_resets = RASPBERRYPI_FIRMWARE_RESET_NUM_IDS; | ||
| 99 | priv->rcdev.ops = &rpi_reset_ops; | ||
| 100 | priv->rcdev.of_node = dev->of_node; | ||
| 101 | |||
| 102 | return devm_reset_controller_register(dev, &priv->rcdev); | ||
| 103 | } | ||
| 104 | |||
| 105 | static const struct of_device_id rpi_reset_of_match[] = { | ||
| 106 | { .compatible = "raspberrypi,firmware-reset" }, | ||
| 107 | { /* sentinel */ } | ||
| 108 | }; | ||
| 109 | MODULE_DEVICE_TABLE(of, rpi_reset_of_match); | ||
| 110 | |||
| 111 | static struct platform_driver rpi_reset_driver = { | ||
| 112 | .probe = rpi_reset_probe, | ||
| 113 | .driver = { | ||
| 114 | .name = "raspberrypi-reset", | ||
| 115 | .of_match_table = rpi_reset_of_match, | ||
| 116 | }, | ||
| 117 | }; | ||
| 118 | module_platform_driver(rpi_reset_driver); | ||
| 119 | |||
| 120 | MODULE_AUTHOR("Nicolas Saenz Julienne <nsaenzjulienne@suse.de>"); | ||
| 121 | MODULE_DESCRIPTION("Raspberry Pi 4 firmware reset driver"); | ||
| 122 | MODULE_LICENSE("GPL"); | ||
| @@ -44,8 +44,6 @@ source "drivers/staging/media/tegra-video/Kconfig" · 43 unmodified lines | |||
| 44 | 44 | ||
| 45 | source "drivers/staging/media/ipu3/Kconfig" | 45 | source "drivers/staging/media/ipu3/Kconfig" |
| 46 | 46 | ||
| 47 | source "drivers/staging/media/phy-rockchip-dphy-rx0/Kconfig" | ||
| 48 | |||
| 49 | source "drivers/staging/media/rkisp1/Kconfig" | 47 | source "drivers/staging/media/rkisp1/Kconfig" |
| 50 | 48 | ||
| 51 | endif | 49 | endif |
| @@ -10,6 +10,5 @@ obj-$(CONFIG_VIDEO_TEGRA) += tegra-video/ · 9 unmodified lines | |||
| 10 | obj-$(CONFIG_TEGRA_VDE) += tegra-vde/ | 10 | obj-$(CONFIG_TEGRA_VDE) += tegra-vde/ |
| 11 | obj-$(CONFIG_VIDEO_HANTRO) += hantro/ | 11 | obj-$(CONFIG_VIDEO_HANTRO) += hantro/ |
| 12 | obj-$(CONFIG_VIDEO_IPU3_IMGU) += ipu3/ | 12 | obj-$(CONFIG_VIDEO_IPU3_IMGU) += ipu3/ |
| 13 | obj-$(CONFIG_PHY_ROCKCHIP_DPHY_RX0) += phy-rockchip-dphy-rx0/ | ||
| 14 | obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1) += rkisp1/ | 13 | obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1) += rkisp1/ |
| 15 | obj-$(CONFIG_VIDEO_ZORAN) += zoran/ | 14 | obj-$(CONFIG_VIDEO_ZORAN) += zoran/ |
| @@ -1,13 +0,0 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | |||
| 3 | config PHY_ROCKCHIP_DPHY_RX0 | ||
| 4 | tristate "Rockchip MIPI Synopsys DPHY RX0 driver" | ||
| 5 | depends on ARCH_ROCKCHIP || COMPILE_TEST | ||
| 6 | select GENERIC_PHY_MIPI_DPHY | ||
| 7 | select GENERIC_PHY | ||
| 8 | help | ||
| 9 | Enable this to support the Rockchip MIPI Synopsys DPHY RX0 | ||
| 10 | associated to the Rockchip ISP module present in RK3399 SoCs. | ||
| 11 | |||
| 12 | To compile this driver as a module, choose M here: the module | ||
| 13 | will be called phy-rockchip-dphy-rx0. | ||
| @@ -1,2 +0,0 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | ||
| 2 | obj-$(CONFIG_PHY_ROCKCHIP_DPHY_RX0) += phy-rockchip-dphy-rx0.o | ||
| @@ -1,6 +0,0 @@ | |||
| 1 | The main reason for keeping this in staging is because the only driver | ||
| 2 | that uses this is rkisp1, which is also in staging. It should be moved together | ||
| 3 | with rkisp1. | ||
| 4 | |||
| 5 | Please CC patches to Linux Media <linux-media@vger.kernel.org> and | ||
| 6 | Helen Koike <helen.koike@collabora.com>. | ||
| @@ -16,7 +16,19 @@ menuconfig USB4 · 15 unmodified lines | |||
| 16 | To compile this driver a module, choose M here. The module will be | 16 | To compile this driver a module, choose M here. The module will be |
| 17 | called thunderbolt. | 17 | called thunderbolt. |
| 18 | 18 | ||
| 19 | if USB4 | ||
| 20 | |||
| 21 | config USB4_DEBUGFS_WRITE | ||
| 22 | bool "Enable write by debugfs to configuration spaces (DANGEROUS)" | ||
| 23 | help | ||
| 24 | Enables writing to device configuration registers through | ||
| 25 | debugfs interface. | ||
| 26 | |||
| 27 | Only enable this if you know what you are doing! Never enable | ||
| 28 | this for production systems or distro kernels. | ||
| 29 | |||
| 19 | config USB4_KUNIT_TEST | 30 | config USB4_KUNIT_TEST |
| 20 | bool "KUnit tests" | 31 | bool "KUnit tests" |
| 21 | depends on KUNIT=y | 32 | depends on KUNIT=y |
| 22 | depends on USB4=y | 33 | |
| 34 | endif # USB4 | ||
| @@ -4,4 +4,6 @@ thunderbolt-objs := nhi.o nhi_ops.o ctl.o tb.o switch.o cap.o path.o tunnel.o ee · 3 unmodified lines | |||
| 4 | thunderbolt-objs += domain.o dma_port.o icm.o property.o xdomain.o lc.o tmu.o usb4.o | 4 | thunderbolt-objs += domain.o dma_port.o icm.o property.o xdomain.o lc.o tmu.o usb4.o |
| 5 | thunderbolt-objs += nvm.o retimer.o quirks.o | 5 | thunderbolt-objs += nvm.o retimer.o quirks.o |
| 6 | 6 | ||
| 7 | obj-${CONFIG_USB4_KUNIT_TEST} += test.o | 7 | thunderbolt-${CONFIG_ACPI} += acpi.o |
| 8 | thunderbolt-$(CONFIG_DEBUG_FS) += debugfs.o | ||
| 9 | thunderbolt-${CONFIG_USB4_KUNIT_TEST} += test.o | ||
| @@ -0,0 +1,117 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * ACPI support | ||
| 4 | * | ||
| 5 | * Copyright (C) 2020, Intel Corporation | ||
| 6 | * Author: Mika Westerberg <mika.westerberg@linux.intel.com> | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/acpi.h> | ||
| 10 | |||
| 11 | #include "tb.h" | ||
| 12 | |||
| 13 | static acpi_status tb_acpi_add_link(acpi_handle handle, u32 level, void *data, | ||
| 14 | void **return_value) | ||
| 15 | { | ||
| 16 | struct fwnode_reference_args args; | ||
| 17 | struct fwnode_handle *fwnode; | ||
| 18 | struct tb_nhi *nhi = data; | ||
| 19 | struct acpi_device *adev; | ||
| 20 | struct pci_dev *pdev; | ||
| 21 | struct device *dev; | ||
| 22 | int ret; | ||
| 23 | |||
| 24 | if (acpi_bus_get_device(handle, &adev)) | ||
| 25 | return AE_OK; | ||
| 26 | |||
| 27 | fwnode = acpi_fwnode_handle(adev); | ||
| 28 | ret = fwnode_property_get_reference_args(fwnode, "usb4-host-interface", | ||
| 29 | NULL, 0, 0, &args); | ||
| 30 | if (ret) | ||
| 31 | return AE_OK; | ||
| 32 | |||
| 33 | /* It needs to reference this NHI */ | ||
| 34 | if (nhi->pdev->dev.fwnode != args.fwnode) | ||
| 35 | goto out_put; | ||
| 36 | |||
| 37 | /* | ||
| 38 | * Try to find physical device walking upwards to the hierarcy. | ||
| 39 | * We need to do this because the xHCI driver might not yet be | ||
| 40 | * bound so the USB3 SuperSpeed ports are not yet created. | ||
| 41 | */ | ||
| 42 | dev = acpi_get_first_physical_node(adev); | ||
| 43 | while (!dev) { | ||
| 44 | adev = adev->parent; | ||
| 45 | if (!adev) | ||
| 46 | break; | ||
| 47 | dev = acpi_get_first_physical_node(adev); | ||
| 48 | } | ||
| 49 | |||
| 50 | if (!dev) | ||
| 51 | goto out_put; | ||
| 52 | |||
| 53 | /* | ||
| 54 | * Check that the device is PCIe. This is because USB3 | ||
| 55 | * SuperSpeed ports have this property and they are not power | ||
| 56 | * managed with the xHCI and the SuperSpeed hub so we create the | ||
| 57 | * link from xHCI instead. | ||
| 58 | */ | ||
| 59 | while (!dev_is_pci(dev)) | ||
| 60 | dev = dev->parent; | ||
| 61 | |||
| 62 | if (!dev) | ||
| 63 | goto out_put; | ||
| 64 | |||
| 65 | /* | ||
| 66 | * Check that this actually matches the type of device we | ||
| 67 | * expect. It should either be xHCI or PCIe root/downstream | ||
| 68 | * port. | ||
| 69 | */ | ||
| 70 | pdev = to_pci_dev(dev); | ||
| 71 | if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI || | ||
| 72 | (pci_is_pcie(pdev) && | ||
| 73 | (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT || | ||
| 74 | pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM))) { | ||
| 75 | const struct device_link *link; | ||
| 76 | |||
| 77 | link = device_link_add(&pdev->dev, &nhi->pdev->dev, | ||
| 78 | DL_FLAG_AUTOREMOVE_SUPPLIER | | ||
| 79 | DL_FLAG_PM_RUNTIME); | ||
| 80 | if (link) { | ||
| 81 | dev_dbg(&nhi->pdev->dev, "created link from %s\n", | ||
| 82 | dev_name(&pdev->dev)); | ||
| 83 | } else { | ||
| 84 | dev_warn(&nhi->pdev->dev, "device link creation from %s failed\n", | ||
| 85 | dev_name(&pdev->dev)); | ||
| 86 | } | ||
| 87 | } | ||
| 88 | |||
| 89 | out_put: | ||
| 90 | fwnode_handle_put(args.fwnode); | ||
| 91 | return AE_OK; | ||
| 92 | } | ||
| 93 | |||
| 94 | /** | ||
| 95 | * tb_acpi_add_links() - Add device links based on ACPI description | ||
| 96 | * @nhi: Pointer to NHI | ||
| 97 | * | ||
| 98 | * Goes over ACPI namespace finding tunneled ports that reference to | ||
| 99 | * @nhi ACPI node. For each reference a device link is added. The link | ||
| 100 | * is automatically removed by the driver core. | ||
| 101 | */ | ||
| 102 | void tb_acpi_add_links(struct tb_nhi *nhi) | ||
| 103 | { | ||
| 104 | acpi_status status; | ||
| 105 | |||
| 106 | if (!has_acpi_companion(&nhi->pdev->dev)) | ||
| 107 | return; | ||
| 108 | |||
| 109 | /* | ||
| 110 | * Find all devices that have usb4-host-controller interface | ||
| 111 | * property that references to this NHI. | ||
| 112 | */ | ||
| 113 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 32, | ||
| 114 | tb_acpi_add_link, NULL, nhi, NULL); | ||
| 115 | if (ACPI_FAILURE(status)) | ||
| 116 | dev_warn(&nhi->pdev->dev, "failed to enumerate tunneled ports\n"); | ||
| 117 | } | ||
| @@ -15,14 +15,6 @@ · 14 unmodified lines | |||
| 15 | #define VSE_CAP_OFFSET_MAX 0xffff | 15 | #define VSE_CAP_OFFSET_MAX 0xffff |
| 16 | #define TMU_ACCESS_EN BIT(20) | 16 | #define TMU_ACCESS_EN BIT(20) |
| 17 | 17 | ||
| 18 | struct tb_cap_any { | ||
| 19 | union { | ||
| 20 | struct tb_cap_basic basic; | ||
| 21 | struct tb_cap_extended_short extended_short; | ||
| 22 | struct tb_cap_extended_long extended_long; | ||
| 23 | }; | ||
| 24 | } __packed; | ||
| 25 | |||
| 26 | static int tb_port_enable_tmu(struct tb_port *port, bool enable) | 18 | static int tb_port_enable_tmu(struct tb_port *port, bool enable) |
| 27 | { | 19 | { |
| 28 | struct tb_switch *sw = port->sw; | 20 | struct tb_switch *sw = port->sw; |
| @@ -67,23 +59,50 @@ static void tb_port_dummy_read(struct tb_port *port) · 38 unmodified lines | |||
| 67 | } | 59 | } |
| 68 | } | 60 | } |
| 69 | 61 | ||
| 62 | /** | ||
| 63 | * tb_port_next_cap() - Return next capability in the linked list | ||
| 64 | * @port: Port to find the capability for | ||
| 65 | * @offset: Previous capability offset (%0 for start) | ||
| 66 | * | ||
| 67 | * Returns dword offset of the next capability in port config space | ||
| 68 | * capability list and returns it. Passing %0 returns the first entry in | ||
| 69 | * the capability list. If no next capability is found returns %0. In case | ||
| 70 | * of failure returns negative errno. | ||
| 71 | */ | ||
| 72 | int tb_port_next_cap(struct tb_port *port, unsigned int offset) | ||
| 73 | { | ||
| 74 | struct tb_cap_any header; | ||
| 75 | int ret; | ||
| 76 | |||
| 77 | if (!offset) | ||
| 78 | return port->config.first_cap_offset; | ||
| 79 | |||
| 80 | ret = tb_port_read(port, &header, TB_CFG_PORT, offset, 1); | ||
| 81 | if (ret) | ||
| 82 | return ret; | ||
| 83 | |||
| 84 | return header.basic.next; | ||
| 85 | } | ||
| 86 | |||
| 70 | static int __tb_port_find_cap(struct tb_port *port, enum tb_port_cap cap) | 87 | static int __tb_port_find_cap(struct tb_port *port, enum tb_port_cap cap) |
| 71 | { | 88 | { |
| 72 | u32 offset = 1; | 89 | int offset = 0; |
| 73 | 90 | ||
| 74 | do { | 91 | do { |
| 75 | struct tb_cap_any header; | 92 | struct tb_cap_any header; |
| 76 | int ret; | 93 | int ret; |
| 77 | 94 | ||
| 95 | offset = tb_port_next_cap(port, offset); | ||
| 96 | if (offset < 0) | ||
| 97 | return offset; | ||
| 98 | |||
| 78 | ret = tb_port_read(port, &header, TB_CFG_PORT, offset, 1); | 99 | ret = tb_port_read(port, &header, TB_CFG_PORT, offset, 1); |
| 79 | if (ret) | 100 | if (ret) |
| 80 | return ret; | 101 | return ret; |
| 81 | 102 | ||
| 82 | if (header.basic.cap == cap) | 103 | if (header.basic.cap == cap) |
| 83 | return offset; | 104 | return offset; |
| 84 | 105 | } while (offset > 0); | |
| 85 | offset = header.basic.next; | ||
| 86 | } while (offset); | ||
| 87 | 106 | ||
| 88 | return -ENOENT; | 107 | return -ENOENT; |
| 89 | } | 108 | } |
| @@ -113,6 +132,50 @@ int tb_port_find_cap(struct tb_port *port, enum tb_port_cap cap) · 23 unmodified lines | |||
| 113 | return ret; | 132 | return ret; |
| 114 | } | 133 | } |
| 115 | 134 | ||
| 135 | /** | ||
| 136 | * tb_switch_next_cap() - Return next capability in the linked list | ||
| 137 | * @sw: Switch to find the capability for | ||
| 138 | * @offset: Previous capability offset (%0 for start) | ||
| 139 | * | ||
| 140 | * Finds dword offset of the next capability in router config space | ||
| 141 | * capability list and returns it. Passing %0 returns the first entry in | ||
| 142 | * the capability list. If no next capability is found returns %0. In case | ||
| 143 | * of failure returns negative errno. | ||
| 144 | */ | ||
| 145 | int tb_switch_next_cap(struct tb_switch *sw, unsigned int offset) | ||
| 146 | { | ||
| 147 | struct tb_cap_any header; | ||
| 148 | int ret; | ||
| 149 | |||
| 150 | if (!offset) | ||
| 151 | return sw->config.first_cap_offset; | ||
| 152 | |||
| 153 | ret = tb_sw_read(sw, &header, TB_CFG_SWITCH, offset, 2); | ||
| 154 | if (ret) | ||
| 155 | return ret; | ||
| 156 | |||
| 157 | switch (header.basic.cap) { | ||
| 158 | case TB_SWITCH_CAP_TMU: | ||
| 159 | ret = header.basic.next; | ||
| 160 | break; | ||
| 161 | |||
| 162 | case TB_SWITCH_CAP_VSE: | ||
| 163 | if (!header.extended_short.length) | ||
| 164 | ret = header.extended_long.next; | ||
| 165 | else | ||
| 166 | ret = header.extended_short.next; | ||
| 167 | break; | ||
| 168 | |||
| 169 | default: | ||
| 170 | tb_sw_dbg(sw, "unknown capability %#x at %#x\n", | ||
| 171 | header.basic.cap, offset); | ||
| 172 | ret = -EINVAL; | ||
| 173 | break; | ||
| 174 | } | ||
| 175 | |||
| 176 | return ret >= VSE_CAP_OFFSET_MAX ? 0 : ret; | ||
| 177 | } | ||
| 178 | |||
| 116 | /** | 179 | /** |
| 117 | * tb_switch_find_cap() - Find switch capability | 180 | * tb_switch_find_cap() - Find switch capability |
| 118 | * @sw Switch to find the capability for | 181 | * @sw Switch to find the capability for |
| @@ -124,21 +187,23 @@ int tb_port_find_cap(struct tb_port *port, enum tb_port_cap cap) · 5 unmodified lines | |||
| 124 | */ | 187 | */ |
| 125 | int tb_switch_find_cap(struct tb_switch *sw, enum tb_switch_cap cap) | 188 | int tb_switch_find_cap(struct tb_switch *sw, enum tb_switch_cap cap) |
| 126 | { | 189 | { |
| 127 | int offset = sw->config.first_cap_offset; | 190 | int offset = 0; |
| 128 | 191 | ||
| 129 | while (offset > 0 && offset < CAP_OFFSET_MAX) { | 192 | do { |
| 130 | struct tb_cap_any header; | 193 | struct tb_cap_any header; |
| 131 | int ret; | 194 | int ret; |
| 132 | 195 | ||
| 196 | offset = tb_switch_next_cap(sw, offset); | ||
| 197 | if (offset < 0) | ||
| 198 | return offset; | ||
| 199 | |||
| 133 | ret = tb_sw_read(sw, &header, TB_CFG_SWITCH, offset, 1); | 200 | ret = tb_sw_read(sw, &header, TB_CFG_SWITCH, offset, 1); |
| 134 | if (ret) | 201 | if (ret) |
| 135 | return ret; | 202 | return ret; |
| 136 | 203 | ||
| 137 | if (header.basic.cap == cap) | 204 | if (header.basic.cap == cap) |
| 138 | return offset; | 205 | return offset; |
| 139 | 206 | } while (offset); | |
| 140 | offset = header.basic.next; | ||
| 141 | } | ||
| 142 | 207 | ||
| 143 | return -ENOENT; | 208 | return -ENOENT; |
| 144 | } | 209 | } |
| @@ -155,37 +220,24 @@ int tb_switch_find_cap(struct tb_switch *sw, enum tb_switch_cap cap) · 10 unmodified lines | |||
| 155 | */ | 220 | */ |
| 156 | int tb_switch_find_vse_cap(struct tb_switch *sw, enum tb_switch_vse_cap vsec) | 221 | int tb_switch_find_vse_cap(struct tb_switch *sw, enum tb_switch_vse_cap vsec) |
| 157 | { | 222 | { |
| 158 | struct tb_cap_any header; | 223 | int offset = 0; |
| 159 | int offset; | ||
| 160 | 224 | ||
| 161 | offset = tb_switch_find_cap(sw, TB_SWITCH_CAP_VSE); | 225 | do { |
| 162 | if (offset < 0) | 226 | struct tb_cap_any header; |
| 163 | return offset; | ||
| 164 | |||
| 165 | while (offset > 0 && offset < VSE_CAP_OFFSET_MAX) { | ||
| 166 | int ret; | 227 | int ret; |
| 167 | 228 | ||
| 168 | ret = tb_sw_read(sw, &header, TB_CFG_SWITCH, offset, 2); | 229 | offset = tb_switch_next_cap(sw, offset); |
| 230 | if (offset < 0) | ||
| 231 | return offset; | ||
| 232 | |||
| 233 | ret = tb_sw_read(sw, &header, TB_CFG_SWITCH, offset, 1); | ||
| 169 | if (ret) | 234 | if (ret) |
| 170 | return ret; | 235 | return ret; |
| 171 | 236 | ||
| 172 | /* | 237 | if (header.extended_short.cap == TB_SWITCH_CAP_VSE && |
| 173 | * Extended vendor specific capabilities come in two | 238 | header.extended_short.vsec_id == vsec) |
| 174 | * flavors: short and long. The latter is used when | 239 | return offset; |
| 175 | * offset is over 0xff. | 240 | } while (offset); |
| 176 | */ | ||
| 177 | if (offset >= CAP_OFFSET_MAX) { | ||
| 178 | if (header.extended_long.vsec_id == vsec) | ||
| 179 | return offset; | ||
| 180 | offset = header.extended_long.next; | ||
| 181 | } else { | ||
| 182 | if (header.extended_short.vsec_id == vsec) | ||
| 183 | return offset; | ||
| 184 | if (!header.extended_short.length) | ||
| 185 | return -ENOENT; | ||
| 186 | offset = header.extended_short.next; | ||
| 187 | } | ||
| 188 | } | ||
| 189 | 241 | ||
| 190 | return -ENOENT; | 242 | return -ENOENT; |
| 191 | } | 243 | } |
| @@ -219,6 +219,7 @@ static int check_config_address(struct tb_cfg_address addr, · 218 unmodified lines | |||
| 219 | static struct tb_cfg_result decode_error(const struct ctl_pkg *response) | 219 | static struct tb_cfg_result decode_error(const struct ctl_pkg *response) |
| 220 | { | 220 | { |
| 221 | struct cfg_error_pkg *pkg = response->buffer; | 221 | struct cfg_error_pkg *pkg = response->buffer; |
| 222 | struct tb_ctl *ctl = response->ctl; | ||
| 222 | struct tb_cfg_result res = { 0 }; | 223 | struct tb_cfg_result res = { 0 }; |
| 223 | res.response_route = tb_cfg_get_route(&pkg->header); | 224 | res.response_route = tb_cfg_get_route(&pkg->header); |
| 224 | res.response_port = 0; | 225 | res.response_port = 0; |
| @@ -227,9 +228,13 @@ static struct tb_cfg_result decode_error(const struct ctl_pkg *response) · 2 unmodified lines | |||
| 227 | if (res.err) | 228 | if (res.err) |
| 228 | return res; | 229 | return res; |
| 229 | 230 | ||
| 230 | WARN(pkg->zero1, "pkg->zero1 is %#x\n", pkg->zero1); | 231 | if (pkg->zero1) |
| 231 | WARN(pkg->zero2, "pkg->zero1 is %#x\n", pkg->zero1); | 232 | tb_ctl_warn(ctl, "pkg->zero1 is %#x\n", pkg->zero1); |
| 232 | WARN(pkg->zero3, "pkg->zero1 is %#x\n", pkg->zero1); | 233 | if (pkg->zero2) |
| 234 | tb_ctl_warn(ctl, "pkg->zero2 is %#x\n", pkg->zero2); | ||
| 235 | if (pkg->zero3) | ||
| 236 | tb_ctl_warn(ctl, "pkg->zero3 is %#x\n", pkg->zero3); | ||
| 237 | |||
| 233 | res.err = 1; | 238 | res.err = 1; |
| 234 | res.tb_error = pkg->error; | 239 | res.tb_error = pkg->error; |
| 235 | res.response_port = pkg->port; | 240 | res.response_port = pkg->port; |
| @@ -266,9 +271,8 @@ static void tb_cfg_print_error(struct tb_ctl *ctl, · 30 unmodified lines | |||
| 266 | * Invalid cfg_space/offset/length combination in | 271 | * Invalid cfg_space/offset/length combination in |
| 267 | * cfg_read/cfg_write. | 272 | * cfg_read/cfg_write. |
| 268 | */ | 273 | */ |
| 269 | tb_ctl_WARN(ctl, | 274 | tb_ctl_dbg(ctl, "%llx:%x: invalid config space or offset\n", |
| 270 | "CFG_ERROR(%llx:%x): Invalid config space or offset\n", | 275 | res->response_route, res->response_port); |
| 271 | res->response_route, res->response_port); | ||
| 272 | return; | 276 | return; |
| 273 | case TB_CFG_ERROR_NO_SUCH_PORT: | 277 | case TB_CFG_ERROR_NO_SUCH_PORT: |
| 274 | /* | 278 | /* |
| @@ -283,6 +287,10 @@ static void tb_cfg_print_error(struct tb_ctl *ctl, · 8 unmodified lines | |||
| 283 | tb_ctl_WARN(ctl, "CFG_ERROR(%llx:%x): Route contains a loop\n", | 287 | tb_ctl_WARN(ctl, "CFG_ERROR(%llx:%x): Route contains a loop\n", |
| 284 | res->response_route, res->response_port); | 288 | res->response_route, res->response_port); |
| 285 | return; | 289 | return; |
| 290 | case TB_CFG_ERROR_LOCK: | ||
| 291 | tb_ctl_warn(ctl, "%llx:%x: downstream port is locked\n", | ||
| 292 | res->response_route, res->response_port); | ||
| 293 | return; | ||
| 286 | default: | 294 | default: |
| 287 | /* 5,6,7,9 and 11 are also valid error codes */ | 295 | /* 5,6,7,9 and 11 are also valid error codes */ |
| 288 | tb_ctl_WARN(ctl, "CFG_ERROR(%llx:%x): Unknown error\n", | 296 | tb_ctl_WARN(ctl, "CFG_ERROR(%llx:%x): Unknown error\n", |
| @@ -951,6 +959,9 @@ static int tb_cfg_get_error(struct tb_ctl *ctl, enum tb_cfg_space space, · 662 unmodified lines | |||
| 951 | return -ENODEV; | 959 | return -ENODEV; |
| 952 | 960 | ||
| 953 | tb_cfg_print_error(ctl, res); | 961 | tb_cfg_print_error(ctl, res); |
| 962 | |||
| 963 | if (res->tb_error == TB_CFG_ERROR_LOCK) | ||
| 964 | return -EACCES; | ||
| 954 | return -EIO; | 965 | return -EIO; |
| 955 | } | 966 | } |
| 956 | 967 | ||
| @@ -0,0 +1,701 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Debugfs interface | ||
| 4 | * | ||
| 5 | * Copyright (C) 2020, Intel Corporation | ||
| 6 | * Authors: Gil Fine <gil.fine@intel.com> | ||
| 7 | * Mika Westerberg <mika.westerberg@linux.intel.com> | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/debugfs.h> | ||
| 11 | #include <linux/pm_runtime.h> | ||
| 12 | |||
| 13 | #include "tb.h" | ||
| 14 | |||
| 15 | #define PORT_CAP_PCIE_LEN 1 | ||
| 16 | #define PORT_CAP_POWER_LEN 2 | ||
| 17 | #define PORT_CAP_LANE_LEN 3 | ||
| 18 | #define PORT_CAP_USB3_LEN 5 | ||
| 19 | #define PORT_CAP_DP_LEN 8 | ||
| 20 | #define PORT_CAP_TMU_LEN 8 | ||
| 21 | #define PORT_CAP_BASIC_LEN 9 | ||
| 22 | #define PORT_CAP_USB4_LEN 20 | ||
| 23 | |||
| 24 | #define SWITCH_CAP_TMU_LEN 26 | ||
| 25 | #define SWITCH_CAP_BASIC_LEN 27 | ||
| 26 | |||
| 27 | #define PATH_LEN 2 | ||
| 28 | |||
| 29 | #define COUNTER_SET_LEN 3 | ||
| 30 | |||
| 31 | #define DEBUGFS_ATTR(__space, __write) \ | ||
| 32 | static int __space ## _open(struct inode *inode, struct file *file) \ | ||
| 33 | { \ | ||
| 34 | return single_open(file, __space ## _show, inode->i_private); \ | ||
| 35 | } \ | ||
| 36 | \ | ||
| 37 | static const struct file_operations __space ## _fops = { \ | ||
| 38 | .owner = THIS_MODULE, \ | ||
| 39 | .open = __space ## _open, \ | ||
| 40 | .release = single_release, \ | ||
| 41 | .read = seq_read, \ | ||
| 42 | .write = __write, \ | ||
| 43 | .llseek = seq_lseek, \ | ||
| 44 | } | ||
| 45 | |||
| 46 | #define DEBUGFS_ATTR_RO(__space) \ | ||
| 47 | DEBUGFS_ATTR(__space, NULL) | ||
| 48 | |||
| 49 | #define DEBUGFS_ATTR_RW(__space) \ | ||
| 50 | DEBUGFS_ATTR(__space, __space ## _write) | ||
| 51 | |||
| 52 | static struct dentry *tb_debugfs_root; | ||
| 53 | |||
| 54 | static void *validate_and_copy_from_user(const void __user *user_buf, | ||
| 55 | size_t *count) | ||
| 56 | { | ||
| 57 | size_t nbytes; | ||
| 58 | void *buf; | ||
| 59 | |||
| 60 | if (!*count) | ||
| 61 | return ERR_PTR(-EINVAL); | ||
| 62 | |||
| 63 | if (!access_ok(user_buf, *count)) | ||
| 64 | return ERR_PTR(-EFAULT); | ||
| 65 | |||
| 66 | buf = (void *)get_zeroed_page(GFP_KERNEL); | ||
| 67 | if (!buf) | ||
| 68 | return ERR_PTR(-ENOMEM); | ||
| 69 | |||
| 70 | nbytes = min_t(size_t, *count, PAGE_SIZE); | ||
| 71 | if (copy_from_user(buf, user_buf, nbytes)) { | ||
| 72 | free_page((unsigned long)buf); | ||
| 73 | return ERR_PTR(-EFAULT); | ||
| 74 | } | ||
| 75 | |||
| 76 | *count = nbytes; | ||
| 77 | return buf; | ||
| 78 | } | ||
| 79 | |||
| 80 | static bool parse_line(char **line, u32 *offs, u32 *val, int short_fmt_len, | ||
| 81 | int long_fmt_len) | ||
| 82 | { | ||
| 83 | char *token; | ||
| 84 | u32 v[5]; | ||
| 85 | int ret; | ||
| 86 | |||
| 87 | token = strsep(line, "\n"); | ||
| 88 | if (!token) | ||
| 89 | return false; | ||
| 90 | |||
| 91 | /* | ||
| 92 | * For Adapter/Router configuration space: | ||
| 93 | * Short format is: offset value\n | ||
| 94 | * v[0] v[1] | ||
| 95 | * Long format as produced from the read side: | ||
| 96 | * offset relative_offset cap_id vs_cap_id value\n | ||
| 97 | * v[0] v[1] v[2] v[3] v[4] | ||
| 98 | * | ||
| 99 | * For Counter configuration space: | ||
| 100 | * Short format is: offset\n | ||
| 101 | * v[0] | ||
| 102 | * Long format as produced from the read side: | ||
| 103 | * offset relative_offset counter_id value\n | ||
| 104 | * v[0] v[1] v[2] v[3] | ||
| 105 | */ | ||
| 106 | ret = sscanf(token, "%i %i %i %i %i", &v[0], &v[1], &v[2], &v[3], &v[4]); | ||
| 107 | /* In case of Counters, clear counter, "val" content is NA */ | ||
| 108 | if (ret == short_fmt_len) { | ||
| 109 | *offs = v[0]; | ||
| 110 | *val = v[short_fmt_len - 1]; | ||
| 111 | return true; | ||
| 112 | } else if (ret == long_fmt_len) { | ||
| 113 | *offs = v[0]; | ||
| 114 | *val = v[long_fmt_len - 1]; | ||
| 115 | return true; | ||
| 116 | } | ||
| 117 | |||
| 118 | return false; | ||
| 119 | } | ||
| 120 | |||
| 121 | #if IS_ENABLED(CONFIG_USB4_DEBUGFS_WRITE) | ||
| 122 | static ssize_t regs_write(struct tb_switch *sw, struct tb_port *port, | ||
| 123 | const char __user *user_buf, size_t count, | ||
| 124 | loff_t *ppos) | ||
| 125 | { | ||
| 126 | struct tb *tb = sw->tb; | ||
| 127 | char *line, *buf; | ||
| 128 | u32 val, offset; | ||
| 129 | int ret = 0; | ||
| 130 | |||
| 131 | buf = validate_and_copy_from_user(user_buf, &count); | ||
| 132 | if (IS_ERR(buf)) | ||
| 133 | return PTR_ERR(buf); | ||
| 134 | |||
| 135 | pm_runtime_get_sync(&sw->dev); | ||
| 136 | |||
| 137 | if (mutex_lock_interruptible(&tb->lock)) { | ||
| 138 | ret = -ERESTARTSYS; | ||
| 139 | goto out; | ||
| 140 | } | ||
| 141 | |||
| 142 | /* User did hardware changes behind the driver's back */ | ||
| 143 | add_taint(TAINT_USER, LOCKDEP_STILL_OK); | ||
| 144 | |||
| 145 | line = buf; | ||
| 146 | while (parse_line(&line, &offset, &val, 2, 5)) { | ||
| 147 | if (port) | ||
| 148 | ret = tb_port_write(port, &val, TB_CFG_PORT, offset, 1); | ||
| 149 | else | ||
| 150 | ret = tb_sw_write(sw, &val, TB_CFG_SWITCH, offset, 1); | ||
| 151 | if (ret) | ||
| 152 | break; | ||
| 153 | } | ||
| 154 | |||
| 155 | mutex_unlock(&tb->lock); | ||
| 156 | |||
| 157 | out: | ||
| 158 | pm_runtime_mark_last_busy(&sw->dev); | ||
| 159 | pm_runtime_put_autosuspend(&sw->dev); | ||
| 160 | free_page((unsigned long)buf); | ||
| 161 | |||
| 162 | return ret < 0 ? ret : count; | ||
| 163 | } | ||
| 164 | |||
| 165 | static ssize_t port_regs_write(struct file *file, const char __user *user_buf, | ||
| 166 | size_t count, loff_t *ppos) | ||
| 167 | { | ||
| 168 | struct seq_file *s = file->private_data; | ||
| 169 | struct tb_port *port = s->private; | ||
| 170 | |||
| 171 | return regs_write(port->sw, port, user_buf, count, ppos); | ||
| 172 | } | ||
| 173 | |||
| 174 | static ssize_t switch_regs_write(struct file *file, const char __user *user_buf, | ||
| 175 | size_t count, loff_t *ppos) | ||
| 176 | { | ||
| 177 | struct seq_file *s = file->private_data; | ||
| 178 | struct tb_switch *sw = s->private; | ||
| 179 | |||
| 180 | return regs_write(sw, NULL, user_buf, count, ppos); | ||
| 181 | } | ||
| 182 | #define DEBUGFS_MODE 0600 | ||
| 183 | #else | ||
| 184 | #define port_regs_write NULL | ||
| 185 | #define switch_regs_write NULL | ||
| 186 | #define DEBUGFS_MODE 0400 | ||
| 187 | #endif | ||
| 188 | |||
| 189 | static int port_clear_all_counters(struct tb_port *port) | ||
| 190 | { | ||
| 191 | u32 *buf; | ||
| 192 | int ret; | ||
| 193 | |||
| 194 | buf = kcalloc(COUNTER_SET_LEN * port->config.max_counters, sizeof(u32), | ||
| 195 | GFP_KERNEL); | ||
| 196 | if (!buf) | ||
| 197 | return -ENOMEM; | ||
| 198 | |||
| 199 | ret = tb_port_write(port, buf, TB_CFG_COUNTERS, 0, | ||
| 200 | COUNTER_SET_LEN * port->config.max_counters); | ||
| 201 | kfree(buf); | ||
| 202 | |||
| 203 | return ret; | ||
| 204 | } | ||
| 205 | |||
| 206 | static ssize_t counters_write(struct file *file, const char __user *user_buf, | ||
| 207 | size_t count, loff_t *ppos) | ||
| 208 | { | ||
| 209 | struct seq_file *s = file->private_data; | ||
| 210 | struct tb_port *port = s->private; | ||
| 211 | struct tb_switch *sw = port->sw; | ||
| 212 | struct tb *tb = port->sw->tb; | ||
| 213 | char *buf; | ||
| 214 | int ret; | ||
| 215 | |||
| 216 | buf = validate_and_copy_from_user(user_buf, &count); | ||
| 217 | if (IS_ERR(buf)) | ||
| 218 | return PTR_ERR(buf); | ||
| 219 | |||
| 220 | pm_runtime_get_sync(&sw->dev); | ||
| 221 | |||
| 222 | if (mutex_lock_interruptible(&tb->lock)) { | ||
| 223 | ret = -ERESTARTSYS; | ||
| 224 | goto out; | ||
| 225 | } | ||
| 226 | |||
| 227 | /* If written delimiter only, clear all counters in one shot */ | ||
| 228 | if (buf[0] == '\n') { | ||
| 229 | ret = port_clear_all_counters(port); | ||
| 230 | } else { | ||
| 231 | char *line = buf; | ||
| 232 | u32 val, offset; | ||
| 233 | |||
| 234 | ret = -EINVAL; | ||
| 235 | while (parse_line(&line, &offset, &val, 1, 4)) { | ||
| 236 | ret = tb_port_write(port, &val, TB_CFG_COUNTERS, | ||
| 237 | offset, 1); | ||
| 238 | if (ret) | ||
| 239 | break; | ||
| 240 | } | ||
| 241 | } | ||
| 242 | |||
| 243 | mutex_unlock(&tb->lock); | ||
| 244 | |||
| 245 | out: | ||
| 246 | pm_runtime_mark_last_busy(&sw->dev); | ||
| 247 | pm_runtime_put_autosuspend(&sw->dev); | ||
| 248 | free_page((unsigned long)buf); | ||
| 249 | |||
| 250 | return ret < 0 ? ret : count; | ||
| 251 | } | ||
| 252 | |||
| 253 | static void cap_show(struct seq_file *s, struct tb_switch *sw, | ||
| 254 | struct tb_port *port, unsigned int cap, u8 cap_id, | ||
| 255 | u8 vsec_id, int length) | ||
| 256 | { | ||
| 257 | int ret, offset = 0; | ||
| 258 | |||
| 259 | while (length > 0) { | ||
| 260 | int i, dwords = min(length, TB_MAX_CONFIG_RW_LENGTH); | ||
| 261 | u32 data[TB_MAX_CONFIG_RW_LENGTH]; | ||
| 262 | |||
| 263 | if (port) | ||
| 264 | ret = tb_port_read(port, data, TB_CFG_PORT, cap + offset, | ||
| 265 | dwords); | ||
| 266 | else | ||
| 267 | ret = tb_sw_read(sw, data, TB_CFG_SWITCH, cap + offset, dwords); | ||
| 268 | if (ret) { | ||
| 269 | seq_printf(s, "0x%04x <not accessible>\n", | ||
| 270 | cap + offset); | ||
| 271 | if (dwords > 1) | ||
| 272 | seq_printf(s, "0x%04x ...\n", cap + offset + 1); | ||
| 273 | return; | ||
| 274 | } | ||
| 275 | |||
| 276 | for (i = 0; i < dwords; i++) { | ||
| 277 | seq_printf(s, "0x%04x %4d 0x%02x 0x%02x 0x%08x\n", | ||
| 278 | cap + offset + i, offset + i, | ||
| 279 | cap_id, vsec_id, data[i]); | ||
| 280 | } | ||
| 281 | |||
| 282 | length -= dwords; | ||
| 283 | offset += dwords; | ||
| 284 | } | ||
| 285 | } | ||
| 286 | |||
| 287 | static void port_cap_show(struct tb_port *port, struct seq_file *s, | ||
| 288 | unsigned int cap) | ||
| 289 | { | ||
| 290 | struct tb_cap_any header; | ||
| 291 | u8 vsec_id = 0; | ||
| 292 | size_t length; | ||
| 293 | int ret; | ||
| 294 | |||
| 295 | ret = tb_port_read(port, &header, TB_CFG_PORT, cap, 1); | ||
| 296 | if (ret) { | ||
| 297 | seq_printf(s, "0x%04x <capability read failed>\n", cap); | ||
| 298 | return; | ||
| 299 | } | ||
| 300 | |||
| 301 | switch (header.basic.cap) { | ||
| 302 | case TB_PORT_CAP_PHY: | ||
| 303 | length = PORT_CAP_LANE_LEN; | ||
| 304 | break; | ||
| 305 | |||
| 306 | case TB_PORT_CAP_TIME1: | ||
| 307 | length = PORT_CAP_TMU_LEN; | ||
| 308 | break; | ||
| 309 | |||
| 310 | case TB_PORT_CAP_POWER: | ||
| 311 | length = PORT_CAP_POWER_LEN; | ||
| 312 | break; | ||
| 313 | |||
| 314 | case TB_PORT_CAP_ADAP: | ||
| 315 | if (tb_port_is_pcie_down(port) || tb_port_is_pcie_up(port)) { | ||
| 316 | length = PORT_CAP_PCIE_LEN; | ||
| 317 | } else if (tb_port_is_dpin(port) || tb_port_is_dpout(port)) { | ||
| 318 | length = PORT_CAP_DP_LEN; | ||
| 319 | } else if (tb_port_is_usb3_down(port) || | ||
| 320 | tb_port_is_usb3_up(port)) { | ||
| 321 | length = PORT_CAP_USB3_LEN; | ||
| 322 | } else { | ||
| 323 | seq_printf(s, "0x%04x <unsupported capability 0x%02x>\n", | ||
| 324 | cap, header.basic.cap); | ||
| 325 | return; | ||
| 326 | } | ||
| 327 | break; | ||
| 328 | |||
| 329 | case TB_PORT_CAP_VSE: | ||
| 330 | if (!header.extended_short.length) { | ||
| 331 | ret = tb_port_read(port, (u32 *)&header + 1, TB_CFG_PORT, | ||
| 332 | cap + 1, 1); | ||
| 333 | if (ret) { | ||
| 334 | seq_printf(s, "0x%04x <capability read failed>\n", | ||
| 335 | cap + 1); | ||
| 336 | return; | ||
| 337 | } | ||
| 338 | length = header.extended_long.length; | ||
| 339 | vsec_id = header.extended_short.vsec_id; | ||
| 340 | } else { | ||
| 341 | length = header.extended_short.length; | ||
| 342 | vsec_id = header.extended_short.vsec_id; | ||
| 343 | /* | ||
| 344 | * Ice Lake and Tiger Lake do not implement the | ||
| 345 | * full length of the capability, only first 32 | ||
| 346 | * dwords so hard-code it here. | ||
| 347 | */ | ||
| 348 | if (!vsec_id && | ||
| 349 | (tb_switch_is_ice_lake(port->sw) || | ||
| 350 | tb_switch_is_tiger_lake(port->sw))) | ||
| 351 | length = 32; | ||
| 352 | } | ||
| 353 | break; | ||
| 354 | |||
| 355 | case TB_PORT_CAP_USB4: | ||
| 356 | length = PORT_CAP_USB4_LEN; | ||
| 357 | break; | ||
| 358 | |||
| 359 | default: | ||
| 360 | seq_printf(s, "0x%04x <unsupported capability 0x%02x>\n", | ||
| 361 | cap, header.basic.cap); | ||
| 362 | return; | ||
| 363 | } | ||
| 364 | |||
| 365 | cap_show(s, NULL, port, cap, header.basic.cap, vsec_id, length); | ||
| 366 | } | ||
| 367 | |||
| 368 | static void port_caps_show(struct tb_port *port, struct seq_file *s) | ||
| 369 | { | ||
| 370 | int cap; | ||
| 371 | |||
| 372 | cap = tb_port_next_cap(port, 0); | ||
| 373 | while (cap > 0) { | ||
| 374 | port_cap_show(port, s, cap); | ||
| 375 | cap = tb_port_next_cap(port, cap); | ||
| 376 | } | ||
| 377 | } | ||
| 378 | |||
| 379 | static int port_basic_regs_show(struct tb_port *port, struct seq_file *s) | ||
| 380 | { | ||
| 381 | u32 data[PORT_CAP_BASIC_LEN]; | ||
| 382 | int ret, i; | ||
| 383 | |||
| 384 | ret = tb_port_read(port, data, TB_CFG_PORT, 0, ARRAY_SIZE(data)); | ||
| 385 | if (ret) | ||
| 386 | return ret; | ||
| 387 | |||
| 388 | for (i = 0; i < ARRAY_SIZE(data); i++) | ||
| 389 | seq_printf(s, "0x%04x %4d 0x00 0x00 0x%08x\n", i, i, data[i]); | ||
| 390 | |||
| 391 | return 0; | ||
| 392 | } | ||
| 393 | |||
| 394 | static int port_regs_show(struct seq_file *s, void *not_used) | ||
| 395 | { | ||
| 396 | struct tb_port *port = s->private; | ||
| 397 | struct tb_switch *sw = port->sw; | ||
| 398 | struct tb *tb = sw->tb; | ||
| 399 | int ret; | ||
| 400 | |||
| 401 | pm_runtime_get_sync(&sw->dev); | ||
| 402 | |||
| 403 | if (mutex_lock_interruptible(&tb->lock)) { | ||
| 404 | ret = -ERESTARTSYS; | ||
| 405 | goto out_rpm_put; | ||
| 406 | } | ||
| 407 | |||
| 408 | seq_puts(s, "# offset relative_offset cap_id vs_cap_id value\n"); | ||
| 409 | |||
| 410 | ret = port_basic_regs_show(port, s); | ||
| 411 | if (ret) | ||
| 412 | goto out_unlock; | ||
| 413 | |||
| 414 | port_caps_show(port, s); | ||
| 415 | |||
| 416 | out_unlock: | ||
| 417 | mutex_unlock(&tb->lock); | ||
| 418 | out_rpm_put: | ||
| 419 | pm_runtime_mark_last_busy(&sw->dev); | ||
| 420 | pm_runtime_put_autosuspend(&sw->dev); | ||
| 421 | |||
| 422 | return ret; | ||
| 423 | } | ||
| 424 | DEBUGFS_ATTR_RW(port_regs); | ||
| 425 | |||
| 426 | static void switch_cap_show(struct tb_switch *sw, struct seq_file *s, | ||
| 427 | unsigned int cap) | ||
| 428 | { | ||
| 429 | struct tb_cap_any header; | ||
| 430 | int ret, length; | ||
| 431 | u8 vsec_id = 0; | ||
| 432 | |||
| 433 | ret = tb_sw_read(sw, &header, TB_CFG_SWITCH, cap, 1); | ||
| 434 | if (ret) { | ||
| 435 | seq_printf(s, "0x%04x <capability read failed>\n", cap); | ||
| 436 | return; | ||
| 437 | } | ||
| 438 | |||
| 439 | if (header.basic.cap == TB_SWITCH_CAP_VSE) { | ||
| 440 | if (!header.extended_short.length) { | ||
| 441 | ret = tb_sw_read(sw, (u32 *)&header + 1, TB_CFG_SWITCH, | ||
| 442 | cap + 1, 1); | ||
| 443 | if (ret) { | ||
| 444 | seq_printf(s, "0x%04x <capability read failed>\n", | ||
| 445 | cap + 1); | ||
| 446 | return; | ||
| 447 | } | ||
| 448 | length = header.extended_long.length; | ||
| 449 | } else { | ||
| 450 | length = header.extended_short.length; | ||
| 451 | } | ||
| 452 | vsec_id = header.extended_short.vsec_id; | ||
| 453 | } else { | ||
| 454 | if (header.basic.cap == TB_SWITCH_CAP_TMU) { | ||
| 455 | length = SWITCH_CAP_TMU_LEN; | ||
| 456 | } else { | ||
| 457 | seq_printf(s, "0x%04x <unknown capability 0x%02x>\n", | ||
| 458 | cap, header.basic.cap); | ||
| 459 | return; | ||
| 460 | } | ||
| 461 | } | ||
| 462 | |||
| 463 | cap_show(s, sw, NULL, cap, header.basic.cap, vsec_id, length); | ||
| 464 | } | ||
| 465 | |||
| 466 | static void switch_caps_show(struct tb_switch *sw, struct seq_file *s) | ||
| 467 | { | ||
| 468 | int cap; | ||
| 469 | |||
| 470 | cap = tb_switch_next_cap(sw, 0); | ||
| 471 | while (cap > 0) { | ||
| 472 | switch_cap_show(sw, s, cap); | ||
| 473 | cap = tb_switch_next_cap(sw, cap); | ||
| 474 | } | ||
| 475 | } | ||
| 476 | |||
| 477 | static int switch_basic_regs_show(struct tb_switch *sw, struct seq_file *s) | ||
| 478 | { | ||
| 479 | u32 data[SWITCH_CAP_BASIC_LEN]; | ||
| 480 | size_t dwords; | ||
| 481 | int ret, i; | ||
| 482 | |||
| 483 | /* Only USB4 has the additional registers */ | ||
| 484 | if (tb_switch_is_usb4(sw)) | ||
| 485 | dwords = ARRAY_SIZE(data); | ||
| 486 | else | ||
| 487 | dwords = 7; | ||
| 488 | |||
| 489 | ret = tb_sw_read(sw, data, TB_CFG_SWITCH, 0, dwords); | ||
| 490 | if (ret) | ||
| 491 | return ret; | ||
| 492 | |||
| 493 | for (i = 0; i < dwords; i++) | ||
| 494 | seq_printf(s, "0x%04x %4d 0x00 0x00 0x%08x\n", i, i, data[i]); | ||
| 495 | |||
| 496 | return 0; | ||
| 497 | } | ||
| 498 | |||
| 499 | static int switch_regs_show(struct seq_file *s, void *not_used) | ||
| 500 | { | ||
| 501 | struct tb_switch *sw = s->private; | ||
| 502 | struct tb *tb = sw->tb; | ||
| 503 | int ret; | ||
| 504 | |||
| 505 | pm_runtime_get_sync(&sw->dev); | ||
| 506 | |||
| 507 | if (mutex_lock_interruptible(&tb->lock)) { | ||
| 508 | ret = -ERESTARTSYS; | ||
| 509 | goto out_rpm_put; | ||
| 510 | } | ||
| 511 | |||
| 512 | seq_puts(s, "# offset relative_offset cap_id vs_cap_id value\n"); | ||
| 513 | |||
| 514 | ret = switch_basic_regs_show(sw, s); | ||
| 515 | if (ret) | ||
| 516 | goto out_unlock; | ||
| 517 | |||
| 518 | switch_caps_show(sw, s); | ||
| 519 | |||
| 520 | out_unlock: | ||
| 521 | mutex_unlock(&tb->lock); | ||
| 522 | out_rpm_put: | ||
| 523 | pm_runtime_mark_last_busy(&sw->dev); | ||
| 524 | pm_runtime_put_autosuspend(&sw->dev); | ||
| 525 | |||
| 526 | return ret; | ||
| 527 | } | ||
| 528 | DEBUGFS_ATTR_RW(switch_regs); | ||
| 529 | |||
| 530 | static int path_show_one(struct tb_port *port, struct seq_file *s, int hopid) | ||
| 531 | { | ||
| 532 | u32 data[PATH_LEN]; | ||
| 533 | int ret, i; | ||
| 534 | |||
| 535 | ret = tb_port_read(port, data, TB_CFG_HOPS, hopid * PATH_LEN, | ||
| 536 | ARRAY_SIZE(data)); | ||
| 537 | if (ret) { | ||
| 538 | seq_printf(s, "0x%04x <not accessible>\n", hopid * PATH_LEN); | ||
| 539 | return ret; | ||
| 540 | } | ||
| 541 | |||
| 542 | for (i = 0; i < ARRAY_SIZE(data); i++) { | ||
| 543 | seq_printf(s, "0x%04x %4d 0x%02x 0x%08x\n", | ||
| 544 | hopid * PATH_LEN + i, i, hopid, data[i]); | ||
| 545 | } | ||
| 546 | |||
| 547 | return 0; | ||
| 548 | } | ||
| 549 | |||
| 550 | static int path_show(struct seq_file *s, void *not_used) | ||
| 551 | { | ||
| 552 | struct tb_port *port = s->private; | ||
| 553 | struct tb_switch *sw = port->sw; | ||
| 554 | struct tb *tb = sw->tb; | ||
| 555 | int start, i, ret = 0; | ||
| 556 | |||
| 557 | pm_runtime_get_sync(&sw->dev); | ||
| 558 | |||
| 559 | if (mutex_lock_interruptible(&tb->lock)) { | ||
| 560 | ret = -ERESTARTSYS; | ||
| 561 | goto out_rpm_put; | ||
| 562 | } | ||
| 563 | |||
| 564 | seq_puts(s, "# offset relative_offset in_hop_id value\n"); | ||
| 565 | |||
| 566 | /* NHI and lane adapters have entry for path 0 */ | ||
| 567 | if (tb_port_is_null(port) || tb_port_is_nhi(port)) { | ||
| 568 | ret = path_show_one(port, s, 0); | ||
| 569 | if (ret) | ||
| 570 | goto out_unlock; | ||
| 571 | } | ||
| 572 | |||
| 573 | start = tb_port_is_nhi(port) ? 1 : TB_PATH_MIN_HOPID; | ||
| 574 | |||
| 575 | for (i = start; i <= port->config.max_in_hop_id; i++) { | ||
| 576 | ret = path_show_one(port, s, i); | ||
| 577 | if (ret) | ||
| 578 | break; | ||
| 579 | } | ||
| 580 | |||
| 581 | out_unlock: | ||
| 582 | mutex_unlock(&tb->lock); | ||
| 583 | out_rpm_put: | ||
| 584 | pm_runtime_mark_last_busy(&sw->dev); | ||
| 585 | pm_runtime_put_autosuspend(&sw->dev); | ||
| 586 | |||
| 587 | return ret; | ||
| 588 | } | ||
| 589 | DEBUGFS_ATTR_RO(path); | ||
| 590 | |||
| 591 | static int counter_set_regs_show(struct tb_port *port, struct seq_file *s, | ||
| 592 | int counter) | ||
| 593 | { | ||
| 594 | u32 data[COUNTER_SET_LEN]; | ||
| 595 | int ret, i; | ||
| 596 | |||
| 597 | ret = tb_port_read(port, data, TB_CFG_COUNTERS, | ||
| 598 | counter * COUNTER_SET_LEN, ARRAY_SIZE(data)); | ||
| 599 | if (ret) { | ||
| 600 | seq_printf(s, "0x%04x <not accessible>\n", | ||
| 601 | counter * COUNTER_SET_LEN); | ||
| 602 | return ret; | ||
| 603 | } | ||
| 604 | |||
| 605 | for (i = 0; i < ARRAY_SIZE(data); i++) { | ||
| 606 | seq_printf(s, "0x%04x %4d 0x%02x 0x%08x\n", | ||
| 607 | counter * COUNTER_SET_LEN + i, i, counter, data[i]); | ||
| 608 | } | ||
| 609 | |||
| 610 | return 0; | ||
| 611 | } | ||
| 612 | |||
| 613 | static int counters_show(struct seq_file *s, void *not_used) | ||
| 614 | { | ||
| 615 | struct tb_port *port = s->private; | ||
| 616 | struct tb_switch *sw = port->sw; | ||
| 617 | struct tb *tb = sw->tb; | ||
| 618 | int i, ret = 0; | ||
| 619 | |||
| 620 | pm_runtime_get_sync(&sw->dev); | ||
| 621 | |||
| 622 | if (mutex_lock_interruptible(&tb->lock)) { | ||
| 623 | ret = -ERESTARTSYS; | ||
| 624 | goto out; | ||
| 625 | } | ||
| 626 | |||
| 627 | seq_puts(s, "# offset relative_offset counter_id value\n"); | ||
| 628 | |||
| 629 | for (i = 0; i < port->config.max_counters; i++) { | ||
| 630 | ret = counter_set_regs_show(port, s, i); | ||
| 631 | if (ret) | ||
| 632 | break; | ||
| 633 | } | ||
| 634 | |||
| 635 | mutex_unlock(&tb->lock); | ||
| 636 | |||
| 637 | out: | ||
| 638 | pm_runtime_mark_last_busy(&sw->dev); | ||
| 639 | pm_runtime_put_autosuspend(&sw->dev); | ||
| 640 | |||
| 641 | return ret; | ||
| 642 | } | ||
| 643 | DEBUGFS_ATTR_RW(counters); | ||
| 644 | |||
| 645 | /** | ||
| 646 | * tb_switch_debugfs_init() - Add debugfs entries for router | ||
| 647 | * @sw: Pointer to the router | ||
| 648 | * | ||
| 649 | * Adds debugfs directories and files for given router. | ||
| 650 | */ | ||
| 651 | void tb_switch_debugfs_init(struct tb_switch *sw) | ||
| 652 | { | ||
| 653 | struct dentry *debugfs_dir; | ||
| 654 | struct tb_port *port; | ||
| 655 | |||
| 656 | debugfs_dir = debugfs_create_dir(dev_name(&sw->dev), tb_debugfs_root); | ||
| 657 | sw->debugfs_dir = debugfs_dir; | ||
| 658 | debugfs_create_file("regs", DEBUGFS_MODE, debugfs_dir, sw, | ||
| 659 | &switch_regs_fops); | ||
| 660 | |||
| 661 | tb_switch_for_each_port(sw, port) { | ||
| 662 | struct dentry *debugfs_dir; | ||
| 663 | char dir_name[10]; | ||
| 664 | |||
| 665 | if (port->disabled) | ||
| 666 | continue; | ||
| 667 | if (port->config.type == TB_TYPE_INACTIVE) | ||
| 668 | continue; | ||
| 669 | |||
| 670 | snprintf(dir_name, sizeof(dir_name), "port%d", port->port); | ||
| 671 | debugfs_dir = debugfs_create_dir(dir_name, sw->debugfs_dir); | ||
| 672 | debugfs_create_file("regs", DEBUGFS_MODE, debugfs_dir, | ||
| 673 | port, &port_regs_fops); | ||
| 674 | debugfs_create_file("path", 0400, debugfs_dir, port, | ||
| 675 | &path_fops); | ||
| 676 | if (port->config.counters_support) | ||
| 677 | debugfs_create_file("counters", 0600, debugfs_dir, port, | ||
| 678 | &counters_fops); | ||
| 679 | } | ||
| 680 | } | ||
| 681 | |||
| 682 | /** | ||
| 683 | * tb_switch_debugfs_remove() - Remove all router debugfs entries | ||
| 684 | * @sw: Pointer to the router | ||
| 685 | * | ||
| 686 | * Removes all previously added debugfs entries under this router. | ||
| 687 | */ | ||
| 688 | void tb_switch_debugfs_remove(struct tb_switch *sw) | ||
| 689 | { | ||
| 690 | debugfs_remove_recursive(sw->debugfs_dir); | ||
| 691 | } | ||
| 692 | |||
| 693 | void tb_debugfs_init(void) | ||
| 694 | { | ||
| 695 | tb_debugfs_root = debugfs_create_dir("thunderbolt", NULL); | ||
| 696 | } | ||
| 697 | |||
| 698 | void tb_debugfs_exit(void) | ||
| 699 | { | ||
| 700 | debugfs_remove_recursive(tb_debugfs_root); | ||
| 701 | } | ||
| @@ -275,7 +275,7 @@ static struct attribute *domain_attrs[] = { · 274 unmodified lines | |||
| 275 | static umode_t domain_attr_is_visible(struct kobject *kobj, | 275 | static umode_t domain_attr_is_visible(struct kobject *kobj, |
| 276 | struct attribute *attr, int n) | 276 | struct attribute *attr, int n) |
| 277 | { | 277 | { |
| 278 | struct device *dev = container_of(kobj, struct device, kobj); | 278 | struct device *dev = kobj_to_dev(kobj); |
| 279 | struct tb *tb = container_of(dev, struct tb, dev); | 279 | struct tb *tb = container_of(dev, struct tb, dev); |
| 280 | 280 | ||
| 281 | if (attr == &dev_attr_boot_acl.attr) { | 281 | if (attr == &dev_attr_boot_acl.attr) { |
| @@ -455,6 +455,8 @@ int tb_domain_add(struct tb *tb) · 173 unmodified lines | |||
| 455 | /* This starts event processing */ | 455 | /* This starts event processing */ |
| 456 | mutex_unlock(&tb->lock); | 456 | mutex_unlock(&tb->lock); |
| 457 | 457 | ||
| 458 | device_init_wakeup(&tb->dev, true); | ||
| 459 | |||
| 458 | pm_runtime_no_callbacks(&tb->dev); | 460 | pm_runtime_no_callbacks(&tb->dev); |
| 459 | pm_runtime_set_active(&tb->dev); | 461 | pm_runtime_set_active(&tb->dev); |
| 460 | pm_runtime_enable(&tb->dev); | 462 | pm_runtime_enable(&tb->dev); |
| @@ -544,6 +546,33 @@ int tb_domain_suspend(struct tb *tb) · 83 unmodified lines | |||
| 544 | return tb->cm_ops->suspend ? tb->cm_ops->suspend(tb) : 0; | 546 | return tb->cm_ops->suspend ? tb->cm_ops->suspend(tb) : 0; |
| 545 | } | 547 | } |
| 546 | 548 | ||
| 549 | int tb_domain_freeze_noirq(struct tb *tb) | ||
| 550 | { | ||
| 551 | int ret = 0; | ||
| 552 | |||
| 553 | mutex_lock(&tb->lock); | ||
| 554 | if (tb->cm_ops->freeze_noirq) | ||
| 555 | ret = tb->cm_ops->freeze_noirq(tb); | ||
| 556 | if (!ret) | ||
| 557 | tb_ctl_stop(tb->ctl); | ||
| 558 | mutex_unlock(&tb->lock); | ||
| 559 | |||
| 560 | return ret; | ||
| 561 | } | ||
| 562 | |||
| 563 | int tb_domain_thaw_noirq(struct tb *tb) | ||
| 564 | { | ||
| 565 | int ret = 0; | ||
| 566 | |||
| 567 | mutex_lock(&tb->lock); | ||
| 568 | tb_ctl_start(tb->ctl); | ||
| 569 | if (tb->cm_ops->thaw_noirq) | ||
| 570 | ret = tb->cm_ops->thaw_noirq(tb); | ||
| 571 | mutex_unlock(&tb->lock); | ||
| 572 | |||
| 573 | return ret; | ||
| 574 | } | ||
| 575 | |||
| 547 | void tb_domain_complete(struct tb *tb) | 576 | void tb_domain_complete(struct tb *tb) |
| 548 | { | 577 | { |
| 549 | if (tb->cm_ops->complete) | 578 | if (tb->cm_ops->complete) |
| @@ -798,12 +827,23 @@ int tb_domain_init(void) · 248 unmodified lines | |||
| 798 | { | 827 | { |
| 799 | int ret; | 828 | int ret; |
| 800 | 829 | ||
| 830 | tb_test_init(); | ||
| 831 | |||
| 832 | tb_debugfs_init(); | ||
| 801 | ret = tb_xdomain_init(); | 833 | ret = tb_xdomain_init(); |
| 802 | if (ret) | 834 | if (ret) |
| 803 | return ret; | 835 | goto err_debugfs; |
| 804 | ret = bus_register(&tb_bus_type); | 836 | ret = bus_register(&tb_bus_type); |
| 805 | if (ret) | 837 | if (ret) |
| 806 | tb_xdomain_exit(); | 838 | goto err_xdomain; |
| 839 | |||
| 840 | return 0; | ||
| 841 | |||
| 842 | err_xdomain: | ||
| 843 | tb_xdomain_exit(); | ||
| 844 | err_debugfs: | ||
| 845 | tb_debugfs_exit(); | ||
| 846 | tb_test_exit(); | ||
| 807 | 847 | ||
| 808 | return ret; | 848 | return ret; |
| 809 | } | 849 | } |
| @@ -814,4 +854,6 @@ void tb_domain_exit(void) · 4 unmodified lines | |||
| 814 | ida_destroy(&tb_domain_ida); | 854 | ida_destroy(&tb_domain_ida); |
| 815 | tb_nvm_exit(); | 855 | tb_nvm_exit(); |
| 816 | tb_xdomain_exit(); | 856 | tb_xdomain_exit(); |
| 857 | tb_debugfs_exit(); | ||
| 858 | tb_test_exit(); | ||
| 817 | } | 859 | } |
| @@ -1635,11 +1635,14 @@ static void icm_icl_rtd3_veto(struct tb *tb, const struct icm_pkg_header *hdr) · 1634 unmodified lines | |||
| 1635 | 1635 | ||
| 1636 | static bool icm_tgl_is_supported(struct tb *tb) | 1636 | static bool icm_tgl_is_supported(struct tb *tb) |
| 1637 | { | 1637 | { |
| 1638 | u32 val; | ||
| 1639 | |||
| 1638 | /* | 1640 | /* |
| 1639 | * If the firmware is not running use software CM. This platform | 1641 | * If the firmware is not running use software CM. This platform |
| 1640 | * should fully support both. | 1642 | * should fully support both. |
| 1641 | */ | 1643 | */ |
| 1642 | return icm_firmware_running(tb->nhi); | 1644 | val = ioread32(tb->nhi->iobase + REG_FW_STS); |
| 1645 | return !!(val & REG_FW_STS_NVM_AUTH_DONE); | ||
| 1643 | } | 1646 | } |
| 1644 | 1647 | ||
| 1645 | static void icm_handle_notification(struct work_struct *work) | 1648 | static void icm_handle_notification(struct work_struct *work) |
| @@ -45,7 +45,7 @@ static int find_port_lc_cap(struct tb_port *port) · 44 unmodified lines | |||
| 45 | return sw->cap_lc + start + phys * size; | 45 | return sw->cap_lc + start + phys * size; |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | static int tb_lc_configure_lane(struct tb_port *port, bool configure) | 48 | static int tb_lc_set_port_configured(struct tb_port *port, bool configured) |
| 49 | { | 49 | { |
| 50 | bool upstream = tb_is_upstream_port(port); | 50 | bool upstream = tb_is_upstream_port(port); |
| 51 | struct tb_switch *sw = port->sw; | 51 | struct tb_switch *sw = port->sw; |
| @@ -69,7 +69,7 @@ static int tb_lc_configure_lane(struct tb_port *port, bool configure) · 17 unmodified lines | |||
| 69 | else | 69 | else |
| 70 | lane = TB_LC_SX_CTRL_L2C; | 70 | lane = TB_LC_SX_CTRL_L2C; |
| 71 | 71 | ||
| 72 | if (configure) { | 72 | if (configured) { |
| 73 | ctrl |= lane; | 73 | ctrl |= lane; |
| 74 | if (upstream) | 74 | if (upstream) |
| 75 | ctrl |= TB_LC_SX_CTRL_UPSTREAM; | 75 | ctrl |= TB_LC_SX_CTRL_UPSTREAM; |
| @@ -83,55 +83,146 @@ static int tb_lc_configure_lane(struct tb_port *port, bool configure) · 7 unmodified lines | |||
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | /** | 85 | /** |
| 86 | * tb_lc_configure_link() - Let LC know about configured link | 86 | * tb_lc_configure_port() - Let LC know about configured port |
| 87 | * @sw: Switch that is being added | 87 | * @port: Port that is set as configured |
| 88 | * | 88 | * |
| 89 | * Informs LC of both parent switch and @sw that there is established | 89 | * Sets the port configured for power management purposes. |
| 90 | * link between the two. | ||
| 91 | */ | 90 | */ |
| 92 | int tb_lc_configure_link(struct tb_switch *sw) | 91 | int tb_lc_configure_port(struct tb_port *port) |
| 93 | { | 92 | { |
| 94 | struct tb_port *up, *down; | 93 | return tb_lc_set_port_configured(port, true); |
| 95 | int ret; | 94 | } |
| 95 | |||
| 96 | /** | ||
| 97 | * tb_lc_unconfigure_port() - Let LC know about unconfigured port | ||
| 98 | * @port: Port that is set as configured | ||
| 99 | * | ||
| 100 | * Sets the port unconfigured for power management purposes. | ||
| 101 | */ | ||
| 102 | void tb_lc_unconfigure_port(struct tb_port *port) | ||
| 103 | { | ||
| 104 | tb_lc_set_port_configured(port, false); | ||
| 105 | } | ||
| 96 | 106 | ||
| 97 | if (!tb_route(sw) || tb_switch_is_icm(sw)) | 107 | static int tb_lc_set_xdomain_configured(struct tb_port *port, bool configure) |
| 108 | { | ||
| 109 | struct tb_switch *sw = port->sw; | ||
| 110 | u32 ctrl, lane; | ||
| 111 | int cap, ret; | ||
| 112 | |||
| 113 | if (sw->generation < 2) | ||
| 98 | return 0; | 114 | return 0; |
| 99 | 115 | ||
| 100 | up = tb_upstream_port(sw); | 116 | cap = find_port_lc_cap(port); |
| 101 | down = tb_port_at(tb_route(sw), tb_to_switch(sw->dev.parent)); | 117 | if (cap < 0) |
| 118 | return cap; | ||
| 102 | 119 | ||
| 103 | /* Configure parent link toward this switch */ | 120 | ret = tb_sw_read(sw, &ctrl, TB_CFG_SWITCH, cap + TB_LC_SX_CTRL, 1); |
| 104 | ret = tb_lc_configure_lane(down, true); | ||
| 105 | if (ret) | 121 | if (ret) |
| 106 | return ret; | 122 | return ret; |
| 107 | 123 | ||
| 108 | /* Configure upstream link from this switch to the parent */ | 124 | /* Resolve correct lane */ |
| 109 | ret = tb_lc_configure_lane(up, true); | 125 | if (port->port % 2) |
| 126 | lane = TB_LC_SX_CTRL_L1D; | ||
| 127 | else | ||
| 128 | lane = TB_LC_SX_CTRL_L2D; | ||
| 129 | |||
| 130 | if (configure) | ||
| 131 | ctrl |= lane; | ||
| 132 | else | ||
| 133 | ctrl &= ~lane; | ||
| 134 | |||
| 135 | return tb_sw_write(sw, &ctrl, TB_CFG_SWITCH, cap + TB_LC_SX_CTRL, 1); | ||
| 136 | } | ||
| 137 | |||
| 138 | /** | ||
| 139 | * tb_lc_configure_xdomain() - Inform LC that the link is XDomain | ||
| 140 | * @port: Switch downstream port connected to another host | ||
| 141 | * | ||
| 142 | * Sets the lane configured for XDomain accordingly so that the LC knows | ||
| 143 | * about this. Returns %0 in success and negative errno in failure. | ||
| 144 | */ | ||
| 145 | int tb_lc_configure_xdomain(struct tb_port *port) | ||
| 146 | { | ||
| 147 | return tb_lc_set_xdomain_configured(port, true); | ||
| 148 | } | ||
| 149 | |||
| 150 | /** | ||
| 151 | * tb_lc_unconfigure_xdomain() - Unconfigure XDomain from port | ||
| 152 | * @port: Switch downstream port that was connected to another host | ||
| 153 | * | ||
| 154 | * Unsets the lane XDomain configuration. | ||
| 155 | */ | ||
| 156 | void tb_lc_unconfigure_xdomain(struct tb_port *port) | ||
| 157 | { | ||
| 158 | tb_lc_set_xdomain_configured(port, false); | ||
| 159 | } | ||
| 160 | |||
| 161 | static int tb_lc_set_wake_one(struct tb_switch *sw, unsigned int offset, | ||
| 162 | unsigned int flags) | ||
| 163 | { | ||
| 164 | u32 ctrl; | ||
| 165 | int ret; | ||
| 166 | |||
| 167 | /* | ||
| 168 | * Enable wake on PCIe and USB4 (wake coming from another | ||
| 169 | * router). | ||
| 170 | */ | ||
| 171 | ret = tb_sw_read(sw, &ctrl, TB_CFG_SWITCH, | ||
| 172 | offset + TB_LC_SX_CTRL, 1); | ||
| 110 | if (ret) | 173 | if (ret) |
| 111 | tb_lc_configure_lane(down, false); | 174 | return ret; |
| 175 | |||
| 176 | ctrl &= ~(TB_LC_SX_CTRL_WOC | TB_LC_SX_CTRL_WOD | TB_LC_SX_CTRL_WOP | | ||
| 177 | TB_LC_SX_CTRL_WOU4); | ||
| 178 | |||
| 179 | if (flags & TB_WAKE_ON_CONNECT) | ||
| 180 | ctrl |= TB_LC_SX_CTRL_WOC | TB_LC_SX_CTRL_WOD; | ||
| 181 | if (flags & TB_WAKE_ON_USB4) | ||
| 182 | ctrl |= TB_LC_SX_CTRL_WOU4; | ||
| 183 | if (flags & TB_WAKE_ON_PCIE) | ||
| 184 | ctrl |= TB_LC_SX_CTRL_WOP; | ||
| 112 | 185 | ||
| 113 | return ret; | 186 | return tb_sw_write(sw, &ctrl, TB_CFG_SWITCH, offset + TB_LC_SX_CTRL, 1); |
| 114 | } | 187 | } |
| 115 | 188 | ||
| 116 | /** | 189 | /** |
| 117 | * tb_lc_unconfigure_link() - Let LC know about unconfigured link | 190 | * tb_lc_set_wake() - Enable/disable wake |
| 118 | * @sw: Switch to unconfigure | 191 | * @sw: Switch whose wakes to configure |
| 192 | * @flags: Wakeup flags (%0 to disable) | ||
| 119 | * | 193 | * |
| 120 | * Informs LC of both parent switch and @sw that the link between the | 194 | * For each LC sets wake bits accordingly. |
| 121 | * two does not exist anymore. | ||
| 122 | */ | 195 | */ |
| 123 | void tb_lc_unconfigure_link(struct tb_switch *sw) | 196 | int tb_lc_set_wake(struct tb_switch *sw, unsigned int flags) |
| 124 | { | 197 | { |
| 125 | struct tb_port *up, *down; | 198 | int start, size, nlc, ret, i; |
| 199 | u32 desc; | ||
| 126 | 200 | ||
| 127 | if (sw->is_unplugged || !tb_route(sw) || tb_switch_is_icm(sw)) | 201 | if (sw->generation < 2) |
| 128 | return; | 202 | return 0; |
| 129 | 203 | ||
| 130 | up = tb_upstream_port(sw); | 204 | if (!tb_route(sw)) |
| 131 | down = tb_port_at(tb_route(sw), tb_to_switch(sw->dev.parent)); | 205 | return 0; |
| 132 | 206 | ||
| 133 | tb_lc_configure_lane(up, false); | 207 | ret = read_lc_desc(sw, &desc); |
| 134 | tb_lc_configure_lane(down, false); | 208 | if (ret) |
| 209 | return ret; | ||
| 210 | |||
| 211 | /* Figure out number of link controllers */ | ||
| 212 | nlc = desc & TB_LC_DESC_NLC_MASK; | ||
| 213 | start = (desc & TB_LC_DESC_SIZE_MASK) >> TB_LC_DESC_SIZE_SHIFT; | ||
| 214 | size = (desc & TB_LC_DESC_PORT_SIZE_MASK) >> TB_LC_DESC_PORT_SIZE_SHIFT; | ||
| 215 | |||
| 216 | /* For each link controller set sleep bit */ | ||
| 217 | for (i = 0; i < nlc; i++) { | ||
| 218 | unsigned int offset = sw->cap_lc + start + i * size; | ||
| 219 | |||
| 220 | ret = tb_lc_set_wake_one(sw, offset, flags); | ||
| 221 | if (ret) | ||
| 222 | return ret; | ||
| 223 | } | ||
| 224 | |||
| 225 | return 0; | ||
| 135 | } | 226 | } |
| 136 | 227 | ||
| 137 | /** | 228 | /** |
| @@ -17,6 +17,7 @@ · 16 unmodified lines | |||
| 17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
| 18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
| 19 | #include <linux/property.h> | 19 | #include <linux/property.h> |
| 20 | #include <linux/platform_data/x86/apple.h> | ||
| 20 | 21 | ||
| 21 | #include "nhi.h" | 22 | #include "nhi.h" |
| 22 | #include "nhi_regs.h" | 23 | #include "nhi_regs.h" |
| @@ -863,6 +864,22 @@ static int nhi_suspend_noirq(struct device *dev) · 840 unmodified lines | |||
| 863 | return __nhi_suspend_noirq(dev, device_may_wakeup(dev)); | 864 | return __nhi_suspend_noirq(dev, device_may_wakeup(dev)); |
| 864 | } | 865 | } |
| 865 | 866 | ||
| 867 | static int nhi_freeze_noirq(struct device *dev) | ||
| 868 | { | ||
| 869 | struct pci_dev *pdev = to_pci_dev(dev); | ||
| 870 | struct tb *tb = pci_get_drvdata(pdev); | ||
| 871 | |||
| 872 | return tb_domain_freeze_noirq(tb); | ||
| 873 | } | ||
| 874 | |||
| 875 | static int nhi_thaw_noirq(struct device *dev) | ||
| 876 | { | ||
| 877 | struct pci_dev *pdev = to_pci_dev(dev); | ||
| 878 | struct tb *tb = pci_get_drvdata(pdev); | ||
| 879 | |||
| 880 | return tb_domain_thaw_noirq(tb); | ||
| 881 | } | ||
| 882 | |||
| 866 | static bool nhi_wake_supported(struct pci_dev *pdev) | 883 | static bool nhi_wake_supported(struct pci_dev *pdev) |
| 867 | { | 884 | { |
| 868 | u8 val; | 885 | u8 val; |
| @@ -1069,6 +1086,69 @@ static bool nhi_imr_valid(struct pci_dev *pdev) · 200 unmodified lines | |||
| 1069 | return true; | 1086 | return true; |
| 1070 | } | 1087 | } |
| 1071 | 1088 | ||
| 1089 | /* | ||
| 1090 | * During suspend the Thunderbolt controller is reset and all PCIe | ||
| 1091 | * tunnels are lost. The NHI driver will try to reestablish all tunnels | ||
| 1092 | * during resume. This adds device links between the tunneled PCIe | ||
| 1093 | * downstream ports and the NHI so that the device core will make sure | ||
| 1094 | * NHI is resumed first before the rest. | ||
| 1095 | */ | ||
| 1096 | static void tb_apple_add_links(struct tb_nhi *nhi) | ||
| 1097 | { | ||
| 1098 | struct pci_dev *upstream, *pdev; | ||
| 1099 | |||
| 1100 | if (!x86_apple_machine) | ||
| 1101 | return; | ||
| 1102 | |||
| 1103 | switch (nhi->pdev->device) { | ||
| 1104 | case PCI_DEVICE_ID_INTEL_LIGHT_RIDGE: | ||
| 1105 | case PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C: | ||
| 1106 | case PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI: | ||
| 1107 | case PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI: | ||
| 1108 | break; | ||
| 1109 | default: | ||
| 1110 | return; | ||
| 1111 | } | ||
| 1112 | |||
| 1113 | upstream = pci_upstream_bridge(nhi->pdev); | ||
| 1114 | while (upstream) { | ||
| 1115 | if (!pci_is_pcie(upstream)) | ||
| 1116 | return; | ||
| 1117 | if (pci_pcie_type(upstream) == PCI_EXP_TYPE_UPSTREAM) | ||
| 1118 | break; | ||
| 1119 | upstream = pci_upstream_bridge(upstream); | ||
| 1120 | } | ||
| 1121 | |||
| 1122 | if (!upstream) | ||
| 1123 | return; | ||
| 1124 | |||
| 1125 | /* | ||
| 1126 | * For each hotplug downstream port, create add device link | ||
| 1127 | * back to NHI so that PCIe tunnels can be re-established after | ||
| 1128 | * sleep. | ||
| 1129 | */ | ||
| 1130 | for_each_pci_bridge(pdev, upstream->subordinate) { | ||
| 1131 | const struct device_link *link; | ||
| 1132 | |||
| 1133 | if (!pci_is_pcie(pdev)) | ||
| 1134 | continue; | ||
| 1135 | if (pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM || | ||
| 1136 | !pdev->is_hotplug_bridge) | ||
| 1137 | continue; | ||
| 1138 | |||
| 1139 | link = device_link_add(&pdev->dev, &nhi->pdev->dev, | ||
| 1140 | DL_FLAG_AUTOREMOVE_SUPPLIER | | ||
| 1141 | DL_FLAG_PM_RUNTIME); | ||
| 1142 | if (link) { | ||
| 1143 | dev_dbg(&nhi->pdev->dev, "created link from %s\n", | ||
| 1144 | dev_name(&pdev->dev)); | ||
| 1145 | } else { | ||
| 1146 | dev_warn(&nhi->pdev->dev, "device link creation from %s failed\n", | ||
| 1147 | dev_name(&pdev->dev)); | ||
| 1148 | } | ||
| 1149 | } | ||
| 1150 | } | ||
| 1151 | |||
| 1072 | static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 1152 | static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
| 1073 | { | 1153 | { |
| 1074 | struct tb_nhi *nhi; | 1154 | struct tb_nhi *nhi; |
| @@ -1134,6 +1214,9 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) · 59 unmodified lines | |||
| 1134 | return res; | 1214 | return res; |
| 1135 | } | 1215 | } |
| 1136 | 1216 | ||
| 1217 | tb_apple_add_links(nhi); | ||
| 1218 | tb_acpi_add_links(nhi); | ||
| 1219 | |||
| 1137 | tb = icm_probe(nhi); | 1220 | tb = icm_probe(nhi); |
| 1138 | if (!tb) | 1221 | if (!tb) |
| 1139 | tb = tb_probe(nhi); | 1222 | tb = tb_probe(nhi); |
| @@ -1157,6 +1240,8 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) · 17 unmodified lines | |||
| 1157 | } | 1240 | } |
| 1158 | pci_set_drvdata(pdev, tb); | 1241 | pci_set_drvdata(pdev, tb); |
| 1159 | 1242 | ||
| 1243 | device_wakeup_enable(&pdev->dev); | ||
| 1244 | |||
| 1160 | pm_runtime_allow(&pdev->dev); | 1245 | pm_runtime_allow(&pdev->dev); |
| 1161 | pm_runtime_set_autosuspend_delay(&pdev->dev, TB_AUTOSUSPEND_DELAY); | 1246 | pm_runtime_set_autosuspend_delay(&pdev->dev, TB_AUTOSUSPEND_DELAY); |
| 1162 | pm_runtime_use_autosuspend(&pdev->dev); | 1247 | pm_runtime_use_autosuspend(&pdev->dev); |
| @@ -1186,14 +1271,13 @@ static void nhi_remove(struct pci_dev *pdev) · 23 unmodified lines | |||
| 1186 | static const struct dev_pm_ops nhi_pm_ops = { | 1271 | static const struct dev_pm_ops nhi_pm_ops = { |
| 1187 | .suspend_noirq = nhi_suspend_noirq, | 1272 | .suspend_noirq = nhi_suspend_noirq, |
| 1188 | .resume_noirq = nhi_resume_noirq, | 1273 | .resume_noirq = nhi_resume_noirq, |
| 1189 | .freeze_noirq = nhi_suspend_noirq, /* | 1274 | .freeze_noirq = nhi_freeze_noirq, /* |
| 1190 | * we just disable hotplug, the | 1275 | * we just disable hotplug, the |
| 1191 | * pci-tunnels stay alive. | 1276 | * pci-tunnels stay alive. |
| 1192 | */ | 1277 | */ |
| 1193 | .thaw_noirq = nhi_resume_noirq, | 1278 | .thaw_noirq = nhi_thaw_noirq, |
| 1194 | .restore_noirq = nhi_resume_noirq, | 1279 | .restore_noirq = nhi_resume_noirq, |
| 1195 | .suspend = nhi_suspend, | 1280 | .suspend = nhi_suspend, |
| 1196 | .freeze = nhi_suspend, | ||
| 1197 | .poweroff_noirq = nhi_poweroff_noirq, | 1281 | .poweroff_noirq = nhi_poweroff_noirq, |
| 1198 | .poweroff = nhi_suspend, | 1282 | .poweroff = nhi_suspend, |
| 1199 | .complete = nhi_complete, | 1283 | .complete = nhi_complete, |
| @@ -59,7 +59,7 @@ static int icl_nhi_force_power(struct tb_nhi *nhi, bool power) · 58 unmodified lines | |||
| 59 | pci_write_config_dword(nhi->pdev, VS_CAP_22, vs_cap); | 59 | pci_write_config_dword(nhi->pdev, VS_CAP_22, vs_cap); |
| 60 | 60 | ||
| 61 | if (power) { | 61 | if (power) { |
| 62 | unsigned int retries = 10; | 62 | unsigned int retries = 350; |
| 63 | u32 val; | 63 | u32 val; |
| 64 | 64 | ||
| 65 | /* Wait until the firmware tells it is up and running */ | 65 | /* Wait until the firmware tells it is up and running */ |
| @@ -67,7 +67,7 @@ static int icl_nhi_force_power(struct tb_nhi *nhi, bool power) · 1 unmodified line | |||
| 67 | pci_read_config_dword(nhi->pdev, VS_CAP_9, &val); | 67 | pci_read_config_dword(nhi->pdev, VS_CAP_9, &val); |
| 68 | if (val & VS_CAP_9_FW_READY) | 68 | if (val & VS_CAP_9_FW_READY) |
| 69 | return 0; | 69 | return 0; |
| 70 | msleep(250); | 70 | usleep_range(3000, 3100); |
| 71 | } while (--retries); | 71 | } while (--retries); |
| 72 | 72 | ||
| 73 | return -ETIMEDOUT; | 73 | return -ETIMEDOUT; |
| @@ -97,7 +97,7 @@ static int icl_nhi_lc_mailbox_cmd_complete(struct tb_nhi *nhi, int timeout) · 23 unmodified lines | |||
| 97 | pci_read_config_dword(nhi->pdev, VS_CAP_18, &data); | 97 | pci_read_config_dword(nhi->pdev, VS_CAP_18, &data); |
| 98 | if (data & VS_CAP_18_DONE) | 98 | if (data & VS_CAP_18_DONE) |
| 99 | goto clear; | 99 | goto clear; |
| 100 | msleep(100); | 100 | usleep_range(1000, 1100); |
| 101 | } while (time_before(jiffies, end)); | 101 | } while (time_before(jiffies, end)); |
| 102 | 102 | ||
| 103 | return -ETIMEDOUT; | 103 | return -ETIMEDOUT; |
| @@ -121,31 +121,38 @@ static void icl_nhi_set_ltr(struct tb_nhi *nhi) · 17 unmodified lines | |||
| 121 | 121 | ||
| 122 | static int icl_nhi_suspend(struct tb_nhi *nhi) | 122 | static int icl_nhi_suspend(struct tb_nhi *nhi) |
| 123 | { | 123 | { |
| 124 | struct tb *tb = pci_get_drvdata(nhi->pdev); | ||
| 124 | int ret; | 125 | int ret; |
| 125 | 126 | ||
| 126 | if (icl_nhi_is_device_connected(nhi)) | 127 | if (icl_nhi_is_device_connected(nhi)) |
| 127 | return 0; | 128 | return 0; |
| 128 | 129 | ||
| 129 | /* | 130 | if (tb_switch_is_icm(tb->root_switch)) { |
| 130 | * If there is no device connected we need to perform both: a | 131 | /* |
| 131 | * handshake through LC mailbox and force power down before | 132 | * If there is no device connected we need to perform |
| 132 | * entering D3. | 133 | * both: a handshake through LC mailbox and force power |
| 133 | */ | 134 | * down before entering D3. |
| 134 | icl_nhi_lc_mailbox_cmd(nhi, ICL_LC_PREPARE_FOR_RESET); | 135 | */ |
| 135 | ret = icl_nhi_lc_mailbox_cmd_complete(nhi, ICL_LC_MAILBOX_TIMEOUT); | 136 | icl_nhi_lc_mailbox_cmd(nhi, ICL_LC_PREPARE_FOR_RESET); |
| 136 | if (ret) | 137 | ret = icl_nhi_lc_mailbox_cmd_complete(nhi, ICL_LC_MAILBOX_TIMEOUT); |
| 137 | return ret; | 138 | if (ret) |
| 139 | return ret; | ||
| 140 | } | ||
| 138 | 141 | ||
| 139 | return icl_nhi_force_power(nhi, false); | 142 | return icl_nhi_force_power(nhi, false); |
| 140 | } | 143 | } |
| 141 | 144 | ||
| 142 | static int icl_nhi_suspend_noirq(struct tb_nhi *nhi, bool wakeup) | 145 | static int icl_nhi_suspend_noirq(struct tb_nhi *nhi, bool wakeup) |
| 143 | { | 146 | { |
| 147 | struct tb *tb = pci_get_drvdata(nhi->pdev); | ||
| 144 | enum icl_lc_mailbox_cmd cmd; | 148 | enum icl_lc_mailbox_cmd cmd; |
| 145 | 149 | ||
| 146 | if (!pm_suspend_via_firmware()) | 150 | if (!pm_suspend_via_firmware()) |
| 147 | return icl_nhi_suspend(nhi); | 151 | return icl_nhi_suspend(nhi); |
| 148 | 152 | ||
| 153 | if (!tb_switch_is_icm(tb->root_switch)) | ||
| 154 | return 0; | ||
| 155 | |||
| 149 | cmd = wakeup ? ICL_LC_GO2SX : ICL_LC_GO2SX_NO_WAKE; | 156 | cmd = wakeup ? ICL_LC_GO2SX : ICL_LC_GO2SX_NO_WAKE; |
| 150 | icl_nhi_lc_mailbox_cmd(nhi, cmd); | 157 | icl_nhi_lc_mailbox_cmd(nhi, cmd); |
| 151 | return icl_nhi_lc_mailbox_cmd_complete(nhi, ICL_LC_MAILBOX_TIMEOUT); | 158 | return icl_nhi_lc_mailbox_cmd_complete(nhi, ICL_LC_MAILBOX_TIMEOUT); |
| @@ -27,7 +27,7 @@ static const struct tb_quirk tb_quirks[] = { · 26 unmodified lines | |||
| 27 | * tb_check_quirks() - Check for quirks to apply | 27 | * tb_check_quirks() - Check for quirks to apply |
| 28 | * @sw: Thunderbolt switch | 28 | * @sw: Thunderbolt switch |
| 29 | * | 29 | * |
| 30 | * Apply any quirks for the Thunderbolt controller | 30 | * Apply any quirks for the Thunderbolt controller. |
| 31 | */ | 31 | */ |
| 32 | void tb_check_quirks(struct tb_switch *sw) | 32 | void tb_check_quirks(struct tb_switch *sw) |
| 33 | { | 33 | { |
| @@ -601,6 +601,13 @@ int tb_port_add_nfc_credits(struct tb_port *port, int credits) · 600 unmodified lines | |||
| 601 | if (credits == 0 || port->sw->is_unplugged) | 601 | if (credits == 0 || port->sw->is_unplugged) |
| 602 | return 0; | 602 | return 0; |
| 603 | 603 | ||
| 604 | /* | ||
| 605 | * USB4 restricts programming NFC buffers to lane adapters only | ||
| 606 | * so skip other ports. | ||
| 607 | */ | ||
| 608 | if (tb_switch_is_usb4(port->sw) && !tb_port_is_null(port)) | ||
| 609 | return 0; | ||
| 610 | |||
| 604 | nfc_credits = port->config.nfc_credits & ADP_CS_4_NFC_BUFFERS_MASK; | 611 | nfc_credits = port->config.nfc_credits & ADP_CS_4_NFC_BUFFERS_MASK; |
| 605 | nfc_credits += credits; | 612 | nfc_credits += credits; |
| 606 | 613 | ||
| @@ -666,6 +673,50 @@ int tb_port_unlock(struct tb_port *port) · 59 unmodified lines | |||
| 666 | return 0; | 673 | return 0; |
| 667 | } | 674 | } |
| 668 | 675 | ||
| 676 | static int __tb_port_enable(struct tb_port *port, bool enable) | ||
| 677 | { | ||
| 678 | int ret; | ||
| 679 | u32 phy; | ||
| 680 | |||
| 681 | if (!tb_port_is_null(port)) | ||
| 682 | return -EINVAL; | ||
| 683 | |||
| 684 | ret = tb_port_read(port, &phy, TB_CFG_PORT, | ||
| 685 | port->cap_phy + LANE_ADP_CS_1, 1); | ||
| 686 | if (ret) | ||
| 687 | return ret; | ||
| 688 | |||
| 689 | if (enable) | ||
| 690 | phy &= ~LANE_ADP_CS_1_LD; | ||
| 691 | else | ||
| 692 | phy |= LANE_ADP_CS_1_LD; | ||
| 693 | |||
| 694 | return tb_port_write(port, &phy, TB_CFG_PORT, | ||
| 695 | port->cap_phy + LANE_ADP_CS_1, 1); | ||
| 696 | } | ||
| 697 | |||
| 698 | /** | ||
| 699 | * tb_port_enable() - Enable lane adapter | ||
| 700 | * @port: Port to enable (can be %NULL) | ||
| 701 | * | ||
| 702 | * This is used for lane 0 and 1 adapters to enable it. | ||
| 703 | */ | ||
| 704 | int tb_port_enable(struct tb_port *port) | ||
| 705 | { | ||
| 706 | return __tb_port_enable(port, true); | ||
| 707 | } | ||
| 708 | |||
| 709 | /** | ||
| 710 | * tb_port_disable() - Disable lane adapter | ||
| 711 | * @port: Port to disable (can be %NULL) | ||
| 712 | * | ||
| 713 | * This is used for lane 0 and 1 adapters to disable it. | ||
| 714 | */ | ||
| 715 | int tb_port_disable(struct tb_port *port) | ||
| 716 | { | ||
| 717 | return __tb_port_enable(port, false); | ||
| 718 | } | ||
| 719 | |||
| 669 | /** | 720 | /** |
| 670 | * tb_init_port() - initialize a port | 721 | * tb_init_port() - initialize a port |
| 671 | * | 722 | * |
| @@ -739,7 +790,7 @@ static int tb_port_alloc_hopid(struct tb_port *port, bool in, int min_hopid, · 67 unmodified lines | |||
| 739 | * NHI can use HopIDs 1-max for other adapters HopIDs 0-7 are | 790 | * NHI can use HopIDs 1-max for other adapters HopIDs 0-7 are |
| 740 | * reserved. | 791 | * reserved. |
| 741 | */ | 792 | */ |
| 742 | if (port->config.type != TB_TYPE_NHI && min_hopid < TB_PATH_MIN_HOPID) | 793 | if (!tb_port_is_nhi(port) && min_hopid < TB_PATH_MIN_HOPID) |
| 743 | min_hopid = TB_PATH_MIN_HOPID; | 794 | min_hopid = TB_PATH_MIN_HOPID; |
| 744 | 795 | ||
| 745 | if (max_hopid < 0 || max_hopid > port_max_hopid) | 796 | if (max_hopid < 0 || max_hopid > port_max_hopid) |
| @@ -1227,23 +1278,24 @@ static void tb_dump_switch(const struct tb *tb, const struct tb_switch *sw) · 481 unmodified lines | |||
| 1227 | 1278 | ||
| 1228 | /** | 1279 | /** |
| 1229 | * reset_switch() - reconfigure route, enable and send TB_CFG_PKG_RESET | 1280 | * reset_switch() - reconfigure route, enable and send TB_CFG_PKG_RESET |
| 1281 | * @sw: Switch to reset | ||
| 1230 | * | 1282 | * |
| 1231 | * Return: Returns 0 on success or an error code on failure. | 1283 | * Return: Returns 0 on success or an error code on failure. |
| 1232 | */ | 1284 | */ |
| 1233 | int tb_switch_reset(struct tb *tb, u64 route) | 1285 | int tb_switch_reset(struct tb_switch *sw) |
| 1234 | { | 1286 | { |
| 1235 | struct tb_cfg_result res; | 1287 | struct tb_cfg_result res; |
| 1236 | struct tb_regs_switch_header header = { | 1288 | |
| 1237 | header.route_hi = route >> 32, | 1289 | if (sw->generation > 1) |
| 1238 | header.route_lo = route, | 1290 | return 0; |
| 1239 | header.enabled = true, | 1291 | |
| 1240 | }; | 1292 | tb_sw_dbg(sw, "resetting switch\n"); |
| 1241 | tb_dbg(tb, "resetting switch at %llx\n", route); | 1293 | |
| 1242 | res.err = tb_cfg_write(tb->ctl, ((u32 *) &header) + 2, route, | 1294 | res.err = tb_sw_write(sw, ((u32 *) &sw->config) + 2, |
| 1243 | 0, 2, 2, 2); | 1295 | TB_CFG_SWITCH, 2, 2); |
| 1244 | if (res.err) | 1296 | if (res.err) |
| 1245 | return res.err; | 1297 | return res.err; |
| 1246 | res = tb_cfg_reset(tb->ctl, route, TB_CFG_DEFAULT_TIMEOUT); | 1298 | res = tb_cfg_reset(sw->tb->ctl, tb_route(sw), TB_CFG_DEFAULT_TIMEOUT); |
| 1247 | if (res.err > 0) | 1299 | if (res.err > 0) |
| 1248 | return -EIO; | 1300 | return -EIO; |
| 1249 | return res.err; | 1301 | return res.err; |
| @@ -1261,7 +1313,7 @@ static int tb_plug_events_active(struct tb_switch *sw, bool active) · 11 unmodified lines | |||
| 1261 | u32 data; | 1313 | u32 data; |
| 1262 | int res; | 1314 | int res; |
| 1263 | 1315 | ||
| 1264 | if (tb_switch_is_icm(sw)) | 1316 | if (tb_switch_is_icm(sw) || tb_switch_is_usb4(sw)) |
| 1265 | return 0; | 1317 | return 0; |
| 1266 | 1318 | ||
| 1267 | sw->config.plug_events_delay = 0xff; | 1319 | sw->config.plug_events_delay = 0xff; |
| @@ -1269,10 +1321,6 @@ static int tb_plug_events_active(struct tb_switch *sw, bool active) · 1 unmodified line | |||
| 1269 | if (res) | 1321 | if (res) |
| 1270 | return res; | 1322 | return res; |
| 1271 | 1323 | ||
| 1272 | /* Plug events are always enabled in USB4 */ | ||
| 1273 | if (tb_switch_is_usb4(sw)) | ||
| 1274 | return 0; | ||
| 1275 | |||
| 1276 | res = tb_sw_read(sw, &data, TB_CFG_SWITCH, sw->cap_plug_events + 1, 1); | 1324 | res = tb_sw_read(sw, &data, TB_CFG_SWITCH, sw->cap_plug_events + 1, 1); |
| 1277 | if (res) | 1325 | if (res) |
| 1278 | return res; | 1326 | return res; |
| @@ -1649,7 +1697,7 @@ static struct attribute *switch_attrs[] = { · 370 unmodified lines | |||
| 1649 | static umode_t switch_attr_is_visible(struct kobject *kobj, | 1697 | static umode_t switch_attr_is_visible(struct kobject *kobj, |
| 1650 | struct attribute *attr, int n) | 1698 | struct attribute *attr, int n) |
| 1651 | { | 1699 | { |
| 1652 | struct device *dev = container_of(kobj, struct device, kobj); | 1700 | struct device *dev = kobj_to_dev(kobj); |
| 1653 | struct tb_switch *sw = tb_to_switch(dev); | 1701 | struct tb_switch *sw = tb_to_switch(dev); |
| 1654 | 1702 | ||
| 1655 | if (attr == &dev_attr_device.attr) { | 1703 | if (attr == &dev_attr_device.attr) { |
| @@ -1988,7 +2036,7 @@ int tb_switch_configure(struct tb_switch *sw) · 332 unmodified lines | |||
| 1988 | route = tb_route(sw); | 2036 | route = tb_route(sw); |
| 1989 | 2037 | ||
| 1990 | tb_dbg(tb, "%s Switch at %#llx (depth: %d, up port: %d)\n", | 2038 | tb_dbg(tb, "%s Switch at %#llx (depth: %d, up port: %d)\n", |
| 1991 | sw->config.enabled ? "restoring " : "initializing", route, | 2039 | sw->config.enabled ? "restoring" : "initializing", route, |
| 1992 | tb_route_length(route), sw->config.upstream_port_number); | 2040 | tb_route_length(route), sw->config.upstream_port_number); |
| 1993 | 2041 | ||
| 1994 | sw->config.enabled = 1; | 2042 | sw->config.enabled = 1; |
| @@ -2008,10 +2056,6 @@ int tb_switch_configure(struct tb_switch *sw) · 13 unmodified lines | |||
| 2008 | return ret; | 2056 | return ret; |
| 2009 | 2057 | ||
| 2010 | ret = usb4_switch_setup(sw); | 2058 | ret = usb4_switch_setup(sw); |
| 2011 | if (ret) | ||
| 2012 | return ret; | ||
| 2013 | |||
| 2014 | ret = usb4_switch_configure_link(sw); | ||
| 2015 | } else { | 2059 | } else { |
| 2016 | if (sw->config.vendor_id != PCI_VENDOR_ID_INTEL) | 2060 | if (sw->config.vendor_id != PCI_VENDOR_ID_INTEL) |
| 2017 | tb_sw_warn(sw, "unknown switch vendor id %#x\n", | 2061 | tb_sw_warn(sw, "unknown switch vendor id %#x\n", |
| @@ -2025,10 +2069,6 @@ int tb_switch_configure(struct tb_switch *sw) · 7 unmodified lines | |||
| 2025 | /* Enumerate the switch */ | 2069 | /* Enumerate the switch */ |
| 2026 | ret = tb_sw_write(sw, (u32 *)&sw->config + 1, TB_CFG_SWITCH, | 2070 | ret = tb_sw_write(sw, (u32 *)&sw->config + 1, TB_CFG_SWITCH, |
| 2027 | ROUTER_CS_1, 3); | 2071 | ROUTER_CS_1, 3); |
| 2028 | if (ret) | ||
| 2029 | return ret; | ||
| 2030 | |||
| 2031 | ret = tb_lc_configure_link(sw); | ||
| 2032 | } | 2072 | } |
| 2033 | if (ret) | 2073 | if (ret) |
| 2034 | return ret; | 2074 | return ret; |
| @@ -2311,6 +2351,69 @@ void tb_switch_lane_bonding_disable(struct tb_switch *sw) · 276 unmodified lines | |||
| 2311 | tb_sw_dbg(sw, "lane bonding disabled\n"); | 2351 | tb_sw_dbg(sw, "lane bonding disabled\n"); |
| 2312 | } | 2352 | } |
| 2313 | 2353 | ||
| 2354 | /** | ||
| 2355 | * tb_switch_configure_link() - Set link configured | ||
| 2356 | * @sw: Switch whose link is configured | ||
| 2357 | * | ||
| 2358 | * Sets the link upstream from @sw configured (from both ends) so that | ||
| 2359 | * it will not be disconnected when the domain exits sleep. Can be | ||
| 2360 | * called for any switch. | ||
| 2361 | * | ||
| 2362 | * It is recommended that this is called after lane bonding is enabled. | ||
| 2363 | * | ||
| 2364 | * Returns %0 on success and negative errno in case of error. | ||
| 2365 | */ | ||
| 2366 | int tb_switch_configure_link(struct tb_switch *sw) | ||
| 2367 | { | ||
| 2368 | struct tb_port *up, *down; | ||
| 2369 | int ret; | ||
| 2370 | |||
| 2371 | if (!tb_route(sw) || tb_switch_is_icm(sw)) | ||
| 2372 | return 0; | ||
| 2373 | |||
| 2374 | up = tb_upstream_port(sw); | ||
| 2375 | if (tb_switch_is_usb4(up->sw)) | ||
| 2376 | ret = usb4_port_configure(up); | ||
| 2377 | else | ||
| 2378 | ret = tb_lc_configure_port(up); | ||
| 2379 | if (ret) | ||
| 2380 | return ret; | ||
| 2381 | |||
| 2382 | down = up->remote; | ||
| 2383 | if (tb_switch_is_usb4(down->sw)) | ||
| 2384 | return usb4_port_configure(down); | ||
| 2385 | return tb_lc_configure_port(down); | ||
| 2386 | } | ||
| 2387 | |||
| 2388 | /** | ||
| 2389 | * tb_switch_unconfigure_link() - Unconfigure link | ||
| 2390 | * @sw: Switch whose link is unconfigured | ||
| 2391 | * | ||
| 2392 | * Sets the link unconfigured so the @sw will be disconnected if the | ||
| 2393 | * domain exists sleep. | ||
| 2394 | */ | ||
| 2395 | void tb_switch_unconfigure_link(struct tb_switch *sw) | ||
| 2396 | { | ||
| 2397 | struct tb_port *up, *down; | ||
| 2398 | |||
| 2399 | if (sw->is_unplugged) | ||
| 2400 | return; | ||
| 2401 | if (!tb_route(sw) || tb_switch_is_icm(sw)) | ||
| 2402 | return; | ||
| 2403 | |||
| 2404 | up = tb_upstream_port(sw); | ||
| 2405 | if (tb_switch_is_usb4(up->sw)) | ||
| 2406 | usb4_port_unconfigure(up); | ||
| 2407 | else | ||
| 2408 | tb_lc_unconfigure_port(up); | ||
| 2409 | |||
| 2410 | down = up->remote; | ||
| 2411 | if (tb_switch_is_usb4(down->sw)) | ||
| 2412 | usb4_port_unconfigure(down); | ||
| 2413 | else | ||
| 2414 | tb_lc_unconfigure_port(down); | ||
| 2415 | } | ||
| 2416 | |||
| 2314 | /** | 2417 | /** |
| 2315 | * tb_switch_add() - Add a switch to the domain | 2418 | * tb_switch_add() - Add a switch to the domain |
| 2316 | * @sw: Switch to add | 2419 | * @sw: Switch to add |
| @@ -2399,6 +2502,13 @@ int tb_switch_add(struct tb_switch *sw) · 82 unmodified lines | |||
| 2399 | return ret; | 2502 | return ret; |
| 2400 | } | 2503 | } |
| 2401 | 2504 | ||
| 2505 | /* | ||
| 2506 | * Thunderbolt routers do not generate wakeups themselves but | ||
| 2507 | * they forward wakeups from tunneled protocols, so enable it | ||
| 2508 | * here. | ||
| 2509 | */ | ||
| 2510 | device_init_wakeup(&sw->dev, true); | ||
| 2511 | |||
| 2402 | pm_runtime_set_active(&sw->dev); | 2512 | pm_runtime_set_active(&sw->dev); |
| 2403 | if (sw->rpm) { | 2513 | if (sw->rpm) { |
| 2404 | pm_runtime_set_autosuspend_delay(&sw->dev, TB_AUTOSUSPEND_DELAY); | 2514 | pm_runtime_set_autosuspend_delay(&sw->dev, TB_AUTOSUSPEND_DELAY); |
| @@ -2408,6 +2518,7 @@ int tb_switch_add(struct tb_switch *sw) · 3 unmodified lines | |||
| 2408 | pm_request_autosuspend(&sw->dev); | 2518 | pm_request_autosuspend(&sw->dev); |
| 2409 | } | 2519 | } |
| 2410 | 2520 | ||
| 2521 | tb_switch_debugfs_init(sw); | ||
| 2411 | return 0; | 2522 | return 0; |
| 2412 | } | 2523 | } |
| 2413 | 2524 | ||
| @@ -2423,6 +2534,8 @@ void tb_switch_remove(struct tb_switch *sw) · 9 unmodified lines | |||
| 2423 | { | 2534 | { |
| 2424 | struct tb_port *port; | 2535 | struct tb_port *port; |
| 2425 | 2536 | ||
| 2537 | tb_switch_debugfs_remove(sw); | ||
| 2538 | |||
| 2426 | if (sw->rpm) { | 2539 | if (sw->rpm) { |
| 2427 | pm_runtime_get_sync(&sw->dev); | 2540 | pm_runtime_get_sync(&sw->dev); |
| 2428 | pm_runtime_disable(&sw->dev); | 2541 | pm_runtime_disable(&sw->dev); |
| @@ -2445,11 +2558,6 @@ void tb_switch_remove(struct tb_switch *sw) · 16 unmodified lines | |||
| 2445 | if (!sw->is_unplugged) | 2558 | if (!sw->is_unplugged) |
| 2446 | tb_plug_events_active(sw, false); | 2559 | tb_plug_events_active(sw, false); |
| 2447 | 2560 | ||
| 2448 | if (tb_switch_is_usb4(sw)) | ||
| 2449 | usb4_switch_unconfigure_link(sw); | ||
| 2450 | else | ||
| 2451 | tb_lc_unconfigure_link(sw); | ||
| 2452 | |||
| 2453 | tb_switch_nvm_remove(sw); | 2561 | tb_switch_nvm_remove(sw); |
| 2454 | 2562 | ||
| 2455 | if (tb_route(sw)) | 2563 | if (tb_route(sw)) |
| @@ -2481,6 +2589,18 @@ void tb_sw_set_unplugged(struct tb_switch *sw) · 25 unmodified lines | |||
| 2481 | } | 2589 | } |
| 2482 | } | 2590 | } |
| 2483 | 2591 | ||
| 2592 | static int tb_switch_set_wake(struct tb_switch *sw, unsigned int flags) | ||
| 2593 | { | ||
| 2594 | if (flags) | ||
| 2595 | tb_sw_dbg(sw, "enabling wakeup: %#x\n", flags); | ||
| 2596 | else | ||
| 2597 | tb_sw_dbg(sw, "disabling wakeup\n"); | ||
| 2598 | |||
| 2599 | if (tb_switch_is_usb4(sw)) | ||
| 2600 | return usb4_switch_set_wake(sw, flags); | ||
| 2601 | return tb_lc_set_wake(sw, flags); | ||
| 2602 | } | ||
| 2603 | |||
| 2484 | int tb_switch_resume(struct tb_switch *sw) | 2604 | int tb_switch_resume(struct tb_switch *sw) |
| 2485 | { | 2605 | { |
| 2486 | struct tb_port *port; | 2606 | struct tb_port *port; |
| @@ -2526,6 +2646,13 @@ int tb_switch_resume(struct tb_switch *sw) · 39 unmodified lines | |||
| 2526 | if (err) | 2646 | if (err) |
| 2527 | return err; | 2647 | return err; |
| 2528 | 2648 | ||
| 2649 | /* Disable wakes */ | ||
| 2650 | tb_switch_set_wake(sw, 0); | ||
| 2651 | |||
| 2652 | err = tb_switch_tmu_init(sw); | ||
| 2653 | if (err) | ||
| 2654 | return err; | ||
| 2655 | |||
| 2529 | /* check for surviving downstream switches */ | 2656 | /* check for surviving downstream switches */ |
| 2530 | tb_switch_for_each_port(sw, port) { | 2657 | tb_switch_for_each_port(sw, port) { |
| 2531 | if (!tb_port_has_remote(port) && !port->xdomain) | 2658 | if (!tb_port_has_remote(port) && !port->xdomain) |
| @@ -2555,20 +2682,43 @@ int tb_switch_resume(struct tb_switch *sw) · 23 unmodified lines | |||
| 2555 | return 0; | 2682 | return 0; |
| 2556 | } | 2683 | } |
| 2557 | 2684 | ||
| 2558 | void tb_switch_suspend(struct tb_switch *sw) | 2685 | /** |
| 2686 | * tb_switch_suspend() - Put a switch to sleep | ||
| 2687 | * @sw: Switch to suspend | ||
| 2688 | * @runtime: Is this runtime suspend or system sleep | ||
| 2689 | * | ||
| 2690 | * Suspends router and all its children. Enables wakes according to | ||
| 2691 | * value of @runtime and then sets sleep bit for the router. If @sw is | ||
| 2692 | * host router the domain is ready to go to sleep once this function | ||
| 2693 | * returns. | ||
| 2694 | */ | ||
| 2695 | void tb_switch_suspend(struct tb_switch *sw, bool runtime) | ||
| 2559 | { | 2696 | { |
| 2697 | unsigned int flags = 0; | ||
| 2560 | struct tb_port *port; | 2698 | struct tb_port *port; |
| 2561 | int err; | 2699 | int err; |
| 2562 | 2700 | ||
| 2701 | tb_sw_dbg(sw, "suspending switch\n"); | ||
| 2702 | |||
| 2563 | err = tb_plug_events_active(sw, false); | 2703 | err = tb_plug_events_active(sw, false); |
| 2564 | if (err) | 2704 | if (err) |
| 2565 | return; | 2705 | return; |
| 2566 | 2706 | ||
| 2567 | tb_switch_for_each_port(sw, port) { | 2707 | tb_switch_for_each_port(sw, port) { |
| 2568 | if (tb_port_has_remote(port)) | 2708 | if (tb_port_has_remote(port)) |
| 2569 | tb_switch_suspend(port->remote->sw); | 2709 | tb_switch_suspend(port->remote->sw, runtime); |
| 2570 | } | 2710 | } |
| 2571 | 2711 | ||
| 2712 | if (runtime) { | ||
| 2713 | /* Trigger wake when something is plugged in/out */ | ||
| 2714 | flags |= TB_WAKE_ON_CONNECT | TB_WAKE_ON_DISCONNECT; | ||
| 2715 | flags |= TB_WAKE_ON_USB4 | TB_WAKE_ON_USB3 | TB_WAKE_ON_PCIE; | ||
| 2716 | } else if (device_may_wakeup(&sw->dev)) { | ||
| 2717 | flags |= TB_WAKE_ON_USB4 | TB_WAKE_ON_USB3 | TB_WAKE_ON_PCIE; | ||
| 2718 | } | ||
| 2719 | |||
| 2720 | tb_switch_set_wake(sw, flags); | ||
| 2721 | |||
| 2572 | if (tb_switch_is_usb4(sw)) | 2722 | if (tb_switch_is_usb4(sw)) |
| 2573 | usb4_switch_set_sleep(sw); | 2723 | usb4_switch_set_sleep(sw); |
| 2574 | else | 2724 | else |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | |||
| 9 | #include <linux/slab.h> | 9 | #include <linux/slab.h> |
| 10 | #include <linux/errno.h> | 10 | #include <linux/errno.h> |
| 11 | #include <linux/delay.h> | 11 | #include <linux/delay.h> |
| 12 | #include <linux/pm_runtime.h> | ||
| 12 | 13 | ||
| 13 | #include "tb.h" | 14 | #include "tb.h" |
| 14 | #include "tb_regs.h" | 15 | #include "tb_regs.h" |
| @@ -22,13 +23,21 @@ · 7 unmodified lines | |||
| 22 | * events and exit if this is not set (it needs to | 23 | * events and exit if this is not set (it needs to |
| 23 | * acquire the lock one more time). Used to drain wq | 24 | * acquire the lock one more time). Used to drain wq |
| 24 | * after cfg has been paused. | 25 | * after cfg has been paused. |
| 26 | * @remove_work: Work used to remove any unplugged routers after | ||
| 27 | * runtime resume | ||
| 25 | */ | 28 | */ |
| 26 | struct tb_cm { | 29 | struct tb_cm { |
| 27 | struct list_head tunnel_list; | 30 | struct list_head tunnel_list; |
| 28 | struct list_head dp_resources; | 31 | struct list_head dp_resources; |
| 29 | bool hotplug_active; | 32 | bool hotplug_active; |
| 33 | struct delayed_work remove_work; | ||
| 30 | }; | 34 | }; |
| 31 | 35 | ||
| 36 | static inline struct tb *tcm_to_tb(struct tb_cm *tcm) | ||
| 37 | { | ||
| 38 | return ((void *)tcm - sizeof(struct tb)); | ||
| 39 | } | ||
| 40 | |||
| 32 | struct tb_hotplug_event { | 41 | struct tb_hotplug_event { |
| 33 | struct work_struct work; | 42 | struct work_struct work; |
| 34 | struct tb *tb; | 43 | struct tb *tb; |
| @@ -140,6 +149,29 @@ static void tb_discover_tunnels(struct tb_switch *sw) · 105 unmodified lines | |||
| 140 | } | 149 | } |
| 141 | } | 150 | } |
| 142 | 151 | ||
| 152 | static int tb_port_configure_xdomain(struct tb_port *port) | ||
| 153 | { | ||
| 154 | /* | ||
| 155 | * XDomain paths currently only support single lane so we must | ||
| 156 | * disable the other lane according to USB4 spec. | ||
| 157 | */ | ||
| 158 | tb_port_disable(port->dual_link_port); | ||
| 159 | |||
| 160 | if (tb_switch_is_usb4(port->sw)) | ||
| 161 | return usb4_port_configure_xdomain(port); | ||
| 162 | return tb_lc_configure_xdomain(port); | ||
| 163 | } | ||
| 164 | |||
| 165 | static void tb_port_unconfigure_xdomain(struct tb_port *port) | ||
| 166 | { | ||
| 167 | if (tb_switch_is_usb4(port->sw)) | ||
| 168 | usb4_port_unconfigure_xdomain(port); | ||
| 169 | else | ||
| 170 | tb_lc_unconfigure_xdomain(port); | ||
| 171 | |||
| 172 | tb_port_enable(port->dual_link_port); | ||
| 173 | } | ||
| 174 | |||
| 143 | static void tb_scan_xdomain(struct tb_port *port) | 175 | static void tb_scan_xdomain(struct tb_port *port) |
| 144 | { | 176 | { |
| 145 | struct tb_switch *sw = port->sw; | 177 | struct tb_switch *sw = port->sw; |
| @@ -158,6 +190,7 @@ static void tb_scan_xdomain(struct tb_port *port) · 12 unmodified lines | |||
| 158 | NULL); | 190 | NULL); |
| 159 | if (xd) { | 191 | if (xd) { |
| 160 | tb_port_at(route, sw)->xdomain = xd; | 192 | tb_port_at(route, sw)->xdomain = xd; |
| 193 | tb_port_configure_xdomain(port); | ||
| 161 | tb_xdomain_add(xd); | 194 | tb_xdomain_add(xd); |
| 162 | } | 195 | } |
| 163 | } | 196 | } |
| @@ -502,8 +535,13 @@ static void tb_scan_switch(struct tb_switch *sw) · 338 unmodified lines | |||
| 502 | { | 535 | { |
| 503 | struct tb_port *port; | 536 | struct tb_port *port; |
| 504 | 537 | ||
| 538 | pm_runtime_get_sync(&sw->dev); | ||
| 539 | |||
| 505 | tb_switch_for_each_port(sw, port) | 540 | tb_switch_for_each_port(sw, port) |
| 506 | tb_scan_port(port); | 541 | tb_scan_port(port); |
| 542 | |||
| 543 | pm_runtime_mark_last_busy(&sw->dev); | ||
| 544 | pm_runtime_put_autosuspend(&sw->dev); | ||
| 507 | } | 545 | } |
| 508 | 546 | ||
| 509 | /** | 547 | /** |
| @@ -566,6 +604,7 @@ static void tb_scan_port(struct tb_port *port) · 56 unmodified lines | |||
| 566 | */ | 604 | */ |
| 567 | if (port->xdomain) { | 605 | if (port->xdomain) { |
| 568 | tb_xdomain_remove(port->xdomain); | 606 | tb_xdomain_remove(port->xdomain); |
| 607 | tb_port_unconfigure_xdomain(port); | ||
| 569 | port->xdomain = NULL; | 608 | port->xdomain = NULL; |
| 570 | } | 609 | } |
| 571 | 610 | ||
| @@ -577,6 +616,12 @@ static void tb_scan_port(struct tb_port *port) · 5 unmodified lines | |||
| 577 | if (!tcm->hotplug_active) | 616 | if (!tcm->hotplug_active) |
| 578 | dev_set_uevent_suppress(&sw->dev, true); | 617 | dev_set_uevent_suppress(&sw->dev, true); |
| 579 | 618 | ||
| 619 | /* | ||
| 620 | * At the moment Thunderbolt 2 and beyond (devices with LC) we | ||
| 621 | * can support runtime PM. | ||
| 622 | */ | ||
| 623 | sw->rpm = sw->generation > 1; | ||
| 624 | |||
| 580 | if (tb_switch_add(sw)) { | 625 | if (tb_switch_add(sw)) { |
| 581 | tb_switch_put(sw); | 626 | tb_switch_put(sw); |
| 582 | return; | 627 | return; |
| @@ -592,8 +637,9 @@ static void tb_scan_port(struct tb_port *port) · 9 unmodified lines | |||
| 592 | } | 637 | } |
| 593 | 638 | ||
| 594 | /* Enable lane bonding if supported */ | 639 | /* Enable lane bonding if supported */ |
| 595 | if (tb_switch_lane_bonding_enable(sw)) | 640 | tb_switch_lane_bonding_enable(sw); |
| 596 | tb_sw_warn(sw, "failed to enable lane bonding\n"); | 641 | /* Set the link configured */ |
| 642 | tb_switch_configure_link(sw); | ||
| 597 | 643 | ||
| 598 | if (tb_enable_tmu(sw)) | 644 | if (tb_enable_tmu(sw)) |
| 599 | tb_sw_warn(sw, "failed to enable TMU\n"); | 645 | tb_sw_warn(sw, "failed to enable TMU\n"); |
| @@ -636,6 +682,11 @@ static void tb_deactivate_and_free_tunnel(struct tb_tunnel *tunnel) · 36 unmodified lines | |||
| 636 | * deallocated properly. | 682 | * deallocated properly. |
| 637 | */ | 683 | */ |
| 638 | tb_switch_dealloc_dp_resource(src_port->sw, src_port); | 684 | tb_switch_dealloc_dp_resource(src_port->sw, src_port); |
| 685 | /* Now we can allow the domain to runtime suspend again */ | ||
| 686 | pm_runtime_mark_last_busy(&dst_port->sw->dev); | ||
| 687 | pm_runtime_put_autosuspend(&dst_port->sw->dev); | ||
| 688 | pm_runtime_mark_last_busy(&src_port->sw->dev); | ||
| 689 | pm_runtime_put_autosuspend(&src_port->sw->dev); | ||
| 639 | fallthrough; | 690 | fallthrough; |
| 640 | 691 | ||
| 641 | case TB_TUNNEL_USB3: | 692 | case TB_TUNNEL_USB3: |
| @@ -682,6 +733,7 @@ static void tb_free_unplugged_children(struct tb_switch *sw) · 40 unmodified lines | |||
| 682 | if (port->remote->sw->is_unplugged) { | 733 | if (port->remote->sw->is_unplugged) { |
| 683 | tb_retimer_remove_all(port); | 734 | tb_retimer_remove_all(port); |
| 684 | tb_remove_dp_resources(port->remote->sw); | 735 | tb_remove_dp_resources(port->remote->sw); |
| 736 | tb_switch_unconfigure_link(port->remote->sw); | ||
| 685 | tb_switch_lane_bonding_disable(port->remote->sw); | 737 | tb_switch_lane_bonding_disable(port->remote->sw); |
| 686 | tb_switch_remove(port->remote->sw); | 738 | tb_switch_remove(port->remote->sw); |
| 687 | port->remote = NULL; | 739 | port->remote = NULL; |
| @@ -821,9 +873,20 @@ static void tb_tunnel_dp(struct tb *tb) · 133 unmodified lines | |||
| 821 | return; | 873 | return; |
| 822 | } | 874 | } |
| 823 | 875 | ||
| 876 | /* | ||
| 877 | * DP stream needs the domain to be active so runtime resume | ||
| 878 | * both ends of the tunnel. | ||
| 879 | * | ||
| 880 | * This should bring the routers in the middle active as well | ||
| 881 | * and keeps the domain from runtime suspending while the DP | ||
| 882 | * tunnel is active. | ||
| 883 | */ | ||
| 884 | pm_runtime_get_sync(&in->sw->dev); | ||
| 885 | pm_runtime_get_sync(&out->sw->dev); | ||
| 886 | |||
| 824 | if (tb_switch_alloc_dp_resource(in->sw, in)) { | 887 | if (tb_switch_alloc_dp_resource(in->sw, in)) { |
| 825 | tb_port_dbg(in, "no resource available for DP IN, not tunneling\n"); | 888 | tb_port_dbg(in, "no resource available for DP IN, not tunneling\n"); |
| 826 | return; | 889 | goto err_rpm_put; |
| 827 | } | 890 | } |
| 828 | 891 | ||
| 829 | /* Make all unused USB3 bandwidth available for the new DP tunnel */ | 892 | /* Make all unused USB3 bandwidth available for the new DP tunnel */ |
| @@ -862,6 +925,11 @@ err_reclaim: · 32 unmodified lines | |||
| 862 | tb_reclaim_usb3_bandwidth(tb, in, out); | 925 | tb_reclaim_usb3_bandwidth(tb, in, out); |
| 863 | err_dealloc_dp: | 926 | err_dealloc_dp: |
| 864 | tb_switch_dealloc_dp_resource(in->sw, in); | 927 | tb_switch_dealloc_dp_resource(in->sw, in); |
| 928 | err_rpm_put: | ||
| 929 | pm_runtime_mark_last_busy(&out->sw->dev); | ||
| 930 | pm_runtime_put_autosuspend(&out->sw->dev); | ||
| 931 | pm_runtime_mark_last_busy(&in->sw->dev); | ||
| 932 | pm_runtime_put_autosuspend(&in->sw->dev); | ||
| 865 | } | 933 | } |
| 866 | 934 | ||
| 867 | static void tb_dp_resource_unavailable(struct tb *tb, struct tb_port *port) | 935 | static void tb_dp_resource_unavailable(struct tb *tb, struct tb_port *port) |
| @@ -911,6 +979,29 @@ static void tb_dp_resource_available(struct tb *tb, struct tb_port *port) · 43 unmodified lines | |||
| 911 | tb_tunnel_dp(tb); | 979 | tb_tunnel_dp(tb); |
| 912 | } | 980 | } |
| 913 | 981 | ||
| 982 | static void tb_disconnect_and_release_dp(struct tb *tb) | ||
| 983 | { | ||
| 984 | struct tb_cm *tcm = tb_priv(tb); | ||
| 985 | struct tb_tunnel *tunnel, *n; | ||
| 986 | |||
| 987 | /* | ||
| 988 | * Tear down all DP tunnels and release their resources. They | ||
| 989 | * will be re-established after resume based on plug events. | ||
| 990 | */ | ||
| 991 | list_for_each_entry_safe_reverse(tunnel, n, &tcm->tunnel_list, list) { | ||
| 992 | if (tb_tunnel_is_dp(tunnel)) | ||
| 993 | tb_deactivate_and_free_tunnel(tunnel); | ||
| 994 | } | ||
| 995 | |||
| 996 | while (!list_empty(&tcm->dp_resources)) { | ||
| 997 | struct tb_port *port; | ||
| 998 | |||
| 999 | port = list_first_entry(&tcm->dp_resources, | ||
| 1000 | struct tb_port, list); | ||
| 1001 | list_del_init(&port->list); | ||
| 1002 | } | ||
| 1003 | } | ||
| 1004 | |||
| 914 | static int tb_tunnel_pci(struct tb *tb, struct tb_switch *sw) | 1005 | static int tb_tunnel_pci(struct tb *tb, struct tb_switch *sw) |
| 915 | { | 1006 | { |
| 916 | struct tb_port *up, *down, *port; | 1007 | struct tb_port *up, *down, *port; |
| @@ -1022,6 +1113,10 @@ static void tb_handle_hotplug(struct work_struct *work) · 105 unmodified lines | |||
| 1022 | struct tb_cm *tcm = tb_priv(tb); | 1113 | struct tb_cm *tcm = tb_priv(tb); |
| 1023 | struct tb_switch *sw; | 1114 | struct tb_switch *sw; |
| 1024 | struct tb_port *port; | 1115 | struct tb_port *port; |
| 1116 | |||
| 1117 | /* Bring the domain back from sleep if it was suspended */ | ||
| 1118 | pm_runtime_get_sync(&tb->dev); | ||
| 1119 | |||
| 1025 | mutex_lock(&tb->lock); | 1120 | mutex_lock(&tb->lock); |
| 1026 | if (!tcm->hotplug_active) | 1121 | if (!tcm->hotplug_active) |
| 1027 | goto out; /* during init, suspend or shutdown */ | 1122 | goto out; /* during init, suspend or shutdown */ |
| @@ -1045,6 +1140,9 @@ static void tb_handle_hotplug(struct work_struct *work) · 17 unmodified lines | |||
| 1045 | ev->route, ev->port, ev->unplug); | 1140 | ev->route, ev->port, ev->unplug); |
| 1046 | goto put_sw; | 1141 | goto put_sw; |
| 1047 | } | 1142 | } |
| 1143 | |||
| 1144 | pm_runtime_get_sync(&sw->dev); | ||
| 1145 | |||
| 1048 | if (ev->unplug) { | 1146 | if (ev->unplug) { |
| 1049 | tb_retimer_remove_all(port); | 1147 | tb_retimer_remove_all(port); |
| 1050 | 1148 | ||
| @@ -1054,6 +1152,7 @@ static void tb_handle_hotplug(struct work_struct *work) · 3 unmodified lines | |||
| 1054 | tb_free_invalid_tunnels(tb); | 1152 | tb_free_invalid_tunnels(tb); |
| 1055 | tb_remove_dp_resources(port->remote->sw); | 1153 | tb_remove_dp_resources(port->remote->sw); |
| 1056 | tb_switch_tmu_disable(port->remote->sw); | 1154 | tb_switch_tmu_disable(port->remote->sw); |
| 1155 | tb_switch_unconfigure_link(port->remote->sw); | ||
| 1057 | tb_switch_lane_bonding_disable(port->remote->sw); | 1156 | tb_switch_lane_bonding_disable(port->remote->sw); |
| 1058 | tb_switch_remove(port->remote->sw); | 1157 | tb_switch_remove(port->remote->sw); |
| 1059 | port->remote = NULL; | 1158 | port->remote = NULL; |
| @@ -1077,6 +1176,7 @@ static void tb_handle_hotplug(struct work_struct *work) · 17 unmodified lines | |||
| 1077 | port->xdomain = NULL; | 1176 | port->xdomain = NULL; |
| 1078 | __tb_disconnect_xdomain_paths(tb, xd); | 1177 | __tb_disconnect_xdomain_paths(tb, xd); |
| 1079 | tb_xdomain_put(xd); | 1178 | tb_xdomain_put(xd); |
| 1179 | tb_port_unconfigure_xdomain(port); | ||
| 1080 | } else if (tb_port_is_dpout(port) || tb_port_is_dpin(port)) { | 1180 | } else if (tb_port_is_dpout(port) || tb_port_is_dpin(port)) { |
| 1081 | tb_dp_resource_unavailable(tb, port); | 1181 | tb_dp_resource_unavailable(tb, port); |
| 1082 | } else { | 1182 | } else { |
| @@ -1096,10 +1196,17 @@ static void tb_handle_hotplug(struct work_struct *work) · 13 unmodified lines | |||
| 1096 | } | 1196 | } |
| 1097 | } | 1197 | } |
| 1098 | 1198 | ||
| 1199 | pm_runtime_mark_last_busy(&sw->dev); | ||
| 1200 | pm_runtime_put_autosuspend(&sw->dev); | ||
| 1201 | |||
| 1099 | put_sw: | 1202 | put_sw: |
| 1100 | tb_switch_put(sw); | 1203 | tb_switch_put(sw); |
| 1101 | out: | 1204 | out: |
| 1102 | mutex_unlock(&tb->lock); | 1205 | mutex_unlock(&tb->lock); |
| 1206 | |||
| 1207 | pm_runtime_mark_last_busy(&tb->dev); | ||
| 1208 | pm_runtime_put_autosuspend(&tb->dev); | ||
| 1209 | |||
| 1103 | kfree(ev); | 1210 | kfree(ev); |
| 1104 | } | 1211 | } |
| 1105 | 1212 | ||
| @@ -1135,6 +1242,7 @@ static void tb_stop(struct tb *tb) · 29 unmodified lines | |||
| 1135 | struct tb_tunnel *tunnel; | 1242 | struct tb_tunnel *tunnel; |
| 1136 | struct tb_tunnel *n; | 1243 | struct tb_tunnel *n; |
| 1137 | 1244 | ||
| 1245 | cancel_delayed_work(&tcm->remove_work); | ||
| 1138 | /* tunnels are only present after everything has been initialized */ | 1246 | /* tunnels are only present after everything has been initialized */ |
| 1139 | list_for_each_entry_safe(tunnel, n, &tcm->tunnel_list, list) { | 1247 | list_for_each_entry_safe(tunnel, n, &tcm->tunnel_list, list) { |
| 1140 | /* | 1248 | /* |
| @@ -1186,6 +1294,8 @@ static int tb_start(struct tb *tb) · 45 unmodified lines | |||
| 1186 | * root switch. | 1294 | * root switch. |
| 1187 | */ | 1295 | */ |
| 1188 | tb->root_switch->no_nvm_upgrade = true; | 1296 | tb->root_switch->no_nvm_upgrade = true; |
| 1297 | /* All USB4 routers support runtime PM */ | ||
| 1298 | tb->root_switch->rpm = tb_switch_is_usb4(tb->root_switch); | ||
| 1189 | 1299 | ||
| 1190 | ret = tb_switch_configure(tb->root_switch); | 1300 | ret = tb_switch_configure(tb->root_switch); |
| 1191 | if (ret) { | 1301 | if (ret) { |
| @@ -1227,7 +1337,8 @@ static int tb_suspend_noirq(struct tb *tb) · 35 unmodified lines | |||
| 1227 | struct tb_cm *tcm = tb_priv(tb); | 1337 | struct tb_cm *tcm = tb_priv(tb); |
| 1228 | 1338 | ||
| 1229 | tb_dbg(tb, "suspending...\n"); | 1339 | tb_dbg(tb, "suspending...\n"); |
| 1230 | tb_switch_suspend(tb->root_switch); | 1340 | tb_disconnect_and_release_dp(tb); |
| 1341 | tb_switch_suspend(tb->root_switch, false); | ||
| 1231 | tcm->hotplug_active = false; /* signal tb_handle_hotplug to quit */ | 1342 | tcm->hotplug_active = false; /* signal tb_handle_hotplug to quit */ |
| 1232 | tb_dbg(tb, "suspend finished\n"); | 1343 | tb_dbg(tb, "suspend finished\n"); |
| 1233 | 1344 | ||
| @@ -1238,17 +1349,25 @@ static void tb_restore_children(struct tb_switch *sw) · 4 unmodified lines | |||
| 1238 | { | 1349 | { |
| 1239 | struct tb_port *port; | 1350 | struct tb_port *port; |
| 1240 | 1351 | ||
| 1352 | /* No need to restore if the router is already unplugged */ | ||
| 1353 | if (sw->is_unplugged) | ||
| 1354 | return; | ||
| 1355 | |||
| 1241 | if (tb_enable_tmu(sw)) | 1356 | if (tb_enable_tmu(sw)) |
| 1242 | tb_sw_warn(sw, "failed to restore TMU configuration\n"); | 1357 | tb_sw_warn(sw, "failed to restore TMU configuration\n"); |
| 1243 | 1358 | ||
| 1244 | tb_switch_for_each_port(sw, port) { | 1359 | tb_switch_for_each_port(sw, port) { |
| 1245 | if (!tb_port_has_remote(port)) | 1360 | if (!tb_port_has_remote(port) && !port->xdomain) |
| 1246 | continue; | 1361 | continue; |
| 1247 | 1362 | ||
| 1248 | if (tb_switch_lane_bonding_enable(port->remote->sw)) | 1363 | if (port->remote) { |
| 1249 | dev_warn(&sw->dev, "failed to restore lane bonding\n"); | 1364 | tb_switch_lane_bonding_enable(port->remote->sw); |
| 1365 | tb_switch_configure_link(port->remote->sw); | ||
| 1250 | 1366 | ||
| 1251 | tb_restore_children(port->remote->sw); | 1367 | tb_restore_children(port->remote->sw); |
| 1368 | } else if (port->xdomain) { | ||
| 1369 | tb_port_configure_xdomain(port); | ||
| 1370 | } | ||
| 1252 | } | 1371 | } |
| 1253 | } | 1372 | } |
| 1254 | 1373 | ||
| @@ -1260,7 +1379,7 @@ static int tb_resume_noirq(struct tb *tb) · 5 unmodified lines | |||
| 1260 | tb_dbg(tb, "resuming...\n"); | 1379 | tb_dbg(tb, "resuming...\n"); |
| 1261 | 1380 | ||
| 1262 | /* remove any pci devices the firmware might have setup */ | 1381 | /* remove any pci devices the firmware might have setup */ |
| 1263 | tb_switch_reset(tb, 0); | 1382 | tb_switch_reset(tb->root_switch); |
| 1264 | 1383 | ||
| 1265 | tb_switch_resume(tb->root_switch); | 1384 | tb_switch_resume(tb->root_switch); |
| 1266 | tb_free_invalid_tunnels(tb); | 1385 | tb_free_invalid_tunnels(tb); |
| @@ -1294,6 +1413,7 @@ static int tb_free_unplugged_xdomains(struct tb_switch *sw) · 27 unmodified lines | |||
| 1294 | if (port->xdomain && port->xdomain->is_unplugged) { | 1413 | if (port->xdomain && port->xdomain->is_unplugged) { |
| 1295 | tb_retimer_remove_all(port); | 1414 | tb_retimer_remove_all(port); |
| 1296 | tb_xdomain_remove(port->xdomain); | 1415 | tb_xdomain_remove(port->xdomain); |
| 1416 | tb_port_unconfigure_xdomain(port); | ||
| 1297 | port->xdomain = NULL; | 1417 | port->xdomain = NULL; |
| 1298 | ret++; | 1418 | ret++; |
| 1299 | } else if (port->remote) { | 1419 | } else if (port->remote) { |
| @@ -1304,6 +1424,22 @@ static int tb_free_unplugged_xdomains(struct tb_switch *sw) · 4 unmodified lines | |||
| 1304 | return ret; | 1424 | return ret; |
| 1305 | } | 1425 | } |
| 1306 | 1426 | ||
| 1427 | static int tb_freeze_noirq(struct tb *tb) | ||
| 1428 | { | ||
| 1429 | struct tb_cm *tcm = tb_priv(tb); | ||
| 1430 | |||
| 1431 | tcm->hotplug_active = false; | ||
| 1432 | return 0; | ||
| 1433 | } | ||
| 1434 | |||
| 1435 | static int tb_thaw_noirq(struct tb *tb) | ||
| 1436 | { | ||
| 1437 | struct tb_cm *tcm = tb_priv(tb); | ||
| 1438 | |||
| 1439 | tcm->hotplug_active = true; | ||
| 1440 | return 0; | ||
| 1441 | } | ||
| 1442 | |||
| 1307 | static void tb_complete(struct tb *tb) | 1443 | static void tb_complete(struct tb *tb) |
| 1308 | { | 1444 | { |
| 1309 | /* | 1445 | /* |
| @@ -1317,12 +1453,64 @@ static void tb_complete(struct tb *tb) · 7 unmodified lines | |||
| 1317 | mutex_unlock(&tb->lock); | 1453 | mutex_unlock(&tb->lock); |
| 1318 | } | 1454 | } |
| 1319 | 1455 | ||
| 1456 | static int tb_runtime_suspend(struct tb *tb) | ||
| 1457 | { | ||
| 1458 | struct tb_cm *tcm = tb_priv(tb); | ||
| 1459 | |||
| 1460 | mutex_lock(&tb->lock); | ||
| 1461 | tb_switch_suspend(tb->root_switch, true); | ||
| 1462 | tcm->hotplug_active = false; | ||
| 1463 | mutex_unlock(&tb->lock); | ||
| 1464 | |||
| 1465 | return 0; | ||
| 1466 | } | ||
| 1467 | |||
| 1468 | static void tb_remove_work(struct work_struct *work) | ||
| 1469 | { | ||
| 1470 | struct tb_cm *tcm = container_of(work, struct tb_cm, remove_work.work); | ||
| 1471 | struct tb *tb = tcm_to_tb(tcm); | ||
| 1472 | |||
| 1473 | mutex_lock(&tb->lock); | ||
| 1474 | if (tb->root_switch) { | ||
| 1475 | tb_free_unplugged_children(tb->root_switch); | ||
| 1476 | tb_free_unplugged_xdomains(tb->root_switch); | ||
| 1477 | } | ||
| 1478 | mutex_unlock(&tb->lock); | ||
| 1479 | } | ||
| 1480 | |||
| 1481 | static int tb_runtime_resume(struct tb *tb) | ||
| 1482 | { | ||
| 1483 | struct tb_cm *tcm = tb_priv(tb); | ||
| 1484 | struct tb_tunnel *tunnel, *n; | ||
| 1485 | |||
| 1486 | mutex_lock(&tb->lock); | ||
| 1487 | tb_switch_resume(tb->root_switch); | ||
| 1488 | tb_free_invalid_tunnels(tb); | ||
| 1489 | tb_restore_children(tb->root_switch); | ||
| 1490 | list_for_each_entry_safe(tunnel, n, &tcm->tunnel_list, list) | ||
| 1491 | tb_tunnel_restart(tunnel); | ||
| 1492 | tcm->hotplug_active = true; | ||
| 1493 | mutex_unlock(&tb->lock); | ||
| 1494 | |||
| 1495 | /* | ||
| 1496 | * Schedule cleanup of any unplugged devices. Run this in a | ||
| 1497 | * separate thread to avoid possible deadlock if the device | ||
| 1498 | * removal runtime resumes the unplugged device. | ||
| 1499 | */ | ||
| 1500 | queue_delayed_work(tb->wq, &tcm->remove_work, msecs_to_jiffies(50)); | ||
| 1501 | return 0; | ||
| 1502 | } | ||
| 1503 | |||
| 1320 | static const struct tb_cm_ops tb_cm_ops = { | 1504 | static const struct tb_cm_ops tb_cm_ops = { |
| 1321 | .start = tb_start, | 1505 | .start = tb_start, |
| 1322 | .stop = tb_stop, | 1506 | .stop = tb_stop, |
| 1323 | .suspend_noirq = tb_suspend_noirq, | 1507 | .suspend_noirq = tb_suspend_noirq, |
| 1324 | .resume_noirq = tb_resume_noirq, | 1508 | .resume_noirq = tb_resume_noirq, |
| 1509 | .freeze_noirq = tb_freeze_noirq, | ||
| 1510 | .thaw_noirq = tb_thaw_noirq, | ||
| 1325 | .complete = tb_complete, | 1511 | .complete = tb_complete, |
| 1512 | .runtime_suspend = tb_runtime_suspend, | ||
| 1513 | .runtime_resume = tb_runtime_resume, | ||
| 1326 | .handle_event = tb_handle_event, | 1514 | .handle_event = tb_handle_event, |
| 1327 | .approve_switch = tb_tunnel_pci, | 1515 | .approve_switch = tb_tunnel_pci, |
| 1328 | .approve_xdomain_paths = tb_approve_xdomain_paths, | 1516 | .approve_xdomain_paths = tb_approve_xdomain_paths, |
| @@ -1344,6 +1532,7 @@ struct tb *tb_probe(struct tb_nhi *nhi) · 15 unmodified lines | |||
| 1344 | tcm = tb_priv(tb); | 1532 | tcm = tb_priv(tb); |
| 1345 | INIT_LIST_HEAD(&tcm->tunnel_list); | 1533 | INIT_LIST_HEAD(&tcm->tunnel_list); |
| 1346 | INIT_LIST_HEAD(&tcm->dp_resources); | 1534 | INIT_LIST_HEAD(&tcm->dp_resources); |
| 1535 | INIT_DELAYED_WORK(&tcm->remove_work, tb_remove_work); | ||
| 1347 | 1536 | ||
| 1348 | return tb; | 1537 | return tb; |
| 1349 | } | 1538 | } |
| @@ -125,6 +125,7 @@ struct tb_switch_tmu { · 124 unmodified lines | |||
| 125 | * @rpm: The switch supports runtime PM | 125 | * @rpm: The switch supports runtime PM |
| 126 | * @authorized: Whether the switch is authorized by user or policy | 126 | * @authorized: Whether the switch is authorized by user or policy |
| 127 | * @security_level: Switch supported security level | 127 | * @security_level: Switch supported security level |
| 128 | * @debugfs_dir: Pointer to the debugfs structure | ||
| 128 | * @key: Contains the key used to challenge the device or %NULL if not | 129 | * @key: Contains the key used to challenge the device or %NULL if not |
| 129 | * supported. Size of the key is %TB_SWITCH_KEY_SIZE. | 130 | * supported. Size of the key is %TB_SWITCH_KEY_SIZE. |
| 130 | * @connection_id: Connection ID used with ICM messaging | 131 | * @connection_id: Connection ID used with ICM messaging |
| @@ -166,6 +167,7 @@ struct tb_switch { · 35 unmodified lines | |||
| 166 | bool rpm; | 167 | bool rpm; |
| 167 | unsigned int authorized; | 168 | unsigned int authorized; |
| 168 | enum tb_security_level security_level; | 169 | enum tb_security_level security_level; |
| 170 | struct dentry *debugfs_dir; | ||
| 169 | u8 *key; | 171 | u8 *key; |
| 170 | u8 connection_id; | 172 | u8 connection_id; |
| 171 | u8 connection_key; | 173 | u8 connection_key; |
| @@ -333,6 +335,13 @@ struct tb_path { · 161 unmodified lines | |||
| 333 | */ | 335 | */ |
| 334 | #define TB_PATH_MAX_HOPS (7 * 2) | 336 | #define TB_PATH_MAX_HOPS (7 * 2) |
| 335 | 337 | ||
| 338 | /* Possible wake types */ | ||
| 339 | #define TB_WAKE_ON_CONNECT BIT(0) | ||
| 340 | #define TB_WAKE_ON_DISCONNECT BIT(1) | ||
| 341 | #define TB_WAKE_ON_USB4 BIT(2) | ||
| 342 | #define TB_WAKE_ON_USB3 BIT(3) | ||
| 343 | #define TB_WAKE_ON_PCIE BIT(4) | ||
| 344 | |||
| 336 | /** | 345 | /** |
| 337 | * struct tb_cm_ops - Connection manager specific operations vector | 346 | * struct tb_cm_ops - Connection manager specific operations vector |
| 338 | * @driver_ready: Called right after control channel is started. Used by | 347 | * @driver_ready: Called right after control channel is started. Used by |
| @@ -342,6 +351,8 @@ struct tb_path { · 3 unmodified lines | |||
| 342 | * @suspend_noirq: Connection manager specific suspend_noirq | 351 | * @suspend_noirq: Connection manager specific suspend_noirq |
| 343 | * @resume_noirq: Connection manager specific resume_noirq | 352 | * @resume_noirq: Connection manager specific resume_noirq |
| 344 | * @suspend: Connection manager specific suspend | 353 | * @suspend: Connection manager specific suspend |
| 354 | * @freeze_noirq: Connection manager specific freeze_noirq | ||
| 355 | * @thaw_noirq: Connection manager specific thaw_noirq | ||
| 345 | * @complete: Connection manager specific complete | 356 | * @complete: Connection manager specific complete |
| 346 | * @runtime_suspend: Connection manager specific runtime_suspend | 357 | * @runtime_suspend: Connection manager specific runtime_suspend |
| 347 | * @runtime_resume: Connection manager specific runtime_resume | 358 | * @runtime_resume: Connection manager specific runtime_resume |
| @@ -364,6 +375,8 @@ struct tb_cm_ops { · 16 unmodified lines | |||
| 364 | int (*suspend_noirq)(struct tb *tb); | 375 | int (*suspend_noirq)(struct tb *tb); |
| 365 | int (*resume_noirq)(struct tb *tb); | 376 | int (*resume_noirq)(struct tb *tb); |
| 366 | int (*suspend)(struct tb *tb); | 377 | int (*suspend)(struct tb *tb); |
| 378 | int (*freeze_noirq)(struct tb *tb); | ||
| 379 | int (*thaw_noirq)(struct tb *tb); | ||
| 367 | void (*complete)(struct tb *tb); | 380 | void (*complete)(struct tb *tb); |
| 368 | int (*runtime_suspend)(struct tb *tb); | 381 | int (*runtime_suspend)(struct tb *tb); |
| 369 | int (*runtime_resume)(struct tb *tb); | 382 | int (*runtime_resume)(struct tb *tb); |
| @@ -457,6 +470,11 @@ static inline bool tb_port_is_null(const struct tb_port *port) · 87 unmodified lines | |||
| 457 | return port && port->port && port->config.type == TB_TYPE_PORT; | 470 | return port && port->port && port->config.type == TB_TYPE_PORT; |
| 458 | } | 471 | } |
| 459 | 472 | ||
| 473 | static inline bool tb_port_is_nhi(const struct tb_port *port) | ||
| 474 | { | ||
| 475 | return port && port->config.type == TB_TYPE_NHI; | ||
| 476 | } | ||
| 477 | |||
| 460 | static inline bool tb_port_is_pcie_down(const struct tb_port *port) | 478 | static inline bool tb_port_is_pcie_down(const struct tb_port *port) |
| 461 | { | 479 | { |
| 462 | return port && port->config.type == TB_TYPE_PCIE_DOWN; | 480 | return port && port->config.type == TB_TYPE_PCIE_DOWN; |
| @@ -593,6 +611,8 @@ void tb_domain_remove(struct tb *tb); · 130 unmodified lines | |||
| 593 | int tb_domain_suspend_noirq(struct tb *tb); | 611 | int tb_domain_suspend_noirq(struct tb *tb); |
| 594 | int tb_domain_resume_noirq(struct tb *tb); | 612 | int tb_domain_resume_noirq(struct tb *tb); |
| 595 | int tb_domain_suspend(struct tb *tb); | 613 | int tb_domain_suspend(struct tb *tb); |
| 614 | int tb_domain_freeze_noirq(struct tb *tb); | ||
| 615 | int tb_domain_thaw_noirq(struct tb *tb); | ||
| 596 | void tb_domain_complete(struct tb *tb); | 616 | void tb_domain_complete(struct tb *tb); |
| 597 | int tb_domain_runtime_suspend(struct tb *tb); | 617 | int tb_domain_runtime_suspend(struct tb *tb); |
| 598 | int tb_domain_runtime_resume(struct tb *tb); | 618 | int tb_domain_runtime_resume(struct tb *tb); |
| @@ -632,9 +652,9 @@ struct tb_switch *tb_switch_alloc_safe_mode(struct tb *tb, · 33 unmodified lines | |||
| 632 | int tb_switch_configure(struct tb_switch *sw); | 652 | int tb_switch_configure(struct tb_switch *sw); |
| 633 | int tb_switch_add(struct tb_switch *sw); | 653 | int tb_switch_add(struct tb_switch *sw); |
| 634 | void tb_switch_remove(struct tb_switch *sw); | 654 | void tb_switch_remove(struct tb_switch *sw); |
| 635 | void tb_switch_suspend(struct tb_switch *sw); | 655 | void tb_switch_suspend(struct tb_switch *sw, bool runtime); |
| 636 | int tb_switch_resume(struct tb_switch *sw); | 656 | int tb_switch_resume(struct tb_switch *sw); |
| 637 | int tb_switch_reset(struct tb *tb, u64 route); | 657 | int tb_switch_reset(struct tb_switch *sw); |
| 638 | void tb_sw_set_unplugged(struct tb_switch *sw); | 658 | void tb_sw_set_unplugged(struct tb_switch *sw); |
| 639 | struct tb_port *tb_switch_find_port(struct tb_switch *sw, | 659 | struct tb_port *tb_switch_find_port(struct tb_switch *sw, |
| 640 | enum tb_port_type type); | 660 | enum tb_port_type type); |
| @@ -685,59 +705,89 @@ static inline struct tb_switch *tb_switch_parent(struct tb_switch *sw) · 44 unmodified lines | |||
| 685 | 705 | ||
| 686 | static inline bool tb_switch_is_light_ridge(const struct tb_switch *sw) | 706 | static inline bool tb_switch_is_light_ridge(const struct tb_switch *sw) |
| 687 | { | 707 | { |
| 688 | return sw->config.device_id == PCI_DEVICE_ID_INTEL_LIGHT_RIDGE; | 708 | return sw->config.vendor_id == PCI_VENDOR_ID_INTEL && |
| 709 | sw->config.device_id == PCI_DEVICE_ID_INTEL_LIGHT_RIDGE; | ||
| 689 | } | 710 | } |
| 690 | 711 | ||
| 691 | static inline bool tb_switch_is_eagle_ridge(const struct tb_switch *sw) | 712 | static inline bool tb_switch_is_eagle_ridge(const struct tb_switch *sw) |
| 692 | { | 713 | { |
| 693 | return sw->config.device_id == PCI_DEVICE_ID_INTEL_EAGLE_RIDGE; | 714 | return sw->config.vendor_id == PCI_VENDOR_ID_INTEL && |
| 715 | sw->config.device_id == PCI_DEVICE_ID_INTEL_EAGLE_RIDGE; | ||
| 694 | } | 716 | } |
| 695 | 717 | ||
| 696 | static inline bool tb_switch_is_cactus_ridge(const struct tb_switch *sw) | 718 | static inline bool tb_switch_is_cactus_ridge(const struct tb_switch *sw) |
| 697 | { | 719 | { |
| 698 | switch (sw->config.device_id) { | 720 | if (sw->config.vendor_id == PCI_VENDOR_ID_INTEL) { |
| 699 | case PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_2C: | 721 | switch (sw->config.device_id) { |
| 700 | case PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C: | 722 | case PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_2C: |
| 701 | return true; | 723 | case PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C: |
| 702 | default: | 724 | return true; |
| 703 | return false; | 725 | } |
| 704 | } | 726 | } |
| 727 | return false; | ||
| 705 | } | 728 | } |
| 706 | 729 | ||
| 707 | static inline bool tb_switch_is_falcon_ridge(const struct tb_switch *sw) | 730 | static inline bool tb_switch_is_falcon_ridge(const struct tb_switch *sw) |
| 708 | { | 731 | { |
| 709 | switch (sw->config.device_id) { | 732 | if (sw->config.vendor_id == PCI_VENDOR_ID_INTEL) { |
| 710 | case PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_BRIDGE: | 733 | switch (sw->config.device_id) { |
| 711 | case PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_BRIDGE: | 734 | case PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_BRIDGE: |
| 712 | return true; | 735 | case PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_BRIDGE: |
| 713 | default: | 736 | return true; |
| 714 | return false; | 737 | } |
| 715 | } | 738 | } |
| 739 | return false; | ||
| 716 | } | 740 | } |
| 717 | 741 | ||
| 718 | static inline bool tb_switch_is_alpine_ridge(const struct tb_switch *sw) | 742 | static inline bool tb_switch_is_alpine_ridge(const struct tb_switch *sw) |
| 719 | { | 743 | { |
| 720 | switch (sw->config.device_id) { | 744 | if (sw->config.vendor_id == PCI_VENDOR_ID_INTEL) { |
| 721 | case PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_BRIDGE: | 745 | switch (sw->config.device_id) { |
| 722 | case PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_LP_BRIDGE: | 746 | case PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_BRIDGE: |
| 723 | case PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_4C_BRIDGE: | 747 | case PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_LP_BRIDGE: |
| 724 | case PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_2C_BRIDGE: | 748 | case PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_4C_BRIDGE: |
| 725 | return true; | 749 | case PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_2C_BRIDGE: |
| 726 | default: | 750 | return true; |
| 727 | return false; | 751 | } |
| 728 | } | 752 | } |
| 753 | return false; | ||
| 729 | } | 754 | } |
| 730 | 755 | ||
| 731 | static inline bool tb_switch_is_titan_ridge(const struct tb_switch *sw) | 756 | static inline bool tb_switch_is_titan_ridge(const struct tb_switch *sw) |
| 732 | { | 757 | { |
| 733 | switch (sw->config.device_id) { | 758 | if (sw->config.vendor_id == PCI_VENDOR_ID_INTEL) { |
| 734 | case PCI_DEVICE_ID_INTEL_TITAN_RIDGE_2C_BRIDGE: | 759 | switch (sw->config.device_id) { |
| 735 | case PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_BRIDGE: | 760 | case PCI_DEVICE_ID_INTEL_TITAN_RIDGE_2C_BRIDGE: |
| 736 | case PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_BRIDGE: | 761 | case PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_BRIDGE: |
| 737 | return true; | 762 | case PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_BRIDGE: |
| 738 | default: | 763 | return true; |
| 739 | return false; | 764 | } |
| 765 | } | ||
| 766 | return false; | ||
| 767 | } | ||
| 768 | |||
| 769 | static inline bool tb_switch_is_ice_lake(const struct tb_switch *sw) | ||
| 770 | { | ||
| 771 | if (sw->config.vendor_id == PCI_VENDOR_ID_INTEL) { | ||
| 772 | switch (sw->config.device_id) { | ||
| 773 | case PCI_DEVICE_ID_INTEL_ICL_NHI0: | ||
| 774 | case PCI_DEVICE_ID_INTEL_ICL_NHI1: | ||
| 775 | return true; | ||
| 776 | } | ||
| 777 | } | ||
| 778 | return false; | ||
| 779 | } | ||
| 780 | |||
| 781 | static inline bool tb_switch_is_tiger_lake(const struct tb_switch *sw) | ||
| 782 | { | ||
| 783 | if (sw->config.vendor_id == PCI_VENDOR_ID_INTEL) { | ||
| 784 | switch (sw->config.device_id) { | ||
| 785 | case PCI_DEVICE_ID_INTEL_TGL_NHI0: | ||
| 786 | case PCI_DEVICE_ID_INTEL_TGL_NHI1: | ||
| 787 | return true; | ||
| 788 | } | ||
| 740 | } | 789 | } |
| 790 | return false; | ||
| 741 | } | 791 | } |
| 742 | 792 | ||
| 743 | /** | 793 | /** |
| @@ -767,6 +817,8 @@ static inline bool tb_switch_is_icm(const struct tb_switch *sw) · 23 unmodified lines | |||
| 767 | 817 | ||
| 768 | int tb_switch_lane_bonding_enable(struct tb_switch *sw); | 818 | int tb_switch_lane_bonding_enable(struct tb_switch *sw); |
| 769 | void tb_switch_lane_bonding_disable(struct tb_switch *sw); | 819 | void tb_switch_lane_bonding_disable(struct tb_switch *sw); |
| 820 | int tb_switch_configure_link(struct tb_switch *sw); | ||
| 821 | void tb_switch_unconfigure_link(struct tb_switch *sw); | ||
| 770 | 822 | ||
| 771 | bool tb_switch_query_dp_resource(struct tb_switch *sw, struct tb_port *in); | 823 | bool tb_switch_query_dp_resource(struct tb_switch *sw, struct tb_port *in); |
| 772 | int tb_switch_alloc_dp_resource(struct tb_switch *sw, struct tb_port *in); | 824 | int tb_switch_alloc_dp_resource(struct tb_switch *sw, struct tb_port *in); |
| @@ -788,6 +840,8 @@ int tb_port_add_nfc_credits(struct tb_port *port, int credits); · 15 unmodified lines | |||
| 788 | int tb_port_set_initial_credits(struct tb_port *port, u32 credits); | 840 | int tb_port_set_initial_credits(struct tb_port *port, u32 credits); |
| 789 | int tb_port_clear_counter(struct tb_port *port, int counter); | 841 | int tb_port_clear_counter(struct tb_port *port, int counter); |
| 790 | int tb_port_unlock(struct tb_port *port); | 842 | int tb_port_unlock(struct tb_port *port); |
| 843 | int tb_port_enable(struct tb_port *port); | ||
| 844 | int tb_port_disable(struct tb_port *port); | ||
| 791 | int tb_port_alloc_in_hopid(struct tb_port *port, int hopid, int max_hopid); | 845 | int tb_port_alloc_in_hopid(struct tb_port *port, int hopid, int max_hopid); |
| 792 | void tb_port_release_in_hopid(struct tb_port *port, int hopid); | 846 | void tb_port_release_in_hopid(struct tb_port *port, int hopid); |
| 793 | int tb_port_alloc_out_hopid(struct tb_port *port, int hopid, int max_hopid); | 847 | int tb_port_alloc_out_hopid(struct tb_port *port, int hopid, int max_hopid); |
| @@ -811,7 +865,9 @@ int tb_port_get_link_speed(struct tb_port *port); · 17 unmodified lines | |||
| 811 | 865 | ||
| 812 | int tb_switch_find_vse_cap(struct tb_switch *sw, enum tb_switch_vse_cap vsec); | 866 | int tb_switch_find_vse_cap(struct tb_switch *sw, enum tb_switch_vse_cap vsec); |
| 813 | int tb_switch_find_cap(struct tb_switch *sw, enum tb_switch_cap cap); | 867 | int tb_switch_find_cap(struct tb_switch *sw, enum tb_switch_cap cap); |
| 868 | int tb_switch_next_cap(struct tb_switch *sw, unsigned int offset); | ||
| 814 | int tb_port_find_cap(struct tb_port *port, enum tb_port_cap cap); | 869 | int tb_port_find_cap(struct tb_port *port, enum tb_port_cap cap); |
| 870 | int tb_port_next_cap(struct tb_port *port, unsigned int offset); | ||
| 815 | bool tb_port_is_enabled(struct tb_port *port); | 871 | bool tb_port_is_enabled(struct tb_port *port); |
| 816 | 872 | ||
| 817 | bool tb_usb3_port_is_enabled(struct tb_port *port); | 873 | bool tb_usb3_port_is_enabled(struct tb_port *port); |
| @@ -844,8 +900,11 @@ int tb_drom_read(struct tb_switch *sw); · 26 unmodified lines | |||
| 844 | int tb_drom_read_uid_only(struct tb_switch *sw, u64 *uid); | 900 | int tb_drom_read_uid_only(struct tb_switch *sw, u64 *uid); |
| 845 | 901 | ||
| 846 | int tb_lc_read_uuid(struct tb_switch *sw, u32 *uuid); | 902 | int tb_lc_read_uuid(struct tb_switch *sw, u32 *uuid); |
| 847 | int tb_lc_configure_link(struct tb_switch *sw); | 903 | int tb_lc_configure_port(struct tb_port *port); |
| 848 | void tb_lc_unconfigure_link(struct tb_switch *sw); | 904 | void tb_lc_unconfigure_port(struct tb_port *port); |
| 905 | int tb_lc_configure_xdomain(struct tb_port *port); | ||
| 906 | void tb_lc_unconfigure_xdomain(struct tb_port *port); | ||
| 907 | int tb_lc_set_wake(struct tb_switch *sw, unsigned int flags); | ||
| 849 | int tb_lc_set_sleep(struct tb_switch *sw); | 908 | int tb_lc_set_sleep(struct tb_switch *sw); |
| 850 | bool tb_lc_lane_bonding_possible(struct tb_switch *sw); | 909 | bool tb_lc_lane_bonding_possible(struct tb_switch *sw); |
| 851 | bool tb_lc_dp_sink_query(struct tb_switch *sw, struct tb_port *in); | 910 | bool tb_lc_dp_sink_query(struct tb_switch *sw, struct tb_port *in); |
| @@ -900,9 +959,8 @@ int usb4_switch_setup(struct tb_switch *sw); · 48 unmodified lines | |||
| 900 | int usb4_switch_read_uid(struct tb_switch *sw, u64 *uid); | 959 | int usb4_switch_read_uid(struct tb_switch *sw, u64 *uid); |
| 901 | int usb4_switch_drom_read(struct tb_switch *sw, unsigned int address, void *buf, | 960 | int usb4_switch_drom_read(struct tb_switch *sw, unsigned int address, void *buf, |
| 902 | size_t size); | 961 | size_t size); |
| 903 | int usb4_switch_configure_link(struct tb_switch *sw); | ||
| 904 | void usb4_switch_unconfigure_link(struct tb_switch *sw); | ||
| 905 | bool usb4_switch_lane_bonding_possible(struct tb_switch *sw); | 962 | bool usb4_switch_lane_bonding_possible(struct tb_switch *sw); |
| 963 | int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags); | ||
| 906 | int usb4_switch_set_sleep(struct tb_switch *sw); | 964 | int usb4_switch_set_sleep(struct tb_switch *sw); |
| 907 | int usb4_switch_nvm_sector_size(struct tb_switch *sw); | 965 | int usb4_switch_nvm_sector_size(struct tb_switch *sw); |
| 908 | int usb4_switch_nvm_read(struct tb_switch *sw, unsigned int address, void *buf, | 966 | int usb4_switch_nvm_read(struct tb_switch *sw, unsigned int address, void *buf, |
| @@ -919,6 +977,10 @@ struct tb_port *usb4_switch_map_usb3_down(struct tb_switch *sw, · 10 unmodified lines | |||
| 919 | const struct tb_port *port); | 977 | const struct tb_port *port); |
| 920 | 978 | ||
| 921 | int usb4_port_unlock(struct tb_port *port); | 979 | int usb4_port_unlock(struct tb_port *port); |
| 980 | int usb4_port_configure(struct tb_port *port); | ||
| 981 | void usb4_port_unconfigure(struct tb_port *port); | ||
| 982 | int usb4_port_configure_xdomain(struct tb_port *port); | ||
| 983 | void usb4_port_unconfigure_xdomain(struct tb_port *port); | ||
| 922 | int usb4_port_enumerate_retimers(struct tb_port *port); | 984 | int usb4_port_enumerate_retimers(struct tb_port *port); |
| 923 | 985 | ||
| 924 | int usb4_port_retimer_read(struct tb_port *port, u8 index, u8 reg, void *buf, | 986 | int usb4_port_retimer_read(struct tb_port *port, u8 index, u8 reg, void *buf, |
| @@ -945,9 +1007,35 @@ int usb4_usb3_port_allocate_bandwidth(struct tb_port *port, int *upstream_bw, · 20 unmodified lines | |||
| 945 | int usb4_usb3_port_release_bandwidth(struct tb_port *port, int *upstream_bw, | 1007 | int usb4_usb3_port_release_bandwidth(struct tb_port *port, int *upstream_bw, |
| 946 | int *downstream_bw); | 1008 | int *downstream_bw); |
| 947 | 1009 | ||
| 948 | /* keep link controller awake during update */ | 1010 | /* Keep link controller awake during update */ |
| 949 | #define QUIRK_FORCE_POWER_LINK_CONTROLLER BIT(0) | 1011 | #define QUIRK_FORCE_POWER_LINK_CONTROLLER BIT(0) |
| 950 | 1012 | ||
| 951 | void tb_check_quirks(struct tb_switch *sw); | 1013 | void tb_check_quirks(struct tb_switch *sw); |
| 952 | 1014 | ||
| 1015 | #ifdef CONFIG_ACPI | ||
| 1016 | void tb_acpi_add_links(struct tb_nhi *nhi); | ||
| 1017 | #else | ||
| 1018 | static inline void tb_acpi_add_links(struct tb_nhi *nhi) { } | ||
| 1019 | #endif | ||
| 1020 | |||
| 1021 | #ifdef CONFIG_DEBUG_FS | ||
| 1022 | void tb_debugfs_init(void); | ||
| 1023 | void tb_debugfs_exit(void); | ||
| 1024 | void tb_switch_debugfs_init(struct tb_switch *sw); | ||
| 1025 | void tb_switch_debugfs_remove(struct tb_switch *sw); | ||
| 1026 | #else | ||
| 1027 | static inline void tb_debugfs_init(void) { } | ||
| 1028 | static inline void tb_debugfs_exit(void) { } | ||
| 1029 | static inline void tb_switch_debugfs_init(struct tb_switch *sw) { } | ||
| 1030 | static inline void tb_switch_debugfs_remove(struct tb_switch *sw) { } | ||
| 1031 | #endif | ||
| 1032 | |||
| 1033 | #ifdef CONFIG_USB4_KUNIT_TEST | ||
| 1034 | int tb_test_init(void); | ||
| 1035 | void tb_test_exit(void); | ||
| 1036 | #else | ||
| 1037 | static inline int tb_test_init(void) { return 0; } | ||
| 1038 | static inline void tb_test_exit(void) { } | ||
| 1039 | #endif | ||
| 1040 | |||
| 953 | #endif | 1041 | #endif |
| @@ -28,6 +28,7 @@ enum tb_cfg_error { · 27 unmodified lines | |||
| 28 | TB_CFG_ERROR_LOOP = 8, | 28 | TB_CFG_ERROR_LOOP = 8, |
| 29 | TB_CFG_ERROR_HEC_ERROR_DETECTED = 12, | 29 | TB_CFG_ERROR_HEC_ERROR_DETECTED = 12, |
| 30 | TB_CFG_ERROR_FLOW_CONTROL_ERROR = 13, | 30 | TB_CFG_ERROR_FLOW_CONTROL_ERROR = 13, |
| 31 | TB_CFG_ERROR_LOCK = 15, | ||
| 31 | }; | 32 | }; |
| 32 | 33 | ||
| 33 | /* common header */ | 34 | /* common header */ |
| @@ -39,6 +39,7 @@ enum tb_switch_vse_cap { · 38 unmodified lines | |||
| 39 | 39 | ||
| 40 | enum tb_port_cap { | 40 | enum tb_port_cap { |
| 41 | TB_PORT_CAP_PHY = 0x01, | 41 | TB_PORT_CAP_PHY = 0x01, |
| 42 | TB_PORT_CAP_POWER = 0x02, | ||
| 42 | TB_PORT_CAP_TIME1 = 0x03, | 43 | TB_PORT_CAP_TIME1 = 0x03, |
| 43 | TB_PORT_CAP_ADAP = 0x04, | 44 | TB_PORT_CAP_ADAP = 0x04, |
| 44 | TB_PORT_CAP_VSE = 0x05, | 45 | TB_PORT_CAP_VSE = 0x05, |
| @@ -93,6 +94,20 @@ struct tb_cap_extended_long { · 48 unmodified lines | |||
| 93 | u16 length; | 94 | u16 length; |
| 94 | } __packed; | 95 | } __packed; |
| 95 | 96 | ||
| 97 | /** | ||
| 98 | * struct tb_cap_any - Structure capable of hold every capability | ||
| 99 | * @basic: Basic capability | ||
| 100 | * @extended_short: Vendor specific capability | ||
| 101 | * @extended_long: Vendor specific extended capability | ||
| 102 | */ | ||
| 103 | struct tb_cap_any { | ||
| 104 | union { | ||
| 105 | struct tb_cap_basic basic; | ||
| 106 | struct tb_cap_extended_short extended_short; | ||
| 107 | struct tb_cap_extended_long extended_long; | ||
| 108 | }; | ||
| 109 | } __packed; | ||
| 110 | |||
| 96 | /* capabilities */ | 111 | /* capabilities */ |
| 97 | 112 | ||
| 98 | struct tb_cap_link_controller { | 113 | struct tb_cap_link_controller { |
| @@ -178,6 +193,8 @@ struct tb_regs_switch_header { · 79 unmodified lines | |||
| 178 | #define ROUTER_CS_4 0x04 | 193 | #define ROUTER_CS_4 0x04 |
| 179 | #define ROUTER_CS_5 0x05 | 194 | #define ROUTER_CS_5 0x05 |
| 180 | #define ROUTER_CS_5_SLP BIT(0) | 195 | #define ROUTER_CS_5_SLP BIT(0) |
| 196 | #define ROUTER_CS_5_WOP BIT(1) | ||
| 197 | #define ROUTER_CS_5_WOU BIT(2) | ||
| 181 | #define ROUTER_CS_5_C3S BIT(23) | 198 | #define ROUTER_CS_5_C3S BIT(23) |
| 182 | #define ROUTER_CS_5_PTO BIT(24) | 199 | #define ROUTER_CS_5_PTO BIT(24) |
| 183 | #define ROUTER_CS_5_UTO BIT(25) | 200 | #define ROUTER_CS_5_UTO BIT(25) |
| @@ -186,6 +203,8 @@ struct tb_regs_switch_header { · 2 unmodified lines | |||
| 186 | #define ROUTER_CS_6 0x06 | 203 | #define ROUTER_CS_6 0x06 |
| 187 | #define ROUTER_CS_6_SLPR BIT(0) | 204 | #define ROUTER_CS_6_SLPR BIT(0) |
| 188 | #define ROUTER_CS_6_TNS BIT(1) | 205 | #define ROUTER_CS_6_TNS BIT(1) |
| 206 | #define ROUTER_CS_6_WOPS BIT(2) | ||
| 207 | #define ROUTER_CS_6_WOUS BIT(3) | ||
| 189 | #define ROUTER_CS_6_HCI BIT(18) | 208 | #define ROUTER_CS_6_HCI BIT(18) |
| 190 | #define ROUTER_CS_6_CR BIT(25) | 209 | #define ROUTER_CS_6_CR BIT(25) |
| 191 | #define ROUTER_CS_7 0x07 | 210 | #define ROUTER_CS_7 0x07 |
| @@ -234,7 +253,8 @@ struct tb_regs_port_header { · 42 unmodified lines | |||
| 234 | /* DWORD 1 */ | 253 | /* DWORD 1 */ |
| 235 | u32 first_cap_offset:8; | 254 | u32 first_cap_offset:8; |
| 236 | u32 max_counters:11; | 255 | u32 max_counters:11; |
| 237 | u32 __unknown1:5; | 256 | u32 counters_support:1; |
| 257 | u32 __unknown1:4; | ||
| 238 | u32 revision:8; | 258 | u32 revision:8; |
| 239 | /* DWORD 2 */ | 259 | /* DWORD 2 */ |
| 240 | enum tb_port_type type:24; | 260 | enum tb_port_type type:24; |
| @@ -279,6 +299,7 @@ struct tb_regs_port_header { · 38 unmodified lines | |||
| 279 | #define LANE_ADP_CS_1_TARGET_WIDTH_SHIFT 4 | 299 | #define LANE_ADP_CS_1_TARGET_WIDTH_SHIFT 4 |
| 280 | #define LANE_ADP_CS_1_TARGET_WIDTH_SINGLE 0x1 | 300 | #define LANE_ADP_CS_1_TARGET_WIDTH_SINGLE 0x1 |
| 281 | #define LANE_ADP_CS_1_TARGET_WIDTH_DUAL 0x3 | 301 | #define LANE_ADP_CS_1_TARGET_WIDTH_DUAL 0x3 |
| 302 | #define LANE_ADP_CS_1_LD BIT(14) | ||
| 282 | #define LANE_ADP_CS_1_LB BIT(15) | 303 | #define LANE_ADP_CS_1_LB BIT(15) |
| 283 | #define LANE_ADP_CS_1_CURRENT_SPEED_MASK GENMASK(19, 16) | 304 | #define LANE_ADP_CS_1_CURRENT_SPEED_MASK GENMASK(19, 16) |
| 284 | #define LANE_ADP_CS_1_CURRENT_SPEED_SHIFT 16 | 305 | #define LANE_ADP_CS_1_CURRENT_SPEED_SHIFT 16 |
| @@ -301,8 +322,13 @@ struct tb_regs_port_header { · 16 unmodified lines | |||
| 301 | #define PORT_CS_18 0x12 | 322 | #define PORT_CS_18 0x12 |
| 302 | #define PORT_CS_18_BE BIT(8) | 323 | #define PORT_CS_18_BE BIT(8) |
| 303 | #define PORT_CS_18_TCM BIT(9) | 324 | #define PORT_CS_18_TCM BIT(9) |
| 325 | #define PORT_CS_18_WOU4S BIT(18) | ||
| 304 | #define PORT_CS_19 0x13 | 326 | #define PORT_CS_19 0x13 |
| 305 | #define PORT_CS_19_PC BIT(3) | 327 | #define PORT_CS_19_PC BIT(3) |
| 328 | #define PORT_CS_19_PID BIT(4) | ||
| 329 | #define PORT_CS_19_WOC BIT(16) | ||
| 330 | #define PORT_CS_19_WOD BIT(17) | ||
| 331 | #define PORT_CS_19_WOU4 BIT(18) | ||
| 306 | 332 | ||
| 307 | /* Display Port adapter registers */ | 333 | /* Display Port adapter registers */ |
| 308 | #define ADP_DP_CS_0 0x00 | 334 | #define ADP_DP_CS_0 0x00 |
| @@ -416,8 +442,14 @@ struct tb_regs_hop { · 107 unmodified lines | |||
| 416 | #define TB_LC_PORT_ATTR_BE BIT(12) | 442 | #define TB_LC_PORT_ATTR_BE BIT(12) |
| 417 | 443 | ||
| 418 | #define TB_LC_SX_CTRL 0x96 | 444 | #define TB_LC_SX_CTRL 0x96 |
| 445 | #define TB_LC_SX_CTRL_WOC BIT(1) | ||
| 446 | #define TB_LC_SX_CTRL_WOD BIT(2) | ||
| 447 | #define TB_LC_SX_CTRL_WOU4 BIT(5) | ||
| 448 | #define TB_LC_SX_CTRL_WOP BIT(6) | ||
| 419 | #define TB_LC_SX_CTRL_L1C BIT(16) | 449 | #define TB_LC_SX_CTRL_L1C BIT(16) |
| 450 | #define TB_LC_SX_CTRL_L1D BIT(17) | ||
| 420 | #define TB_LC_SX_CTRL_L2C BIT(20) | 451 | #define TB_LC_SX_CTRL_L2C BIT(20) |
| 452 | #define TB_LC_SX_CTRL_L2D BIT(21) | ||
| 421 | #define TB_LC_SX_CTRL_UPSTREAM BIT(30) | 453 | #define TB_LC_SX_CTRL_UPSTREAM BIT(30) |
| 422 | #define TB_LC_SX_CTRL_SLP BIT(31) | 454 | #define TB_LC_SX_CTRL_SLP BIT(31) |
| 423 | 455 | ||
| @@ -1623,4 +1623,15 @@ static struct kunit_suite tb_test_suite = { · 1622 unmodified lines | |||
| 1623 | .name = "thunderbolt", | 1623 | .name = "thunderbolt", |
| 1624 | .test_cases = tb_test_cases, | 1624 | .test_cases = tb_test_cases, |
| 1625 | }; | 1625 | }; |
| 1626 | kunit_test_suite(tb_test_suite); | 1626 | |
| 1627 | static struct kunit_suite *tb_test_suites[] = { &tb_test_suite, NULL }; | ||
| 1628 | |||
| 1629 | int tb_test_init(void) | ||
| 1630 | { | ||
| 1631 | return __kunit_test_suites_init(tb_test_suites); | ||
| 1632 | } | ||
| 1633 | |||
| 1634 | void tb_test_exit(void) | ||
| 1635 | { | ||
| 1636 | return __kunit_test_suites_exit(tb_test_suites); | ||
| 1637 | } | ||
| @@ -196,6 +196,46 @@ static int usb4_switch_op(struct tb_switch *sw, u16 opcode, u8 *status) · 195 unmodified lines | |||
| 196 | return 0; | 196 | return 0; |
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | static void usb4_switch_check_wakes(struct tb_switch *sw) | ||
| 200 | { | ||
| 201 | struct tb_port *port; | ||
| 202 | bool wakeup = false; | ||
| 203 | u32 val; | ||
| 204 | |||
| 205 | if (!device_may_wakeup(&sw->dev)) | ||
| 206 | return; | ||
| 207 | |||
| 208 | if (tb_route(sw)) { | ||
| 209 | if (tb_sw_read(sw, &val, TB_CFG_SWITCH, ROUTER_CS_6, 1)) | ||
| 210 | return; | ||
| 211 | |||
| 212 | tb_sw_dbg(sw, "PCIe wake: %s, USB3 wake: %s\n", | ||
| 213 | (val & ROUTER_CS_6_WOPS) ? "yes" : "no", | ||
| 214 | (val & ROUTER_CS_6_WOUS) ? "yes" : "no"); | ||
| 215 | |||
| 216 | wakeup = val & (ROUTER_CS_6_WOPS | ROUTER_CS_6_WOUS); | ||
| 217 | } | ||
| 218 | |||
| 219 | /* Check for any connected downstream ports for USB4 wake */ | ||
| 220 | tb_switch_for_each_port(sw, port) { | ||
| 221 | if (!tb_port_has_remote(port)) | ||
| 222 | continue; | ||
| 223 | |||
| 224 | if (tb_port_read(port, &val, TB_CFG_PORT, | ||
| 225 | port->cap_usb4 + PORT_CS_18, 1)) | ||
| 226 | break; | ||
| 227 | |||
| 228 | tb_port_dbg(port, "USB4 wake: %s\n", | ||
| 229 | (val & PORT_CS_18_WOU4S) ? "yes" : "no"); | ||
| 230 | |||
| 231 | if (val & PORT_CS_18_WOU4S) | ||
| 232 | wakeup = true; | ||
| 233 | } | ||
| 234 | |||
| 235 | if (wakeup) | ||
| 236 | pm_wakeup_event(&sw->dev, 0); | ||
| 237 | } | ||
| 238 | |||
| 199 | static bool link_is_usb4(struct tb_port *port) | 239 | static bool link_is_usb4(struct tb_port *port) |
| 200 | { | 240 | { |
| 201 | u32 val; | 241 | u32 val; |
| @@ -229,6 +269,8 @@ int usb4_switch_setup(struct tb_switch *sw) · 27 unmodified lines | |||
| 229 | u32 val = 0; | 269 | u32 val = 0; |
| 230 | int ret; | 270 | int ret; |
| 231 | 271 | ||
| 272 | usb4_switch_check_wakes(sw); | ||
| 273 | |||
| 232 | if (!tb_route(sw)) | 274 | if (!tb_route(sw)) |
| 233 | return 0; | 275 | return 0; |
| 234 | 276 | ||
| @@ -338,87 +380,99 @@ int usb4_switch_drom_read(struct tb_switch *sw, unsigned int address, void *buf, · 103 unmodified lines | |||
| 338 | usb4_switch_drom_read_block, sw); | 380 | usb4_switch_drom_read_block, sw); |
| 339 | } | 381 | } |
| 340 | 382 | ||
| 341 | static int usb4_set_port_configured(struct tb_port *port, bool configured) | 383 | /** |
| 384 | * usb4_switch_lane_bonding_possible() - Are conditions met for lane bonding | ||
| 385 | * @sw: USB4 router | ||
| 386 | * | ||
| 387 | * Checks whether conditions are met so that lane bonding can be | ||
| 388 | * established with the upstream router. Call only for device routers. | ||
| 389 | */ | ||
| 390 | bool usb4_switch_lane_bonding_possible(struct tb_switch *sw) | ||
| 342 | { | 391 | { |
| 392 | struct tb_port *up; | ||
| 343 | int ret; | 393 | int ret; |
| 344 | u32 val; | 394 | u32 val; |
| 345 | 395 | ||
| 346 | ret = tb_port_read(port, &val, TB_CFG_PORT, | 396 | up = tb_upstream_port(sw); |
| 347 | port->cap_usb4 + PORT_CS_19, 1); | 397 | ret = tb_port_read(up, &val, TB_CFG_PORT, up->cap_usb4 + PORT_CS_18, 1); |
| 348 | if (ret) | 398 | if (ret) |
| 349 | return ret; | 399 | return false; |
| 350 | |||
| 351 | if (configured) | ||
| 352 | val |= PORT_CS_19_PC; | ||
| 353 | else | ||
| 354 | val &= ~PORT_CS_19_PC; | ||
| 355 | 400 | ||
| 356 | return tb_port_write(port, &val, TB_CFG_PORT, | 401 | return !!(val & PORT_CS_18_BE); |
| 357 | port->cap_usb4 + PORT_CS_19, 1); | ||
| 358 | } | 402 | } |
| 359 | 403 | ||
| 360 | /** | 404 | /** |
| 361 | * usb4_switch_configure_link() - Set upstream USB4 link configured | 405 | * usb4_switch_set_wake() - Enabled/disable wake |
| 362 | * @sw: USB4 router | 406 | * @sw: USB4 router |
| 407 | * @flags: Wakeup flags (%0 to disable) | ||
| 363 | * | 408 | * |
| 364 | * Sets the upstream USB4 link to be configured for power management | 409 | * Enables/disables router to wake up from sleep. |
| 365 | * purposes. | ||
| 366 | */ | 410 | */ |
| 367 | int usb4_switch_configure_link(struct tb_switch *sw) | 411 | int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags) |
| 368 | { | 412 | { |
| 369 | struct tb_port *up; | 413 | struct tb_port *port; |
| 414 | u64 route = tb_route(sw); | ||
| 415 | u32 val; | ||
| 416 | int ret; | ||
| 370 | 417 | ||
| 371 | if (!tb_route(sw)) | 418 | /* |
| 372 | return 0; | 419 | * Enable wakes coming from all USB4 downstream ports (from |
| 420 | * child routers). For device routers do this also for the | ||
| 421 | * upstream USB4 port. | ||
| 422 | */ | ||
| 423 | tb_switch_for_each_port(sw, port) { | ||
| 424 | if (!route && tb_is_upstream_port(port)) | ||
| 425 | continue; | ||
| 373 | 426 | ||
| 374 | up = tb_upstream_port(sw); | 427 | ret = tb_port_read(port, &val, TB_CFG_PORT, |
| 375 | return usb4_set_port_configured(up, true); | 428 | port->cap_usb4 + PORT_CS_19, 1); |
| 376 | } | 429 | if (ret) |
| 430 | return ret; | ||
| 377 | 431 | ||
| 378 | /** | 432 | val &= ~(PORT_CS_19_WOC | PORT_CS_19_WOD | PORT_CS_19_WOU4); |
| 379 | * usb4_switch_unconfigure_link() - Un-set upstream USB4 link configuration | ||
| 380 | * @sw: USB4 router | ||
| 381 | * | ||
| 382 | * Reverse of usb4_switch_configure_link(). | ||
| 383 | */ | ||
| 384 | void usb4_switch_unconfigure_link(struct tb_switch *sw) | ||
| 385 | { | ||
| 386 | struct tb_port *up; | ||
| 387 | 433 | ||
| 388 | if (sw->is_unplugged || !tb_route(sw)) | 434 | if (flags & TB_WAKE_ON_CONNECT) |
| 389 | return; | 435 | val |= PORT_CS_19_WOC; |
| 436 | if (flags & TB_WAKE_ON_DISCONNECT) | ||
| 437 | val |= PORT_CS_19_WOD; | ||
| 438 | if (flags & TB_WAKE_ON_USB4) | ||
| 439 | val |= PORT_CS_19_WOU4; | ||
| 390 | 440 | ||
| 391 | up = tb_upstream_port(sw); | 441 | ret = tb_port_write(port, &val, TB_CFG_PORT, |
| 392 | usb4_set_port_configured(up, false); | 442 | port->cap_usb4 + PORT_CS_19, 1); |
| 393 | } | 443 | if (ret) |
| 444 | return ret; | ||
| 445 | } | ||
| 394 | 446 | ||
| 395 | /** | 447 | /* |
| 396 | * usb4_switch_lane_bonding_possible() - Are conditions met for lane bonding | 448 | * Enable wakes from PCIe and USB 3.x on this router. Only |
| 397 | * @sw: USB4 router | 449 | * needed for device routers. |
| 398 | * | 450 | */ |
| 399 | * Checks whether conditions are met so that lane bonding can be | 451 | if (route) { |
| 400 | * established with the upstream router. Call only for device routers. | 452 | ret = tb_sw_read(sw, &val, TB_CFG_SWITCH, ROUTER_CS_5, 1); |
| 401 | */ | 453 | if (ret) |
| 402 | bool usb4_switch_lane_bonding_possible(struct tb_switch *sw) | 454 | return ret; |
| 403 | { | ||
| 404 | struct tb_port *up; | ||
| 405 | int ret; | ||
| 406 | u32 val; | ||
| 407 | 455 | ||
| 408 | up = tb_upstream_port(sw); | 456 | val &= ~(ROUTER_CS_5_WOP | ROUTER_CS_5_WOU); |
| 409 | ret = tb_port_read(up, &val, TB_CFG_PORT, up->cap_usb4 + PORT_CS_18, 1); | 457 | if (flags & TB_WAKE_ON_USB3) |
| 410 | if (ret) | 458 | val |= ROUTER_CS_5_WOU; |
| 411 | return false; | 459 | if (flags & TB_WAKE_ON_PCIE) |
| 460 | val |= ROUTER_CS_5_WOP; | ||
| 412 | 461 | ||
| 413 | return !!(val & PORT_CS_18_BE); | 462 | ret = tb_sw_write(sw, &val, TB_CFG_SWITCH, ROUTER_CS_5, 1); |
| 463 | if (ret) | ||
| 464 | return ret; | ||
| 465 | } | ||
| 466 | |||
| 467 | return 0; | ||
| 414 | } | 468 | } |
| 415 | 469 | ||
| 416 | /** | 470 | /** |
| 417 | * usb4_switch_set_sleep() - Prepare the router to enter sleep | 471 | * usb4_switch_set_sleep() - Prepare the router to enter sleep |
| 418 | * @sw: USB4 router | 472 | * @sw: USB4 router |
| 419 | * | 473 | * |
| 420 | * Enables wakes and sets sleep bit for the router. Returns when the | 474 | * Sets sleep bit for the router. Returns when the router sleep ready |
| 421 | * router sleep ready bit has been asserted. | 475 | * bit has been asserted. |
| 422 | */ | 476 | */ |
| 423 | int usb4_switch_set_sleep(struct tb_switch *sw) | 477 | int usb4_switch_set_sleep(struct tb_switch *sw) |
| 424 | { | 478 | { |
| @@ -795,6 +849,95 @@ int usb4_port_unlock(struct tb_port *port) · 370 unmodified lines | |||
| 795 | return tb_port_write(port, &val, TB_CFG_PORT, ADP_CS_4, 1); | 849 | return tb_port_write(port, &val, TB_CFG_PORT, ADP_CS_4, 1); |
| 796 | } | 850 | } |
| 797 | 851 | ||
| 852 | static int usb4_port_set_configured(struct tb_port *port, bool configured) | ||
| 853 | { | ||
| 854 | int ret; | ||
| 855 | u32 val; | ||
| 856 | |||
| 857 | if (!port->cap_usb4) | ||
| 858 | return -EINVAL; | ||
| 859 | |||
| 860 | ret = tb_port_read(port, &val, TB_CFG_PORT, | ||
| 861 | port->cap_usb4 + PORT_CS_19, 1); | ||
| 862 | if (ret) | ||
| 863 | return ret; | ||
| 864 | |||
| 865 | if (configured) | ||
| 866 | val |= PORT_CS_19_PC; | ||
| 867 | else | ||
| 868 | val &= ~PORT_CS_19_PC; | ||
| 869 | |||
| 870 | return tb_port_write(port, &val, TB_CFG_PORT, | ||
| 871 | port->cap_usb4 + PORT_CS_19, 1); | ||
| 872 | } | ||
| 873 | |||
| 874 | /** | ||
| 875 | * usb4_port_configure() - Set USB4 port configured | ||
| 876 | * @port: USB4 router | ||
| 877 | * | ||
| 878 | * Sets the USB4 link to be configured for power management purposes. | ||
| 879 | */ | ||
| 880 | int usb4_port_configure(struct tb_port *port) | ||
| 881 | { | ||
| 882 | return usb4_port_set_configured(port, true); | ||
| 883 | } | ||
| 884 | |||
| 885 | /** | ||
| 886 | * usb4_port_unconfigure() - Set USB4 port unconfigured | ||
| 887 | * @port: USB4 router | ||
| 888 | * | ||
| 889 | * Sets the USB4 link to be unconfigured for power management purposes. | ||
| 890 | */ | ||
| 891 | void usb4_port_unconfigure(struct tb_port *port) | ||
| 892 | { | ||
| 893 | usb4_port_set_configured(port, false); | ||
| 894 | } | ||
| 895 | |||
| 896 | static int usb4_set_xdomain_configured(struct tb_port *port, bool configured) | ||
| 897 | { | ||
| 898 | int ret; | ||
| 899 | u32 val; | ||
| 900 | |||
| 901 | if (!port->cap_usb4) | ||
| 902 | return -EINVAL; | ||
| 903 | |||
| 904 | ret = tb_port_read(port, &val, TB_CFG_PORT, | ||
| 905 | port->cap_usb4 + PORT_CS_19, 1); | ||
| 906 | if (ret) | ||
| 907 | return ret; | ||
| 908 | |||
| 909 | if (configured) | ||
| 910 | val |= PORT_CS_19_PID; | ||
| 911 | else | ||
| 912 | val &= ~PORT_CS_19_PID; | ||
| 913 | |||
| 914 | return tb_port_write(port, &val, TB_CFG_PORT, | ||
| 915 | port->cap_usb4 + PORT_CS_19, 1); | ||
| 916 | } | ||
| 917 | |||
| 918 | /** | ||
| 919 | * usb4_port_configure_xdomain() - Configure port for XDomain | ||
| 920 | * @port: USB4 port connected to another host | ||
| 921 | * | ||
| 922 | * Marks the USB4 port as being connected to another host. Returns %0 in | ||
| 923 | * success and negative errno in failure. | ||
| 924 | */ | ||
| 925 | int usb4_port_configure_xdomain(struct tb_port *port) | ||
| 926 | { | ||
| 927 | return usb4_set_xdomain_configured(port, true); | ||
| 928 | } | ||
| 929 | |||
| 930 | /** | ||
| 931 | * usb4_port_unconfigure_xdomain() - Unconfigure port for XDomain | ||
| 932 | * @port: USB4 port that was connected to another host | ||
| 933 | * | ||
| 934 | * Clears USB4 port from being marked as XDomain. | ||
| 935 | */ | ||
| 936 | void usb4_port_unconfigure_xdomain(struct tb_port *port) | ||
| 937 | { | ||
| 938 | usb4_set_xdomain_configured(port, false); | ||
| 939 | } | ||
| 940 | |||
| 798 | static int usb4_port_wait_for_bit(struct tb_port *port, u32 offset, u32 bit, | 941 | static int usb4_port_wait_for_bit(struct tb_port *port, u32 offset, u32 bit, |
| 799 | u32 value, int timeout_msec) | 942 | u32 value, int timeout_msec) |
| 800 | { | 943 | { |
| @@ -230,12 +230,12 @@ CXACRU__ATTR_INIT(_name) · 229 unmodified lines | |||
| 230 | 230 | ||
| 231 | static ssize_t cxacru_sysfs_showattr_u32(u32 value, char *buf) | 231 | static ssize_t cxacru_sysfs_showattr_u32(u32 value, char *buf) |
| 232 | { | 232 | { |
| 233 | return snprintf(buf, PAGE_SIZE, "%u\n", value); | 233 | return sprintf(buf, "%u\n", value); |
| 234 | } | 234 | } |
| 235 | 235 | ||
| 236 | static ssize_t cxacru_sysfs_showattr_s8(s8 value, char *buf) | 236 | static ssize_t cxacru_sysfs_showattr_s8(s8 value, char *buf) |
| 237 | { | 237 | { |
| 238 | return snprintf(buf, PAGE_SIZE, "%d\n", value); | 238 | return sprintf(buf, "%d\n", value); |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | static ssize_t cxacru_sysfs_showattr_dB(s16 value, char *buf) | 241 | static ssize_t cxacru_sysfs_showattr_dB(s16 value, char *buf) |
| @@ -255,8 +255,8 @@ static ssize_t cxacru_sysfs_showattr_bool(u32 value, char *buf) · 13 unmodified lines | |||
| 255 | static char *str[] = { "no", "yes" }; | 255 | static char *str[] = { "no", "yes" }; |
| 256 | 256 | ||
| 257 | if (unlikely(value >= ARRAY_SIZE(str))) | 257 | if (unlikely(value >= ARRAY_SIZE(str))) |
| 258 | return snprintf(buf, PAGE_SIZE, "%u\n", value); | 258 | return sprintf(buf, "%u\n", value); |
| 259 | return snprintf(buf, PAGE_SIZE, "%s\n", str[value]); | 259 | return sprintf(buf, "%s\n", str[value]); |
| 260 | } | 260 | } |
| 261 | 261 | ||
| 262 | static ssize_t cxacru_sysfs_showattr_LINK(u32 value, char *buf) | 262 | static ssize_t cxacru_sysfs_showattr_LINK(u32 value, char *buf) |
| @@ -264,8 +264,8 @@ static ssize_t cxacru_sysfs_showattr_LINK(u32 value, char *buf) · 1 unmodified line | |||
| 264 | static char *str[] = { NULL, "not connected", "connected", "lost" }; | 264 | static char *str[] = { NULL, "not connected", "connected", "lost" }; |
| 265 | 265 | ||
| 266 | if (unlikely(value >= ARRAY_SIZE(str) || str[value] == NULL)) | 266 | if (unlikely(value >= ARRAY_SIZE(str) || str[value] == NULL)) |
| 267 | return snprintf(buf, PAGE_SIZE, "%u\n", value); | 267 | return sprintf(buf, "%u\n", value); |
| 268 | return snprintf(buf, PAGE_SIZE, "%s\n", str[value]); | 268 | return sprintf(buf, "%s\n", str[value]); |
| 269 | } | 269 | } |
| 270 | 270 | ||
| 271 | static ssize_t cxacru_sysfs_showattr_LINE(u32 value, char *buf) | 271 | static ssize_t cxacru_sysfs_showattr_LINE(u32 value, char *buf) |
| @@ -275,8 +275,8 @@ static ssize_t cxacru_sysfs_showattr_LINE(u32 value, char *buf) · 3 unmodified lines | |||
| 275 | "waiting", "initialising" | 275 | "waiting", "initialising" |
| 276 | }; | 276 | }; |
| 277 | if (unlikely(value >= ARRAY_SIZE(str))) | 277 | if (unlikely(value >= ARRAY_SIZE(str))) |
| 278 | return snprintf(buf, PAGE_SIZE, "%u\n", value); | 278 | return sprintf(buf, "%u\n", value); |
| 279 | return snprintf(buf, PAGE_SIZE, "%s\n", str[value]); | 279 | return sprintf(buf, "%s\n", str[value]); |
| 280 | } | 280 | } |
| 281 | 281 | ||
| 282 | static ssize_t cxacru_sysfs_showattr_MODU(u32 value, char *buf) | 282 | static ssize_t cxacru_sysfs_showattr_MODU(u32 value, char *buf) |
| @@ -288,8 +288,8 @@ static ssize_t cxacru_sysfs_showattr_MODU(u32 value, char *buf) · 5 unmodified lines | |||
| 288 | "ITU-T G.992.2 (G.LITE)" | 288 | "ITU-T G.992.2 (G.LITE)" |
| 289 | }; | 289 | }; |
| 290 | if (unlikely(value >= ARRAY_SIZE(str))) | 290 | if (unlikely(value >= ARRAY_SIZE(str))) |
| 291 | return snprintf(buf, PAGE_SIZE, "%u\n", value); | 291 | return sprintf(buf, "%u\n", value); |
| 292 | return snprintf(buf, PAGE_SIZE, "%s\n", str[value]); | 292 | return sprintf(buf, "%s\n", str[value]); |
| 293 | } | 293 | } |
| 294 | 294 | ||
| 295 | /* | 295 | /* |
| @@ -309,8 +309,7 @@ static ssize_t mac_address_show(struct device *dev, · 13 unmodified lines | |||
| 309 | if (instance == NULL || instance->usbatm->atm_dev == NULL) | 309 | if (instance == NULL || instance->usbatm->atm_dev == NULL) |
| 310 | return -ENODEV; | 310 | return -ENODEV; |
| 311 | 311 | ||
| 312 | return snprintf(buf, PAGE_SIZE, "%pM\n", | 312 | return sprintf(buf, "%pM\n", instance->usbatm->atm_dev->esi); |
| 313 | instance->usbatm->atm_dev->esi); | ||
| 314 | } | 313 | } |
| 315 | 314 | ||
| 316 | static ssize_t adsl_state_show(struct device *dev, | 315 | static ssize_t adsl_state_show(struct device *dev, |
| @@ -326,8 +325,8 @@ static ssize_t adsl_state_show(struct device *dev, · 9 unmodified lines | |||
| 326 | 325 | ||
| 327 | value = instance->card_info[CXINF_LINE_STARTABLE]; | 326 | value = instance->card_info[CXINF_LINE_STARTABLE]; |
| 328 | if (unlikely(value >= ARRAY_SIZE(str))) | 327 | if (unlikely(value >= ARRAY_SIZE(str))) |
| 329 | return snprintf(buf, PAGE_SIZE, "%u\n", value); | 328 | return sprintf(buf, "%u\n", value); |
| 330 | return snprintf(buf, PAGE_SIZE, "%s\n", str[value]); | 329 | return sprintf(buf, "%s\n", str[value]); |
| 331 | } | 330 | } |
| 332 | 331 | ||
| 333 | static ssize_t adsl_state_store(struct device *dev, | 332 | static ssize_t adsl_state_store(struct device *dev, |
| @@ -511,9 +511,10 @@ static unsigned int usbatm_write_cells(struct usbatm_data *instance, · 510 unmodified lines | |||
| 511 | ** receive ** | 511 | ** receive ** |
| 512 | **************/ | 512 | **************/ |
| 513 | 513 | ||
| 514 | static void usbatm_rx_process(unsigned long data) | 514 | static void usbatm_rx_process(struct tasklet_struct *t) |
| 515 | { | 515 | { |
| 516 | struct usbatm_data *instance = (struct usbatm_data *)data; | 516 | struct usbatm_data *instance = from_tasklet(instance, t, |
| 517 | rx_channel.tasklet); | ||
| 517 | struct urb *urb; | 518 | struct urb *urb; |
| 518 | 519 | ||
| 519 | while ((urb = usbatm_pop_urb(&instance->rx_channel))) { | 520 | while ((urb = usbatm_pop_urb(&instance->rx_channel))) { |
| @@ -564,9 +565,10 @@ static void usbatm_rx_process(unsigned long data) · 44 unmodified lines | |||
| 564 | ** send ** | 565 | ** send ** |
| 565 | ***********/ | 566 | ***********/ |
| 566 | 567 | ||
| 567 | static void usbatm_tx_process(unsigned long data) | 568 | static void usbatm_tx_process(struct tasklet_struct *t) |
| 568 | { | 569 | { |
| 569 | struct usbatm_data *instance = (struct usbatm_data *)data; | 570 | struct usbatm_data *instance = from_tasklet(instance, t, |
| 571 | tx_channel.tasklet); | ||
| 570 | struct sk_buff *skb = instance->current_skb; | 572 | struct sk_buff *skb = instance->current_skb; |
| 571 | struct urb *urb = NULL; | 573 | struct urb *urb = NULL; |
| 572 | const unsigned int buf_size = instance->tx_channel.buf_size; | 574 | const unsigned int buf_size = instance->tx_channel.buf_size; |
| @@ -1069,8 +1071,8 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, · 496 unmodified lines | |||
| 1069 | 1071 | ||
| 1070 | usbatm_init_channel(&instance->rx_channel); | 1072 | usbatm_init_channel(&instance->rx_channel); |
| 1071 | usbatm_init_channel(&instance->tx_channel); | 1073 | usbatm_init_channel(&instance->tx_channel); |
| 1072 | tasklet_init(&instance->rx_channel.tasklet, usbatm_rx_process, (unsigned long)instance); | 1074 | tasklet_setup(&instance->rx_channel.tasklet, usbatm_rx_process); |
| 1073 | tasklet_init(&instance->tx_channel.tasklet, usbatm_tx_process, (unsigned long)instance); | 1075 | tasklet_setup(&instance->tx_channel.tasklet, usbatm_tx_process); |
| 1074 | instance->rx_channel.stride = ATM_CELL_SIZE + driver->rx_padding; | 1076 | instance->rx_channel.stride = ATM_CELL_SIZE + driver->rx_padding; |
| 1075 | instance->tx_channel.stride = ATM_CELL_SIZE + driver->tx_padding; | 1077 | instance->tx_channel.stride = ATM_CELL_SIZE + driver->tx_padding; |
| 1076 | instance->rx_channel.usbatm = instance->tx_channel.usbatm = instance; | 1078 | instance->rx_channel.usbatm = instance->tx_channel.usbatm = instance; |
| @@ -1123,9 +1123,9 @@ static void c67x00_do_work(struct c67x00_hcd *c67x00) · 1122 unmodified lines | |||
| 1123 | 1123 | ||
| 1124 | /* -------------------------------------------------------------------------- */ | 1124 | /* -------------------------------------------------------------------------- */ |
| 1125 | 1125 | ||
| 1126 | static void c67x00_sched_tasklet(unsigned long __c67x00) | 1126 | static void c67x00_sched_tasklet(struct tasklet_struct *t) |
| 1127 | { | 1127 | { |
| 1128 | struct c67x00_hcd *c67x00 = (struct c67x00_hcd *)__c67x00; | 1128 | struct c67x00_hcd *c67x00 = from_tasklet(c67x00, t, tasklet); |
| 1129 | c67x00_do_work(c67x00); | 1129 | c67x00_do_work(c67x00); |
| 1130 | } | 1130 | } |
| 1131 | 1131 | ||
| @@ -1136,8 +1136,7 @@ void c67x00_sched_kick(struct c67x00_hcd *c67x00) · 4 unmodified lines | |||
| 1136 | 1136 | ||
| 1137 | int c67x00_sched_start_scheduler(struct c67x00_hcd *c67x00) | 1137 | int c67x00_sched_start_scheduler(struct c67x00_hcd *c67x00) |
| 1138 | { | 1138 | { |
| 1139 | tasklet_init(&c67x00->tasklet, c67x00_sched_tasklet, | 1139 | tasklet_setup(&c67x00->tasklet, c67x00_sched_tasklet); |
| 1140 | (unsigned long)c67x00); | ||
| 1141 | return 0; | 1140 | return 0; |
| 1142 | } | 1141 | } |
| 1143 | 1142 | ||
| @@ -15,6 +15,8 @@ · 14 unmodified lines | |||
| 15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
| 16 | #include <linux/of_platform.h> | 16 | #include <linux/of_platform.h> |
| 17 | #include <linux/iopoll.h> | 17 | #include <linux/iopoll.h> |
| 18 | #include <linux/pm_runtime.h> | ||
| 19 | #include "core.h" | ||
| 18 | 20 | ||
| 19 | #define USB3_CORE_CTRL1 0x00 | 21 | #define USB3_CORE_CTRL1 0x00 |
| 20 | #define USB3_CORE_CTRL2 0x04 | 22 | #define USB3_CORE_CTRL2 0x04 |
| @@ -32,7 +34,7 @@ · 11 unmodified lines | |||
| 32 | /* Register bits definition */ | 34 | /* Register bits definition */ |
| 33 | 35 | ||
| 34 | /* USB3_CORE_CTRL1 */ | 36 | /* USB3_CORE_CTRL1 */ |
| 35 | #define SW_RESET_MASK (0x3f << 26) | 37 | #define SW_RESET_MASK GENMASK(31, 26) |
| 36 | #define PWR_SW_RESET BIT(31) | 38 | #define PWR_SW_RESET BIT(31) |
| 37 | #define APB_SW_RESET BIT(30) | 39 | #define APB_SW_RESET BIT(30) |
| 38 | #define AXI_SW_RESET BIT(29) | 40 | #define AXI_SW_RESET BIT(29) |
| @@ -53,8 +55,8 @@ · 14 unmodified lines | |||
| 53 | #define LPM_CLK_REQ BIT(28) | 55 | #define LPM_CLK_REQ BIT(28) |
| 54 | #define DEVU3_WAEKUP_EN BIT(14) | 56 | #define DEVU3_WAEKUP_EN BIT(14) |
| 55 | #define OTG_WAKEUP_EN BIT(12) | 57 | #define OTG_WAKEUP_EN BIT(12) |
| 56 | #define DEV_INT_EN (3 << 8) /* DEV INT b9:8 */ | 58 | #define DEV_INT_EN (3 << 8) /* DEV INT b9:8 */ |
| 57 | #define HOST_INT1_EN (1 << 0) /* HOST INT b7:0 */ | 59 | #define HOST_INT1_EN (1 << 0) /* HOST INT b7:0 */ |
| 58 | 60 | ||
| 59 | /* USB3_CORE_STATUS */ | 61 | /* USB3_CORE_STATUS */ |
| 60 | #define MDCTRL_CLK_STATUS BIT(15) | 62 | #define MDCTRL_CLK_STATUS BIT(15) |
| @@ -66,11 +68,30 @@ · 5 unmodified lines | |||
| 66 | #define CLK_VALID_COMPARE_BITS (0xf << 28) | 68 | #define CLK_VALID_COMPARE_BITS (0xf << 28) |
| 67 | #define PHY_REFCLK_REQ (1 << 0) | 69 | #define PHY_REFCLK_REQ (1 << 0) |
| 68 | 70 | ||
| 71 | /* OTG registers definition */ | ||
| 72 | #define OTGSTS 0x4 | ||
| 73 | /* OTGSTS */ | ||
| 74 | #define OTG_NRDY BIT(11) | ||
| 75 | |||
| 76 | /* xHCI registers definition */ | ||
| 77 | #define XECP_PM_PMCSR 0x8018 | ||
| 78 | #define XECP_AUX_CTRL_REG1 0x8120 | ||
| 79 | |||
| 80 | /* Register bits definition */ | ||
| 81 | /* XECP_AUX_CTRL_REG1 */ | ||
| 82 | #define CFG_RXDET_P3_EN BIT(15) | ||
| 83 | |||
| 84 | /* XECP_PM_PMCSR */ | ||
| 85 | #define PS_MASK GENMASK(1, 0) | ||
| 86 | #define PS_D0 0 | ||
| 87 | #define PS_D1 1 | ||
| 88 | |||
| 69 | struct cdns_imx { | 89 | struct cdns_imx { |
| 70 | struct device *dev; | 90 | struct device *dev; |
| 71 | void __iomem *noncore; | 91 | void __iomem *noncore; |
| 72 | struct clk_bulk_data *clks; | 92 | struct clk_bulk_data *clks; |
| 73 | int num_clks; | 93 | int num_clks; |
| 94 | struct platform_device *cdns3_pdev; | ||
| 74 | }; | 95 | }; |
| 75 | 96 | ||
| 76 | static inline u32 cdns_imx_readl(struct cdns_imx *data, u32 offset) | 97 | static inline u32 cdns_imx_readl(struct cdns_imx *data, u32 offset) |
| @@ -126,6 +147,20 @@ static int cdns_imx_noncore_init(struct cdns_imx *data) · 49 unmodified lines | |||
| 126 | return ret; | 147 | return ret; |
| 127 | } | 148 | } |
| 128 | 149 | ||
| 150 | static int cdns_imx_platform_suspend(struct device *dev, | ||
| 151 | bool suspend, bool wakeup); | ||
| 152 | static struct cdns3_platform_data cdns_imx_pdata = { | ||
| 153 | .platform_suspend = cdns_imx_platform_suspend, | ||
| 154 | }; | ||
| 155 | |||
| 156 | static const struct of_dev_auxdata cdns_imx_auxdata[] = { | ||
| 157 | { | ||
| 158 | .compatible = "cdns,usb3", | ||
| 159 | .platform_data = &cdns_imx_pdata, | ||
| 160 | }, | ||
| 161 | {}, | ||
| 162 | }; | ||
| 163 | |||
| 129 | static int cdns_imx_probe(struct platform_device *pdev) | 164 | static int cdns_imx_probe(struct platform_device *pdev) |
| 130 | { | 165 | { |
| 131 | struct device *dev = &pdev->dev; | 166 | struct device *dev = &pdev->dev; |
| @@ -162,14 +197,18 @@ static int cdns_imx_probe(struct platform_device *pdev) · 30 unmodified lines | |||
| 162 | if (ret) | 197 | if (ret) |
| 163 | goto err; | 198 | goto err; |
| 164 | 199 | ||
| 165 | ret = of_platform_populate(node, NULL, NULL, dev); | 200 | ret = of_platform_populate(node, NULL, cdns_imx_auxdata, dev); |
| 166 | if (ret) { | 201 | if (ret) { |
| 167 | dev_err(dev, "failed to create children: %d\n", ret); | 202 | dev_err(dev, "failed to create children: %d\n", ret); |
| 168 | goto err; | 203 | goto err; |
| 169 | } | 204 | } |
| 170 | 205 | ||
| 171 | return ret; | 206 | device_set_wakeup_capable(dev, true); |
| 207 | pm_runtime_set_active(dev); | ||
| 208 | pm_runtime_enable(dev); | ||
| 209 | pm_runtime_forbid(dev); | ||
| 172 | 210 | ||
| 211 | return ret; | ||
| 173 | err: | 212 | err: |
| 174 | clk_bulk_disable_unprepare(data->num_clks, data->clks); | 213 | clk_bulk_disable_unprepare(data->num_clks, data->clks); |
| 175 | return ret; | 214 | return ret; |
| @@ -194,6 +233,147 @@ static int cdns_imx_remove(struct platform_device *pdev) · 18 unmodified lines | |||
| 194 | return 0; | 233 | return 0; |
| 195 | } | 234 | } |
| 196 | 235 | ||
| 236 | #ifdef CONFIG_PM | ||
| 237 | static void cdns3_set_wakeup(struct cdns_imx *data, bool enable) | ||
| 238 | { | ||
| 239 | u32 value; | ||
| 240 | |||
| 241 | value = cdns_imx_readl(data, USB3_INT_REG); | ||
| 242 | if (enable) | ||
| 243 | value |= OTG_WAKEUP_EN | DEVU3_WAEKUP_EN; | ||
| 244 | else | ||
| 245 | value &= ~(OTG_WAKEUP_EN | DEVU3_WAEKUP_EN); | ||
| 246 | |||
| 247 | cdns_imx_writel(data, USB3_INT_REG, value); | ||
| 248 | } | ||
| 249 | |||
| 250 | static int cdns_imx_platform_suspend(struct device *dev, | ||
| 251 | bool suspend, bool wakeup) | ||
| 252 | { | ||
| 253 | struct cdns3 *cdns = dev_get_drvdata(dev); | ||
| 254 | struct device *parent = dev->parent; | ||
| 255 | struct cdns_imx *data = dev_get_drvdata(parent); | ||
| 256 | void __iomem *otg_regs = (void __iomem *)(cdns->otg_regs); | ||
| 257 | void __iomem *xhci_regs = cdns->xhci_regs; | ||
| 258 | u32 value; | ||
| 259 | int ret = 0; | ||
| 260 | |||
| 261 | if (cdns->role != USB_ROLE_HOST) | ||
| 262 | return 0; | ||
| 263 | |||
| 264 | if (suspend) { | ||
| 265 | /* SW request low power when all usb ports allow to it ??? */ | ||
| 266 | value = readl(xhci_regs + XECP_PM_PMCSR); | ||
| 267 | value &= ~PS_MASK; | ||
| 268 | value |= PS_D1; | ||
| 269 | writel(value, xhci_regs + XECP_PM_PMCSR); | ||
| 270 | |||
| 271 | /* mdctrl_clk_sel */ | ||
| 272 | value = cdns_imx_readl(data, USB3_CORE_CTRL1); | ||
| 273 | value |= MDCTRL_CLK_SEL; | ||
| 274 | cdns_imx_writel(data, USB3_CORE_CTRL1, value); | ||
| 275 | |||
| 276 | /* wait for mdctrl_clk_status */ | ||
| 277 | value = cdns_imx_readl(data, USB3_CORE_STATUS); | ||
| 278 | ret = readl_poll_timeout(data->noncore + USB3_CORE_STATUS, value, | ||
| 279 | (value & MDCTRL_CLK_STATUS) == MDCTRL_CLK_STATUS, | ||
| 280 | 10, 100000); | ||
| 281 | if (ret) | ||
| 282 | dev_warn(parent, "wait mdctrl_clk_status timeout\n"); | ||
| 283 | |||
| 284 | /* wait lpm_clk_req to be 0 */ | ||
| 285 | value = cdns_imx_readl(data, USB3_INT_REG); | ||
| 286 | ret = readl_poll_timeout(data->noncore + USB3_INT_REG, value, | ||
| 287 | (value & LPM_CLK_REQ) != LPM_CLK_REQ, | ||
| 288 | 10, 100000); | ||
| 289 | if (ret) | ||
| 290 | dev_warn(parent, "wait lpm_clk_req timeout\n"); | ||
| 291 | |||
| 292 | /* wait phy_refclk_req to be 0 */ | ||
| 293 | value = cdns_imx_readl(data, USB3_SSPHY_STATUS); | ||
| 294 | ret = readl_poll_timeout(data->noncore + USB3_SSPHY_STATUS, value, | ||
| 295 | (value & PHY_REFCLK_REQ) != PHY_REFCLK_REQ, | ||
| 296 | 10, 100000); | ||
| 297 | if (ret) | ||
| 298 | dev_warn(parent, "wait phy_refclk_req timeout\n"); | ||
| 299 | |||
| 300 | cdns3_set_wakeup(data, wakeup); | ||
| 301 | } else { | ||
| 302 | cdns3_set_wakeup(data, false); | ||
| 303 | |||
| 304 | /* SW request D0 */ | ||
| 305 | value = readl(xhci_regs + XECP_PM_PMCSR); | ||
| 306 | value &= ~PS_MASK; | ||
| 307 | value |= PS_D0; | ||
| 308 | writel(value, xhci_regs + XECP_PM_PMCSR); | ||
| 309 | |||
| 310 | /* clr CFG_RXDET_P3_EN */ | ||
| 311 | value = readl(xhci_regs + XECP_AUX_CTRL_REG1); | ||
| 312 | value &= ~CFG_RXDET_P3_EN; | ||
| 313 | writel(value, xhci_regs + XECP_AUX_CTRL_REG1); | ||
| 314 | |||
| 315 | /* clear mdctrl_clk_sel */ | ||
| 316 | value = cdns_imx_readl(data, USB3_CORE_CTRL1); | ||
| 317 | value &= ~MDCTRL_CLK_SEL; | ||
| 318 | cdns_imx_writel(data, USB3_CORE_CTRL1, value); | ||
| 319 | |||
| 320 | /* wait CLK_125_REQ to be 1 */ | ||
| 321 | value = cdns_imx_readl(data, USB3_INT_REG); | ||
| 322 | ret = readl_poll_timeout(data->noncore + USB3_INT_REG, value, | ||
| 323 | (value & CLK_125_REQ) == CLK_125_REQ, | ||
| 324 | 10, 100000); | ||
| 325 | if (ret) | ||
| 326 | dev_warn(parent, "wait CLK_125_REQ timeout\n"); | ||
| 327 | |||
| 328 | /* wait for mdctrl_clk_status is cleared */ | ||
| 329 | value = cdns_imx_readl(data, USB3_CORE_STATUS); | ||
| 330 | ret = readl_poll_timeout(data->noncore + USB3_CORE_STATUS, value, | ||
| 331 | (value & MDCTRL_CLK_STATUS) != MDCTRL_CLK_STATUS, | ||
| 332 | 10, 100000); | ||
| 333 | if (ret) | ||
| 334 | dev_warn(parent, "wait mdctrl_clk_status cleared timeout\n"); | ||
| 335 | |||
| 336 | /* Wait until OTG_NRDY is 0 */ | ||
| 337 | value = readl(otg_regs + OTGSTS); | ||
| 338 | ret = readl_poll_timeout(otg_regs + OTGSTS, value, | ||
| 339 | (value & OTG_NRDY) != OTG_NRDY, | ||
| 340 | 10, 100000); | ||
| 341 | if (ret) | ||
| 342 | dev_warn(parent, "wait OTG ready timeout\n"); | ||
| 343 | } | ||
| 344 | |||
| 345 | return ret; | ||
| 346 | |||
| 347 | } | ||
| 348 | |||
| 349 | static int cdns_imx_resume(struct device *dev) | ||
| 350 | { | ||
| 351 | struct cdns_imx *data = dev_get_drvdata(dev); | ||
| 352 | |||
| 353 | return clk_bulk_prepare_enable(data->num_clks, data->clks); | ||
| 354 | } | ||
| 355 | |||
| 356 | static int cdns_imx_suspend(struct device *dev) | ||
| 357 | { | ||
| 358 | struct cdns_imx *data = dev_get_drvdata(dev); | ||
| 359 | |||
| 360 | clk_bulk_disable_unprepare(data->num_clks, data->clks); | ||
| 361 | |||
| 362 | return 0; | ||
| 363 | } | ||
| 364 | #else | ||
| 365 | static int cdns_imx_platform_suspend(struct device *dev, | ||
| 366 | bool suspend, bool wakeup) | ||
| 367 | { | ||
| 368 | return 0; | ||
| 369 | } | ||
| 370 | |||
| 371 | #endif /* CONFIG_PM */ | ||
| 372 | |||
| 373 | static const struct dev_pm_ops cdns_imx_pm_ops = { | ||
| 374 | SET_RUNTIME_PM_OPS(cdns_imx_suspend, cdns_imx_resume, NULL) | ||
| 375 | }; | ||
| 376 | |||
| 197 | static const struct of_device_id cdns_imx_of_match[] = { | 377 | static const struct of_device_id cdns_imx_of_match[] = { |
| 198 | { .compatible = "fsl,imx8qm-usb3", }, | 378 | { .compatible = "fsl,imx8qm-usb3", }, |
| 199 | {}, | 379 | {}, |
| @@ -206,6 +386,7 @@ static struct platform_driver cdns_imx_driver = { · 6 unmodified lines | |||
| 206 | .driver = { | 386 | .driver = { |
| 207 | .name = "cdns3-imx", | 387 | .name = "cdns3-imx", |
| 208 | .of_match_table = cdns_imx_of_match, | 388 | .of_match_table = cdns_imx_of_match, |
| 389 | .pm = &cdns_imx_pm_ops, | ||
| 209 | }, | 390 | }, |
| 210 | }; | 391 | }; |
| 211 | module_platform_driver(cdns_imx_driver); | 392 | module_platform_driver(cdns_imx_driver); |
| @@ -280,6 +280,10 @@ int cdns3_hw_role_switch(struct cdns3 *cdns) · 279 unmodified lines | |||
| 280 | enum usb_role real_role, current_role; | 280 | enum usb_role real_role, current_role; |
| 281 | int ret = 0; | 281 | int ret = 0; |
| 282 | 282 | ||
| 283 | /* Depends on role switch class */ | ||
| 284 | if (cdns->role_sw) | ||
| 285 | return 0; | ||
| 286 | |||
| 283 | pm_runtime_get_sync(cdns->dev); | 287 | pm_runtime_get_sync(cdns->dev); |
| 284 | 288 | ||
| 285 | current_role = cdns->role; | 289 | current_role = cdns->role; |
| @@ -371,6 +375,50 @@ pm_put: · 85 unmodified lines | |||
| 371 | return ret; | 375 | return ret; |
| 372 | } | 376 | } |
| 373 | 377 | ||
| 378 | static int set_phy_power_on(struct cdns3 *cdns) | ||
| 379 | { | ||
| 380 | int ret; | ||
| 381 | |||
| 382 | ret = phy_power_on(cdns->usb2_phy); | ||
| 383 | if (ret) | ||
| 384 | return ret; | ||
| 385 | |||
| 386 | ret = phy_power_on(cdns->usb3_phy); | ||
| 387 | if (ret) | ||
| 388 | phy_power_off(cdns->usb2_phy); | ||
| 389 | |||
| 390 | return ret; | ||
| 391 | } | ||
| 392 | |||
| 393 | static void set_phy_power_off(struct cdns3 *cdns) | ||
| 394 | { | ||
| 395 | phy_power_off(cdns->usb3_phy); | ||
| 396 | phy_power_off(cdns->usb2_phy); | ||
| 397 | } | ||
| 398 | |||
| 399 | /** | ||
| 400 | * cdns3_wakeup_irq - interrupt handler for wakeup events | ||
| 401 | * @irq: irq number for cdns3 core device | ||
| 402 | * @data: structure of cdns3 | ||
| 403 | * | ||
| 404 | * Returns IRQ_HANDLED or IRQ_NONE | ||
| 405 | */ | ||
| 406 | static irqreturn_t cdns3_wakeup_irq(int irq, void *data) | ||
| 407 | { | ||
| 408 | struct cdns3 *cdns = data; | ||
| 409 | |||
| 410 | if (cdns->in_lpm) { | ||
| 411 | disable_irq_nosync(irq); | ||
| 412 | cdns->wakeup_pending = true; | ||
| 413 | if ((cdns->role == USB_ROLE_HOST) && cdns->host_dev) | ||
| 414 | pm_request_resume(&cdns->host_dev->dev); | ||
| 415 | |||
| 416 | return IRQ_HANDLED; | ||
| 417 | } | ||
| 418 | |||
| 419 | return IRQ_NONE; | ||
| 420 | } | ||
| 421 | |||
| 374 | /** | 422 | /** |
| 375 | * cdns3_probe - probe for cdns3 core device | 423 | * cdns3_probe - probe for cdns3 core device |
| 376 | * @pdev: Pointer to cdns3 core platform device | 424 | * @pdev: Pointer to cdns3 core platform device |
| @@ -397,6 +445,7 @@ static int cdns3_probe(struct platform_device *pdev) · 20 unmodified lines | |||
| 397 | return -ENOMEM; | 445 | return -ENOMEM; |
| 398 | 446 | ||
| 399 | cdns->dev = dev; | 447 | cdns->dev = dev; |
| 448 | cdns->pdata = dev_get_platdata(dev); | ||
| 400 | 449 | ||
| 401 | platform_set_drvdata(pdev, cdns); | 450 | platform_set_drvdata(pdev, cdns); |
| 402 | 451 | ||
| @@ -443,8 +492,21 @@ static int cdns3_probe(struct platform_device *pdev) · 40 unmodified lines | |||
| 443 | return -ENXIO; | 492 | return -ENXIO; |
| 444 | } | 493 | } |
| 445 | 494 | ||
| 495 | cdns->phyrst_a_enable = device_property_read_bool(dev, "cdns,phyrst-a-enable"); | ||
| 496 | |||
| 446 | cdns->otg_res = *res; | 497 | cdns->otg_res = *res; |
| 447 | 498 | ||
| 499 | cdns->wakeup_irq = platform_get_irq_byname_optional(pdev, "wakeup"); | ||
| 500 | if (cdns->wakeup_irq == -EPROBE_DEFER) | ||
| 501 | return cdns->wakeup_irq; | ||
| 502 | else if (cdns->wakeup_irq == 0) | ||
| 503 | return -EINVAL; | ||
| 504 | |||
| 505 | if (cdns->wakeup_irq < 0) { | ||
| 506 | dev_dbg(dev, "couldn't get wakeup irq\n"); | ||
| 507 | cdns->wakeup_irq = 0x0; | ||
| 508 | } | ||
| 509 | |||
| 448 | mutex_init(&cdns->mutex); | 510 | mutex_init(&cdns->mutex); |
| 449 | 511 | ||
| 450 | cdns->usb2_phy = devm_phy_optional_get(dev, "cdns3,usb2-phy"); | 512 | cdns->usb2_phy = devm_phy_optional_get(dev, "cdns3,usb2-phy"); |
| @@ -463,14 +525,10 @@ static int cdns3_probe(struct platform_device *pdev) · 12 unmodified lines | |||
| 463 | if (ret) | 525 | if (ret) |
| 464 | goto err1; | 526 | goto err1; |
| 465 | 527 | ||
| 466 | ret = phy_power_on(cdns->usb2_phy); | 528 | ret = set_phy_power_on(cdns); |
| 467 | if (ret) | 529 | if (ret) |
| 468 | goto err2; | 530 | goto err2; |
| 469 | 531 | ||
| 470 | ret = phy_power_on(cdns->usb3_phy); | ||
| 471 | if (ret) | ||
| 472 | goto err3; | ||
| 473 | |||
| 474 | sw_desc.set = cdns3_role_set; | 532 | sw_desc.set = cdns3_role_set; |
| 475 | sw_desc.get = cdns3_role_get; | 533 | sw_desc.get = cdns3_role_get; |
| 476 | sw_desc.allow_userspace_control = true; | 534 | sw_desc.allow_userspace_control = true; |
| @@ -482,20 +540,34 @@ static int cdns3_probe(struct platform_device *pdev) · 5 unmodified lines | |||
| 482 | if (IS_ERR(cdns->role_sw)) { | 540 | if (IS_ERR(cdns->role_sw)) { |
| 483 | ret = PTR_ERR(cdns->role_sw); | 541 | ret = PTR_ERR(cdns->role_sw); |
| 484 | dev_warn(dev, "Unable to register Role Switch\n"); | 542 | dev_warn(dev, "Unable to register Role Switch\n"); |
| 485 | goto err4; | 543 | goto err3; |
| 544 | } | ||
| 545 | |||
| 546 | if (cdns->wakeup_irq) { | ||
| 547 | ret = devm_request_irq(cdns->dev, cdns->wakeup_irq, | ||
| 548 | cdns3_wakeup_irq, | ||
| 549 | IRQF_SHARED, | ||
| 550 | dev_name(cdns->dev), cdns); | ||
| 551 | |||
| 552 | if (ret) { | ||
| 553 | dev_err(cdns->dev, "couldn't register wakeup irq handler\n"); | ||
| 554 | goto err3; | ||
| 555 | } | ||
| 486 | } | 556 | } |
| 487 | 557 | ||
| 488 | ret = cdns3_drd_init(cdns); | 558 | ret = cdns3_drd_init(cdns); |
| 489 | if (ret) | 559 | if (ret) |
| 490 | goto err5; | 560 | goto err4; |
| 491 | 561 | ||
| 492 | ret = cdns3_core_init_role(cdns); | 562 | ret = cdns3_core_init_role(cdns); |
| 493 | if (ret) | 563 | if (ret) |
| 494 | goto err5; | 564 | goto err4; |
| 495 | 565 | ||
| 566 | spin_lock_init(&cdns->lock); | ||
| 496 | device_set_wakeup_capable(dev, true); | 567 | device_set_wakeup_capable(dev, true); |
| 497 | pm_runtime_set_active(dev); | 568 | pm_runtime_set_active(dev); |
| 498 | pm_runtime_enable(dev); | 569 | pm_runtime_enable(dev); |
| 570 | pm_runtime_forbid(dev); | ||
| 499 | 571 | ||
| 500 | /* | 572 | /* |
| 501 | * The controller needs less time between bus and controller suspend, | 573 | * The controller needs less time between bus and controller suspend, |
| @@ -508,14 +580,11 @@ static int cdns3_probe(struct platform_device *pdev) · 6 unmodified lines | |||
| 508 | dev_dbg(dev, "Cadence USB3 core: probe succeed\n"); | 580 | dev_dbg(dev, "Cadence USB3 core: probe succeed\n"); |
| 509 | 581 | ||
| 510 | return 0; | 582 | return 0; |
| 511 | err5: | 583 | err4: |
| 512 | cdns3_drd_exit(cdns); | 584 | cdns3_drd_exit(cdns); |
| 513 | usb_role_switch_unregister(cdns->role_sw); | 585 | usb_role_switch_unregister(cdns->role_sw); |
| 514 | err4: | ||
| 515 | phy_power_off(cdns->usb3_phy); | ||
| 516 | |||
| 517 | err3: | 586 | err3: |
| 518 | phy_power_off(cdns->usb2_phy); | 587 | set_phy_power_off(cdns); |
| 519 | err2: | 588 | err2: |
| 520 | phy_exit(cdns->usb3_phy); | 589 | phy_exit(cdns->usb3_phy); |
| 521 | err1: | 590 | err1: |
| @@ -539,59 +608,128 @@ static int cdns3_remove(struct platform_device *pdev) · 17 unmodified lines | |||
| 539 | pm_runtime_put_noidle(&pdev->dev); | 608 | pm_runtime_put_noidle(&pdev->dev); |
| 540 | cdns3_exit_roles(cdns); | 609 | cdns3_exit_roles(cdns); |
| 541 | usb_role_switch_unregister(cdns->role_sw); | 610 | usb_role_switch_unregister(cdns->role_sw); |
| 542 | phy_power_off(cdns->usb2_phy); | 611 | set_phy_power_off(cdns); |
| 543 | phy_power_off(cdns->usb3_phy); | ||
| 544 | phy_exit(cdns->usb2_phy); | 612 | phy_exit(cdns->usb2_phy); |
| 545 | phy_exit(cdns->usb3_phy); | 613 | phy_exit(cdns->usb3_phy); |
| 546 | return 0; | 614 | return 0; |
| 547 | } | 615 | } |
| 548 | 616 | ||
| 549 | #ifdef CONFIG_PM_SLEEP | 617 | #ifdef CONFIG_PM |
| 550 | 618 | ||
| 551 | static int cdns3_suspend(struct device *dev) | 619 | static int cdns3_set_platform_suspend(struct device *dev, |
| 620 | bool suspend, bool wakeup) | ||
| 621 | { | ||
| 622 | struct cdns3 *cdns = dev_get_drvdata(dev); | ||
| 623 | int ret = 0; | ||
| 624 | |||
| 625 | if (cdns->pdata && cdns->pdata->platform_suspend) | ||
| 626 | ret = cdns->pdata->platform_suspend(dev, suspend, wakeup); | ||
| 627 | |||
| 628 | return ret; | ||
| 629 | } | ||
| 630 | |||
| 631 | static int cdns3_controller_suspend(struct device *dev, pm_message_t msg) | ||
| 552 | { | 632 | { |
| 553 | struct cdns3 *cdns = dev_get_drvdata(dev); | 633 | struct cdns3 *cdns = dev_get_drvdata(dev); |
| 634 | bool wakeup; | ||
| 554 | unsigned long flags; | 635 | unsigned long flags; |
| 555 | 636 | ||
| 556 | if (cdns->role == USB_ROLE_HOST) | 637 | if (cdns->in_lpm) |
| 557 | return 0; | 638 | return 0; |
| 558 | 639 | ||
| 559 | if (pm_runtime_status_suspended(dev)) | 640 | if (PMSG_IS_AUTO(msg)) |
| 560 | pm_runtime_resume(dev); | 641 | wakeup = true; |
| 642 | else | ||
| 643 | wakeup = device_may_wakeup(dev); | ||
| 561 | 644 | ||
| 562 | if (cdns->roles[cdns->role]->suspend) { | 645 | cdns3_set_platform_suspend(cdns->dev, true, wakeup); |
| 563 | spin_lock_irqsave(&cdns->gadget_dev->lock, flags); | 646 | set_phy_power_off(cdns); |
| 564 | cdns->roles[cdns->role]->suspend(cdns, false); | 647 | spin_lock_irqsave(&cdns->lock, flags); |
| 565 | spin_unlock_irqrestore(&cdns->gadget_dev->lock, flags); | 648 | cdns->in_lpm = true; |
| 566 | } | 649 | spin_unlock_irqrestore(&cdns->lock, flags); |
| 650 | dev_dbg(cdns->dev, "%s ends\n", __func__); | ||
| 567 | 651 | ||
| 568 | return 0; | 652 | return 0; |
| 569 | } | 653 | } |
| 570 | 654 | ||
| 571 | static int cdns3_resume(struct device *dev) | 655 | static int cdns3_controller_resume(struct device *dev, pm_message_t msg) |
| 572 | { | 656 | { |
| 573 | struct cdns3 *cdns = dev_get_drvdata(dev); | 657 | struct cdns3 *cdns = dev_get_drvdata(dev); |
| 658 | int ret; | ||
| 574 | unsigned long flags; | 659 | unsigned long flags; |
| 575 | 660 | ||
| 576 | if (cdns->role == USB_ROLE_HOST) | 661 | if (!cdns->in_lpm) |
| 577 | return 0; | 662 | return 0; |
| 578 | 663 | ||
| 579 | if (cdns->roles[cdns->role]->resume) { | 664 | ret = set_phy_power_on(cdns); |
| 580 | spin_lock_irqsave(&cdns->gadget_dev->lock, flags); | 665 | if (ret) |
| 666 | return ret; | ||
| 667 | |||
| 668 | cdns3_set_platform_suspend(cdns->dev, false, false); | ||
| 669 | |||
| 670 | spin_lock_irqsave(&cdns->lock, flags); | ||
| 671 | if (cdns->roles[cdns->role]->resume && !PMSG_IS_AUTO(msg)) | ||
| 581 | cdns->roles[cdns->role]->resume(cdns, false); | 672 | cdns->roles[cdns->role]->resume(cdns, false); |
| 582 | spin_unlock_irqrestore(&cdns->gadget_dev->lock, flags); | 673 | |
| 674 | cdns->in_lpm = false; | ||
| 675 | spin_unlock_irqrestore(&cdns->lock, flags); | ||
| 676 | if (cdns->wakeup_pending) { | ||
| 677 | cdns->wakeup_pending = false; | ||
| 678 | enable_irq(cdns->wakeup_irq); | ||
| 679 | } | ||
| 680 | dev_dbg(cdns->dev, "%s ends\n", __func__); | ||
| 681 | |||
| 682 | return ret; | ||
| 683 | } | ||
| 684 | |||
| 685 | static int cdns3_runtime_suspend(struct device *dev) | ||
| 686 | { | ||
| 687 | return cdns3_controller_suspend(dev, PMSG_AUTO_SUSPEND); | ||
| 688 | } | ||
| 689 | |||
| 690 | static int cdns3_runtime_resume(struct device *dev) | ||
| 691 | { | ||
| 692 | return cdns3_controller_resume(dev, PMSG_AUTO_RESUME); | ||
| 693 | } | ||
| 694 | #ifdef CONFIG_PM_SLEEP | ||
| 695 | |||
| 696 | static int cdns3_suspend(struct device *dev) | ||
| 697 | { | ||
| 698 | struct cdns3 *cdns = dev_get_drvdata(dev); | ||
| 699 | unsigned long flags; | ||
| 700 | |||
| 701 | if (pm_runtime_status_suspended(dev)) | ||
| 702 | pm_runtime_resume(dev); | ||
| 703 | |||
| 704 | if (cdns->roles[cdns->role]->suspend) { | ||
| 705 | spin_lock_irqsave(&cdns->lock, flags); | ||
| 706 | cdns->roles[cdns->role]->suspend(cdns, false); | ||
| 707 | spin_unlock_irqrestore(&cdns->lock, flags); | ||
| 583 | } | 708 | } |
| 584 | 709 | ||
| 710 | return cdns3_controller_suspend(dev, PMSG_SUSPEND); | ||
| 711 | } | ||
| 712 | |||
| 713 | static int cdns3_resume(struct device *dev) | ||
| 714 | { | ||
| 715 | int ret; | ||
| 716 | |||
| 717 | ret = cdns3_controller_resume(dev, PMSG_RESUME); | ||
| 718 | if (ret) | ||
| 719 | return ret; | ||
| 720 | |||
| 585 | pm_runtime_disable(dev); | 721 | pm_runtime_disable(dev); |
| 586 | pm_runtime_set_active(dev); | 722 | pm_runtime_set_active(dev); |
| 587 | pm_runtime_enable(dev); | 723 | pm_runtime_enable(dev); |
| 588 | 724 | ||
| 589 | return 0; | 725 | return ret; |
| 590 | } | 726 | } |
| 591 | #endif | 727 | #endif /* CONFIG_PM_SLEEP */ |
| 728 | #endif /* CONFIG_PM */ | ||
| 592 | 729 | ||
| 593 | static const struct dev_pm_ops cdns3_pm_ops = { | 730 | static const struct dev_pm_ops cdns3_pm_ops = { |
| 594 | SET_SYSTEM_SLEEP_PM_OPS(cdns3_suspend, cdns3_resume) | 731 | SET_SYSTEM_SLEEP_PM_OPS(cdns3_suspend, cdns3_resume) |
| 732 | SET_RUNTIME_PM_OPS(cdns3_runtime_suspend, cdns3_runtime_resume, NULL) | ||
| 595 | }; | 733 | }; |
| 596 | 734 | ||
| 597 | #ifdef CONFIG_OF | 735 | #ifdef CONFIG_OF |
| @@ -38,6 +38,12 @@ struct cdns3_role_driver { · 37 unmodified lines | |||
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| 40 | #define CDNS3_XHCI_RESOURCES_NUM 2 | 40 | #define CDNS3_XHCI_RESOURCES_NUM 2 |
| 41 | |||
| 42 | struct cdns3_platform_data { | ||
| 43 | int (*platform_suspend)(struct device *dev, | ||
| 44 | bool suspend, bool wakeup); | ||
| 45 | }; | ||
| 46 | |||
| 41 | /** | 47 | /** |
| 42 | * struct cdns3 - Representation of Cadence USB3 DRD controller. | 48 | * struct cdns3 - Representation of Cadence USB3 DRD controller. |
| 43 | * @dev: pointer to Cadence device struct | 49 | * @dev: pointer to Cadence device struct |
| @@ -50,6 +56,7 @@ struct cdns3_role_driver { · 6 unmodified lines | |||
| 50 | * @otg_regs: pointer to base of otg registers | 56 | * @otg_regs: pointer to base of otg registers |
| 51 | * @otg_irq: irq number for otg controller | 57 | * @otg_irq: irq number for otg controller |
| 52 | * @dev_irq: irq number for device controller | 58 | * @dev_irq: irq number for device controller |
| 59 | * @wakeup_irq: irq number for wakeup event, it is optional | ||
| 53 | * @roles: array of supported roles for this controller | 60 | * @roles: array of supported roles for this controller |
| 54 | * @role: current role | 61 | * @role: current role |
| 55 | * @host_dev: the child host device pointer for cdns3 core | 62 | * @host_dev: the child host device pointer for cdns3 core |
| @@ -62,6 +69,10 @@ struct cdns3_role_driver { · 6 unmodified lines | |||
| 62 | * This field based on firmware setting, kernel configuration | 69 | * This field based on firmware setting, kernel configuration |
| 63 | * and hardware configuration. | 70 | * and hardware configuration. |
| 64 | * @role_sw: pointer to role switch object. | 71 | * @role_sw: pointer to role switch object. |
| 72 | * @in_lpm: indicate the controller is in low power mode | ||
| 73 | * @wakeup_pending: wakeup interrupt pending | ||
| 74 | * @pdata: platform data from glue layer | ||
| 75 | * @lock: spinlock structure | ||
| 65 | */ | 76 | */ |
| 66 | struct cdns3 { | 77 | struct cdns3 { |
| 67 | struct device *dev; | 78 | struct device *dev; |
| @@ -76,9 +87,11 @@ struct cdns3 { · 8 unmodified lines | |||
| 76 | #define CDNS3_CONTROLLER_V0 0 | 87 | #define CDNS3_CONTROLLER_V0 0 |
| 77 | #define CDNS3_CONTROLLER_V1 1 | 88 | #define CDNS3_CONTROLLER_V1 1 |
| 78 | u32 version; | 89 | u32 version; |
| 90 | bool phyrst_a_enable; | ||
| 79 | 91 | ||
| 80 | int otg_irq; | 92 | int otg_irq; |
| 81 | int dev_irq; | 93 | int dev_irq; |
| 94 | int wakeup_irq; | ||
| 82 | struct cdns3_role_driver *roles[USB_ROLE_DEVICE + 1]; | 95 | struct cdns3_role_driver *roles[USB_ROLE_DEVICE + 1]; |
| 83 | enum usb_role role; | 96 | enum usb_role role; |
| 84 | struct platform_device *host_dev; | 97 | struct platform_device *host_dev; |
| @@ -89,6 +102,10 @@ struct cdns3 { · 4 unmodified lines | |||
| 89 | struct mutex mutex; | 102 | struct mutex mutex; |
| 90 | enum usb_dr_mode dr_mode; | 103 | enum usb_dr_mode dr_mode; |
| 91 | struct usb_role_switch *role_sw; | 104 | struct usb_role_switch *role_sw; |
| 105 | bool in_lpm; | ||
| 106 | bool wakeup_pending; | ||
| 107 | struct cdns3_platform_data *pdata; | ||
| 108 | spinlock_t lock; | ||
| 92 | }; | 109 | }; |
| 93 | 110 | ||
| 94 | int cdns3_hw_role_switch(struct cdns3 *cdns); | 111 | int cdns3_hw_role_switch(struct cdns3 *cdns); |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | |||
| 15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
| 16 | #include <linux/iopoll.h> | 16 | #include <linux/iopoll.h> |
| 17 | #include <linux/usb/otg.h> | 17 | #include <linux/usb/otg.h> |
| 18 | #include <linux/phy/phy.h> | ||
| 18 | 19 | ||
| 19 | #include "gadget.h" | 20 | #include "gadget.h" |
| 20 | #include "drd.h" | 21 | #include "drd.h" |
| @@ -42,6 +43,18 @@ int cdns3_set_mode(struct cdns3 *cdns, enum usb_dr_mode mode) · 21 unmodified lines | |||
| 42 | reg = readl(&cdns->otg_v1_regs->override); | 43 | reg = readl(&cdns->otg_v1_regs->override); |
| 43 | reg |= OVERRIDE_IDPULLUP; | 44 | reg |= OVERRIDE_IDPULLUP; |
| 44 | writel(reg, &cdns->otg_v1_regs->override); | 45 | writel(reg, &cdns->otg_v1_regs->override); |
| 46 | |||
| 47 | /* | ||
| 48 | * Enable work around feature built into the | ||
| 49 | * controller to address issue with RX Sensitivity | ||
| 50 | * est (EL_17) for USB2 PHY. The issue only occures | ||
| 51 | * for 0x0002450D controller version. | ||
| 52 | */ | ||
| 53 | if (cdns->phyrst_a_enable) { | ||
| 54 | reg = readl(&cdns->otg_v1_regs->phyrst_cfg); | ||
| 55 | reg |= PHYRST_CFG_PHYRST_A_ENABLE; | ||
| 56 | writel(reg, &cdns->otg_v1_regs->phyrst_cfg); | ||
| 57 | } | ||
| 45 | } else { | 58 | } else { |
| 46 | reg = readl(&cdns->otg_v0_regs->ctrl1); | 59 | reg = readl(&cdns->otg_v0_regs->ctrl1); |
| 47 | reg |= OVERRIDE_IDPULLUP_V0; | 60 | reg |= OVERRIDE_IDPULLUP_V0; |
| @@ -145,6 +158,7 @@ int cdns3_drd_host_on(struct cdns3 *cdns) · 97 unmodified lines | |||
| 145 | if (ret) | 158 | if (ret) |
| 146 | dev_err(cdns->dev, "timeout waiting for xhci_ready\n"); | 159 | dev_err(cdns->dev, "timeout waiting for xhci_ready\n"); |
| 147 | 160 | ||
| 161 | phy_set_mode(cdns->usb3_phy, PHY_MODE_USB_HOST); | ||
| 148 | return ret; | 162 | return ret; |
| 149 | } | 163 | } |
| 150 | 164 | ||
| @@ -164,6 +178,7 @@ void cdns3_drd_host_off(struct cdns3 *cdns) · 13 unmodified lines | |||
| 164 | readl_poll_timeout_atomic(&cdns->otg_regs->state, val, | 178 | readl_poll_timeout_atomic(&cdns->otg_regs->state, val, |
| 165 | !(val & OTGSTATE_HOST_STATE_MASK), | 179 | !(val & OTGSTATE_HOST_STATE_MASK), |
| 166 | 1, 2000000); | 180 | 1, 2000000); |
| 181 | phy_set_mode(cdns->usb3_phy, PHY_MODE_INVALID); | ||
| 167 | } | 182 | } |
| 168 | 183 | ||
| 169 | /** | 184 | /** |
| @@ -190,6 +205,7 @@ int cdns3_drd_gadget_on(struct cdns3 *cdns) · 20 unmodified lines | |||
| 190 | return ret; | 205 | return ret; |
| 191 | } | 206 | } |
| 192 | 207 | ||
| 208 | phy_set_mode(cdns->usb3_phy, PHY_MODE_USB_DEVICE); | ||
| 193 | return 0; | 209 | return 0; |
| 194 | } | 210 | } |
| 195 | 211 | ||
| @@ -213,6 +229,7 @@ void cdns3_drd_gadget_off(struct cdns3 *cdns) · 17 unmodified lines | |||
| 213 | readl_poll_timeout_atomic(&cdns->otg_regs->state, val, | 229 | readl_poll_timeout_atomic(&cdns->otg_regs->state, val, |
| 214 | !(val & OTGSTATE_DEV_STATE_MASK), | 230 | !(val & OTGSTATE_DEV_STATE_MASK), |
| 215 | 1, 2000000); | 231 | 1, 2000000); |
| 232 | phy_set_mode(cdns->usb3_phy, PHY_MODE_INVALID); | ||
| 216 | } | 233 | } |
| 217 | 234 | ||
| 218 | /** | 235 | /** |
| @@ -293,6 +310,9 @@ static irqreturn_t cdns3_drd_irq(int irq, void *data) · 74 unmodified lines | |||
| 293 | if (cdns->dr_mode != USB_DR_MODE_OTG) | 310 | if (cdns->dr_mode != USB_DR_MODE_OTG) |
| 294 | return IRQ_NONE; | 311 | return IRQ_NONE; |
| 295 | 312 | ||
| 313 | if (cdns->in_lpm) | ||
| 314 | return ret; | ||
| 315 | |||
| 296 | reg = readl(&cdns->otg_regs->ivect); | 316 | reg = readl(&cdns->otg_regs->ivect); |
| 297 | 317 | ||
| 298 | if (!reg) | 318 | if (!reg) |
| @@ -31,7 +31,7 @@ struct cdns3_otg_regs { · 30 unmodified lines | |||
| 31 | __le32 simulate; | 31 | __le32 simulate; |
| 32 | __le32 override; | 32 | __le32 override; |
| 33 | __le32 susp_ctrl; | 33 | __le32 susp_ctrl; |
| 34 | __le32 reserved4; | 34 | __le32 phyrst_cfg; |
| 35 | __le32 anasts; | 35 | __le32 anasts; |
| 36 | __le32 adp_ramp_time; | 36 | __le32 adp_ramp_time; |
| 37 | __le32 ctrl1; | 37 | __le32 ctrl1; |
| @@ -153,6 +153,9 @@ struct cdns3_otg_common_regs { · 115 unmodified lines | |||
| 153 | /* Only for CDNS3_CONTROLLER_V0 version */ | 153 | /* Only for CDNS3_CONTROLLER_V0 version */ |
| 154 | #define OVERRIDE_IDPULLUP_V0 BIT(24) | 154 | #define OVERRIDE_IDPULLUP_V0 BIT(24) |
| 155 | 155 | ||
| 156 | /* PHYRST_CFG - bitmasks */ | ||
| 157 | #define PHYRST_CFG_PHYRST_A_ENABLE BIT(0) | ||
| 158 | |||
| 156 | #define CDNS3_ID_PERIPHERAL 1 | 159 | #define CDNS3_ID_PERIPHERAL 1 |
| 157 | #define CDNS3_ID_HOST 0 | 160 | #define CDNS3_ID_HOST 0 |
| 158 | 161 | ||
| @@ -717,9 +717,17 @@ static int cdns3_gadget_ep0_queue(struct usb_ep *ep, · 716 unmodified lines | |||
| 717 | 717 | ||
| 718 | /* send STATUS stage. Should be called only for SET_CONFIGURATION */ | 718 | /* send STATUS stage. Should be called only for SET_CONFIGURATION */ |
| 719 | if (priv_dev->ep0_stage == CDNS3_STATUS_STAGE) { | 719 | if (priv_dev->ep0_stage == CDNS3_STATUS_STAGE) { |
| 720 | u32 val; | ||
| 721 | |||
| 720 | cdns3_select_ep(priv_dev, 0x00); | 722 | cdns3_select_ep(priv_dev, 0x00); |
| 721 | cdns3_set_hw_configuration(priv_dev); | 723 | cdns3_set_hw_configuration(priv_dev); |
| 722 | cdns3_ep0_complete_setup(priv_dev, 0, 1); | 724 | cdns3_ep0_complete_setup(priv_dev, 0, 1); |
| 725 | /* wait until configuration set */ | ||
| 726 | ret = readl_poll_timeout_atomic(&priv_dev->regs->usb_sts, val, | ||
| 727 | val & USB_STS_CFGSTS_MASK, 1, 100); | ||
| 728 | if (ret == -ETIMEDOUT) | ||
| 729 | dev_warn(priv_dev->dev, "timeout for waiting configuration set\n"); | ||
| 730 | |||
| 723 | request->actual = 0; | 731 | request->actual = 0; |
| 724 | priv_dev->status_completion_no_call = true; | 732 | priv_dev->status_completion_no_call = true; |
| 725 | priv_dev->pending_status_request = request; | 733 | priv_dev->pending_status_request = request; |
| @@ -731,7 +739,7 @@ static int cdns3_gadget_ep0_queue(struct usb_ep *ep, · 5 unmodified lines | |||
| 731 | * ep0_queue is back. | 739 | * ep0_queue is back. |
| 732 | */ | 740 | */ |
| 733 | queue_work(system_freezable_wq, &priv_dev->pending_status_wq); | 741 | queue_work(system_freezable_wq, &priv_dev->pending_status_wq); |
| 734 | return 0; | 742 | return ret; |
| 735 | } | 743 | } |
| 736 | 744 | ||
| 737 | if (!list_empty(&priv_ep->pending_req_list)) { | 745 | if (!list_empty(&priv_ep->pending_req_list)) { |
| @@ -261,8 +261,8 @@ int cdns3_allocate_trb_pool(struct cdns3_endpoint *priv_ep) · 260 unmodified lines | |||
| 261 | */ | 261 | */ |
| 262 | link_trb->control = 0; | 262 | link_trb->control = 0; |
| 263 | } else { | 263 | } else { |
| 264 | link_trb->buffer = TRB_BUFFER(priv_ep->trb_pool_dma); | 264 | link_trb->buffer = cpu_to_le32(TRB_BUFFER(priv_ep->trb_pool_dma)); |
| 265 | link_trb->control = TRB_CYCLE | TRB_TYPE(TRB_LINK) | TRB_TOGGLE; | 265 | link_trb->control = cpu_to_le32(TRB_CYCLE | TRB_TYPE(TRB_LINK) | TRB_TOGGLE); |
| 266 | } | 266 | } |
| 267 | return 0; | 267 | return 0; |
| 268 | } | 268 | } |
| @@ -462,6 +462,36 @@ static int cdns3_start_all_request(struct cdns3_device *priv_dev, · 193 unmodified lines | |||
| 462 | (reg) |= EP_STS_EN_DESCMISEN; \ | 462 | (reg) |= EP_STS_EN_DESCMISEN; \ |
| 463 | } } while (0) | 463 | } } while (0) |
| 464 | 464 | ||
| 465 | static void __cdns3_descmiss_copy_data(struct usb_request *request, | ||
| 466 | struct usb_request *descmiss_req) | ||
| 467 | { | ||
| 468 | int length = request->actual + descmiss_req->actual; | ||
| 469 | struct scatterlist *s = request->sg; | ||
| 470 | |||
| 471 | if (!s) { | ||
| 472 | if (length <= request->length) { | ||
| 473 | memcpy(&((u8 *)request->buf)[request->actual], | ||
| 474 | descmiss_req->buf, | ||
| 475 | descmiss_req->actual); | ||
| 476 | request->actual = length; | ||
| 477 | } else { | ||
| 478 | /* It should never occures */ | ||
| 479 | request->status = -ENOMEM; | ||
| 480 | } | ||
| 481 | } else { | ||
| 482 | if (length <= sg_dma_len(s)) { | ||
| 483 | void *p = phys_to_virt(sg_dma_address(s)); | ||
| 484 | |||
| 485 | memcpy(&((u8 *)p)[request->actual], | ||
| 486 | descmiss_req->buf, | ||
| 487 | descmiss_req->actual); | ||
| 488 | request->actual = length; | ||
| 489 | } else { | ||
| 490 | request->status = -ENOMEM; | ||
| 491 | } | ||
| 492 | } | ||
| 493 | } | ||
| 494 | |||
| 465 | /** | 495 | /** |
| 466 | * cdns3_wa2_descmiss_copy_data copy data from internal requests to | 496 | * cdns3_wa2_descmiss_copy_data copy data from internal requests to |
| 467 | * request queued by class driver. | 497 | * request queued by class driver. |
| @@ -488,21 +518,9 @@ static void cdns3_wa2_descmiss_copy_data(struct cdns3_endpoint *priv_ep, · 20 unmodified lines | |||
| 488 | 518 | ||
| 489 | chunk_end = descmiss_priv_req->flags & REQUEST_INTERNAL_CH; | 519 | chunk_end = descmiss_priv_req->flags & REQUEST_INTERNAL_CH; |
| 490 | length = request->actual + descmiss_req->actual; | 520 | length = request->actual + descmiss_req->actual; |
| 491 | |||
| 492 | request->status = descmiss_req->status; | 521 | request->status = descmiss_req->status; |
| 493 | 522 | __cdns3_descmiss_copy_data(request, descmiss_req); | |
| 494 | if (length <= request->length) { | ||
| 495 | memcpy(&((u8 *)request->buf)[request->actual], | ||
| 496 | descmiss_req->buf, | ||
| 497 | descmiss_req->actual); | ||
| 498 | request->actual = length; | ||
| 499 | } else { | ||
| 500 | /* It should never occures */ | ||
| 501 | request->status = -ENOMEM; | ||
| 502 | } | ||
| 503 | |||
| 504 | list_del_init(&descmiss_priv_req->list); | 523 | list_del_init(&descmiss_priv_req->list); |
| 505 | |||
| 506 | kfree(descmiss_req->buf); | 524 | kfree(descmiss_req->buf); |
| 507 | cdns3_gadget_ep_free_request(&priv_ep->endpoint, descmiss_req); | 525 | cdns3_gadget_ep_free_request(&priv_ep->endpoint, descmiss_req); |
| 508 | --priv_ep->wa2_counter; | 526 | --priv_ep->wa2_counter; |
| @@ -817,6 +835,8 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep, · 308 unmodified lines | |||
| 817 | request->length); | 835 | request->length); |
| 818 | 836 | ||
| 819 | priv_req->flags &= ~(REQUEST_PENDING | REQUEST_UNALIGNED); | 837 | priv_req->flags &= ~(REQUEST_PENDING | REQUEST_UNALIGNED); |
| 838 | /* All TRBs have finished, clear the counter */ | ||
| 839 | priv_req->finished_trb = 0; | ||
| 820 | trace_cdns3_gadget_giveback(priv_req); | 840 | trace_cdns3_gadget_giveback(priv_req); |
| 821 | 841 | ||
| 822 | if (priv_dev->dev_ver < DEV_VER_V2) { | 842 | if (priv_dev->dev_ver < DEV_VER_V2) { |
| @@ -847,10 +867,10 @@ static void cdns3_wa1_restore_cycle_bit(struct cdns3_endpoint *priv_ep) · 24 unmodified lines | |||
| 847 | priv_ep->wa1_trb_index = 0xFFFF; | 867 | priv_ep->wa1_trb_index = 0xFFFF; |
| 848 | if (priv_ep->wa1_cycle_bit) { | 868 | if (priv_ep->wa1_cycle_bit) { |
| 849 | priv_ep->wa1_trb->control = | 869 | priv_ep->wa1_trb->control = |
| 850 | priv_ep->wa1_trb->control | 0x1; | 870 | priv_ep->wa1_trb->control | cpu_to_le32(0x1); |
| 851 | } else { | 871 | } else { |
| 852 | priv_ep->wa1_trb->control = | 872 | priv_ep->wa1_trb->control = |
| 853 | priv_ep->wa1_trb->control & ~0x1; | 873 | priv_ep->wa1_trb->control & cpu_to_le32(~0x1); |
| 854 | } | 874 | } |
| 855 | } | 875 | } |
| 856 | } | 876 | } |
| @@ -1008,17 +1028,16 @@ static int cdns3_ep_run_stream_transfer(struct cdns3_endpoint *priv_ep, · 151 unmodified lines | |||
| 1008 | TRB_STREAM_ID(priv_req->request.stream_id) | TRB_ISP; | 1028 | TRB_STREAM_ID(priv_req->request.stream_id) | TRB_ISP; |
| 1009 | 1029 | ||
| 1010 | if (!request->num_sgs) { | 1030 | if (!request->num_sgs) { |
| 1011 | trb->buffer = TRB_BUFFER(trb_dma); | 1031 | trb->buffer = cpu_to_le32(TRB_BUFFER(trb_dma)); |
| 1012 | length = request->length; | 1032 | length = request->length; |
| 1013 | } else { | 1033 | } else { |
| 1014 | trb->buffer = TRB_BUFFER(request->sg[sg_idx].dma_address); | 1034 | trb->buffer = cpu_to_le32(TRB_BUFFER(request->sg[sg_idx].dma_address)); |
| 1015 | length = request->sg[sg_idx].length; | 1035 | length = request->sg[sg_idx].length; |
| 1016 | } | 1036 | } |
| 1017 | 1037 | ||
| 1018 | tdl = DIV_ROUND_UP(length, priv_ep->endpoint.maxpacket); | 1038 | tdl = DIV_ROUND_UP(length, priv_ep->endpoint.maxpacket); |
| 1019 | 1039 | ||
| 1020 | trb->length = TRB_BURST_LEN(16 /*priv_ep->trb_burst_size*/) | | 1040 | trb->length = cpu_to_le32(TRB_BURST_LEN(16) | TRB_LEN(length)); |
| 1021 | TRB_LEN(length); | ||
| 1022 | 1041 | ||
| 1023 | /* | 1042 | /* |
| 1024 | * For DEV_VER_V2 controller version we have enabled | 1043 | * For DEV_VER_V2 controller version we have enabled |
| @@ -1027,11 +1046,11 @@ static int cdns3_ep_run_stream_transfer(struct cdns3_endpoint *priv_ep, · 2 unmodified lines | |||
| 1027 | */ | 1046 | */ |
| 1028 | if (priv_dev->dev_ver >= DEV_VER_V2) { | 1047 | if (priv_dev->dev_ver >= DEV_VER_V2) { |
| 1029 | if (priv_dev->gadget.speed == USB_SPEED_SUPER) | 1048 | if (priv_dev->gadget.speed == USB_SPEED_SUPER) |
| 1030 | trb->length |= TRB_TDL_SS_SIZE(tdl); | 1049 | trb->length |= cpu_to_le32(TRB_TDL_SS_SIZE(tdl)); |
| 1031 | } | 1050 | } |
| 1032 | priv_req->flags |= REQUEST_PENDING; | 1051 | priv_req->flags |= REQUEST_PENDING; |
| 1033 | 1052 | ||
| 1034 | trb->control = control; | 1053 | trb->control = cpu_to_le32(control); |
| 1035 | 1054 | ||
| 1036 | trace_cdns3_prepare_trb(priv_ep, priv_req->trb); | 1055 | trace_cdns3_prepare_trb(priv_ep, priv_req->trb); |
| 1037 | 1056 | ||
| @@ -1091,6 +1110,7 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep, · 53 unmodified lines | |||
| 1091 | struct cdns3_device *priv_dev = priv_ep->cdns3_dev; | 1110 | struct cdns3_device *priv_dev = priv_ep->cdns3_dev; |
| 1092 | struct cdns3_request *priv_req; | 1111 | struct cdns3_request *priv_req; |
| 1093 | struct cdns3_trb *trb; | 1112 | struct cdns3_trb *trb; |
| 1113 | struct cdns3_trb *link_trb; | ||
| 1094 | dma_addr_t trb_dma; | 1114 | dma_addr_t trb_dma; |
| 1095 | u32 togle_pcs = 1; | 1115 | u32 togle_pcs = 1; |
| 1096 | int sg_iter = 0; | 1116 | int sg_iter = 0; |
| @@ -1099,11 +1119,13 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep, · 2 unmodified lines | |||
| 1099 | u32 control; | 1119 | u32 control; |
| 1100 | int pcs; | 1120 | int pcs; |
| 1101 | u16 total_tdl = 0; | 1121 | u16 total_tdl = 0; |
| 1122 | struct scatterlist *s = NULL; | ||
| 1123 | bool sg_supported = !!(request->num_mapped_sgs); | ||
| 1102 | 1124 | ||
| 1103 | if (priv_ep->type == USB_ENDPOINT_XFER_ISOC) | 1125 | if (priv_ep->type == USB_ENDPOINT_XFER_ISOC) |
| 1104 | num_trb = priv_ep->interval; | 1126 | num_trb = priv_ep->interval; |
| 1105 | else | 1127 | else |
| 1106 | num_trb = request->num_sgs ? request->num_sgs : 1; | 1128 | num_trb = sg_supported ? request->num_mapped_sgs : 1; |
| 1107 | 1129 | ||
| 1108 | if (num_trb > priv_ep->free_trbs) { | 1130 | if (num_trb > priv_ep->free_trbs) { |
| 1109 | priv_ep->flags |= EP_RING_FULL; | 1131 | priv_ep->flags |= EP_RING_FULL; |
| @@ -1129,7 +1151,6 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep, · 19 unmodified lines | |||
| 1129 | 1151 | ||
| 1130 | /* prepare ring */ | 1152 | /* prepare ring */ |
| 1131 | if ((priv_ep->enqueue + num_trb) >= (priv_ep->num_trbs - 1)) { | 1153 | if ((priv_ep->enqueue + num_trb) >= (priv_ep->num_trbs - 1)) { |
| 1132 | struct cdns3_trb *link_trb; | ||
| 1133 | int doorbell, dma_index; | 1154 | int doorbell, dma_index; |
| 1134 | u32 ch_bit = 0; | 1155 | u32 ch_bit = 0; |
| 1135 | 1156 | ||
| @@ -1156,13 +1177,16 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep, · 20 unmodified lines | |||
| 1156 | TRBS_PER_SEGMENT > 2) | 1177 | TRBS_PER_SEGMENT > 2) |
| 1157 | ch_bit = TRB_CHAIN; | 1178 | ch_bit = TRB_CHAIN; |
| 1158 | 1179 | ||
| 1159 | link_trb->control = ((priv_ep->pcs) ? TRB_CYCLE : 0) | | 1180 | link_trb->control = cpu_to_le32(((priv_ep->pcs) ? TRB_CYCLE : 0) | |
| 1160 | TRB_TYPE(TRB_LINK) | TRB_TOGGLE | ch_bit; | 1181 | TRB_TYPE(TRB_LINK) | TRB_TOGGLE | ch_bit); |
| 1161 | } | 1182 | } |
| 1162 | 1183 | ||
| 1163 | if (priv_dev->dev_ver <= DEV_VER_V2) | 1184 | if (priv_dev->dev_ver <= DEV_VER_V2) |
| 1164 | togle_pcs = cdns3_wa1_update_guard(priv_ep, trb); | 1185 | togle_pcs = cdns3_wa1_update_guard(priv_ep, trb); |
| 1165 | 1186 | ||
| 1187 | if (sg_supported) | ||
| 1188 | s = request->sg; | ||
| 1189 | |||
| 1166 | /* set incorrect Cycle Bit for first trb*/ | 1190 | /* set incorrect Cycle Bit for first trb*/ |
| 1167 | control = priv_ep->pcs ? 0 : TRB_CYCLE; | 1191 | control = priv_ep->pcs ? 0 : TRB_CYCLE; |
| 1168 | 1192 | ||
| @@ -1172,13 +1196,13 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep, · 3 unmodified lines | |||
| 1172 | 1196 | ||
| 1173 | /* fill TRB */ | 1197 | /* fill TRB */ |
| 1174 | control |= TRB_TYPE(TRB_NORMAL); | 1198 | control |= TRB_TYPE(TRB_NORMAL); |
| 1175 | trb->buffer = TRB_BUFFER(request->num_sgs == 0 | 1199 | if (sg_supported) { |
| 1176 | ? trb_dma : request->sg[sg_iter].dma_address); | 1200 | trb->buffer = cpu_to_le32(TRB_BUFFER(sg_dma_address(s))); |
| 1177 | 1201 | length = sg_dma_len(s); | |
| 1178 | if (likely(!request->num_sgs)) | 1202 | } else { |
| 1203 | trb->buffer = cpu_to_le32(TRB_BUFFER(trb_dma)); | ||
| 1179 | length = request->length; | 1204 | length = request->length; |
| 1180 | else | 1205 | } |
| 1181 | length = request->sg[sg_iter].length; | ||
| 1182 | 1206 | ||
| 1183 | if (likely(priv_dev->dev_ver >= DEV_VER_V2)) | 1207 | if (likely(priv_dev->dev_ver >= DEV_VER_V2)) |
| 1184 | td_size = DIV_ROUND_UP(length, | 1208 | td_size = DIV_ROUND_UP(length, |
| @@ -1187,10 +1211,10 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep, · 2 unmodified lines | |||
| 1187 | total_tdl += DIV_ROUND_UP(length, | 1211 | total_tdl += DIV_ROUND_UP(length, |
| 1188 | priv_ep->endpoint.maxpacket); | 1212 | priv_ep->endpoint.maxpacket); |
| 1189 | 1213 | ||
| 1190 | trb->length = TRB_BURST_LEN(priv_ep->trb_burst_size) | | 1214 | trb->length = cpu_to_le32(TRB_BURST_LEN(priv_ep->trb_burst_size) | |
| 1191 | TRB_LEN(length); | 1215 | TRB_LEN(length)); |
| 1192 | if (priv_dev->gadget.speed == USB_SPEED_SUPER) | 1216 | if (priv_dev->gadget.speed == USB_SPEED_SUPER) |
| 1193 | trb->length |= TRB_TDL_SS_SIZE(td_size); | 1217 | trb->length |= cpu_to_le32(TRB_TDL_SS_SIZE(td_size)); |
| 1194 | else | 1218 | else |
| 1195 | control |= TRB_TDL_HS_SIZE(td_size); | 1219 | control |= TRB_TDL_HS_SIZE(td_size); |
| 1196 | 1220 | ||
| @@ -1212,9 +1236,18 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep, · 15 unmodified lines | |||
| 1212 | } | 1236 | } |
| 1213 | 1237 | ||
| 1214 | if (sg_iter) | 1238 | if (sg_iter) |
| 1215 | trb->control = control; | 1239 | trb->control = cpu_to_le32(control); |
| 1216 | else | 1240 | else |
| 1217 | priv_req->trb->control = control; | 1241 | priv_req->trb->control = cpu_to_le32(control); |
| 1242 | |||
| 1243 | if (sg_supported) { | ||
| 1244 | trb->control |= TRB_ISP; | ||
| 1245 | /* Don't set chain bit for last TRB */ | ||
| 1246 | if (sg_iter < num_trb - 1) | ||
| 1247 | trb->control |= TRB_CHAIN; | ||
| 1248 | |||
| 1249 | s = sg_next(s); | ||
| 1250 | } | ||
| 1218 | 1251 | ||
| 1219 | control = 0; | 1252 | control = 0; |
| 1220 | ++sg_iter; | 1253 | ++sg_iter; |
| @@ -1226,9 +1259,10 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep, · 5 unmodified lines | |||
| 1226 | trb = priv_req->trb; | 1259 | trb = priv_req->trb; |
| 1227 | 1260 | ||
| 1228 | priv_req->flags |= REQUEST_PENDING; | 1261 | priv_req->flags |= REQUEST_PENDING; |
| 1262 | priv_req->num_of_trb = num_trb; | ||
| 1229 | 1263 | ||
| 1230 | if (sg_iter == 1) | 1264 | if (sg_iter == 1) |
| 1231 | trb->control |= TRB_IOC | TRB_ISP; | 1265 | trb->control |= cpu_to_le32(TRB_IOC | TRB_ISP); |
| 1232 | 1266 | ||
| 1233 | if (priv_dev->dev_ver < DEV_VER_V2 && | 1267 | if (priv_dev->dev_ver < DEV_VER_V2 && |
| 1234 | (priv_ep->flags & EP_TDLCHK_EN)) { | 1268 | (priv_ep->flags & EP_TDLCHK_EN)) { |
| @@ -1254,12 +1288,27 @@ static int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep, · 19 unmodified lines | |||
| 1254 | 1288 | ||
| 1255 | /* give the TD to the consumer*/ | 1289 | /* give the TD to the consumer*/ |
| 1256 | if (togle_pcs) | 1290 | if (togle_pcs) |
| 1257 | trb->control = trb->control ^ 1; | 1291 | trb->control = trb->control ^ cpu_to_le32(1); |
| 1258 | 1292 | ||
| 1259 | if (priv_dev->dev_ver <= DEV_VER_V2) | 1293 | if (priv_dev->dev_ver <= DEV_VER_V2) |
| 1260 | cdns3_wa1_tray_restore_cycle_bit(priv_dev, priv_ep); | 1294 | cdns3_wa1_tray_restore_cycle_bit(priv_dev, priv_ep); |
| 1261 | 1295 | ||
| 1262 | trace_cdns3_prepare_trb(priv_ep, priv_req->trb); | 1296 | if (num_trb > 1) { |
| 1297 | int i = 0; | ||
| 1298 | |||
| 1299 | while (i < num_trb) { | ||
| 1300 | trace_cdns3_prepare_trb(priv_ep, trb + i); | ||
| 1301 | if (trb + i == link_trb) { | ||
| 1302 | trb = priv_ep->trb_pool; | ||
| 1303 | num_trb = num_trb - i; | ||
| 1304 | i = 0; | ||
| 1305 | } else { | ||
| 1306 | i++; | ||
| 1307 | } | ||
| 1308 | } | ||
| 1309 | } else { | ||
| 1310 | trace_cdns3_prepare_trb(priv_ep, priv_req->trb); | ||
| 1311 | } | ||
| 1263 | 1312 | ||
| 1264 | /* | 1313 | /* |
| 1265 | * Memory barrier - Cycle Bit must be set before trb->length and | 1314 | * Memory barrier - Cycle Bit must be set before trb->length and |
| @@ -1310,7 +1359,6 @@ void cdns3_set_hw_configuration(struct cdns3_device *priv_dev) · 44 unmodified lines | |||
| 1310 | { | 1359 | { |
| 1311 | struct cdns3_endpoint *priv_ep; | 1360 | struct cdns3_endpoint *priv_ep; |
| 1312 | struct usb_ep *ep; | 1361 | struct usb_ep *ep; |
| 1313 | int val; | ||
| 1314 | 1362 | ||
| 1315 | if (priv_dev->hw_configured_flag) | 1363 | if (priv_dev->hw_configured_flag) |
| 1316 | return; | 1364 | return; |
| @@ -1320,10 +1368,6 @@ void cdns3_set_hw_configuration(struct cdns3_device *priv_dev) · 3 unmodified lines | |||
| 1320 | cdns3_set_register_bit(&priv_dev->regs->usb_conf, | 1368 | cdns3_set_register_bit(&priv_dev->regs->usb_conf, |
| 1321 | USB_CONF_U1EN | USB_CONF_U2EN); | 1369 | USB_CONF_U1EN | USB_CONF_U2EN); |
| 1322 | 1370 | ||
| 1323 | /* wait until configuration set */ | ||
| 1324 | readl_poll_timeout_atomic(&priv_dev->regs->usb_sts, val, | ||
| 1325 | val & USB_STS_CFGSTS_MASK, 1, 100); | ||
| 1326 | |||
| 1327 | priv_dev->hw_configured_flag = 1; | 1371 | priv_dev->hw_configured_flag = 1; |
| 1328 | 1372 | ||
| 1329 | list_for_each_entry(ep, &priv_dev->gadget.ep_list, ep_list) { | 1373 | list_for_each_entry(ep, &priv_dev->gadget.ep_list, ep_list) { |
| @@ -1337,7 +1381,7 @@ void cdns3_set_hw_configuration(struct cdns3_device *priv_dev) · 7 unmodified lines | |||
| 1337 | } | 1381 | } |
| 1338 | 1382 | ||
| 1339 | /** | 1383 | /** |
| 1340 | * cdns3_request_handled - check whether request has been handled by DMA | 1384 | * cdns3_trb_handled - check whether trb has been handled by DMA |
| 1341 | * | 1385 | * |
| 1342 | * @priv_ep: extended endpoint object. | 1386 | * @priv_ep: extended endpoint object. |
| 1343 | * @priv_req: request object for checking | 1387 | * @priv_req: request object for checking |
| @@ -1354,32 +1398,28 @@ void cdns3_set_hw_configuration(struct cdns3_device *priv_dev) · 10 unmodified lines | |||
| 1354 | * ET = priv_req->end_trb - index of last TRB in transfer ring | 1398 | * ET = priv_req->end_trb - index of last TRB in transfer ring |
| 1355 | * CI = current_index - index of processed TRB by DMA. | 1399 | * CI = current_index - index of processed TRB by DMA. |
| 1356 | * | 1400 | * |
| 1357 | * As first step, function checks if cycle bit for priv_req->start_trb is | 1401 | * As first step, we check if the TRB between the ST and ET. |
| 1358 | * correct. | 1402 | * Then, we check if cycle bit for index priv_ep->dequeue |
| 1403 | * is correct. | ||
| 1359 | * | 1404 | * |
| 1360 | * some rules: | 1405 | * some rules: |
| 1361 | * 1. priv_ep->dequeue never exceed current_index. | 1406 | * 1. priv_ep->dequeue never equals to current_index. |
| 1362 | * 2 priv_ep->enqueue never exceed priv_ep->dequeue | 1407 | * 2 priv_ep->enqueue never exceed priv_ep->dequeue |
| 1363 | * 3. exception: priv_ep->enqueue == priv_ep->dequeue | 1408 | * 3. exception: priv_ep->enqueue == priv_ep->dequeue |
| 1364 | * and priv_ep->free_trbs is zero. | 1409 | * and priv_ep->free_trbs is zero. |
| 1365 | * This case indicate that TR is full. | 1410 | * This case indicate that TR is full. |
| 1366 | * | 1411 | * |
| 1367 | * Then We can split recognition into two parts: | 1412 | * At below two cases, the request have been handled. |
| 1368 | * Case 1 - priv_ep->dequeue < current_index | 1413 | * Case 1 - priv_ep->dequeue < current_index |
| 1369 | * SR ... EQ ... DQ ... CI ... ER | 1414 | * SR ... EQ ... DQ ... CI ... ER |
| 1370 | * SR ... DQ ... CI ... EQ ... ER | 1415 | * SR ... DQ ... CI ... EQ ... ER |
| 1371 | * | 1416 | * |
| 1372 | * Request has been handled by DMA if ST and ET is between DQ and CI. | ||
| 1373 | * | ||
| 1374 | * Case 2 - priv_ep->dequeue > current_index | 1417 | * Case 2 - priv_ep->dequeue > current_index |
| 1375 | * This situation take place when CI go through the LINK TRB at the end of | 1418 | * This situation takes place when CI go through the LINK TRB at the end of |
| 1376 | * transfer ring. | 1419 | * transfer ring. |
| 1377 | * SR ... CI ... EQ ... DQ ... ER | 1420 | * SR ... CI ... EQ ... DQ ... ER |
| 1378 | * | ||
| 1379 | * Request has been handled by DMA if ET is less then CI or | ||
| 1380 | * ET is greater or equal DQ. | ||
| 1381 | */ | 1421 | */ |
| 1382 | static bool cdns3_request_handled(struct cdns3_endpoint *priv_ep, | 1422 | static bool cdns3_trb_handled(struct cdns3_endpoint *priv_ep, |
| 1383 | struct cdns3_request *priv_req) | 1423 | struct cdns3_request *priv_req) |
| 1384 | { | 1424 | { |
| 1385 | struct cdns3_device *priv_dev = priv_ep->cdns3_dev; | 1425 | struct cdns3_device *priv_dev = priv_ep->cdns3_dev; |
| @@ -1391,9 +1431,27 @@ static bool cdns3_request_handled(struct cdns3_endpoint *priv_ep, · 5 unmodified lines | |||
| 1391 | current_index = cdns3_get_dma_pos(priv_dev, priv_ep); | 1431 | current_index = cdns3_get_dma_pos(priv_dev, priv_ep); |
| 1392 | doorbell = !!(readl(&priv_dev->regs->ep_cmd) & EP_CMD_DRDY); | 1432 | doorbell = !!(readl(&priv_dev->regs->ep_cmd) & EP_CMD_DRDY); |
| 1393 | 1433 | ||
| 1394 | trb = &priv_ep->trb_pool[priv_req->start_trb]; | 1434 | /* current trb doesn't belong to this request */ |
| 1435 | if (priv_req->start_trb < priv_req->end_trb) { | ||
| 1436 | if (priv_ep->dequeue > priv_req->end_trb) | ||
| 1437 | goto finish; | ||
| 1438 | |||
| 1439 | if (priv_ep->dequeue < priv_req->start_trb) | ||
| 1440 | goto finish; | ||
| 1441 | } | ||
| 1442 | |||
| 1443 | if ((priv_req->start_trb > priv_req->end_trb) && | ||
| 1444 | (priv_ep->dequeue > priv_req->end_trb) && | ||
| 1445 | (priv_ep->dequeue < priv_req->start_trb)) | ||
| 1446 | goto finish; | ||
| 1395 | 1447 | ||
| 1396 | if ((trb->control & TRB_CYCLE) != priv_ep->ccs) | 1448 | if ((priv_req->start_trb == priv_req->end_trb) && |
| 1449 | (priv_ep->dequeue != priv_req->end_trb)) | ||
| 1450 | goto finish; | ||
| 1451 | |||
| 1452 | trb = &priv_ep->trb_pool[priv_ep->dequeue]; | ||
| 1453 | |||
| 1454 | if ((le32_to_cpu(trb->control) & TRB_CYCLE) != priv_ep->ccs) | ||
| 1397 | goto finish; | 1455 | goto finish; |
| 1398 | 1456 | ||
| 1399 | if (doorbell == 1 && current_index == priv_ep->dequeue) | 1457 | if (doorbell == 1 && current_index == priv_ep->dequeue) |
| @@ -1413,12 +1471,8 @@ static bool cdns3_request_handled(struct cdns3_endpoint *priv_ep, · 13 unmodified lines | |||
| 1413 | !priv_ep->dequeue) | 1471 | !priv_ep->dequeue) |
| 1414 | goto finish; | 1472 | goto finish; |
| 1415 | 1473 | ||
| 1416 | if (priv_req->end_trb >= priv_ep->dequeue && | 1474 | handled = 1; |
| 1417 | priv_req->end_trb < current_index) | ||
| 1418 | handled = 1; | ||
| 1419 | } else if (priv_ep->dequeue > current_index) { | 1475 | } else if (priv_ep->dequeue > current_index) { |
| 1420 | if (priv_req->end_trb < current_index || | ||
| 1421 | priv_req->end_trb >= priv_ep->dequeue) | ||
| 1422 | handled = 1; | 1476 | handled = 1; |
| 1423 | } | 1477 | } |
| 1424 | 1478 | ||
| @@ -1434,6 +1488,8 @@ static void cdns3_transfer_completed(struct cdns3_device *priv_dev, · 9 unmodified lines | |||
| 1434 | struct cdns3_request *priv_req; | 1488 | struct cdns3_request *priv_req; |
| 1435 | struct usb_request *request; | 1489 | struct usb_request *request; |
| 1436 | struct cdns3_trb *trb; | 1490 | struct cdns3_trb *trb; |
| 1491 | bool request_handled = false; | ||
| 1492 | bool transfer_end = false; | ||
| 1437 | 1493 | ||
| 1438 | while (!list_empty(&priv_ep->pending_req_list)) { | 1494 | while (!list_empty(&priv_ep->pending_req_list)) { |
| 1439 | request = cdns3_next_request(&priv_ep->pending_req_list); | 1495 | request = cdns3_next_request(&priv_ep->pending_req_list); |
| @@ -1442,7 +1498,7 @@ static void cdns3_transfer_completed(struct cdns3_device *priv_dev, · 2 unmodified lines | |||
| 1442 | trb = priv_ep->trb_pool + priv_ep->dequeue; | 1498 | trb = priv_ep->trb_pool + priv_ep->dequeue; |
| 1443 | 1499 | ||
| 1444 | /* Request was dequeued and TRB was changed to TRB_LINK. */ | 1500 | /* Request was dequeued and TRB was changed to TRB_LINK. */ |
| 1445 | if (TRB_FIELD_TO_TYPE(trb->control) == TRB_LINK) { | 1501 | if (TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) == TRB_LINK) { |
| 1446 | trace_cdns3_complete_trb(priv_ep, trb); | 1502 | trace_cdns3_complete_trb(priv_ep, trb); |
| 1447 | cdns3_move_deq_to_next_trb(priv_req); | 1503 | cdns3_move_deq_to_next_trb(priv_req); |
| 1448 | } | 1504 | } |
| @@ -1453,20 +1509,32 @@ static void cdns3_transfer_completed(struct cdns3_device *priv_dev, · 4 unmodified lines | |||
| 1453 | */ | 1509 | */ |
| 1454 | cdns3_select_ep(priv_dev, priv_ep->endpoint.address); | 1510 | cdns3_select_ep(priv_dev, priv_ep->endpoint.address); |
| 1455 | 1511 | ||
| 1456 | if (!cdns3_request_handled(priv_ep, priv_req)) | 1512 | while (cdns3_trb_handled(priv_ep, priv_req)) { |
| 1457 | goto prepare_next_td; | 1513 | priv_req->finished_trb++; |
| 1514 | if (priv_req->finished_trb >= priv_req->num_of_trb) | ||
| 1515 | request_handled = true; | ||
| 1458 | 1516 | ||
| 1459 | trb = priv_ep->trb_pool + priv_ep->dequeue; | 1517 | trb = priv_ep->trb_pool + priv_ep->dequeue; |
| 1460 | trace_cdns3_complete_trb(priv_ep, trb); | 1518 | trace_cdns3_complete_trb(priv_ep, trb); |
| 1461 | 1519 | ||
| 1462 | if (trb != priv_req->trb) | 1520 | if (!transfer_end) |
| 1463 | dev_warn(priv_dev->dev, | 1521 | request->actual += |
| 1464 | "request_trb=0x%p, queue_trb=0x%p\n", | 1522 | TRB_LEN(le32_to_cpu(trb->length)); |
| 1465 | priv_req->trb, trb); | ||
| 1466 | 1523 | ||
| 1467 | request->actual = TRB_LEN(le32_to_cpu(trb->length)); | 1524 | if (priv_req->num_of_trb > 1 && |
| 1468 | cdns3_move_deq_to_next_trb(priv_req); | 1525 | le32_to_cpu(trb->control) & TRB_SMM) |
| 1469 | cdns3_gadget_giveback(priv_ep, priv_req, 0); | 1526 | transfer_end = true; |
| 1527 | |||
| 1528 | cdns3_ep_inc_deq(priv_ep); | ||
| 1529 | } | ||
| 1530 | |||
| 1531 | if (request_handled) { | ||
| 1532 | cdns3_gadget_giveback(priv_ep, priv_req, 0); | ||
| 1533 | request_handled = false; | ||
| 1534 | transfer_end = false; | ||
| 1535 | } else { | ||
| 1536 | goto prepare_next_td; | ||
| 1537 | } | ||
| 1470 | 1538 | ||
| 1471 | if (priv_ep->type != USB_ENDPOINT_XFER_ISOC && | 1539 | if (priv_ep->type != USB_ENDPOINT_XFER_ISOC && |
| 1472 | TRBS_PER_SEGMENT == 2) | 1540 | TRBS_PER_SEGMENT == 2) |
| @@ -1574,7 +1642,7 @@ static int cdns3_check_ep_interrupt_proceed(struct cdns3_endpoint *priv_ep) · 101 unmodified lines | |||
| 1574 | * that host ignore the ERDY packet and driver has to send it | 1642 | * that host ignore the ERDY packet and driver has to send it |
| 1575 | * again. | 1643 | * again. |
| 1576 | */ | 1644 | */ |
| 1577 | if (tdl && (dbusy | !EP_STS_BUFFEMPTY(ep_sts_reg) | | 1645 | if (tdl && (dbusy || !EP_STS_BUFFEMPTY(ep_sts_reg) || |
| 1578 | EP_STS_HOSTPP(ep_sts_reg))) { | 1646 | EP_STS_HOSTPP(ep_sts_reg))) { |
| 1579 | writel(EP_CMD_ERDY | | 1647 | writel(EP_CMD_ERDY | |
| 1580 | EP_CMD_ERDY_SID(priv_ep->last_stream_id), | 1648 | EP_CMD_ERDY_SID(priv_ep->last_stream_id), |
| @@ -1769,9 +1837,13 @@ static void cdns3_check_usb_interrupt_proceed(struct cdns3_device *priv_dev, · 188 unmodified lines | |||
| 1769 | static irqreturn_t cdns3_device_irq_handler(int irq, void *data) | 1837 | static irqreturn_t cdns3_device_irq_handler(int irq, void *data) |
| 1770 | { | 1838 | { |
| 1771 | struct cdns3_device *priv_dev = data; | 1839 | struct cdns3_device *priv_dev = data; |
| 1840 | struct cdns3 *cdns = dev_get_drvdata(priv_dev->dev); | ||
| 1772 | irqreturn_t ret = IRQ_NONE; | 1841 | irqreturn_t ret = IRQ_NONE; |
| 1773 | u32 reg; | 1842 | u32 reg; |
| 1774 | 1843 | ||
| 1844 | if (cdns->in_lpm) | ||
| 1845 | return ret; | ||
| 1846 | |||
| 1775 | /* check USB device interrupt */ | 1847 | /* check USB device interrupt */ |
| 1776 | reg = readl(&priv_dev->regs->usb_ists); | 1848 | reg = readl(&priv_dev->regs->usb_ists); |
| 1777 | if (reg) { | 1849 | if (reg) { |
| @@ -2552,10 +2624,10 @@ found: · 774 unmodified lines | |||
| 2552 | 2624 | ||
| 2553 | /* Update ring only if removed request is on pending_req_list list */ | 2625 | /* Update ring only if removed request is on pending_req_list list */ |
| 2554 | if (req_on_hw_ring && link_trb) { | 2626 | if (req_on_hw_ring && link_trb) { |
| 2555 | link_trb->buffer = TRB_BUFFER(priv_ep->trb_pool_dma + | 2627 | link_trb->buffer = cpu_to_le32(TRB_BUFFER(priv_ep->trb_pool_dma + |
| 2556 | ((priv_req->end_trb + 1) * TRB_SIZE)); | 2628 | ((priv_req->end_trb + 1) * TRB_SIZE))); |
| 2557 | link_trb->control = (link_trb->control & TRB_CYCLE) | | 2629 | link_trb->control = cpu_to_le32((le32_to_cpu(link_trb->control) & TRB_CYCLE) | |
| 2558 | TRB_TYPE(TRB_LINK) | TRB_CHAIN; | 2630 | TRB_TYPE(TRB_LINK) | TRB_CHAIN); |
| 2559 | 2631 | ||
| 2560 | if (priv_ep->wa1_trb == priv_req->trb) | 2632 | if (priv_ep->wa1_trb == priv_req->trb) |
| 2561 | cdns3_wa1_restore_cycle_bit(priv_ep); | 2633 | cdns3_wa1_restore_cycle_bit(priv_ep); |
| @@ -2610,7 +2682,7 @@ int __cdns3_gadget_ep_clear_halt(struct cdns3_endpoint *priv_ep) · 48 unmodified lines | |||
| 2610 | priv_req = to_cdns3_request(request); | 2682 | priv_req = to_cdns3_request(request); |
| 2611 | trb = priv_req->trb; | 2683 | trb = priv_req->trb; |
| 2612 | if (trb) | 2684 | if (trb) |
| 2613 | trb->control = trb->control ^ TRB_CYCLE; | 2685 | trb->control = trb->control ^ cpu_to_le32(TRB_CYCLE); |
| 2614 | } | 2686 | } |
| 2615 | 2687 | ||
| 2616 | writel(EP_CMD_CSTALL | EP_CMD_EPRST, &priv_dev->regs->ep_cmd); | 2688 | writel(EP_CMD_CSTALL | EP_CMD_EPRST, &priv_dev->regs->ep_cmd); |
| @@ -2625,7 +2697,8 @@ int __cdns3_gadget_ep_clear_halt(struct cdns3_endpoint *priv_ep) · 8 unmodified lines | |||
| 2625 | 2697 | ||
| 2626 | if (request) { | 2698 | if (request) { |
| 2627 | if (trb) | 2699 | if (trb) |
| 2628 | trb->control = trb->control ^ TRB_CYCLE; | 2700 | trb->control = trb->control ^ cpu_to_le32(TRB_CYCLE); |
| 2701 | |||
| 2629 | cdns3_rearm_transfer(priv_ep, 1); | 2702 | cdns3_rearm_transfer(priv_ep, 1); |
| 2630 | } | 2703 | } |
| 2631 | 2704 | ||
| @@ -2735,10 +2808,13 @@ static int cdns3_gadget_pullup(struct usb_gadget *gadget, int is_on) · 103 unmodified lines | |||
| 2735 | { | 2808 | { |
| 2736 | struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget); | 2809 | struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget); |
| 2737 | 2810 | ||
| 2738 | if (is_on) | 2811 | if (is_on) { |
| 2739 | writel(USB_CONF_DEVEN, &priv_dev->regs->usb_conf); | 2812 | writel(USB_CONF_DEVEN, &priv_dev->regs->usb_conf); |
| 2740 | else | 2813 | } else { |
| 2814 | writel(~0, &priv_dev->regs->ep_ists); | ||
| 2815 | writel(~0, &priv_dev->regs->usb_ists); | ||
| 2741 | writel(USB_CONF_DEVDS, &priv_dev->regs->usb_conf); | 2816 | writel(USB_CONF_DEVDS, &priv_dev->regs->usb_conf); |
| 2817 | } | ||
| 2742 | 2818 | ||
| 2743 | return 0; | 2819 | return 0; |
| 2744 | } | 2820 | } |
| @@ -2779,6 +2855,8 @@ static void cdns3_gadget_config(struct cdns3_device *priv_dev) · 34 unmodified lines | |||
| 2779 | /* enable generic interrupt*/ | 2855 | /* enable generic interrupt*/ |
| 2780 | writel(USB_IEN_INIT, ®s->usb_ien); | 2856 | writel(USB_IEN_INIT, ®s->usb_ien); |
| 2781 | writel(USB_CONF_CLK2OFFDS | USB_CONF_L1DS, ®s->usb_conf); | 2857 | writel(USB_CONF_CLK2OFFDS | USB_CONF_L1DS, ®s->usb_conf); |
| 2858 | /* keep Fast Access bit */ | ||
| 2859 | writel(PUSB_PWR_FST_REG_ACCESS, &priv_dev->regs->usb_pwr); | ||
| 2782 | 2860 | ||
| 2783 | cdns3_configure_dmult(priv_dev, NULL); | 2861 | cdns3_configure_dmult(priv_dev, NULL); |
| 2784 | } | 2862 | } |
| @@ -2862,6 +2940,7 @@ static int cdns3_gadget_udc_stop(struct usb_gadget *gadget) · 77 unmodified lines | |||
| 2862 | 2940 | ||
| 2863 | /* disable interrupt for device */ | 2941 | /* disable interrupt for device */ |
| 2864 | writel(0, &priv_dev->regs->usb_ien); | 2942 | writel(0, &priv_dev->regs->usb_ien); |
| 2943 | writel(0, &priv_dev->regs->usb_pwr); | ||
| 2865 | writel(USB_CONF_DEVDS, &priv_dev->regs->usb_conf); | 2944 | writel(USB_CONF_DEVDS, &priv_dev->regs->usb_conf); |
| 2866 | 2945 | ||
| 2867 | return 0; | 2946 | return 0; |
| @@ -2984,18 +3063,26 @@ err: · 116 unmodified lines | |||
| 2984 | return -ENOMEM; | 3063 | return -ENOMEM; |
| 2985 | } | 3064 | } |
| 2986 | 3065 | ||
| 3066 | static void cdns3_gadget_release(struct device *dev) | ||
| 3067 | { | ||
| 3068 | struct cdns3_device *priv_dev = container_of(dev, | ||
| 3069 | struct cdns3_device, gadget.dev); | ||
| 3070 | |||
| 3071 | kfree(priv_dev); | ||
| 3072 | } | ||
| 3073 | |||
| 2987 | void cdns3_gadget_exit(struct cdns3 *cdns) | 3074 | void cdns3_gadget_exit(struct cdns3 *cdns) |
| 2988 | { | 3075 | { |
| 2989 | struct cdns3_device *priv_dev; | 3076 | struct cdns3_device *priv_dev; |
| 2990 | 3077 | ||
| 2991 | priv_dev = cdns->gadget_dev; | 3078 | priv_dev = cdns->gadget_dev; |
| 2992 | 3079 | ||
| 2993 | devm_free_irq(cdns->dev, cdns->dev_irq, priv_dev); | ||
| 2994 | 3080 | ||
| 2995 | pm_runtime_mark_last_busy(cdns->dev); | 3081 | pm_runtime_mark_last_busy(cdns->dev); |
| 2996 | pm_runtime_put_autosuspend(cdns->dev); | 3082 | pm_runtime_put_autosuspend(cdns->dev); |
| 2997 | 3083 | ||
| 2998 | usb_del_gadget_udc(&priv_dev->gadget); | 3084 | usb_del_gadget(&priv_dev->gadget); |
| 3085 | devm_free_irq(cdns->dev, cdns->dev_irq, priv_dev); | ||
| 2999 | 3086 | ||
| 3000 | cdns3_free_all_eps(priv_dev); | 3087 | cdns3_free_all_eps(priv_dev); |
| 3001 | 3088 | ||
| @@ -3015,7 +3102,7 @@ void cdns3_gadget_exit(struct cdns3 *cdns) · 13 unmodified lines | |||
| 3015 | priv_dev->setup_dma); | 3102 | priv_dev->setup_dma); |
| 3016 | 3103 | ||
| 3017 | kfree(priv_dev->zlp_buf); | 3104 | kfree(priv_dev->zlp_buf); |
| 3018 | kfree(priv_dev); | 3105 | usb_put_gadget(&priv_dev->gadget); |
| 3019 | cdns->gadget_dev = NULL; | 3106 | cdns->gadget_dev = NULL; |
| 3020 | cdns3_drd_gadget_off(cdns); | 3107 | cdns3_drd_gadget_off(cdns); |
| 3021 | } | 3108 | } |
| @@ -3030,6 +3117,8 @@ static int cdns3_gadget_start(struct cdns3 *cdns) · 8 unmodified lines | |||
| 3030 | if (!priv_dev) | 3117 | if (!priv_dev) |
| 3031 | return -ENOMEM; | 3118 | return -ENOMEM; |
| 3032 | 3119 | ||
| 3120 | usb_initialize_gadget(cdns->dev, &priv_dev->gadget, | ||
| 3121 | cdns3_gadget_release); | ||
| 3033 | cdns->gadget_dev = priv_dev; | 3122 | cdns->gadget_dev = priv_dev; |
| 3034 | priv_dev->sysdev = cdns->dev; | 3123 | priv_dev->sysdev = cdns->dev; |
| 3035 | priv_dev->dev = cdns->dev; | 3124 | priv_dev->dev = cdns->dev; |
| @@ -3070,7 +3159,6 @@ static int cdns3_gadget_start(struct cdns3 *cdns) · 34 unmodified lines | |||
| 3070 | priv_dev->gadget.speed = USB_SPEED_UNKNOWN; | 3159 | priv_dev->gadget.speed = USB_SPEED_UNKNOWN; |
| 3071 | priv_dev->gadget.ops = &cdns3_gadget_ops; | 3160 | priv_dev->gadget.ops = &cdns3_gadget_ops; |
| 3072 | priv_dev->gadget.name = "usb-ss-gadget"; | 3161 | priv_dev->gadget.name = "usb-ss-gadget"; |
| 3073 | priv_dev->gadget.sg_supported = 1; | ||
| 3074 | priv_dev->gadget.quirk_avoids_skb_reserve = 1; | 3162 | priv_dev->gadget.quirk_avoids_skb_reserve = 1; |
| 3075 | priv_dev->gadget.irq = cdns->dev_irq; | 3163 | priv_dev->gadget.irq = cdns->dev_irq; |
| 3076 | 3164 | ||
| @@ -3109,6 +3197,8 @@ static int cdns3_gadget_start(struct cdns3 *cdns) · 32 unmodified lines | |||
| 3109 | readl(&priv_dev->regs->usb_cap2)); | 3197 | readl(&priv_dev->regs->usb_cap2)); |
| 3110 | 3198 | ||
| 3111 | priv_dev->dev_ver = GET_DEV_BASE_VERSION(priv_dev->dev_ver); | 3199 | priv_dev->dev_ver = GET_DEV_BASE_VERSION(priv_dev->dev_ver); |
| 3200 | if (priv_dev->dev_ver >= DEV_VER_V2) | ||
| 3201 | priv_dev->gadget.sg_supported = 1; | ||
| 3112 | 3202 | ||
| 3113 | priv_dev->zlp_buf = kzalloc(CDNS3_EP_ZLP_BUF_SIZE, GFP_KERNEL); | 3203 | priv_dev->zlp_buf = kzalloc(CDNS3_EP_ZLP_BUF_SIZE, GFP_KERNEL); |
| 3114 | if (!priv_dev->zlp_buf) { | 3204 | if (!priv_dev->zlp_buf) { |
| @@ -3117,10 +3207,9 @@ static int cdns3_gadget_start(struct cdns3 *cdns) · 2 unmodified lines | |||
| 3117 | } | 3207 | } |
| 3118 | 3208 | ||
| 3119 | /* add USB gadget device */ | 3209 | /* add USB gadget device */ |
| 3120 | ret = usb_add_gadget_udc(priv_dev->dev, &priv_dev->gadget); | 3210 | ret = usb_add_gadget(&priv_dev->gadget); |
| 3121 | if (ret < 0) { | 3211 | if (ret < 0) { |
| 3122 | dev_err(priv_dev->dev, | 3212 | dev_err(priv_dev->dev, "Failed to add gadget\n"); |
| 3123 | "Failed to register USB device controller\n"); | ||
| 3124 | goto err4; | 3213 | goto err4; |
| 3125 | } | 3214 | } |
| 3126 | 3215 | ||
| @@ -3133,6 +3222,7 @@ err3: · 6 unmodified lines | |||
| 3133 | err2: | 3222 | err2: |
| 3134 | cdns3_free_all_eps(priv_dev); | 3223 | cdns3_free_all_eps(priv_dev); |
| 3135 | err1: | 3224 | err1: |
| 3225 | usb_put_gadget(&priv_dev->gadget); | ||
| 3136 | cdns->gadget_dev = NULL; | 3226 | cdns->gadget_dev = NULL; |
| 3137 | return ret; | 3227 | return ret; |
| 3138 | } | 3228 | } |
| @@ -966,7 +966,7 @@ struct cdns3_usb_regs { · 965 unmodified lines | |||
| 966 | /* | 966 | /* |
| 967 | * USBSS-DEV DMA interface. | 967 | * USBSS-DEV DMA interface. |
| 968 | */ | 968 | */ |
| 969 | #define TRBS_PER_SEGMENT 40 | 969 | #define TRBS_PER_SEGMENT 600 |
| 970 | 970 | ||
| 971 | #define ISO_MAX_INTERVAL 10 | 971 | #define ISO_MAX_INTERVAL 10 |
| 972 | 972 | ||
| @@ -1030,6 +1030,11 @@ struct cdns3_trb { · 57 unmodified lines | |||
| 1030 | * When set to '1', the device will toggle its interpretation of the Cycle bit | 1030 | * When set to '1', the device will toggle its interpretation of the Cycle bit |
| 1031 | */ | 1031 | */ |
| 1032 | #define TRB_TOGGLE BIT(1) | 1032 | #define TRB_TOGGLE BIT(1) |
| 1033 | /* | ||
| 1034 | * The controller will set it if OUTSMM (OUT size mismatch) is detected, | ||
| 1035 | * this bit is for normal TRB | ||
| 1036 | */ | ||
| 1037 | #define TRB_SMM BIT(1) | ||
| 1033 | 1038 | ||
| 1034 | /* | 1039 | /* |
| 1035 | * Short Packet (SP). OUT EPs at DMULT=1 only. Indicates if the TRB was | 1040 | * Short Packet (SP). OUT EPs at DMULT=1 only. Indicates if the TRB was |
| @@ -1215,6 +1220,8 @@ struct cdns3_aligned_buf { · 179 unmodified lines | |||
| 1215 | * this endpoint | 1220 | * this endpoint |
| 1216 | * @flags: flag specifying special usage of request | 1221 | * @flags: flag specifying special usage of request |
| 1217 | * @list: used by internally allocated request to add to wa2_descmiss_req_list. | 1222 | * @list: used by internally allocated request to add to wa2_descmiss_req_list. |
| 1223 | * @finished_trb: number of trb has already finished per request | ||
| 1224 | * @num_of_trb: how many trbs in this request | ||
| 1218 | */ | 1225 | */ |
| 1219 | struct cdns3_request { | 1226 | struct cdns3_request { |
| 1220 | struct usb_request request; | 1227 | struct usb_request request; |
| @@ -1230,6 +1237,8 @@ struct cdns3_request { · 9 unmodified lines | |||
| 1230 | #define REQUEST_UNALIGNED BIT(4) | 1237 | #define REQUEST_UNALIGNED BIT(4) |
| 1231 | u32 flags; | 1238 | u32 flags; |
| 1232 | struct list_head list; | 1239 | struct list_head list; |
| 1240 | int finished_trb; | ||
| 1241 | int num_of_trb; | ||
| 1233 | }; | 1242 | }; |
| 1234 | 1243 | ||
| 1235 | #define to_cdns3_request(r) (container_of(r, struct cdns3_request, request)) | 1244 | #define to_cdns3_request(r) (container_of(r, struct cdns3_request, request)) |
| @@ -13,11 +13,13 @@ · 12 unmodified lines | |||
| 13 | #include "core.h" | 13 | #include "core.h" |
| 14 | #include "drd.h" | 14 | #include "drd.h" |
| 15 | #include "host-export.h" | 15 | #include "host-export.h" |
| 16 | #include <linux/usb/hcd.h> | ||
| 16 | 17 | ||
| 17 | static int __cdns3_host_init(struct cdns3 *cdns) | 18 | static int __cdns3_host_init(struct cdns3 *cdns) |
| 18 | { | 19 | { |
| 19 | struct platform_device *xhci; | 20 | struct platform_device *xhci; |
| 20 | int ret; | 21 | int ret; |
| 22 | struct usb_hcd *hcd; | ||
| 21 | 23 | ||
| 22 | cdns3_drd_host_on(cdns); | 24 | cdns3_drd_host_on(cdns); |
| 23 | 25 | ||
| @@ -43,6 +45,11 @@ static int __cdns3_host_init(struct cdns3 *cdns) · 19 unmodified lines | |||
| 43 | goto err1; | 45 | goto err1; |
| 44 | } | 46 | } |
| 45 | 47 | ||
| 48 | /* Glue needs to access xHCI region register for Power management */ | ||
| 49 | hcd = platform_get_drvdata(xhci); | ||
| 50 | if (hcd) | ||
| 51 | cdns->xhci_regs = hcd->regs; | ||
| 52 | |||
| 46 | return 0; | 53 | return 0; |
| 47 | err1: | 54 | err1: |
| 48 | platform_device_put(xhci); | 55 | platform_device_put(xhci); |
| @@ -165,6 +165,11 @@ static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev) · 164 unmodified lines | |||
| 165 | if (of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI) | 165 | if (of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI) |
| 166 | data->ulpi = 1; | 166 | data->ulpi = 1; |
| 167 | 167 | ||
| 168 | of_property_read_u32(np, "samsung,picophy-pre-emp-curr-control", | ||
| 169 | &data->emp_curr_control); | ||
| 170 | of_property_read_u32(np, "samsung,picophy-dc-vol-level-adjust", | ||
| 171 | &data->dc_vol_level_adjust); | ||
| 172 | |||
| 168 | return data; | 173 | return data; |
| 169 | } | 174 | } |
| 170 | 175 | ||
| @@ -609,7 +614,12 @@ static int __maybe_unused ci_hdrc_imx_suspend(struct device *dev) · 438 unmodified lines | |||
| 609 | } | 614 | } |
| 610 | } | 615 | } |
| 611 | 616 | ||
| 612 | return imx_controller_suspend(dev); | 617 | ret = imx_controller_suspend(dev); |
| 618 | if (ret) | ||
| 619 | return ret; | ||
| 620 | |||
| 621 | pinctrl_pm_select_sleep_state(dev); | ||
| 622 | return ret; | ||
| 613 | } | 623 | } |
| 614 | 624 | ||
| 615 | static int __maybe_unused ci_hdrc_imx_resume(struct device *dev) | 625 | static int __maybe_unused ci_hdrc_imx_resume(struct device *dev) |
| @@ -617,6 +627,7 @@ static int __maybe_unused ci_hdrc_imx_resume(struct device *dev) · 1 unmodified line | |||
| 617 | struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); | 627 | struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); |
| 618 | int ret; | 628 | int ret; |
| 619 | 629 | ||
| 630 | pinctrl_pm_select_default_state(dev); | ||
| 620 | ret = imx_controller_resume(dev); | 631 | ret = imx_controller_resume(dev); |
| 621 | if (!ret && data->supports_runtime_pm) { | 632 | if (!ret && data->supports_runtime_pm) { |
| 622 | pm_runtime_disable(dev); | 633 | pm_runtime_disable(dev); |
| @@ -26,6 +26,8 @@ struct imx_usbmisc_data { · 25 unmodified lines | |||
| 26 | unsigned int ext_vbus:1; /* Vbus from exteranl event */ | 26 | unsigned int ext_vbus:1; /* Vbus from exteranl event */ |
| 27 | struct usb_phy *usb_phy; | 27 | struct usb_phy *usb_phy; |
| 28 | enum usb_dr_mode available_role; /* runtime usb dr mode */ | 28 | enum usb_dr_mode available_role; /* runtime usb dr mode */ |
| 29 | int emp_curr_control; | ||
| 30 | int dc_vol_level_adjust; | ||
| 29 | }; | 31 | }; |
| 30 | 32 | ||
| 31 | int imx_usbmisc_init(struct imx_usbmisc_data *data); | 33 | int imx_usbmisc_init(struct imx_usbmisc_data *data); |
| @@ -128,6 +128,12 @@ · 127 unmodified lines | |||
| 128 | #define MX7D_USB_OTG_PHY_STATUS_VBUS_VLD BIT(3) | 128 | #define MX7D_USB_OTG_PHY_STATUS_VBUS_VLD BIT(3) |
| 129 | #define MX7D_USB_OTG_PHY_STATUS_CHRGDET BIT(29) | 129 | #define MX7D_USB_OTG_PHY_STATUS_CHRGDET BIT(29) |
| 130 | 130 | ||
| 131 | #define MX7D_USB_OTG_PHY_CFG1 0x30 | ||
| 132 | #define TXPREEMPAMPTUNE0_BIT 28 | ||
| 133 | #define TXPREEMPAMPTUNE0_MASK (3 << 28) | ||
| 134 | #define TXVREFTUNE0_BIT 20 | ||
| 135 | #define TXVREFTUNE0_MASK (0xf << 20) | ||
| 136 | |||
| 131 | #define MX6_USB_OTG_WAKEUP_BITS (MX6_BM_WAKEUP_ENABLE | MX6_BM_VBUS_WAKEUP | \ | 137 | #define MX6_USB_OTG_WAKEUP_BITS (MX6_BM_WAKEUP_ENABLE | MX6_BM_VBUS_WAKEUP | \ |
| 132 | MX6_BM_ID_WAKEUP) | 138 | MX6_BM_ID_WAKEUP) |
| 133 | 139 | ||
| @@ -649,6 +655,21 @@ static int usbmisc_imx7d_init(struct imx_usbmisc_data *data) · 515 unmodified lines | |||
| 649 | writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID | 655 | writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID |
| 650 | | MX7D_USBNC_AUTO_RESUME, | 656 | | MX7D_USBNC_AUTO_RESUME, |
| 651 | usbmisc->base + MX7D_USBNC_USB_CTRL2); | 657 | usbmisc->base + MX7D_USBNC_USB_CTRL2); |
| 658 | /* PHY tuning for signal quality */ | ||
| 659 | reg = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG1); | ||
| 660 | if (data->emp_curr_control && data->emp_curr_control <= | ||
| 661 | (TXPREEMPAMPTUNE0_MASK >> TXPREEMPAMPTUNE0_BIT)) { | ||
| 662 | reg &= ~TXPREEMPAMPTUNE0_MASK; | ||
| 663 | reg |= (data->emp_curr_control << TXPREEMPAMPTUNE0_BIT); | ||
| 664 | } | ||
| 665 | |||
| 666 | if (data->dc_vol_level_adjust && data->dc_vol_level_adjust <= | ||
| 667 | (TXVREFTUNE0_MASK >> TXVREFTUNE0_BIT)) { | ||
| 668 | reg &= ~TXVREFTUNE0_MASK; | ||
| 669 | reg |= (data->dc_vol_level_adjust << TXVREFTUNE0_BIT); | ||
| 670 | } | ||
| 671 | |||
| 672 | writel(reg, usbmisc->base + MX7D_USB_OTG_PHY_CFG1); | ||
| 652 | } | 673 | } |
| 653 | 674 | ||
| 654 | spin_unlock_irqrestore(&usbmisc->lock, flags); | 675 | spin_unlock_irqrestore(&usbmisc->lock, flags); |
| @@ -173,7 +173,7 @@ static int acm_wb_alloc(struct acm *acm) · 172 unmodified lines | |||
| 173 | for (;;) { | 173 | for (;;) { |
| 174 | wb = &acm->wb[wbn]; | 174 | wb = &acm->wb[wbn]; |
| 175 | if (!wb->use) { | 175 | if (!wb->use) { |
| 176 | wb->use = 1; | 176 | wb->use = true; |
| 177 | wb->len = 0; | 177 | wb->len = 0; |
| 178 | return wbn; | 178 | return wbn; |
| 179 | } | 179 | } |
| @@ -191,7 +191,8 @@ static int acm_wb_is_avail(struct acm *acm) · 11 unmodified lines | |||
| 191 | n = ACM_NW; | 191 | n = ACM_NW; |
| 192 | spin_lock_irqsave(&acm->write_lock, flags); | 192 | spin_lock_irqsave(&acm->write_lock, flags); |
| 193 | for (i = 0; i < ACM_NW; i++) | 193 | for (i = 0; i < ACM_NW; i++) |
| 194 | n -= acm->wb[i].use; | 194 | if(acm->wb[i].use) |
| 195 | n--; | ||
| 195 | spin_unlock_irqrestore(&acm->write_lock, flags); | 196 | spin_unlock_irqrestore(&acm->write_lock, flags); |
| 196 | return n; | 197 | return n; |
| 197 | } | 198 | } |
| @@ -201,7 +202,7 @@ static int acm_wb_is_avail(struct acm *acm) · 3 unmodified lines | |||
| 201 | */ | 202 | */ |
| 202 | static void acm_write_done(struct acm *acm, struct acm_wb *wb) | 203 | static void acm_write_done(struct acm *acm, struct acm_wb *wb) |
| 203 | { | 204 | { |
| 204 | wb->use = 0; | 205 | wb->use = false; |
| 205 | acm->transmitting--; | 206 | acm->transmitting--; |
| 206 | usb_autopm_put_interface_async(acm->control); | 207 | usb_autopm_put_interface_async(acm->control); |
| 207 | } | 208 | } |
| @@ -741,7 +742,7 @@ static void acm_port_shutdown(struct tty_port *port) · 533 unmodified lines | |||
| 741 | if (!urb) | 742 | if (!urb) |
| 742 | break; | 743 | break; |
| 743 | wb = urb->context; | 744 | wb = urb->context; |
| 744 | wb->use = 0; | 745 | wb->use = false; |
| 745 | usb_autopm_put_interface_async(acm->control); | 746 | usb_autopm_put_interface_async(acm->control); |
| 746 | } | 747 | } |
| 747 | 748 | ||
| @@ -792,7 +793,7 @@ static int acm_tty_write(struct tty_struct *tty, · 44 unmodified lines | |||
| 792 | wb = &acm->wb[wbn]; | 793 | wb = &acm->wb[wbn]; |
| 793 | 794 | ||
| 794 | if (!acm->dev) { | 795 | if (!acm->dev) { |
| 795 | wb->use = 0; | 796 | wb->use = false; |
| 796 | spin_unlock_irqrestore(&acm->write_lock, flags); | 797 | spin_unlock_irqrestore(&acm->write_lock, flags); |
| 797 | return -ENODEV; | 798 | return -ENODEV; |
| 798 | } | 799 | } |
| @@ -804,7 +805,7 @@ static int acm_tty_write(struct tty_struct *tty, · 5 unmodified lines | |||
| 804 | 805 | ||
| 805 | stat = usb_autopm_get_interface_async(acm->control); | 806 | stat = usb_autopm_get_interface_async(acm->control); |
| 806 | if (stat) { | 807 | if (stat) { |
| 807 | wb->use = 0; | 808 | wb->use = false; |
| 808 | spin_unlock_irqrestore(&acm->write_lock, flags); | 809 | spin_unlock_irqrestore(&acm->write_lock, flags); |
| 809 | return stat; | 810 | return stat; |
| 810 | } | 811 | } |
| @@ -1196,9 +1197,6 @@ static int acm_probe(struct usb_interface *intf, · 385 unmodified lines | |||
| 1196 | return -EINVAL; | 1197 | return -EINVAL; |
| 1197 | } | 1198 | } |
| 1198 | 1199 | ||
| 1199 | if (!intf->cur_altsetting) | ||
| 1200 | return -EINVAL; | ||
| 1201 | |||
| 1202 | if (!buflen) { | 1200 | if (!buflen) { |
| 1203 | if (intf->cur_altsetting->endpoint && | 1201 | if (intf->cur_altsetting->endpoint && |
| 1204 | intf->cur_altsetting->endpoint->extralen && | 1202 | intf->cur_altsetting->endpoint->extralen && |
| @@ -1221,39 +1219,42 @@ static int acm_probe(struct usb_interface *intf, · 16 unmodified lines | |||
| 1221 | call_intf_num = cmgmd->bDataInterface; | 1219 | call_intf_num = cmgmd->bDataInterface; |
| 1222 | 1220 | ||
| 1223 | if (!union_header) { | 1221 | if (!union_header) { |
| 1224 | if (call_intf_num > 0) { | 1222 | if (intf->cur_altsetting->desc.bNumEndpoints == 3) { |
| 1223 | dev_dbg(&intf->dev, "No union descriptor, assuming single interface\n"); | ||
| 1224 | combined_interfaces = 1; | ||
| 1225 | control_interface = data_interface = intf; | ||
| 1226 | goto look_for_collapsed_interface; | ||
| 1227 | } else if (call_intf_num > 0) { | ||
| 1225 | dev_dbg(&intf->dev, "No union descriptor, using call management descriptor\n"); | 1228 | dev_dbg(&intf->dev, "No union descriptor, using call management descriptor\n"); |
| 1226 | /* quirks for Droids MuIn LCD */ | 1229 | data_intf_num = call_intf_num; |
| 1227 | if (quirks & NO_DATA_INTERFACE) { | 1230 | data_interface = usb_ifnum_to_if(usb_dev, data_intf_num); |
| 1228 | data_interface = usb_ifnum_to_if(usb_dev, 0); | ||
| 1229 | } else { | ||
| 1230 | data_intf_num = call_intf_num; | ||
| 1231 | data_interface = usb_ifnum_to_if(usb_dev, data_intf_num); | ||
| 1232 | } | ||
| 1233 | control_interface = intf; | 1231 | control_interface = intf; |
| 1234 | } else { | 1232 | } else { |
| 1235 | if (intf->cur_altsetting->desc.bNumEndpoints != 3) { | 1233 | dev_dbg(&intf->dev, "No union descriptor, giving up\n"); |
| 1236 | dev_dbg(&intf->dev,"No union descriptor, giving up\n"); | 1234 | return -ENODEV; |
| 1237 | return -ENODEV; | ||
| 1238 | } else { | ||
| 1239 | dev_warn(&intf->dev,"No union descriptor, testing for castrated device\n"); | ||
| 1240 | combined_interfaces = 1; | ||
| 1241 | control_interface = data_interface = intf; | ||
| 1242 | goto look_for_collapsed_interface; | ||
| 1243 | } | ||
| 1244 | } | 1235 | } |
| 1245 | } else { | 1236 | } else { |
| 1237 | int class = -1; | ||
| 1238 | |||
| 1246 | data_intf_num = union_header->bSlaveInterface0; | 1239 | data_intf_num = union_header->bSlaveInterface0; |
| 1247 | control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0); | 1240 | control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0); |
| 1248 | data_interface = usb_ifnum_to_if(usb_dev, data_intf_num); | 1241 | data_interface = usb_ifnum_to_if(usb_dev, data_intf_num); |
| 1242 | |||
| 1243 | if (control_interface) | ||
| 1244 | class = control_interface->cur_altsetting->desc.bInterfaceClass; | ||
| 1245 | |||
| 1246 | if (class != USB_CLASS_COMM && class != USB_CLASS_CDC_DATA) { | ||
| 1247 | dev_dbg(&intf->dev, "Broken union descriptor, assuming single interface\n"); | ||
| 1248 | combined_interfaces = 1; | ||
| 1249 | control_interface = data_interface = intf; | ||
| 1250 | goto look_for_collapsed_interface; | ||
| 1251 | } | ||
| 1249 | } | 1252 | } |
| 1250 | 1253 | ||
| 1251 | if (!control_interface || !data_interface) { | 1254 | if (!control_interface || !data_interface) { |
| 1252 | dev_dbg(&intf->dev, "no interfaces\n"); | 1255 | dev_dbg(&intf->dev, "no interfaces\n"); |
| 1253 | return -ENODEV; | 1256 | return -ENODEV; |
| 1254 | } | 1257 | } |
| 1255 | if (!data_interface->cur_altsetting || !control_interface->cur_altsetting) | ||
| 1256 | return -ENODEV; | ||
| 1257 | 1258 | ||
| 1258 | if (data_intf_num != call_intf_num) | 1259 | if (data_intf_num != call_intf_num) |
| 1259 | dev_dbg(&intf->dev, "Separate call control interface. That is not fully supported.\n"); | 1260 | dev_dbg(&intf->dev, "Separate call control interface. That is not fully supported.\n"); |
| @@ -1280,10 +1281,8 @@ look_for_collapsed_interface: · 20 unmodified lines | |||
| 1280 | skip_normal_probe: | 1281 | skip_normal_probe: |
| 1281 | 1282 | ||
| 1282 | /*workaround for switched interfaces */ | 1283 | /*workaround for switched interfaces */ |
| 1283 | if (data_interface->cur_altsetting->desc.bInterfaceClass | 1284 | if (data_interface->cur_altsetting->desc.bInterfaceClass != USB_CLASS_CDC_DATA) { |
| 1284 | != CDC_DATA_INTERFACE_TYPE) { | 1285 | if (control_interface->cur_altsetting->desc.bInterfaceClass == USB_CLASS_CDC_DATA) { |
| 1285 | if (control_interface->cur_altsetting->desc.bInterfaceClass | ||
| 1286 | == CDC_DATA_INTERFACE_TYPE) { | ||
| 1287 | dev_dbg(&intf->dev, | 1286 | dev_dbg(&intf->dev, |
| 1288 | "Your device has switched interfaces.\n"); | 1287 | "Your device has switched interfaces.\n"); |
| 1289 | swap(control_interface, data_interface); | 1288 | swap(control_interface, data_interface); |
| @@ -1876,11 +1875,6 @@ static const struct usb_device_id acm_ids[] = { · 586 unmodified lines | |||
| 1876 | 1875 | ||
| 1877 | /* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */ | 1876 | /* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */ |
| 1878 | 1877 | ||
| 1879 | /* Support for Droids MuIn LCD */ | ||
| 1880 | { USB_DEVICE(0x04d8, 0x000b), | ||
| 1881 | .driver_info = NO_DATA_INTERFACE, | ||
| 1882 | }, | ||
| 1883 | |||
| 1884 | #if IS_ENABLED(CONFIG_INPUT_IMS_PCU) | 1878 | #if IS_ENABLED(CONFIG_INPUT_IMS_PCU) |
| 1885 | { USB_DEVICE(0x04d8, 0x0082), /* Application mode */ | 1879 | { USB_DEVICE(0x04d8, 0x0082), /* Application mode */ |
| 1886 | .driver_info = IGNORE_DEVICE, | 1880 | .driver_info = IGNORE_DEVICE, |
| @@ -1906,6 +1900,17 @@ static const struct usb_device_id acm_ids[] = { · 19 unmodified lines | |||
| 1906 | .driver_info = IGNORE_DEVICE, | 1900 | .driver_info = IGNORE_DEVICE, |
| 1907 | }, | 1901 | }, |
| 1908 | 1902 | ||
| 1903 | /* Exclude ETAS ES58x */ | ||
| 1904 | { USB_DEVICE(0x108c, 0x0159), /* ES581.4 */ | ||
| 1905 | .driver_info = IGNORE_DEVICE, | ||
| 1906 | }, | ||
| 1907 | { USB_DEVICE(0x108c, 0x0168), /* ES582.1 */ | ||
| 1908 | .driver_info = IGNORE_DEVICE, | ||
| 1909 | }, | ||
| 1910 | { USB_DEVICE(0x108c, 0x0169), /* ES584.1 */ | ||
| 1911 | .driver_info = IGNORE_DEVICE, | ||
| 1912 | }, | ||
| 1913 | |||
| 1909 | { USB_DEVICE(0x1bc7, 0x0021), /* Telit 3G ACM only composition */ | 1914 | { USB_DEVICE(0x1bc7, 0x0021), /* Telit 3G ACM only composition */ |
| 1910 | .driver_info = SEND_ZERO_PACKET, | 1915 | .driver_info = SEND_ZERO_PACKET, |
| 1911 | }, | 1916 | }, |
| @@ -64,12 +64,12 @@ · 63 unmodified lines | |||
| 64 | #define ACM_NR 16 | 64 | #define ACM_NR 16 |
| 65 | 65 | ||
| 66 | struct acm_wb { | 66 | struct acm_wb { |
| 67 | unsigned char *buf; | 67 | u8 *buf; |
| 68 | dma_addr_t dmah; | 68 | dma_addr_t dmah; |
| 69 | int len; | 69 | unsigned int len; |
| 70 | int use; | ||
| 71 | struct urb *urb; | 70 | struct urb *urb; |
| 72 | struct acm *instance; | 71 | struct acm *instance; |
| 72 | bool use; | ||
| 73 | }; | 73 | }; |
| 74 | 74 | ||
| 75 | struct acm_rb { | 75 | struct acm_rb { |
| @@ -131,15 +131,12 @@ struct acm { · 55 unmodified lines | |||
| 131 | unsigned long quirks; | 131 | unsigned long quirks; |
| 132 | }; | 132 | }; |
| 133 | 133 | ||
| 134 | #define CDC_DATA_INTERFACE_TYPE 0x0a | ||
| 135 | |||
| 136 | /* constants describing various quirks and errors */ | 134 | /* constants describing various quirks and errors */ |
| 137 | #define NO_UNION_NORMAL BIT(0) | 135 | #define NO_UNION_NORMAL BIT(0) |
| 138 | #define SINGLE_RX_URB BIT(1) | 136 | #define SINGLE_RX_URB BIT(1) |
| 139 | #define NO_CAP_LINE BIT(2) | 137 | #define NO_CAP_LINE BIT(2) |
| 140 | #define NO_DATA_INTERFACE BIT(4) | 138 | #define IGNORE_DEVICE BIT(3) |
| 141 | #define IGNORE_DEVICE BIT(5) | 139 | #define QUIRK_CONTROL_LINE_STATE BIT(4) |
| 142 | #define QUIRK_CONTROL_LINE_STATE BIT(6) | 140 | #define CLEAR_HALT_CONDITIONS BIT(5) |
| 143 | #define CLEAR_HALT_CONDITIONS BIT(7) | 141 | #define SEND_ZERO_PACKET BIT(6) |
| 144 | #define SEND_ZERO_PACKET BIT(8) | 142 | #define DISABLE_ECHO BIT(7) |
| 145 | #define DISABLE_ECHO BIT(9) | ||
| @@ -58,6 +58,9 @@ MODULE_DEVICE_TABLE (usb, wdm_ids); · 57 unmodified lines | |||
| 58 | 58 | ||
| 59 | #define WDM_MAX 16 | 59 | #define WDM_MAX 16 |
| 60 | 60 | ||
| 61 | /* we cannot wait forever at flush() */ | ||
| 62 | #define WDM_FLUSH_TIMEOUT (30 * HZ) | ||
| 63 | |||
| 61 | /* CDC-WMC r1.1 requires wMaxCommand to be "at least 256 decimal (0x100)" */ | 64 | /* CDC-WMC r1.1 requires wMaxCommand to be "at least 256 decimal (0x100)" */ |
| 62 | #define WDM_DEFAULT_BUFSIZE 256 | 65 | #define WDM_DEFAULT_BUFSIZE 256 |
| 63 | 66 | ||
| @@ -151,7 +154,7 @@ static void wdm_out_callback(struct urb *urb) · 87 unmodified lines | |||
| 151 | kfree(desc->outbuf); | 154 | kfree(desc->outbuf); |
| 152 | desc->outbuf = NULL; | 155 | desc->outbuf = NULL; |
| 153 | clear_bit(WDM_IN_USE, &desc->flags); | 156 | clear_bit(WDM_IN_USE, &desc->flags); |
| 154 | wake_up(&desc->wait); | 157 | wake_up_all(&desc->wait); |
| 155 | } | 158 | } |
| 156 | 159 | ||
| 157 | static void wdm_in_callback(struct urb *urb) | 160 | static void wdm_in_callback(struct urb *urb) |
| @@ -393,6 +396,9 @@ static ssize_t wdm_write · 235 unmodified lines | |||
| 393 | if (test_bit(WDM_RESETTING, &desc->flags)) | 396 | if (test_bit(WDM_RESETTING, &desc->flags)) |
| 394 | r = -EIO; | 397 | r = -EIO; |
| 395 | 398 | ||
| 399 | if (test_bit(WDM_DISCONNECTING, &desc->flags)) | ||
| 400 | r = -ENODEV; | ||
| 401 | |||
| 396 | if (r < 0) { | 402 | if (r < 0) { |
| 397 | rv = r; | 403 | rv = r; |
| 398 | goto out_free_mem_pm; | 404 | goto out_free_mem_pm; |
| @@ -424,6 +430,7 @@ static ssize_t wdm_write · 25 unmodified lines | |||
| 424 | if (rv < 0) { | 430 | if (rv < 0) { |
| 425 | desc->outbuf = NULL; | 431 | desc->outbuf = NULL; |
| 426 | clear_bit(WDM_IN_USE, &desc->flags); | 432 | clear_bit(WDM_IN_USE, &desc->flags); |
| 433 | wake_up_all(&desc->wait); /* for wdm_wait_for_response() */ | ||
| 427 | dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv); | 434 | dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv); |
| 428 | rv = usb_translate_errors(rv); | 435 | rv = usb_translate_errors(rv); |
| 429 | goto out_free_mem_pm; | 436 | goto out_free_mem_pm; |
| @@ -583,28 +590,58 @@ err: · 153 unmodified lines | |||
| 583 | return rv; | 590 | return rv; |
| 584 | } | 591 | } |
| 585 | 592 | ||
| 586 | static int wdm_flush(struct file *file, fl_owner_t id) | 593 | static int wdm_wait_for_response(struct file *file, long timeout) |
| 587 | { | 594 | { |
| 588 | struct wdm_device *desc = file->private_data; | 595 | struct wdm_device *desc = file->private_data; |
| 596 | long rv; /* Use long here because (int) MAX_SCHEDULE_TIMEOUT < 0. */ | ||
| 597 | |||
| 598 | /* | ||
| 599 | * Needs both flags. We cannot do with one because resetting it would | ||
| 600 | * cause a race with write() yet we need to signal a disconnect. | ||
| 601 | */ | ||
| 602 | rv = wait_event_interruptible_timeout(desc->wait, | ||
| 603 | !test_bit(WDM_IN_USE, &desc->flags) || | ||
| 604 | test_bit(WDM_DISCONNECTING, &desc->flags), | ||
| 605 | timeout); | ||
| 589 | 606 | ||
| 590 | wait_event(desc->wait, | 607 | /* |
| 591 | /* | 608 | * To report the correct error. This is best effort. |
| 592 | * needs both flags. We cannot do with one | 609 | * We are inevitably racing with the hardware. |
| 593 | * because resetting it would cause a race | 610 | */ |
| 594 | * with write() yet we need to signal | ||
| 595 | * a disconnect | ||
| 596 | */ | ||
| 597 | !test_bit(WDM_IN_USE, &desc->flags) || | ||
| 598 | test_bit(WDM_DISCONNECTING, &desc->flags)); | ||
| 599 | |||
| 600 | /* cannot dereference desc->intf if WDM_DISCONNECTING */ | ||
| 601 | if (test_bit(WDM_DISCONNECTING, &desc->flags)) | 611 | if (test_bit(WDM_DISCONNECTING, &desc->flags)) |
| 602 | return -ENODEV; | 612 | return -ENODEV; |
| 603 | if (desc->werr < 0) | 613 | if (!rv) |
| 604 | dev_err(&desc->intf->dev, "Error in flush path: %d\n", | 614 | return -EIO; |
| 605 | desc->werr); | 615 | if (rv < 0) |
| 616 | return -EINTR; | ||
| 617 | |||
| 618 | spin_lock_irq(&desc->iuspin); | ||
| 619 | rv = desc->werr; | ||
| 620 | desc->werr = 0; | ||
| 621 | spin_unlock_irq(&desc->iuspin); | ||
| 622 | |||
| 623 | return usb_translate_errors(rv); | ||
| 624 | |||
| 625 | } | ||
| 626 | |||
| 627 | /* | ||
| 628 | * You need to send a signal when you react to malicious or defective hardware. | ||
| 629 | * Also, don't abort when fsync() returned -EINVAL, for older kernels which do | ||
| 630 | * not implement wdm_flush() will return -EINVAL. | ||
| 631 | */ | ||
| 632 | static int wdm_fsync(struct file *file, loff_t start, loff_t end, int datasync) | ||
| 633 | { | ||
| 634 | return wdm_wait_for_response(file, MAX_SCHEDULE_TIMEOUT); | ||
| 635 | } | ||
| 606 | 636 | ||
| 607 | return usb_translate_errors(desc->werr); | 637 | /* |
| 638 | * Same with wdm_fsync(), except it uses finite timeout in order to react to | ||
| 639 | * malicious or defective hardware which ceased communication after close() was | ||
| 640 | * implicitly called due to process termination. | ||
| 641 | */ | ||
| 642 | static int wdm_flush(struct file *file, fl_owner_t id) | ||
| 643 | { | ||
| 644 | return wdm_wait_for_response(file, WDM_FLUSH_TIMEOUT); | ||
| 608 | } | 645 | } |
| 609 | 646 | ||
| 610 | static __poll_t wdm_poll(struct file *file, struct poll_table_struct *wait) | 647 | static __poll_t wdm_poll(struct file *file, struct poll_table_struct *wait) |
| @@ -729,6 +766,7 @@ static const struct file_operations wdm_fops = { · 118 unmodified lines | |||
| 729 | .owner = THIS_MODULE, | 766 | .owner = THIS_MODULE, |
| 730 | .read = wdm_read, | 767 | .read = wdm_read, |
| 731 | .write = wdm_write, | 768 | .write = wdm_write, |
| 769 | .fsync = wdm_fsync, | ||
| 732 | .open = wdm_open, | 770 | .open = wdm_open, |
| 733 | .flush = wdm_flush, | 771 | .flush = wdm_flush, |
| 734 | .release = wdm_release, | 772 | .release = wdm_release, |
| @@ -91,14 +91,14 @@ static void usb_conn_detect_cable(struct work_struct *work) · 90 unmodified lines | |||
| 91 | return; | 91 | return; |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | if (info->last_role == USB_ROLE_HOST) | 94 | if (info->last_role == USB_ROLE_HOST && info->vbus) |
| 95 | regulator_disable(info->vbus); | 95 | regulator_disable(info->vbus); |
| 96 | 96 | ||
| 97 | ret = usb_role_switch_set_role(info->role_sw, role); | 97 | ret = usb_role_switch_set_role(info->role_sw, role); |
| 98 | if (ret) | 98 | if (ret) |
| 99 | dev_err(info->dev, "failed to set role: %d\n", ret); | 99 | dev_err(info->dev, "failed to set role: %d\n", ret); |
| 100 | 100 | ||
| 101 | if (role == USB_ROLE_HOST) { | 101 | if (role == USB_ROLE_HOST && info->vbus) { |
| 102 | ret = regulator_enable(info->vbus); | 102 | ret = regulator_enable(info->vbus); |
| 103 | if (ret) | 103 | if (ret) |
| 104 | dev_err(info->dev, "enable vbus regulator failed\n"); | 104 | dev_err(info->dev, "enable vbus regulator failed\n"); |
| @@ -106,8 +106,9 @@ static void usb_conn_detect_cable(struct work_struct *work) · 1 unmodified line | |||
| 106 | 106 | ||
| 107 | info->last_role = role; | 107 | info->last_role = role; |
| 108 | 108 | ||
| 109 | dev_dbg(info->dev, "vbus regulator is %s\n", | 109 | if (info->vbus) |
| 110 | regulator_is_enabled(info->vbus) ? "enabled" : "disabled"); | 110 | dev_dbg(info->dev, "vbus regulator is %s\n", |
| 111 | regulator_is_enabled(info->vbus) ? "enabled" : "disabled"); | ||
| 111 | 112 | ||
| 112 | power_supply_changed(info->charger); | 113 | power_supply_changed(info->charger); |
| 113 | } | 114 | } |
| @@ -156,6 +157,7 @@ static int usb_conn_probe(struct platform_device *pdev) · 42 unmodified lines | |||
| 156 | struct power_supply_config cfg = { | 157 | struct power_supply_config cfg = { |
| 157 | .of_node = dev->of_node, | 158 | .of_node = dev->of_node, |
| 158 | }; | 159 | }; |
| 160 | bool need_vbus = true; | ||
| 159 | int ret = 0; | 161 | int ret = 0; |
| 160 | 162 | ||
| 161 | info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); | 163 | info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); |
| @@ -185,10 +187,26 @@ static int usb_conn_probe(struct platform_device *pdev) · 23 unmodified lines | |||
| 185 | 187 | ||
| 186 | INIT_DELAYED_WORK(&info->dw_det, usb_conn_detect_cable); | 188 | INIT_DELAYED_WORK(&info->dw_det, usb_conn_detect_cable); |
| 187 | 189 | ||
| 188 | info->vbus = devm_regulator_get(dev, "vbus"); | 190 | /* |
| 191 | * If the USB connector is a child of a USB port and that port already provides the VBUS | ||
| 192 | * supply, there's no need for the USB connector to provide it again. | ||
| 193 | */ | ||
| 194 | if (dev->parent && dev->parent->of_node) { | ||
| 195 | if (of_find_property(dev->parent->of_node, "vbus-supply", NULL)) | ||
| 196 | need_vbus = false; | ||
| 197 | } | ||
| 198 | |||
| 199 | if (!need_vbus) { | ||
| 200 | info->vbus = devm_regulator_get_optional(dev, "vbus"); | ||
| 201 | if (PTR_ERR(info->vbus) == -ENODEV) | ||
| 202 | info->vbus = NULL; | ||
| 203 | } else { | ||
| 204 | info->vbus = devm_regulator_get(dev, "vbus"); | ||
| 205 | } | ||
| 206 | |||
| 189 | if (IS_ERR(info->vbus)) { | 207 | if (IS_ERR(info->vbus)) { |
| 190 | if (PTR_ERR(info->vbus) != -EPROBE_DEFER) | 208 | if (PTR_ERR(info->vbus) != -EPROBE_DEFER) |
| 191 | dev_err(dev, "failed to get vbus\n"); | 209 | dev_err(dev, "failed to get vbus: %ld\n", PTR_ERR(info->vbus)); |
| 192 | return PTR_ERR(info->vbus); | 210 | return PTR_ERR(info->vbus); |
| 193 | } | 211 | } |
| 194 | 212 | ||
| @@ -266,7 +284,7 @@ static int usb_conn_remove(struct platform_device *pdev) · 71 unmodified lines | |||
| 266 | 284 | ||
| 267 | cancel_delayed_work_sync(&info->dw_det); | 285 | cancel_delayed_work_sync(&info->dw_det); |
| 268 | 286 | ||
| 269 | if (info->last_role == USB_ROLE_HOST) | 287 | if (info->last_role == USB_ROLE_HOST && info->vbus) |
| 270 | regulator_disable(info->vbus); | 288 | regulator_disable(info->vbus); |
| 271 | 289 | ||
| 272 | usb_role_switch_put(info->role_sw); | 290 | usb_role_switch_put(info->role_sw); |
| @@ -32,6 +32,20 @@ config USB_DEFAULT_PERSIST · 31 unmodified lines | |||
| 32 | If you have any questions about this, say Y here, only say N | 32 | If you have any questions about this, say Y here, only say N |
| 33 | if you know exactly what you are doing. | 33 | if you know exactly what you are doing. |
| 34 | 34 | ||
| 35 | config USB_FEW_INIT_RETRIES | ||
| 36 | bool "Limit USB device initialization to only a few retries" | ||
| 37 | help | ||
| 38 | When a new USB device is detected, the kernel tries very hard | ||
| 39 | to initialize and enumerate it, with lots of nested retry loops. | ||
| 40 | This almost always works, but when it fails it can take a long time. | ||
| 41 | This option tells the kernel to make only a few retry attempts, | ||
| 42 | so that the total time required for a failed initialization is | ||
| 43 | no more than 30 seconds (as required by the USB OTG spec). | ||
| 44 | |||
| 45 | Say N here unless you require new-device enumeration failure to | ||
| 46 | occur within 30 seconds (as might be needed in an embedded | ||
| 47 | application). | ||
| 48 | |||
| 35 | config USB_DYNAMIC_MINORS | 49 | config USB_DYNAMIC_MINORS |
| 36 | bool "Dynamic USB minor allocation" | 50 | bool "Dynamic USB minor allocation" |
| 37 | help | 51 | help |
| @@ -39,7 +39,6 @@ · 38 unmodified lines | |||
| 39 | #include <linux/fs.h> | 39 | #include <linux/fs.h> |
| 40 | #include <linux/mm.h> | 40 | #include <linux/mm.h> |
| 41 | #include <linux/gfp.h> | 41 | #include <linux/gfp.h> |
| 42 | #include <linux/poll.h> | ||
| 43 | #include <linux/usb.h> | 42 | #include <linux/usb.h> |
| 44 | #include <linux/usbdevice_fs.h> | 43 | #include <linux/usbdevice_fs.h> |
| 45 | #include <linux/usb/hcd.h> | 44 | #include <linux/usb/hcd.h> |
| @@ -97,22 +96,6 @@ static const char format_endpt[] = · 51 unmodified lines | |||
| 97 | /* E: Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=D?s */ | 96 | /* E: Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=D?s */ |
| 98 | "E: Ad=%02x(%c) Atr=%02x(%-4s) MxPS=%4d Ivl=%d%cs\n"; | 97 | "E: Ad=%02x(%c) Atr=%02x(%-4s) MxPS=%4d Ivl=%d%cs\n"; |
| 99 | 98 | ||
| 100 | /* | ||
| 101 | * Wait for an connect/disconnect event to happen. We initialize | ||
| 102 | * the event counter with an odd number, and each event will increment | ||
| 103 | * the event counter by two, so it will always _stay_ odd. That means | ||
| 104 | * that it will never be zero, so "event 0" will never match a current | ||
| 105 | * event, and thus 'poll' will always trigger as readable for the first | ||
| 106 | * time it gets called. | ||
| 107 | */ | ||
| 108 | static struct device_connect_event { | ||
| 109 | atomic_t count; | ||
| 110 | wait_queue_head_t wait; | ||
| 111 | } device_event = { | ||
| 112 | .count = ATOMIC_INIT(1), | ||
| 113 | .wait = __WAIT_QUEUE_HEAD_INITIALIZER(device_event.wait) | ||
| 114 | }; | ||
| 115 | |||
| 116 | struct class_info { | 99 | struct class_info { |
| 117 | int class; | 100 | int class; |
| 118 | char *class_name; | 101 | char *class_name; |
| @@ -146,12 +129,6 @@ static const struct class_info clas_info[] = { · 27 unmodified lines | |||
| 146 | 129 | ||
| 147 | /*****************************************************************/ | 130 | /*****************************************************************/ |
| 148 | 131 | ||
| 149 | void usbfs_conn_disc_event(void) | ||
| 150 | { | ||
| 151 | atomic_add(2, &device_event.count); | ||
| 152 | wake_up(&device_event.wait); | ||
| 153 | } | ||
| 154 | |||
| 155 | static const char *class_decode(const int class) | 132 | static const char *class_decode(const int class) |
| 156 | { | 133 | { |
| 157 | int ix; | 134 | int ix; |
| @@ -623,25 +600,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, · 465 unmodified lines | |||
| 623 | return total_written; | 600 | return total_written; |
| 624 | } | 601 | } |
| 625 | 602 | ||
| 626 | /* Kernel lock for "lastev" protection */ | ||
| 627 | static __poll_t usb_device_poll(struct file *file, | ||
| 628 | struct poll_table_struct *wait) | ||
| 629 | { | ||
| 630 | unsigned int event_count; | ||
| 631 | |||
| 632 | poll_wait(file, &device_event.wait, wait); | ||
| 633 | |||
| 634 | event_count = atomic_read(&device_event.count); | ||
| 635 | if (file->f_version != event_count) { | ||
| 636 | file->f_version = event_count; | ||
| 637 | return EPOLLIN | EPOLLRDNORM; | ||
| 638 | } | ||
| 639 | |||
| 640 | return 0; | ||
| 641 | } | ||
| 642 | |||
| 643 | const struct file_operations usbfs_devices_fops = { | 603 | const struct file_operations usbfs_devices_fops = { |
| 644 | .llseek = no_seek_end_llseek, | 604 | .llseek = no_seek_end_llseek, |
| 645 | .read = usb_device_read, | 605 | .read = usb_device_read, |
| 646 | .poll = usb_device_poll, | ||
| 647 | }; | 606 | }; |
| @@ -991,8 +991,7 @@ int usb_register_device_driver(struct usb_device_driver *new_udriver, · 990 unmodified lines | |||
| 991 | bus_for_each_dev(&usb_bus_type, NULL, new_udriver, | 991 | bus_for_each_dev(&usb_bus_type, NULL, new_udriver, |
| 992 | __usb_bus_reprobe_drivers); | 992 | __usb_bus_reprobe_drivers); |
| 993 | } else { | 993 | } else { |
| 994 | printk(KERN_ERR "%s: error %d registering device " | 994 | pr_err("%s: error %d registering device driver %s\n", |
| 995 | " driver %s\n", | ||
| 996 | usbcore_name, retval, new_udriver->name); | 995 | usbcore_name, retval, new_udriver->name); |
| 997 | } | 996 | } |
| 998 | 997 | ||
| @@ -1068,9 +1067,8 @@ out: · 69 unmodified lines | |||
| 1068 | out_newid: | 1067 | out_newid: |
| 1069 | driver_unregister(&new_driver->drvwrap.driver); | 1068 | driver_unregister(&new_driver->drvwrap.driver); |
| 1070 | 1069 | ||
| 1071 | printk(KERN_ERR "%s: error %d registering interface " | 1070 | pr_err("%s: error %d registering interface driver %s\n", |
| 1072 | " driver %s\n", | 1071 | usbcore_name, retval, new_driver->name); |
| 1073 | usbcore_name, retval, new_driver->name); | ||
| 1074 | goto out; | 1072 | goto out; |
| 1075 | } | 1073 | } |
| 1076 | EXPORT_SYMBOL_GPL(usb_register_driver); | 1074 | EXPORT_SYMBOL_GPL(usb_register_driver); |
| @@ -195,7 +195,7 @@ int usb_choose_configuration(struct usb_device *udev) · 194 unmodified lines | |||
| 195 | } | 195 | } |
| 196 | EXPORT_SYMBOL_GPL(usb_choose_configuration); | 196 | EXPORT_SYMBOL_GPL(usb_choose_configuration); |
| 197 | 197 | ||
| 198 | static int __check_usb_generic(struct device_driver *drv, void *data) | 198 | static int __check_for_non_generic_match(struct device_driver *drv, void *data) |
| 199 | { | 199 | { |
| 200 | struct usb_device *udev = data; | 200 | struct usb_device *udev = data; |
| 201 | struct usb_device_driver *udrv; | 201 | struct usb_device_driver *udrv; |
| @@ -219,7 +219,7 @@ static bool usb_generic_driver_match(struct usb_device *udev) · 17 unmodified lines | |||
| 219 | * If any other driver wants the device, leave the device to this other | 219 | * If any other driver wants the device, leave the device to this other |
| 220 | * driver. | 220 | * driver. |
| 221 | */ | 221 | */ |
| 222 | if (bus_for_each_drv(&usb_bus_type, NULL, udev, __check_usb_generic)) | 222 | if (bus_for_each_drv(&usb_bus_type, NULL, udev, __check_for_non_generic_match)) |
| 223 | return false; | 223 | return false; |
| 224 | 224 | ||
| 225 | return true; | 225 | return true; |
| @@ -1657,9 +1657,9 @@ static void __usb_hcd_giveback_urb(struct urb *urb) · 1656 unmodified lines | |||
| 1657 | usb_put_urb(urb); | 1657 | usb_put_urb(urb); |
| 1658 | } | 1658 | } |
| 1659 | 1659 | ||
| 1660 | static void usb_giveback_urb_bh(unsigned long param) | 1660 | static void usb_giveback_urb_bh(struct tasklet_struct *t) |
| 1661 | { | 1661 | { |
| 1662 | struct giveback_urb_bh *bh = (struct giveback_urb_bh *)param; | 1662 | struct giveback_urb_bh *bh = from_tasklet(bh, t, bh); |
| 1663 | struct list_head local_list; | 1663 | struct list_head local_list; |
| 1664 | 1664 | ||
| 1665 | spin_lock_irq(&bh->lock); | 1665 | spin_lock_irq(&bh->lock); |
| @@ -2403,7 +2403,7 @@ static void init_giveback_urb_bh(struct giveback_urb_bh *bh) · 737 unmodified lines | |||
| 2403 | 2403 | ||
| 2404 | spin_lock_init(&bh->lock); | 2404 | spin_lock_init(&bh->lock); |
| 2405 | INIT_LIST_HEAD(&bh->head); | 2405 | INIT_LIST_HEAD(&bh->head); |
| 2406 | tasklet_init(&bh->bh, usb_giveback_urb_bh, (unsigned long)bh); | 2406 | tasklet_setup(&bh->bh, usb_giveback_urb_bh); |
| 2407 | } | 2407 | } |
| 2408 | 2408 | ||
| 2409 | struct usb_hcd *__usb_create_hcd(const struct hc_driver *driver, | 2409 | struct usb_hcd *__usb_create_hcd(const struct hc_driver *driver, |
| @@ -2705,11 +2705,20 @@ static unsigned hub_is_wusb(struct usb_hub *hub) · 2704 unmodified lines | |||
| 2705 | } | 2705 | } |
| 2706 | 2706 | ||
| 2707 | 2707 | ||
| 2708 | #ifdef CONFIG_USB_FEW_INIT_RETRIES | ||
| 2709 | #define PORT_RESET_TRIES 2 | ||
| 2710 | #define SET_ADDRESS_TRIES 1 | ||
| 2711 | #define GET_DESCRIPTOR_TRIES 1 | ||
| 2712 | #define GET_MAXPACKET0_TRIES 1 | ||
| 2713 | #define PORT_INIT_TRIES 4 | ||
| 2714 | |||
| 2715 | #else | ||
| 2708 | #define PORT_RESET_TRIES 5 | 2716 | #define PORT_RESET_TRIES 5 |
| 2709 | #define SET_ADDRESS_TRIES 2 | 2717 | #define SET_ADDRESS_TRIES 2 |
| 2710 | #define GET_DESCRIPTOR_TRIES 2 | 2718 | #define GET_DESCRIPTOR_TRIES 2 |
| 2711 | #define SET_CONFIG_TRIES (2 * (use_both_schemes + 1)) | 2719 | #define GET_MAXPACKET0_TRIES 3 |
| 2712 | #define USE_NEW_SCHEME(i, scheme) ((i) / 2 == (int)(scheme)) | 2720 | #define PORT_INIT_TRIES 4 |
| 2721 | #endif /* CONFIG_USB_FEW_INIT_RETRIES */ | ||
| 2713 | 2722 | ||
| 2714 | #define HUB_ROOT_RESET_TIME 60 /* times are in msec */ | 2723 | #define HUB_ROOT_RESET_TIME 60 /* times are in msec */ |
| 2715 | #define HUB_SHORT_RESET_TIME 10 | 2724 | #define HUB_SHORT_RESET_TIME 10 |
| @@ -2717,23 +2726,31 @@ static unsigned hub_is_wusb(struct usb_hub *hub) · 1 unmodified line | |||
| 2717 | #define HUB_LONG_RESET_TIME 200 | 2726 | #define HUB_LONG_RESET_TIME 200 |
| 2718 | #define HUB_RESET_TIMEOUT 800 | 2727 | #define HUB_RESET_TIMEOUT 800 |
| 2719 | 2728 | ||
| 2720 | /* | ||
| 2721 | * "New scheme" enumeration causes an extra state transition to be | ||
| 2722 | * exposed to an xhci host and causes USB3 devices to receive control | ||
| 2723 | * commands in the default state. This has been seen to cause | ||
| 2724 | * enumeration failures, so disable this enumeration scheme for USB3 | ||
| 2725 | * devices. | ||
| 2726 | */ | ||
| 2727 | static bool use_new_scheme(struct usb_device *udev, int retry, | 2729 | static bool use_new_scheme(struct usb_device *udev, int retry, |
| 2728 | struct usb_port *port_dev) | 2730 | struct usb_port *port_dev) |
| 2729 | { | 2731 | { |
| 2730 | int old_scheme_first_port = | 2732 | int old_scheme_first_port = |
| 2731 | port_dev->quirks & USB_PORT_QUIRK_OLD_SCHEME; | 2733 | (port_dev->quirks & USB_PORT_QUIRK_OLD_SCHEME) || |
| 2734 | old_scheme_first; | ||
| 2732 | 2735 | ||
| 2736 | /* | ||
| 2737 | * "New scheme" enumeration causes an extra state transition to be | ||
| 2738 | * exposed to an xhci host and causes USB3 devices to receive control | ||
| 2739 | * commands in the default state. This has been seen to cause | ||
| 2740 | * enumeration failures, so disable this enumeration scheme for USB3 | ||
| 2741 | * devices. | ||
| 2742 | */ | ||
| 2733 | if (udev->speed >= USB_SPEED_SUPER) | 2743 | if (udev->speed >= USB_SPEED_SUPER) |
| 2734 | return false; | 2744 | return false; |
| 2735 | 2745 | ||
| 2736 | return USE_NEW_SCHEME(retry, old_scheme_first_port || old_scheme_first); | 2746 | /* |
| 2747 | * If use_both_schemes is set, use the first scheme (whichever | ||
| 2748 | * it is) for the larger half of the retries, then use the other | ||
| 2749 | * scheme. Otherwise, use the first scheme for all the retries. | ||
| 2750 | */ | ||
| 2751 | if (use_both_schemes && retry >= (PORT_INIT_TRIES + 1) / 2) | ||
| 2752 | return old_scheme_first_port; /* Second half */ | ||
| 2753 | return !old_scheme_first_port; /* First half or all */ | ||
| 2737 | } | 2754 | } |
| 2738 | 2755 | ||
| 2739 | /* Is a USB 3.0 port in the Inactive or Compliance Mode state? | 2756 | /* Is a USB 3.0 port in the Inactive or Compliance Mode state? |
| @@ -4545,6 +4562,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, · 1805 unmodified lines | |||
| 4545 | const char *speed; | 4562 | const char *speed; |
| 4546 | int devnum = udev->devnum; | 4563 | int devnum = udev->devnum; |
| 4547 | const char *driver_name; | 4564 | const char *driver_name; |
| 4565 | bool do_new_scheme; | ||
| 4548 | 4566 | ||
| 4549 | /* root hub ports have a slightly longer reset period | 4567 | /* root hub ports have a slightly longer reset period |
| 4550 | * (from USB 2.0 spec, section 7.1.7.5) | 4568 | * (from USB 2.0 spec, section 7.1.7.5) |
| @@ -4657,14 +4675,13 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, · 106 unmodified lines | |||
| 4657 | * first 8 bytes of the device descriptor to get the ep0 maxpacket | 4675 | * first 8 bytes of the device descriptor to get the ep0 maxpacket |
| 4658 | * value. | 4676 | * value. |
| 4659 | */ | 4677 | */ |
| 4660 | for (retries = 0; retries < GET_DESCRIPTOR_TRIES; (++retries, msleep(100))) { | 4678 | do_new_scheme = use_new_scheme(udev, retry_counter, port_dev); |
| 4661 | bool did_new_scheme = false; | ||
| 4662 | 4679 | ||
| 4663 | if (use_new_scheme(udev, retry_counter, port_dev)) { | 4680 | for (retries = 0; retries < GET_DESCRIPTOR_TRIES; (++retries, msleep(100))) { |
| 4681 | if (do_new_scheme) { | ||
| 4664 | struct usb_device_descriptor *buf; | 4682 | struct usb_device_descriptor *buf; |
| 4665 | int r = 0; | 4683 | int r = 0; |
| 4666 | 4684 | ||
| 4667 | did_new_scheme = true; | ||
| 4668 | retval = hub_enable_device(udev); | 4685 | retval = hub_enable_device(udev); |
| 4669 | if (retval < 0) { | 4686 | if (retval < 0) { |
| 4670 | dev_err(&udev->dev, | 4687 | dev_err(&udev->dev, |
| @@ -4684,7 +4701,8 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, · 13 unmodified lines | |||
| 4684 | * 255 is for WUSB devices, we actually need to use | 4701 | * 255 is for WUSB devices, we actually need to use |
| 4685 | * 512 (WUSB1.0[4.8.1]). | 4702 | * 512 (WUSB1.0[4.8.1]). |
| 4686 | */ | 4703 | */ |
| 4687 | for (operations = 0; operations < 3; ++operations) { | 4704 | for (operations = 0; operations < GET_MAXPACKET0_TRIES; |
| 4705 | ++operations) { | ||
| 4688 | buf->bMaxPacketSize0 = 0; | 4706 | buf->bMaxPacketSize0 = 0; |
| 4689 | r = usb_control_msg(udev, usb_rcvaddr0pipe(), | 4707 | r = usb_control_msg(udev, usb_rcvaddr0pipe(), |
| 4690 | USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, | 4708 | USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, |
| @@ -4773,11 +4791,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, · 82 unmodified lines | |||
| 4773 | * - read ep0 maxpacket even for high and low speed, | 4791 | * - read ep0 maxpacket even for high and low speed, |
| 4774 | */ | 4792 | */ |
| 4775 | msleep(10); | 4793 | msleep(10); |
| 4776 | /* use_new_scheme() checks the speed which may have | 4794 | if (do_new_scheme) |
| 4777 | * changed since the initial look so we cache the result | ||
| 4778 | * in did_new_scheme | ||
| 4779 | */ | ||
| 4780 | if (did_new_scheme) | ||
| 4781 | break; | 4795 | break; |
| 4782 | } | 4796 | } |
| 4783 | 4797 | ||
| @@ -5106,7 +5120,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, · 322 unmodified lines | |||
| 5106 | unit_load = 100; | 5120 | unit_load = 100; |
| 5107 | 5121 | ||
| 5108 | status = 0; | 5122 | status = 0; |
| 5109 | for (i = 0; i < SET_CONFIG_TRIES; i++) { | 5123 | for (i = 0; i < PORT_INIT_TRIES; i++) { |
| 5110 | 5124 | ||
| 5111 | /* reallocate for each attempt, since references | 5125 | /* reallocate for each attempt, since references |
| 5112 | * to the previous one can escape in various ways | 5126 | * to the previous one can escape in various ways |
| @@ -5239,7 +5253,7 @@ loop: · 126 unmodified lines | |||
| 5239 | break; | 5253 | break; |
| 5240 | 5254 | ||
| 5241 | /* When halfway through our retry count, power-cycle the port */ | 5255 | /* When halfway through our retry count, power-cycle the port */ |
| 5242 | if (i == (SET_CONFIG_TRIES / 2) - 1) { | 5256 | if (i == (PORT_INIT_TRIES - 1) / 2) { |
| 5243 | dev_info(&port_dev->dev, "attempt power cycle\n"); | 5257 | dev_info(&port_dev->dev, "attempt power cycle\n"); |
| 5244 | usb_hub_set_port_power(hdev, hub, port1, false); | 5258 | usb_hub_set_port_power(hdev, hub, port1, false); |
| 5245 | msleep(2 * hub_power_on_good_delay(hub)); | 5259 | msleep(2 * hub_power_on_good_delay(hub)); |
| @@ -5770,7 +5784,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev) · 524 unmodified lines | |||
| 5770 | bos = udev->bos; | 5784 | bos = udev->bos; |
| 5771 | udev->bos = NULL; | 5785 | udev->bos = NULL; |
| 5772 | 5786 | ||
| 5773 | for (i = 0; i < SET_CONFIG_TRIES; ++i) { | 5787 | for (i = 0; i < PORT_INIT_TRIES; ++i) { |
| 5774 | 5788 | ||
| 5775 | /* ep0 maxpacket size may change; let the HCD know about it. | 5789 | /* ep0 maxpacket size may change; let the HCD know about it. |
| 5776 | * Other endpoints will be handled by re-enumeration. */ | 5790 | * Other endpoints will be handled by re-enumeration. */ |
| @@ -162,6 +162,143 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, · 161 unmodified lines | |||
| 162 | } | 162 | } |
| 163 | EXPORT_SYMBOL_GPL(usb_control_msg); | 163 | EXPORT_SYMBOL_GPL(usb_control_msg); |
| 164 | 164 | ||
| 165 | /** | ||
| 166 | * usb_control_msg_send - Builds a control "send" message, sends it off and waits for completion | ||
| 167 | * @dev: pointer to the usb device to send the message to | ||
| 168 | * @endpoint: endpoint to send the message to | ||
| 169 | * @request: USB message request value | ||
| 170 | * @requesttype: USB message request type value | ||
| 171 | * @value: USB message value | ||
| 172 | * @index: USB message index value | ||
| 173 | * @driver_data: pointer to the data to send | ||
| 174 | * @size: length in bytes of the data to send | ||
| 175 | * @timeout: time in msecs to wait for the message to complete before timing | ||
| 176 | * out (if 0 the wait is forever) | ||
| 177 | * @memflags: the flags for memory allocation for buffers | ||
| 178 | * | ||
| 179 | * Context: !in_interrupt () | ||
| 180 | * | ||
| 181 | * This function sends a control message to a specified endpoint that is not | ||
| 182 | * expected to fill in a response (i.e. a "send message") and waits for the | ||
| 183 | * message to complete, or timeout. | ||
| 184 | * | ||
| 185 | * Do not use this function from within an interrupt context. If you need | ||
| 186 | * an asynchronous message, or need to send a message from within interrupt | ||
| 187 | * context, use usb_submit_urb(). If a thread in your driver uses this call, | ||
| 188 | * make sure your disconnect() method can wait for it to complete. Since you | ||
| 189 | * don't have a handle on the URB used, you can't cancel the request. | ||
| 190 | * | ||
| 191 | * The data pointer can be made to a reference on the stack, or anywhere else, | ||
| 192 | * as it will not be modified at all. This does not have the restriction that | ||
| 193 | * usb_control_msg() has where the data pointer must be to dynamically allocated | ||
| 194 | * memory (i.e. memory that can be successfully DMAed to a device). | ||
| 195 | * | ||
| 196 | * Return: If successful, 0 is returned, Otherwise, a negative error number. | ||
| 197 | */ | ||
| 198 | int usb_control_msg_send(struct usb_device *dev, __u8 endpoint, __u8 request, | ||
| 199 | __u8 requesttype, __u16 value, __u16 index, | ||
| 200 | const void *driver_data, __u16 size, int timeout, | ||
| 201 | gfp_t memflags) | ||
| 202 | { | ||
| 203 | unsigned int pipe = usb_sndctrlpipe(dev, endpoint); | ||
| 204 | int ret; | ||
| 205 | u8 *data = NULL; | ||
| 206 | |||
| 207 | if (usb_pipe_type_check(dev, pipe)) | ||
| 208 | return -EINVAL; | ||
| 209 | |||
| 210 | if (size) { | ||
| 211 | data = kmemdup(driver_data, size, memflags); | ||
| 212 | if (!data) | ||
| 213 | return -ENOMEM; | ||
| 214 | } | ||
| 215 | |||
| 216 | ret = usb_control_msg(dev, pipe, request, requesttype, value, index, | ||
| 217 | data, size, timeout); | ||
| 218 | kfree(data); | ||
| 219 | |||
| 220 | if (ret < 0) | ||
| 221 | return ret; | ||
| 222 | if (ret == size) | ||
| 223 | return 0; | ||
| 224 | return -EINVAL; | ||
| 225 | } | ||
| 226 | EXPORT_SYMBOL_GPL(usb_control_msg_send); | ||
| 227 | |||
| 228 | /** | ||
| 229 | * usb_control_msg_recv - Builds a control "receive" message, sends it off and waits for completion | ||
| 230 | * @dev: pointer to the usb device to send the message to | ||
| 231 | * @endpoint: endpoint to send the message to | ||
| 232 | * @request: USB message request value | ||
| 233 | * @requesttype: USB message request type value | ||
| 234 | * @value: USB message value | ||
| 235 | * @index: USB message index value | ||
| 236 | * @driver_data: pointer to the data to be filled in by the message | ||
| 237 | * @size: length in bytes of the data to be received | ||
| 238 | * @timeout: time in msecs to wait for the message to complete before timing | ||
| 239 | * out (if 0 the wait is forever) | ||
| 240 | * @memflags: the flags for memory allocation for buffers | ||
| 241 | * | ||
| 242 | * Context: !in_interrupt () | ||
| 243 | * | ||
| 244 | * This function sends a control message to a specified endpoint that is | ||
| 245 | * expected to fill in a response (i.e. a "receive message") and waits for the | ||
| 246 | * message to complete, or timeout. | ||
| 247 | * | ||
| 248 | * Do not use this function from within an interrupt context. If you need | ||
| 249 | * an asynchronous message, or need to send a message from within interrupt | ||
| 250 | * context, use usb_submit_urb(). If a thread in your driver uses this call, | ||
| 251 | * make sure your disconnect() method can wait for it to complete. Since you | ||
| 252 | * don't have a handle on the URB used, you can't cancel the request. | ||
| 253 | * | ||
| 254 | * The data pointer can be made to a reference on the stack, or anywhere else | ||
| 255 | * that can be successfully written to. This function does not have the | ||
| 256 | * restriction that usb_control_msg() has where the data pointer must be to | ||
| 257 | * dynamically allocated memory (i.e. memory that can be successfully DMAed to a | ||
| 258 | * device). | ||
| 259 | * | ||
| 260 | * The "whole" message must be properly received from the device in order for | ||
| 261 | * this function to be successful. If a device returns less than the expected | ||
| 262 | * amount of data, then the function will fail. Do not use this for messages | ||
| 263 | * where a variable amount of data might be returned. | ||
| 264 | * | ||
| 265 | * Return: If successful, 0 is returned, Otherwise, a negative error number. | ||
| 266 | */ | ||
| 267 | int usb_control_msg_recv(struct usb_device *dev, __u8 endpoint, __u8 request, | ||
| 268 | __u8 requesttype, __u16 value, __u16 index, | ||
| 269 | void *driver_data, __u16 size, int timeout, | ||
| 270 | gfp_t memflags) | ||
| 271 | { | ||
| 272 | unsigned int pipe = usb_rcvctrlpipe(dev, endpoint); | ||
| 273 | int ret; | ||
| 274 | u8 *data; | ||
| 275 | |||
| 276 | if (!size || !driver_data || usb_pipe_type_check(dev, pipe)) | ||
| 277 | return -EINVAL; | ||
| 278 | |||
| 279 | data = kmalloc(size, memflags); | ||
| 280 | if (!data) | ||
| 281 | return -ENOMEM; | ||
| 282 | |||
| 283 | ret = usb_control_msg(dev, pipe, request, requesttype, value, index, | ||
| 284 | data, size, timeout); | ||
| 285 | |||
| 286 | if (ret < 0) | ||
| 287 | goto exit; | ||
| 288 | |||
| 289 | if (ret == size) { | ||
| 290 | memcpy(driver_data, data, size); | ||
| 291 | ret = 0; | ||
| 292 | } else { | ||
| 293 | ret = -EINVAL; | ||
| 294 | } | ||
| 295 | |||
| 296 | exit: | ||
| 297 | kfree(data); | ||
| 298 | return ret; | ||
| 299 | } | ||
| 300 | EXPORT_SYMBOL_GPL(usb_control_msg_recv); | ||
| 301 | |||
| 165 | /** | 302 | /** |
| 166 | * usb_interrupt_msg - Builds an interrupt urb, sends it off and waits for completion | 303 | * usb_interrupt_msg - Builds an interrupt urb, sends it off and waits for completion |
| 167 | * @usb_dev: pointer to the usb device to send the message to | 304 | * @usb_dev: pointer to the usb device to send the message to |
| @@ -948,11 +1085,12 @@ int usb_set_isoch_delay(struct usb_device *dev) · 780 unmodified lines | |||
| 948 | if (dev->speed < USB_SPEED_SUPER) | 1085 | if (dev->speed < USB_SPEED_SUPER) |
| 949 | return 0; | 1086 | return 0; |
| 950 | 1087 | ||
| 951 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 1088 | return usb_control_msg_send(dev, 0, |
| 952 | USB_REQ_SET_ISOCH_DELAY, | 1089 | USB_REQ_SET_ISOCH_DELAY, |
| 953 | USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, | 1090 | USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, |
| 954 | dev->hub_delay, 0, NULL, 0, | 1091 | dev->hub_delay, 0, NULL, 0, |
| 955 | USB_CTRL_SET_TIMEOUT); | 1092 | USB_CTRL_SET_TIMEOUT, |
| 1093 | GFP_NOIO); | ||
| 956 | } | 1094 | } |
| 957 | 1095 | ||
| 958 | /** | 1096 | /** |
| @@ -1070,13 +1208,13 @@ int usb_clear_halt(struct usb_device *dev, int pipe) · 111 unmodified lines | |||
| 1070 | * (like some ibmcam model 1 units) seem to expect hosts to make | 1208 | * (like some ibmcam model 1 units) seem to expect hosts to make |
| 1071 | * this request for iso endpoints, which can't halt! | 1209 | * this request for iso endpoints, which can't halt! |
| 1072 | */ | 1210 | */ |
| 1073 | result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 1211 | result = usb_control_msg_send(dev, 0, |
| 1074 | USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, | 1212 | USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, |
| 1075 | USB_ENDPOINT_HALT, endp, NULL, 0, | 1213 | USB_ENDPOINT_HALT, endp, NULL, 0, |
| 1076 | USB_CTRL_SET_TIMEOUT); | 1214 | USB_CTRL_SET_TIMEOUT, GFP_NOIO); |
| 1077 | 1215 | ||
| 1078 | /* don't un-halt or force to DATA0 except on success */ | 1216 | /* don't un-halt or force to DATA0 except on success */ |
| 1079 | if (result < 0) | 1217 | if (result) |
| 1080 | return result; | 1218 | return result; |
| 1081 | 1219 | ||
| 1082 | /* NOTE: seems like Microsoft and Apple don't bother verifying | 1220 | /* NOTE: seems like Microsoft and Apple don't bother verifying |
| @@ -1438,9 +1576,11 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) · 355 unmodified lines | |||
| 1438 | if (dev->quirks & USB_QUIRK_NO_SET_INTF) | 1576 | if (dev->quirks & USB_QUIRK_NO_SET_INTF) |
| 1439 | ret = -EPIPE; | 1577 | ret = -EPIPE; |
| 1440 | else | 1578 | else |
| 1441 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 1579 | ret = usb_control_msg_send(dev, 0, |
| 1442 | USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, | 1580 | USB_REQ_SET_INTERFACE, |
| 1443 | alternate, interface, NULL, 0, 5000); | 1581 | USB_RECIP_INTERFACE, alternate, |
| 1582 | interface, NULL, 0, 5000, | ||
| 1583 | GFP_NOIO); | ||
| 1444 | 1584 | ||
| 1445 | /* 9.4.10 says devices don't need this and are free to STALL the | 1585 | /* 9.4.10 says devices don't need this and are free to STALL the |
| 1446 | * request if the interface only has one alternate setting. | 1586 | * request if the interface only has one alternate setting. |
| @@ -1450,7 +1590,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) · 3 unmodified lines | |||
| 1450 | "manual set_interface for iface %d, alt %d\n", | 1590 | "manual set_interface for iface %d, alt %d\n", |
| 1451 | interface, alternate); | 1591 | interface, alternate); |
| 1452 | manual = 1; | 1592 | manual = 1; |
| 1453 | } else if (ret < 0) { | 1593 | } else if (ret) { |
| 1454 | /* Re-instate the old alt setting */ | 1594 | /* Re-instate the old alt setting */ |
| 1455 | usb_hcd_alloc_bandwidth(dev, NULL, alt, iface->cur_altsetting); | 1595 | usb_hcd_alloc_bandwidth(dev, NULL, alt, iface->cur_altsetting); |
| 1456 | usb_enable_lpm(dev); | 1596 | usb_enable_lpm(dev); |
| @@ -1574,11 +1714,11 @@ int usb_reset_configuration(struct usb_device *dev) · 117 unmodified lines | |||
| 1574 | mutex_unlock(hcd->bandwidth_mutex); | 1714 | mutex_unlock(hcd->bandwidth_mutex); |
| 1575 | return retval; | 1715 | return retval; |
| 1576 | } | 1716 | } |
| 1577 | retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 1717 | retval = usb_control_msg_send(dev, 0, USB_REQ_SET_CONFIGURATION, 0, |
| 1578 | USB_REQ_SET_CONFIGURATION, 0, | 1718 | config->desc.bConfigurationValue, 0, |
| 1579 | config->desc.bConfigurationValue, 0, | 1719 | NULL, 0, USB_CTRL_SET_TIMEOUT, |
| 1580 | NULL, 0, USB_CTRL_SET_TIMEOUT); | 1720 | GFP_NOIO); |
| 1581 | if (retval < 0) { | 1721 | if (retval) { |
| 1582 | usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); | 1722 | usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); |
| 1583 | usb_enable_lpm(dev); | 1723 | usb_enable_lpm(dev); |
| 1584 | mutex_unlock(hcd->bandwidth_mutex); | 1724 | mutex_unlock(hcd->bandwidth_mutex); |
| @@ -1963,10 +2103,10 @@ free_interfaces: · 378 unmodified lines | |||
| 1963 | } | 2103 | } |
| 1964 | kfree(new_interfaces); | 2104 | kfree(new_interfaces); |
| 1965 | 2105 | ||
| 1966 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 2106 | ret = usb_control_msg_send(dev, 0, USB_REQ_SET_CONFIGURATION, 0, |
| 1967 | USB_REQ_SET_CONFIGURATION, 0, configuration, 0, | 2107 | configuration, 0, NULL, 0, |
| 1968 | NULL, 0, USB_CTRL_SET_TIMEOUT); | 2108 | USB_CTRL_SET_TIMEOUT, GFP_NOIO); |
| 1969 | if (ret < 0 && cp) { | 2109 | if (ret && cp) { |
| 1970 | /* | 2110 | /* |
| 1971 | * All the old state is gone, so what else can we do? | 2111 | * All the old state is gone, so what else can we do? |
| 1972 | * The device is probably useless now anyway. | 2112 | * The device is probably useless now anyway. |
| @@ -192,24 +192,39 @@ static const int pipetypes[4] = { · 191 unmodified lines | |||
| 192 | }; | 192 | }; |
| 193 | 193 | ||
| 194 | /** | 194 | /** |
| 195 | * usb_urb_ep_type_check - sanity check of endpoint in the given urb | 195 | * usb_pipe_type_check - sanity check of a specific pipe for a usb device |
| 196 | * @urb: urb to be checked | 196 | * @dev: struct usb_device to be checked |
| 197 | * @pipe: pipe to check | ||
| 197 | * | 198 | * |
| 198 | * This performs a light-weight sanity check for the endpoint in the | 199 | * This performs a light-weight sanity check for the endpoint in the |
| 199 | * given urb. It returns 0 if the urb contains a valid endpoint, otherwise | 200 | * given usb device. It returns 0 if the pipe is valid for the specific usb |
| 200 | * a negative error code. | 201 | * device, otherwise a negative error code. |
| 201 | */ | 202 | */ |
| 202 | int usb_urb_ep_type_check(const struct urb *urb) | 203 | int usb_pipe_type_check(struct usb_device *dev, unsigned int pipe) |
| 203 | { | 204 | { |
| 204 | const struct usb_host_endpoint *ep; | 205 | const struct usb_host_endpoint *ep; |
| 205 | 206 | ||
| 206 | ep = usb_pipe_endpoint(urb->dev, urb->pipe); | 207 | ep = usb_pipe_endpoint(dev, pipe); |
| 207 | if (!ep) | 208 | if (!ep) |
| 208 | return -EINVAL; | 209 | return -EINVAL; |
| 209 | if (usb_pipetype(urb->pipe) != pipetypes[usb_endpoint_type(&ep->desc)]) | 210 | if (usb_pipetype(pipe) != pipetypes[usb_endpoint_type(&ep->desc)]) |
| 210 | return -EINVAL; | 211 | return -EINVAL; |
| 211 | return 0; | 212 | return 0; |
| 212 | } | 213 | } |
| 214 | EXPORT_SYMBOL_GPL(usb_pipe_type_check); | ||
| 215 | |||
| 216 | /** | ||
| 217 | * usb_urb_ep_type_check - sanity check of endpoint in the given urb | ||
| 218 | * @urb: urb to be checked | ||
| 219 | * | ||
| 220 | * This performs a light-weight sanity check for the endpoint in the | ||
| 221 | * given urb. It returns 0 if the urb contains a valid endpoint, otherwise | ||
| 222 | * a negative error code. | ||
| 223 | */ | ||
| 224 | int usb_urb_ep_type_check(const struct urb *urb) | ||
| 225 | { | ||
| 226 | return usb_pipe_type_check(urb->dev, urb->pipe); | ||
| 227 | } | ||
| 213 | EXPORT_SYMBOL_GPL(usb_urb_ep_type_check); | 228 | EXPORT_SYMBOL_GPL(usb_urb_ep_type_check); |
| 214 | 229 | ||
| 215 | /** | 230 | /** |
| @@ -474,7 +489,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) · 258 unmodified lines | |||
| 474 | */ | 489 | */ |
| 475 | 490 | ||
| 476 | /* Check that the pipe's type matches the endpoint's type */ | 491 | /* Check that the pipe's type matches the endpoint's type */ |
| 477 | if (usb_urb_ep_type_check(urb)) | 492 | if (usb_pipe_type_check(urb->dev, urb->pipe)) |
| 478 | dev_WARN(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n", | 493 | dev_WARN(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n", |
| 479 | usb_pipetype(urb->pipe), pipetypes[xfertype]); | 494 | usb_pipetype(urb->pipe), pipetypes[xfertype]); |
| 480 | 495 | ||
| @@ -772,11 +787,12 @@ void usb_block_urb(struct urb *urb) · 291 unmodified lines | |||
| 772 | EXPORT_SYMBOL_GPL(usb_block_urb); | 787 | EXPORT_SYMBOL_GPL(usb_block_urb); |
| 773 | 788 | ||
| 774 | /** | 789 | /** |
| 775 | * usb_kill_anchored_urbs - cancel transfer requests en masse | 790 | * usb_kill_anchored_urbs - kill all URBs associated with an anchor |
| 776 | * @anchor: anchor the requests are bound to | 791 | * @anchor: anchor the requests are bound to |
| 777 | * | 792 | * |
| 778 | * this allows all outstanding URBs to be killed starting | 793 | * This kills all outstanding URBs starting from the back of the queue, |
| 779 | * from the back of the queue | 794 | * with guarantee that no completer callbacks will take place from the |
| 795 | * anchor after this function returns. | ||
| 780 | * | 796 | * |
| 781 | * This routine should not be called by a driver after its disconnect | 797 | * This routine should not be called by a driver after its disconnect |
| 782 | * method has returned. | 798 | * method has returned. |
| @@ -784,20 +800,26 @@ EXPORT_SYMBOL_GPL(usb_block_urb); · 1 unmodified line | |||
| 784 | void usb_kill_anchored_urbs(struct usb_anchor *anchor) | 800 | void usb_kill_anchored_urbs(struct usb_anchor *anchor) |
| 785 | { | 801 | { |
| 786 | struct urb *victim; | 802 | struct urb *victim; |
| 803 | int surely_empty; | ||
| 787 | 804 | ||
| 788 | spin_lock_irq(&anchor->lock); | 805 | do { |
| 789 | while (!list_empty(&anchor->urb_list)) { | ||
| 790 | victim = list_entry(anchor->urb_list.prev, struct urb, | ||
| 791 | anchor_list); | ||
| 792 | /* we must make sure the URB isn't freed before we kill it*/ | ||
| 793 | usb_get_urb(victim); | ||
| 794 | spin_unlock_irq(&anchor->lock); | ||
| 795 | /* this will unanchor the URB */ | ||
| 796 | usb_kill_urb(victim); | ||
| 797 | usb_put_urb(victim); | ||
| 798 | spin_lock_irq(&anchor->lock); | 806 | spin_lock_irq(&anchor->lock); |
| 799 | } | 807 | while (!list_empty(&anchor->urb_list)) { |
| 800 | spin_unlock_irq(&anchor->lock); | 808 | victim = list_entry(anchor->urb_list.prev, |
| 809 | struct urb, anchor_list); | ||
| 810 | /* make sure the URB isn't freed before we kill it */ | ||
| 811 | usb_get_urb(victim); | ||
| 812 | spin_unlock_irq(&anchor->lock); | ||
| 813 | /* this will unanchor the URB */ | ||
| 814 | usb_kill_urb(victim); | ||
| 815 | usb_put_urb(victim); | ||
| 816 | spin_lock_irq(&anchor->lock); | ||
| 817 | } | ||
| 818 | surely_empty = usb_anchor_check_wakeup(anchor); | ||
| 819 | |||
| 820 | spin_unlock_irq(&anchor->lock); | ||
| 821 | cpu_relax(); | ||
| 822 | } while (!surely_empty); | ||
| 801 | } | 823 | } |
| 802 | EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs); | 824 | EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs); |
| 803 | 825 | ||
| @@ -816,21 +838,27 @@ EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs); · 12 unmodified lines | |||
| 816 | void usb_poison_anchored_urbs(struct usb_anchor *anchor) | 838 | void usb_poison_anchored_urbs(struct usb_anchor *anchor) |
| 817 | { | 839 | { |
| 818 | struct urb *victim; | 840 | struct urb *victim; |
| 841 | int surely_empty; | ||
| 819 | 842 | ||
| 820 | spin_lock_irq(&anchor->lock); | 843 | do { |
| 821 | anchor->poisoned = 1; | ||
| 822 | while (!list_empty(&anchor->urb_list)) { | ||
| 823 | victim = list_entry(anchor->urb_list.prev, struct urb, | ||
| 824 | anchor_list); | ||
| 825 | /* we must make sure the URB isn't freed before we kill it*/ | ||
| 826 | usb_get_urb(victim); | ||
| 827 | spin_unlock_irq(&anchor->lock); | ||
| 828 | /* this will unanchor the URB */ | ||
| 829 | usb_poison_urb(victim); | ||
| 830 | usb_put_urb(victim); | ||
| 831 | spin_lock_irq(&anchor->lock); | 844 | spin_lock_irq(&anchor->lock); |
| 832 | } | 845 | anchor->poisoned = 1; |
| 833 | spin_unlock_irq(&anchor->lock); | 846 | while (!list_empty(&anchor->urb_list)) { |
| 847 | victim = list_entry(anchor->urb_list.prev, | ||
| 848 | struct urb, anchor_list); | ||
| 849 | /* make sure the URB isn't freed before we kill it */ | ||
| 850 | usb_get_urb(victim); | ||
| 851 | spin_unlock_irq(&anchor->lock); | ||
| 852 | /* this will unanchor the URB */ | ||
| 853 | usb_poison_urb(victim); | ||
| 854 | usb_put_urb(victim); | ||
| 855 | spin_lock_irq(&anchor->lock); | ||
| 856 | } | ||
| 857 | surely_empty = usb_anchor_check_wakeup(anchor); | ||
| 858 | |||
| 859 | spin_unlock_irq(&anchor->lock); | ||
| 860 | cpu_relax(); | ||
| 861 | } while (!surely_empty); | ||
| 834 | } | 862 | } |
| 835 | EXPORT_SYMBOL_GPL(usb_poison_anchored_urbs); | 863 | EXPORT_SYMBOL_GPL(usb_poison_anchored_urbs); |
| 836 | 864 | ||
| @@ -970,14 +998,20 @@ void usb_scuttle_anchored_urbs(struct usb_anchor *anchor) · 133 unmodified lines | |||
| 970 | { | 998 | { |
| 971 | struct urb *victim; | 999 | struct urb *victim; |
| 972 | unsigned long flags; | 1000 | unsigned long flags; |
| 1001 | int surely_empty; | ||
| 1002 | |||
| 1003 | do { | ||
| 1004 | spin_lock_irqsave(&anchor->lock, flags); | ||
| 1005 | while (!list_empty(&anchor->urb_list)) { | ||
| 1006 | victim = list_entry(anchor->urb_list.prev, | ||
| 1007 | struct urb, anchor_list); | ||
| 1008 | __usb_unanchor_urb(victim, anchor); | ||
| 1009 | } | ||
| 1010 | surely_empty = usb_anchor_check_wakeup(anchor); | ||
| 973 | 1011 | ||
| 974 | spin_lock_irqsave(&anchor->lock, flags); | 1012 | spin_unlock_irqrestore(&anchor->lock, flags); |
| 975 | while (!list_empty(&anchor->urb_list)) { | 1013 | cpu_relax(); |
| 976 | victim = list_entry(anchor->urb_list.prev, struct urb, | 1014 | } while (!surely_empty); |
| 977 | anchor_list); | ||
| 978 | __usb_unanchor_urb(victim, anchor); | ||
| 979 | } | ||
| 980 | spin_unlock_irqrestore(&anchor->lock, flags); | ||
| 981 | } | 1015 | } |
| 982 | 1016 | ||
| 983 | EXPORT_SYMBOL_GPL(usb_scuttle_anchored_urbs); | 1017 | EXPORT_SYMBOL_GPL(usb_scuttle_anchored_urbs); |
| @@ -191,7 +191,6 @@ extern const struct attribute_group *usb_interface_groups[]; · 190 unmodified lines | |||
| 191 | extern struct usb_driver usbfs_driver; | 191 | extern struct usb_driver usbfs_driver; |
| 192 | extern const struct file_operations usbfs_devices_fops; | 192 | extern const struct file_operations usbfs_devices_fops; |
| 193 | extern const struct file_operations usbdev_file_operations; | 193 | extern const struct file_operations usbdev_file_operations; |
| 194 | extern void usbfs_conn_disc_event(void); | ||
| 195 | 194 | ||
| 196 | extern int usb_devio_init(void); | 195 | extern int usb_devio_init(void); |
| 197 | extern void usb_devio_cleanup(void); | 196 | extern void usb_devio_cleanup(void); |
| @@ -5,6 +5,7 @@ config USB_DWC2 · 4 unmodified lines | |||
| 5 | depends on HAS_DMA | 5 | depends on HAS_DMA |
| 6 | depends on USB || USB_GADGET | 6 | depends on USB || USB_GADGET |
| 7 | depends on HAS_IOMEM | 7 | depends on HAS_IOMEM |
| 8 | select USB_ROLE_SWITCH | ||
| 8 | help | 9 | help |
| 9 | Say Y here if your system has a Dual Role Hi-Speed USB | 10 | Say Y here if your system has a Dual Role Hi-Speed USB |
| 10 | controller based on the DesignWare HSOTG IP Core. | 11 | controller based on the DesignWare HSOTG IP Core. |
| @@ -3,7 +3,7 @@ ccflags-$(CONFIG_USB_DWC2_DEBUG) += -DDEBUG · 2 unmodified lines | |||
| 3 | ccflags-$(CONFIG_USB_DWC2_VERBOSE) += -DVERBOSE_DEBUG | 3 | ccflags-$(CONFIG_USB_DWC2_VERBOSE) += -DVERBOSE_DEBUG |
| 4 | 4 | ||
| 5 | obj-$(CONFIG_USB_DWC2) += dwc2.o | 5 | obj-$(CONFIG_USB_DWC2) += dwc2.o |
| 6 | dwc2-y := core.o core_intr.o platform.o | 6 | dwc2-y := core.o core_intr.o platform.o drd.o |
| 7 | dwc2-y += params.o | 7 | dwc2-y += params.o |
| 8 | 8 | ||
| 9 | ifneq ($(filter y,$(CONFIG_USB_DWC2_HOST) $(CONFIG_USB_DWC2_DUAL_ROLE)),) | 9 | ifneq ($(filter y,$(CONFIG_USB_DWC2_HOST) $(CONFIG_USB_DWC2_DUAL_ROLE)),) |
| @@ -860,6 +860,7 @@ struct dwc2_hregs_backup { · 859 unmodified lines | |||
| 860 | * - USB_DR_MODE_PERIPHERAL | 860 | * - USB_DR_MODE_PERIPHERAL |
| 861 | * - USB_DR_MODE_HOST | 861 | * - USB_DR_MODE_HOST |
| 862 | * - USB_DR_MODE_OTG | 862 | * - USB_DR_MODE_OTG |
| 863 | * @role_sw: usb_role_switch handle | ||
| 863 | * @hcd_enabled: Host mode sub-driver initialization indicator. | 864 | * @hcd_enabled: Host mode sub-driver initialization indicator. |
| 864 | * @gadget_enabled: Peripheral mode sub-driver initialization indicator. | 865 | * @gadget_enabled: Peripheral mode sub-driver initialization indicator. |
| 865 | * @ll_hw_enabled: Status of low-level hardware resources. | 866 | * @ll_hw_enabled: Status of low-level hardware resources. |
| @@ -1054,6 +1055,7 @@ struct dwc2_hsotg { · 188 unmodified lines | |||
| 1054 | struct dwc2_core_params params; | 1055 | struct dwc2_core_params params; |
| 1055 | enum usb_otg_state op_state; | 1056 | enum usb_otg_state op_state; |
| 1056 | enum usb_dr_mode dr_mode; | 1057 | enum usb_dr_mode dr_mode; |
| 1058 | struct usb_role_switch *role_sw; | ||
| 1057 | unsigned int hcd_enabled:1; | 1059 | unsigned int hcd_enabled:1; |
| 1058 | unsigned int gadget_enabled:1; | 1060 | unsigned int gadget_enabled:1; |
| 1059 | unsigned int ll_hw_enabled:1; | 1061 | unsigned int ll_hw_enabled:1; |
| @@ -1376,6 +1378,11 @@ static inline int dwc2_is_device_mode(struct dwc2_hsotg *hsotg) · 316 unmodified lines | |||
| 1376 | return (dwc2_readl(hsotg, GINTSTS) & GINTSTS_CURMODE_HOST) == 0; | 1378 | return (dwc2_readl(hsotg, GINTSTS) & GINTSTS_CURMODE_HOST) == 0; |
| 1377 | } | 1379 | } |
| 1378 | 1380 | ||
| 1381 | int dwc2_drd_init(struct dwc2_hsotg *hsotg); | ||
| 1382 | void dwc2_drd_suspend(struct dwc2_hsotg *hsotg); | ||
| 1383 | void dwc2_drd_resume(struct dwc2_hsotg *hsotg); | ||
| 1384 | void dwc2_drd_exit(struct dwc2_hsotg *hsotg); | ||
| 1385 | |||
| 1379 | /* | 1386 | /* |
| 1380 | * Dump core registers and SPRAM | 1387 | * Dump core registers and SPRAM |
| 1381 | */ | 1388 | */ |
| @@ -1392,6 +1399,7 @@ int dwc2_hsotg_resume(struct dwc2_hsotg *dwc2); · 10 unmodified lines | |||
| 1392 | int dwc2_gadget_init(struct dwc2_hsotg *hsotg); | 1399 | int dwc2_gadget_init(struct dwc2_hsotg *hsotg); |
| 1393 | void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2, | 1400 | void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2, |
| 1394 | bool reset); | 1401 | bool reset); |
| 1402 | void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg); | ||
| 1395 | void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg); | 1403 | void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg); |
| 1396 | void dwc2_hsotg_disconnect(struct dwc2_hsotg *dwc2); | 1404 | void dwc2_hsotg_disconnect(struct dwc2_hsotg *dwc2); |
| 1397 | int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode); | 1405 | int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode); |
| @@ -1417,6 +1425,7 @@ static inline int dwc2_gadget_init(struct dwc2_hsotg *hsotg) · 19 unmodified lines | |||
| 1417 | { return 0; } | 1425 | { return 0; } |
| 1418 | static inline void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2, | 1426 | static inline void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2, |
| 1419 | bool reset) {} | 1427 | bool reset) {} |
| 1428 | static inline void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg) {} | ||
| 1420 | static inline void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg) {} | 1429 | static inline void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg) {} |
| 1421 | static inline void dwc2_hsotg_disconnect(struct dwc2_hsotg *dwc2) {} | 1430 | static inline void dwc2_hsotg_disconnect(struct dwc2_hsotg *dwc2) {} |
| 1422 | static inline int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, | 1431 | static inline int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, |
| @@ -0,0 +1,180 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * drd.c - DesignWare USB2 DRD Controller Dual-role support | ||
| 4 | * | ||
| 5 | * Copyright (C) 2020 STMicroelectronics | ||
| 6 | * | ||
| 7 | * Author(s): Amelie Delaunay <amelie.delaunay@st.com> | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/iopoll.h> | ||
| 11 | #include <linux/platform_device.h> | ||
| 12 | #include <linux/usb/role.h> | ||
| 13 | #include "core.h" | ||
| 14 | |||
| 15 | static void dwc2_ovr_init(struct dwc2_hsotg *hsotg) | ||
| 16 | { | ||
| 17 | unsigned long flags; | ||
| 18 | u32 gotgctl; | ||
| 19 | |||
| 20 | spin_lock_irqsave(&hsotg->lock, flags); | ||
| 21 | |||
| 22 | gotgctl = dwc2_readl(hsotg, GOTGCTL); | ||
| 23 | gotgctl |= GOTGCTL_BVALOEN | GOTGCTL_AVALOEN | GOTGCTL_VBVALOEN; | ||
| 24 | gotgctl |= GOTGCTL_DBNCE_FLTR_BYPASS; | ||
| 25 | gotgctl &= ~(GOTGCTL_BVALOVAL | GOTGCTL_AVALOVAL | GOTGCTL_VBVALOVAL); | ||
| 26 | dwc2_writel(hsotg, gotgctl, GOTGCTL); | ||
| 27 | |||
| 28 | dwc2_force_mode(hsotg, false); | ||
| 29 | |||
| 30 | spin_unlock_irqrestore(&hsotg->lock, flags); | ||
| 31 | } | ||
| 32 | |||
| 33 | static int dwc2_ovr_avalid(struct dwc2_hsotg *hsotg, bool valid) | ||
| 34 | { | ||
| 35 | u32 gotgctl = dwc2_readl(hsotg, GOTGCTL); | ||
| 36 | |||
| 37 | /* Check if A-Session is already in the right state */ | ||
| 38 | if ((valid && (gotgctl & GOTGCTL_ASESVLD)) || | ||
| 39 | (!valid && !(gotgctl & GOTGCTL_ASESVLD))) | ||
| 40 | return -EALREADY; | ||
| 41 | |||
| 42 | if (valid) | ||
| 43 | gotgctl |= GOTGCTL_AVALOVAL | GOTGCTL_VBVALOVAL; | ||
| 44 | else | ||
| 45 | gotgctl &= ~(GOTGCTL_AVALOVAL | GOTGCTL_VBVALOVAL); | ||
| 46 | dwc2_writel(hsotg, gotgctl, GOTGCTL); | ||
| 47 | |||
| 48 | return 0; | ||
| 49 | } | ||
| 50 | |||
| 51 | static int dwc2_ovr_bvalid(struct dwc2_hsotg *hsotg, bool valid) | ||
| 52 | { | ||
| 53 | u32 gotgctl = dwc2_readl(hsotg, GOTGCTL); | ||
| 54 | |||
| 55 | /* Check if B-Session is already in the right state */ | ||
| 56 | if ((valid && (gotgctl & GOTGCTL_BSESVLD)) || | ||
| 57 | (!valid && !(gotgctl & GOTGCTL_BSESVLD))) | ||
| 58 | return -EALREADY; | ||
| 59 | |||
| 60 | if (valid) | ||
| 61 | gotgctl |= GOTGCTL_BVALOVAL | GOTGCTL_VBVALOVAL; | ||
| 62 | else | ||
| 63 | gotgctl &= ~(GOTGCTL_BVALOVAL | GOTGCTL_VBVALOVAL); | ||
| 64 | dwc2_writel(hsotg, gotgctl, GOTGCTL); | ||
| 65 | |||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | static int dwc2_drd_role_sw_set(struct usb_role_switch *sw, enum usb_role role) | ||
| 70 | { | ||
| 71 | struct dwc2_hsotg *hsotg = usb_role_switch_get_drvdata(sw); | ||
| 72 | unsigned long flags; | ||
| 73 | int already = 0; | ||
| 74 | |||
| 75 | /* Skip session not in line with dr_mode */ | ||
| 76 | if ((role == USB_ROLE_DEVICE && hsotg->dr_mode == USB_DR_MODE_HOST) || | ||
| 77 | (role == USB_ROLE_HOST && hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)) | ||
| 78 | return -EINVAL; | ||
| 79 | |||
| 80 | #if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \ | ||
| 81 | IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) | ||
| 82 | /* Skip session if core is in test mode */ | ||
| 83 | if (role == USB_ROLE_NONE && hsotg->test_mode) { | ||
| 84 | dev_dbg(hsotg->dev, "Core is in test mode\n"); | ||
| 85 | return -EBUSY; | ||
| 86 | } | ||
| 87 | #endif | ||
| 88 | |||
| 89 | spin_lock_irqsave(&hsotg->lock, flags); | ||
| 90 | |||
| 91 | if (role == USB_ROLE_HOST) { | ||
| 92 | already = dwc2_ovr_avalid(hsotg, true); | ||
| 93 | } else if (role == USB_ROLE_DEVICE) { | ||
| 94 | already = dwc2_ovr_bvalid(hsotg, true); | ||
| 95 | /* This clear DCTL.SFTDISCON bit */ | ||
| 96 | dwc2_hsotg_core_connect(hsotg); | ||
| 97 | } else { | ||
| 98 | if (dwc2_is_device_mode(hsotg)) { | ||
| 99 | if (!dwc2_ovr_bvalid(hsotg, false)) | ||
| 100 | /* This set DCTL.SFTDISCON bit */ | ||
| 101 | dwc2_hsotg_core_disconnect(hsotg); | ||
| 102 | } else { | ||
| 103 | dwc2_ovr_avalid(hsotg, false); | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | spin_unlock_irqrestore(&hsotg->lock, flags); | ||
| 108 | |||
| 109 | if (!already && hsotg->dr_mode == USB_DR_MODE_OTG) | ||
| 110 | /* This will raise a Connector ID Status Change Interrupt */ | ||
| 111 | dwc2_force_mode(hsotg, role == USB_ROLE_HOST); | ||
| 112 | |||
| 113 | dev_dbg(hsotg->dev, "%s-session valid\n", | ||
| 114 | role == USB_ROLE_NONE ? "No" : | ||
| 115 | role == USB_ROLE_HOST ? "A" : "B"); | ||
| 116 | |||
| 117 | return 0; | ||
| 118 | } | ||
| 119 | |||
| 120 | int dwc2_drd_init(struct dwc2_hsotg *hsotg) | ||
| 121 | { | ||
| 122 | struct usb_role_switch_desc role_sw_desc = {0}; | ||
| 123 | struct usb_role_switch *role_sw; | ||
| 124 | int ret; | ||
| 125 | |||
| 126 | if (!device_property_read_bool(hsotg->dev, "usb-role-switch")) | ||
| 127 | return 0; | ||
| 128 | |||
| 129 | role_sw_desc.driver_data = hsotg; | ||
| 130 | role_sw_desc.fwnode = dev_fwnode(hsotg->dev); | ||
| 131 | role_sw_desc.set = dwc2_drd_role_sw_set; | ||
| 132 | role_sw_desc.allow_userspace_control = true; | ||
| 133 | |||
| 134 | role_sw = usb_role_switch_register(hsotg->dev, &role_sw_desc); | ||
| 135 | if (IS_ERR(role_sw)) { | ||
| 136 | ret = PTR_ERR(role_sw); | ||
| 137 | dev_err(hsotg->dev, | ||
| 138 | "failed to register role switch: %d\n", ret); | ||
| 139 | return ret; | ||
| 140 | } | ||
| 141 | |||
| 142 | hsotg->role_sw = role_sw; | ||
| 143 | |||
| 144 | /* Enable override and initialize values */ | ||
| 145 | dwc2_ovr_init(hsotg); | ||
| 146 | |||
| 147 | return 0; | ||
| 148 | } | ||
| 149 | |||
| 150 | void dwc2_drd_suspend(struct dwc2_hsotg *hsotg) | ||
| 151 | { | ||
| 152 | u32 gintsts, gintmsk; | ||
| 153 | |||
| 154 | if (hsotg->role_sw && !hsotg->params.external_id_pin_ctl) { | ||
| 155 | gintmsk = dwc2_readl(hsotg, GINTMSK); | ||
| 156 | gintmsk &= ~GINTSTS_CONIDSTSCHNG; | ||
| 157 | dwc2_writel(hsotg, gintmsk, GINTMSK); | ||
| 158 | gintsts = dwc2_readl(hsotg, GINTSTS); | ||
| 159 | dwc2_writel(hsotg, gintsts | GINTSTS_CONIDSTSCHNG, GINTSTS); | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 163 | void dwc2_drd_resume(struct dwc2_hsotg *hsotg) | ||
| 164 | { | ||
| 165 | u32 gintsts, gintmsk; | ||
| 166 | |||
| 167 | if (hsotg->role_sw && !hsotg->params.external_id_pin_ctl) { | ||
| 168 | gintsts = dwc2_readl(hsotg, GINTSTS); | ||
| 169 | dwc2_writel(hsotg, gintsts | GINTSTS_CONIDSTSCHNG, GINTSTS); | ||
| 170 | gintmsk = dwc2_readl(hsotg, GINTMSK); | ||
| 171 | gintmsk |= GINTSTS_CONIDSTSCHNG; | ||
| 172 | dwc2_writel(hsotg, gintmsk, GINTMSK); | ||
| 173 | } | ||
| 174 | } | ||
| 175 | |||
| 176 | void dwc2_drd_exit(struct dwc2_hsotg *hsotg) | ||
| 177 | { | ||
| 178 | if (hsotg->role_sw) | ||
| 179 | usb_role_switch_unregister(hsotg->role_sw); | ||
| 180 | } | ||
| @@ -713,8 +713,11 @@ static u32 dwc2_hsotg_read_frameno(struct dwc2_hsotg *hsotg) · 712 unmodified lines | |||
| 713 | */ | 713 | */ |
| 714 | static unsigned int dwc2_gadget_get_chain_limit(struct dwc2_hsotg_ep *hs_ep) | 714 | static unsigned int dwc2_gadget_get_chain_limit(struct dwc2_hsotg_ep *hs_ep) |
| 715 | { | 715 | { |
| 716 | const struct usb_endpoint_descriptor *ep_desc = hs_ep->ep.desc; | ||
| 716 | int is_isoc = hs_ep->isochronous; | 717 | int is_isoc = hs_ep->isochronous; |
| 717 | unsigned int maxsize; | 718 | unsigned int maxsize; |
| 719 | u32 mps = hs_ep->ep.maxpacket; | ||
| 720 | int dir_in = hs_ep->dir_in; | ||
| 718 | 721 | ||
| 719 | if (is_isoc) | 722 | if (is_isoc) |
| 720 | maxsize = (hs_ep->dir_in ? DEV_DMA_ISOC_TX_NBYTES_LIMIT : | 723 | maxsize = (hs_ep->dir_in ? DEV_DMA_ISOC_TX_NBYTES_LIMIT : |
| @@ -723,6 +726,11 @@ static unsigned int dwc2_gadget_get_chain_limit(struct dwc2_hsotg_ep *hs_ep) · 2 unmodified lines | |||
| 723 | else | 726 | else |
| 724 | maxsize = DEV_DMA_NBYTES_LIMIT * MAX_DMA_DESC_NUM_GENERIC; | 727 | maxsize = DEV_DMA_NBYTES_LIMIT * MAX_DMA_DESC_NUM_GENERIC; |
| 725 | 728 | ||
| 729 | /* Interrupt OUT EP with mps not multiple of 4 */ | ||
| 730 | if (hs_ep->index) | ||
| 731 | if (usb_endpoint_xfer_int(ep_desc) && !dir_in && (mps % 4)) | ||
| 732 | maxsize = mps * MAX_DMA_DESC_NUM_GENERIC; | ||
| 733 | |||
| 726 | return maxsize; | 734 | return maxsize; |
| 727 | } | 735 | } |
| 728 | 736 | ||
| @@ -738,11 +746,14 @@ static unsigned int dwc2_gadget_get_chain_limit(struct dwc2_hsotg_ep *hs_ep) · 9 unmodified lines | |||
| 738 | * Isochronous - descriptor rx/tx bytes bitfield limit, | 746 | * Isochronous - descriptor rx/tx bytes bitfield limit, |
| 739 | * Control In/Bulk/Interrupt - multiple of mps. This will allow to not | 747 | * Control In/Bulk/Interrupt - multiple of mps. This will allow to not |
| 740 | * have concatenations from various descriptors within one packet. | 748 | * have concatenations from various descriptors within one packet. |
| 749 | * Interrupt OUT - if mps not multiple of 4 then a single packet corresponds | ||
| 750 | * to a single descriptor. | ||
| 741 | * | 751 | * |
| 742 | * Selects corresponding mask for RX/TX bytes as well. | 752 | * Selects corresponding mask for RX/TX bytes as well. |
| 743 | */ | 753 | */ |
| 744 | static u32 dwc2_gadget_get_desc_params(struct dwc2_hsotg_ep *hs_ep, u32 *mask) | 754 | static u32 dwc2_gadget_get_desc_params(struct dwc2_hsotg_ep *hs_ep, u32 *mask) |
| 745 | { | 755 | { |
| 756 | const struct usb_endpoint_descriptor *ep_desc = hs_ep->ep.desc; | ||
| 746 | u32 mps = hs_ep->ep.maxpacket; | 757 | u32 mps = hs_ep->ep.maxpacket; |
| 747 | int dir_in = hs_ep->dir_in; | 758 | int dir_in = hs_ep->dir_in; |
| 748 | u32 desc_size = 0; | 759 | u32 desc_size = 0; |
| @@ -766,6 +777,13 @@ static u32 dwc2_gadget_get_desc_params(struct dwc2_hsotg_ep *hs_ep, u32 *mask) · 17 unmodified lines | |||
| 766 | desc_size -= desc_size % mps; | 777 | desc_size -= desc_size % mps; |
| 767 | } | 778 | } |
| 768 | 779 | ||
| 780 | /* Interrupt OUT EP with mps not multiple of 4 */ | ||
| 781 | if (hs_ep->index) | ||
| 782 | if (usb_endpoint_xfer_int(ep_desc) && !dir_in && (mps % 4)) { | ||
| 783 | desc_size = mps; | ||
| 784 | *mask = DEV_DMA_NBYTES_MASK; | ||
| 785 | } | ||
| 786 | |||
| 769 | return desc_size; | 787 | return desc_size; |
| 770 | } | 788 | } |
| 771 | 789 | ||
| @@ -1123,13 +1141,7 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg, · 351 unmodified lines | |||
| 1123 | length += (mps - (length % mps)); | 1141 | length += (mps - (length % mps)); |
| 1124 | } | 1142 | } |
| 1125 | 1143 | ||
| 1126 | /* | 1144 | if (continuing) |
| 1127 | * If more data to send, adjust DMA for EP0 out data stage. | ||
| 1128 | * ureq->dma stays unchanged, hence increment it by already | ||
| 1129 | * passed passed data count before starting new transaction. | ||
| 1130 | */ | ||
| 1131 | if (!index && hsotg->ep0_state == DWC2_EP0_DATA_OUT && | ||
| 1132 | continuing) | ||
| 1133 | offset = ureq->actual; | 1145 | offset = ureq->actual; |
| 1134 | 1146 | ||
| 1135 | /* Fill DDMA chain entries */ | 1147 | /* Fill DDMA chain entries */ |
| @@ -2320,22 +2332,36 @@ static void dwc2_hsotg_change_ep_iso_parity(struct dwc2_hsotg *hsotg, · 1184 unmodified lines | |||
| 2320 | */ | 2332 | */ |
| 2321 | static unsigned int dwc2_gadget_get_xfersize_ddma(struct dwc2_hsotg_ep *hs_ep) | 2333 | static unsigned int dwc2_gadget_get_xfersize_ddma(struct dwc2_hsotg_ep *hs_ep) |
| 2322 | { | 2334 | { |
| 2335 | const struct usb_endpoint_descriptor *ep_desc = hs_ep->ep.desc; | ||
| 2323 | struct dwc2_hsotg *hsotg = hs_ep->parent; | 2336 | struct dwc2_hsotg *hsotg = hs_ep->parent; |
| 2324 | unsigned int bytes_rem = 0; | 2337 | unsigned int bytes_rem = 0; |
| 2338 | unsigned int bytes_rem_correction = 0; | ||
| 2325 | struct dwc2_dma_desc *desc = hs_ep->desc_list; | 2339 | struct dwc2_dma_desc *desc = hs_ep->desc_list; |
| 2326 | int i; | 2340 | int i; |
| 2327 | u32 status; | 2341 | u32 status; |
| 2342 | u32 mps = hs_ep->ep.maxpacket; | ||
| 2343 | int dir_in = hs_ep->dir_in; | ||
| 2328 | 2344 | ||
| 2329 | if (!desc) | 2345 | if (!desc) |
| 2330 | return -EINVAL; | 2346 | return -EINVAL; |
| 2331 | 2347 | ||
| 2348 | /* Interrupt OUT EP with mps not multiple of 4 */ | ||
| 2349 | if (hs_ep->index) | ||
| 2350 | if (usb_endpoint_xfer_int(ep_desc) && !dir_in && (mps % 4)) | ||
| 2351 | bytes_rem_correction = 4 - (mps % 4); | ||
| 2352 | |||
| 2332 | for (i = 0; i < hs_ep->desc_count; ++i) { | 2353 | for (i = 0; i < hs_ep->desc_count; ++i) { |
| 2333 | status = desc->status; | 2354 | status = desc->status; |
| 2334 | bytes_rem += status & DEV_DMA_NBYTES_MASK; | 2355 | bytes_rem += status & DEV_DMA_NBYTES_MASK; |
| 2356 | bytes_rem -= bytes_rem_correction; | ||
| 2335 | 2357 | ||
| 2336 | if (status & DEV_DMA_STS_MASK) | 2358 | if (status & DEV_DMA_STS_MASK) |
| 2337 | dev_err(hsotg->dev, "descriptor %d closed with %x\n", | 2359 | dev_err(hsotg->dev, "descriptor %d closed with %x\n", |
| 2338 | i, status & DEV_DMA_STS_MASK); | 2360 | i, status & DEV_DMA_STS_MASK); |
| 2361 | |||
| 2362 | if (status & DEV_DMA_L) | ||
| 2363 | break; | ||
| 2364 | |||
| 2339 | desc++; | 2365 | desc++; |
| 2340 | } | 2366 | } |
| 2341 | 2367 | ||
| @@ -3530,7 +3556,7 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, · 1188 unmodified lines | |||
| 3530 | dwc2_readl(hsotg, DOEPCTL0)); | 3556 | dwc2_readl(hsotg, DOEPCTL0)); |
| 3531 | } | 3557 | } |
| 3532 | 3558 | ||
| 3533 | static void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg) | 3559 | void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg) |
| 3534 | { | 3560 | { |
| 3535 | /* set the soft-disconnect bit */ | 3561 | /* set the soft-disconnect bit */ |
| 3536 | dwc2_set_bit(hsotg, DCTL, DCTL_SFTDISCON); | 3562 | dwc2_set_bit(hsotg, DCTL, DCTL_SFTDISCON); |
| @@ -185,7 +185,7 @@ static void dwc2_set_stm32mp15_hsotg_params(struct dwc2_hsotg *hsotg) · 184 unmodified lines | |||
| 185 | struct dwc2_core_params *p = &hsotg->params; | 185 | struct dwc2_core_params *p = &hsotg->params; |
| 186 | 186 | ||
| 187 | p->otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE; | 187 | p->otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE; |
| 188 | p->activate_stm_id_vb_detection = true; | 188 | p->activate_stm_id_vb_detection = !device_property_read_bool(hsotg->dev, "usb-role-switch"); |
| 189 | p->host_rx_fifo_size = 440; | 189 | p->host_rx_fifo_size = 440; |
| 190 | p->host_nperio_tx_fifo_size = 256; | 190 | p->host_nperio_tx_fifo_size = 256; |
| 191 | p->host_perio_tx_fifo_size = 256; | 191 | p->host_perio_tx_fifo_size = 256; |
| @@ -210,6 +210,7 @@ const struct of_device_id dwc2_of_match_table[] = { · 18 unmodified lines | |||
| 210 | { .compatible = "amlogic,meson-g12a-usb", | 210 | { .compatible = "amlogic,meson-g12a-usb", |
| 211 | .data = dwc2_set_amlogic_g12a_params }, | 211 | .data = dwc2_set_amlogic_g12a_params }, |
| 212 | { .compatible = "amcc,dwc-otg", .data = dwc2_set_amcc_params }, | 212 | { .compatible = "amcc,dwc-otg", .data = dwc2_set_amcc_params }, |
| 213 | { .compatible = "apm,apm82181-dwc-otg", .data = dwc2_set_amcc_params }, | ||
| 213 | { .compatible = "st,stm32f4x9-fsotg", | 214 | { .compatible = "st,stm32f4x9-fsotg", |
| 214 | .data = dwc2_set_stm32f4x9_fsotg_params }, | 215 | .data = dwc2_set_stm32f4x9_fsotg_params }, |
| 215 | { .compatible = "st,stm32f4x9-hsotg" }, | 216 | { .compatible = "st,stm32f4x9-hsotg" }, |
| @@ -860,7 +861,7 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) · 644 unmodified lines | |||
| 860 | int dwc2_init_params(struct dwc2_hsotg *hsotg) | 861 | int dwc2_init_params(struct dwc2_hsotg *hsotg) |
| 861 | { | 862 | { |
| 862 | const struct of_device_id *match; | 863 | const struct of_device_id *match; |
| 863 | void (*set_params)(void *data); | 864 | void (*set_params)(struct dwc2_hsotg *data); |
| 864 | 865 | ||
| 865 | dwc2_set_default_params(hsotg); | 866 | dwc2_set_default_params(hsotg); |
| 866 | dwc2_get_device_properties(hsotg); | 867 | dwc2_get_device_properties(hsotg); |
| @@ -121,6 +121,13 @@ static int dwc2_get_dr_mode(struct dwc2_hsotg *hsotg) · 120 unmodified lines | |||
| 121 | return 0; | 121 | return 0; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | static void __dwc2_disable_regulators(void *data) | ||
| 125 | { | ||
| 126 | struct dwc2_hsotg *hsotg = data; | ||
| 127 | |||
| 128 | regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); | ||
| 129 | } | ||
| 130 | |||
| 124 | static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg) | 131 | static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg) |
| 125 | { | 132 | { |
| 126 | struct platform_device *pdev = to_platform_device(hsotg->dev); | 133 | struct platform_device *pdev = to_platform_device(hsotg->dev); |
| @@ -131,6 +138,11 @@ static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg) · 4 unmodified lines | |||
| 131 | if (ret) | 138 | if (ret) |
| 132 | return ret; | 139 | return ret; |
| 133 | 140 | ||
| 141 | ret = devm_add_action_or_reset(&pdev->dev, | ||
| 142 | __dwc2_disable_regulators, hsotg); | ||
| 143 | if (ret) | ||
| 144 | return ret; | ||
| 145 | |||
| 134 | if (hsotg->clk) { | 146 | if (hsotg->clk) { |
| 135 | ret = clk_prepare_enable(hsotg->clk); | 147 | ret = clk_prepare_enable(hsotg->clk); |
| 136 | if (ret) | 148 | if (ret) |
| @@ -186,10 +198,7 @@ static int __dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg) · 49 unmodified lines | |||
| 186 | if (hsotg->clk) | 198 | if (hsotg->clk) |
| 187 | clk_disable_unprepare(hsotg->clk); | 199 | clk_disable_unprepare(hsotg->clk); |
| 188 | 200 | ||
| 189 | ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), | 201 | return 0; |
| 190 | hsotg->supplies); | ||
| 191 | |||
| 192 | return ret; | ||
| 193 | } | 202 | } |
| 194 | 203 | ||
| 195 | /** | 204 | /** |
| @@ -314,6 +323,8 @@ static int dwc2_driver_remove(struct platform_device *dev) · 118 unmodified lines | |||
| 314 | if (hsotg->gadget_enabled) | 323 | if (hsotg->gadget_enabled) |
| 315 | dwc2_hsotg_remove(hsotg); | 324 | dwc2_hsotg_remove(hsotg); |
| 316 | 325 | ||
| 326 | dwc2_drd_exit(hsotg); | ||
| 327 | |||
| 317 | if (hsotg->params.activate_stm_id_vb_detection) | 328 | if (hsotg->params.activate_stm_id_vb_detection) |
| 318 | regulator_disable(hsotg->usb33d); | 329 | regulator_disable(hsotg->usb33d); |
| 319 | 330 | ||
| @@ -533,10 +544,17 @@ static int dwc2_driver_probe(struct platform_device *dev) · 213 unmodified lines | |||
| 533 | dwc2_writel(hsotg, ggpio, GGPIO); | 544 | dwc2_writel(hsotg, ggpio, GGPIO); |
| 534 | } | 545 | } |
| 535 | 546 | ||
| 547 | retval = dwc2_drd_init(hsotg); | ||
| 548 | if (retval) { | ||
| 549 | if (retval != -EPROBE_DEFER) | ||
| 550 | dev_err(hsotg->dev, "failed to initialize dual-role\n"); | ||
| 551 | goto error_init; | ||
| 552 | } | ||
| 553 | |||
| 536 | if (hsotg->dr_mode != USB_DR_MODE_HOST) { | 554 | if (hsotg->dr_mode != USB_DR_MODE_HOST) { |
| 537 | retval = dwc2_gadget_init(hsotg); | 555 | retval = dwc2_gadget_init(hsotg); |
| 538 | if (retval) | 556 | if (retval) |
| 539 | goto error_init; | 557 | goto error_drd; |
| 540 | hsotg->gadget_enabled = 1; | 558 | hsotg->gadget_enabled = 1; |
| 541 | } | 559 | } |
| 542 | 560 | ||
| @@ -562,7 +580,7 @@ static int dwc2_driver_probe(struct platform_device *dev) · 19 unmodified lines | |||
| 562 | if (retval) { | 580 | if (retval) { |
| 563 | if (hsotg->gadget_enabled) | 581 | if (hsotg->gadget_enabled) |
| 564 | dwc2_hsotg_remove(hsotg); | 582 | dwc2_hsotg_remove(hsotg); |
| 565 | goto error_init; | 583 | goto error_drd; |
| 566 | } | 584 | } |
| 567 | hsotg->hcd_enabled = 1; | 585 | hsotg->hcd_enabled = 1; |
| 568 | } | 586 | } |
| @@ -584,12 +602,19 @@ static int dwc2_driver_probe(struct platform_device *dev) · 15 unmodified lines | |||
| 584 | if (retval) { | 602 | if (retval) { |
| 585 | hsotg->gadget.udc = NULL; | 603 | hsotg->gadget.udc = NULL; |
| 586 | dwc2_hsotg_remove(hsotg); | 604 | dwc2_hsotg_remove(hsotg); |
| 587 | goto error_init; | 605 | goto error_debugfs; |
| 588 | } | 606 | } |
| 589 | } | 607 | } |
| 590 | #endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */ | 608 | #endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */ |
| 591 | return 0; | 609 | return 0; |
| 592 | 610 | ||
| 611 | error_debugfs: | ||
| 612 | dwc2_debugfs_exit(hsotg); | ||
| 613 | if (hsotg->hcd_enabled) | ||
| 614 | dwc2_hcd_remove(hsotg); | ||
| 615 | error_drd: | ||
| 616 | dwc2_drd_exit(hsotg); | ||
| 617 | |||
| 593 | error_init: | 618 | error_init: |
| 594 | if (hsotg->params.activate_stm_id_vb_detection) | 619 | if (hsotg->params.activate_stm_id_vb_detection) |
| 595 | regulator_disable(hsotg->usb33d); | 620 | regulator_disable(hsotg->usb33d); |
| @@ -608,6 +633,8 @@ static int __maybe_unused dwc2_suspend(struct device *dev) · 12 unmodified lines | |||
| 608 | if (is_device_mode) | 633 | if (is_device_mode) |
| 609 | dwc2_hsotg_suspend(dwc2); | 634 | dwc2_hsotg_suspend(dwc2); |
| 610 | 635 | ||
| 636 | dwc2_drd_suspend(dwc2); | ||
| 637 | |||
| 611 | if (dwc2->params.activate_stm_id_vb_detection) { | 638 | if (dwc2->params.activate_stm_id_vb_detection) { |
| 612 | unsigned long flags; | 639 | unsigned long flags; |
| 613 | u32 ggpio, gotgctl; | 640 | u32 ggpio, gotgctl; |
| @@ -688,6 +715,8 @@ static int __maybe_unused dwc2_resume(struct device *dev) · 74 unmodified lines | |||
| 688 | /* Need to restore FORCEDEVMODE/FORCEHOSTMODE */ | 715 | /* Need to restore FORCEDEVMODE/FORCEHOSTMODE */ |
| 689 | dwc2_force_dr_mode(dwc2); | 716 | dwc2_force_dr_mode(dwc2); |
| 690 | 717 | ||
| 718 | dwc2_drd_resume(dwc2); | ||
| 719 | |||
| 691 | if (dwc2_is_device_mode(dwc2)) | 720 | if (dwc2_is_device_mode(dwc2)) |
| 692 | ret = dwc2_hsotg_resume(dwc2); | 721 | ret = dwc2_hsotg_resume(dwc2); |
| 693 | 722 | ||
| @@ -119,9 +119,7 @@ static void __dwc3_set_mode(struct work_struct *work) · 118 unmodified lines | |||
| 119 | struct dwc3 *dwc = work_to_dwc(work); | 119 | struct dwc3 *dwc = work_to_dwc(work); |
| 120 | unsigned long flags; | 120 | unsigned long flags; |
| 121 | int ret; | 121 | int ret; |
| 122 | 122 | u32 reg; | |
| 123 | if (dwc->dr_mode != USB_DR_MODE_OTG) | ||
| 124 | return; | ||
| 125 | 123 | ||
| 126 | pm_runtime_get_sync(dwc->dev); | 124 | pm_runtime_get_sync(dwc->dev); |
| 127 | 125 | ||
| @@ -172,6 +170,11 @@ static void __dwc3_set_mode(struct work_struct *work) · 44 unmodified lines | |||
| 172 | otg_set_vbus(dwc->usb2_phy->otg, true); | 170 | otg_set_vbus(dwc->usb2_phy->otg, true); |
| 173 | phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST); | 171 | phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST); |
| 174 | phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST); | 172 | phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST); |
| 173 | if (dwc->dis_split_quirk) { | ||
| 174 | reg = dwc3_readl(dwc->regs, DWC3_GUCTL3); | ||
| 175 | reg |= DWC3_GUCTL3_SPLITDISABLE; | ||
| 176 | dwc3_writel(dwc->regs, DWC3_GUCTL3, reg); | ||
| 177 | } | ||
| 175 | } | 178 | } |
| 176 | break; | 179 | break; |
| 177 | case DWC3_GCTL_PRTCAP_DEVICE: | 180 | case DWC3_GCTL_PRTCAP_DEVICE: |
| @@ -203,6 +206,9 @@ void dwc3_set_mode(struct dwc3 *dwc, u32 mode) · 25 unmodified lines | |||
| 203 | { | 206 | { |
| 204 | unsigned long flags; | 207 | unsigned long flags; |
| 205 | 208 | ||
| 209 | if (dwc->dr_mode != USB_DR_MODE_OTG) | ||
| 210 | return; | ||
| 211 | |||
| 206 | spin_lock_irqsave(&dwc->lock, flags); | 212 | spin_lock_irqsave(&dwc->lock, flags); |
| 207 | dwc->desired_dr_role = mode; | 213 | dwc->desired_dr_role = mode; |
| 208 | spin_unlock_irqrestore(&dwc->lock, flags); | 214 | spin_unlock_irqrestore(&dwc->lock, flags); |
| @@ -929,13 +935,6 @@ static int dwc3_core_init(struct dwc3 *dwc) · 720 unmodified lines | |||
| 929 | */ | 935 | */ |
| 930 | dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); | 936 | dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); |
| 931 | 937 | ||
| 932 | /* Handle USB2.0-only core configuration */ | ||
| 933 | if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == | ||
| 934 | DWC3_GHWPARAMS3_SSPHY_IFC_DIS) { | ||
| 935 | if (dwc->maximum_speed == USB_SPEED_SUPER) | ||
| 936 | dwc->maximum_speed = USB_SPEED_HIGH; | ||
| 937 | } | ||
| 938 | |||
| 939 | ret = dwc3_phy_setup(dwc); | 938 | ret = dwc3_phy_setup(dwc); |
| 940 | if (ret) | 939 | if (ret) |
| 941 | goto err0; | 940 | goto err0; |
| @@ -1356,6 +1355,9 @@ static void dwc3_get_properties(struct dwc3 *dwc) · 414 unmodified lines | |||
| 1356 | dwc->dis_metastability_quirk = device_property_read_bool(dev, | 1355 | dwc->dis_metastability_quirk = device_property_read_bool(dev, |
| 1357 | "snps,dis_metastability_quirk"); | 1356 | "snps,dis_metastability_quirk"); |
| 1358 | 1357 | ||
| 1358 | dwc->dis_split_quirk = device_property_read_bool(dev, | ||
| 1359 | "snps,dis-split-quirk"); | ||
| 1360 | |||
| 1359 | dwc->lpm_nyet_threshold = lpm_nyet_threshold; | 1361 | dwc->lpm_nyet_threshold = lpm_nyet_threshold; |
| 1360 | dwc->tx_de_emphasis = tx_de_emphasis; | 1362 | dwc->tx_de_emphasis = tx_de_emphasis; |
| 1361 | 1363 | ||
| @@ -1381,6 +1383,8 @@ bool dwc3_has_imod(struct dwc3 *dwc) · 19 unmodified lines | |||
| 1381 | static void dwc3_check_params(struct dwc3 *dwc) | 1383 | static void dwc3_check_params(struct dwc3 *dwc) |
| 1382 | { | 1384 | { |
| 1383 | struct device *dev = dwc->dev; | 1385 | struct device *dev = dwc->dev; |
| 1386 | unsigned int hwparam_gen = | ||
| 1387 | DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3); | ||
| 1384 | 1388 | ||
| 1385 | /* Check for proper value of imod_interval */ | 1389 | /* Check for proper value of imod_interval */ |
| 1386 | if (dwc->imod_interval && !dwc3_has_imod(dwc)) { | 1390 | if (dwc->imod_interval && !dwc3_has_imod(dwc)) { |
| @@ -1404,25 +1408,40 @@ static void dwc3_check_params(struct dwc3 *dwc) · 17 unmodified lines | |||
| 1404 | case USB_SPEED_LOW: | 1408 | case USB_SPEED_LOW: |
| 1405 | case USB_SPEED_FULL: | 1409 | case USB_SPEED_FULL: |
| 1406 | case USB_SPEED_HIGH: | 1410 | case USB_SPEED_HIGH: |
| 1411 | break; | ||
| 1407 | case USB_SPEED_SUPER: | 1412 | case USB_SPEED_SUPER: |
| 1413 | if (hwparam_gen == DWC3_GHWPARAMS3_SSPHY_IFC_DIS) | ||
| 1414 | dev_warn(dev, "UDC doesn't support Gen 1\n"); | ||
| 1415 | break; | ||
| 1408 | case USB_SPEED_SUPER_PLUS: | 1416 | case USB_SPEED_SUPER_PLUS: |
| 1417 | if ((DWC3_IP_IS(DWC32) && | ||
| 1418 | hwparam_gen == DWC3_GHWPARAMS3_SSPHY_IFC_DIS) || | ||
| 1419 | (!DWC3_IP_IS(DWC32) && | ||
| 1420 | hwparam_gen != DWC3_GHWPARAMS3_SSPHY_IFC_GEN2)) | ||
| 1421 | dev_warn(dev, "UDC doesn't support SSP\n"); | ||
| 1409 | break; | 1422 | break; |
| 1410 | default: | 1423 | default: |
| 1411 | dev_err(dev, "invalid maximum_speed parameter %d\n", | 1424 | dev_err(dev, "invalid maximum_speed parameter %d\n", |
| 1412 | dwc->maximum_speed); | 1425 | dwc->maximum_speed); |
| 1413 | fallthrough; | 1426 | fallthrough; |
| 1414 | case USB_SPEED_UNKNOWN: | 1427 | case USB_SPEED_UNKNOWN: |
| 1415 | /* default to superspeed */ | 1428 | switch (hwparam_gen) { |
| 1416 | dwc->maximum_speed = USB_SPEED_SUPER; | 1429 | case DWC3_GHWPARAMS3_SSPHY_IFC_GEN2: |
| 1417 | |||
| 1418 | /* | ||
| 1419 | * default to superspeed plus if we are capable. | ||
| 1420 | */ | ||
| 1421 | if ((DWC3_IP_IS(DWC31) || DWC3_IP_IS(DWC32)) && | ||
| 1422 | (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == | ||
| 1423 | DWC3_GHWPARAMS3_SSPHY_IFC_GEN2)) | ||
| 1424 | dwc->maximum_speed = USB_SPEED_SUPER_PLUS; | 1430 | dwc->maximum_speed = USB_SPEED_SUPER_PLUS; |
| 1425 | 1431 | break; | |
| 1432 | case DWC3_GHWPARAMS3_SSPHY_IFC_GEN1: | ||
| 1433 | if (DWC3_IP_IS(DWC32)) | ||
| 1434 | dwc->maximum_speed = USB_SPEED_SUPER_PLUS; | ||
| 1435 | else | ||
| 1436 | dwc->maximum_speed = USB_SPEED_SUPER; | ||
| 1437 | break; | ||
| 1438 | case DWC3_GHWPARAMS3_SSPHY_IFC_DIS: | ||
| 1439 | dwc->maximum_speed = USB_SPEED_HIGH; | ||
| 1440 | break; | ||
| 1441 | default: | ||
| 1442 | dwc->maximum_speed = USB_SPEED_SUPER; | ||
| 1443 | break; | ||
| 1444 | } | ||
| 1426 | break; | 1445 | break; |
| 1427 | } | 1446 | } |
| 1428 | } | 1447 | } |
| @@ -1554,6 +1573,17 @@ static int dwc3_probe(struct platform_device *pdev) · 125 unmodified lines | |||
| 1554 | 1573 | ||
| 1555 | err5: | 1574 | err5: |
| 1556 | dwc3_event_buffers_cleanup(dwc); | 1575 | dwc3_event_buffers_cleanup(dwc); |
| 1576 | |||
| 1577 | usb_phy_shutdown(dwc->usb2_phy); | ||
| 1578 | usb_phy_shutdown(dwc->usb3_phy); | ||
| 1579 | phy_exit(dwc->usb2_generic_phy); | ||
| 1580 | phy_exit(dwc->usb3_generic_phy); | ||
| 1581 | |||
| 1582 | usb_phy_set_suspend(dwc->usb2_phy, 1); | ||
| 1583 | usb_phy_set_suspend(dwc->usb3_phy, 1); | ||
| 1584 | phy_power_off(dwc->usb2_generic_phy); | ||
| 1585 | phy_power_off(dwc->usb3_generic_phy); | ||
| 1586 | |||
| 1557 | dwc3_ulpi_exit(dwc); | 1587 | dwc3_ulpi_exit(dwc); |
| 1558 | 1588 | ||
| 1559 | err4: | 1589 | err4: |
| @@ -1589,9 +1619,9 @@ static int dwc3_remove(struct platform_device *pdev) · 29 unmodified lines | |||
| 1589 | dwc3_core_exit(dwc); | 1619 | dwc3_core_exit(dwc); |
| 1590 | dwc3_ulpi_exit(dwc); | 1620 | dwc3_ulpi_exit(dwc); |
| 1591 | 1621 | ||
| 1592 | pm_runtime_put_sync(&pdev->dev); | ||
| 1593 | pm_runtime_allow(&pdev->dev); | ||
| 1594 | pm_runtime_disable(&pdev->dev); | 1622 | pm_runtime_disable(&pdev->dev); |
| 1623 | pm_runtime_put_noidle(&pdev->dev); | ||
| 1624 | pm_runtime_set_suspended(&pdev->dev); | ||
| 1595 | 1625 | ||
| 1596 | dwc3_free_event_buffers(dwc); | 1626 | dwc3_free_event_buffers(dwc); |
| 1597 | dwc3_free_scratch_buffers(dwc); | 1627 | dwc3_free_scratch_buffers(dwc); |
| @@ -1865,10 +1895,26 @@ static int dwc3_resume(struct device *dev) · 267 unmodified lines | |||
| 1865 | 1895 | ||
| 1866 | return 0; | 1896 | return 0; |
| 1867 | } | 1897 | } |
| 1898 | |||
| 1899 | static void dwc3_complete(struct device *dev) | ||
| 1900 | { | ||
| 1901 | struct dwc3 *dwc = dev_get_drvdata(dev); | ||
| 1902 | u32 reg; | ||
| 1903 | |||
| 1904 | if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST && | ||
| 1905 | dwc->dis_split_quirk) { | ||
| 1906 | reg = dwc3_readl(dwc->regs, DWC3_GUCTL3); | ||
| 1907 | reg |= DWC3_GUCTL3_SPLITDISABLE; | ||
| 1908 | dwc3_writel(dwc->regs, DWC3_GUCTL3, reg); | ||
| 1909 | } | ||
| 1910 | } | ||
| 1911 | #else | ||
| 1912 | #define dwc3_complete NULL | ||
| 1868 | #endif /* CONFIG_PM_SLEEP */ | 1913 | #endif /* CONFIG_PM_SLEEP */ |
| 1869 | 1914 | ||
| 1870 | static const struct dev_pm_ops dwc3_dev_pm_ops = { | 1915 | static const struct dev_pm_ops dwc3_dev_pm_ops = { |
| 1871 | SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) | 1916 | SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) |
| 1917 | .complete = dwc3_complete, | ||
| 1872 | SET_RUNTIME_PM_OPS(dwc3_runtime_suspend, dwc3_runtime_resume, | 1918 | SET_RUNTIME_PM_OPS(dwc3_runtime_suspend, dwc3_runtime_resume, |
| 1873 | dwc3_runtime_idle) | 1919 | dwc3_runtime_idle) |
| 1874 | }; | 1920 | }; |
| @@ -138,6 +138,7 @@ · 137 unmodified lines | |||
| 138 | #define DWC3_GEVNTCOUNT(n) (0xc40c + ((n) * 0x10)) | 138 | #define DWC3_GEVNTCOUNT(n) (0xc40c + ((n) * 0x10)) |
| 139 | 139 | ||
| 140 | #define DWC3_GHWPARAMS8 0xc600 | 140 | #define DWC3_GHWPARAMS8 0xc600 |
| 141 | #define DWC3_GUCTL3 0xc60c | ||
| 141 | #define DWC3_GFLADJ 0xc630 | 142 | #define DWC3_GFLADJ 0xc630 |
| 142 | 143 | ||
| 143 | /* Device Registers */ | 144 | /* Device Registers */ |
| @@ -380,6 +381,9 @@ · 236 unmodified lines | |||
| 380 | /* Global User Control Register 2 */ | 381 | /* Global User Control Register 2 */ |
| 381 | #define DWC3_GUCTL2_RST_ACTBITLATER BIT(14) | 382 | #define DWC3_GUCTL2_RST_ACTBITLATER BIT(14) |
| 382 | 383 | ||
| 384 | /* Global User Control Register 3 */ | ||
| 385 | #define DWC3_GUCTL3_SPLITDISABLE BIT(14) | ||
| 386 | |||
| 383 | /* Device Configuration Register */ | 387 | /* Device Configuration Register */ |
| 384 | #define DWC3_DCFG_DEVADDR(addr) ((addr) << 3) | 388 | #define DWC3_DCFG_DEVADDR(addr) ((addr) << 3) |
| 385 | #define DWC3_DCFG_DEVADDR_MASK DWC3_DCFG_DEVADDR(0x7f) | 389 | #define DWC3_DCFG_DEVADDR_MASK DWC3_DCFG_DEVADDR(0x7f) |
| @@ -634,7 +638,7 @@ struct dwc3_trb; · 248 unmodified lines | |||
| 634 | struct dwc3_event_buffer { | 638 | struct dwc3_event_buffer { |
| 635 | void *buf; | 639 | void *buf; |
| 636 | void *cache; | 640 | void *cache; |
| 637 | unsigned length; | 641 | unsigned int length; |
| 638 | unsigned int lpos; | 642 | unsigned int lpos; |
| 639 | unsigned int count; | 643 | unsigned int count; |
| 640 | unsigned int flags; | 644 | unsigned int flags; |
| @@ -694,7 +698,7 @@ struct dwc3_ep { · 53 unmodified lines | |||
| 694 | struct dwc3 *dwc; | 698 | struct dwc3 *dwc; |
| 695 | 699 | ||
| 696 | u32 saved_state; | 700 | u32 saved_state; |
| 697 | unsigned flags; | 701 | unsigned int flags; |
| 698 | #define DWC3_EP_ENABLED BIT(0) | 702 | #define DWC3_EP_ENABLED BIT(0) |
| 699 | #define DWC3_EP_STALL BIT(1) | 703 | #define DWC3_EP_STALL BIT(1) |
| 700 | #define DWC3_EP_WEDGE BIT(2) | 704 | #define DWC3_EP_WEDGE BIT(2) |
| @@ -706,6 +710,7 @@ struct dwc3_ep { · 5 unmodified lines | |||
| 706 | #define DWC3_EP_IGNORE_NEXT_NOSTREAM BIT(8) | 710 | #define DWC3_EP_IGNORE_NEXT_NOSTREAM BIT(8) |
| 707 | #define DWC3_EP_FORCE_RESTART_STREAM BIT(9) | 711 | #define DWC3_EP_FORCE_RESTART_STREAM BIT(9) |
| 708 | #define DWC3_EP_FIRST_STREAM_PRIMED BIT(10) | 712 | #define DWC3_EP_FIRST_STREAM_PRIMED BIT(10) |
| 713 | #define DWC3_EP_PENDING_CLEAR_STALL BIT(11) | ||
| 709 | 714 | ||
| 710 | /* This last one is specific to EP0 */ | 715 | /* This last one is specific to EP0 */ |
| 711 | #define DWC3_EP0_DIR_IN BIT(31) | 716 | #define DWC3_EP0_DIR_IN BIT(31) |
| @@ -893,9 +898,9 @@ struct dwc3_request { · 181 unmodified lines | |||
| 893 | struct scatterlist *sg; | 898 | struct scatterlist *sg; |
| 894 | struct scatterlist *start_sg; | 899 | struct scatterlist *start_sg; |
| 895 | 900 | ||
| 896 | unsigned num_pending_sgs; | 901 | unsigned int num_pending_sgs; |
| 897 | unsigned int num_queued_sgs; | 902 | unsigned int num_queued_sgs; |
| 898 | unsigned remaining; | 903 | unsigned int remaining; |
| 899 | 904 | ||
| 900 | unsigned int status; | 905 | unsigned int status; |
| 901 | #define DWC3_REQUEST_STATUS_QUEUED 0 | 906 | #define DWC3_REQUEST_STATUS_QUEUED 0 |
| @@ -908,11 +913,11 @@ struct dwc3_request { · 6 unmodified lines | |||
| 908 | struct dwc3_trb *trb; | 913 | struct dwc3_trb *trb; |
| 909 | dma_addr_t trb_dma; | 914 | dma_addr_t trb_dma; |
| 910 | 915 | ||
| 911 | unsigned num_trbs; | 916 | unsigned int num_trbs; |
| 912 | 917 | ||
| 913 | unsigned needs_extra_trb:1; | 918 | unsigned int needs_extra_trb:1; |
| 914 | unsigned direction:1; | 919 | unsigned int direction:1; |
| 915 | unsigned mapped:1; | 920 | unsigned int mapped:1; |
| 916 | }; | 921 | }; |
| 917 | 922 | ||
| 918 | /* | 923 | /* |
| @@ -1010,8 +1015,8 @@ struct dwc3_scratchpad_array { · 91 unmodified lines | |||
| 1010 | * @has_lpm_erratum: true when core was configured with LPM Erratum. Note that | 1015 | * @has_lpm_erratum: true when core was configured with LPM Erratum. Note that |
| 1011 | * there's now way for software to detect this in runtime. | 1016 | * there's now way for software to detect this in runtime. |
| 1012 | * @is_utmi_l1_suspend: the core asserts output signal | 1017 | * @is_utmi_l1_suspend: the core asserts output signal |
| 1013 | * 0 - utmi_sleep_n | 1018 | * 0 - utmi_sleep_n |
| 1014 | * 1 - utmi_l1_suspend_n | 1019 | * 1 - utmi_l1_suspend_n |
| 1015 | * @is_fpga: true when we are using the FPGA board | 1020 | * @is_fpga: true when we are using the FPGA board |
| 1016 | * @pending_events: true when we have pending IRQs to be handled | 1021 | * @pending_events: true when we have pending IRQs to be handled |
| 1017 | * @pullups_connected: true when Run/Stop bit is set | 1022 | * @pullups_connected: true when Run/Stop bit is set |
| @@ -1047,13 +1052,14 @@ struct dwc3_scratchpad_array { · 29 unmodified lines | |||
| 1047 | * instances in park mode. | 1052 | * instances in park mode. |
| 1048 | * @tx_de_emphasis_quirk: set if we enable Tx de-emphasis quirk | 1053 | * @tx_de_emphasis_quirk: set if we enable Tx de-emphasis quirk |
| 1049 | * @tx_de_emphasis: Tx de-emphasis value | 1054 | * @tx_de_emphasis: Tx de-emphasis value |
| 1050 | * 0 - -6dB de-emphasis | 1055 | * 0 - -6dB de-emphasis |
| 1051 | * 1 - -3.5dB de-emphasis | 1056 | * 1 - -3.5dB de-emphasis |
| 1052 | * 2 - No de-emphasis | 1057 | * 2 - No de-emphasis |
| 1053 | * 3 - Reserved | 1058 | * 3 - Reserved |
| 1054 | * @dis_metastability_quirk: set to disable metastability quirk. | 1059 | * @dis_metastability_quirk: set to disable metastability quirk. |
| 1060 | * @dis_split_quirk: set to disable split boundary. | ||
| 1055 | * @imod_interval: set the interrupt moderation interval in 250ns | 1061 | * @imod_interval: set the interrupt moderation interval in 250ns |
| 1056 | * increments or 0 to disable. | 1062 | * increments or 0 to disable. |
| 1057 | */ | 1063 | */ |
| 1058 | struct dwc3 { | 1064 | struct dwc3 { |
| 1059 | struct work_struct drd_work; | 1065 | struct work_struct drd_work; |
| @@ -1079,7 +1085,7 @@ struct dwc3 { · 19 unmodified lines | |||
| 1079 | struct dwc3_event_buffer *ev_buf; | 1085 | struct dwc3_event_buffer *ev_buf; |
| 1080 | struct dwc3_ep *eps[DWC3_ENDPOINTS_NUM]; | 1086 | struct dwc3_ep *eps[DWC3_ENDPOINTS_NUM]; |
| 1081 | 1087 | ||
| 1082 | struct usb_gadget gadget; | 1088 | struct usb_gadget *gadget; |
| 1083 | struct usb_gadget_driver *gadget_driver; | 1089 | struct usb_gadget_driver *gadget_driver; |
| 1084 | 1090 | ||
| 1085 | struct clk_bulk_data *clks; | 1091 | struct clk_bulk_data *clks; |
| @@ -1245,6 +1251,8 @@ struct dwc3 { · 159 unmodified lines | |||
| 1245 | 1251 | ||
| 1246 | unsigned dis_metastability_quirk:1; | 1252 | unsigned dis_metastability_quirk:1; |
| 1247 | 1253 | ||
| 1254 | unsigned dis_split_quirk:1; | ||
| 1255 | |||
| 1248 | u16 imod_interval; | 1256 | u16 imod_interval; |
| 1249 | }; | 1257 | }; |
| 1250 | 1258 | ||
| @@ -1456,9 +1464,10 @@ void dwc3_gadget_exit(struct dwc3 *dwc); · 205 unmodified lines | |||
| 1456 | int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode); | 1464 | int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode); |
| 1457 | int dwc3_gadget_get_link_state(struct dwc3 *dwc); | 1465 | int dwc3_gadget_get_link_state(struct dwc3 *dwc); |
| 1458 | int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state); | 1466 | int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state); |
| 1459 | int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd, | 1467 | int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd, |
| 1460 | struct dwc3_gadget_ep_cmd_params *params); | 1468 | struct dwc3_gadget_ep_cmd_params *params); |
| 1461 | int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned cmd, u32 param); | 1469 | int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned int cmd, |
| 1470 | u32 param); | ||
| 1462 | #else | 1471 | #else |
| 1463 | static inline int dwc3_gadget_init(struct dwc3 *dwc) | 1472 | static inline int dwc3_gadget_init(struct dwc3 *dwc) |
| 1464 | { return 0; } | 1473 | { return 0; } |
| @@ -1472,7 +1481,7 @@ static inline int dwc3_gadget_set_link_state(struct dwc3 *dwc, · 7 unmodified lines | |||
| 1472 | enum dwc3_link_state state) | 1481 | enum dwc3_link_state state) |
| 1473 | { return 0; } | 1482 | { return 0; } |
| 1474 | 1483 | ||
| 1475 | static inline int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd, | 1484 | static inline int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd, |
| 1476 | struct dwc3_gadget_ep_cmd_params *params) | 1485 | struct dwc3_gadget_ep_cmd_params *params) |
| 1477 | { return 0; } | 1486 | { return 0; } |
| 1478 | static inline int dwc3_send_gadget_generic_command(struct dwc3 *dwc, | 1487 | static inline int dwc3_send_gadget_generic_command(struct dwc3 *dwc, |
| @@ -371,7 +371,9 @@ static inline const char *dwc3_gadget_event_type_string(u8 event) · 370 unmodified lines | |||
| 371 | static inline const char *dwc3_decode_event(char *str, size_t size, u32 event, | 371 | static inline const char *dwc3_decode_event(char *str, size_t size, u32 event, |
| 372 | u32 ep0state) | 372 | u32 ep0state) |
| 373 | { | 373 | { |
| 374 | const union dwc3_event evt = (union dwc3_event) event; | 374 | union dwc3_event evt; |
| 375 | |||
| 376 | memcpy(&evt, &event, sizeof(event)); | ||
| 375 | 377 | ||
| 376 | if (evt.type.is_devspec) | 378 | if (evt.type.is_devspec) |
| 377 | return dwc3_gadget_event_string(str, size, &evt.devt); | 379 | return dwc3_gadget_event_string(str, size, &evt.devt); |
| @@ -411,8 +413,8 @@ static inline const char *dwc3_gadget_generic_cmd_status_string(int status) · 33 unmodified lines | |||
| 411 | 413 | ||
| 412 | 414 | ||
| 413 | #ifdef CONFIG_DEBUG_FS | 415 | #ifdef CONFIG_DEBUG_FS |
| 414 | extern void dwc3_debugfs_init(struct dwc3 *); | 416 | extern void dwc3_debugfs_init(struct dwc3 *d); |
| 415 | extern void dwc3_debugfs_exit(struct dwc3 *); | 417 | extern void dwc3_debugfs_exit(struct dwc3 *d); |
| 416 | #else | 418 | #else |
| 417 | static inline void dwc3_debugfs_init(struct dwc3 *d) | 419 | static inline void dwc3_debugfs_init(struct dwc3 *d) |
| 418 | { } | 420 | { } |
| @@ -397,13 +397,13 @@ static int dwc3_mode_show(struct seq_file *s, void *unused) · 396 unmodified lines | |||
| 397 | 397 | ||
| 398 | switch (DWC3_GCTL_PRTCAP(reg)) { | 398 | switch (DWC3_GCTL_PRTCAP(reg)) { |
| 399 | case DWC3_GCTL_PRTCAP_HOST: | 399 | case DWC3_GCTL_PRTCAP_HOST: |
| 400 | seq_printf(s, "host\n"); | 400 | seq_puts(s, "host\n"); |
| 401 | break; | 401 | break; |
| 402 | case DWC3_GCTL_PRTCAP_DEVICE: | 402 | case DWC3_GCTL_PRTCAP_DEVICE: |
| 403 | seq_printf(s, "device\n"); | 403 | seq_puts(s, "device\n"); |
| 404 | break; | 404 | break; |
| 405 | case DWC3_GCTL_PRTCAP_OTG: | 405 | case DWC3_GCTL_PRTCAP_OTG: |
| 406 | seq_printf(s, "otg\n"); | 406 | seq_puts(s, "otg\n"); |
| 407 | break; | 407 | break; |
| 408 | default: | 408 | default: |
| 409 | seq_printf(s, "UNKNOWN %08x\n", DWC3_GCTL_PRTCAP(reg)); | 409 | seq_printf(s, "UNKNOWN %08x\n", DWC3_GCTL_PRTCAP(reg)); |
| @@ -428,6 +428,9 @@ static ssize_t dwc3_mode_write(struct file *file, · 18 unmodified lines | |||
| 428 | if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) | 428 | if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) |
| 429 | return -EFAULT; | 429 | return -EFAULT; |
| 430 | 430 | ||
| 431 | if (dwc->dr_mode != USB_DR_MODE_OTG) | ||
| 432 | return count; | ||
| 433 | |||
| 431 | if (!strncmp(buf, "host", 4)) | 434 | if (!strncmp(buf, "host", 4)) |
| 432 | mode = DWC3_GCTL_PRTCAP_HOST; | 435 | mode = DWC3_GCTL_PRTCAP_HOST; |
| 433 | 436 | ||
| @@ -464,22 +467,22 @@ static int dwc3_testmode_show(struct seq_file *s, void *unused) · 30 unmodified lines | |||
| 464 | 467 | ||
| 465 | switch (reg) { | 468 | switch (reg) { |
| 466 | case 0: | 469 | case 0: |
| 467 | seq_printf(s, "no test\n"); | 470 | seq_puts(s, "no test\n"); |
| 468 | break; | 471 | break; |
| 469 | case USB_TEST_J: | 472 | case USB_TEST_J: |
| 470 | seq_printf(s, "test_j\n"); | 473 | seq_puts(s, "test_j\n"); |
| 471 | break; | 474 | break; |
| 472 | case USB_TEST_K: | 475 | case USB_TEST_K: |
| 473 | seq_printf(s, "test_k\n"); | 476 | seq_puts(s, "test_k\n"); |
| 474 | break; | 477 | break; |
| 475 | case USB_TEST_SE0_NAK: | 478 | case USB_TEST_SE0_NAK: |
| 476 | seq_printf(s, "test_se0_nak\n"); | 479 | seq_puts(s, "test_se0_nak\n"); |
| 477 | break; | 480 | break; |
| 478 | case USB_TEST_PACKET: | 481 | case USB_TEST_PACKET: |
| 479 | seq_printf(s, "test_packet\n"); | 482 | seq_puts(s, "test_packet\n"); |
| 480 | break; | 483 | break; |
| 481 | case USB_TEST_FORCE_ENABLE: | 484 | case USB_TEST_FORCE_ENABLE: |
| 482 | seq_printf(s, "test_force_enable\n"); | 485 | seq_puts(s, "test_force_enable\n"); |
| 483 | break; | 486 | break; |
| 484 | default: | 487 | default: |
| 485 | seq_printf(s, "UNKNOWN %d\n", reg); | 488 | seq_printf(s, "UNKNOWN %d\n", reg); |
| @@ -760,27 +763,26 @@ static int dwc3_transfer_type_show(struct seq_file *s, void *unused) · 274 unmodified lines | |||
| 760 | unsigned long flags; | 763 | unsigned long flags; |
| 761 | 764 | ||
| 762 | spin_lock_irqsave(&dwc->lock, flags); | 765 | spin_lock_irqsave(&dwc->lock, flags); |
| 763 | if (!(dep->flags & DWC3_EP_ENABLED) || | 766 | if (!(dep->flags & DWC3_EP_ENABLED) || !dep->endpoint.desc) { |
| 764 | !dep->endpoint.desc) { | 767 | seq_puts(s, "--\n"); |
| 765 | seq_printf(s, "--\n"); | ||
| 766 | goto out; | 768 | goto out; |
| 767 | } | 769 | } |
| 768 | 770 | ||
| 769 | switch (usb_endpoint_type(dep->endpoint.desc)) { | 771 | switch (usb_endpoint_type(dep->endpoint.desc)) { |
| 770 | case USB_ENDPOINT_XFER_CONTROL: | 772 | case USB_ENDPOINT_XFER_CONTROL: |
| 771 | seq_printf(s, "control\n"); | 773 | seq_puts(s, "control\n"); |
| 772 | break; | 774 | break; |
| 773 | case USB_ENDPOINT_XFER_ISOC: | 775 | case USB_ENDPOINT_XFER_ISOC: |
| 774 | seq_printf(s, "isochronous\n"); | 776 | seq_puts(s, "isochronous\n"); |
| 775 | break; | 777 | break; |
| 776 | case USB_ENDPOINT_XFER_BULK: | 778 | case USB_ENDPOINT_XFER_BULK: |
| 777 | seq_printf(s, "bulk\n"); | 779 | seq_puts(s, "bulk\n"); |
| 778 | break; | 780 | break; |
| 779 | case USB_ENDPOINT_XFER_INT: | 781 | case USB_ENDPOINT_XFER_INT: |
| 780 | seq_printf(s, "interrupt\n"); | 782 | seq_puts(s, "interrupt\n"); |
| 781 | break; | 783 | break; |
| 782 | default: | 784 | default: |
| 783 | seq_printf(s, "--\n"); | 785 | seq_puts(s, "--\n"); |
| 784 | } | 786 | } |
| 785 | 787 | ||
| 786 | out: | 788 | out: |
| @@ -798,11 +800,11 @@ static int dwc3_trb_ring_show(struct seq_file *s, void *unused) · 11 unmodified lines | |||
| 798 | 800 | ||
| 799 | spin_lock_irqsave(&dwc->lock, flags); | 801 | spin_lock_irqsave(&dwc->lock, flags); |
| 800 | if (dep->number <= 1) { | 802 | if (dep->number <= 1) { |
| 801 | seq_printf(s, "--\n"); | 803 | seq_puts(s, "--\n"); |
| 802 | goto out; | 804 | goto out; |
| 803 | } | 805 | } |
| 804 | 806 | ||
| 805 | seq_printf(s, "buffer_addr,size,type,ioc,isp_imi,csp,chn,lst,hwo\n"); | 807 | seq_puts(s, "buffer_addr,size,type,ioc,isp_imi,csp,chn,lst,hwo\n"); |
| 806 | 808 | ||
| 807 | for (i = 0; i < DWC3_TRB_NUM; i++) { | 809 | for (i = 0; i < DWC3_TRB_NUM; i++) { |
| 808 | struct dwc3_trb *trb = &dep->trb_pool[i]; | 810 | struct dwc3_trb *trb = &dep->trb_pool[i]; |
| @@ -884,7 +886,7 @@ static void dwc3_debugfs_create_endpoint_files(struct dwc3_ep *dep, · 75 unmodified lines | |||
| 884 | const struct file_operations *fops = dwc3_ep_file_map[i].fops; | 886 | const struct file_operations *fops = dwc3_ep_file_map[i].fops; |
| 885 | const char *name = dwc3_ep_file_map[i].name; | 887 | const char *name = dwc3_ep_file_map[i].name; |
| 886 | 888 | ||
| 887 | debugfs_create_file(name, S_IRUGO, parent, dep, fops); | 889 | debugfs_create_file(name, 0444, parent, dep, fops); |
| 888 | } | 890 | } |
| 889 | } | 891 | } |
| 890 | 892 | ||
| @@ -929,21 +931,18 @@ void dwc3_debugfs_init(struct dwc3 *dwc) · 38 unmodified lines | |||
| 929 | root = debugfs_create_dir(dev_name(dwc->dev), usb_debug_root); | 931 | root = debugfs_create_dir(dev_name(dwc->dev), usb_debug_root); |
| 930 | dwc->root = root; | 932 | dwc->root = root; |
| 931 | 933 | ||
| 932 | debugfs_create_regset32("regdump", S_IRUGO, root, dwc->regset); | 934 | debugfs_create_regset32("regdump", 0444, root, dwc->regset); |
| 933 | 935 | debugfs_create_file("lsp_dump", 0644, root, dwc, &dwc3_lsp_fops); | |
| 934 | debugfs_create_file("lsp_dump", S_IRUGO | S_IWUSR, root, dwc, | ||
| 935 | &dwc3_lsp_fops); | ||
| 936 | 936 | ||
| 937 | if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)) { | 937 | if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)) |
| 938 | debugfs_create_file("mode", S_IRUGO | S_IWUSR, root, dwc, | 938 | debugfs_create_file("mode", 0644, root, dwc, |
| 939 | &dwc3_mode_fops); | 939 | &dwc3_mode_fops); |
| 940 | } | ||
| 941 | 940 | ||
| 942 | if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) || | 941 | if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) || |
| 943 | IS_ENABLED(CONFIG_USB_DWC3_GADGET)) { | 942 | IS_ENABLED(CONFIG_USB_DWC3_GADGET)) { |
| 944 | debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root, dwc, | 943 | debugfs_create_file("testmode", 0644, root, dwc, |
| 945 | &dwc3_testmode_fops); | 944 | &dwc3_testmode_fops); |
| 946 | debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root, dwc, | 945 | debugfs_create_file("link_state", 0644, root, dwc, |
| 947 | &dwc3_link_state_fops); | 946 | &dwc3_link_state_fops); |
| 948 | dwc3_debugfs_create_endpoint_dirs(dwc, root); | 947 | dwc3_debugfs_create_endpoint_dirs(dwc, root); |
| 949 | } | 948 | } |
| @@ -116,23 +116,24 @@ static struct clk_bulk_data meson_a1_clocks[] = { · 115 unmodified lines | |||
| 116 | { .id = "xtal_usb_ctrl" }, | 116 | { .id = "xtal_usb_ctrl" }, |
| 117 | }; | 117 | }; |
| 118 | 118 | ||
| 119 | static const char *meson_gxm_phy_names[] = { | 119 | static const char * const meson_gxm_phy_names[] = { |
| 120 | "usb2-phy0", "usb2-phy1", "usb2-phy2", | 120 | "usb2-phy0", "usb2-phy1", "usb2-phy2", |
| 121 | }; | 121 | }; |
| 122 | 122 | ||
| 123 | static const char *meson_g12a_phy_names[] = { | 123 | static const char * const meson_g12a_phy_names[] = { |
| 124 | "usb2-phy0", "usb2-phy1", "usb3-phy0", | 124 | "usb2-phy0", "usb2-phy1", "usb3-phy0", |
| 125 | }; | 125 | }; |
| 126 | 126 | ||
| 127 | /* | 127 | /* |
| 128 | * Amlogic A1 has a single physical PHY, in slot 1, but still has the | 128 | * Amlogic A1 has a single physical PHY, in slot 1, but still has the |
| 129 | * two U2 PHY controls register blocks like G12A. | 129 | * two U2 PHY controls register blocks like G12A. |
| 130 | * AXG has the similar scheme, thus needs the same tweak. | ||
| 130 | * Handling the first PHY on slot 1 would need a large amount of code | 131 | * Handling the first PHY on slot 1 would need a large amount of code |
| 131 | * changes, and the current management is generic enough to handle it | 132 | * changes, and the current management is generic enough to handle it |
| 132 | * correctly when only the "usb2-phy1" phy is specified on-par with the | 133 | * correctly when only the "usb2-phy1" phy is specified on-par with the |
| 133 | * DT bindings. | 134 | * DT bindings. |
| 134 | */ | 135 | */ |
| 135 | static const char *meson_a1_phy_names[] = { | 136 | static const char * const meson_a1_phy_names[] = { |
| 136 | "usb2-phy0", "usb2-phy1" | 137 | "usb2-phy0", "usb2-phy1" |
| 137 | }; | 138 | }; |
| 138 | 139 | ||
| @@ -143,7 +144,7 @@ struct dwc3_meson_g12a_drvdata { · 4 unmodified lines | |||
| 143 | bool otg_phy_host_port_disable; | 144 | bool otg_phy_host_port_disable; |
| 144 | struct clk_bulk_data *clks; | 145 | struct clk_bulk_data *clks; |
| 145 | int num_clks; | 146 | int num_clks; |
| 146 | const char **phy_names; | 147 | const char * const *phy_names; |
| 147 | int num_phys; | 148 | int num_phys; |
| 148 | int (*setup_regmaps)(struct dwc3_meson_g12a *priv, void __iomem *base); | 149 | int (*setup_regmaps)(struct dwc3_meson_g12a *priv, void __iomem *base); |
| 149 | int (*usb2_init_phy)(struct dwc3_meson_g12a *priv, int i, | 150 | int (*usb2_init_phy)(struct dwc3_meson_g12a *priv, int i, |
| @@ -215,6 +216,19 @@ static struct dwc3_meson_g12a_drvdata gxm_drvdata = { · 65 unmodified lines | |||
| 215 | .usb_post_init = dwc3_meson_gxl_usb_post_init, | 216 | .usb_post_init = dwc3_meson_gxl_usb_post_init, |
| 216 | }; | 217 | }; |
| 217 | 218 | ||
| 219 | static struct dwc3_meson_g12a_drvdata axg_drvdata = { | ||
| 220 | .otg_switch_supported = true, | ||
| 221 | .clks = meson_gxl_clocks, | ||
| 222 | .num_clks = ARRAY_SIZE(meson_gxl_clocks), | ||
| 223 | .phy_names = meson_a1_phy_names, | ||
| 224 | .num_phys = ARRAY_SIZE(meson_a1_phy_names), | ||
| 225 | .setup_regmaps = dwc3_meson_gxl_setup_regmaps, | ||
| 226 | .usb2_init_phy = dwc3_meson_gxl_usb2_init_phy, | ||
| 227 | .set_phy_mode = dwc3_meson_gxl_set_phy_mode, | ||
| 228 | .usb_init = dwc3_meson_g12a_usb_init, | ||
| 229 | .usb_post_init = dwc3_meson_gxl_usb_post_init, | ||
| 230 | }; | ||
| 231 | |||
| 218 | static struct dwc3_meson_g12a_drvdata g12a_drvdata = { | 232 | static struct dwc3_meson_g12a_drvdata g12a_drvdata = { |
| 219 | .otg_switch_supported = true, | 233 | .otg_switch_supported = true, |
| 220 | .clks = meson_g12a_clocks, | 234 | .clks = meson_g12a_clocks, |
| @@ -520,11 +534,7 @@ static int dwc3_meson_g12a_role_set(struct usb_role_switch *sw, · 299 unmodified lines | |||
| 520 | return 0; | 534 | return 0; |
| 521 | 535 | ||
| 522 | if (priv->drvdata->otg_phy_host_port_disable) | 536 | if (priv->drvdata->otg_phy_host_port_disable) |
| 523 | dev_warn_once(priv->dev, "Manual OTG switch is broken on this "\ | 537 | dev_warn_once(priv->dev, "Broken manual OTG switch\n"); |
| 524 | "SoC, when manual switching from "\ | ||
| 525 | "Host to device, DWC3 controller "\ | ||
| 526 | "will need to be resetted in order "\ | ||
| 527 | "to recover usage of the Host port"); | ||
| 528 | 538 | ||
| 529 | return dwc3_meson_g12a_otg_mode_set(priv, mode); | 539 | return dwc3_meson_g12a_otg_mode_set(priv, mode); |
| 530 | } | 540 | } |
| @@ -626,10 +636,7 @@ static int dwc3_meson_gxl_setup_regmaps(struct dwc3_meson_g12a *priv, · 95 unmodified lines | |||
| 626 | /* GXL controls the PHY mode in the PHY registers unlike G12A */ | 636 | /* GXL controls the PHY mode in the PHY registers unlike G12A */ |
| 627 | priv->usb_glue_regmap = devm_regmap_init_mmio(priv->dev, base, | 637 | priv->usb_glue_regmap = devm_regmap_init_mmio(priv->dev, base, |
| 628 | &phy_meson_g12a_usb_glue_regmap_conf); | 638 | &phy_meson_g12a_usb_glue_regmap_conf); |
| 629 | if (IS_ERR(priv->usb_glue_regmap)) | 639 | return PTR_ERR_OR_ZERO(priv->usb_glue_regmap); |
| 630 | return PTR_ERR(priv->usb_glue_regmap); | ||
| 631 | |||
| 632 | return 0; | ||
| 633 | } | 640 | } |
| 634 | 641 | ||
| 635 | static int dwc3_meson_g12a_setup_regmaps(struct dwc3_meson_g12a *priv, | 642 | static int dwc3_meson_g12a_setup_regmaps(struct dwc3_meson_g12a *priv, |
| @@ -906,8 +913,8 @@ static int __maybe_unused dwc3_meson_g12a_resume(struct device *dev) · 270 unmodified lines | |||
| 906 | return ret; | 913 | return ret; |
| 907 | } | 914 | } |
| 908 | 915 | ||
| 909 | if (priv->vbus && priv->otg_phy_mode == PHY_MODE_USB_HOST) { | 916 | if (priv->vbus && priv->otg_phy_mode == PHY_MODE_USB_HOST) { |
| 910 | ret = regulator_enable(priv->vbus); | 917 | ret = regulator_enable(priv->vbus); |
| 911 | if (ret) | 918 | if (ret) |
| 912 | return ret; | 919 | return ret; |
| 913 | } | 920 | } |
| @@ -930,6 +937,10 @@ static const struct of_device_id dwc3_meson_g12a_match[] = { · 16 unmodified lines | |||
| 930 | .compatible = "amlogic,meson-gxm-usb-ctrl", | 937 | .compatible = "amlogic,meson-gxm-usb-ctrl", |
| 931 | .data = &gxm_drvdata, | 938 | .data = &gxm_drvdata, |
| 932 | }, | 939 | }, |
| 940 | { | ||
| 941 | .compatible = "amlogic,meson-axg-usb-ctrl", | ||
| 942 | .data = &axg_drvdata, | ||
| 943 | }, | ||
| 933 | { | 944 | { |
| 934 | .compatible = "amlogic,meson-g12a-usb-ctrl", | 945 | .compatible = "amlogic,meson-g12a-usb-ctrl", |
| 935 | .data = &g12a_drvdata, | 946 | .data = &g12a_drvdata, |
| @@ -176,6 +176,8 @@ static const struct of_device_id of_dwc3_simple_match[] = { · 175 unmodified lines | |||
| 176 | { .compatible = "cavium,octeon-7130-usb-uctl" }, | 176 | { .compatible = "cavium,octeon-7130-usb-uctl" }, |
| 177 | { .compatible = "sprd,sc9860-dwc3" }, | 177 | { .compatible = "sprd,sc9860-dwc3" }, |
| 178 | { .compatible = "allwinner,sun50i-h6-dwc3" }, | 178 | { .compatible = "allwinner,sun50i-h6-dwc3" }, |
| 179 | { .compatible = "hisilicon,hi3670-dwc3" }, | ||
| 180 | { .compatible = "intel,keembay-dwc3" }, | ||
| 179 | { /* Sentinel */ } | 181 | { /* Sentinel */ } |
| 180 | }; | 182 | }; |
| 181 | MODULE_DEVICE_TABLE(of, of_dwc3_simple_match); | 183 | MODULE_DEVICE_TABLE(of, of_dwc3_simple_match); |
| @@ -147,7 +147,8 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc) · 146 unmodified lines | |||
| 147 | 147 | ||
| 148 | if (pdev->vendor == PCI_VENDOR_ID_INTEL) { | 148 | if (pdev->vendor == PCI_VENDOR_ID_INTEL) { |
| 149 | if (pdev->device == PCI_DEVICE_ID_INTEL_BXT || | 149 | if (pdev->device == PCI_DEVICE_ID_INTEL_BXT || |
| 150 | pdev->device == PCI_DEVICE_ID_INTEL_BXT_M) { | 150 | pdev->device == PCI_DEVICE_ID_INTEL_BXT_M || |
| 151 | pdev->device == PCI_DEVICE_ID_INTEL_EHLLP) { | ||
| 151 | guid_parse(PCI_INTEL_BXT_DSM_GUID, &dwc->guid); | 152 | guid_parse(PCI_INTEL_BXT_DSM_GUID, &dwc->guid); |
| 152 | dwc->has_dsm_for_pm = true; | 153 | dwc->has_dsm_for_pm = true; |
| 153 | } | 154 | } |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | |||
| 13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
| 14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| 15 | #include <linux/extcon.h> | 15 | #include <linux/extcon.h> |
| 16 | #include <linux/interconnect.h> | ||
| 16 | #include <linux/of_platform.h> | 17 | #include <linux/of_platform.h> |
| 17 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
| 18 | #include <linux/phy/phy.h> | 19 | #include <linux/phy/phy.h> |
| @@ -43,6 +44,14 @@ · 24 unmodified lines | |||
| 43 | #define SDM845_QSCRATCH_SIZE 0x400 | 44 | #define SDM845_QSCRATCH_SIZE 0x400 |
| 44 | #define SDM845_DWC3_CORE_SIZE 0xcd00 | 45 | #define SDM845_DWC3_CORE_SIZE 0xcd00 |
| 45 | 46 | ||
| 47 | /* Interconnect path bandwidths in MBps */ | ||
| 48 | #define USB_MEMORY_AVG_HS_BW MBps_to_icc(240) | ||
| 49 | #define USB_MEMORY_PEAK_HS_BW MBps_to_icc(700) | ||
| 50 | #define USB_MEMORY_AVG_SS_BW MBps_to_icc(1000) | ||
| 51 | #define USB_MEMORY_PEAK_SS_BW MBps_to_icc(2500) | ||
| 52 | #define APPS_USB_AVG_BW 0 | ||
| 53 | #define APPS_USB_PEAK_BW MBps_to_icc(40) | ||
| 54 | |||
| 46 | struct dwc3_acpi_pdata { | 55 | struct dwc3_acpi_pdata { |
| 47 | u32 qscratch_base_offset; | 56 | u32 qscratch_base_offset; |
| 48 | u32 qscratch_base_size; | 57 | u32 qscratch_base_size; |
| @@ -76,6 +85,8 @@ struct dwc3_qcom { · 27 unmodified lines | |||
| 76 | enum usb_dr_mode mode; | 85 | enum usb_dr_mode mode; |
| 77 | bool is_suspended; | 86 | bool is_suspended; |
| 78 | bool pm_suspended; | 87 | bool pm_suspended; |
| 88 | struct icc_path *icc_path_ddr; | ||
| 89 | struct icc_path *icc_path_apps; | ||
| 79 | }; | 90 | }; |
| 80 | 91 | ||
| 81 | static inline void dwc3_qcom_setbits(void __iomem *base, u32 offset, u32 val) | 92 | static inline void dwc3_qcom_setbits(void __iomem *base, u32 offset, u32 val) |
| @@ -190,6 +201,96 @@ static int dwc3_qcom_register_extcon(struct dwc3_qcom *qcom) · 108 unmodified lines | |||
| 190 | return 0; | 201 | return 0; |
| 191 | } | 202 | } |
| 192 | 203 | ||
| 204 | static int dwc3_qcom_interconnect_enable(struct dwc3_qcom *qcom) | ||
| 205 | { | ||
| 206 | int ret; | ||
| 207 | |||
| 208 | ret = icc_enable(qcom->icc_path_ddr); | ||
| 209 | if (ret) | ||
| 210 | return ret; | ||
| 211 | |||
| 212 | ret = icc_enable(qcom->icc_path_apps); | ||
| 213 | if (ret) | ||
| 214 | icc_disable(qcom->icc_path_ddr); | ||
| 215 | |||
| 216 | return ret; | ||
| 217 | } | ||
| 218 | |||
| 219 | static int dwc3_qcom_interconnect_disable(struct dwc3_qcom *qcom) | ||
| 220 | { | ||
| 221 | int ret; | ||
| 222 | |||
| 223 | ret = icc_disable(qcom->icc_path_ddr); | ||
| 224 | if (ret) | ||
| 225 | return ret; | ||
| 226 | |||
| 227 | ret = icc_disable(qcom->icc_path_apps); | ||
| 228 | if (ret) | ||
| 229 | icc_enable(qcom->icc_path_ddr); | ||
| 230 | |||
| 231 | return ret; | ||
| 232 | } | ||
| 233 | |||
| 234 | /** | ||
| 235 | * dwc3_qcom_interconnect_init() - Get interconnect path handles | ||
| 236 | * and set bandwidhth. | ||
| 237 | * @qcom: Pointer to the concerned usb core. | ||
| 238 | * | ||
| 239 | */ | ||
| 240 | static int dwc3_qcom_interconnect_init(struct dwc3_qcom *qcom) | ||
| 241 | { | ||
| 242 | struct device *dev = qcom->dev; | ||
| 243 | int ret; | ||
| 244 | |||
| 245 | qcom->icc_path_ddr = of_icc_get(dev, "usb-ddr"); | ||
| 246 | if (IS_ERR(qcom->icc_path_ddr)) { | ||
| 247 | dev_err(dev, "failed to get usb-ddr path: %ld\n", | ||
| 248 | PTR_ERR(qcom->icc_path_ddr)); | ||
| 249 | return PTR_ERR(qcom->icc_path_ddr); | ||
| 250 | } | ||
| 251 | |||
| 252 | qcom->icc_path_apps = of_icc_get(dev, "apps-usb"); | ||
| 253 | if (IS_ERR(qcom->icc_path_apps)) { | ||
| 254 | dev_err(dev, "failed to get apps-usb path: %ld\n", | ||
| 255 | PTR_ERR(qcom->icc_path_apps)); | ||
| 256 | return PTR_ERR(qcom->icc_path_apps); | ||
| 257 | } | ||
| 258 | |||
| 259 | if (usb_get_maximum_speed(&qcom->dwc3->dev) >= USB_SPEED_SUPER || | ||
| 260 | usb_get_maximum_speed(&qcom->dwc3->dev) == USB_SPEED_UNKNOWN) | ||
| 261 | ret = icc_set_bw(qcom->icc_path_ddr, | ||
| 262 | USB_MEMORY_AVG_SS_BW, USB_MEMORY_PEAK_SS_BW); | ||
| 263 | else | ||
| 264 | ret = icc_set_bw(qcom->icc_path_ddr, | ||
| 265 | USB_MEMORY_AVG_HS_BW, USB_MEMORY_PEAK_HS_BW); | ||
| 266 | |||
| 267 | if (ret) { | ||
| 268 | dev_err(dev, "failed to set bandwidth for usb-ddr path: %d\n", ret); | ||
| 269 | return ret; | ||
| 270 | } | ||
| 271 | |||
| 272 | ret = icc_set_bw(qcom->icc_path_apps, | ||
| 273 | APPS_USB_AVG_BW, APPS_USB_PEAK_BW); | ||
| 274 | if (ret) { | ||
| 275 | dev_err(dev, "failed to set bandwidth for apps-usb path: %d\n", ret); | ||
| 276 | return ret; | ||
| 277 | } | ||
| 278 | |||
| 279 | return 0; | ||
| 280 | } | ||
| 281 | |||
| 282 | /** | ||
| 283 | * dwc3_qcom_interconnect_exit() - Release interconnect path handles | ||
| 284 | * @qcom: Pointer to the concerned usb core. | ||
| 285 | * | ||
| 286 | * This function is used to release interconnect path handle. | ||
| 287 | */ | ||
| 288 | static void dwc3_qcom_interconnect_exit(struct dwc3_qcom *qcom) | ||
| 289 | { | ||
| 290 | icc_put(qcom->icc_path_ddr); | ||
| 291 | icc_put(qcom->icc_path_apps); | ||
| 292 | } | ||
| 293 | |||
| 193 | static void dwc3_qcom_disable_interrupts(struct dwc3_qcom *qcom) | 294 | static void dwc3_qcom_disable_interrupts(struct dwc3_qcom *qcom) |
| 194 | { | 295 | { |
| 195 | if (qcom->hs_phy_irq) { | 296 | if (qcom->hs_phy_irq) { |
| @@ -239,7 +340,7 @@ static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom) · 43 unmodified lines | |||
| 239 | static int dwc3_qcom_suspend(struct dwc3_qcom *qcom) | 340 | static int dwc3_qcom_suspend(struct dwc3_qcom *qcom) |
| 240 | { | 341 | { |
| 241 | u32 val; | 342 | u32 val; |
| 242 | int i; | 343 | int i, ret; |
| 243 | 344 | ||
| 244 | if (qcom->is_suspended) | 345 | if (qcom->is_suspended) |
| 245 | return 0; | 346 | return 0; |
| @@ -251,6 +352,10 @@ static int dwc3_qcom_suspend(struct dwc3_qcom *qcom) · 5 unmodified lines | |||
| 251 | for (i = qcom->num_clocks - 1; i >= 0; i--) | 352 | for (i = qcom->num_clocks - 1; i >= 0; i--) |
| 252 | clk_disable_unprepare(qcom->clks[i]); | 353 | clk_disable_unprepare(qcom->clks[i]); |
| 253 | 354 | ||
| 355 | ret = dwc3_qcom_interconnect_disable(qcom); | ||
| 356 | if (ret) | ||
| 357 | dev_warn(qcom->dev, "failed to disable interconnect: %d\n", ret); | ||
| 358 | |||
| 254 | qcom->is_suspended = true; | 359 | qcom->is_suspended = true; |
| 255 | dwc3_qcom_enable_interrupts(qcom); | 360 | dwc3_qcom_enable_interrupts(qcom); |
| 256 | 361 | ||
| @@ -276,6 +381,10 @@ static int dwc3_qcom_resume(struct dwc3_qcom *qcom) · 19 unmodified lines | |||
| 276 | } | 381 | } |
| 277 | } | 382 | } |
| 278 | 383 | ||
| 384 | ret = dwc3_qcom_interconnect_enable(qcom); | ||
| 385 | if (ret) | ||
| 386 | dev_warn(qcom->dev, "failed to enable interconnect: %d\n", ret); | ||
| 387 | |||
| 279 | /* Clear existing events from PHY related to L2 in/out */ | 388 | /* Clear existing events from PHY related to L2 in/out */ |
| 280 | dwc3_qcom_setbits(qcom->qscratch_base, PWR_EVNT_IRQ_STAT_REG, | 389 | dwc3_qcom_setbits(qcom->qscratch_base, PWR_EVNT_IRQ_STAT_REG, |
| 281 | PWR_EVNT_LPM_IN_L2_MASK | PWR_EVNT_LPM_OUT_L2_MASK); | 390 | PWR_EVNT_LPM_IN_L2_MASK | PWR_EVNT_LPM_OUT_L2_MASK); |
| @@ -335,7 +444,9 @@ static int dwc3_qcom_setup_irq(struct platform_device *pdev) · 53 unmodified lines | |||
| 335 | { | 444 | { |
| 336 | struct dwc3_qcom *qcom = platform_get_drvdata(pdev); | 445 | struct dwc3_qcom *qcom = platform_get_drvdata(pdev); |
| 337 | const struct dwc3_acpi_pdata *pdata = qcom->acpi_pdata; | 446 | const struct dwc3_acpi_pdata *pdata = qcom->acpi_pdata; |
| 338 | int irq, ret; | 447 | int irq; |
| 448 | int ret; | ||
| 449 | |||
| 339 | irq = dwc3_qcom_get_irq(pdev, "hs_phy_irq", | 450 | irq = dwc3_qcom_get_irq(pdev, "hs_phy_irq", |
| 340 | pdata ? pdata->hs_phy_irq_index : -1); | 451 | pdata ? pdata->hs_phy_irq_index : -1); |
| 341 | if (irq > 0) { | 452 | if (irq > 0) { |
| @@ -454,7 +565,7 @@ static const struct property_entry dwc3_qcom_acpi_properties[] = { · 112 unmodified lines | |||
| 454 | 565 | ||
| 455 | static int dwc3_qcom_acpi_register_core(struct platform_device *pdev) | 566 | static int dwc3_qcom_acpi_register_core(struct platform_device *pdev) |
| 456 | { | 567 | { |
| 457 | struct dwc3_qcom *qcom = platform_get_drvdata(pdev); | 568 | struct dwc3_qcom *qcom = platform_get_drvdata(pdev); |
| 458 | struct device *dev = &pdev->dev; | 569 | struct device *dev = &pdev->dev; |
| 459 | struct resource *res, *child_res = NULL; | 570 | struct resource *res, *child_res = NULL; |
| 460 | int irq; | 571 | int irq; |
| @@ -514,7 +625,7 @@ out: · 53 unmodified lines | |||
| 514 | 625 | ||
| 515 | static int dwc3_qcom_of_register_core(struct platform_device *pdev) | 626 | static int dwc3_qcom_of_register_core(struct platform_device *pdev) |
| 516 | { | 627 | { |
| 517 | struct dwc3_qcom *qcom = platform_get_drvdata(pdev); | 628 | struct dwc3_qcom *qcom = platform_get_drvdata(pdev); |
| 518 | struct device_node *np = pdev->dev.of_node, *dwc3_np; | 629 | struct device_node *np = pdev->dev.of_node, *dwc3_np; |
| 519 | struct device *dev = &pdev->dev; | 630 | struct device *dev = &pdev->dev; |
| 520 | int ret; | 631 | int ret; |
| @@ -638,6 +749,10 @@ static int dwc3_qcom_probe(struct platform_device *pdev) · 117 unmodified lines | |||
| 638 | goto depopulate; | 749 | goto depopulate; |
| 639 | } | 750 | } |
| 640 | 751 | ||
| 752 | ret = dwc3_qcom_interconnect_init(qcom); | ||
| 753 | if (ret) | ||
| 754 | goto depopulate; | ||
| 755 | |||
| 641 | qcom->mode = usb_get_dr_mode(&qcom->dwc3->dev); | 756 | qcom->mode = usb_get_dr_mode(&qcom->dwc3->dev); |
| 642 | 757 | ||
| 643 | /* enable vbus override for device mode */ | 758 | /* enable vbus override for device mode */ |
| @@ -647,7 +762,7 @@ static int dwc3_qcom_probe(struct platform_device *pdev) · 3 unmodified lines | |||
| 647 | /* register extcon to override sw_vbus on Vbus change later */ | 762 | /* register extcon to override sw_vbus on Vbus change later */ |
| 648 | ret = dwc3_qcom_register_extcon(qcom); | 763 | ret = dwc3_qcom_register_extcon(qcom); |
| 649 | if (ret) | 764 | if (ret) |
| 650 | goto depopulate; | 765 | goto interconnect_exit; |
| 651 | 766 | ||
| 652 | device_init_wakeup(&pdev->dev, 1); | 767 | device_init_wakeup(&pdev->dev, 1); |
| 653 | qcom->is_suspended = false; | 768 | qcom->is_suspended = false; |
| @@ -657,6 +772,8 @@ static int dwc3_qcom_probe(struct platform_device *pdev) · 3 unmodified lines | |||
| 657 | 772 | ||
| 658 | return 0; | 773 | return 0; |
| 659 | 774 | ||
| 775 | interconnect_exit: | ||
| 776 | dwc3_qcom_interconnect_exit(qcom); | ||
| 660 | depopulate: | 777 | depopulate: |
| 661 | if (np) | 778 | if (np) |
| 662 | of_platform_depopulate(&pdev->dev); | 779 | of_platform_depopulate(&pdev->dev); |
| @@ -687,6 +804,7 @@ static int dwc3_qcom_remove(struct platform_device *pdev) · 24 unmodified lines | |||
| 687 | } | 804 | } |
| 688 | qcom->num_clocks = 0; | 805 | qcom->num_clocks = 0; |
| 689 | 806 | ||
| 807 | dwc3_qcom_interconnect_exit(qcom); | ||
| 690 | reset_control_assert(qcom->resets); | 808 | reset_control_assert(qcom->resets); |
| 691 | 809 | ||
| 692 | pm_runtime_allow(dev); | 810 | pm_runtime_allow(dev); |
| @@ -105,7 +105,7 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, · 104 unmodified lines | |||
| 105 | * IRQ we were waiting for is long gone. | 105 | * IRQ we were waiting for is long gone. |
| 106 | */ | 106 | */ |
| 107 | if (dep->flags & DWC3_EP_PENDING_REQUEST) { | 107 | if (dep->flags & DWC3_EP_PENDING_REQUEST) { |
| 108 | unsigned direction; | 108 | unsigned int direction; |
| 109 | 109 | ||
| 110 | direction = !!(dep->flags & DWC3_EP0_DIR_IN); | 110 | direction = !!(dep->flags & DWC3_EP0_DIR_IN); |
| 111 | 111 | ||
| @@ -127,11 +127,11 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, · 15 unmodified lines | |||
| 127 | * handle it here. | 127 | * handle it here. |
| 128 | */ | 128 | */ |
| 129 | if (dwc->delayed_status) { | 129 | if (dwc->delayed_status) { |
| 130 | unsigned direction; | 130 | unsigned int direction; |
| 131 | 131 | ||
| 132 | direction = !dwc->ep0_expect_in; | 132 | direction = !dwc->ep0_expect_in; |
| 133 | dwc->delayed_status = false; | 133 | dwc->delayed_status = false; |
| 134 | usb_gadget_set_state(&dwc->gadget, USB_STATE_CONFIGURED); | 134 | usb_gadget_set_state(dwc->gadget, USB_STATE_CONFIGURED); |
| 135 | 135 | ||
| 136 | if (dwc->ep0state == EP0_STATUS_PHASE) | 136 | if (dwc->ep0state == EP0_STATUS_PHASE) |
| 137 | __dwc3_ep0_do_control_status(dwc, dwc->eps[direction]); | 137 | __dwc3_ep0_do_control_status(dwc, dwc->eps[direction]); |
| @@ -172,7 +172,7 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, · 34 unmodified lines | |||
| 172 | * XferNotReady(STATUS). | 172 | * XferNotReady(STATUS). |
| 173 | */ | 173 | */ |
| 174 | if (dwc->three_stage_setup) { | 174 | if (dwc->three_stage_setup) { |
| 175 | unsigned direction; | 175 | unsigned int direction; |
| 176 | 176 | ||
| 177 | direction = dwc->ep0_expect_in; | 177 | direction = dwc->ep0_expect_in; |
| 178 | dwc->ep0state = EP0_DATA_PHASE; | 178 | dwc->ep0state = EP0_DATA_PHASE; |
| @@ -197,7 +197,7 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, · 18 unmodified lines | |||
| 197 | int ret; | 197 | int ret; |
| 198 | 198 | ||
| 199 | spin_lock_irqsave(&dwc->lock, flags); | 199 | spin_lock_irqsave(&dwc->lock, flags); |
| 200 | if (!dep->endpoint.desc) { | 200 | if (!dep->endpoint.desc || !dwc->pullups_connected) { |
| 201 | dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n", | 201 | dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n", |
| 202 | dep->name); | 202 | dep->name); |
| 203 | ret = -ESHUTDOWN; | 203 | ret = -ESHUTDOWN; |
| @@ -325,7 +325,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc, · 121 unmodified lines | |||
| 325 | /* | 325 | /* |
| 326 | * LTM will be set once we know how to set this in HW. | 326 | * LTM will be set once we know how to set this in HW. |
| 327 | */ | 327 | */ |
| 328 | usb_status |= dwc->gadget.is_selfpowered; | 328 | usb_status |= dwc->gadget->is_selfpowered; |
| 329 | 329 | ||
| 330 | if ((dwc->speed == DWC3_DSTS_SUPERSPEED) || | 330 | if ((dwc->speed == DWC3_DSTS_SUPERSPEED) || |
| 331 | (dwc->speed == DWC3_DSTS_SUPERSPEED_PLUS)) { | 331 | (dwc->speed == DWC3_DSTS_SUPERSPEED_PLUS)) { |
| @@ -450,7 +450,7 @@ static int dwc3_ep0_handle_device(struct dwc3 *dwc, · 118 unmodified lines | |||
| 450 | 450 | ||
| 451 | wValue = le16_to_cpu(ctrl->wValue); | 451 | wValue = le16_to_cpu(ctrl->wValue); |
| 452 | wIndex = le16_to_cpu(ctrl->wIndex); | 452 | wIndex = le16_to_cpu(ctrl->wIndex); |
| 453 | state = dwc->gadget.state; | 453 | state = dwc->gadget->state; |
| 454 | 454 | ||
| 455 | switch (wValue) { | 455 | switch (wValue) { |
| 456 | case USB_DEVICE_REMOTE_WAKEUP: | 456 | case USB_DEVICE_REMOTE_WAKEUP: |
| @@ -524,6 +524,11 @@ static int dwc3_ep0_handle_endpoint(struct dwc3 *dwc, · 67 unmodified lines | |||
| 524 | ret = __dwc3_gadget_ep_set_halt(dep, set, true); | 524 | ret = __dwc3_gadget_ep_set_halt(dep, set, true); |
| 525 | if (ret) | 525 | if (ret) |
| 526 | return -EINVAL; | 526 | return -EINVAL; |
| 527 | |||
| 528 | /* ClearFeature(Halt) may need delayed status */ | ||
| 529 | if (!set && (dep->flags & DWC3_EP_END_TRANSFER_PENDING)) | ||
| 530 | return USB_GADGET_DELAYED_STATUS; | ||
| 531 | |||
| 527 | break; | 532 | break; |
| 528 | default: | 533 | default: |
| 529 | return -EINVAL; | 534 | return -EINVAL; |
| @@ -559,7 +564,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, · 29 unmodified lines | |||
| 559 | 564 | ||
| 560 | static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) | 565 | static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) |
| 561 | { | 566 | { |
| 562 | enum usb_device_state state = dwc->gadget.state; | 567 | enum usb_device_state state = dwc->gadget->state; |
| 563 | u32 addr; | 568 | u32 addr; |
| 564 | u32 reg; | 569 | u32 reg; |
| 565 | 570 | ||
| @@ -580,9 +585,9 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) · 14 unmodified lines | |||
| 580 | dwc3_writel(dwc->regs, DWC3_DCFG, reg); | 585 | dwc3_writel(dwc->regs, DWC3_DCFG, reg); |
| 581 | 586 | ||
| 582 | if (addr) | 587 | if (addr) |
| 583 | usb_gadget_set_state(&dwc->gadget, USB_STATE_ADDRESS); | 588 | usb_gadget_set_state(dwc->gadget, USB_STATE_ADDRESS); |
| 584 | else | 589 | else |
| 585 | usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT); | 590 | usb_gadget_set_state(dwc->gadget, USB_STATE_DEFAULT); |
| 586 | 591 | ||
| 587 | return 0; | 592 | return 0; |
| 588 | } | 593 | } |
| @@ -592,14 +597,14 @@ static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) · 3 unmodified lines | |||
| 592 | int ret; | 597 | int ret; |
| 593 | 598 | ||
| 594 | spin_unlock(&dwc->lock); | 599 | spin_unlock(&dwc->lock); |
| 595 | ret = dwc->gadget_driver->setup(&dwc->gadget, ctrl); | 600 | ret = dwc->gadget_driver->setup(dwc->gadget, ctrl); |
| 596 | spin_lock(&dwc->lock); | 601 | spin_lock(&dwc->lock); |
| 597 | return ret; | 602 | return ret; |
| 598 | } | 603 | } |
| 599 | 604 | ||
| 600 | static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) | 605 | static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) |
| 601 | { | 606 | { |
| 602 | enum usb_device_state state = dwc->gadget.state; | 607 | enum usb_device_state state = dwc->gadget->state; |
| 603 | u32 cfg; | 608 | u32 cfg; |
| 604 | int ret; | 609 | int ret; |
| 605 | u32 reg; | 610 | u32 reg; |
| @@ -622,7 +627,7 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) · 16 unmodified lines | |||
| 622 | * to change the state on the next usb_ep_queue() | 627 | * to change the state on the next usb_ep_queue() |
| 623 | */ | 628 | */ |
| 624 | if (ret == 0) | 629 | if (ret == 0) |
| 625 | usb_gadget_set_state(&dwc->gadget, | 630 | usb_gadget_set_state(dwc->gadget, |
| 626 | USB_STATE_CONFIGURED); | 631 | USB_STATE_CONFIGURED); |
| 627 | 632 | ||
| 628 | /* | 633 | /* |
| @@ -641,7 +646,7 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) · 12 unmodified lines | |||
| 641 | case USB_STATE_CONFIGURED: | 646 | case USB_STATE_CONFIGURED: |
| 642 | ret = dwc3_ep0_delegate_req(dwc, ctrl); | 647 | ret = dwc3_ep0_delegate_req(dwc, ctrl); |
| 643 | if (!cfg && !ret) | 648 | if (!cfg && !ret) |
| 644 | usb_gadget_set_state(&dwc->gadget, | 649 | usb_gadget_set_state(dwc->gadget, |
| 645 | USB_STATE_ADDRESS); | 650 | USB_STATE_ADDRESS); |
| 646 | break; | 651 | break; |
| 647 | default: | 652 | default: |
| @@ -697,7 +702,7 @@ static void dwc3_ep0_set_sel_cmpl(struct usb_ep *ep, struct usb_request *req) · 49 unmodified lines | |||
| 697 | static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) | 702 | static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) |
| 698 | { | 703 | { |
| 699 | struct dwc3_ep *dep; | 704 | struct dwc3_ep *dep; |
| 700 | enum usb_device_state state = dwc->gadget.state; | 705 | enum usb_device_state state = dwc->gadget->state; |
| 701 | u16 wLength; | 706 | u16 wLength; |
| 702 | 707 | ||
| 703 | if (state == USB_STATE_DEFAULT) | 708 | if (state == USB_STATE_DEFAULT) |
| @@ -741,7 +746,7 @@ static int dwc3_ep0_set_isoch_delay(struct dwc3 *dwc, struct usb_ctrlrequest *ct · 37 unmodified lines | |||
| 741 | if (wIndex || wLength) | 746 | if (wIndex || wLength) |
| 742 | return -EINVAL; | 747 | return -EINVAL; |
| 743 | 748 | ||
| 744 | dwc->gadget.isoch_delay = wValue; | 749 | dwc->gadget->isoch_delay = wValue; |
| 745 | 750 | ||
| 746 | return 0; | 751 | return 0; |
| 747 | } | 752 | } |
| @@ -942,12 +947,16 @@ static void dwc3_ep0_xfer_complete(struct dwc3 *dwc, · 194 unmodified lines | |||
| 942 | static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, | 947 | static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, |
| 943 | struct dwc3_ep *dep, struct dwc3_request *req) | 948 | struct dwc3_ep *dep, struct dwc3_request *req) |
| 944 | { | 949 | { |
| 950 | unsigned int trb_length = 0; | ||
| 945 | int ret; | 951 | int ret; |
| 946 | 952 | ||
| 947 | req->direction = !!dep->number; | 953 | req->direction = !!dep->number; |
| 948 | 954 | ||
| 949 | if (req->request.length == 0) { | 955 | if (req->request.length == 0) { |
| 950 | dwc3_ep0_prepare_one_trb(dep, dwc->ep0_trb_addr, 0, | 956 | if (!req->direction) |
| 957 | trb_length = dep->endpoint.maxpacket; | ||
| 958 | |||
| 959 | dwc3_ep0_prepare_one_trb(dep, dwc->bounce_addr, trb_length, | ||
| 951 | DWC3_TRBCTL_CONTROL_DATA, false); | 960 | DWC3_TRBCTL_CONTROL_DATA, false); |
| 952 | ret = dwc3_ep0_start_trans(dep); | 961 | ret = dwc3_ep0_start_trans(dep); |
| 953 | } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket) | 962 | } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket) |
| @@ -994,9 +1003,12 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, · 40 unmodified lines | |||
| 994 | 1003 | ||
| 995 | req->trb = &dwc->ep0_trb[dep->trb_enqueue - 1]; | 1004 | req->trb = &dwc->ep0_trb[dep->trb_enqueue - 1]; |
| 996 | 1005 | ||
| 1006 | if (!req->direction) | ||
| 1007 | trb_length = dep->endpoint.maxpacket; | ||
| 1008 | |||
| 997 | /* Now prepare one extra TRB to align transfer size */ | 1009 | /* Now prepare one extra TRB to align transfer size */ |
| 998 | dwc3_ep0_prepare_one_trb(dep, dwc->bounce_addr, | 1010 | dwc3_ep0_prepare_one_trb(dep, dwc->bounce_addr, |
| 999 | 0, DWC3_TRBCTL_CONTROL_DATA, | 1011 | trb_length, DWC3_TRBCTL_CONTROL_DATA, |
| 1000 | false); | 1012 | false); |
| 1001 | ret = dwc3_ep0_start_trans(dep); | 1013 | ret = dwc3_ep0_start_trans(dep); |
| 1002 | } else { | 1014 | } else { |
| @@ -1042,6 +1054,17 @@ static void dwc3_ep0_do_control_status(struct dwc3 *dwc, · 39 unmodified lines | |||
| 1042 | __dwc3_ep0_do_control_status(dwc, dep); | 1054 | __dwc3_ep0_do_control_status(dwc, dep); |
| 1043 | } | 1055 | } |
| 1044 | 1056 | ||
| 1057 | void dwc3_ep0_send_delayed_status(struct dwc3 *dwc) | ||
| 1058 | { | ||
| 1059 | unsigned int direction = !dwc->ep0_expect_in; | ||
| 1060 | |||
| 1061 | if (dwc->ep0state != EP0_STATUS_PHASE) | ||
| 1062 | return; | ||
| 1063 | |||
| 1064 | dwc->delayed_status = false; | ||
| 1065 | __dwc3_ep0_do_control_status(dwc, dwc->eps[direction]); | ||
| 1066 | } | ||
| 1067 | |||
| 1045 | static void dwc3_ep0_end_control_data(struct dwc3 *dwc, struct dwc3_ep *dep) | 1068 | static void dwc3_ep0_end_control_data(struct dwc3 *dwc, struct dwc3_ep *dep) |
| 1046 | { | 1069 | { |
| 1047 | struct dwc3_gadget_ep_cmd_params params; | 1070 | struct dwc3_gadget_ep_cmd_params params; |
| @@ -1102,7 +1125,7 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc, · 54 unmodified lines | |||
| 1102 | */ | 1125 | */ |
| 1103 | if (!list_empty(&dep->pending_list)) { | 1126 | if (!list_empty(&dep->pending_list)) { |
| 1104 | dwc->delayed_status = false; | 1127 | dwc->delayed_status = false; |
| 1105 | usb_gadget_set_state(&dwc->gadget, | 1128 | usb_gadget_set_state(dwc->gadget, |
| 1106 | USB_STATE_CONFIGURED); | 1129 | USB_STATE_CONFIGURED); |
| 1107 | dwc3_ep0_do_control_status(dwc, event); | 1130 | dwc3_ep0_do_control_status(dwc, event); |
| 1108 | } | 1131 | } |
| @@ -227,7 +227,8 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, · 226 unmodified lines | |||
| 227 | * Caller should take care of locking. Issue @cmd with a given @param to @dwc | 227 | * Caller should take care of locking. Issue @cmd with a given @param to @dwc |
| 228 | * and wait for its completion. | 228 | * and wait for its completion. |
| 229 | */ | 229 | */ |
| 230 | int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned cmd, u32 param) | 230 | int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned int cmd, |
| 231 | u32 param) | ||
| 231 | { | 232 | { |
| 232 | u32 timeout = 500; | 233 | u32 timeout = 500; |
| 233 | int status = 0; | 234 | int status = 0; |
| @@ -268,7 +269,7 @@ static int __dwc3_gadget_wakeup(struct dwc3 *dwc); · 34 unmodified lines | |||
| 268 | * Caller should handle locking. This function will issue @cmd with given | 269 | * Caller should handle locking. This function will issue @cmd with given |
| 269 | * @params to @dep and wait for its completion. | 270 | * @params to @dep and wait for its completion. |
| 270 | */ | 271 | */ |
| 271 | int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd, | 272 | int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd, |
| 272 | struct dwc3_gadget_ep_cmd_params *params) | 273 | struct dwc3_gadget_ep_cmd_params *params) |
| 273 | { | 274 | { |
| 274 | const struct usb_endpoint_descriptor *desc = dep->endpoint.desc; | 275 | const struct usb_endpoint_descriptor *desc = dep->endpoint.desc; |
| @@ -290,7 +291,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd, · 15 unmodified lines | |||
| 290 | * | 291 | * |
| 291 | * DWC_usb3 3.30a and DWC_usb31 1.90a programming guide section 3.2.2 | 292 | * DWC_usb3 3.30a and DWC_usb31 1.90a programming guide section 3.2.2 |
| 292 | */ | 293 | */ |
| 293 | if (dwc->gadget.speed <= USB_SPEED_HIGH) { | 294 | if (dwc->gadget->speed <= USB_SPEED_HIGH) { |
| 294 | reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); | 295 | reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); |
| 295 | if (unlikely(reg & DWC3_GUSB2PHYCFG_SUSPHY)) { | 296 | if (unlikely(reg & DWC3_GUSB2PHYCFG_SUSPHY)) { |
| 296 | saved_config |= DWC3_GUSB2PHYCFG_SUSPHY; | 297 | saved_config |= DWC3_GUSB2PHYCFG_SUSPHY; |
| @@ -422,7 +423,7 @@ static int dwc3_send_clear_stall_ep_cmd(struct dwc3_ep *dep) · 125 unmodified lines | |||
| 422 | */ | 423 | */ |
| 423 | if (dep->direction && | 424 | if (dep->direction && |
| 424 | !DWC3_VER_IS_PRIOR(DWC3, 260A) && | 425 | !DWC3_VER_IS_PRIOR(DWC3, 260A) && |
| 425 | (dwc->gadget.speed >= USB_SPEED_SUPER)) | 426 | (dwc->gadget->speed >= USB_SPEED_SUPER)) |
| 426 | cmd |= DWC3_DEPCMD_CLEARPENDIN; | 427 | cmd |= DWC3_DEPCMD_CLEARPENDIN; |
| 427 | 428 | ||
| 428 | memset(¶ms, 0, sizeof(params)); | 429 | memset(¶ms, 0, sizeof(params)); |
| @@ -562,8 +563,9 @@ static int dwc3_gadget_set_ep_config(struct dwc3_ep *dep, unsigned int action) · 133 unmodified lines | |||
| 562 | | DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc)); | 563 | | DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc)); |
| 563 | 564 | ||
| 564 | /* Burst size is only needed in SuperSpeed mode */ | 565 | /* Burst size is only needed in SuperSpeed mode */ |
| 565 | if (dwc->gadget.speed >= USB_SPEED_SUPER) { | 566 | if (dwc->gadget->speed >= USB_SPEED_SUPER) { |
| 566 | u32 burst = dep->endpoint.maxburst; | 567 | u32 burst = dep->endpoint.maxburst; |
| 568 | |||
| 567 | params.param0 |= DWC3_DEPCFG_BURST_SIZE(burst - 1); | 569 | params.param0 |= DWC3_DEPCFG_BURST_SIZE(burst - 1); |
| 568 | } | 570 | } |
| 569 | 571 | ||
| @@ -942,12 +944,13 @@ static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep) · 372 unmodified lines | |||
| 942 | } | 944 | } |
| 943 | 945 | ||
| 944 | static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb, | 946 | static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb, |
| 945 | dma_addr_t dma, unsigned length, unsigned chain, unsigned node, | 947 | dma_addr_t dma, unsigned int length, unsigned int chain, |
| 946 | unsigned stream_id, unsigned short_not_ok, | 948 | unsigned int node, unsigned int stream_id, |
| 947 | unsigned no_interrupt, unsigned is_last) | 949 | unsigned int short_not_ok, unsigned int no_interrupt, |
| 950 | unsigned int is_last, bool must_interrupt) | ||
| 948 | { | 951 | { |
| 949 | struct dwc3 *dwc = dep->dwc; | 952 | struct dwc3 *dwc = dep->dwc; |
| 950 | struct usb_gadget *gadget = &dwc->gadget; | 953 | struct usb_gadget *gadget = dwc->gadget; |
| 951 | enum usb_device_speed speed = gadget->speed; | 954 | enum usb_device_speed speed = gadget->speed; |
| 952 | 955 | ||
| 953 | trb->size = DWC3_TRB_SIZE_LENGTH(length); | 956 | trb->size = DWC3_TRB_SIZE_LENGTH(length); |
| @@ -1031,8 +1034,7 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb, · 77 unmodified lines | |||
| 1031 | trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; | 1034 | trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; |
| 1032 | } | 1035 | } |
| 1033 | 1036 | ||
| 1034 | if ((!no_interrupt && !chain) || | 1037 | if ((!no_interrupt && !chain) || must_interrupt) |
| 1035 | (dwc3_calc_trbs_left(dep) == 1)) | ||
| 1036 | trb->ctrl |= DWC3_TRB_CTRL_IOC; | 1038 | trb->ctrl |= DWC3_TRB_CTRL_IOC; |
| 1037 | 1039 | ||
| 1038 | if (chain) | 1040 | if (chain) |
| @@ -1057,19 +1059,24 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb, · 18 unmodified lines | |||
| 1057 | * @trb_length: buffer size of the TRB | 1059 | * @trb_length: buffer size of the TRB |
| 1058 | * @chain: should this TRB be chained to the next? | 1060 | * @chain: should this TRB be chained to the next? |
| 1059 | * @node: only for isochronous endpoints. First TRB needs different type. | 1061 | * @node: only for isochronous endpoints. First TRB needs different type. |
| 1062 | * @use_bounce_buffer: set to use bounce buffer | ||
| 1063 | * @must_interrupt: set to interrupt on TRB completion | ||
| 1060 | */ | 1064 | */ |
| 1061 | static void dwc3_prepare_one_trb(struct dwc3_ep *dep, | 1065 | static void dwc3_prepare_one_trb(struct dwc3_ep *dep, |
| 1062 | struct dwc3_request *req, unsigned int trb_length, | 1066 | struct dwc3_request *req, unsigned int trb_length, |
| 1063 | unsigned chain, unsigned node) | 1067 | unsigned int chain, unsigned int node, bool use_bounce_buffer, |
| 1068 | bool must_interrupt) | ||
| 1064 | { | 1069 | { |
| 1065 | struct dwc3_trb *trb; | 1070 | struct dwc3_trb *trb; |
| 1066 | dma_addr_t dma; | 1071 | dma_addr_t dma; |
| 1067 | unsigned stream_id = req->request.stream_id; | 1072 | unsigned int stream_id = req->request.stream_id; |
| 1068 | unsigned short_not_ok = req->request.short_not_ok; | 1073 | unsigned int short_not_ok = req->request.short_not_ok; |
| 1069 | unsigned no_interrupt = req->request.no_interrupt; | 1074 | unsigned int no_interrupt = req->request.no_interrupt; |
| 1070 | unsigned is_last = req->request.is_last; | 1075 | unsigned int is_last = req->request.is_last; |
| 1071 | 1076 | ||
| 1072 | if (req->request.num_sgs > 0) | 1077 | if (use_bounce_buffer) |
| 1078 | dma = dep->dwc->bounce_addr; | ||
| 1079 | else if (req->request.num_sgs > 0) | ||
| 1073 | dma = sg_dma_address(req->start_sg); | 1080 | dma = sg_dma_address(req->start_sg); |
| 1074 | else | 1081 | else |
| 1075 | dma = req->request.dma; | 1082 | dma = req->request.dma; |
| @@ -1085,10 +1092,63 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, · 9 unmodified lines | |||
| 1085 | req->num_trbs++; | 1092 | req->num_trbs++; |
| 1086 | 1093 | ||
| 1087 | __dwc3_prepare_one_trb(dep, trb, dma, trb_length, chain, node, | 1094 | __dwc3_prepare_one_trb(dep, trb, dma, trb_length, chain, node, |
| 1088 | stream_id, short_not_ok, no_interrupt, is_last); | 1095 | stream_id, short_not_ok, no_interrupt, is_last, |
| 1096 | must_interrupt); | ||
| 1089 | } | 1097 | } |
| 1090 | 1098 | ||
| 1091 | static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, | 1099 | static bool dwc3_needs_extra_trb(struct dwc3_ep *dep, struct dwc3_request *req) |
| 1100 | { | ||
| 1101 | unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); | ||
| 1102 | unsigned int rem = req->request.length % maxp; | ||
| 1103 | |||
| 1104 | if ((req->request.length && req->request.zero && !rem && | ||
| 1105 | !usb_endpoint_xfer_isoc(dep->endpoint.desc)) || | ||
| 1106 | (!req->direction && rem)) | ||
| 1107 | return true; | ||
| 1108 | |||
| 1109 | return false; | ||
| 1110 | } | ||
| 1111 | |||
| 1112 | /** | ||
| 1113 | * dwc3_prepare_last_sg - prepare TRBs for the last SG entry | ||
| 1114 | * @dep: The endpoint that the request belongs to | ||
| 1115 | * @req: The request to prepare | ||
| 1116 | * @entry_length: The last SG entry size | ||
| 1117 | * @node: Indicates whether this is not the first entry (for isoc only) | ||
| 1118 | * | ||
| 1119 | * Return the number of TRBs prepared. | ||
| 1120 | */ | ||
| 1121 | static int dwc3_prepare_last_sg(struct dwc3_ep *dep, | ||
| 1122 | struct dwc3_request *req, unsigned int entry_length, | ||
| 1123 | unsigned int node) | ||
| 1124 | { | ||
| 1125 | unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); | ||
| 1126 | unsigned int rem = req->request.length % maxp; | ||
| 1127 | unsigned int num_trbs = 1; | ||
| 1128 | |||
| 1129 | if (dwc3_needs_extra_trb(dep, req)) | ||
| 1130 | num_trbs++; | ||
| 1131 | |||
| 1132 | if (dwc3_calc_trbs_left(dep) < num_trbs) | ||
| 1133 | return 0; | ||
| 1134 | |||
| 1135 | req->needs_extra_trb = num_trbs > 1; | ||
| 1136 | |||
| 1137 | /* Prepare a normal TRB */ | ||
| 1138 | if (req->direction || req->request.length) | ||
| 1139 | dwc3_prepare_one_trb(dep, req, entry_length, | ||
| 1140 | req->needs_extra_trb, node, false, false); | ||
| 1141 | |||
| 1142 | /* Prepare extra TRBs for ZLP and MPS OUT transfer alignment */ | ||
| 1143 | if ((!req->direction && !req->request.length) || req->needs_extra_trb) | ||
| 1144 | dwc3_prepare_one_trb(dep, req, | ||
| 1145 | req->direction ? 0 : maxp - rem, | ||
| 1146 | false, 1, true, false); | ||
| 1147 | |||
| 1148 | return num_trbs; | ||
| 1149 | } | ||
| 1150 | |||
| 1151 | static int dwc3_prepare_trbs_sg(struct dwc3_ep *dep, | ||
| 1092 | struct dwc3_request *req) | 1152 | struct dwc3_request *req) |
| 1093 | { | 1153 | { |
| 1094 | struct scatterlist *sg = req->start_sg; | 1154 | struct scatterlist *sg = req->start_sg; |
| @@ -1097,6 +1157,8 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, · 2 unmodified lines | |||
| 1097 | unsigned int length = req->request.length; | 1157 | unsigned int length = req->request.length; |
| 1098 | unsigned int remaining = req->request.num_mapped_sgs | 1158 | unsigned int remaining = req->request.num_mapped_sgs |
| 1099 | - req->num_queued_sgs; | 1159 | - req->num_queued_sgs; |
| 1160 | unsigned int num_trbs = req->num_trbs; | ||
| 1161 | bool needs_extra_trb = dwc3_needs_extra_trb(dep, req); | ||
| 1100 | 1162 | ||
| 1101 | /* | 1163 | /* |
| 1102 | * If we resume preparing the request, then get the remaining length of | 1164 | * If we resume preparing the request, then get the remaining length of |
| @@ -1106,10 +1168,10 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, · 3 unmodified lines | |||
| 1106 | length -= sg_dma_len(s); | 1168 | length -= sg_dma_len(s); |
| 1107 | 1169 | ||
| 1108 | for_each_sg(sg, s, remaining, i) { | 1170 | for_each_sg(sg, s, remaining, i) { |
| 1109 | unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); | 1171 | unsigned int num_trbs_left = dwc3_calc_trbs_left(dep); |
| 1110 | unsigned int rem = length % maxp; | ||
| 1111 | unsigned int trb_length; | 1172 | unsigned int trb_length; |
| 1112 | unsigned chain = true; | 1173 | bool must_interrupt = false; |
| 1174 | bool last_sg = false; | ||
| 1113 | 1175 | ||
| 1114 | trb_length = min_t(unsigned int, length, sg_dma_len(s)); | 1176 | trb_length = min_t(unsigned int, length, sg_dma_len(s)); |
| 1115 | 1177 | ||
| @@ -1123,59 +1185,28 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, · 7 unmodified lines | |||
| 1123 | * mapped sg. | 1185 | * mapped sg. |
| 1124 | */ | 1186 | */ |
| 1125 | if ((i == remaining - 1) || !length) | 1187 | if ((i == remaining - 1) || !length) |
| 1126 | chain = false; | 1188 | last_sg = true; |
| 1127 | 1189 | ||
| 1128 | if (rem && usb_endpoint_dir_out(dep->endpoint.desc) && !chain) { | 1190 | if (!num_trbs_left) |
| 1129 | struct dwc3 *dwc = dep->dwc; | 1191 | break; |
| 1130 | struct dwc3_trb *trb; | 1192 | |
| 1131 | 1193 | if (last_sg) { | |
| 1132 | req->needs_extra_trb = true; | 1194 | if (!dwc3_prepare_last_sg(dep, req, trb_length, i)) |
| 1133 | 1195 | break; | |
| 1134 | /* prepare normal TRB */ | ||
| 1135 | dwc3_prepare_one_trb(dep, req, trb_length, true, i); | ||
| 1136 | |||
| 1137 | /* Now prepare one extra TRB to align transfer size */ | ||
| 1138 | trb = &dep->trb_pool[dep->trb_enqueue]; | ||
| 1139 | req->num_trbs++; | ||
| 1140 | __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, | ||
| 1141 | maxp - rem, false, 1, | ||
| 1142 | req->request.stream_id, | ||
| 1143 | req->request.short_not_ok, | ||
| 1144 | req->request.no_interrupt, | ||
| 1145 | req->request.is_last); | ||
| 1146 | } else if (req->request.zero && req->request.length && | ||
| 1147 | !usb_endpoint_xfer_isoc(dep->endpoint.desc) && | ||
| 1148 | !rem && !chain) { | ||
| 1149 | struct dwc3 *dwc = dep->dwc; | ||
| 1150 | struct dwc3_trb *trb; | ||
| 1151 | |||
| 1152 | req->needs_extra_trb = true; | ||
| 1153 | |||
| 1154 | /* Prepare normal TRB */ | ||
| 1155 | dwc3_prepare_one_trb(dep, req, trb_length, true, i); | ||
| 1156 | |||
| 1157 | /* Prepare one extra TRB to handle ZLP */ | ||
| 1158 | trb = &dep->trb_pool[dep->trb_enqueue]; | ||
| 1159 | req->num_trbs++; | ||
| 1160 | __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0, | ||
| 1161 | !req->direction, 1, | ||
| 1162 | req->request.stream_id, | ||
| 1163 | req->request.short_not_ok, | ||
| 1164 | req->request.no_interrupt, | ||
| 1165 | req->request.is_last); | ||
| 1166 | |||
| 1167 | /* Prepare one more TRB to handle MPS alignment */ | ||
| 1168 | if (!req->direction) { | ||
| 1169 | trb = &dep->trb_pool[dep->trb_enqueue]; | ||
| 1170 | req->num_trbs++; | ||
| 1171 | __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp, | ||
| 1172 | false, 1, req->request.stream_id, | ||
| 1173 | req->request.short_not_ok, | ||
| 1174 | req->request.no_interrupt, | ||
| 1175 | req->request.is_last); | ||
| 1176 | } | ||
| 1177 | } else { | 1196 | } else { |
| 1178 | dwc3_prepare_one_trb(dep, req, trb_length, chain, i); | 1197 | /* |
| 1198 | * Look ahead to check if we have enough TRBs for the | ||
| 1199 | * next SG entry. If not, set interrupt on this TRB to | ||
| 1200 | * resume preparing the next SG entry when more TRBs are | ||
| 1201 | * free. | ||
| 1202 | */ | ||
| 1203 | if (num_trbs_left == 1 || (needs_extra_trb && | ||
| 1204 | num_trbs_left <= 2 && | ||
| 1205 | sg_dma_len(sg_next(s)) >= length)) | ||
| 1206 | must_interrupt = true; | ||
| 1207 | |||
| 1208 | dwc3_prepare_one_trb(dep, req, trb_length, 1, i, false, | ||
| 1209 | must_interrupt); | ||
| 1179 | } | 1210 | } |
| 1180 | 1211 | ||
| 1181 | /* | 1212 | /* |
| @@ -1185,7 +1216,7 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, · 3 unmodified lines | |||
| 1185 | * we have free trbs we can continue queuing from where we | 1216 | * we have free trbs we can continue queuing from where we |
| 1186 | * previously stopped | 1217 | * previously stopped |
| 1187 | */ | 1218 | */ |
| 1188 | if (chain) | 1219 | if (!last_sg) |
| 1189 | req->start_sg = sg_next(s); | 1220 | req->start_sg = sg_next(s); |
| 1190 | 1221 | ||
| 1191 | req->num_queued_sgs++; | 1222 | req->num_queued_sgs++; |
| @@ -1200,68 +1231,17 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, · 8 unmodified lines | |||
| 1200 | break; | 1231 | break; |
| 1201 | } | 1232 | } |
| 1202 | 1233 | ||
| 1203 | if (!dwc3_calc_trbs_left(dep)) | 1234 | if (must_interrupt) |
| 1204 | break; | 1235 | break; |
| 1205 | } | 1236 | } |
| 1237 | |||
| 1238 | return req->num_trbs - num_trbs; | ||
| 1206 | } | 1239 | } |
| 1207 | 1240 | ||
| 1208 | static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, | 1241 | static int dwc3_prepare_trbs_linear(struct dwc3_ep *dep, |
| 1209 | struct dwc3_request *req) | 1242 | struct dwc3_request *req) |
| 1210 | { | 1243 | { |
| 1211 | unsigned int length = req->request.length; | 1244 | return dwc3_prepare_last_sg(dep, req, req->request.length, 0); |
| 1212 | unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); | ||
| 1213 | unsigned int rem = length % maxp; | ||
| 1214 | |||
| 1215 | if ((!length || rem) && usb_endpoint_dir_out(dep->endpoint.desc)) { | ||
| 1216 | struct dwc3 *dwc = dep->dwc; | ||
| 1217 | struct dwc3_trb *trb; | ||
| 1218 | |||
| 1219 | req->needs_extra_trb = true; | ||
| 1220 | |||
| 1221 | /* prepare normal TRB */ | ||
| 1222 | dwc3_prepare_one_trb(dep, req, length, true, 0); | ||
| 1223 | |||
| 1224 | /* Now prepare one extra TRB to align transfer size */ | ||
| 1225 | trb = &dep->trb_pool[dep->trb_enqueue]; | ||
| 1226 | req->num_trbs++; | ||
| 1227 | __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp - rem, | ||
| 1228 | false, 1, req->request.stream_id, | ||
| 1229 | req->request.short_not_ok, | ||
| 1230 | req->request.no_interrupt, | ||
| 1231 | req->request.is_last); | ||
| 1232 | } else if (req->request.zero && req->request.length && | ||
| 1233 | !usb_endpoint_xfer_isoc(dep->endpoint.desc) && | ||
| 1234 | (IS_ALIGNED(req->request.length, maxp))) { | ||
| 1235 | struct dwc3 *dwc = dep->dwc; | ||
| 1236 | struct dwc3_trb *trb; | ||
| 1237 | |||
| 1238 | req->needs_extra_trb = true; | ||
| 1239 | |||
| 1240 | /* prepare normal TRB */ | ||
| 1241 | dwc3_prepare_one_trb(dep, req, length, true, 0); | ||
| 1242 | |||
| 1243 | /* Prepare one extra TRB to handle ZLP */ | ||
| 1244 | trb = &dep->trb_pool[dep->trb_enqueue]; | ||
| 1245 | req->num_trbs++; | ||
| 1246 | __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0, | ||
| 1247 | !req->direction, 1, req->request.stream_id, | ||
| 1248 | req->request.short_not_ok, | ||
| 1249 | req->request.no_interrupt, | ||
| 1250 | req->request.is_last); | ||
| 1251 | |||
| 1252 | /* Prepare one more TRB to handle MPS alignment for OUT */ | ||
| 1253 | if (!req->direction) { | ||
| 1254 | trb = &dep->trb_pool[dep->trb_enqueue]; | ||
| 1255 | req->num_trbs++; | ||
| 1256 | __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp, | ||
| 1257 | false, 1, req->request.stream_id, | ||
| 1258 | req->request.short_not_ok, | ||
| 1259 | req->request.no_interrupt, | ||
| 1260 | req->request.is_last); | ||
| 1261 | } | ||
| 1262 | } else { | ||
| 1263 | dwc3_prepare_one_trb(dep, req, length, false, 0); | ||
| 1264 | } | ||
| 1265 | } | 1245 | } |
| 1266 | 1246 | ||
| 1267 | /* | 1247 | /* |
| @@ -1271,10 +1251,13 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, · 3 unmodified lines | |||
| 1271 | * The function goes through the requests list and sets up TRBs for the | 1251 | * The function goes through the requests list and sets up TRBs for the |
| 1272 | * transfers. The function returns once there are no more TRBs available or | 1252 | * transfers. The function returns once there are no more TRBs available or |
| 1273 | * it runs out of requests. | 1253 | * it runs out of requests. |
| 1254 | * | ||
| 1255 | * Returns the number of TRBs prepared or negative errno. | ||
| 1274 | */ | 1256 | */ |
| 1275 | static void dwc3_prepare_trbs(struct dwc3_ep *dep) | 1257 | static int dwc3_prepare_trbs(struct dwc3_ep *dep) |
| 1276 | { | 1258 | { |
| 1277 | struct dwc3_request *req, *n; | 1259 | struct dwc3_request *req, *n; |
| 1260 | int ret = 0; | ||
| 1278 | 1261 | ||
| 1279 | BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM); | 1262 | BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM); |
| 1280 | 1263 | ||
| @@ -1289,11 +1272,14 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep) · 8 unmodified lines | |||
| 1289 | * break things. | 1272 | * break things. |
| 1290 | */ | 1273 | */ |
| 1291 | list_for_each_entry(req, &dep->started_list, list) { | 1274 | list_for_each_entry(req, &dep->started_list, list) { |
| 1292 | if (req->num_pending_sgs > 0) | 1275 | if (req->num_pending_sgs > 0) { |
| 1293 | dwc3_prepare_one_trb_sg(dep, req); | 1276 | ret = dwc3_prepare_trbs_sg(dep, req); |
| 1277 | if (!ret || req->num_pending_sgs) | ||
| 1278 | return ret; | ||
| 1279 | } | ||
| 1294 | 1280 | ||
| 1295 | if (!dwc3_calc_trbs_left(dep)) | 1281 | if (!dwc3_calc_trbs_left(dep)) |
| 1296 | return; | 1282 | return ret; |
| 1297 | 1283 | ||
| 1298 | /* | 1284 | /* |
| 1299 | * Don't prepare beyond a transfer. In DWC_usb32, its transfer | 1285 | * Don't prepare beyond a transfer. In DWC_usb32, its transfer |
| @@ -1301,30 +1287,32 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep) · 1 unmodified line | |||
| 1301 | * active transfer instead of stopping. | 1287 | * active transfer instead of stopping. |
| 1302 | */ | 1288 | */ |
| 1303 | if (dep->stream_capable && req->request.is_last) | 1289 | if (dep->stream_capable && req->request.is_last) |
| 1304 | return; | 1290 | return ret; |
| 1305 | } | 1291 | } |
| 1306 | 1292 | ||
| 1307 | list_for_each_entry_safe(req, n, &dep->pending_list, list) { | 1293 | list_for_each_entry_safe(req, n, &dep->pending_list, list) { |
| 1308 | struct dwc3 *dwc = dep->dwc; | 1294 | struct dwc3 *dwc = dep->dwc; |
| 1309 | int ret; | ||
| 1310 | 1295 | ||
| 1311 | ret = usb_gadget_map_request_by_dev(dwc->sysdev, &req->request, | 1296 | ret = usb_gadget_map_request_by_dev(dwc->sysdev, &req->request, |
| 1312 | dep->direction); | 1297 | dep->direction); |
| 1313 | if (ret) | 1298 | if (ret) |
| 1314 | return; | 1299 | return ret; |
| 1315 | 1300 | ||
| 1316 | req->sg = req->request.sg; | 1301 | req->sg = req->request.sg; |
| 1317 | req->start_sg = req->sg; | 1302 | req->start_sg = req->sg; |
| 1318 | req->num_queued_sgs = 0; | 1303 | req->num_queued_sgs = 0; |
| 1319 | req->num_pending_sgs = req->request.num_mapped_sgs; | 1304 | req->num_pending_sgs = req->request.num_mapped_sgs; |
| 1320 | 1305 | ||
| 1321 | if (req->num_pending_sgs > 0) | 1306 | if (req->num_pending_sgs > 0) { |
| 1322 | dwc3_prepare_one_trb_sg(dep, req); | 1307 | ret = dwc3_prepare_trbs_sg(dep, req); |
| 1323 | else | 1308 | if (req->num_pending_sgs) |
| 1324 | dwc3_prepare_one_trb_linear(dep, req); | 1309 | return ret; |
| 1310 | } else { | ||
| 1311 | ret = dwc3_prepare_trbs_linear(dep, req); | ||
| 1312 | } | ||
| 1325 | 1313 | ||
| 1326 | if (!dwc3_calc_trbs_left(dep)) | 1314 | if (!ret || !dwc3_calc_trbs_left(dep)) |
| 1327 | return; | 1315 | return ret; |
| 1328 | 1316 | ||
| 1329 | /* | 1317 | /* |
| 1330 | * Don't prepare beyond a transfer. In DWC_usb32, its transfer | 1318 | * Don't prepare beyond a transfer. In DWC_usb32, its transfer |
| @@ -1332,8 +1320,10 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep) · 1 unmodified line | |||
| 1332 | * active transfer instead of stopping. | 1320 | * active transfer instead of stopping. |
| 1333 | */ | 1321 | */ |
| 1334 | if (dep->stream_capable && req->request.is_last) | 1322 | if (dep->stream_capable && req->request.is_last) |
| 1335 | return; | 1323 | return ret; |
| 1336 | } | 1324 | } |
| 1325 | |||
| 1326 | return ret; | ||
| 1337 | } | 1327 | } |
| 1338 | 1328 | ||
| 1339 | static void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep); | 1329 | static void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep); |
| @@ -1346,12 +1336,24 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep) · 6 unmodified lines | |||
| 1346 | int ret; | 1336 | int ret; |
| 1347 | u32 cmd; | 1337 | u32 cmd; |
| 1348 | 1338 | ||
| 1349 | if (!dwc3_calc_trbs_left(dep)) | 1339 | /* |
| 1350 | return 0; | 1340 | * Note that it's normal to have no new TRBs prepared (i.e. ret == 0). |
| 1341 | * This happens when we need to stop and restart a transfer such as in | ||
| 1342 | * the case of reinitiating a stream or retrying an isoc transfer. | ||
| 1343 | */ | ||
| 1344 | ret = dwc3_prepare_trbs(dep); | ||
| 1345 | if (ret < 0) | ||
| 1346 | return ret; | ||
| 1351 | 1347 | ||
| 1352 | starting = !(dep->flags & DWC3_EP_TRANSFER_STARTED); | 1348 | starting = !(dep->flags & DWC3_EP_TRANSFER_STARTED); |
| 1353 | 1349 | ||
| 1354 | dwc3_prepare_trbs(dep); | 1350 | /* |
| 1351 | * If there's no new TRB prepared and we don't need to restart a | ||
| 1352 | * transfer, there's no need to update the transfer. | ||
| 1353 | */ | ||
| 1354 | if (!ret && !starting) | ||
| 1355 | return ret; | ||
| 1356 | |||
| 1355 | req = next_request(&dep->started_list); | 1357 | req = next_request(&dep->started_list); |
| 1356 | if (!req) { | 1358 | if (!req) { |
| 1357 | dep->flags |= DWC3_EP_PENDING_REQUEST; | 1359 | dep->flags |= DWC3_EP_PENDING_REQUEST; |
| @@ -1539,12 +1541,12 @@ static int __dwc3_gadget_start_isoc(struct dwc3_ep *dep) · 181 unmodified lines | |||
| 1539 | if (!dwc->dis_start_transfer_quirk && | 1541 | if (!dwc->dis_start_transfer_quirk && |
| 1540 | (DWC3_VER_IS_PRIOR(DWC31, 170A) || | 1542 | (DWC3_VER_IS_PRIOR(DWC31, 170A) || |
| 1541 | DWC3_VER_TYPE_IS_WITHIN(DWC31, 170A, EA01, EA06))) { | 1543 | DWC3_VER_TYPE_IS_WITHIN(DWC31, 170A, EA01, EA06))) { |
| 1542 | if (dwc->gadget.speed <= USB_SPEED_HIGH && dep->direction) | 1544 | if (dwc->gadget->speed <= USB_SPEED_HIGH && dep->direction) |
| 1543 | return dwc3_gadget_start_isoc_quirk(dep); | 1545 | return dwc3_gadget_start_isoc_quirk(dep); |
| 1544 | } | 1546 | } |
| 1545 | 1547 | ||
| 1546 | if (desc->bInterval <= 14 && | 1548 | if (desc->bInterval <= 14 && |
| 1547 | dwc->gadget.speed >= USB_SPEED_HIGH) { | 1549 | dwc->gadget->speed >= USB_SPEED_HIGH) { |
| 1548 | u32 frame = __dwc3_gadget_get_frame(dwc); | 1550 | u32 frame = __dwc3_gadget_get_frame(dwc); |
| 1549 | bool rollover = frame < | 1551 | bool rollover = frame < |
| 1550 | (dep->frame_number & DWC3_FRNUMBER_MASK); | 1552 | (dep->frame_number & DWC3_FRNUMBER_MASK); |
| @@ -1600,7 +1602,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) · 49 unmodified lines | |||
| 1600 | { | 1602 | { |
| 1601 | struct dwc3 *dwc = dep->dwc; | 1603 | struct dwc3 *dwc = dep->dwc; |
| 1602 | 1604 | ||
| 1603 | if (!dep->endpoint.desc) { | 1605 | if (!dep->endpoint.desc || !dwc->pullups_connected) { |
| 1604 | dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n", | 1606 | dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n", |
| 1605 | dep->name); | 1607 | dep->name); |
| 1606 | return -ESHUTDOWN; | 1608 | return -ESHUTDOWN; |
| @@ -1628,8 +1630,13 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) · 21 unmodified lines | |||
| 1628 | if (dep->flags & DWC3_EP_WAIT_TRANSFER_COMPLETE) | 1630 | if (dep->flags & DWC3_EP_WAIT_TRANSFER_COMPLETE) |
| 1629 | return 0; | 1631 | return 0; |
| 1630 | 1632 | ||
| 1631 | /* Start the transfer only after the END_TRANSFER is completed */ | 1633 | /* |
| 1632 | if (dep->flags & DWC3_EP_END_TRANSFER_PENDING) { | 1634 | * Start the transfer only after the END_TRANSFER is completed |
| 1635 | * and endpoint STALL is cleared. | ||
| 1636 | */ | ||
| 1637 | if ((dep->flags & DWC3_EP_END_TRANSFER_PENDING) || | ||
| 1638 | (dep->flags & DWC3_EP_WEDGE) || | ||
| 1639 | (dep->flags & DWC3_EP_STALL)) { | ||
| 1633 | dep->flags |= DWC3_EP_DELAY_START; | 1640 | dep->flags |= DWC3_EP_DELAY_START; |
| 1634 | return 0; | 1641 | return 0; |
| 1635 | } | 1642 | } |
| @@ -1648,9 +1655,8 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) · 12 unmodified lines | |||
| 1648 | return 0; | 1655 | return 0; |
| 1649 | 1656 | ||
| 1650 | if ((dep->flags & DWC3_EP_PENDING_REQUEST)) { | 1657 | if ((dep->flags & DWC3_EP_PENDING_REQUEST)) { |
| 1651 | if (!(dep->flags & DWC3_EP_TRANSFER_STARTED)) { | 1658 | if (!(dep->flags & DWC3_EP_TRANSFER_STARTED)) |
| 1652 | return __dwc3_gadget_start_isoc(dep); | 1659 | return __dwc3_gadget_start_isoc(dep); |
| 1653 | } | ||
| 1654 | } | 1660 | } |
| 1655 | } | 1661 | } |
| 1656 | 1662 | ||
| @@ -1788,8 +1794,8 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol) · 131 unmodified lines | |||
| 1788 | if (value) { | 1794 | if (value) { |
| 1789 | struct dwc3_trb *trb; | 1795 | struct dwc3_trb *trb; |
| 1790 | 1796 | ||
| 1791 | unsigned transfer_in_flight; | 1797 | unsigned int transfer_in_flight; |
| 1792 | unsigned started; | 1798 | unsigned int started; |
| 1793 | 1799 | ||
| 1794 | if (dep->number > 1) | 1800 | if (dep->number > 1) |
| 1795 | trb = dwc3_ep_prev_trb(dep, dep->trb_enqueue); | 1801 | trb = dwc3_ep_prev_trb(dep, dep->trb_enqueue); |
| @@ -1822,6 +1828,18 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol) · 26 unmodified lines | |||
| 1822 | return 0; | 1828 | return 0; |
| 1823 | } | 1829 | } |
| 1824 | 1830 | ||
| 1831 | dwc3_stop_active_transfer(dep, true, true); | ||
| 1832 | |||
| 1833 | list_for_each_entry_safe(req, tmp, &dep->started_list, list) | ||
| 1834 | dwc3_gadget_move_cancelled_request(req); | ||
| 1835 | |||
| 1836 | if (dep->flags & DWC3_EP_END_TRANSFER_PENDING) { | ||
| 1837 | dep->flags |= DWC3_EP_PENDING_CLEAR_STALL; | ||
| 1838 | return 0; | ||
| 1839 | } | ||
| 1840 | |||
| 1841 | dwc3_gadget_ep_cleanup_cancelled_requests(dep); | ||
| 1842 | |||
| 1825 | ret = dwc3_send_clear_stall_ep_cmd(dep); | 1843 | ret = dwc3_send_clear_stall_ep_cmd(dep); |
| 1826 | if (ret) { | 1844 | if (ret) { |
| 1827 | dev_err(dwc->dev, "failed to clear STALL on %s\n", | 1845 | dev_err(dwc->dev, "failed to clear STALL on %s\n", |
| @@ -1831,18 +1849,11 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol) · 3 unmodified lines | |||
| 1831 | 1849 | ||
| 1832 | dep->flags &= ~(DWC3_EP_STALL | DWC3_EP_WEDGE); | 1850 | dep->flags &= ~(DWC3_EP_STALL | DWC3_EP_WEDGE); |
| 1833 | 1851 | ||
| 1834 | dwc3_stop_active_transfer(dep, true, true); | 1852 | if ((dep->flags & DWC3_EP_DELAY_START) && |
| 1835 | 1853 | !usb_endpoint_xfer_isoc(dep->endpoint.desc)) | |
| 1836 | list_for_each_entry_safe(req, tmp, &dep->started_list, list) | 1854 | __dwc3_gadget_kick_transfer(dep); |
| 1837 | dwc3_gadget_move_cancelled_request(req); | ||
| 1838 | |||
| 1839 | list_for_each_entry_safe(req, tmp, &dep->pending_list, list) | ||
| 1840 | dwc3_gadget_move_cancelled_request(req); | ||
| 1841 | 1855 | ||
| 1842 | if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) { | 1856 | dep->flags &= ~DWC3_EP_DELAY_START; |
| 1843 | dep->flags &= ~DWC3_EP_DELAY_START; | ||
| 1844 | dwc3_gadget_ep_cleanup_cancelled_requests(dep); | ||
| 1845 | } | ||
| 1846 | } | 1857 | } |
| 1847 | 1858 | ||
| 1848 | return ret; | 1859 | return ret; |
| @@ -2010,6 +2021,21 @@ static int dwc3_gadget_set_selfpowered(struct usb_gadget *g, · 161 unmodified lines | |||
| 2010 | return 0; | 2021 | return 0; |
| 2011 | } | 2022 | } |
| 2012 | 2023 | ||
| 2024 | static void dwc3_stop_active_transfers(struct dwc3 *dwc) | ||
| 2025 | { | ||
| 2026 | u32 epnum; | ||
| 2027 | |||
| 2028 | for (epnum = 2; epnum < dwc->num_eps; epnum++) { | ||
| 2029 | struct dwc3_ep *dep; | ||
| 2030 | |||
| 2031 | dep = dwc->eps[epnum]; | ||
| 2032 | if (!dep) | ||
| 2033 | continue; | ||
| 2034 | |||
| 2035 | dwc3_remove_requests(dwc, dep); | ||
| 2036 | } | ||
| 2037 | } | ||
| 2038 | |||
| 2013 | static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend) | 2039 | static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend) |
| 2014 | { | 2040 | { |
| 2015 | u32 reg; | 2041 | u32 reg; |
| @@ -2055,6 +2081,9 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend) · 39 unmodified lines | |||
| 2055 | return 0; | 2081 | return 0; |
| 2056 | } | 2082 | } |
| 2057 | 2083 | ||
| 2084 | static void dwc3_gadget_disable_irq(struct dwc3 *dwc); | ||
| 2085 | static void __dwc3_gadget_stop(struct dwc3 *dwc); | ||
| 2086 | |||
| 2058 | static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) | 2087 | static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) |
| 2059 | { | 2088 | { |
| 2060 | struct dwc3 *dwc = gadget_to_dwc(g); | 2089 | struct dwc3 *dwc = gadget_to_dwc(g); |
| @@ -2078,7 +2107,46 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) · 17 unmodified lines | |||
| 2078 | } | 2107 | } |
| 2079 | } | 2108 | } |
| 2080 | 2109 | ||
| 2110 | /* | ||
| 2111 | * Synchronize any pending event handling before executing the controller | ||
| 2112 | * halt routine. | ||
| 2113 | */ | ||
| 2114 | if (!is_on) { | ||
| 2115 | dwc3_gadget_disable_irq(dwc); | ||
| 2116 | synchronize_irq(dwc->irq_gadget); | ||
| 2117 | } | ||
| 2118 | |||
| 2081 | spin_lock_irqsave(&dwc->lock, flags); | 2119 | spin_lock_irqsave(&dwc->lock, flags); |
| 2120 | |||
| 2121 | if (!is_on) { | ||
| 2122 | u32 count; | ||
| 2123 | |||
| 2124 | /* | ||
| 2125 | * In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a | ||
| 2126 | * Section 4.1.8 Table 4-7, it states that for a device-initiated | ||
| 2127 | * disconnect, the SW needs to ensure that it sends "a DEPENDXFER | ||
| 2128 | * command for any active transfers" before clearing the RunStop | ||
| 2129 | * bit. | ||
| 2130 | */ | ||
| 2131 | dwc3_stop_active_transfers(dwc); | ||
| 2132 | __dwc3_gadget_stop(dwc); | ||
| 2133 | |||
| 2134 | /* | ||
| 2135 | * In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a | ||
| 2136 | * Section 1.3.4, it mentions that for the DEVCTRLHLT bit, the | ||
| 2137 | * "software needs to acknowledge the events that are generated | ||
| 2138 | * (by writing to GEVNTCOUNTn) while it is waiting for this bit | ||
| 2139 | * to be set to '1'." | ||
| 2140 | */ | ||
| 2141 | count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0)); | ||
| 2142 | count &= DWC3_GEVNTCOUNT_MASK; | ||
| 2143 | if (count > 0) { | ||
| 2144 | dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), count); | ||
| 2145 | dwc->ev_buf->lpos = (dwc->ev_buf->lpos + count) % | ||
| 2146 | dwc->ev_buf->length; | ||
| 2147 | } | ||
| 2148 | } | ||
| 2149 | |||
| 2082 | ret = dwc3_gadget_run_stop(dwc, is_on, false); | 2150 | ret = dwc3_gadget_run_stop(dwc, is_on, false); |
| 2083 | spin_unlock_irqrestore(&dwc->lock, flags); | 2151 | spin_unlock_irqrestore(&dwc->lock, flags); |
| 2084 | 2152 | ||
| @@ -2244,7 +2312,7 @@ static int dwc3_gadget_start(struct usb_gadget *g, · 159 unmodified lines | |||
| 2244 | spin_lock_irqsave(&dwc->lock, flags); | 2312 | spin_lock_irqsave(&dwc->lock, flags); |
| 2245 | if (dwc->gadget_driver) { | 2313 | if (dwc->gadget_driver) { |
| 2246 | dev_err(dwc->dev, "%s is already bound to %s\n", | 2314 | dev_err(dwc->dev, "%s is already bound to %s\n", |
| 2247 | dwc->gadget.name, | 2315 | dwc->gadget->name, |
| 2248 | dwc->gadget_driver->driver.name); | 2316 | dwc->gadget_driver->driver.name); |
| 2249 | ret = -EBUSY; | 2317 | ret = -EBUSY; |
| 2250 | goto err1; | 2318 | goto err1; |
| @@ -2416,7 +2484,7 @@ static int dwc3_gadget_init_control_endpoint(struct dwc3_ep *dep) · 165 unmodified lines | |||
| 2416 | dep->endpoint.maxburst = 1; | 2484 | dep->endpoint.maxburst = 1; |
| 2417 | dep->endpoint.ops = &dwc3_gadget_ep0_ops; | 2485 | dep->endpoint.ops = &dwc3_gadget_ep0_ops; |
| 2418 | if (!dep->direction) | 2486 | if (!dep->direction) |
| 2419 | dwc->gadget.ep0 = &dep->endpoint; | 2487 | dwc->gadget->ep0 = &dep->endpoint; |
| 2420 | 2488 | ||
| 2421 | dep->endpoint.caps.type_control = true; | 2489 | dep->endpoint.caps.type_control = true; |
| 2422 | 2490 | ||
| @@ -2459,10 +2527,10 @@ static int dwc3_gadget_init_in_endpoint(struct dwc3_ep *dep) · 36 unmodified lines | |||
| 2459 | 2527 | ||
| 2460 | usb_ep_set_maxpacket_limit(&dep->endpoint, size); | 2528 | usb_ep_set_maxpacket_limit(&dep->endpoint, size); |
| 2461 | 2529 | ||
| 2462 | dep->endpoint.max_streams = 15; | 2530 | dep->endpoint.max_streams = 16; |
| 2463 | dep->endpoint.ops = &dwc3_gadget_ep_ops; | 2531 | dep->endpoint.ops = &dwc3_gadget_ep_ops; |
| 2464 | list_add_tail(&dep->endpoint.ep_list, | 2532 | list_add_tail(&dep->endpoint.ep_list, |
| 2465 | &dwc->gadget.ep_list); | 2533 | &dwc->gadget->ep_list); |
| 2466 | dep->endpoint.caps.type_iso = true; | 2534 | dep->endpoint.caps.type_iso = true; |
| 2467 | dep->endpoint.caps.type_bulk = true; | 2535 | dep->endpoint.caps.type_bulk = true; |
| 2468 | dep->endpoint.caps.type_int = true; | 2536 | dep->endpoint.caps.type_int = true; |
| @@ -2508,10 +2576,10 @@ static int dwc3_gadget_init_out_endpoint(struct dwc3_ep *dep) · 39 unmodified lines | |||
| 2508 | size /= 3; | 2576 | size /= 3; |
| 2509 | 2577 | ||
| 2510 | usb_ep_set_maxpacket_limit(&dep->endpoint, size); | 2578 | usb_ep_set_maxpacket_limit(&dep->endpoint, size); |
| 2511 | dep->endpoint.max_streams = 15; | 2579 | dep->endpoint.max_streams = 16; |
| 2512 | dep->endpoint.ops = &dwc3_gadget_ep_ops; | 2580 | dep->endpoint.ops = &dwc3_gadget_ep_ops; |
| 2513 | list_add_tail(&dep->endpoint.ep_list, | 2581 | list_add_tail(&dep->endpoint.ep_list, |
| 2514 | &dwc->gadget.ep_list); | 2582 | &dwc->gadget->ep_list); |
| 2515 | dep->endpoint.caps.type_iso = true; | 2583 | dep->endpoint.caps.type_iso = true; |
| 2516 | dep->endpoint.caps.type_bulk = true; | 2584 | dep->endpoint.caps.type_bulk = true; |
| 2517 | dep->endpoint.caps.type_int = true; | 2585 | dep->endpoint.caps.type_int = true; |
| @@ -2572,7 +2640,7 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc, u8 total) · 54 unmodified lines | |||
| 2572 | { | 2640 | { |
| 2573 | u8 epnum; | 2641 | u8 epnum; |
| 2574 | 2642 | ||
| 2575 | INIT_LIST_HEAD(&dwc->gadget.ep_list); | 2643 | INIT_LIST_HEAD(&dwc->gadget->ep_list); |
| 2576 | 2644 | ||
| 2577 | for (epnum = 0; epnum < total; epnum++) { | 2645 | for (epnum = 0; epnum < total; epnum++) { |
| 2578 | int ret; | 2646 | int ret; |
| @@ -2652,12 +2720,12 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep, · 73 unmodified lines | |||
| 2652 | } | 2720 | } |
| 2653 | 2721 | ||
| 2654 | /* | 2722 | /* |
| 2655 | * If we're dealing with unaligned size OUT transfer, we will be left | 2723 | * We use bounce buffer for requests that needs extra TRB or OUT ZLP. If |
| 2656 | * with one TRB pending in the ring. We need to manually clear HWO bit | 2724 | * this TRB points to the bounce buffer address, it's a MPS alignment |
| 2657 | * from that TRB. | 2725 | * TRB. Don't add it to req->remaining calculation. |
| 2658 | */ | 2726 | */ |
| 2659 | 2727 | if (trb->bpl == lower_32_bits(dep->dwc->bounce_addr) && | |
| 2660 | if (req->needs_extra_trb && !(trb->ctrl & DWC3_TRB_CTRL_CHN)) { | 2728 | trb->bph == upper_32_bits(dep->dwc->bounce_addr)) { |
| 2661 | trb->ctrl &= ~DWC3_TRB_CTRL_HWO; | 2729 | trb->ctrl &= ~DWC3_TRB_CTRL_HWO; |
| 2662 | return 1; | 2730 | return 1; |
| 2663 | } | 2731 | } |
| @@ -2732,26 +2800,17 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep, · 68 unmodified lines | |||
| 2732 | ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, | 2800 | ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, |
| 2733 | status); | 2801 | status); |
| 2734 | 2802 | ||
| 2735 | if (req->needs_extra_trb) { | 2803 | req->request.actual = req->request.length - req->remaining; |
| 2736 | unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); | 2804 | |
| 2805 | if (!dwc3_gadget_ep_request_completed(req)) | ||
| 2806 | goto out; | ||
| 2737 | 2807 | ||
| 2808 | if (req->needs_extra_trb) { | ||
| 2738 | ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, | 2809 | ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, |
| 2739 | status); | 2810 | status); |
| 2740 | |||
| 2741 | /* Reclaim MPS padding TRB for ZLP */ | ||
| 2742 | if (!req->direction && req->request.zero && req->request.length && | ||
| 2743 | !usb_endpoint_xfer_isoc(dep->endpoint.desc) && | ||
| 2744 | (IS_ALIGNED(req->request.length, maxp))) | ||
| 2745 | ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, status); | ||
| 2746 | |||
| 2747 | req->needs_extra_trb = false; | 2811 | req->needs_extra_trb = false; |
| 2748 | } | 2812 | } |
| 2749 | 2813 | ||
| 2750 | req->request.actual = req->request.length - req->remaining; | ||
| 2751 | |||
| 2752 | if (!dwc3_gadget_ep_request_completed(req)) | ||
| 2753 | goto out; | ||
| 2754 | |||
| 2755 | dwc3_gadget_giveback(dep, req, status); | 2814 | dwc3_gadget_giveback(dep, req, status); |
| 2756 | 2815 | ||
| 2757 | out: | 2816 | out: |
| @@ -2896,6 +2955,43 @@ static void dwc3_gadget_endpoint_transfer_not_ready(struct dwc3_ep *dep, · 138 unmodified lines | |||
| 2896 | (void) __dwc3_gadget_start_isoc(dep); | 2955 | (void) __dwc3_gadget_start_isoc(dep); |
| 2897 | } | 2956 | } |
| 2898 | 2957 | ||
| 2958 | static void dwc3_gadget_endpoint_command_complete(struct dwc3_ep *dep, | ||
| 2959 | const struct dwc3_event_depevt *event) | ||
| 2960 | { | ||
| 2961 | u8 cmd = DEPEVT_PARAMETER_CMD(event->parameters); | ||
| 2962 | |||
| 2963 | if (cmd != DWC3_DEPCMD_ENDTRANSFER) | ||
| 2964 | return; | ||
| 2965 | |||
| 2966 | dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING; | ||
| 2967 | dep->flags &= ~DWC3_EP_TRANSFER_STARTED; | ||
| 2968 | dwc3_gadget_ep_cleanup_cancelled_requests(dep); | ||
| 2969 | |||
| 2970 | if (dep->flags & DWC3_EP_PENDING_CLEAR_STALL) { | ||
| 2971 | struct dwc3 *dwc = dep->dwc; | ||
| 2972 | |||
| 2973 | dep->flags &= ~DWC3_EP_PENDING_CLEAR_STALL; | ||
| 2974 | if (dwc3_send_clear_stall_ep_cmd(dep)) { | ||
| 2975 | struct usb_ep *ep0 = &dwc->eps[0]->endpoint; | ||
| 2976 | |||
| 2977 | dev_err(dwc->dev, "failed to clear STALL on %s\n", dep->name); | ||
| 2978 | if (dwc->delayed_status) | ||
| 2979 | __dwc3_gadget_ep0_set_halt(ep0, 1); | ||
| 2980 | return; | ||
| 2981 | } | ||
| 2982 | |||
| 2983 | dep->flags &= ~(DWC3_EP_STALL | DWC3_EP_WEDGE); | ||
| 2984 | if (dwc->delayed_status) | ||
| 2985 | dwc3_ep0_send_delayed_status(dwc); | ||
| 2986 | } | ||
| 2987 | |||
| 2988 | if ((dep->flags & DWC3_EP_DELAY_START) && | ||
| 2989 | !usb_endpoint_xfer_isoc(dep->endpoint.desc)) | ||
| 2990 | __dwc3_gadget_kick_transfer(dep); | ||
| 2991 | |||
| 2992 | dep->flags &= ~DWC3_EP_DELAY_START; | ||
| 2993 | } | ||
| 2994 | |||
| 2899 | static void dwc3_gadget_endpoint_stream_event(struct dwc3_ep *dep, | 2995 | static void dwc3_gadget_endpoint_stream_event(struct dwc3_ep *dep, |
| 2900 | const struct dwc3_event_depevt *event) | 2996 | const struct dwc3_event_depevt *event) |
| 2901 | { | 2997 | { |
| @@ -2965,7 +3061,6 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, · 63 unmodified lines | |||
| 2965 | { | 3061 | { |
| 2966 | struct dwc3_ep *dep; | 3062 | struct dwc3_ep *dep; |
| 2967 | u8 epnum = event->endpoint_number; | 3063 | u8 epnum = event->endpoint_number; |
| 2968 | u8 cmd; | ||
| 2969 | 3064 | ||
| 2970 | dep = dwc->eps[epnum]; | 3065 | dep = dwc->eps[epnum]; |
| 2971 | 3066 | ||
| @@ -2991,18 +3086,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, · 19 unmodified lines | |||
| 2991 | dwc3_gadget_endpoint_transfer_not_ready(dep, event); | 3086 | dwc3_gadget_endpoint_transfer_not_ready(dep, event); |
| 2992 | break; | 3087 | break; |
| 2993 | case DWC3_DEPEVT_EPCMDCMPLT: | 3088 | case DWC3_DEPEVT_EPCMDCMPLT: |
| 2994 | cmd = DEPEVT_PARAMETER_CMD(event->parameters); | 3089 | dwc3_gadget_endpoint_command_complete(dep, event); |
| 2995 | |||
| 2996 | if (cmd == DWC3_DEPCMD_ENDTRANSFER) { | ||
| 2997 | dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING; | ||
| 2998 | dep->flags &= ~DWC3_EP_TRANSFER_STARTED; | ||
| 2999 | dwc3_gadget_ep_cleanup_cancelled_requests(dep); | ||
| 3000 | if ((dep->flags & DWC3_EP_DELAY_START) && | ||
| 3001 | !usb_endpoint_xfer_isoc(dep->endpoint.desc)) | ||
| 3002 | __dwc3_gadget_kick_transfer(dep); | ||
| 3003 | |||
| 3004 | dep->flags &= ~DWC3_EP_DELAY_START; | ||
| 3005 | } | ||
| 3006 | break; | 3090 | break; |
| 3007 | case DWC3_DEPEVT_XFERCOMPLETE: | 3091 | case DWC3_DEPEVT_XFERCOMPLETE: |
| 3008 | dwc3_gadget_endpoint_transfer_complete(dep, event); | 3092 | dwc3_gadget_endpoint_transfer_complete(dep, event); |
| @@ -3019,7 +3103,7 @@ static void dwc3_disconnect_gadget(struct dwc3 *dwc) · 10 unmodified lines | |||
| 3019 | { | 3103 | { |
| 3020 | if (dwc->gadget_driver && dwc->gadget_driver->disconnect) { | 3104 | if (dwc->gadget_driver && dwc->gadget_driver->disconnect) { |
| 3021 | spin_unlock(&dwc->lock); | 3105 | spin_unlock(&dwc->lock); |
| 3022 | dwc->gadget_driver->disconnect(&dwc->gadget); | 3106 | dwc->gadget_driver->disconnect(dwc->gadget); |
| 3023 | spin_lock(&dwc->lock); | 3107 | spin_lock(&dwc->lock); |
| 3024 | } | 3108 | } |
| 3025 | } | 3109 | } |
| @@ -3028,7 +3112,7 @@ static void dwc3_suspend_gadget(struct dwc3 *dwc) · 2 unmodified lines | |||
| 3028 | { | 3112 | { |
| 3029 | if (dwc->gadget_driver && dwc->gadget_driver->suspend) { | 3113 | if (dwc->gadget_driver && dwc->gadget_driver->suspend) { |
| 3030 | spin_unlock(&dwc->lock); | 3114 | spin_unlock(&dwc->lock); |
| 3031 | dwc->gadget_driver->suspend(&dwc->gadget); | 3115 | dwc->gadget_driver->suspend(dwc->gadget); |
| 3032 | spin_lock(&dwc->lock); | 3116 | spin_lock(&dwc->lock); |
| 3033 | } | 3117 | } |
| 3034 | } | 3118 | } |
| @@ -3037,7 +3121,7 @@ static void dwc3_resume_gadget(struct dwc3 *dwc) · 2 unmodified lines | |||
| 3037 | { | 3121 | { |
| 3038 | if (dwc->gadget_driver && dwc->gadget_driver->resume) { | 3122 | if (dwc->gadget_driver && dwc->gadget_driver->resume) { |
| 3039 | spin_unlock(&dwc->lock); | 3123 | spin_unlock(&dwc->lock); |
| 3040 | dwc->gadget_driver->resume(&dwc->gadget); | 3124 | dwc->gadget_driver->resume(dwc->gadget); |
| 3041 | spin_lock(&dwc->lock); | 3125 | spin_lock(&dwc->lock); |
| 3042 | } | 3126 | } |
| 3043 | } | 3127 | } |
| @@ -3047,9 +3131,9 @@ static void dwc3_reset_gadget(struct dwc3 *dwc) · 3 unmodified lines | |||
| 3047 | if (!dwc->gadget_driver) | 3131 | if (!dwc->gadget_driver) |
| 3048 | return; | 3132 | return; |
| 3049 | 3133 | ||
| 3050 | if (dwc->gadget.speed != USB_SPEED_UNKNOWN) { | 3134 | if (dwc->gadget->speed != USB_SPEED_UNKNOWN) { |
| 3051 | spin_unlock(&dwc->lock); | 3135 | spin_unlock(&dwc->lock); |
| 3052 | usb_gadget_udc_reset(&dwc->gadget, dwc->gadget_driver); | 3136 | usb_gadget_udc_reset(dwc->gadget, dwc->gadget_driver); |
| 3053 | spin_lock(&dwc->lock); | 3137 | spin_lock(&dwc->lock); |
| 3054 | } | 3138 | } |
| 3055 | } | 3139 | } |
| @@ -3150,9 +3234,9 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) · 94 unmodified lines | |||
| 3150 | 3234 | ||
| 3151 | dwc3_disconnect_gadget(dwc); | 3235 | dwc3_disconnect_gadget(dwc); |
| 3152 | 3236 | ||
| 3153 | dwc->gadget.speed = USB_SPEED_UNKNOWN; | 3237 | dwc->gadget->speed = USB_SPEED_UNKNOWN; |
| 3154 | dwc->setup_packet_pending = false; | 3238 | dwc->setup_packet_pending = false; |
| 3155 | usb_gadget_set_state(&dwc->gadget, USB_STATE_NOTATTACHED); | 3239 | usb_gadget_set_state(dwc->gadget, USB_STATE_NOTATTACHED); |
| 3156 | 3240 | ||
| 3157 | dwc->connected = false; | 3241 | dwc->connected = false; |
| 3158 | } | 3242 | } |
| @@ -3195,6 +3279,13 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) · 36 unmodified lines | |||
| 3195 | } | 3279 | } |
| 3196 | 3280 | ||
| 3197 | dwc3_reset_gadget(dwc); | 3281 | dwc3_reset_gadget(dwc); |
| 3282 | /* | ||
| 3283 | * In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a | ||
| 3284 | * Section 4.1.2 Table 4-2, it states that during a USB reset, the SW | ||
| 3285 | * needs to ensure that it sends "a DEPENDXFER command for any active | ||
| 3286 | * transfers." | ||
| 3287 | */ | ||
| 3288 | dwc3_stop_active_transfers(dwc); | ||
| 3198 | 3289 | ||
| 3199 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); | 3290 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); |
| 3200 | reg &= ~DWC3_DCTL_TSTCTRL_MASK; | 3291 | reg &= ~DWC3_DCTL_TSTCTRL_MASK; |
| @@ -3231,8 +3322,8 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) · 30 unmodified lines | |||
| 3231 | switch (speed) { | 3322 | switch (speed) { |
| 3232 | case DWC3_DSTS_SUPERSPEED_PLUS: | 3323 | case DWC3_DSTS_SUPERSPEED_PLUS: |
| 3233 | dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); | 3324 | dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); |
| 3234 | dwc->gadget.ep0->maxpacket = 512; | 3325 | dwc->gadget->ep0->maxpacket = 512; |
| 3235 | dwc->gadget.speed = USB_SPEED_SUPER_PLUS; | 3326 | dwc->gadget->speed = USB_SPEED_SUPER_PLUS; |
| 3236 | break; | 3327 | break; |
| 3237 | case DWC3_DSTS_SUPERSPEED: | 3328 | case DWC3_DSTS_SUPERSPEED: |
| 3238 | /* | 3329 | /* |
| @@ -3252,27 +3343,27 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) · 13 unmodified lines | |||
| 3252 | dwc3_gadget_reset_interrupt(dwc); | 3343 | dwc3_gadget_reset_interrupt(dwc); |
| 3253 | 3344 | ||
| 3254 | dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); | 3345 | dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); |
| 3255 | dwc->gadget.ep0->maxpacket = 512; | 3346 | dwc->gadget->ep0->maxpacket = 512; |
| 3256 | dwc->gadget.speed = USB_SPEED_SUPER; | 3347 | dwc->gadget->speed = USB_SPEED_SUPER; |
| 3257 | break; | 3348 | break; |
| 3258 | case DWC3_DSTS_HIGHSPEED: | 3349 | case DWC3_DSTS_HIGHSPEED: |
| 3259 | dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(64); | 3350 | dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(64); |
| 3260 | dwc->gadget.ep0->maxpacket = 64; | 3351 | dwc->gadget->ep0->maxpacket = 64; |
| 3261 | dwc->gadget.speed = USB_SPEED_HIGH; | 3352 | dwc->gadget->speed = USB_SPEED_HIGH; |
| 3262 | break; | 3353 | break; |
| 3263 | case DWC3_DSTS_FULLSPEED: | 3354 | case DWC3_DSTS_FULLSPEED: |
| 3264 | dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(64); | 3355 | dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(64); |
| 3265 | dwc->gadget.ep0->maxpacket = 64; | 3356 | dwc->gadget->ep0->maxpacket = 64; |
| 3266 | dwc->gadget.speed = USB_SPEED_FULL; | 3357 | dwc->gadget->speed = USB_SPEED_FULL; |
| 3267 | break; | 3358 | break; |
| 3268 | case DWC3_DSTS_LOWSPEED: | 3359 | case DWC3_DSTS_LOWSPEED: |
| 3269 | dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(8); | 3360 | dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(8); |
| 3270 | dwc->gadget.ep0->maxpacket = 8; | 3361 | dwc->gadget->ep0->maxpacket = 8; |
| 3271 | dwc->gadget.speed = USB_SPEED_LOW; | 3362 | dwc->gadget->speed = USB_SPEED_LOW; |
| 3272 | break; | 3363 | break; |
| 3273 | } | 3364 | } |
| 3274 | 3365 | ||
| 3275 | dwc->eps[1]->endpoint.maxpacket = dwc->gadget.ep0->maxpacket; | 3366 | dwc->eps[1]->endpoint.maxpacket = dwc->gadget->ep0->maxpacket; |
| 3276 | 3367 | ||
| 3277 | /* Enable USB2 LPM Capability */ | 3368 | /* Enable USB2 LPM Capability */ |
| 3278 | 3369 | ||
| @@ -3340,7 +3431,7 @@ static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc) · 61 unmodified lines | |||
| 3340 | 3431 | ||
| 3341 | if (dwc->gadget_driver && dwc->gadget_driver->resume) { | 3432 | if (dwc->gadget_driver && dwc->gadget_driver->resume) { |
| 3342 | spin_unlock(&dwc->lock); | 3433 | spin_unlock(&dwc->lock); |
| 3343 | dwc->gadget_driver->resume(&dwc->gadget); | 3434 | dwc->gadget_driver->resume(dwc->gadget); |
| 3344 | spin_lock(&dwc->lock); | 3435 | spin_lock(&dwc->lock); |
| 3345 | } | 3436 | } |
| 3346 | } | 3437 | } |
| @@ -3511,7 +3602,7 @@ static void dwc3_gadget_interrupt(struct dwc3 *dwc, · 164 unmodified lines | |||
| 3511 | * Ignore suspend event until the gadget enters into | 3602 | * Ignore suspend event until the gadget enters into |
| 3512 | * USB_STATE_CONFIGURED state. | 3603 | * USB_STATE_CONFIGURED state. |
| 3513 | */ | 3604 | */ |
| 3514 | if (dwc->gadget.state >= USB_STATE_CONFIGURED) | 3605 | if (dwc->gadget->state >= USB_STATE_CONFIGURED) |
| 3515 | dwc3_gadget_suspend_interrupt(dwc, | 3606 | dwc3_gadget_suspend_interrupt(dwc, |
| 3516 | event->event_info); | 3607 | event->event_info); |
| 3517 | } | 3608 | } |
| @@ -3686,6 +3777,13 @@ out: · 168 unmodified lines | |||
| 3686 | return irq; | 3777 | return irq; |
| 3687 | } | 3778 | } |
| 3688 | 3779 | ||
| 3780 | static void dwc_gadget_release(struct device *dev) | ||
| 3781 | { | ||
| 3782 | struct usb_gadget *gadget = container_of(dev, struct usb_gadget, dev); | ||
| 3783 | |||
| 3784 | kfree(gadget); | ||
| 3785 | } | ||
| 3786 | |||
| 3689 | /** | 3787 | /** |
| 3690 | * dwc3_gadget_init - initializes gadget related registers | 3788 | * dwc3_gadget_init - initializes gadget related registers |
| 3691 | * @dwc: pointer to our controller context structure | 3789 | * @dwc: pointer to our controller context structure |
| @@ -3696,6 +3794,7 @@ int dwc3_gadget_init(struct dwc3 *dwc) · 4 unmodified lines | |||
| 3696 | { | 3794 | { |
| 3697 | int ret; | 3795 | int ret; |
| 3698 | int irq; | 3796 | int irq; |
| 3797 | struct device *dev; | ||
| 3699 | 3798 | ||
| 3700 | irq = dwc3_gadget_get_irq(dwc); | 3799 | irq = dwc3_gadget_get_irq(dwc); |
| 3701 | if (irq < 0) { | 3800 | if (irq < 0) { |
| @@ -3728,12 +3827,21 @@ int dwc3_gadget_init(struct dwc3 *dwc) · 26 unmodified lines | |||
| 3728 | } | 3827 | } |
| 3729 | 3828 | ||
| 3730 | init_completion(&dwc->ep0_in_setup); | 3829 | init_completion(&dwc->ep0_in_setup); |
| 3830 | dwc->gadget = kzalloc(sizeof(struct usb_gadget), GFP_KERNEL); | ||
| 3831 | if (!dwc->gadget) { | ||
| 3832 | ret = -ENOMEM; | ||
| 3833 | goto err3; | ||
| 3834 | } | ||
| 3731 | 3835 | ||
| 3732 | dwc->gadget.ops = &dwc3_gadget_ops; | 3836 | |
| 3733 | dwc->gadget.speed = USB_SPEED_UNKNOWN; | 3837 | usb_initialize_gadget(dwc->dev, dwc->gadget, dwc_gadget_release); |
| 3734 | dwc->gadget.sg_supported = true; | 3838 | dev = &dwc->gadget->dev; |
| 3735 | dwc->gadget.name = "dwc3-gadget"; | 3839 | dev->platform_data = dwc; |
| 3736 | dwc->gadget.lpm_capable = true; | 3840 | dwc->gadget->ops = &dwc3_gadget_ops; |
| 3841 | dwc->gadget->speed = USB_SPEED_UNKNOWN; | ||
| 3842 | dwc->gadget->sg_supported = true; | ||
| 3843 | dwc->gadget->name = "dwc3-gadget"; | ||
| 3844 | dwc->gadget->lpm_capable = true; | ||
| 3737 | 3845 | ||
| 3738 | /* | 3846 | /* |
| 3739 | * FIXME We might be setting max_speed to <SUPER, however versions | 3847 | * FIXME We might be setting max_speed to <SUPER, however versions |
| @@ -3756,7 +3864,7 @@ int dwc3_gadget_init(struct dwc3 *dwc) · 16 unmodified lines | |||
| 3756 | dev_info(dwc->dev, "changing max_speed on rev %08x\n", | 3864 | dev_info(dwc->dev, "changing max_speed on rev %08x\n", |
| 3757 | dwc->revision); | 3865 | dwc->revision); |
| 3758 | 3866 | ||
| 3759 | dwc->gadget.max_speed = dwc->maximum_speed; | 3867 | dwc->gadget->max_speed = dwc->maximum_speed; |
| 3760 | 3868 | ||
| 3761 | /* | 3869 | /* |
| 3762 | * REVISIT: Here we should clear all pending IRQs to be | 3870 | * REVISIT: Here we should clear all pending IRQs to be |
| @@ -3765,21 +3873,22 @@ int dwc3_gadget_init(struct dwc3 *dwc) · 2 unmodified lines | |||
| 3765 | 3873 | ||
| 3766 | ret = dwc3_gadget_init_endpoints(dwc, dwc->num_eps); | 3874 | ret = dwc3_gadget_init_endpoints(dwc, dwc->num_eps); |
| 3767 | if (ret) | 3875 | if (ret) |
| 3768 | goto err3; | 3876 | goto err4; |
| 3769 | 3877 | ||
| 3770 | ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget); | 3878 | ret = usb_add_gadget(dwc->gadget); |
| 3771 | if (ret) { | 3879 | if (ret) { |
| 3772 | dev_err(dwc->dev, "failed to register udc\n"); | 3880 | dev_err(dwc->dev, "failed to add gadget\n"); |
| 3773 | goto err4; | 3881 | goto err5; |
| 3774 | } | 3882 | } |
| 3775 | 3883 | ||
| 3776 | dwc3_gadget_set_speed(&dwc->gadget, dwc->maximum_speed); | 3884 | dwc3_gadget_set_speed(dwc->gadget, dwc->maximum_speed); |
| 3777 | 3885 | ||
| 3778 | return 0; | 3886 | return 0; |
| 3779 | 3887 | ||
| 3780 | err4: | 3888 | err5: |
| 3781 | dwc3_gadget_free_endpoints(dwc); | 3889 | dwc3_gadget_free_endpoints(dwc); |
| 3782 | 3890 | err4: | |
| 3891 | usb_put_gadget(dwc->gadget); | ||
| 3783 | err3: | 3892 | err3: |
| 3784 | dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce, | 3893 | dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce, |
| 3785 | dwc->bounce_addr); | 3894 | dwc->bounce_addr); |
| @@ -3799,7 +3908,7 @@ err0: · 13 unmodified lines | |||
| 3799 | 3908 | ||
| 3800 | void dwc3_gadget_exit(struct dwc3 *dwc) | 3909 | void dwc3_gadget_exit(struct dwc3 *dwc) |
| 3801 | { | 3910 | { |
| 3802 | usb_del_gadget_udc(&dwc->gadget); | 3911 | usb_del_gadget_udc(dwc->gadget); |
| 3803 | dwc3_gadget_free_endpoints(dwc); | 3912 | dwc3_gadget_free_endpoints(dwc); |
| 3804 | dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce, | 3913 | dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce, |
| 3805 | dwc->bounce_addr); | 3914 | dwc->bounce_addr); |
| @@ -17,7 +17,7 @@ · 16 unmodified lines | |||
| 17 | 17 | ||
| 18 | struct dwc3; | 18 | struct dwc3; |
| 19 | #define to_dwc3_ep(ep) (container_of(ep, struct dwc3_ep, endpoint)) | 19 | #define to_dwc3_ep(ep) (container_of(ep, struct dwc3_ep, endpoint)) |
| 20 | #define gadget_to_dwc(g) (container_of(g, struct dwc3, gadget)) | 20 | #define gadget_to_dwc(g) (dev_get_platdata(&g->dev)) |
| 21 | 21 | ||
| 22 | /* DEPCFG parameter 1 */ | 22 | /* DEPCFG parameter 1 */ |
| 23 | #define DWC3_DEPCFG_INT_NUM(n) (((n) & 0x1f) << 0) | 23 | #define DWC3_DEPCFG_INT_NUM(n) (((n) & 0x1f) << 0) |
| @@ -113,6 +113,7 @@ int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value); · 89 unmodified lines | |||
| 113 | int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, | 113 | int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, |
| 114 | gfp_t gfp_flags); | 114 | gfp_t gfp_flags); |
| 115 | int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol); | 115 | int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol); |
| 116 | void dwc3_ep0_send_delayed_status(struct dwc3 *dwc); | ||
| 116 | 117 | ||
| 117 | /** | 118 | /** |
| 118 | * dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW | 119 | * dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW |
| @@ -104,8 +104,8 @@ DECLARE_EVENT_CLASS(dwc3_log_request, · 103 unmodified lines | |||
| 104 | TP_STRUCT__entry( | 104 | TP_STRUCT__entry( |
| 105 | __string(name, req->dep->name) | 105 | __string(name, req->dep->name) |
| 106 | __field(struct dwc3_request *, req) | 106 | __field(struct dwc3_request *, req) |
| 107 | __field(unsigned, actual) | 107 | __field(unsigned int, actual) |
| 108 | __field(unsigned, length) | 108 | __field(unsigned int, length) |
| 109 | __field(int, status) | 109 | __field(int, status) |
| 110 | __field(int, zero) | 110 | __field(int, zero) |
| 111 | __field(int, short_not_ok) | 111 | __field(int, short_not_ok) |
| @@ -246,6 +246,7 @@ DECLARE_EVENT_CLASS(dwc3_log_trb, · 134 unmodified lines | |||
| 246 | __entry->dequeue, __entry->bph, __entry->bpl, | 246 | __entry->dequeue, __entry->bph, __entry->bpl, |
| 247 | ({char *s; | 247 | ({char *s; |
| 248 | int pcm = ((__entry->size >> 24) & 3) + 1; | 248 | int pcm = ((__entry->size >> 24) & 3) + 1; |
| 249 | |||
| 249 | switch (__entry->type) { | 250 | switch (__entry->type) { |
| 250 | case USB_ENDPOINT_XFER_INT: | 251 | case USB_ENDPOINT_XFER_INT: |
| 251 | case USB_ENDPOINT_XFER_ISOC: | 252 | case USB_ENDPOINT_XFER_ISOC: |
| @@ -291,12 +292,12 @@ DECLARE_EVENT_CLASS(dwc3_log_ep, · 39 unmodified lines | |||
| 291 | TP_ARGS(dep), | 292 | TP_ARGS(dep), |
| 292 | TP_STRUCT__entry( | 293 | TP_STRUCT__entry( |
| 293 | __string(name, dep->name) | 294 | __string(name, dep->name) |
| 294 | __field(unsigned, maxpacket) | 295 | __field(unsigned int, maxpacket) |
| 295 | __field(unsigned, maxpacket_limit) | 296 | __field(unsigned int, maxpacket_limit) |
| 296 | __field(unsigned, max_streams) | 297 | __field(unsigned int, max_streams) |
| 297 | __field(unsigned, maxburst) | 298 | __field(unsigned int, maxburst) |
| 298 | __field(unsigned, flags) | 299 | __field(unsigned int, flags) |
| 299 | __field(unsigned, direction) | 300 | __field(unsigned int, direction) |
| 300 | __field(u8, trb_enqueue) | 301 | __field(u8, trb_enqueue) |
| 301 | __field(u8, trb_dequeue) | 302 | __field(u8, trb_dequeue) |
| 302 | ), | 303 | ), |
| @@ -19,7 +19,7 @@ · 18 unmodified lines | |||
| 19 | 19 | ||
| 20 | static int dwc3_ulpi_busyloop(struct dwc3 *dwc) | 20 | static int dwc3_ulpi_busyloop(struct dwc3 *dwc) |
| 21 | { | 21 | { |
| 22 | unsigned count = 1000; | 22 | unsigned int count = 1000; |
| 23 | u32 reg; | 23 | u32 reg; |
| 24 | 24 | ||
| 25 | while (count--) { | 25 | while (count--) { |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | |||
| 15 | #include <linux/console.h> | 15 | #include <linux/console.h> |
| 16 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
| 17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
| 18 | #include <linux/iopoll.h> | ||
| 18 | #include <linux/pci_regs.h> | 19 | #include <linux/pci_regs.h> |
| 19 | #include <linux/pci_ids.h> | 20 | #include <linux/pci_ids.h> |
| 20 | #include <linux/usb/ch9.h> | 21 | #include <linux/usb/ch9.h> |
| @@ -161,17 +162,11 @@ static inline u32 dbgp_pid_read_update(u32 x, u32 tok) · 140 unmodified lines | |||
| 161 | static int dbgp_wait_until_complete(void) | 162 | static int dbgp_wait_until_complete(void) |
| 162 | { | 163 | { |
| 163 | u32 ctrl; | 164 | u32 ctrl; |
| 164 | int loop = DBGP_TIMEOUT; | 165 | int ret; |
| 165 | |||
| 166 | do { | ||
| 167 | ctrl = readl(&ehci_debug->control); | ||
| 168 | /* Stop when the transaction is finished */ | ||
| 169 | if (ctrl & DBGP_DONE) | ||
| 170 | break; | ||
| 171 | udelay(1); | ||
| 172 | } while (--loop > 0); | ||
| 173 | 166 | ||
| 174 | if (!loop) | 167 | ret = readl_poll_timeout_atomic(&ehci_debug->control, ctrl, |
| 168 | (ctrl & DBGP_DONE), 1, DBGP_TIMEOUT); | ||
| 169 | if (ret) | ||
| 175 | return -DBGP_TIMEOUT; | 170 | return -DBGP_TIMEOUT; |
| 176 | 171 | ||
| 177 | /* | 172 | /* |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | |||
| 14 | #include <linux/pci_ids.h> | 14 | #include <linux/pci_ids.h> |
| 15 | #include <linux/memblock.h> | 15 | #include <linux/memblock.h> |
| 16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
| 17 | #include <linux/iopoll.h> | ||
| 17 | #include <asm/pci-direct.h> | 18 | #include <asm/pci-direct.h> |
| 18 | #include <asm/fixmap.h> | 19 | #include <asm/fixmap.h> |
| 19 | #include <linux/bcd.h> | 20 | #include <linux/bcd.h> |
| @@ -135,16 +136,9 @@ static int handshake(void __iomem *ptr, u32 mask, u32 done, int wait, int delay) · 115 unmodified lines | |||
| 135 | { | 136 | { |
| 136 | u32 result; | 137 | u32 result; |
| 137 | 138 | ||
| 138 | do { | 139 | return readl_poll_timeout_atomic(ptr, result, |
| 139 | result = readl(ptr); | 140 | ((result & mask) == done), |
| 140 | result &= mask; | 141 | delay, wait); |
| 141 | if (result == done) | ||
| 142 | return 0; | ||
| 143 | udelay(delay); | ||
| 144 | wait -= delay; | ||
| 145 | } while (wait > 0); | ||
| 146 | |||
| 147 | return -ETIMEDOUT; | ||
| 148 | } | 142 | } |
| 149 | 143 | ||
| 150 | static void __init xdbc_bios_handoff(void) | 144 | static void __init xdbc_bios_handoff(void) |
| @@ -425,9 +425,11 @@ static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt) · 424 unmodified lines | |||
| 425 | /* we know alt == 0, so this is an activation or a reset */ | 425 | /* we know alt == 0, so this is an activation or a reset */ |
| 426 | 426 | ||
| 427 | if (intf == acm->ctrl_id) { | 427 | if (intf == acm->ctrl_id) { |
| 428 | dev_vdbg(&cdev->gadget->dev, | 428 | if (acm->notify->enabled) { |
| 429 | "reset acm control interface %d\n", intf); | 429 | dev_vdbg(&cdev->gadget->dev, |
| 430 | usb_ep_disable(acm->notify); | 430 | "reset acm control interface %d\n", intf); |
| 431 | usb_ep_disable(acm->notify); | ||
| 432 | } | ||
| 431 | 433 | ||
| 432 | if (!acm->notify->desc) | 434 | if (!acm->notify->desc) |
| 433 | if (config_ep_by_speed(cdev->gadget, f, acm->notify)) | 435 | if (config_ep_by_speed(cdev->gadget, f, acm->notify)) |
| @@ -698,9 +698,9 @@ drop_out: · 697 unmodified lines | |||
| 698 | f_midi_drop_out_substreams(midi); | 698 | f_midi_drop_out_substreams(midi); |
| 699 | } | 699 | } |
| 700 | 700 | ||
| 701 | static void f_midi_in_tasklet(unsigned long data) | 701 | static void f_midi_in_tasklet(struct tasklet_struct *t) |
| 702 | { | 702 | { |
| 703 | struct f_midi *midi = (struct f_midi *) data; | 703 | struct f_midi *midi = from_tasklet(midi, t, tasklet); |
| 704 | f_midi_transmit(midi); | 704 | f_midi_transmit(midi); |
| 705 | } | 705 | } |
| 706 | 706 | ||
| @@ -875,7 +875,7 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f) · 168 unmodified lines | |||
| 875 | int status, n, jack = 1, i = 0, endpoint_descriptor_index = 0; | 875 | int status, n, jack = 1, i = 0, endpoint_descriptor_index = 0; |
| 876 | 876 | ||
| 877 | midi->gadget = cdev->gadget; | 877 | midi->gadget = cdev->gadget; |
| 878 | tasklet_init(&midi->tasklet, f_midi_in_tasklet, (unsigned long) midi); | 878 | tasklet_setup(&midi->tasklet, f_midi_in_tasklet); |
| 879 | status = f_midi_register_card(midi); | 879 | status = f_midi_register_card(midi); |
| 880 | if (status < 0) | 880 | if (status < 0) |
| 881 | goto fail_register; | 881 | goto fail_register; |
| @@ -85,8 +85,10 @@ static inline struct f_ncm *func_to_ncm(struct usb_function *f) · 84 unmodified lines | |||
| 85 | /* peak (theoretical) bulk transfer rate in bits-per-second */ | 85 | /* peak (theoretical) bulk transfer rate in bits-per-second */ |
| 86 | static inline unsigned ncm_bitrate(struct usb_gadget *g) | 86 | static inline unsigned ncm_bitrate(struct usb_gadget *g) |
| 87 | { | 87 | { |
| 88 | if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER) | 88 | if (gadget_is_superspeed(g) && g->speed >= USB_SPEED_SUPER_PLUS) |
| 89 | return 13 * 1024 * 8 * 1000 * 8; | 89 | return 4250000000U; |
| 90 | else if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER) | ||
| 91 | return 3750000000U; | ||
| 90 | else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) | 92 | else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) |
| 91 | return 13 * 512 * 8 * 1000 * 8; | 93 | return 13 * 512 * 8 * 1000 * 8; |
| 92 | else | 94 | else |
| @@ -376,7 +378,7 @@ static struct usb_ss_ep_comp_descriptor ss_ncm_bulk_comp_desc = { · 283 unmodified lines | |||
| 376 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | 378 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, |
| 377 | 379 | ||
| 378 | /* the following 2 values can be tweaked if necessary */ | 380 | /* the following 2 values can be tweaked if necessary */ |
| 379 | /* .bMaxBurst = 0, */ | 381 | .bMaxBurst = 15, |
| 380 | /* .bmAttributes = 0, */ | 382 | /* .bmAttributes = 0, */ |
| 381 | }; | 383 | }; |
| 382 | 384 | ||
| @@ -1534,7 +1536,7 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f) · 1151 unmodified lines | |||
| 1534 | fs_ncm_notify_desc.bEndpointAddress; | 1536 | fs_ncm_notify_desc.bEndpointAddress; |
| 1535 | 1537 | ||
| 1536 | status = usb_assign_descriptors(f, ncm_fs_function, ncm_hs_function, | 1538 | status = usb_assign_descriptors(f, ncm_fs_function, ncm_hs_function, |
| 1537 | ncm_ss_function, NULL); | 1539 | ncm_ss_function, ncm_ss_function); |
| 1538 | if (status) | 1540 | if (status) |
| 1539 | goto fail; | 1541 | goto fail; |
| 1540 | 1542 | ||
| @@ -31,6 +31,7 @@ · 30 unmodified lines | |||
| 31 | #include <linux/types.h> | 31 | #include <linux/types.h> |
| 32 | #include <linux/ctype.h> | 32 | #include <linux/ctype.h> |
| 33 | #include <linux/cdev.h> | 33 | #include <linux/cdev.h> |
| 34 | #include <linux/kref.h> | ||
| 34 | 35 | ||
| 35 | #include <asm/byteorder.h> | 36 | #include <asm/byteorder.h> |
| 36 | #include <linux/io.h> | 37 | #include <linux/io.h> |
| @@ -64,7 +65,7 @@ struct printer_dev { · 27 unmodified lines | |||
| 64 | struct usb_gadget *gadget; | 65 | struct usb_gadget *gadget; |
| 65 | s8 interface; | 66 | s8 interface; |
| 66 | struct usb_ep *in_ep, *out_ep; | 67 | struct usb_ep *in_ep, *out_ep; |
| 67 | 68 | struct kref kref; | |
| 68 | struct list_head rx_reqs; /* List of free RX structs */ | 69 | struct list_head rx_reqs; /* List of free RX structs */ |
| 69 | struct list_head rx_reqs_active; /* List of Active RX xfers */ | 70 | struct list_head rx_reqs_active; /* List of Active RX xfers */ |
| 70 | struct list_head rx_buffers; /* List of completed xfers */ | 71 | struct list_head rx_buffers; /* List of completed xfers */ |
| @@ -218,6 +219,13 @@ static inline struct usb_endpoint_descriptor *ep_desc(struct usb_gadget *gadget, · 147 unmodified lines | |||
| 218 | 219 | ||
| 219 | /*-------------------------------------------------------------------------*/ | 220 | /*-------------------------------------------------------------------------*/ |
| 220 | 221 | ||
| 222 | static void printer_dev_free(struct kref *kref) | ||
| 223 | { | ||
| 224 | struct printer_dev *dev = container_of(kref, struct printer_dev, kref); | ||
| 225 | |||
| 226 | kfree(dev); | ||
| 227 | } | ||
| 228 | |||
| 221 | static struct usb_request * | 229 | static struct usb_request * |
| 222 | printer_req_alloc(struct usb_ep *ep, unsigned len, gfp_t gfp_flags) | 230 | printer_req_alloc(struct usb_ep *ep, unsigned len, gfp_t gfp_flags) |
| 223 | { | 231 | { |
| @@ -353,6 +361,7 @@ printer_open(struct inode *inode, struct file *fd) · 129 unmodified lines | |||
| 353 | 361 | ||
| 354 | spin_unlock_irqrestore(&dev->lock, flags); | 362 | spin_unlock_irqrestore(&dev->lock, flags); |
| 355 | 363 | ||
| 364 | kref_get(&dev->kref); | ||
| 356 | DBG(dev, "printer_open returned %x\n", ret); | 365 | DBG(dev, "printer_open returned %x\n", ret); |
| 357 | return ret; | 366 | return ret; |
| 358 | } | 367 | } |
| @@ -370,6 +379,7 @@ printer_close(struct inode *inode, struct file *fd) · 11 unmodified lines | |||
| 370 | dev->printer_status &= ~PRINTER_SELECTED; | 379 | dev->printer_status &= ~PRINTER_SELECTED; |
| 371 | spin_unlock_irqrestore(&dev->lock, flags); | 380 | spin_unlock_irqrestore(&dev->lock, flags); |
| 372 | 381 | ||
| 382 | kref_put(&dev->kref, printer_dev_free); | ||
| 373 | DBG(dev, "printer_close\n"); | 383 | DBG(dev, "printer_close\n"); |
| 374 | 384 | ||
| 375 | return 0; | 385 | return 0; |
| @@ -1386,7 +1396,8 @@ static void gprinter_free(struct usb_function *f) · 1010 unmodified lines | |||
| 1386 | struct f_printer_opts *opts; | 1396 | struct f_printer_opts *opts; |
| 1387 | 1397 | ||
| 1388 | opts = container_of(f->fi, struct f_printer_opts, func_inst); | 1398 | opts = container_of(f->fi, struct f_printer_opts, func_inst); |
| 1389 | kfree(dev); | 1399 | |
| 1400 | kref_put(&dev->kref, printer_dev_free); | ||
| 1390 | mutex_lock(&opts->lock); | 1401 | mutex_lock(&opts->lock); |
| 1391 | --opts->refcnt; | 1402 | --opts->refcnt; |
| 1392 | mutex_unlock(&opts->lock); | 1403 | mutex_unlock(&opts->lock); |
| @@ -1455,6 +1466,7 @@ static struct usb_function *gprinter_alloc(struct usb_function_instance *fi) · 62 unmodified lines | |||
| 1455 | return ERR_PTR(-ENOMEM); | 1466 | return ERR_PTR(-ENOMEM); |
| 1456 | } | 1467 | } |
| 1457 | 1468 | ||
| 1469 | kref_init(&dev->kref); | ||
| 1458 | ++opts->refcnt; | 1470 | ++opts->refcnt; |
| 1459 | dev->minor = opts->minor; | 1471 | dev->minor = opts->minor; |
| 1460 | dev->pnp_string = opts->pnp_string; | 1472 | dev->pnp_string = opts->pnp_string; |
| @@ -392,12 +392,12 @@ static void bot_set_alt(struct f_uas *fu) · 391 unmodified lines | |||
| 392 | 392 | ||
| 393 | fu->flags = USBG_IS_BOT; | 393 | fu->flags = USBG_IS_BOT; |
| 394 | 394 | ||
| 395 | config_ep_by_speed(gadget, f, fu->ep_in); | 395 | config_ep_by_speed_and_alt(gadget, f, fu->ep_in, USB_G_ALT_INT_BBB); |
| 396 | ret = usb_ep_enable(fu->ep_in); | 396 | ret = usb_ep_enable(fu->ep_in); |
| 397 | if (ret) | 397 | if (ret) |
| 398 | goto err_b_in; | 398 | goto err_b_in; |
| 399 | 399 | ||
| 400 | config_ep_by_speed(gadget, f, fu->ep_out); | 400 | config_ep_by_speed_and_alt(gadget, f, fu->ep_out, USB_G_ALT_INT_BBB); |
| 401 | ret = usb_ep_enable(fu->ep_out); | 401 | ret = usb_ep_enable(fu->ep_out); |
| 402 | if (ret) | 402 | if (ret) |
| 403 | goto err_b_out; | 403 | goto err_b_out; |
| @@ -852,21 +852,21 @@ static void uasp_set_alt(struct f_uas *fu) · 448 unmodified lines | |||
| 852 | if (gadget->speed >= USB_SPEED_SUPER) | 852 | if (gadget->speed >= USB_SPEED_SUPER) |
| 853 | fu->flags |= USBG_USE_STREAMS; | 853 | fu->flags |= USBG_USE_STREAMS; |
| 854 | 854 | ||
| 855 | config_ep_by_speed(gadget, f, fu->ep_in); | 855 | config_ep_by_speed_and_alt(gadget, f, fu->ep_in, USB_G_ALT_INT_UAS); |
| 856 | ret = usb_ep_enable(fu->ep_in); | 856 | ret = usb_ep_enable(fu->ep_in); |
| 857 | if (ret) | 857 | if (ret) |
| 858 | goto err_b_in; | 858 | goto err_b_in; |
| 859 | 859 | ||
| 860 | config_ep_by_speed(gadget, f, fu->ep_out); | 860 | config_ep_by_speed_and_alt(gadget, f, fu->ep_out, USB_G_ALT_INT_UAS); |
| 861 | ret = usb_ep_enable(fu->ep_out); | 861 | ret = usb_ep_enable(fu->ep_out); |
| 862 | if (ret) | 862 | if (ret) |
| 863 | goto err_b_out; | 863 | goto err_b_out; |
| 864 | 864 | ||
| 865 | config_ep_by_speed(gadget, f, fu->ep_cmd); | 865 | config_ep_by_speed_and_alt(gadget, f, fu->ep_cmd, USB_G_ALT_INT_UAS); |
| 866 | ret = usb_ep_enable(fu->ep_cmd); | 866 | ret = usb_ep_enable(fu->ep_cmd); |
| 867 | if (ret) | 867 | if (ret) |
| 868 | goto err_cmd; | 868 | goto err_cmd; |
| 869 | config_ep_by_speed(gadget, f, fu->ep_status); | 869 | config_ep_by_speed_and_alt(gadget, f, fu->ep_status, USB_G_ALT_INT_UAS); |
| 870 | ret = usb_ep_enable(fu->ep_status); | 870 | ret = usb_ep_enable(fu->ep_status); |
| 871 | if (ret) | 871 | if (ret) |
| 872 | goto err_status; | 872 | goto err_status; |
| @@ -740,20 +740,20 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) · 739 unmodified lines | |||
| 740 | /* Initialise video. */ | 740 | /* Initialise video. */ |
| 741 | ret = uvcg_video_init(&uvc->video, uvc); | 741 | ret = uvcg_video_init(&uvc->video, uvc); |
| 742 | if (ret < 0) | 742 | if (ret < 0) |
| 743 | goto error; | 743 | goto v4l2_error; |
| 744 | 744 | ||
| 745 | /* Register a V4L2 device. */ | 745 | /* Register a V4L2 device. */ |
| 746 | ret = uvc_register_video(uvc); | 746 | ret = uvc_register_video(uvc); |
| 747 | if (ret < 0) { | 747 | if (ret < 0) { |
| 748 | uvcg_err(f, "failed to register video device\n"); | 748 | uvcg_err(f, "failed to register video device\n"); |
| 749 | goto error; | 749 | goto v4l2_error; |
| 750 | } | 750 | } |
| 751 | 751 | ||
| 752 | return 0; | 752 | return 0; |
| 753 | 753 | ||
| 754 | error: | 754 | v4l2_error: |
| 755 | v4l2_device_unregister(&uvc->v4l2_dev); | 755 | v4l2_device_unregister(&uvc->v4l2_dev); |
| 756 | 756 | error: | |
| 757 | if (uvc->control_req) | 757 | if (uvc->control_req) |
| 758 | usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); | 758 | usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); |
| 759 | kfree(uvc->control_buf); | 759 | kfree(uvc->control_buf); |
| @@ -93,7 +93,7 @@ struct eth_dev { · 92 unmodified lines | |||
| 93 | static inline int qlen(struct usb_gadget *gadget, unsigned qmult) | 93 | static inline int qlen(struct usb_gadget *gadget, unsigned qmult) |
| 94 | { | 94 | { |
| 95 | if (gadget_is_dualspeed(gadget) && (gadget->speed == USB_SPEED_HIGH || | 95 | if (gadget_is_dualspeed(gadget) && (gadget->speed == USB_SPEED_HIGH || |
| 96 | gadget->speed == USB_SPEED_SUPER)) | 96 | gadget->speed >= USB_SPEED_SUPER)) |
| 97 | return qmult * DEFAULT_QLEN; | 97 | return qmult * DEFAULT_QLEN; |
| 98 | else | 98 | else |
| 99 | return DEFAULT_QLEN; | 99 | return DEFAULT_QLEN; |
| @@ -1391,6 +1391,7 @@ void gserial_disconnect(struct gserial *gser) · 1390 unmodified lines | |||
| 1391 | if (port->port.tty) | 1391 | if (port->port.tty) |
| 1392 | tty_hangup(port->port.tty); | 1392 | tty_hangup(port->port.tty); |
| 1393 | } | 1393 | } |
| 1394 | port->suspended = false; | ||
| 1394 | spin_unlock_irqrestore(&port->port_lock, flags); | 1395 | spin_unlock_irqrestore(&port->port_lock, flags); |
| 1395 | 1396 | ||
| 1396 | /* disable endpoints, aborting down any active I/O */ | 1397 | /* disable endpoints, aborting down any active I/O */ |
| @@ -135,13 +135,9 @@ static irqreturn_t ast_vhub_irq(int irq, void *data) · 134 unmodified lines | |||
| 135 | 135 | ||
| 136 | /* Handle device interrupts */ | 136 | /* Handle device interrupts */ |
| 137 | if (istat & vhub->port_irq_mask) { | 137 | if (istat & vhub->port_irq_mask) { |
| 138 | unsigned long bitmap = istat; | 138 | for (i = 0; i < vhub->max_ports; i++) { |
| 139 | int offset = VHUB_IRQ_DEV1_BIT; | 139 | if (istat & VHUB_DEV_IRQ(i)) |
| 140 | int size = VHUB_IRQ_DEV1_BIT + vhub->max_ports; | 140 | ast_vhub_dev_irq(&vhub->ports[i].dev); |
| 141 | |||
| 142 | for_each_set_bit_from(offset, &bitmap, size) { | ||
| 143 | i = offset - VHUB_IRQ_DEV1_BIT; | ||
| 144 | ast_vhub_dev_irq(&vhub->ports[i].dev); | ||
| 145 | } | 141 | } |
| 146 | } | 142 | } |
| 147 | 143 | ||
| @@ -67,6 +67,9 @@ · 66 unmodified lines | |||
| 67 | #define VHUB_IRQ_HUB_EP0_SETUP (1 << 0) | 67 | #define VHUB_IRQ_HUB_EP0_SETUP (1 << 0) |
| 68 | #define VHUB_IRQ_ACK_ALL 0x1ff | 68 | #define VHUB_IRQ_ACK_ALL 0x1ff |
| 69 | 69 | ||
| 70 | /* Downstream device IRQ mask. */ | ||
| 71 | #define VHUB_DEV_IRQ(n) (VHUB_IRQ_DEVICE1 << (n)) | ||
| 72 | |||
| 70 | /* SW reset reg */ | 73 | /* SW reset reg */ |
| 71 | #define VHUB_SW_RESET_EP_POOL (1 << 9) | 74 | #define VHUB_SW_RESET_EP_POOL (1 << 9) |
| 72 | #define VHUB_SW_RESET_DMA_CONTROLLER (1 << 8) | 75 | #define VHUB_SW_RESET_DMA_CONTROLLER (1 << 8) |
| @@ -1056,16 +1056,19 @@ found_ep: · 1055 unmodified lines | |||
| 1056 | 1056 | ||
| 1057 | switch (usb_endpoint_type(desc)) { | 1057 | switch (usb_endpoint_type(desc)) { |
| 1058 | case USB_ENDPOINT_XFER_CONTROL: | 1058 | case USB_ENDPOINT_XFER_CONTROL: |
| 1059 | ep->nr_banks = 1; | ||
| 1059 | break; | 1060 | break; |
| 1060 | 1061 | ||
| 1061 | case USB_ENDPOINT_XFER_ISOC: | 1062 | case USB_ENDPOINT_XFER_ISOC: |
| 1062 | ep->fifo_size = 1024; | 1063 | ep->fifo_size = 1024; |
| 1063 | ep->nr_banks = 2; | 1064 | if (ep->udc->ep_prealloc) |
| 1065 | ep->nr_banks = 2; | ||
| 1064 | break; | 1066 | break; |
| 1065 | 1067 | ||
| 1066 | case USB_ENDPOINT_XFER_BULK: | 1068 | case USB_ENDPOINT_XFER_BULK: |
| 1067 | ep->fifo_size = 512; | 1069 | ep->fifo_size = 512; |
| 1068 | ep->nr_banks = 1; | 1070 | if (ep->udc->ep_prealloc) |
| 1071 | ep->nr_banks = 1; | ||
| 1069 | break; | 1072 | break; |
| 1070 | 1073 | ||
| 1071 | case USB_ENDPOINT_XFER_INT: | 1074 | case USB_ENDPOINT_XFER_INT: |
| @@ -1075,7 +1078,8 @@ found_ep: · 3 unmodified lines | |||
| 1075 | else | 1078 | else |
| 1076 | ep->fifo_size = | 1079 | ep->fifo_size = |
| 1077 | roundup_pow_of_two(le16_to_cpu(desc->wMaxPacketSize)); | 1080 | roundup_pow_of_two(le16_to_cpu(desc->wMaxPacketSize)); |
| 1078 | ep->nr_banks = 1; | 1081 | if (ep->udc->ep_prealloc) |
| 1082 | ep->nr_banks = 1; | ||
| 1079 | break; | 1083 | break; |
| 1080 | } | 1084 | } |
| 1081 | 1085 | ||
| @@ -1091,8 +1095,6 @@ found_ep: · 9 unmodified lines | |||
| 1091 | USBA_BF(EPT_SIZE, fls(ep->fifo_size - 1) - 3); | 1095 | USBA_BF(EPT_SIZE, fls(ep->fifo_size - 1) - 3); |
| 1092 | 1096 | ||
| 1093 | ep->ept_cfg |= USBA_BF(BK_NUMBER, ep->nr_banks); | 1097 | ep->ept_cfg |= USBA_BF(BK_NUMBER, ep->nr_banks); |
| 1094 | |||
| 1095 | ep->udc->configured_ep++; | ||
| 1096 | } | 1098 | } |
| 1097 | 1099 | ||
| 1098 | return _ep; | 1100 | return _ep; |
| @@ -1786,7 +1788,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) · 687 unmodified lines | |||
| 1786 | 1788 | ||
| 1787 | if (status & USBA_END_OF_RESET) { | 1789 | if (status & USBA_END_OF_RESET) { |
| 1788 | struct usba_ep *ep0, *ep; | 1790 | struct usba_ep *ep0, *ep; |
| 1789 | int i, n; | 1791 | int i; |
| 1790 | 1792 | ||
| 1791 | usba_writel(udc, INT_CLR, | 1793 | usba_writel(udc, INT_CLR, |
| 1792 | USBA_END_OF_RESET|USBA_END_OF_RESUME | 1794 | USBA_END_OF_RESET|USBA_END_OF_RESUME |
| @@ -1834,13 +1836,14 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) · 41 unmodified lines | |||
| 1834 | "ODD: EP0 configuration is invalid!\n"); | 1836 | "ODD: EP0 configuration is invalid!\n"); |
| 1835 | 1837 | ||
| 1836 | /* Preallocate other endpoints */ | 1838 | /* Preallocate other endpoints */ |
| 1837 | n = fifo_mode ? udc->num_ep : udc->configured_ep; | 1839 | for (i = 1; i < udc->num_ep; i++) { |
| 1838 | for (i = 1; i < n; i++) { | ||
| 1839 | ep = &udc->usba_ep[i]; | 1840 | ep = &udc->usba_ep[i]; |
| 1840 | usba_ep_writel(ep, CFG, ep->ept_cfg); | 1841 | if (ep->ep.claimed) { |
| 1841 | if (!(usba_ep_readl(ep, CFG) & USBA_EPT_MAPPED)) | 1842 | usba_ep_writel(ep, CFG, ep->ept_cfg); |
| 1842 | dev_err(&udc->pdev->dev, | 1843 | if (!(usba_ep_readl(ep, CFG) & USBA_EPT_MAPPED)) |
| 1843 | "ODD: EP%d configuration is invalid!\n", i); | 1844 | dev_err(&udc->pdev->dev, |
| 1845 | "ODD: EP%d configuration is invalid!\n", i); | ||
| 1846 | } | ||
| 1844 | } | 1847 | } |
| 1845 | } | 1848 | } |
| 1846 | 1849 | ||
| @@ -2025,9 +2028,6 @@ static int atmel_usba_stop(struct usb_gadget *gadget) · 178 unmodified lines | |||
| 2025 | if (udc->vbus_pin) | 2028 | if (udc->vbus_pin) |
| 2026 | disable_irq(gpiod_to_irq(udc->vbus_pin)); | 2029 | disable_irq(gpiod_to_irq(udc->vbus_pin)); |
| 2027 | 2030 | ||
| 2028 | if (fifo_mode == 0) | ||
| 2029 | udc->configured_ep = 1; | ||
| 2030 | |||
| 2031 | udc->suspended = false; | 2031 | udc->suspended = false; |
| 2032 | usba_stop(udc); | 2032 | usba_stop(udc); |
| 2033 | 2033 | ||
| @@ -2090,33 +2090,51 @@ static const struct usba_udc_config udc_at91sam9rl_cfg = { · 56 unmodified lines | |||
| 2090 | .errata = &at91sam9rl_errata, | 2090 | .errata = &at91sam9rl_errata, |
| 2091 | .config = ep_config_sam9, | 2091 | .config = ep_config_sam9, |
| 2092 | .num_ep = ARRAY_SIZE(ep_config_sam9), | 2092 | .num_ep = ARRAY_SIZE(ep_config_sam9), |
| 2093 | .ep_prealloc = true, | ||
| 2093 | }; | 2094 | }; |
| 2094 | 2095 | ||
| 2095 | static const struct usba_udc_config udc_at91sam9g45_cfg = { | 2096 | static const struct usba_udc_config udc_at91sam9g45_cfg = { |
| 2096 | .errata = &at91sam9g45_errata, | 2097 | .errata = &at91sam9g45_errata, |
| 2097 | .config = ep_config_sam9, | 2098 | .config = ep_config_sam9, |
| 2098 | .num_ep = ARRAY_SIZE(ep_config_sam9), | 2099 | .num_ep = ARRAY_SIZE(ep_config_sam9), |
| 2100 | .ep_prealloc = true, | ||
| 2099 | }; | 2101 | }; |
| 2100 | 2102 | ||
| 2101 | static const struct usba_udc_config udc_sama5d3_cfg = { | 2103 | static const struct usba_udc_config udc_sama5d3_cfg = { |
| 2102 | .config = ep_config_sama5, | 2104 | .config = ep_config_sama5, |
| 2103 | .num_ep = ARRAY_SIZE(ep_config_sama5), | 2105 | .num_ep = ARRAY_SIZE(ep_config_sama5), |
| 2106 | .ep_prealloc = true, | ||
| 2107 | }; | ||
| 2108 | |||
| 2109 | static const struct usba_udc_config udc_sam9x60_cfg = { | ||
| 2110 | .num_ep = ARRAY_SIZE(ep_config_sam9), | ||
| 2111 | .config = ep_config_sam9, | ||
| 2112 | .ep_prealloc = false, | ||
| 2104 | }; | 2113 | }; |
| 2105 | 2114 | ||
| 2106 | static const struct of_device_id atmel_udc_dt_ids[] = { | 2115 | static const struct of_device_id atmel_udc_dt_ids[] = { |
| 2107 | { .compatible = "atmel,at91sam9rl-udc", .data = &udc_at91sam9rl_cfg }, | 2116 | { .compatible = "atmel,at91sam9rl-udc", .data = &udc_at91sam9rl_cfg }, |
| 2108 | { .compatible = "atmel,at91sam9g45-udc", .data = &udc_at91sam9g45_cfg }, | 2117 | { .compatible = "atmel,at91sam9g45-udc", .data = &udc_at91sam9g45_cfg }, |
| 2109 | { .compatible = "atmel,sama5d3-udc", .data = &udc_sama5d3_cfg }, | 2118 | { .compatible = "atmel,sama5d3-udc", .data = &udc_sama5d3_cfg }, |
| 2119 | { .compatible = "microchip,sam9x60-udc", .data = &udc_sam9x60_cfg }, | ||
| 2110 | { /* sentinel */ } | 2120 | { /* sentinel */ } |
| 2111 | }; | 2121 | }; |
| 2112 | 2122 | ||
| 2113 | MODULE_DEVICE_TABLE(of, atmel_udc_dt_ids); | 2123 | MODULE_DEVICE_TABLE(of, atmel_udc_dt_ids); |
| 2114 | 2124 | ||
| 2125 | static const struct of_device_id atmel_pmc_dt_ids[] = { | ||
| 2126 | { .compatible = "atmel,at91sam9g45-pmc" }, | ||
| 2127 | { .compatible = "atmel,at91sam9rl-pmc" }, | ||
| 2128 | { .compatible = "atmel,at91sam9x5-pmc" }, | ||
| 2129 | { /* sentinel */ } | ||
| 2130 | }; | ||
| 2131 | |||
| 2115 | static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, | 2132 | static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, |
| 2116 | struct usba_udc *udc) | 2133 | struct usba_udc *udc) |
| 2117 | { | 2134 | { |
| 2118 | struct device_node *np = pdev->dev.of_node; | 2135 | struct device_node *np = pdev->dev.of_node; |
| 2119 | const struct of_device_id *match; | 2136 | const struct of_device_id *match; |
| 2137 | struct device_node *pp; | ||
| 2120 | int i, ret; | 2138 | int i, ret; |
| 2121 | struct usba_ep *eps, *ep; | 2139 | struct usba_ep *eps, *ep; |
| 2122 | const struct usba_udc_config *udc_config; | 2140 | const struct usba_udc_config *udc_config; |
| @@ -2126,14 +2144,19 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, · 3 unmodified lines | |||
| 2126 | return ERR_PTR(-EINVAL); | 2144 | return ERR_PTR(-EINVAL); |
| 2127 | 2145 | ||
| 2128 | udc_config = match->data; | 2146 | udc_config = match->data; |
| 2147 | udc->ep_prealloc = udc_config->ep_prealloc; | ||
| 2129 | udc->errata = udc_config->errata; | 2148 | udc->errata = udc_config->errata; |
| 2130 | udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9g45-pmc"); | 2149 | if (udc->errata) { |
| 2131 | if (IS_ERR(udc->pmc)) | 2150 | pp = of_find_matching_node_and_match(NULL, atmel_pmc_dt_ids, |
| 2132 | udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9rl-pmc"); | 2151 | NULL); |
| 2133 | if (IS_ERR(udc->pmc)) | 2152 | if (!pp) |
| 2134 | udc->pmc = syscon_regmap_lookup_by_compatible("atmel,at91sam9x5-pmc"); | 2153 | return ERR_PTR(-ENODEV); |
| 2135 | if (udc->errata && IS_ERR(udc->pmc)) | 2154 | |
| 2136 | return ERR_CAST(udc->pmc); | 2155 | udc->pmc = syscon_node_to_regmap(pp); |
| 2156 | of_node_put(pp); | ||
| 2157 | if (IS_ERR(udc->pmc)) | ||
| 2158 | return ERR_CAST(udc->pmc); | ||
| 2159 | } | ||
| 2137 | 2160 | ||
| 2138 | udc->num_ep = 0; | 2161 | udc->num_ep = 0; |
| 2139 | 2162 | ||
| @@ -2142,7 +2165,6 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, · 2 unmodified lines | |||
| 2142 | 2165 | ||
| 2143 | if (fifo_mode == 0) { | 2166 | if (fifo_mode == 0) { |
| 2144 | udc->num_ep = udc_config->num_ep; | 2167 | udc->num_ep = udc_config->num_ep; |
| 2145 | udc->configured_ep = 1; | ||
| 2146 | } else { | 2168 | } else { |
| 2147 | udc->num_ep = usba_config_fifo_table(udc); | 2169 | udc->num_ep = usba_config_fifo_table(udc); |
| 2148 | } | 2170 | } |
| @@ -317,6 +317,7 @@ struct usba_udc_config { · 316 unmodified lines | |||
| 317 | const struct usba_udc_errata *errata; | 317 | const struct usba_udc_errata *errata; |
| 318 | const struct usba_ep_config *config; | 318 | const struct usba_ep_config *config; |
| 319 | const int num_ep; | 319 | const int num_ep; |
| 320 | const bool ep_prealloc; | ||
| 320 | }; | 321 | }; |
| 321 | 322 | ||
| 322 | struct usba_udc { | 323 | struct usba_udc { |
| @@ -336,7 +337,6 @@ struct usba_udc { · 13 unmodified lines | |||
| 336 | int irq; | 337 | int irq; |
| 337 | struct gpio_desc *vbus_pin; | 338 | struct gpio_desc *vbus_pin; |
| 338 | int num_ep; | 339 | int num_ep; |
| 339 | int configured_ep; | ||
| 340 | struct usba_fifo_cfg *fifo_cfg; | 340 | struct usba_fifo_cfg *fifo_cfg; |
| 341 | struct clk *pclk; | 341 | struct clk *pclk; |
| 342 | struct clk *hclk; | 342 | struct clk *hclk; |
| @@ -344,6 +344,7 @@ struct usba_udc { · 1 unmodified line | |||
| 344 | bool bias_pulse_needed; | 344 | bool bias_pulse_needed; |
| 345 | bool clocked; | 345 | bool clocked; |
| 346 | bool suspended; | 346 | bool suspended; |
| 347 | bool ep_prealloc; | ||
| 347 | 348 | ||
| 348 | u16 devstatus; | 349 | u16 devstatus; |
| 349 | 350 | ||
| @@ -26,6 +26,7 @@ · 25 unmodified lines | |||
| 26 | #include <linux/seq_file.h> | 26 | #include <linux/seq_file.h> |
| 27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
| 28 | #include <linux/timer.h> | 28 | #include <linux/timer.h> |
| 29 | #include <linux/usb.h> | ||
| 29 | #include <linux/usb/ch9.h> | 30 | #include <linux/usb/ch9.h> |
| 30 | #include <linux/usb/gadget.h> | 31 | #include <linux/usb/gadget.h> |
| 31 | #include <linux/workqueue.h> | 32 | #include <linux/workqueue.h> |
| @@ -484,7 +484,7 @@ static void bdc_phy_exit(struct bdc *bdc) · 483 unmodified lines | |||
| 484 | static int bdc_probe(struct platform_device *pdev) | 484 | static int bdc_probe(struct platform_device *pdev) |
| 485 | { | 485 | { |
| 486 | struct bdc *bdc; | 486 | struct bdc *bdc; |
| 487 | int ret = -ENOMEM; | 487 | int ret; |
| 488 | int irq; | 488 | int irq; |
| 489 | u32 temp; | 489 | u32 temp; |
| 490 | struct device *dev = &pdev->dev; | 490 | struct device *dev = &pdev->dev; |
| @@ -510,10 +510,9 @@ static int bdc_probe(struct platform_device *pdev) · 19 unmodified lines | |||
| 510 | bdc->clk = clk; | 510 | bdc->clk = clk; |
| 511 | 511 | ||
| 512 | bdc->regs = devm_platform_ioremap_resource(pdev, 0); | 512 | bdc->regs = devm_platform_ioremap_resource(pdev, 0); |
| 513 | if (IS_ERR(bdc->regs)) { | 513 | if (IS_ERR(bdc->regs)) |
| 514 | dev_err(dev, "ioremap error\n"); | 514 | return PTR_ERR(bdc->regs); |
| 515 | return -ENOMEM; | 515 | |
| 516 | } | ||
| 517 | irq = platform_get_irq(pdev, 0); | 516 | irq = platform_get_irq(pdev, 0); |
| 518 | if (irq < 0) | 517 | if (irq < 0) |
| 519 | return irq; | 518 | return irq; |
| @@ -715,6 +715,9 @@ int usb_gadget_disconnect(struct usb_gadget *gadget) · 714 unmodified lines | |||
| 715 | goto out; | 715 | goto out; |
| 716 | } | 716 | } |
| 717 | 717 | ||
| 718 | if (!gadget->connected) | ||
| 719 | goto out; | ||
| 720 | |||
| 718 | if (gadget->deactivated) { | 721 | if (gadget->deactivated) { |
| 719 | /* | 722 | /* |
| 720 | * If gadget is deactivated we only save new state. | 723 | * If gadget is deactivated we only save new state. |
| @@ -1164,21 +1167,18 @@ static int check_pending_gadget_drivers(struct usb_udc *udc) · 443 unmodified lines | |||
| 1164 | } | 1167 | } |
| 1165 | 1168 | ||
| 1166 | /** | 1169 | /** |
| 1167 | * usb_add_gadget_udc_release - adds a new gadget to the udc class driver list | 1170 | * usb_initialize_gadget - initialize a gadget and its embedded struct device |
| 1168 | * @parent: the parent device to this udc. Usually the controller driver's | 1171 | * @parent: the parent device to this udc. Usually the controller driver's |
| 1169 | * device. | 1172 | * device. |
| 1170 | * @gadget: the gadget to be added to the list. | 1173 | * @gadget: the gadget to be initialized. |
| 1171 | * @release: a gadget release function. | 1174 | * @release: a gadget release function. |
| 1172 | * | 1175 | * |
| 1173 | * Returns zero on success, negative errno otherwise. | 1176 | * Returns zero on success, negative errno otherwise. |
| 1174 | * Calls the gadget release function in the latter case. | 1177 | * Calls the gadget release function in the latter case. |
| 1175 | */ | 1178 | */ |
| 1176 | int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget, | 1179 | void usb_initialize_gadget(struct device *parent, struct usb_gadget *gadget, |
| 1177 | void (*release)(struct device *dev)) | 1180 | void (*release)(struct device *dev)) |
| 1178 | { | 1181 | { |
| 1179 | struct usb_udc *udc; | ||
| 1180 | int ret = -ENOMEM; | ||
| 1181 | |||
| 1182 | dev_set_name(&gadget->dev, "gadget"); | 1182 | dev_set_name(&gadget->dev, "gadget"); |
| 1183 | INIT_WORK(&gadget->work, usb_gadget_state_work); | 1183 | INIT_WORK(&gadget->work, usb_gadget_state_work); |
| 1184 | gadget->dev.parent = parent; | 1184 | gadget->dev.parent = parent; |
| @@ -1189,17 +1189,32 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget, · 4 unmodified lines | |||
| 1189 | gadget->dev.release = usb_udc_nop_release; | 1189 | gadget->dev.release = usb_udc_nop_release; |
| 1190 | 1190 | ||
| 1191 | device_initialize(&gadget->dev); | 1191 | device_initialize(&gadget->dev); |
| 1192 | } | ||
| 1193 | EXPORT_SYMBOL_GPL(usb_initialize_gadget); | ||
| 1194 | |||
| 1195 | /** | ||
| 1196 | * usb_add_gadget - adds a new gadget to the udc class driver list | ||
| 1197 | * @gadget: the gadget to be added to the list. | ||
| 1198 | * | ||
| 1199 | * Returns zero on success, negative errno otherwise. | ||
| 1200 | * Does not do a final usb_put_gadget() if an error occurs. | ||
| 1201 | */ | ||
| 1202 | int usb_add_gadget(struct usb_gadget *gadget) | ||
| 1203 | { | ||
| 1204 | struct usb_udc *udc; | ||
| 1205 | int ret = -ENOMEM; | ||
| 1192 | 1206 | ||
| 1193 | udc = kzalloc(sizeof(*udc), GFP_KERNEL); | 1207 | udc = kzalloc(sizeof(*udc), GFP_KERNEL); |
| 1194 | if (!udc) | 1208 | if (!udc) |
| 1195 | goto err_put_gadget; | 1209 | goto error; |
| 1196 | 1210 | ||
| 1197 | device_initialize(&udc->dev); | 1211 | device_initialize(&udc->dev); |
| 1198 | udc->dev.release = usb_udc_release; | 1212 | udc->dev.release = usb_udc_release; |
| 1199 | udc->dev.class = udc_class; | 1213 | udc->dev.class = udc_class; |
| 1200 | udc->dev.groups = usb_udc_attr_groups; | 1214 | udc->dev.groups = usb_udc_attr_groups; |
| 1201 | udc->dev.parent = parent; | 1215 | udc->dev.parent = gadget->dev.parent; |
| 1202 | ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj)); | 1216 | ret = dev_set_name(&udc->dev, "%s", |
| 1217 | kobject_name(&gadget->dev.parent->kobj)); | ||
| 1203 | if (ret) | 1218 | if (ret) |
| 1204 | goto err_put_udc; | 1219 | goto err_put_udc; |
| 1205 | 1220 | ||
| @@ -1242,8 +1257,30 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget, · 36 unmodified lines | |||
| 1242 | err_put_udc: | 1257 | err_put_udc: |
| 1243 | put_device(&udc->dev); | 1258 | put_device(&udc->dev); |
| 1244 | 1259 | ||
| 1245 | err_put_gadget: | 1260 | error: |
| 1246 | put_device(&gadget->dev); | 1261 | return ret; |
| 1262 | } | ||
| 1263 | EXPORT_SYMBOL_GPL(usb_add_gadget); | ||
| 1264 | |||
| 1265 | /** | ||
| 1266 | * usb_add_gadget_udc_release - adds a new gadget to the udc class driver list | ||
| 1267 | * @parent: the parent device to this udc. Usually the controller driver's | ||
| 1268 | * device. | ||
| 1269 | * @gadget: the gadget to be added to the list. | ||
| 1270 | * @release: a gadget release function. | ||
| 1271 | * | ||
| 1272 | * Returns zero on success, negative errno otherwise. | ||
| 1273 | * Calls the gadget release function in the latter case. | ||
| 1274 | */ | ||
| 1275 | int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget, | ||
| 1276 | void (*release)(struct device *dev)) | ||
| 1277 | { | ||
| 1278 | int ret; | ||
| 1279 | |||
| 1280 | usb_initialize_gadget(parent, gadget, release); | ||
| 1281 | ret = usb_add_gadget(gadget); | ||
| 1282 | if (ret) | ||
| 1283 | usb_put_gadget(gadget); | ||
| 1247 | return ret; | 1284 | return ret; |
| 1248 | } | 1285 | } |
| 1249 | EXPORT_SYMBOL_GPL(usb_add_gadget_udc_release); | 1286 | EXPORT_SYMBOL_GPL(usb_add_gadget_udc_release); |
| @@ -1311,13 +1348,14 @@ static void usb_gadget_remove_driver(struct usb_udc *udc) · 61 unmodified lines | |||
| 1311 | } | 1348 | } |
| 1312 | 1349 | ||
| 1313 | /** | 1350 | /** |
| 1314 | * usb_del_gadget_udc - deletes @udc from udc_list | 1351 | * usb_del_gadget - deletes @udc from udc_list |
| 1315 | * @gadget: the gadget to be removed. | 1352 | * @gadget: the gadget to be removed. |
| 1316 | * | 1353 | * |
| 1317 | * This, will call usb_gadget_unregister_driver() if | 1354 | * This will call usb_gadget_unregister_driver() if |
| 1318 | * the @udc is still busy. | 1355 | * the @udc is still busy. |
| 1356 | * It will not do a final usb_put_gadget(). | ||
| 1319 | */ | 1357 | */ |
| 1320 | void usb_del_gadget_udc(struct usb_gadget *gadget) | 1358 | void usb_del_gadget(struct usb_gadget *gadget) |
| 1321 | { | 1359 | { |
| 1322 | struct usb_udc *udc = gadget->udc; | 1360 | struct usb_udc *udc = gadget->udc; |
| 1323 | 1361 | ||
| @@ -1340,8 +1378,20 @@ void usb_del_gadget_udc(struct usb_gadget *gadget) · 16 unmodified lines | |||
| 1340 | kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE); | 1378 | kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE); |
| 1341 | flush_work(&gadget->work); | 1379 | flush_work(&gadget->work); |
| 1342 | device_unregister(&udc->dev); | 1380 | device_unregister(&udc->dev); |
| 1343 | device_unregister(&gadget->dev); | 1381 | device_del(&gadget->dev); |
| 1344 | memset(&gadget->dev, 0x00, sizeof(gadget->dev)); | 1382 | } |
| 1383 | EXPORT_SYMBOL_GPL(usb_del_gadget); | ||
| 1384 | |||
| 1385 | /** | ||
| 1386 | * usb_del_gadget_udc - deletes @udc from udc_list | ||
| 1387 | * @gadget: the gadget to be removed. | ||
| 1388 | * | ||
| 1389 | * Calls usb_del_gadget() and does a final usb_put_gadget(). | ||
| 1390 | */ | ||
| 1391 | void usb_del_gadget_udc(struct usb_gadget *gadget) | ||
| 1392 | { | ||
| 1393 | usb_del_gadget(gadget); | ||
| 1394 | usb_put_gadget(gadget); | ||
| 1345 | } | 1395 | } |
| 1346 | EXPORT_SYMBOL_GPL(usb_del_gadget_udc); | 1396 | EXPORT_SYMBOL_GPL(usb_del_gadget_udc); |
| 1347 | 1397 | ||
| @@ -923,9 +923,9 @@ static int qe_ep_rxframe_handle(struct qe_ep *ep) · 922 unmodified lines | |||
| 923 | return 0; | 923 | return 0; |
| 924 | } | 924 | } |
| 925 | 925 | ||
| 926 | static void ep_rx_tasklet(unsigned long data) | 926 | static void ep_rx_tasklet(struct tasklet_struct *t) |
| 927 | { | 927 | { |
| 928 | struct qe_udc *udc = (struct qe_udc *)data; | 928 | struct qe_udc *udc = from_tasklet(udc, t, rx_tasklet); |
| 929 | struct qe_ep *ep; | 929 | struct qe_ep *ep; |
| 930 | struct qe_frame *pframe; | 930 | struct qe_frame *pframe; |
| 931 | struct qe_bd __iomem *bd; | 931 | struct qe_bd __iomem *bd; |
| @@ -2553,8 +2553,7 @@ static int qe_udc_probe(struct platform_device *ofdev) · 1621 unmodified lines | |||
| 2553 | DMA_TO_DEVICE); | 2553 | DMA_TO_DEVICE); |
| 2554 | } | 2554 | } |
| 2555 | 2555 | ||
| 2556 | tasklet_init(&udc->rx_tasklet, ep_rx_tasklet, | 2556 | tasklet_setup(&udc->rx_tasklet, ep_rx_tasklet); |
| 2557 | (unsigned long)udc); | ||
| 2558 | /* request irq and disable DR */ | 2557 | /* request irq and disable DR */ |
| 2559 | udc->usb_irq = irq_of_parse_and_map(np, 0); | 2558 | udc->usb_irq = irq_of_parse_and_map(np, 0); |
| 2560 | if (!udc->usb_irq) { | 2559 | if (!udc->usb_irq) { |
| @@ -2061,7 +2061,7 @@ static int fsl_proc_read(struct seq_file *m, void *v) · 2060 unmodified lines | |||
| 2061 | "Sleep Enable: %d SOF Received Enable: %d " | 2061 | "Sleep Enable: %d SOF Received Enable: %d " |
| 2062 | "Reset Enable: %d\n" | 2062 | "Reset Enable: %d\n" |
| 2063 | "System Error Enable: %d " | 2063 | "System Error Enable: %d " |
| 2064 | "Port Change Dectected Enable: %d\n" | 2064 | "Port Change Detected Enable: %d\n" |
| 2065 | "USB Error Intr Enable: %d USB Intr Enable: %d\n\n", | 2065 | "USB Error Intr Enable: %d USB Intr Enable: %d\n\n", |
| 2066 | (tmp_reg & USB_INTR_DEVICE_SUSPEND) ? 1 : 0, | 2066 | (tmp_reg & USB_INTR_DEVICE_SUSPEND) ? 1 : 0, |
| 2067 | (tmp_reg & USB_INTR_SOF_EN) ? 1 : 0, | 2067 | (tmp_reg & USB_INTR_SOF_EN) ? 1 : 0, |
| @@ -2439,11 +2439,12 @@ static int fsl_udc_probe(struct platform_device *pdev) · 371 unmodified lines | |||
| 2439 | /* DEN is bidirectional ep number, max_ep doubles the number */ | 2439 | /* DEN is bidirectional ep number, max_ep doubles the number */ |
| 2440 | udc_controller->max_ep = (dccparams & DCCPARAMS_DEN_MASK) * 2; | 2440 | udc_controller->max_ep = (dccparams & DCCPARAMS_DEN_MASK) * 2; |
| 2441 | 2441 | ||
| 2442 | udc_controller->irq = platform_get_irq(pdev, 0); | 2442 | ret = platform_get_irq(pdev, 0); |
| 2443 | if (udc_controller->irq <= 0) { | 2443 | if (ret <= 0) { |
| 2444 | ret = udc_controller->irq ? : -ENODEV; | 2444 | ret = ret ? : -ENODEV; |
| 2445 | goto err_iounmap; | 2445 | goto err_iounmap; |
| 2446 | } | 2446 | } |
| 2447 | udc_controller->irq = ret; | ||
| 2447 | 2448 | ||
| 2448 | ret = request_irq(udc_controller->irq, fsl_udc_irq, IRQF_SHARED, | 2449 | ret = request_irq(udc_controller->irq, fsl_udc_irq, IRQF_SHARED, |
| 2449 | driver_name, udc_controller); | 2450 | driver_name, udc_controller); |
| @@ -495,7 +495,7 @@ static void proc_ep_show(struct seq_file *s, struct lpc32xx_ep *ep) · 494 unmodified lines | |||
| 495 | } | 495 | } |
| 496 | } | 496 | } |
| 497 | 497 | ||
| 498 | static int proc_udc_show(struct seq_file *s, void *unused) | 498 | static int udc_show(struct seq_file *s, void *unused) |
| 499 | { | 499 | { |
| 500 | struct lpc32xx_udc *udc = s->private; | 500 | struct lpc32xx_udc *udc = s->private; |
| 501 | struct lpc32xx_ep *ep; | 501 | struct lpc32xx_ep *ep; |
| @@ -524,22 +524,11 @@ static int proc_udc_show(struct seq_file *s, void *unused) · 22 unmodified lines | |||
| 524 | return 0; | 524 | return 0; |
| 525 | } | 525 | } |
| 526 | 526 | ||
| 527 | static int proc_udc_open(struct inode *inode, struct file *file) | 527 | DEFINE_SHOW_ATTRIBUTE(udc); |
| 528 | { | ||
| 529 | return single_open(file, proc_udc_show, PDE_DATA(inode)); | ||
| 530 | } | ||
| 531 | |||
| 532 | static const struct file_operations proc_ops = { | ||
| 533 | .owner = THIS_MODULE, | ||
| 534 | .open = proc_udc_open, | ||
| 535 | .read = seq_read, | ||
| 536 | .llseek = seq_lseek, | ||
| 537 | .release = single_release, | ||
| 538 | }; | ||
| 539 | 528 | ||
| 540 | static void create_debug_file(struct lpc32xx_udc *udc) | 529 | static void create_debug_file(struct lpc32xx_udc *udc) |
| 541 | { | 530 | { |
| 542 | udc->pde = debugfs_create_file(debug_filename, 0, NULL, udc, &proc_ops); | 531 | udc->pde = debugfs_create_file(debug_filename, 0, NULL, udc, &udc_fops); |
| 543 | } | 532 | } |
| 544 | 533 | ||
| 545 | static void remove_debug_file(struct lpc32xx_udc *udc) | 534 | static void remove_debug_file(struct lpc32xx_udc *udc) |
| @@ -9,7 +9,6 @@ · 8 unmodified lines | |||
| 9 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
| 10 | #include <linux/device.h> | 10 | #include <linux/device.h> |
| 11 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
| 12 | #include <linux/gpio.h> | ||
| 13 | #include <linux/init.h> | 12 | #include <linux/init.h> |
| 14 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
| 15 | #include <linux/io.h> | 14 | #include <linux/io.h> |
| @@ -2196,7 +2195,8 @@ static int net2272_present(struct net2272 *dev) · 2180 unmodified lines | |||
| 2196 | static void | 2195 | static void |
| 2197 | net2272_gadget_release(struct device *_dev) | 2196 | net2272_gadget_release(struct device *_dev) |
| 2198 | { | 2197 | { |
| 2199 | struct net2272 *dev = dev_get_drvdata(_dev); | 2198 | struct net2272 *dev = container_of(_dev, struct net2272, gadget.dev); |
| 2199 | |||
| 2200 | kfree(dev); | 2200 | kfree(dev); |
| 2201 | } | 2201 | } |
| 2202 | 2202 | ||
| @@ -2205,7 +2205,8 @@ net2272_gadget_release(struct device *_dev) · 2 unmodified lines | |||
| 2205 | static void | 2205 | static void |
| 2206 | net2272_remove(struct net2272 *dev) | 2206 | net2272_remove(struct net2272 *dev) |
| 2207 | { | 2207 | { |
| 2208 | usb_del_gadget_udc(&dev->gadget); | 2208 | if (dev->added) |
| 2209 | usb_del_gadget(&dev->gadget); | ||
| 2209 | free_irq(dev->irq, dev); | 2210 | free_irq(dev->irq, dev); |
| 2210 | iounmap(dev->base_addr); | 2211 | iounmap(dev->base_addr); |
| 2211 | device_remove_file(dev->dev, &dev_attr_registers); | 2212 | device_remove_file(dev->dev, &dev_attr_registers); |
| @@ -2235,6 +2236,7 @@ static struct net2272 *net2272_probe_init(struct device *dev, unsigned int irq) · 23 unmodified lines | |||
| 2235 | 2236 | ||
| 2236 | /* the "gadget" abstracts/virtualizes the controller */ | 2237 | /* the "gadget" abstracts/virtualizes the controller */ |
| 2237 | ret->gadget.name = driver_name; | 2238 | ret->gadget.name = driver_name; |
| 2239 | usb_initialize_gadget(dev, &ret->gadget, net2272_gadget_release); | ||
| 2238 | 2240 | ||
| 2239 | return ret; | 2241 | return ret; |
| 2240 | } | 2242 | } |
| @@ -2273,10 +2275,10 @@ net2272_probe_fin(struct net2272 *dev, unsigned int irqflags) · 32 unmodified lines | |||
| 2273 | if (ret) | 2275 | if (ret) |
| 2274 | goto err_irq; | 2276 | goto err_irq; |
| 2275 | 2277 | ||
| 2276 | ret = usb_add_gadget_udc_release(dev->dev, &dev->gadget, | 2278 | ret = usb_add_gadget(&dev->gadget); |
| 2277 | net2272_gadget_release); | ||
| 2278 | if (ret) | 2279 | if (ret) |
| 2279 | goto err_add_udc; | 2280 | goto err_add_udc; |
| 2281 | dev->added = 1; | ||
| 2280 | 2282 | ||
| 2281 | return 0; | 2283 | return 0; |
| 2282 | 2284 | ||
| @@ -2451,7 +2453,7 @@ net2272_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) · 168 unmodified lines | |||
| 2451 | 2453 | ||
| 2452 | if (pci_enable_device(pdev) < 0) { | 2454 | if (pci_enable_device(pdev) < 0) { |
| 2453 | ret = -ENODEV; | 2455 | ret = -ENODEV; |
| 2454 | goto err_free; | 2456 | goto err_put; |
| 2455 | } | 2457 | } |
| 2456 | 2458 | ||
| 2457 | pci_set_master(pdev); | 2459 | pci_set_master(pdev); |
| @@ -2474,8 +2476,8 @@ net2272_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) · 16 unmodified lines | |||
| 2474 | 2476 | ||
| 2475 | err_pci: | 2477 | err_pci: |
| 2476 | pci_disable_device(pdev); | 2478 | pci_disable_device(pdev); |
| 2477 | err_free: | 2479 | err_put: |
| 2478 | kfree(dev); | 2480 | usb_put_gadget(&dev->gadget); |
| 2479 | 2481 | ||
| 2480 | return ret; | 2482 | return ret; |
| 2481 | } | 2483 | } |
| @@ -2536,7 +2538,7 @@ net2272_pci_remove(struct pci_dev *pdev) · 54 unmodified lines | |||
| 2536 | 2538 | ||
| 2537 | pci_disable_device(pdev); | 2539 | pci_disable_device(pdev); |
| 2538 | 2540 | ||
| 2539 | kfree(dev); | 2541 | usb_put_gadget(&dev->gadget); |
| 2540 | } | 2542 | } |
| 2541 | 2543 | ||
| 2542 | /* Table of matching PCI IDs */ | 2544 | /* Table of matching PCI IDs */ |
| @@ -2649,7 +2651,7 @@ net2272_plat_probe(struct platform_device *pdev) · 106 unmodified lines | |||
| 2649 | err_req: | 2651 | err_req: |
| 2650 | release_mem_region(base, len); | 2652 | release_mem_region(base, len); |
| 2651 | err: | 2653 | err: |
| 2652 | kfree(dev); | 2654 | usb_put_gadget(&dev->gadget); |
| 2653 | 2655 | ||
| 2654 | return ret; | 2656 | return ret; |
| 2655 | } | 2657 | } |
| @@ -2664,7 +2666,7 @@ net2272_plat_remove(struct platform_device *pdev) · 8 unmodified lines | |||
| 2664 | release_mem_region(pdev->resource[0].start, | 2666 | release_mem_region(pdev->resource[0].start, |
| 2665 | resource_size(&pdev->resource[0])); | 2667 | resource_size(&pdev->resource[0])); |
| 2666 | 2668 | ||
| 2667 | kfree(dev); | 2669 | usb_put_gadget(&dev->gadget); |
| 2668 | 2670 | ||
| 2669 | return 0; | 2671 | return 0; |
| 2670 | } | 2672 | } |
| @@ -441,6 +441,7 @@ struct net2272 { · 440 unmodified lines | |||
| 441 | unsigned protocol_stall:1, | 441 | unsigned protocol_stall:1, |
| 442 | softconnect:1, | 442 | softconnect:1, |
| 443 | wakeup:1, | 443 | wakeup:1, |
| 444 | added:1, | ||
| 444 | dma_eot_polarity:1, | 445 | dma_eot_polarity:1, |
| 445 | dma_dack_polarity:1, | 446 | dma_dack_polarity:1, |
| 446 | dma_dreq_polarity:1, | 447 | dma_dreq_polarity:1, |
| @@ -52,6 +52,7 @@ · 51 unmodified lines | |||
| 52 | #include <linux/usb/gadget.h> | 52 | #include <linux/usb/gadget.h> |
| 53 | #include <linux/prefetch.h> | 53 | #include <linux/prefetch.h> |
| 54 | #include <linux/io.h> | 54 | #include <linux/io.h> |
| 55 | #include <linux/iopoll.h> | ||
| 55 | 56 | ||
| 56 | #include <asm/byteorder.h> | 57 | #include <asm/byteorder.h> |
| 57 | #include <asm/irq.h> | 58 | #include <asm/irq.h> |
| @@ -360,18 +361,16 @@ print_err: · 302 unmodified lines | |||
| 360 | static int handshake(u32 __iomem *ptr, u32 mask, u32 done, int usec) | 361 | static int handshake(u32 __iomem *ptr, u32 mask, u32 done, int usec) |
| 361 | { | 362 | { |
| 362 | u32 result; | 363 | u32 result; |
| 364 | int ret; | ||
| 363 | 365 | ||
| 364 | do { | 366 | ret = readl_poll_timeout_atomic(ptr, result, |
| 365 | result = readl(ptr); | 367 | ((result & mask) == done || |
| 366 | if (result == ~(u32)0) /* "device unplugged" */ | 368 | result == U32_MAX), |
| 367 | return -ENODEV; | 369 | 1, usec); |
| 368 | result &= mask; | 370 | if (result == U32_MAX) /* device unplugged */ |
| 369 | if (result == done) | 371 | return -ENODEV; |
| 370 | return 0; | 372 | |
| 371 | udelay(1); | 373 | return ret; |
| 372 | usec--; | ||
| 373 | } while (usec > 0); | ||
| 374 | return -ETIMEDOUT; | ||
| 375 | } | 374 | } |
| 376 | 375 | ||
| 377 | static const struct usb_ep_ops net2280_ep_ops; | 376 | static const struct usb_ep_ops net2280_ep_ops; |
| @@ -3561,7 +3560,7 @@ static irqreturn_t net2280_irq(int irq, void *_dev) · 3183 unmodified lines | |||
| 3561 | 3560 | ||
| 3562 | static void gadget_release(struct device *_dev) | 3561 | static void gadget_release(struct device *_dev) |
| 3563 | { | 3562 | { |
| 3564 | struct net2280 *dev = dev_get_drvdata(_dev); | 3563 | struct net2280 *dev = container_of(_dev, struct net2280, gadget.dev); |
| 3565 | 3564 | ||
| 3566 | kfree(dev); | 3565 | kfree(dev); |
| 3567 | } | 3566 | } |
| @@ -3572,7 +3571,8 @@ static void net2280_remove(struct pci_dev *pdev) · 4 unmodified lines | |||
| 3572 | { | 3571 | { |
| 3573 | struct net2280 *dev = pci_get_drvdata(pdev); | 3572 | struct net2280 *dev = pci_get_drvdata(pdev); |
| 3574 | 3573 | ||
| 3575 | usb_del_gadget_udc(&dev->gadget); | 3574 | if (dev->added) |
| 3575 | usb_del_gadget(&dev->gadget); | ||
| 3576 | 3576 | ||
| 3577 | BUG_ON(dev->driver); | 3577 | BUG_ON(dev->driver); |
| 3578 | 3578 | ||
| @@ -3603,6 +3603,7 @@ static void net2280_remove(struct pci_dev *pdev) · 24 unmodified lines | |||
| 3603 | device_remove_file(&pdev->dev, &dev_attr_registers); | 3603 | device_remove_file(&pdev->dev, &dev_attr_registers); |
| 3604 | 3604 | ||
| 3605 | ep_info(dev, "unbind\n"); | 3605 | ep_info(dev, "unbind\n"); |
| 3606 | usb_put_gadget(&dev->gadget); | ||
| 3606 | } | 3607 | } |
| 3607 | 3608 | ||
| 3608 | /* wrap this driver around the specified device, but | 3609 | /* wrap this driver around the specified device, but |
| @@ -3624,6 +3625,7 @@ static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id) · 15 unmodified lines | |||
| 3624 | } | 3625 | } |
| 3625 | 3626 | ||
| 3626 | pci_set_drvdata(pdev, dev); | 3627 | pci_set_drvdata(pdev, dev); |
| 3628 | usb_initialize_gadget(&pdev->dev, &dev->gadget, gadget_release); | ||
| 3627 | spin_lock_init(&dev->lock); | 3629 | spin_lock_init(&dev->lock); |
| 3628 | dev->quirks = id->driver_data; | 3630 | dev->quirks = id->driver_data; |
| 3629 | dev->pdev = pdev; | 3631 | dev->pdev = pdev; |
| @@ -3774,10 +3776,10 @@ static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id) · 144 unmodified lines | |||
| 3774 | if (retval) | 3776 | if (retval) |
| 3775 | goto done; | 3777 | goto done; |
| 3776 | 3778 | ||
| 3777 | retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget, | 3779 | retval = usb_add_gadget(&dev->gadget); |
| 3778 | gadget_release); | ||
| 3779 | if (retval) | 3780 | if (retval) |
| 3780 | goto done; | 3781 | goto done; |
| 3782 | dev->added = 1; | ||
| 3781 | return 0; | 3783 | return 0; |
| 3782 | 3784 | ||
| 3783 | done: | 3785 | done: |
| @@ -156,6 +156,7 @@ struct net2280 { · 155 unmodified lines | |||
| 156 | softconnect : 1, | 156 | softconnect : 1, |
| 157 | got_irq : 1, | 157 | got_irq : 1, |
| 158 | region:1, | 158 | region:1, |
| 159 | added:1, | ||
| 159 | u1_enable:1, | 160 | u1_enable:1, |
| 160 | u2_enable:1, | 161 | u2_enable:1, |
| 161 | ltm_enable:1, | 162 | ltm_enable:1, |
| @@ -12,12 +12,9 @@ · 11 unmodified lines | |||
| 12 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
| 13 | #include <linux/usb/ch9.h> | 13 | #include <linux/usb/ch9.h> |
| 14 | #include <linux/usb/gadget.h> | 14 | #include <linux/usb/gadget.h> |
| 15 | #include <linux/gpio.h> | 15 | #include <linux/gpio/consumer.h> |
| 16 | #include <linux/irq.h> | 16 | #include <linux/irq.h> |
| 17 | 17 | ||
| 18 | /* GPIO port for VBUS detecting */ | ||
| 19 | static int vbus_gpio_port = -1; /* GPIO port number (-1:Not used) */ | ||
| 20 | |||
| 21 | #define PCH_VBUS_PERIOD 3000 /* VBUS polling period (msec) */ | 18 | #define PCH_VBUS_PERIOD 3000 /* VBUS polling period (msec) */ |
| 22 | #define PCH_VBUS_INTERVAL 10 /* VBUS polling interval (msec) */ | 19 | #define PCH_VBUS_INTERVAL 10 /* VBUS polling interval (msec) */ |
| 23 | 20 | ||
| @@ -301,13 +298,13 @@ struct pch_udc_ep { · 277 unmodified lines | |||
| 301 | /** | 298 | /** |
| 302 | * struct pch_vbus_gpio_data - Structure holding GPIO informaton | 299 | * struct pch_vbus_gpio_data - Structure holding GPIO informaton |
| 303 | * for detecting VBUS | 300 | * for detecting VBUS |
| 304 | * @port: gpio port number | 301 | * @port: gpio descriptor for the VBUS GPIO |
| 305 | * @intr: gpio interrupt number | 302 | * @intr: gpio interrupt number |
| 306 | * @irq_work_fall: Structure for WorkQueue | 303 | * @irq_work_fall: Structure for WorkQueue |
| 307 | * @irq_work_rise: Structure for WorkQueue | 304 | * @irq_work_rise: Structure for WorkQueue |
| 308 | */ | 305 | */ |
| 309 | struct pch_vbus_gpio_data { | 306 | struct pch_vbus_gpio_data { |
| 310 | int port; | 307 | struct gpio_desc *port; |
| 311 | int intr; | 308 | int intr; |
| 312 | struct work_struct irq_work_fall; | 309 | struct work_struct irq_work_fall; |
| 313 | struct work_struct irq_work_rise; | 310 | struct work_struct irq_work_rise; |
| @@ -1254,7 +1251,7 @@ static int pch_vbus_gpio_get_value(struct pch_udc_dev *dev) · 940 unmodified lines | |||
| 1254 | int vbus = 0; | 1251 | int vbus = 0; |
| 1255 | 1252 | ||
| 1256 | if (dev->vbus_gpio.port) | 1253 | if (dev->vbus_gpio.port) |
| 1257 | vbus = gpio_get_value(dev->vbus_gpio.port) ? 1 : 0; | 1254 | vbus = gpiod_get_value(dev->vbus_gpio.port) ? 1 : 0; |
| 1258 | else | 1255 | else |
| 1259 | vbus = -1; | 1256 | vbus = -1; |
| 1260 | 1257 | ||
| @@ -1356,42 +1353,30 @@ static irqreturn_t pch_vbus_gpio_irq(int irq, void *data) · 95 unmodified lines | |||
| 1356 | /** | 1353 | /** |
| 1357 | * pch_vbus_gpio_init() - This API initializes GPIO port detecting VBUS. | 1354 | * pch_vbus_gpio_init() - This API initializes GPIO port detecting VBUS. |
| 1358 | * @dev: Reference to the driver structure | 1355 | * @dev: Reference to the driver structure |
| 1359 | * @vbus_gpio_port: Number of GPIO port to detect gpio | ||
| 1360 | * | 1356 | * |
| 1361 | * Return codes: | 1357 | * Return codes: |
| 1362 | * 0: Success | 1358 | * 0: Success |
| 1363 | * -EINVAL: GPIO port is invalid or can't be initialized. | 1359 | * -EINVAL: GPIO port is invalid or can't be initialized. |
| 1364 | */ | 1360 | */ |
| 1365 | static int pch_vbus_gpio_init(struct pch_udc_dev *dev, int vbus_gpio_port) | 1361 | static int pch_vbus_gpio_init(struct pch_udc_dev *dev) |
| 1366 | { | 1362 | { |
| 1367 | int err; | 1363 | int err; |
| 1368 | int irq_num = 0; | 1364 | int irq_num = 0; |
| 1365 | struct gpio_desc *gpiod; | ||
| 1369 | 1366 | ||
| 1370 | dev->vbus_gpio.port = 0; | 1367 | dev->vbus_gpio.port = NULL; |
| 1371 | dev->vbus_gpio.intr = 0; | 1368 | dev->vbus_gpio.intr = 0; |
| 1372 | 1369 | ||
| 1373 | if (vbus_gpio_port <= -1) | 1370 | /* Retrieve the GPIO line from the USB gadget device */ |
| 1374 | return -EINVAL; | 1371 | gpiod = devm_gpiod_get(dev->gadget.dev.parent, NULL, GPIOD_IN); |
| 1375 | 1372 | if (IS_ERR(gpiod)) | |
| 1376 | err = gpio_is_valid(vbus_gpio_port); | 1373 | return PTR_ERR(gpiod); |
| 1377 | if (!err) { | 1374 | gpiod_set_consumer_name(gpiod, "pch_vbus"); |
| 1378 | pr_err("%s: gpio port %d is invalid\n", | ||
| 1379 | __func__, vbus_gpio_port); | ||
| 1380 | return -EINVAL; | ||
| 1381 | } | ||
| 1382 | |||
| 1383 | err = gpio_request(vbus_gpio_port, "pch_vbus"); | ||
| 1384 | if (err) { | ||
| 1385 | pr_err("%s: can't request gpio port %d, err: %d\n", | ||
| 1386 | __func__, vbus_gpio_port, err); | ||
| 1387 | return -EINVAL; | ||
| 1388 | } | ||
| 1389 | 1375 | ||
| 1390 | dev->vbus_gpio.port = vbus_gpio_port; | 1376 | dev->vbus_gpio.port = gpiod; |
| 1391 | gpio_direction_input(vbus_gpio_port); | ||
| 1392 | INIT_WORK(&dev->vbus_gpio.irq_work_fall, pch_vbus_gpio_work_fall); | 1377 | INIT_WORK(&dev->vbus_gpio.irq_work_fall, pch_vbus_gpio_work_fall); |
| 1393 | 1378 | ||
| 1394 | irq_num = gpio_to_irq(vbus_gpio_port); | 1379 | irq_num = gpiod_to_irq(gpiod); |
| 1395 | if (irq_num > 0) { | 1380 | if (irq_num > 0) { |
| 1396 | irq_set_irq_type(irq_num, IRQ_TYPE_EDGE_BOTH); | 1381 | irq_set_irq_type(irq_num, IRQ_TYPE_EDGE_BOTH); |
| 1397 | err = request_irq(irq_num, pch_vbus_gpio_irq, 0, | 1382 | err = request_irq(irq_num, pch_vbus_gpio_irq, 0, |
| @@ -1417,9 +1402,6 @@ static void pch_vbus_gpio_free(struct pch_udc_dev *dev) · 19 unmodified lines | |||
| 1417 | { | 1402 | { |
| 1418 | if (dev->vbus_gpio.intr) | 1403 | if (dev->vbus_gpio.intr) |
| 1419 | free_irq(dev->vbus_gpio.intr, dev); | 1404 | free_irq(dev->vbus_gpio.intr, dev); |
| 1420 | |||
| 1421 | if (dev->vbus_gpio.port) | ||
| 1422 | gpio_free(dev->vbus_gpio.port); | ||
| 1423 | } | 1405 | } |
| 1424 | 1406 | ||
| 1425 | /** | 1407 | /** |
| @@ -2894,7 +2876,7 @@ static int pch_udc_pcd_init(struct pch_udc_dev *dev) · 1468 unmodified lines | |||
| 2894 | { | 2876 | { |
| 2895 | pch_udc_init(dev); | 2877 | pch_udc_init(dev); |
| 2896 | pch_udc_pcd_reinit(dev); | 2878 | pch_udc_pcd_reinit(dev); |
| 2897 | pch_vbus_gpio_init(dev, vbus_gpio_port); | 2879 | pch_vbus_gpio_init(dev); |
| 2898 | return 0; | 2880 | return 0; |
| 2899 | } | 2881 | } |
| 2900 | 2882 | ||
| @@ -3096,6 +3078,13 @@ static int pch_udc_probe(struct pci_dev *pdev, · 195 unmodified lines | |||
| 3096 | 3078 | ||
| 3097 | dev->base_addr = pcim_iomap_table(pdev)[bar]; | 3079 | dev->base_addr = pcim_iomap_table(pdev)[bar]; |
| 3098 | 3080 | ||
| 3081 | /* | ||
| 3082 | * FIXME: add a GPIO descriptor table to pdev.dev using | ||
| 3083 | * gpiod_add_descriptor_table() from <linux/gpio/machine.h> based on | ||
| 3084 | * the PCI subsystem ID. The system-dependent GPIO is necessary for | ||
| 3085 | * VBUS operation. | ||
| 3086 | */ | ||
| 3087 | |||
| 3099 | /* initialize the hardware */ | 3088 | /* initialize the hardware */ |
| 3100 | if (pch_udc_pcd_init(dev)) | 3089 | if (pch_udc_pcd_init(dev)) |
| 3101 | return -ENODEV; | 3090 | return -ENODEV; |
| @@ -1270,7 +1270,6 @@ static int s3c2410_udc_queue(struct usb_ep *_ep, struct usb_request *_req, · 1269 unmodified lines | |||
| 1270 | static int s3c2410_udc_dequeue(struct usb_ep *_ep, struct usb_request *_req) | 1270 | static int s3c2410_udc_dequeue(struct usb_ep *_ep, struct usb_request *_req) |
| 1271 | { | 1271 | { |
| 1272 | struct s3c2410_ep *ep = to_s3c2410_ep(_ep); | 1272 | struct s3c2410_ep *ep = to_s3c2410_ep(_ep); |
| 1273 | struct s3c2410_udc *udc; | ||
| 1274 | int retval = -EINVAL; | 1273 | int retval = -EINVAL; |
| 1275 | unsigned long flags; | 1274 | unsigned long flags; |
| 1276 | struct s3c2410_request *req = NULL; | 1275 | struct s3c2410_request *req = NULL; |
| @@ -1283,8 +1282,6 @@ static int s3c2410_udc_dequeue(struct usb_ep *_ep, struct usb_request *_req) · 6 unmodified lines | |||
| 1283 | if (!_ep || !_req) | 1282 | if (!_ep || !_req) |
| 1284 | return retval; | 1283 | return retval; |
| 1285 | 1284 | ||
| 1286 | udc = to_s3c2410_udc(ep->gadget); | ||
| 1287 | |||
| 1288 | local_irq_save(flags); | 1285 | local_irq_save(flags); |
| 1289 | 1286 | ||
| 1290 | list_for_each_entry(req, &ep->queue, queue) { | 1287 | list_for_each_entry(req, &ep->queue, queue) { |
| @@ -705,11 +705,11 @@ static void tegra_xudc_device_mode_on(struct tegra_xudc *xudc) · 704 unmodified lines | |||
| 705 | 705 | ||
| 706 | err = phy_power_on(xudc->curr_utmi_phy); | 706 | err = phy_power_on(xudc->curr_utmi_phy); |
| 707 | if (err < 0) | 707 | if (err < 0) |
| 708 | dev_err(xudc->dev, "utmi power on failed %d\n", err); | 708 | dev_err(xudc->dev, "UTMI power on failed: %d\n", err); |
| 709 | 709 | ||
| 710 | err = phy_power_on(xudc->curr_usb3_phy); | 710 | err = phy_power_on(xudc->curr_usb3_phy); |
| 711 | if (err < 0) | 711 | if (err < 0) |
| 712 | dev_err(xudc->dev, "usb3 phy power on failed %d\n", err); | 712 | dev_err(xudc->dev, "USB3 PHY power on failed: %d\n", err); |
| 713 | 713 | ||
| 714 | dev_dbg(xudc->dev, "device mode on\n"); | 714 | dev_dbg(xudc->dev, "device mode on\n"); |
| 715 | 715 | ||
| @@ -759,11 +759,11 @@ static void tegra_xudc_device_mode_off(struct tegra_xudc *xudc) · 43 unmodified lines | |||
| 759 | 759 | ||
| 760 | err = phy_power_off(xudc->curr_utmi_phy); | 760 | err = phy_power_off(xudc->curr_utmi_phy); |
| 761 | if (err < 0) | 761 | if (err < 0) |
| 762 | dev_err(xudc->dev, "utmi_phy power off failed %d\n", err); | 762 | dev_err(xudc->dev, "UTMI PHY power off failed: %d\n", err); |
| 763 | 763 | ||
| 764 | err = phy_power_off(xudc->curr_usb3_phy); | 764 | err = phy_power_off(xudc->curr_usb3_phy); |
| 765 | if (err < 0) | 765 | if (err < 0) |
| 766 | dev_err(xudc->dev, "usb3_phy power off failed %d\n", err); | 766 | dev_err(xudc->dev, "USB3 PHY power off failed: %d\n", err); |
| 767 | 767 | ||
| 768 | pm_runtime_put(xudc->dev); | 768 | pm_runtime_put(xudc->dev); |
| 769 | } | 769 | } |
| @@ -1539,7 +1539,7 @@ static int __tegra_xudc_ep_set_halt(struct tegra_xudc_ep *ep, bool halt) · 769 unmodified lines | |||
| 1539 | return -EINVAL; | 1539 | return -EINVAL; |
| 1540 | 1540 | ||
| 1541 | if (usb_endpoint_xfer_isoc(ep->desc)) { | 1541 | if (usb_endpoint_xfer_isoc(ep->desc)) { |
| 1542 | dev_err(xudc->dev, "can't halt isoc EP\n"); | 1542 | dev_err(xudc->dev, "can't halt isochronous EP\n"); |
| 1543 | return -ENOTSUPP; | 1543 | return -ENOTSUPP; |
| 1544 | } | 1544 | } |
| 1545 | 1545 | ||
| @@ -1788,7 +1788,7 @@ static int __tegra_xudc_ep_enable(struct tegra_xudc_ep *ep, · 242 unmodified lines | |||
| 1788 | 1788 | ||
| 1789 | if (usb_endpoint_xfer_isoc(desc)) { | 1789 | if (usb_endpoint_xfer_isoc(desc)) { |
| 1790 | if (xudc->nr_isoch_eps > XUDC_MAX_ISOCH_EPS) { | 1790 | if (xudc->nr_isoch_eps > XUDC_MAX_ISOCH_EPS) { |
| 1791 | dev_err(xudc->dev, "too many isoch endpoints\n"); | 1791 | dev_err(xudc->dev, "too many isochronous endpoints\n"); |
| 1792 | return -EBUSY; | 1792 | return -EBUSY; |
| 1793 | } | 1793 | } |
| 1794 | xudc->nr_isoch_eps++; | 1794 | xudc->nr_isoch_eps++; |
| @@ -3509,7 +3509,7 @@ static int tegra_xudc_phy_get(struct tegra_xudc *xudc) · 1714 unmodified lines | |||
| 3509 | if (IS_ERR(xudc->utmi_phy[i])) { | 3509 | if (IS_ERR(xudc->utmi_phy[i])) { |
| 3510 | err = PTR_ERR(xudc->utmi_phy[i]); | 3510 | err = PTR_ERR(xudc->utmi_phy[i]); |
| 3511 | if (err != -EPROBE_DEFER) | 3511 | if (err != -EPROBE_DEFER) |
| 3512 | dev_err(xudc->dev, "failed to get usb2-%d phy: %d\n", | 3512 | dev_err(xudc->dev, "failed to get usb2-%d PHY: %d\n", |
| 3513 | i, err); | 3513 | i, err); |
| 3514 | 3514 | ||
| 3515 | goto clean_up; | 3515 | goto clean_up; |
| @@ -3539,12 +3539,12 @@ static int tegra_xudc_phy_get(struct tegra_xudc *xudc) · 23 unmodified lines | |||
| 3539 | if (IS_ERR(xudc->usb3_phy[i])) { | 3539 | if (IS_ERR(xudc->usb3_phy[i])) { |
| 3540 | err = PTR_ERR(xudc->usb3_phy[i]); | 3540 | err = PTR_ERR(xudc->usb3_phy[i]); |
| 3541 | if (err != -EPROBE_DEFER) | 3541 | if (err != -EPROBE_DEFER) |
| 3542 | dev_err(xudc->dev, "failed to get usb3-%d phy: %d\n", | 3542 | dev_err(xudc->dev, "failed to get usb3-%d PHY: %d\n", |
| 3543 | usb3, err); | 3543 | usb3, err); |
| 3544 | 3544 | ||
| 3545 | goto clean_up; | 3545 | goto clean_up; |
| 3546 | } else if (xudc->usb3_phy[i]) | 3546 | } else if (xudc->usb3_phy[i]) |
| 3547 | dev_dbg(xudc->dev, "usb3_phy-%d registered", usb3); | 3547 | dev_dbg(xudc->dev, "usb3-%d PHY registered", usb3); |
| 3548 | } | 3548 | } |
| 3549 | 3549 | ||
| 3550 | return err; | 3550 | return err; |
| @@ -3577,13 +3577,13 @@ static int tegra_xudc_phy_init(struct tegra_xudc *xudc) · 26 unmodified lines | |||
| 3577 | for (i = 0; i < xudc->soc->num_phys; i++) { | 3577 | for (i = 0; i < xudc->soc->num_phys; i++) { |
| 3578 | err = phy_init(xudc->utmi_phy[i]); | 3578 | err = phy_init(xudc->utmi_phy[i]); |
| 3579 | if (err < 0) { | 3579 | if (err < 0) { |
| 3580 | dev_err(xudc->dev, "utmi phy init failed: %d\n", err); | 3580 | dev_err(xudc->dev, "UTMI PHY #%u initialization failed: %d\n", i, err); |
| 3581 | goto exit_phy; | 3581 | goto exit_phy; |
| 3582 | } | 3582 | } |
| 3583 | 3583 | ||
| 3584 | err = phy_init(xudc->usb3_phy[i]); | 3584 | err = phy_init(xudc->usb3_phy[i]); |
| 3585 | if (err < 0) { | 3585 | if (err < 0) { |
| 3586 | dev_err(xudc->dev, "usb3 phy init failed: %d\n", err); | 3586 | dev_err(xudc->dev, "USB3 PHY #%u initialization failed: %d\n", i, err); |
| 3587 | goto exit_phy; | 3587 | goto exit_phy; |
| 3588 | } | 3588 | } |
| 3589 | } | 3589 | } |
| @@ -3692,34 +3692,33 @@ static int tegra_xudc_powerdomain_init(struct tegra_xudc *xudc) · 102 unmodified lines | |||
| 3692 | struct device *dev = xudc->dev; | 3692 | struct device *dev = xudc->dev; |
| 3693 | int err; | 3693 | int err; |
| 3694 | 3694 | ||
| 3695 | xudc->genpd_dev_device = dev_pm_domain_attach_by_name(dev, | 3695 | xudc->genpd_dev_device = dev_pm_domain_attach_by_name(dev, "dev"); |
| 3696 | "dev"); | ||
| 3697 | if (IS_ERR(xudc->genpd_dev_device)) { | 3696 | if (IS_ERR(xudc->genpd_dev_device)) { |
| 3698 | err = PTR_ERR(xudc->genpd_dev_device); | 3697 | err = PTR_ERR(xudc->genpd_dev_device); |
| 3699 | dev_err(dev, "failed to get dev pm-domain: %d\n", err); | 3698 | dev_err(dev, "failed to get device power domain: %d\n", err); |
| 3700 | return err; | 3699 | return err; |
| 3701 | } | 3700 | } |
| 3702 | 3701 | ||
| 3703 | xudc->genpd_dev_ss = dev_pm_domain_attach_by_name(dev, "ss"); | 3702 | xudc->genpd_dev_ss = dev_pm_domain_attach_by_name(dev, "ss"); |
| 3704 | if (IS_ERR(xudc->genpd_dev_ss)) { | 3703 | if (IS_ERR(xudc->genpd_dev_ss)) { |
| 3705 | err = PTR_ERR(xudc->genpd_dev_ss); | 3704 | err = PTR_ERR(xudc->genpd_dev_ss); |
| 3706 | dev_err(dev, "failed to get superspeed pm-domain: %d\n", err); | 3705 | dev_err(dev, "failed to get SuperSpeed power domain: %d\n", err); |
| 3707 | return err; | 3706 | return err; |
| 3708 | } | 3707 | } |
| 3709 | 3708 | ||
| 3710 | xudc->genpd_dl_device = device_link_add(dev, xudc->genpd_dev_device, | 3709 | xudc->genpd_dl_device = device_link_add(dev, xudc->genpd_dev_device, |
| 3711 | DL_FLAG_PM_RUNTIME | | 3710 | DL_FLAG_PM_RUNTIME | |
| 3712 | DL_FLAG_STATELESS); | 3711 | DL_FLAG_STATELESS); |
| 3713 | if (!xudc->genpd_dl_device) { | 3712 | if (!xudc->genpd_dl_device) { |
| 3714 | dev_err(dev, "adding usb device device link failed!\n"); | 3713 | dev_err(dev, "failed to add USB device link\n"); |
| 3715 | return -ENODEV; | 3714 | return -ENODEV; |
| 3716 | } | 3715 | } |
| 3717 | 3716 | ||
| 3718 | xudc->genpd_dl_ss = device_link_add(dev, xudc->genpd_dev_ss, | 3717 | xudc->genpd_dl_ss = device_link_add(dev, xudc->genpd_dev_ss, |
| 3719 | DL_FLAG_PM_RUNTIME | | 3718 | DL_FLAG_PM_RUNTIME | |
| 3720 | DL_FLAG_STATELESS); | 3719 | DL_FLAG_STATELESS); |
| 3721 | if (!xudc->genpd_dl_ss) { | 3720 | if (!xudc->genpd_dl_ss) { |
| 3722 | dev_err(dev, "adding superspeed device link failed!\n"); | 3721 | dev_err(dev, "failed to add SuperSpeed device link\n"); |
| 3723 | return -ENODEV; | 3722 | return -ENODEV; |
| 3724 | } | 3723 | } |
| 3725 | 3724 | ||
| @@ -3733,7 +3732,7 @@ static int tegra_xudc_probe(struct platform_device *pdev) · 7 unmodified lines | |||
| 3733 | unsigned int i; | 3732 | unsigned int i; |
| 3734 | int err; | 3733 | int err; |
| 3735 | 3734 | ||
| 3736 | xudc = devm_kzalloc(&pdev->dev, sizeof(*xudc), GFP_ATOMIC); | 3735 | xudc = devm_kzalloc(&pdev->dev, sizeof(*xudc), GFP_KERNEL); |
| 3737 | if (!xudc) | 3736 | if (!xudc) |
| 3738 | return -ENOMEM; | 3737 | return -ENOMEM; |
| 3739 | 3738 | ||
| @@ -3772,18 +3771,19 @@ static int tegra_xudc_probe(struct platform_device *pdev) · 32 unmodified lines | |||
| 3772 | return err; | 3771 | return err; |
| 3773 | } | 3772 | } |
| 3774 | 3773 | ||
| 3775 | xudc->clks = devm_kcalloc(&pdev->dev, xudc->soc->num_clks, | 3774 | xudc->clks = devm_kcalloc(&pdev->dev, xudc->soc->num_clks, sizeof(*xudc->clks), |
| 3776 | sizeof(*xudc->clks), GFP_KERNEL); | 3775 | GFP_KERNEL); |
| 3777 | if (!xudc->clks) | 3776 | if (!xudc->clks) |
| 3778 | return -ENOMEM; | 3777 | return -ENOMEM; |
| 3779 | 3778 | ||
| 3780 | for (i = 0; i < xudc->soc->num_clks; i++) | 3779 | for (i = 0; i < xudc->soc->num_clks; i++) |
| 3781 | xudc->clks[i].id = xudc->soc->clock_names[i]; | 3780 | xudc->clks[i].id = xudc->soc->clock_names[i]; |
| 3782 | 3781 | ||
| 3783 | err = devm_clk_bulk_get(&pdev->dev, xudc->soc->num_clks, | 3782 | err = devm_clk_bulk_get(&pdev->dev, xudc->soc->num_clks, xudc->clks); |
| 3784 | xudc->clks); | ||
| 3785 | if (err) { | 3783 | if (err) { |
| 3786 | dev_err(xudc->dev, "failed to request clks %d\n", err); | 3784 | if (err != -EPROBE_DEFER) |
| 3785 | dev_err(xudc->dev, "failed to request clocks: %d\n", err); | ||
| 3786 | |||
| 3787 | return err; | 3787 | return err; |
| 3788 | } | 3788 | } |
| 3789 | 3789 | ||
| @@ -3798,7 +3798,9 @@ static int tegra_xudc_probe(struct platform_device *pdev) · 8 unmodified lines | |||
| 3798 | err = devm_regulator_bulk_get(&pdev->dev, xudc->soc->num_supplies, | 3798 | err = devm_regulator_bulk_get(&pdev->dev, xudc->soc->num_supplies, |
| 3799 | xudc->supplies); | 3799 | xudc->supplies); |
| 3800 | if (err) { | 3800 | if (err) { |
| 3801 | dev_err(xudc->dev, "failed to request regulators %d\n", err); | 3801 | if (err != -EPROBE_DEFER) |
| 3802 | dev_err(xudc->dev, "failed to request regulators: %d\n", err); | ||
| 3803 | |||
| 3802 | return err; | 3804 | return err; |
| 3803 | } | 3805 | } |
| 3804 | 3806 | ||
| @@ -3808,7 +3810,7 @@ static int tegra_xudc_probe(struct platform_device *pdev) · 3 unmodified lines | |||
| 3808 | 3810 | ||
| 3809 | err = regulator_bulk_enable(xudc->soc->num_supplies, xudc->supplies); | 3811 | err = regulator_bulk_enable(xudc->soc->num_supplies, xudc->supplies); |
| 3810 | if (err) { | 3812 | if (err) { |
| 3811 | dev_err(xudc->dev, "failed to enable regulators %d\n", err); | 3813 | dev_err(xudc->dev, "failed to enable regulators: %d\n", err); |
| 3812 | goto put_padctl; | 3814 | goto put_padctl; |
| 3813 | } | 3815 | } |
| 3814 | 3816 | ||
| @@ -498,15 +498,4 @@ static struct bcma_driver bcma_hcd_driver = { · 497 unmodified lines | |||
| 498 | .suspend = bcma_hcd_suspend, | 498 | .suspend = bcma_hcd_suspend, |
| 499 | .resume = bcma_hcd_resume, | 499 | .resume = bcma_hcd_resume, |
| 500 | }; | 500 | }; |
| 501 | 501 | module_bcma_driver(bcma_hcd_driver); | |
| 502 | static int __init bcma_hcd_init(void) | ||
| 503 | { | ||
| 504 | return bcma_driver_register(&bcma_hcd_driver); | ||
| 505 | } | ||
| 506 | module_init(bcma_hcd_init); | ||
| 507 | |||
| 508 | static void __exit bcma_hcd_exit(void) | ||
| 509 | { | ||
| 510 | bcma_driver_unregister(&bcma_hcd_driver); | ||
| 511 | } | ||
| 512 | module_exit(bcma_hcd_exit); | ||
| @@ -37,8 +37,7 @@ static const char hcd_name[] = "npcm7xx-ehci"; · 36 unmodified lines | |||
| 37 | 37 | ||
| 38 | static struct hc_driver __read_mostly ehci_npcm7xx_hc_driver; | 38 | static struct hc_driver __read_mostly ehci_npcm7xx_hc_driver; |
| 39 | 39 | ||
| 40 | #ifdef CONFIG_PM_SLEEP | 40 | static int __maybe_unused ehci_npcm7xx_drv_suspend(struct device *dev) |
| 41 | static int ehci_npcm7xx_drv_suspend(struct device *dev) | ||
| 42 | { | 41 | { |
| 43 | struct usb_hcd *hcd = dev_get_drvdata(dev); | 42 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
| 44 | bool do_wakeup = device_may_wakeup(dev); | 43 | bool do_wakeup = device_may_wakeup(dev); |
| @@ -46,14 +45,13 @@ static int ehci_npcm7xx_drv_suspend(struct device *dev) · 1 unmodified line | |||
| 46 | return ehci_suspend(hcd, do_wakeup); | 45 | return ehci_suspend(hcd, do_wakeup); |
| 47 | } | 46 | } |
| 48 | 47 | ||
| 49 | static int ehci_npcm7xx_drv_resume(struct device *dev) | 48 | static int __maybe_unused ehci_npcm7xx_drv_resume(struct device *dev) |
| 50 | { | 49 | { |
| 51 | struct usb_hcd *hcd = dev_get_drvdata(dev); | 50 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
| 52 | 51 | ||
| 53 | ehci_resume(hcd, false); | 52 | ehci_resume(hcd, false); |
| 54 | return 0; | 53 | return 0; |
| 55 | } | 54 | } |
| 56 | #endif /* CONFIG_PM_SLEEP */ | ||
| 57 | 55 | ||
| 58 | static SIMPLE_DEV_PM_OPS(ehci_npcm7xx_pm_ops, ehci_npcm7xx_drv_suspend, | 56 | static SIMPLE_DEV_PM_OPS(ehci_npcm7xx_pm_ops, ehci_npcm7xx_drv_suspend, |
| 59 | ehci_npcm7xx_drv_resume); | 57 | ehci_npcm7xx_drv_resume); |
| @@ -183,7 +181,7 @@ static struct platform_driver npcm7xx_ehci_hcd_driver = { · 123 unmodified lines | |||
| 183 | .driver = { | 181 | .driver = { |
| 184 | .name = "npcm7xx-ehci", | 182 | .name = "npcm7xx-ehci", |
| 185 | .bus = &platform_bus_type, | 183 | .bus = &platform_bus_type, |
| 186 | .pm = &ehci_npcm7xx_pm_ops, | 184 | .pm = pm_ptr(&ehci_npcm7xx_pm_ops), |
| 187 | .of_match_table = npcm7xx_ehci_id_table, | 185 | .of_match_table = npcm7xx_ehci_id_table, |
| 188 | } | 186 | } |
| 189 | }; | 187 | }; |
| @@ -42,6 +42,9 @@ · 41 unmodified lines | |||
| 42 | #define EHCI_MAX_CLKS 4 | 42 | #define EHCI_MAX_CLKS 4 |
| 43 | #define hcd_to_ehci_priv(h) ((struct ehci_platform_priv *)hcd_to_ehci(h)->priv) | 43 | #define hcd_to_ehci_priv(h) ((struct ehci_platform_priv *)hcd_to_ehci(h)->priv) |
| 44 | 44 | ||
| 45 | #define BCM_USB_FIFO_THRESHOLD 0x00800040 | ||
| 46 | #define bcm_iproc_insnreg01 hostpc[0] | ||
| 47 | |||
| 45 | struct ehci_platform_priv { | 48 | struct ehci_platform_priv { |
| 46 | struct clk *clks[EHCI_MAX_CLKS]; | 49 | struct clk *clks[EHCI_MAX_CLKS]; |
| 47 | struct reset_control *rsts; | 50 | struct reset_control *rsts; |
| @@ -75,6 +78,11 @@ static int ehci_platform_reset(struct usb_hcd *hcd) · 27 unmodified lines | |||
| 75 | 78 | ||
| 76 | if (pdata->no_io_watchdog) | 79 | if (pdata->no_io_watchdog) |
| 77 | ehci->need_io_watchdog = 0; | 80 | ehci->need_io_watchdog = 0; |
| 81 | |||
| 82 | if (of_device_is_compatible(pdev->dev.of_node, "brcm,xgs-iproc-ehci")) | ||
| 83 | ehci_writel(ehci, BCM_USB_FIFO_THRESHOLD, | ||
| 84 | &ehci->regs->bcm_iproc_insnreg01); | ||
| 85 | |||
| 78 | return 0; | 86 | return 0; |
| 79 | } | 87 | } |
| 80 | 88 | ||
| @@ -410,8 +418,7 @@ static int ehci_platform_remove(struct platform_device *dev) · 329 unmodified lines | |||
| 410 | return 0; | 418 | return 0; |
| 411 | } | 419 | } |
| 412 | 420 | ||
| 413 | #ifdef CONFIG_PM_SLEEP | 421 | static int __maybe_unused ehci_platform_suspend(struct device *dev) |
| 414 | static int ehci_platform_suspend(struct device *dev) | ||
| 415 | { | 422 | { |
| 416 | struct usb_hcd *hcd = dev_get_drvdata(dev); | 423 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
| 417 | struct usb_ehci_pdata *pdata = dev_get_platdata(dev); | 424 | struct usb_ehci_pdata *pdata = dev_get_platdata(dev); |
| @@ -433,7 +440,7 @@ static int ehci_platform_suspend(struct device *dev) · 15 unmodified lines | |||
| 433 | return ret; | 440 | return ret; |
| 434 | } | 441 | } |
| 435 | 442 | ||
| 436 | static int ehci_platform_resume(struct device *dev) | 443 | static int __maybe_unused ehci_platform_resume(struct device *dev) |
| 437 | { | 444 | { |
| 438 | struct usb_hcd *hcd = dev_get_drvdata(dev); | 445 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
| 439 | struct usb_ehci_pdata *pdata = dev_get_platdata(dev); | 446 | struct usb_ehci_pdata *pdata = dev_get_platdata(dev); |
| @@ -464,7 +471,6 @@ static int ehci_platform_resume(struct device *dev) · 24 unmodified lines | |||
| 464 | 471 | ||
| 465 | return 0; | 472 | return 0; |
| 466 | } | 473 | } |
| 467 | #endif /* CONFIG_PM_SLEEP */ | ||
| 468 | 474 | ||
| 469 | static const struct of_device_id vt8500_ehci_ids[] = { | 475 | static const struct of_device_id vt8500_ehci_ids[] = { |
| 470 | { .compatible = "via,vt8500-ehci", }, | 476 | { .compatible = "via,vt8500-ehci", }, |
| @@ -499,7 +505,7 @@ static struct platform_driver ehci_platform_driver = { · 28 unmodified lines | |||
| 499 | .shutdown = usb_hcd_platform_shutdown, | 505 | .shutdown = usb_hcd_platform_shutdown, |
| 500 | .driver = { | 506 | .driver = { |
| 501 | .name = "ehci-platform", | 507 | .name = "ehci-platform", |
| 502 | .pm = &ehci_platform_pm_ops, | 508 | .pm = pm_ptr(&ehci_platform_pm_ops), |
| 503 | .of_match_table = vt8500_ehci_ids, | 509 | .of_match_table = vt8500_ehci_ids, |
| 504 | .acpi_match_table = ACPI_PTR(ehci_acpi_match), | 510 | .acpi_match_table = ACPI_PTR(ehci_acpi_match), |
| 505 | } | 511 | } |
| @@ -307,26 +307,6 @@ static int __maybe_unused same_tt(struct usb_device *dev1, · 306 unmodified lines | |||
| 307 | 307 | ||
| 308 | #ifdef CONFIG_USB_EHCI_TT_NEWSCHED | 308 | #ifdef CONFIG_USB_EHCI_TT_NEWSCHED |
| 309 | 309 | ||
| 310 | /* Which uframe does the low/fullspeed transfer start in? | ||
| 311 | * | ||
| 312 | * The parameter is the mask of ssplits in "H-frame" terms | ||
| 313 | * and this returns the transfer start uframe in "B-frame" terms, | ||
| 314 | * which allows both to match, e.g. a ssplit in "H-frame" uframe 0 | ||
| 315 | * will cause a transfer in "B-frame" uframe 0. "B-frames" lag | ||
| 316 | * "H-frames" by 1 uframe. See the EHCI spec sec 4.5 and figure 4.7. | ||
| 317 | */ | ||
| 318 | static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask) | ||
| 319 | { | ||
| 320 | unsigned char smask = hc32_to_cpu(ehci, mask) & QH_SMASK; | ||
| 321 | |||
| 322 | if (!smask) { | ||
| 323 | ehci_err(ehci, "invalid empty smask!\n"); | ||
| 324 | /* uframe 7 can't have bw so this will indicate failure */ | ||
| 325 | return 7; | ||
| 326 | } | ||
| 327 | return ffs(smask) - 1; | ||
| 328 | } | ||
| 329 | |||
| 330 | static const unsigned char | 310 | static const unsigned char |
| 331 | max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 }; | 311 | max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 }; |
| 332 | 312 | ||
| @@ -34,8 +34,7 @@ struct spear_ehci { · 33 unmodified lines | |||
| 34 | 34 | ||
| 35 | static struct hc_driver __read_mostly ehci_spear_hc_driver; | 35 | static struct hc_driver __read_mostly ehci_spear_hc_driver; |
| 36 | 36 | ||
| 37 | #ifdef CONFIG_PM_SLEEP | 37 | static int __maybe_unused ehci_spear_drv_suspend(struct device *dev) |
| 38 | static int ehci_spear_drv_suspend(struct device *dev) | ||
| 39 | { | 38 | { |
| 40 | struct usb_hcd *hcd = dev_get_drvdata(dev); | 39 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
| 41 | bool do_wakeup = device_may_wakeup(dev); | 40 | bool do_wakeup = device_may_wakeup(dev); |
| @@ -43,14 +42,13 @@ static int ehci_spear_drv_suspend(struct device *dev) · 1 unmodified line | |||
| 43 | return ehci_suspend(hcd, do_wakeup); | 42 | return ehci_suspend(hcd, do_wakeup); |
| 44 | } | 43 | } |
| 45 | 44 | ||
| 46 | static int ehci_spear_drv_resume(struct device *dev) | 45 | static int __maybe_unused ehci_spear_drv_resume(struct device *dev) |
| 47 | { | 46 | { |
| 48 | struct usb_hcd *hcd = dev_get_drvdata(dev); | 47 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
| 49 | 48 | ||
| 50 | ehci_resume(hcd, false); | 49 | ehci_resume(hcd, false); |
| 51 | return 0; | 50 | return 0; |
| 52 | } | 51 | } |
| 53 | #endif /* CONFIG_PM_SLEEP */ | ||
| 54 | 52 | ||
| 55 | static SIMPLE_DEV_PM_OPS(ehci_spear_pm_ops, ehci_spear_drv_suspend, | 53 | static SIMPLE_DEV_PM_OPS(ehci_spear_pm_ops, ehci_spear_drv_suspend, |
| 56 | ehci_spear_drv_resume); | 54 | ehci_spear_drv_resume); |
| @@ -155,7 +153,7 @@ static struct platform_driver spear_ehci_hcd_driver = { · 98 unmodified lines | |||
| 155 | .driver = { | 153 | .driver = { |
| 156 | .name = "spear-ehci", | 154 | .name = "spear-ehci", |
| 157 | .bus = &platform_bus_type, | 155 | .bus = &platform_bus_type, |
| 158 | .pm = &ehci_spear_pm_ops, | 156 | .pm = pm_ptr(&ehci_spear_pm_ops), |
| 159 | .of_match_table = spear_ehci_id_table, | 157 | .of_match_table = spear_ehci_id_table, |
| 160 | } | 158 | } |
| 161 | }; | 159 | }; |
| @@ -32,6 +32,7 @@ · 31 unmodified lines | |||
| 32 | #include <linux/uaccess.h> | 32 | #include <linux/uaccess.h> |
| 33 | #include <linux/platform_device.h> | 33 | #include <linux/platform_device.h> |
| 34 | #include <linux/io.h> | 34 | #include <linux/io.h> |
| 35 | #include <linux/iopoll.h> | ||
| 35 | #include <linux/clk.h> | 36 | #include <linux/clk.h> |
| 36 | 37 | ||
| 37 | #include <asm/byteorder.h> | 38 | #include <asm/byteorder.h> |
| @@ -883,18 +884,15 @@ static int handshake(struct fotg210_hcd *fotg210, void __iomem *ptr, · 845 unmodified lines | |||
| 883 | u32 mask, u32 done, int usec) | 884 | u32 mask, u32 done, int usec) |
| 884 | { | 885 | { |
| 885 | u32 result; | 886 | u32 result; |
| 887 | int ret; | ||
| 886 | 888 | ||
| 887 | do { | 889 | ret = readl_poll_timeout_atomic(ptr, result, |
| 888 | result = fotg210_readl(fotg210, ptr); | 890 | ((result & mask) == done || |
| 889 | if (result == ~(u32)0) /* card removed */ | 891 | result == U32_MAX), 1, usec); |
| 890 | return -ENODEV; | 892 | if (result == U32_MAX) /* card removed */ |
| 891 | result &= mask; | 893 | return -ENODEV; |
| 892 | if (result == done) | 894 | |
| 893 | return 0; | 895 | return ret; |
| 894 | udelay(1); | ||
| 895 | usec--; | ||
| 896 | } while (usec > 0); | ||
| 897 | return -ETIMEDOUT; | ||
| 898 | } | 896 | } |
| 899 | 897 | ||
| 900 | /* Force HC to halt state from unknown (EHCI spec section 2.3). | 898 | /* Force HC to halt state from unknown (EHCI spec section 2.3). |
| @@ -102,7 +102,7 @@ static void io_watchdog_func(struct timer_list *t); · 101 unmodified lines | |||
| 102 | 102 | ||
| 103 | 103 | ||
| 104 | /* Some boards misreport power switching/overcurrent */ | 104 | /* Some boards misreport power switching/overcurrent */ |
| 105 | static bool distrust_firmware = true; | 105 | static bool distrust_firmware; |
| 106 | module_param (distrust_firmware, bool, 0); | 106 | module_param (distrust_firmware, bool, 0); |
| 107 | MODULE_PARM_DESC (distrust_firmware, | 107 | MODULE_PARM_DESC (distrust_firmware, |
| 108 | "true to distrust firmware power/overcurrent setup"); | 108 | "true to distrust firmware power/overcurrent setup"); |
| @@ -673,20 +673,24 @@ retry: · 564 unmodified lines | |||
| 673 | 673 | ||
| 674 | /* handle root hub init quirks ... */ | 674 | /* handle root hub init quirks ... */ |
| 675 | val = roothub_a (ohci); | 675 | val = roothub_a (ohci); |
| 676 | val &= ~(RH_A_PSM | RH_A_OCPM); | 676 | /* Configure for per-port over-current protection by default */ |
| 677 | val &= ~RH_A_NOCP; | ||
| 678 | val |= RH_A_OCPM; | ||
| 677 | if (ohci->flags & OHCI_QUIRK_SUPERIO) { | 679 | if (ohci->flags & OHCI_QUIRK_SUPERIO) { |
| 678 | /* NSC 87560 and maybe others */ | 680 | /* NSC 87560 and maybe others. |
| 681 | * Ganged power switching, no over-current protection. | ||
| 682 | */ | ||
| 679 | val |= RH_A_NOCP; | 683 | val |= RH_A_NOCP; |
| 680 | val &= ~(RH_A_POTPGT | RH_A_NPS); | 684 | val &= ~(RH_A_POTPGT | RH_A_NPS | RH_A_PSM | RH_A_OCPM); |
| 681 | ohci_writel (ohci, val, &ohci->regs->roothub.a); | ||
| 682 | } else if ((ohci->flags & OHCI_QUIRK_AMD756) || | 685 | } else if ((ohci->flags & OHCI_QUIRK_AMD756) || |
| 683 | (ohci->flags & OHCI_QUIRK_HUB_POWER)) { | 686 | (ohci->flags & OHCI_QUIRK_HUB_POWER)) { |
| 684 | /* hub power always on; required for AMD-756 and some | 687 | /* hub power always on; required for AMD-756 and some |
| 685 | * Mac platforms. ganged overcurrent reporting, if any. | 688 | * Mac platforms. |
| 686 | */ | 689 | */ |
| 687 | val |= RH_A_NPS; | 690 | val |= RH_A_NPS; |
| 688 | ohci_writel (ohci, val, &ohci->regs->roothub.a); | ||
| 689 | } | 691 | } |
| 692 | ohci_writel(ohci, val, &ohci->regs->roothub.a); | ||
| 693 | |||
| 690 | ohci_writel (ohci, RH_HS_LPSC, &ohci->regs->roothub.status); | 694 | ohci_writel (ohci, RH_HS_LPSC, &ohci->regs->roothub.status); |
| 691 | ohci_writel (ohci, (val & RH_A_NPS) ? 0 : RH_B_PPCM, | 695 | ohci_writel (ohci, (val & RH_A_NPS) ? 0 : RH_B_PPCM, |
| 692 | &ohci->regs->roothub.b); | 696 | &ohci->regs->roothub.b); |
| @@ -24,6 +24,7 @@ · 23 unmodified lines | |||
| 24 | #include <linux/moduleparam.h> | 24 | #include <linux/moduleparam.h> |
| 25 | #include <linux/dma-mapping.h> | 25 | #include <linux/dma-mapping.h> |
| 26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
| 27 | #include <linux/iopoll.h> | ||
| 27 | 28 | ||
| 28 | #include <asm/irq.h> | 29 | #include <asm/irq.h> |
| 29 | #include <asm/unaligned.h> | 30 | #include <asm/unaligned.h> |
| @@ -748,18 +749,16 @@ static int handshake(struct oxu_hcd *oxu, void __iomem *ptr, · 718 unmodified lines | |||
| 748 | u32 mask, u32 done, int usec) | 749 | u32 mask, u32 done, int usec) |
| 749 | { | 750 | { |
| 750 | u32 result; | 751 | u32 result; |
| 752 | int ret; | ||
| 751 | 753 | ||
| 752 | do { | 754 | ret = readl_poll_timeout_atomic(ptr, result, |
| 753 | result = readl(ptr); | 755 | ((result & mask) == done || |
| 754 | if (result == ~(u32)0) /* card removed */ | 756 | result == U32_MAX), |
| 755 | return -ENODEV; | 757 | 1, usec); |
| 756 | result &= mask; | 758 | if (result == U32_MAX) /* card removed */ |
| 757 | if (result == done) | 759 | return -ENODEV; |
| 758 | return 0; | 760 | |
| 759 | udelay(1); | 761 | return ret; |
| 760 | usec--; | ||
| 761 | } while (usec > 0); | ||
| 762 | return -ETIMEDOUT; | ||
| 763 | } | 762 | } |
| 764 | 763 | ||
| 765 | /* Force HC to halt state from unknown (EHCI spec section 2.3) */ | 764 | /* Force HC to halt state from unknown (EHCI spec section 2.3) */ |
| @@ -16,8 +16,8 @@ · 15 unmodified lines | |||
| 16 | #include <linux/export.h> | 16 | #include <linux/export.h> |
| 17 | #include <linux/acpi.h> | 17 | #include <linux/acpi.h> |
| 18 | #include <linux/dmi.h> | 18 | #include <linux/dmi.h> |
| 19 | 19 | #include <linux/of.h> | |
| 20 | #include <soc/bcm2835/raspberrypi-firmware.h> | 20 | #include <linux/iopoll.h> |
| 21 | 21 | ||
| 22 | #include "pci-quirks.h" | 22 | #include "pci-quirks.h" |
| 23 | #include "xhci-ext-caps.h" | 23 | #include "xhci-ext-caps.h" |
| @@ -1013,15 +1013,9 @@ static int handshake(void __iomem *ptr, u32 mask, u32 done, · 989 unmodified lines | |||
| 1013 | { | 1013 | { |
| 1014 | u32 result; | 1014 | u32 result; |
| 1015 | 1015 | ||
| 1016 | do { | 1016 | return readl_poll_timeout_atomic(ptr, result, |
| 1017 | result = readl(ptr); | 1017 | ((result & mask) == done), |
| 1018 | result &= mask; | 1018 | delay_usec, wait_usec); |
| 1019 | if (result == done) | ||
| 1020 | return 0; | ||
| 1021 | udelay(delay_usec); | ||
| 1022 | wait_usec -= delay_usec; | ||
| 1023 | } while (wait_usec > 0); | ||
| 1024 | return -ETIMEDOUT; | ||
| 1025 | } | 1019 | } |
| 1026 | 1020 | ||
| 1027 | /* | 1021 | /* |
| @@ -1247,7 +1241,8 @@ iounmap: · 219 unmodified lines | |||
| 1247 | 1241 | ||
| 1248 | static void quirk_usb_early_handoff(struct pci_dev *pdev) | 1242 | static void quirk_usb_early_handoff(struct pci_dev *pdev) |
| 1249 | { | 1243 | { |
| 1250 | int ret; | 1244 | struct device_node *parent; |
| 1245 | bool is_rpi; | ||
| 1251 | 1246 | ||
| 1252 | /* Skip Netlogic mips SoC's internal PCI USB controller. | 1247 | /* Skip Netlogic mips SoC's internal PCI USB controller. |
| 1253 | * This device does not need/support EHCI/OHCI handoff | 1248 | * This device does not need/support EHCI/OHCI handoff |
| @@ -1255,14 +1250,16 @@ static void quirk_usb_early_handoff(struct pci_dev *pdev) · 1 unmodified line | |||
| 1255 | if (pdev->vendor == 0x184e) /* vendor Netlogic */ | 1250 | if (pdev->vendor == 0x184e) /* vendor Netlogic */ |
| 1256 | return; | 1251 | return; |
| 1257 | 1252 | ||
| 1253 | /* | ||
| 1254 | * Bypass the Raspberry Pi 4 controller xHCI controller, things are | ||
| 1255 | * taken care of by the board's co-processor. | ||
| 1256 | */ | ||
| 1258 | if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == 0x3483) { | 1257 | if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == 0x3483) { |
| 1259 | ret = rpi_firmware_init_vl805(pdev); | 1258 | parent = of_get_parent(pdev->bus->dev.of_node); |
| 1260 | if (ret) { | 1259 | is_rpi = of_device_is_compatible(parent, "brcm,bcm2711-pcie"); |
| 1261 | /* Firmware might be outdated, or something failed */ | 1260 | of_node_put(parent); |
| 1262 | dev_warn(&pdev->dev, | 1261 | if (is_rpi) |
| 1263 | "Failed to load VL805's firmware: %d. Will continue to attempt to work, but bad things might happen. You should fix this...\n", | 1262 | return; |
| 1264 | ret); | ||
| 1265 | } | ||
| 1266 | } | 1263 | } |
| 1267 | 1264 | ||
| 1268 | if (pdev->class != PCI_CLASS_SERIAL_USB_UHCI && | 1265 | if (pdev->class != PCI_CLASS_SERIAL_USB_UHCI && |
| @@ -288,14 +288,14 @@ static const struct tty_operations dbc_tty_ops = { · 287 unmodified lines | |||
| 288 | .unthrottle = dbc_tty_unthrottle, | 288 | .unthrottle = dbc_tty_unthrottle, |
| 289 | }; | 289 | }; |
| 290 | 290 | ||
| 291 | static void dbc_rx_push(unsigned long _port) | 291 | static void dbc_rx_push(struct tasklet_struct *t) |
| 292 | { | 292 | { |
| 293 | struct dbc_request *req; | 293 | struct dbc_request *req; |
| 294 | struct tty_struct *tty; | 294 | struct tty_struct *tty; |
| 295 | unsigned long flags; | 295 | unsigned long flags; |
| 296 | bool do_push = false; | 296 | bool do_push = false; |
| 297 | bool disconnect = false; | 297 | bool disconnect = false; |
| 298 | struct dbc_port *port = (void *)_port; | 298 | struct dbc_port *port = from_tasklet(port, t, push); |
| 299 | struct list_head *queue = &port->read_queue; | 299 | struct list_head *queue = &port->read_queue; |
| 300 | 300 | ||
| 301 | spin_lock_irqsave(&port->port_lock, flags); | 301 | spin_lock_irqsave(&port->port_lock, flags); |
| @@ -382,7 +382,7 @@ xhci_dbc_tty_init_port(struct xhci_dbc *dbc, struct dbc_port *port) · 80 unmodified lines | |||
| 382 | { | 382 | { |
| 383 | tty_port_init(&port->port); | 383 | tty_port_init(&port->port); |
| 384 | spin_lock_init(&port->port_lock); | 384 | spin_lock_init(&port->port_lock); |
| 385 | tasklet_init(&port->push, dbc_rx_push, (unsigned long)port); | 385 | tasklet_setup(&port->push, dbc_rx_push); |
| 386 | INIT_LIST_HEAD(&port->read_pool); | 386 | INIT_LIST_HEAD(&port->read_pool); |
| 387 | INIT_LIST_HEAD(&port->read_queue); | 387 | INIT_LIST_HEAD(&port->read_queue); |
| 388 | INIT_LIST_HEAD(&port->write_pool); | 388 | INIT_LIST_HEAD(&port->write_pool); |
| @@ -451,9 +451,11 @@ void xhci_debugfs_create_endpoint(struct xhci_hcd *xhci, · 450 unmodified lines | |||
| 451 | if (!epriv) | 451 | if (!epriv) |
| 452 | return; | 452 | return; |
| 453 | 453 | ||
| 454 | epriv->show_ring = dev->eps[ep_index].ring; | ||
| 455 | |||
| 454 | snprintf(epriv->name, sizeof(epriv->name), "ep%02d", ep_index); | 456 | snprintf(epriv->name, sizeof(epriv->name), "ep%02d", ep_index); |
| 455 | epriv->root = xhci_debugfs_create_ring_dir(xhci, | 457 | epriv->root = xhci_debugfs_create_ring_dir(xhci, |
| 456 | &dev->eps[ep_index].ring, | 458 | &epriv->show_ring, |
| 457 | epriv->name, | 459 | epriv->name, |
| 458 | spriv->root); | 460 | spriv->root); |
| 459 | spriv->eps[ep_index] = epriv; | 461 | spriv->eps[ep_index] = epriv; |
| @@ -475,6 +477,111 @@ void xhci_debugfs_remove_endpoint(struct xhci_hcd *xhci, · 15 unmodified lines | |||
| 475 | kfree(epriv); | 477 | kfree(epriv); |
| 476 | } | 478 | } |
| 477 | 479 | ||
| 480 | static int xhci_stream_id_show(struct seq_file *s, void *unused) | ||
| 481 | { | ||
| 482 | struct xhci_ep_priv *epriv = s->private; | ||
| 483 | |||
| 484 | if (!epriv->stream_info) | ||
| 485 | return -EPERM; | ||
| 486 | |||
| 487 | seq_printf(s, "Show stream ID %d trb ring, supported [1 - %d]\n", | ||
| 488 | epriv->stream_id, epriv->stream_info->num_streams - 1); | ||
| 489 | |||
| 490 | return 0; | ||
| 491 | } | ||
| 492 | |||
| 493 | static int xhci_stream_id_open(struct inode *inode, struct file *file) | ||
| 494 | { | ||
| 495 | return single_open(file, xhci_stream_id_show, inode->i_private); | ||
| 496 | } | ||
| 497 | |||
| 498 | static ssize_t xhci_stream_id_write(struct file *file, const char __user *ubuf, | ||
| 499 | size_t count, loff_t *ppos) | ||
| 500 | { | ||
| 501 | struct seq_file *s = file->private_data; | ||
| 502 | struct xhci_ep_priv *epriv = s->private; | ||
| 503 | int ret; | ||
| 504 | u16 stream_id; /* MaxPStreams + 1 <= 16 */ | ||
| 505 | |||
| 506 | if (!epriv->stream_info) | ||
| 507 | return -EPERM; | ||
| 508 | |||
| 509 | /* Decimal number */ | ||
| 510 | ret = kstrtou16_from_user(ubuf, count, 10, &stream_id); | ||
| 511 | if (ret) | ||
| 512 | return ret; | ||
| 513 | |||
| 514 | if (stream_id == 0 || stream_id >= epriv->stream_info->num_streams) | ||
| 515 | return -EINVAL; | ||
| 516 | |||
| 517 | epriv->stream_id = stream_id; | ||
| 518 | epriv->show_ring = epriv->stream_info->stream_rings[stream_id]; | ||
| 519 | |||
| 520 | return count; | ||
| 521 | } | ||
| 522 | |||
| 523 | static const struct file_operations stream_id_fops = { | ||
| 524 | .open = xhci_stream_id_open, | ||
| 525 | .write = xhci_stream_id_write, | ||
| 526 | .read = seq_read, | ||
| 527 | .llseek = seq_lseek, | ||
| 528 | .release = single_release, | ||
| 529 | }; | ||
| 530 | |||
| 531 | static int xhci_stream_context_array_show(struct seq_file *s, void *unused) | ||
| 532 | { | ||
| 533 | struct xhci_ep_priv *epriv = s->private; | ||
| 534 | struct xhci_stream_ctx *stream_ctx; | ||
| 535 | dma_addr_t dma; | ||
| 536 | int id; | ||
| 537 | |||
| 538 | if (!epriv->stream_info) | ||
| 539 | return -EPERM; | ||
| 540 | |||
| 541 | seq_printf(s, "Allocated %d streams and %d stream context array entries\n", | ||
| 542 | epriv->stream_info->num_streams, | ||
| 543 | epriv->stream_info->num_stream_ctxs); | ||
| 544 | |||
| 545 | for (id = 0; id < epriv->stream_info->num_stream_ctxs; id++) { | ||
| 546 | stream_ctx = epriv->stream_info->stream_ctx_array + id; | ||
| 547 | dma = epriv->stream_info->ctx_array_dma + id * 16; | ||
| 548 | if (id < epriv->stream_info->num_streams) | ||
| 549 | seq_printf(s, "%pad stream id %d deq %016llx\n", &dma, | ||
| 550 | id, le64_to_cpu(stream_ctx->stream_ring)); | ||
| 551 | else | ||
| 552 | seq_printf(s, "%pad stream context entry not used deq %016llx\n", | ||
| 553 | &dma, le64_to_cpu(stream_ctx->stream_ring)); | ||
| 554 | } | ||
| 555 | |||
| 556 | return 0; | ||
| 557 | } | ||
| 558 | DEFINE_SHOW_ATTRIBUTE(xhci_stream_context_array); | ||
| 559 | |||
| 560 | void xhci_debugfs_create_stream_files(struct xhci_hcd *xhci, | ||
| 561 | struct xhci_virt_device *dev, | ||
| 562 | int ep_index) | ||
| 563 | { | ||
| 564 | struct xhci_slot_priv *spriv = dev->debugfs_private; | ||
| 565 | struct xhci_ep_priv *epriv; | ||
| 566 | |||
| 567 | if (!spriv || !spriv->eps[ep_index] || | ||
| 568 | !dev->eps[ep_index].stream_info) | ||
| 569 | return; | ||
| 570 | |||
| 571 | epriv = spriv->eps[ep_index]; | ||
| 572 | epriv->stream_info = dev->eps[ep_index].stream_info; | ||
| 573 | |||
| 574 | /* Show trb ring of stream ID 1 by default */ | ||
| 575 | epriv->stream_id = 1; | ||
| 576 | epriv->show_ring = epriv->stream_info->stream_rings[1]; | ||
| 577 | debugfs_create_file("stream_id", 0644, | ||
| 578 | epriv->root, epriv, | ||
| 579 | &stream_id_fops); | ||
| 580 | debugfs_create_file("stream_context_array", 0444, | ||
| 581 | epriv->root, epriv, | ||
| 582 | &xhci_stream_context_array_fops); | ||
| 583 | } | ||
| 584 | |||
| 478 | void xhci_debugfs_create_slot(struct xhci_hcd *xhci, int slot_id) | 585 | void xhci_debugfs_create_slot(struct xhci_hcd *xhci, int slot_id) |
| 479 | { | 586 | { |
| 480 | struct xhci_slot_priv *priv; | 587 | struct xhci_slot_priv *priv; |
| @@ -91,6 +91,9 @@ struct xhci_file_map { · 90 unmodified lines | |||
| 91 | struct xhci_ep_priv { | 91 | struct xhci_ep_priv { |
| 92 | char name[DEBUGFS_NAMELEN]; | 92 | char name[DEBUGFS_NAMELEN]; |
| 93 | struct dentry *root; | 93 | struct dentry *root; |
| 94 | struct xhci_stream_info *stream_info; | ||
| 95 | struct xhci_ring *show_ring; | ||
| 96 | unsigned int stream_id; | ||
| 94 | }; | 97 | }; |
| 95 | 98 | ||
| 96 | struct xhci_slot_priv { | 99 | struct xhci_slot_priv { |
| @@ -113,6 +116,9 @@ void xhci_debugfs_create_endpoint(struct xhci_hcd *xhci, · 16 unmodified lines | |||
| 113 | void xhci_debugfs_remove_endpoint(struct xhci_hcd *xhci, | 116 | void xhci_debugfs_remove_endpoint(struct xhci_hcd *xhci, |
| 114 | struct xhci_virt_device *virt_dev, | 117 | struct xhci_virt_device *virt_dev, |
| 115 | int ep_index); | 118 | int ep_index); |
| 119 | void xhci_debugfs_create_stream_files(struct xhci_hcd *xhci, | ||
| 120 | struct xhci_virt_device *virt_dev, | ||
| 121 | int ep_index); | ||
| 116 | #else | 122 | #else |
| 117 | static inline void xhci_debugfs_init(struct xhci_hcd *xhci) { } | 123 | static inline void xhci_debugfs_init(struct xhci_hcd *xhci) { } |
| 118 | static inline void xhci_debugfs_exit(struct xhci_hcd *xhci) { } | 124 | static inline void xhci_debugfs_exit(struct xhci_hcd *xhci) { } |
| @@ -128,6 +134,10 @@ static inline void · 9 unmodified lines | |||
| 128 | xhci_debugfs_remove_endpoint(struct xhci_hcd *xhci, | 134 | xhci_debugfs_remove_endpoint(struct xhci_hcd *xhci, |
| 129 | struct xhci_virt_device *virt_dev, | 135 | struct xhci_virt_device *virt_dev, |
| 130 | int ep_index) { } | 136 | int ep_index) { } |
| 137 | static inline void | ||
| 138 | xhci_debugfs_create_stream_files(struct xhci_hcd *xhci, | ||
| 139 | struct xhci_virt_device *virt_dev, | ||
| 140 | int ep_index) { } | ||
| 131 | #endif /* CONFIG_DEBUG_FS */ | 141 | #endif /* CONFIG_DEBUG_FS */ |
| 132 | 142 | ||
| 133 | #endif /* __LINUX_XHCI_DEBUGFS_H */ | 143 | #endif /* __LINUX_XHCI_DEBUGFS_H */ |
| @@ -77,7 +77,7 @@ static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk) · 76 unmodified lines | |||
| 77 | { | 77 | { |
| 78 | struct mu3c_ippc_regs __iomem *ippc = mtk->ippc_regs; | 78 | struct mu3c_ippc_regs __iomem *ippc = mtk->ippc_regs; |
| 79 | u32 value, check_val; | 79 | u32 value, check_val; |
| 80 | int u3_ports_disabed = 0; | 80 | int u3_ports_disabled = 0; |
| 81 | int ret; | 81 | int ret; |
| 82 | int i; | 82 | int i; |
| 83 | 83 | ||
| @@ -92,7 +92,7 @@ static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk) · 8 unmodified lines | |||
| 92 | /* power on and enable u3 ports except skipped ones */ | 92 | /* power on and enable u3 ports except skipped ones */ |
| 93 | for (i = 0; i < mtk->num_u3_ports; i++) { | 93 | for (i = 0; i < mtk->num_u3_ports; i++) { |
| 94 | if ((0x1 << i) & mtk->u3p_dis_msk) { | 94 | if ((0x1 << i) & mtk->u3p_dis_msk) { |
| 95 | u3_ports_disabed++; | 95 | u3_ports_disabled++; |
| 96 | continue; | 96 | continue; |
| 97 | } | 97 | } |
| 98 | 98 | ||
| @@ -117,7 +117,7 @@ static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk) · 18 unmodified lines | |||
| 117 | check_val = STS1_SYSPLL_STABLE | STS1_REF_RST | | 117 | check_val = STS1_SYSPLL_STABLE | STS1_REF_RST | |
| 118 | STS1_SYS125_RST | STS1_XHCI_RST; | 118 | STS1_SYS125_RST | STS1_XHCI_RST; |
| 119 | 119 | ||
| 120 | if (mtk->num_u3_ports > u3_ports_disabed) | 120 | if (mtk->num_u3_ports > u3_ports_disabled) |
| 121 | check_val |= STS1_U3_MAC_RST; | 121 | check_val |= STS1_U3_MAC_RST; |
| 122 | 122 | ||
| 123 | ret = readl_poll_timeout(&ippc->ip_pw_sts1, value, | 123 | ret = readl_poll_timeout(&ippc->ip_pw_sts1, value, |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | |||
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
| 14 | #include <linux/acpi.h> | 14 | #include <linux/acpi.h> |
| 15 | #include <linux/reset.h> | ||
| 15 | 16 | ||
| 16 | #include "xhci.h" | 17 | #include "xhci.h" |
| 17 | #include "xhci-trace.h" | 18 | #include "xhci-trace.h" |
| @@ -346,6 +347,7 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) · 328 unmodified lines | |||
| 346 | struct xhci_hcd *xhci; | 347 | struct xhci_hcd *xhci; |
| 347 | struct usb_hcd *hcd; | 348 | struct usb_hcd *hcd; |
| 348 | struct xhci_driver_data *driver_data; | 349 | struct xhci_driver_data *driver_data; |
| 350 | struct reset_control *reset; | ||
| 349 | 351 | ||
| 350 | driver_data = (struct xhci_driver_data *)id->driver_data; | 352 | driver_data = (struct xhci_driver_data *)id->driver_data; |
| 351 | if (driver_data && driver_data->quirks & XHCI_RENESAS_FW_QUIRK) { | 353 | if (driver_data && driver_data->quirks & XHCI_RENESAS_FW_QUIRK) { |
| @@ -354,6 +356,11 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) · 2 unmodified lines | |||
| 354 | return retval; | 356 | return retval; |
| 355 | } | 357 | } |
| 356 | 358 | ||
| 359 | reset = devm_reset_control_get_optional_exclusive(&dev->dev, NULL); | ||
| 360 | if (IS_ERR(reset)) | ||
| 361 | return PTR_ERR(reset); | ||
| 362 | reset_control_reset(reset); | ||
| 363 | |||
| 357 | /* Prevent runtime suspending between USB-2 and USB-3 initialization */ | 364 | /* Prevent runtime suspending between USB-2 and USB-3 initialization */ |
| 358 | pm_runtime_get_noresume(&dev->dev); | 365 | pm_runtime_get_noresume(&dev->dev); |
| 359 | 366 | ||
| @@ -371,6 +378,7 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) · 11 unmodified lines | |||
| 371 | /* USB 2.0 roothub is stored in the PCI device now. */ | 378 | /* USB 2.0 roothub is stored in the PCI device now. */ |
| 372 | hcd = dev_get_drvdata(&dev->dev); | 379 | hcd = dev_get_drvdata(&dev->dev); |
| 373 | xhci = hcd_to_xhci(hcd); | 380 | xhci = hcd_to_xhci(hcd); |
| 381 | xhci->reset = reset; | ||
| 374 | xhci->shared_hcd = usb_create_shared_hcd(&xhci_pci_hc_driver, &dev->dev, | 382 | xhci->shared_hcd = usb_create_shared_hcd(&xhci_pci_hc_driver, &dev->dev, |
| 375 | pci_name(dev), hcd); | 383 | pci_name(dev), hcd); |
| 376 | if (!xhci->shared_hcd) { | 384 | if (!xhci->shared_hcd) { |
| @@ -522,6 +530,8 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated) · 145 unmodified lines | |||
| 522 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); | 530 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); |
| 523 | int retval = 0; | 531 | int retval = 0; |
| 524 | 532 | ||
| 533 | reset_control_reset(xhci->reset); | ||
| 534 | |||
| 525 | /* The BIOS on systems with the Intel Panther Point chipset may or may | 535 | /* The BIOS on systems with the Intel Panther Point chipset may or may |
| 526 | * not support xHCI natively. That means that during system resume, it | 536 | * not support xHCI natively. That means that during system resume, it |
| 527 | * may switch the ports back to EHCI so that users can use their | 537 | * may switch the ports back to EHCI so that users can use their |
| @@ -54,6 +54,16 @@ static int xhci_priv_init_quirk(struct usb_hcd *hcd) · 53 unmodified lines | |||
| 54 | return priv->init_quirk(hcd); | 54 | return priv->init_quirk(hcd); |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | static int xhci_priv_suspend_quirk(struct usb_hcd *hcd) | ||
| 58 | { | ||
| 59 | struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); | ||
| 60 | |||
| 61 | if (!priv->suspend_quirk) | ||
| 62 | return 0; | ||
| 63 | |||
| 64 | return priv->suspend_quirk(hcd); | ||
| 65 | } | ||
| 66 | |||
| 57 | static int xhci_priv_resume_quirk(struct usb_hcd *hcd) | 67 | static int xhci_priv_resume_quirk(struct usb_hcd *hcd) |
| 58 | { | 68 | { |
| 59 | struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); | 69 | struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); |
| @@ -173,6 +183,8 @@ static int xhci_plat_probe(struct platform_device *pdev) · 113 unmodified lines | |||
| 173 | struct usb_hcd *hcd; | 183 | struct usb_hcd *hcd; |
| 174 | int ret; | 184 | int ret; |
| 175 | int irq; | 185 | int irq; |
| 186 | struct xhci_plat_priv *priv = NULL; | ||
| 187 | |||
| 176 | 188 | ||
| 177 | if (usb_disabled()) | 189 | if (usb_disabled()) |
| 178 | return -ENODEV; | 190 | return -ENODEV; |
| @@ -264,16 +276,18 @@ static int xhci_plat_probe(struct platform_device *pdev) · 85 unmodified lines | |||
| 264 | if (ret) | 276 | if (ret) |
| 265 | goto disable_reg_clk; | 277 | goto disable_reg_clk; |
| 266 | 278 | ||
| 267 | priv_match = of_device_get_match_data(&pdev->dev); | 279 | if (pdev->dev.of_node) |
| 268 | if (priv_match) { | 280 | priv_match = of_device_get_match_data(&pdev->dev); |
| 269 | struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); | 281 | else |
| 282 | priv_match = dev_get_platdata(&pdev->dev); | ||
| 270 | 283 | ||
| 284 | if (priv_match) { | ||
| 285 | priv = hcd_to_xhci_priv(hcd); | ||
| 271 | /* Just copy data for now */ | 286 | /* Just copy data for now */ |
| 272 | if (priv_match) | 287 | *priv = *priv_match; |
| 273 | *priv = *priv_match; | ||
| 274 | } | 288 | } |
| 275 | 289 | ||
| 276 | device_wakeup_enable(hcd->self.controller); | 290 | device_set_wakeup_capable(&pdev->dev, true); |
| 277 | 291 | ||
| 278 | xhci->main_hcd = hcd; | 292 | xhci->main_hcd = hcd; |
| 279 | xhci->shared_hcd = __usb_create_hcd(driver, sysdev, &pdev->dev, | 293 | xhci->shared_hcd = __usb_create_hcd(driver, sysdev, &pdev->dev, |
| @@ -316,6 +330,9 @@ static int xhci_plat_probe(struct platform_device *pdev) · 36 unmodified lines | |||
| 316 | 330 | ||
| 317 | hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node); | 331 | hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node); |
| 318 | xhci->shared_hcd->tpl_support = hcd->tpl_support; | 332 | xhci->shared_hcd->tpl_support = hcd->tpl_support; |
| 333 | if (priv && (priv->quirks & XHCI_SKIP_PHY_INIT)) | ||
| 334 | hcd->skip_phy_initialization = 1; | ||
| 335 | |||
| 319 | ret = usb_add_hcd(hcd, irq, IRQF_SHARED); | 336 | ret = usb_add_hcd(hcd, irq, IRQF_SHARED); |
| 320 | if (ret) | 337 | if (ret) |
| 321 | goto disable_usb_phy; | 338 | goto disable_usb_phy; |
| @@ -397,14 +414,14 @@ static int __maybe_unused xhci_plat_suspend(struct device *dev) · 75 unmodified lines | |||
| 397 | { | 414 | { |
| 398 | struct usb_hcd *hcd = dev_get_drvdata(dev); | 415 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
| 399 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 416 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
| 417 | int ret; | ||
| 400 | 418 | ||
| 419 | ret = xhci_priv_suspend_quirk(hcd); | ||
| 420 | if (ret) | ||
| 421 | return ret; | ||
| 401 | /* | 422 | /* |
| 402 | * xhci_suspend() needs `do_wakeup` to know whether host is allowed | 423 | * xhci_suspend() needs `do_wakeup` to know whether host is allowed |
| 403 | * to do wakeup during suspend. Since xhci_plat_suspend is currently | 424 | * to do wakeup during suspend. |
| 404 | * only designed for system suspend, device_may_wakeup() is enough | ||
| 405 | * to dertermine whether host is allowed to do wakeup. Need to | ||
| 406 | * reconsider this when xhci_plat_suspend enlarges its scope, e.g., | ||
| 407 | * also applies to runtime suspend. | ||
| 408 | */ | 425 | */ |
| 409 | return xhci_suspend(xhci, device_may_wakeup(dev)); | 426 | return xhci_suspend(xhci, device_may_wakeup(dev)); |
| 410 | } | 427 | } |
| @@ -434,6 +451,11 @@ static int __maybe_unused xhci_plat_runtime_suspend(struct device *dev) · 23 unmodified lines | |||
| 434 | { | 451 | { |
| 435 | struct usb_hcd *hcd = dev_get_drvdata(dev); | 452 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
| 436 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 453 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
| 454 | int ret; | ||
| 455 | |||
| 456 | ret = xhci_priv_suspend_quirk(hcd); | ||
| 457 | if (ret) | ||
| 458 | return ret; | ||
| 437 | 459 | ||
| 438 | return xhci_suspend(xhci, true); | 460 | return xhci_suspend(xhci, true); |
| 439 | } | 461 | } |
| @@ -15,6 +15,7 @@ struct xhci_plat_priv { · 14 unmodified lines | |||
| 15 | unsigned long long quirks; | 15 | unsigned long long quirks; |
| 16 | void (*plat_start)(struct usb_hcd *); | 16 | void (*plat_start)(struct usb_hcd *); |
| 17 | int (*init_quirk)(struct usb_hcd *); | 17 | int (*init_quirk)(struct usb_hcd *); |
| 18 | int (*suspend_quirk)(struct usb_hcd *); | ||
| 18 | int (*resume_quirk)(struct usb_hcd *); | 19 | int (*resume_quirk)(struct usb_hcd *); |
| 19 | }; | 20 | }; |
| 20 | 21 | ||
| @@ -6,6 +6,7 @@ · 5 unmodified lines | |||
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | #include <linux/firmware.h> | 8 | #include <linux/firmware.h> |
| 9 | #include <linux/iopoll.h> | ||
| 9 | #include <linux/module.h> | 10 | #include <linux/module.h> |
| 10 | #include <linux/platform_device.h> | 11 | #include <linux/platform_device.h> |
| 11 | #include <linux/of.h> | 12 | #include <linux/of.h> |
| @@ -127,8 +128,7 @@ static int xhci_rcar_download_firmware(struct usb_hcd *hcd) · 115 unmodified lines | |||
| 127 | void __iomem *regs = hcd->regs; | 128 | void __iomem *regs = hcd->regs; |
| 128 | struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); | 129 | struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); |
| 129 | const struct firmware *fw; | 130 | const struct firmware *fw; |
| 130 | int retval, index, j, time; | 131 | int retval, index, j; |
| 131 | int timeout = 10000; | ||
| 132 | u32 data, val, temp; | 132 | u32 data, val, temp; |
| 133 | u32 quirks = 0; | 133 | u32 quirks = 0; |
| 134 | const struct soc_device_attribute *attr; | 134 | const struct soc_device_attribute *attr; |
| @@ -166,32 +166,19 @@ static int xhci_rcar_download_firmware(struct usb_hcd *hcd) · 31 unmodified lines | |||
| 166 | temp |= RCAR_USB3_DL_CTRL_FW_SET_DATA0; | 166 | temp |= RCAR_USB3_DL_CTRL_FW_SET_DATA0; |
| 167 | writel(temp, regs + RCAR_USB3_DL_CTRL); | 167 | writel(temp, regs + RCAR_USB3_DL_CTRL); |
| 168 | 168 | ||
| 169 | for (time = 0; time < timeout; time++) { | 169 | retval = readl_poll_timeout_atomic(regs + RCAR_USB3_DL_CTRL, |
| 170 | val = readl(regs + RCAR_USB3_DL_CTRL); | 170 | val, !(val & RCAR_USB3_DL_CTRL_FW_SET_DATA0), |
| 171 | if ((val & RCAR_USB3_DL_CTRL_FW_SET_DATA0) == 0) | 171 | 1, 10000); |
| 172 | break; | 172 | if (retval < 0) |
| 173 | udelay(1); | ||
| 174 | } | ||
| 175 | if (time == timeout) { | ||
| 176 | retval = -ETIMEDOUT; | ||
| 177 | break; | 173 | break; |
| 178 | } | ||
| 179 | } | 174 | } |
| 180 | 175 | ||
| 181 | temp = readl(regs + RCAR_USB3_DL_CTRL); | 176 | temp = readl(regs + RCAR_USB3_DL_CTRL); |
| 182 | temp &= ~RCAR_USB3_DL_CTRL_ENABLE; | 177 | temp &= ~RCAR_USB3_DL_CTRL_ENABLE; |
| 183 | writel(temp, regs + RCAR_USB3_DL_CTRL); | 178 | writel(temp, regs + RCAR_USB3_DL_CTRL); |
| 184 | 179 | ||
| 185 | for (time = 0; time < timeout; time++) { | 180 | retval = readl_poll_timeout_atomic((regs + RCAR_USB3_DL_CTRL), |
| 186 | val = readl(regs + RCAR_USB3_DL_CTRL); | 181 | val, val & RCAR_USB3_DL_CTRL_FW_SUCCESS, 1, 10000); |
| 187 | if (val & RCAR_USB3_DL_CTRL_FW_SUCCESS) { | ||
| 188 | retval = 0; | ||
| 189 | break; | ||
| 190 | } | ||
| 191 | udelay(1); | ||
| 192 | } | ||
| 193 | if (time == timeout) | ||
| 194 | retval = -ETIMEDOUT; | ||
| 195 | 182 | ||
| 196 | release_firmware(fw); | 183 | release_firmware(fw); |
| 197 | 184 | ||
| @@ -200,18 +187,12 @@ static int xhci_rcar_download_firmware(struct usb_hcd *hcd) · 2 unmodified lines | |||
| 200 | 187 | ||
| 201 | static bool xhci_rcar_wait_for_pll_active(struct usb_hcd *hcd) | 188 | static bool xhci_rcar_wait_for_pll_active(struct usb_hcd *hcd) |
| 202 | { | 189 | { |
| 203 | int timeout = 1000; | 190 | int retval; |
| 204 | u32 val, mask = RCAR_USB3_AXH_STA_PLL_ACTIVE_MASK; | 191 | u32 val, mask = RCAR_USB3_AXH_STA_PLL_ACTIVE_MASK; |
| 205 | 192 | ||
| 206 | while (timeout > 0) { | 193 | retval = readl_poll_timeout_atomic(hcd->regs + RCAR_USB3_AXH_STA, |
| 207 | val = readl(hcd->regs + RCAR_USB3_AXH_STA); | 194 | val, (val & mask) == mask, 1, 1000); |
| 208 | if ((val & mask) == mask) | 195 | return !retval; |
| 209 | return true; | ||
| 210 | udelay(1); | ||
| 211 | timeout--; | ||
| 212 | } | ||
| 213 | |||
| 214 | return false; | ||
| 215 | } | 196 | } |
| 216 | 197 | ||
| 217 | /* This function needs to initialize a "phy" of usb before */ | 198 | /* This function needs to initialize a "phy" of usb before */ |
| @@ -3736,6 +3736,24 @@ static int xhci_get_isoc_frame_id(struct xhci_hcd *xhci, · 3735 unmodified lines | |||
| 3736 | return start_frame; | 3736 | return start_frame; |
| 3737 | } | 3737 | } |
| 3738 | 3738 | ||
| 3739 | /* Check if we should generate event interrupt for a TD in an isoc URB */ | ||
| 3740 | static bool trb_block_event_intr(struct xhci_hcd *xhci, int num_tds, int i) | ||
| 3741 | { | ||
| 3742 | if (xhci->hci_version < 0x100) | ||
| 3743 | return false; | ||
| 3744 | /* always generate an event interrupt for the last TD */ | ||
| 3745 | if (i == num_tds - 1) | ||
| 3746 | return false; | ||
| 3747 | /* | ||
| 3748 | * If AVOID_BEI is set the host handles full event rings poorly, | ||
| 3749 | * generate an event at least every 8th TD to clear the event ring | ||
| 3750 | */ | ||
| 3751 | if (i && xhci->quirks & XHCI_AVOID_BEI) | ||
| 3752 | return !!(i % 8); | ||
| 3753 | |||
| 3754 | return true; | ||
| 3755 | } | ||
| 3756 | |||
| 3739 | /* This is for isoc transfer */ | 3757 | /* This is for isoc transfer */ |
| 3740 | static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, | 3758 | static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, |
| 3741 | struct urb *urb, int slot_id, unsigned int ep_index) | 3759 | struct urb *urb, int slot_id, unsigned int ep_index) |
| @@ -3843,10 +3861,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, · 101 unmodified lines | |||
| 3843 | more_trbs_coming = false; | 3861 | more_trbs_coming = false; |
| 3844 | td->last_trb = ep_ring->enqueue; | 3862 | td->last_trb = ep_ring->enqueue; |
| 3845 | field |= TRB_IOC; | 3863 | field |= TRB_IOC; |
| 3846 | /* set BEI, except for the last TD */ | 3864 | if (trb_block_event_intr(xhci, num_tds, i)) |
| 3847 | if (xhci->hci_version >= 0x100 && | ||
| 3848 | !(xhci->quirks & XHCI_AVOID_BEI) && | ||
| 3849 | i < num_tds - 1) | ||
| 3850 | field |= TRB_BEI; | 3865 | field |= TRB_BEI; |
| 3851 | } | 3866 | } |
| 3852 | /* Calculate TRB length */ | 3867 | /* Calculate TRB length */ |
| @@ -1865,7 +1865,6 @@ static const struct tegra_xusb_phy_type tegra124_phy_types[] = { · 1864 unmodified lines | |||
| 1865 | }; | 1865 | }; |
| 1866 | 1866 | ||
| 1867 | static const unsigned int tegra124_xusb_context_ipfs[] = { | 1867 | static const unsigned int tegra124_xusb_context_ipfs[] = { |
| 1868 | IPFS_XUSB_HOST_MSI_BAR_SZ_0, | ||
| 1869 | IPFS_XUSB_HOST_MSI_BAR_SZ_0, | 1868 | IPFS_XUSB_HOST_MSI_BAR_SZ_0, |
| 1870 | IPFS_XUSB_HOST_MSI_AXI_BAR_ST_0, | 1869 | IPFS_XUSB_HOST_MSI_AXI_BAR_ST_0, |
| 1871 | IPFS_XUSB_HOST_MSI_FPCI_BAR_ST_0, | 1870 | IPFS_XUSB_HOST_MSI_FPCI_BAR_ST_0, |
| @@ -982,12 +982,15 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) · 981 unmodified lines | |||
| 982 | xhci->shared_hcd->state != HC_STATE_SUSPENDED) | 982 | xhci->shared_hcd->state != HC_STATE_SUSPENDED) |
| 983 | return -EINVAL; | 983 | return -EINVAL; |
| 984 | 984 | ||
| 985 | xhci_dbc_suspend(xhci); | ||
| 986 | |||
| 987 | /* Clear root port wake on bits if wakeup not allowed. */ | 985 | /* Clear root port wake on bits if wakeup not allowed. */ |
| 988 | if (!do_wakeup) | 986 | if (!do_wakeup) |
| 989 | xhci_disable_port_wake_on_bits(xhci); | 987 | xhci_disable_port_wake_on_bits(xhci); |
| 990 | 988 | ||
| 989 | if (!HCD_HW_ACCESSIBLE(hcd)) | ||
| 990 | return 0; | ||
| 991 | |||
| 992 | xhci_dbc_suspend(xhci); | ||
| 993 | |||
| 991 | /* Don't poll the roothubs on bus suspend. */ | 994 | /* Don't poll the roothubs on bus suspend. */ |
| 992 | xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); | 995 | xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); |
| 993 | clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); | 996 | clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); |
| @@ -1915,8 +1918,6 @@ static int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, · 921 unmodified lines | |||
| 1915 | ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); | 1918 | ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); |
| 1916 | trace_xhci_add_endpoint(ep_ctx); | 1919 | trace_xhci_add_endpoint(ep_ctx); |
| 1917 | 1920 | ||
| 1918 | xhci_debugfs_create_endpoint(xhci, virt_dev, ep_index); | ||
| 1919 | |||
| 1920 | xhci_dbg(xhci, "add ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x\n", | 1921 | xhci_dbg(xhci, "add ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x\n", |
| 1921 | (unsigned int) ep->desc.bEndpointAddress, | 1922 | (unsigned int) ep->desc.bEndpointAddress, |
| 1922 | udev->slot_id, | 1923 | udev->slot_id, |
| @@ -2949,6 +2950,7 @@ static int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) · 1026 unmodified lines | |||
| 2949 | xhci_check_bw_drop_ep_streams(xhci, virt_dev, i); | 2950 | xhci_check_bw_drop_ep_streams(xhci, virt_dev, i); |
| 2950 | virt_dev->eps[i].ring = virt_dev->eps[i].new_ring; | 2951 | virt_dev->eps[i].ring = virt_dev->eps[i].new_ring; |
| 2951 | virt_dev->eps[i].new_ring = NULL; | 2952 | virt_dev->eps[i].new_ring = NULL; |
| 2953 | xhci_debugfs_create_endpoint(xhci, virt_dev, i); | ||
| 2952 | } | 2954 | } |
| 2953 | command_cleanup: | 2955 | command_cleanup: |
| 2954 | kfree(command->completion); | 2956 | kfree(command->completion); |
| @@ -3531,6 +3533,7 @@ static int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev, · 576 unmodified lines | |||
| 3531 | xhci_dbg(xhci, "Slot %u ep ctx %u now has streams.\n", | 3533 | xhci_dbg(xhci, "Slot %u ep ctx %u now has streams.\n", |
| 3532 | udev->slot_id, ep_index); | 3534 | udev->slot_id, ep_index); |
| 3533 | vdev->eps[ep_index].ep_state |= EP_HAS_STREAMS; | 3535 | vdev->eps[ep_index].ep_state |= EP_HAS_STREAMS; |
| 3536 | xhci_debugfs_create_stream_files(xhci, vdev, ep_index); | ||
| 3534 | } | 3537 | } |
| 3535 | xhci_free_command(xhci, config_cmd); | 3538 | xhci_free_command(xhci, config_cmd); |
| 3536 | spin_unlock_irqrestore(&xhci->lock, flags); | 3539 | spin_unlock_irqrestore(&xhci->lock, flags); |
| @@ -1770,6 +1770,8 @@ struct xhci_hcd { · 1769 unmodified lines | |||
| 1770 | /* optional clocks */ | 1770 | /* optional clocks */ |
| 1771 | struct clk *clk; | 1771 | struct clk *clk; |
| 1772 | struct clk *reg_clk; | 1772 | struct clk *reg_clk; |
| 1773 | /* optional reset controller */ | ||
| 1774 | struct reset_control *reset; | ||
| 1773 | /* data structures */ | 1775 | /* data structures */ |
| 1774 | struct xhci_device_context_array *dcbaa; | 1776 | struct xhci_device_context_array *dcbaa; |
| 1775 | struct xhci_ring *cmd_ring; | 1777 | struct xhci_ring *cmd_ring; |
| @@ -1874,6 +1876,7 @@ struct xhci_hcd { · 98 unmodified lines | |||
| 1874 | #define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34) | 1876 | #define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34) |
| 1875 | #define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35) | 1877 | #define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35) |
| 1876 | #define XHCI_RENESAS_FW_QUIRK BIT_ULL(36) | 1878 | #define XHCI_RENESAS_FW_QUIRK BIT_ULL(36) |
| 1879 | #define XHCI_SKIP_PHY_INIT BIT_ULL(37) | ||
| 1877 | 1880 | ||
| 1878 | unsigned int num_active_eps; | 1881 | unsigned int num_active_eps; |
| 1879 | unsigned int limit_active_eps; | 1882 | unsigned int limit_active_eps; |
| @@ -389,7 +389,7 @@ void mts_int_submit_urb (struct urb* transfer, · 388 unmodified lines | |||
| 389 | res = usb_submit_urb( transfer, GFP_ATOMIC ); | 389 | res = usb_submit_urb( transfer, GFP_ATOMIC ); |
| 390 | if ( unlikely(res) ) { | 390 | if ( unlikely(res) ) { |
| 391 | MTS_INT_ERROR( "could not submit URB! Error was %d\n",(int)res ); | 391 | MTS_INT_ERROR( "could not submit URB! Error was %d\n",(int)res ); |
| 392 | context->srb->result = DID_ERROR << 16; | 392 | set_host_byte(context->srb, DID_ERROR); |
| 393 | mts_transfer_cleanup(transfer); | 393 | mts_transfer_cleanup(transfer); |
| 394 | } | 394 | } |
| 395 | } | 395 | } |
| @@ -438,7 +438,7 @@ static void mts_data_done( struct urb* transfer ) · 42 unmodified lines | |||
| 438 | scsi_set_resid(context->srb, context->data_length - | 438 | scsi_set_resid(context->srb, context->data_length - |
| 439 | transfer->actual_length); | 439 | transfer->actual_length); |
| 440 | } else if ( unlikely(status) ) { | 440 | } else if ( unlikely(status) ) { |
| 441 | context->srb->result = (status == -ENOENT ? DID_ABORT : DID_ERROR)<<16; | 441 | set_host_byte(context->srb, (status == -ENOENT ? DID_ABORT : DID_ERROR)); |
| 442 | } | 442 | } |
| 443 | 443 | ||
| 444 | mts_get_status(transfer); | 444 | mts_get_status(transfer); |
| @@ -455,12 +455,12 @@ static void mts_command_done( struct urb *transfer ) · 10 unmodified lines | |||
| 455 | if (status == -ENOENT) { | 455 | if (status == -ENOENT) { |
| 456 | /* We are being killed */ | 456 | /* We are being killed */ |
| 457 | MTS_DEBUG_GOT_HERE(); | 457 | MTS_DEBUG_GOT_HERE(); |
| 458 | context->srb->result = DID_ABORT<<16; | 458 | set_host_byte(context->srb, DID_ABORT); |
| 459 | } else { | 459 | } else { |
| 460 | /* A genuine error has occurred */ | 460 | /* A genuine error has occurred */ |
| 461 | MTS_DEBUG_GOT_HERE(); | 461 | MTS_DEBUG_GOT_HERE(); |
| 462 | 462 | ||
| 463 | context->srb->result = DID_ERROR<<16; | 463 | set_host_byte(context->srb, DID_ERROR); |
| 464 | } | 464 | } |
| 465 | mts_transfer_cleanup(transfer); | 465 | mts_transfer_cleanup(transfer); |
| 466 | 466 | ||
| @@ -495,7 +495,7 @@ static void mts_do_sg (struct urb* transfer) · 28 unmodified lines | |||
| 495 | scsi_sg_count(context->srb)); | 495 | scsi_sg_count(context->srb)); |
| 496 | 496 | ||
| 497 | if (unlikely(status)) { | 497 | if (unlikely(status)) { |
| 498 | context->srb->result = (status == -ENOENT ? DID_ABORT : DID_ERROR)<<16; | 498 | set_host_byte(context->srb, (status == -ENOENT ? DID_ABORT : DID_ERROR)); |
| 499 | mts_transfer_cleanup(transfer); | 499 | mts_transfer_cleanup(transfer); |
| 500 | } | 500 | } |
| 501 | 501 | ||
| @@ -578,7 +578,7 @@ mts_scsi_queuecommand_lck(struct scsi_cmnd *srb, mts_scsi_cmnd_callback callback · 76 unmodified lines | |||
| 578 | 578 | ||
| 579 | MTS_DEBUG("this device doesn't exist\n"); | 579 | MTS_DEBUG("this device doesn't exist\n"); |
| 580 | 580 | ||
| 581 | srb->result = DID_BAD_TARGET << 16; | 581 | set_host_byte(srb, DID_BAD_TARGET); |
| 582 | 582 | ||
| 583 | if(likely(callback != NULL)) | 583 | if(likely(callback != NULL)) |
| 584 | callback(srb); | 584 | callback(srb); |
| @@ -605,7 +605,7 @@ mts_scsi_queuecommand_lck(struct scsi_cmnd *srb, mts_scsi_cmnd_callback callback · 20 unmodified lines | |||
| 605 | 605 | ||
| 606 | if(unlikely(res)){ | 606 | if(unlikely(res)){ |
| 607 | MTS_ERROR("error %d submitting URB\n",(int)res); | 607 | MTS_ERROR("error %d submitting URB\n",(int)res); |
| 608 | srb->result = DID_ERROR << 16; | 608 | set_host_byte(srb, DID_ERROR); |
| 609 | 609 | ||
| 610 | if(likely(callback != NULL)) | 610 | if(likely(callback != NULL)) |
| 611 | callback(srb); | 611 | callback(srb); |
| @@ -22,6 +22,7 @@ · 21 unmodified lines | |||
| 22 | #include <linux/debugfs.h> | 22 | #include <linux/debugfs.h> |
| 23 | #include <linux/uaccess.h> | 23 | #include <linux/uaccess.h> |
| 24 | #include <linux/io.h> | 24 | #include <linux/io.h> |
| 25 | #include <linux/iopoll.h> | ||
| 25 | #include <linux/mm.h> | 26 | #include <linux/mm.h> |
| 26 | #include <linux/timer.h> | 27 | #include <linux/timer.h> |
| 27 | #include <asm/unaligned.h> | 28 | #include <asm/unaligned.h> |
| @@ -380,18 +381,15 @@ static int handshake(struct usb_hcd *hcd, u32 reg, · 352 unmodified lines | |||
| 380 | u32 mask, u32 done, int usec) | 381 | u32 mask, u32 done, int usec) |
| 381 | { | 382 | { |
| 382 | u32 result; | 383 | u32 result; |
| 384 | int ret; | ||
| 385 | |||
| 386 | ret = readl_poll_timeout_atomic(hcd->regs + reg, result, | ||
| 387 | ((result & mask) == done || | ||
| 388 | result == U32_MAX), 1, usec); | ||
| 389 | if (result == U32_MAX) | ||
| 390 | return -ENODEV; | ||
| 383 | 391 | ||
| 384 | do { | 392 | return ret; |
| 385 | result = reg_read32(hcd->regs, reg); | ||
| 386 | if (result == ~0) | ||
| 387 | return -ENODEV; | ||
| 388 | result &= mask; | ||
| 389 | if (result == done) | ||
| 390 | return 0; | ||
| 391 | udelay(1); | ||
| 392 | usec--; | ||
| 393 | } while (usec > 0); | ||
| 394 | return -ETIMEDOUT; | ||
| 395 | } | 393 | } |
| 396 | 394 | ||
| 397 | /* reset a non-running (STS_HALT == 1) controller */ | 395 | /* reset a non-running (STS_HALT == 1) controller */ |
| @@ -209,6 +209,7 @@ static void adu_interrupt_out_callback(struct urb *urb) · 208 unmodified lines | |||
| 209 | 209 | ||
| 210 | if (status != 0) { | 210 | if (status != 0) { |
| 211 | if ((status != -ENOENT) && | 211 | if ((status != -ENOENT) && |
| 212 | (status != -ESHUTDOWN) && | ||
| 212 | (status != -ECONNRESET)) { | 213 | (status != -ECONNRESET)) { |
| 213 | dev_dbg(&dev->udev->dev, | 214 | dev_dbg(&dev->udev->dev, |
| 214 | "%s :nonzero status received: %d\n", __func__, | 215 | "%s :nonzero status received: %d\n", __func__, |
| @@ -342,20 +342,8 @@ static struct usb_driver appledisplay_driver = { · 341 unmodified lines | |||
| 342 | .disconnect = appledisplay_disconnect, | 342 | .disconnect = appledisplay_disconnect, |
| 343 | .id_table = appledisplay_table, | 343 | .id_table = appledisplay_table, |
| 344 | }; | 344 | }; |
| 345 | 345 | module_usb_driver(appledisplay_driver); | |
| 346 | static int __init appledisplay_init(void) | ||
| 347 | { | ||
| 348 | return usb_register(&appledisplay_driver); | ||
| 349 | } | ||
| 350 | |||
| 351 | static void __exit appledisplay_exit(void) | ||
| 352 | { | ||
| 353 | usb_deregister(&appledisplay_driver); | ||
| 354 | } | ||
| 355 | 346 | ||
| 356 | MODULE_AUTHOR("Michael Hanselmann"); | 347 | MODULE_AUTHOR("Michael Hanselmann"); |
| 357 | MODULE_DESCRIPTION("Apple Cinema Display driver"); | 348 | MODULE_DESCRIPTION("Apple Cinema Display driver"); |
| 358 | MODULE_LICENSE("GPL"); | 349 | MODULE_LICENSE("GPL"); |
| 359 | |||
| 360 | module_init(appledisplay_init); | ||
| 361 | module_exit(appledisplay_exit); | ||
| @@ -308,15 +308,9 @@ static int tower_open(struct inode *inode, struct file *file) · 307 unmodified lines | |||
| 308 | int subminor; | 308 | int subminor; |
| 309 | int retval = 0; | 309 | int retval = 0; |
| 310 | struct usb_interface *interface; | 310 | struct usb_interface *interface; |
| 311 | struct tower_reset_reply *reset_reply; | 311 | struct tower_reset_reply reset_reply; |
| 312 | int result; | 312 | int result; |
| 313 | 313 | ||
| 314 | reset_reply = kmalloc(sizeof(*reset_reply), GFP_KERNEL); | ||
| 315 | if (!reset_reply) { | ||
| 316 | retval = -ENOMEM; | ||
| 317 | goto exit; | ||
| 318 | } | ||
| 319 | |||
| 320 | nonseekable_open(inode, file); | 314 | nonseekable_open(inode, file); |
| 321 | subminor = iminor(inode); | 315 | subminor = iminor(inode); |
| 322 | 316 | ||
| @@ -347,15 +341,12 @@ static int tower_open(struct inode *inode, struct file *file) · 24 unmodified lines | |||
| 347 | } | 341 | } |
| 348 | 342 | ||
| 349 | /* reset the tower */ | 343 | /* reset the tower */ |
| 350 | result = usb_control_msg(dev->udev, | 344 | result = usb_control_msg_recv(dev->udev, 0, |
| 351 | usb_rcvctrlpipe(dev->udev, 0), | 345 | LEGO_USB_TOWER_REQUEST_RESET, |
| 352 | LEGO_USB_TOWER_REQUEST_RESET, | 346 | USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, |
| 353 | USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, | 347 | 0, 0, |
| 354 | 0, | 348 | &reset_reply, sizeof(reset_reply), 1000, |
| 355 | 0, | 349 | GFP_KERNEL); |
| 356 | reset_reply, | ||
| 357 | sizeof(*reset_reply), | ||
| 358 | 1000); | ||
| 359 | if (result < 0) { | 350 | if (result < 0) { |
| 360 | dev_err(&dev->udev->dev, | 351 | dev_err(&dev->udev->dev, |
| 361 | "LEGO USB Tower reset control request failed\n"); | 352 | "LEGO USB Tower reset control request failed\n"); |
| @@ -394,7 +385,6 @@ unlock_exit: · 32 unmodified lines | |||
| 394 | mutex_unlock(&dev->lock); | 385 | mutex_unlock(&dev->lock); |
| 395 | 386 | ||
| 396 | exit: | 387 | exit: |
| 397 | kfree(reset_reply); | ||
| 398 | return retval; | 388 | return retval; |
| 399 | } | 389 | } |
| 400 | 390 | ||
| @@ -753,7 +743,7 @@ static int tower_probe(struct usb_interface *interface, const struct usb_device_ · 352 unmodified lines | |||
| 753 | struct device *idev = &interface->dev; | 743 | struct device *idev = &interface->dev; |
| 754 | struct usb_device *udev = interface_to_usbdev(interface); | 744 | struct usb_device *udev = interface_to_usbdev(interface); |
| 755 | struct lego_usb_tower *dev; | 745 | struct lego_usb_tower *dev; |
| 756 | struct tower_get_version_reply *get_version_reply = NULL; | 746 | struct tower_get_version_reply get_version_reply; |
| 757 | int retval = -ENOMEM; | 747 | int retval = -ENOMEM; |
| 758 | int result; | 748 | int result; |
| 759 | 749 | ||
| @@ -798,34 +788,25 @@ static int tower_probe(struct usb_interface *interface, const struct usb_device_ · 38 unmodified lines | |||
| 798 | dev->interrupt_in_interval = interrupt_in_interval ? interrupt_in_interval : dev->interrupt_in_endpoint->bInterval; | 788 | dev->interrupt_in_interval = interrupt_in_interval ? interrupt_in_interval : dev->interrupt_in_endpoint->bInterval; |
| 799 | dev->interrupt_out_interval = interrupt_out_interval ? interrupt_out_interval : dev->interrupt_out_endpoint->bInterval; | 789 | dev->interrupt_out_interval = interrupt_out_interval ? interrupt_out_interval : dev->interrupt_out_endpoint->bInterval; |
| 800 | 790 | ||
| 801 | get_version_reply = kmalloc(sizeof(*get_version_reply), GFP_KERNEL); | ||
| 802 | if (!get_version_reply) { | ||
| 803 | retval = -ENOMEM; | ||
| 804 | goto error; | ||
| 805 | } | ||
| 806 | |||
| 807 | /* get the firmware version and log it */ | 791 | /* get the firmware version and log it */ |
| 808 | result = usb_control_msg(udev, | 792 | result = usb_control_msg_recv(udev, 0, |
| 809 | usb_rcvctrlpipe(udev, 0), | 793 | LEGO_USB_TOWER_REQUEST_GET_VERSION, |
| 810 | LEGO_USB_TOWER_REQUEST_GET_VERSION, | 794 | USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, |
| 811 | USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, | 795 | 0, |
| 812 | 0, | 796 | 0, |
| 813 | 0, | 797 | &get_version_reply, |
| 814 | get_version_reply, | 798 | sizeof(get_version_reply), |
| 815 | sizeof(*get_version_reply), | 799 | 1000, GFP_KERNEL); |
| 816 | 1000); | 800 | if (!result) { |
| 817 | if (result != sizeof(*get_version_reply)) { | ||
| 818 | if (result >= 0) | ||
| 819 | result = -EIO; | ||
| 820 | dev_err(idev, "get version request failed: %d\n", result); | 801 | dev_err(idev, "get version request failed: %d\n", result); |
| 821 | retval = result; | 802 | retval = result; |
| 822 | goto error; | 803 | goto error; |
| 823 | } | 804 | } |
| 824 | dev_info(&interface->dev, | 805 | dev_info(&interface->dev, |
| 825 | "LEGO USB Tower firmware version is %d.%d build %d\n", | 806 | "LEGO USB Tower firmware version is %d.%d build %d\n", |
| 826 | get_version_reply->major, | 807 | get_version_reply.major, |
| 827 | get_version_reply->minor, | 808 | get_version_reply.minor, |
| 828 | le16_to_cpu(get_version_reply->build_no)); | 809 | le16_to_cpu(get_version_reply.build_no)); |
| 829 | 810 | ||
| 830 | /* we can register the device now, as it is ready */ | 811 | /* we can register the device now, as it is ready */ |
| 831 | usb_set_intfdata(interface, dev); | 812 | usb_set_intfdata(interface, dev); |
| @@ -844,11 +825,9 @@ static int tower_probe(struct usb_interface *interface, const struct usb_device_ · 12 unmodified lines | |||
| 844 | USB_MAJOR, dev->minor); | 825 | USB_MAJOR, dev->minor); |
| 845 | 826 | ||
| 846 | exit: | 827 | exit: |
| 847 | kfree(get_version_reply); | ||
| 848 | return retval; | 828 | return retval; |
| 849 | 829 | ||
| 850 | error: | 830 | error: |
| 851 | kfree(get_version_reply); | ||
| 852 | tower_delete(dev); | 831 | tower_delete(dev); |
| 853 | return retval; | 832 | return retval; |
| 854 | } | 833 | } |
| @@ -322,8 +322,7 @@ static int usb3503_platform_remove(struct platform_device *pdev) · 321 unmodified lines | |||
| 322 | return 0; | 322 | return 0; |
| 323 | } | 323 | } |
| 324 | 324 | ||
| 325 | #ifdef CONFIG_PM_SLEEP | 325 | static int __maybe_unused usb3503_suspend(struct usb3503 *hub) |
| 326 | static int usb3503_suspend(struct usb3503 *hub) | ||
| 327 | { | 326 | { |
| 328 | usb3503_switch_mode(hub, USB3503_MODE_STANDBY); | 327 | usb3503_switch_mode(hub, USB3503_MODE_STANDBY); |
| 329 | clk_disable_unprepare(hub->clk); | 328 | clk_disable_unprepare(hub->clk); |
| @@ -331,7 +330,7 @@ static int usb3503_suspend(struct usb3503 *hub) · 1 unmodified line | |||
| 331 | return 0; | 330 | return 0; |
| 332 | } | 331 | } |
| 333 | 332 | ||
| 334 | static int usb3503_resume(struct usb3503 *hub) | 333 | static int __maybe_unused usb3503_resume(struct usb3503 *hub) |
| 335 | { | 334 | { |
| 336 | clk_prepare_enable(hub->clk); | 335 | clk_prepare_enable(hub->clk); |
| 337 | usb3503_switch_mode(hub, hub->mode); | 336 | usb3503_switch_mode(hub, hub->mode); |
| @@ -339,30 +338,29 @@ static int usb3503_resume(struct usb3503 *hub) · 1 unmodified line | |||
| 339 | return 0; | 338 | return 0; |
| 340 | } | 339 | } |
| 341 | 340 | ||
| 342 | static int usb3503_i2c_suspend(struct device *dev) | 341 | static int __maybe_unused usb3503_i2c_suspend(struct device *dev) |
| 343 | { | 342 | { |
| 344 | struct i2c_client *client = to_i2c_client(dev); | 343 | struct i2c_client *client = to_i2c_client(dev); |
| 345 | 344 | ||
| 346 | return usb3503_suspend(i2c_get_clientdata(client)); | 345 | return usb3503_suspend(i2c_get_clientdata(client)); |
| 347 | } | 346 | } |
| 348 | 347 | ||
| 349 | static int usb3503_i2c_resume(struct device *dev) | 348 | static int __maybe_unused usb3503_i2c_resume(struct device *dev) |
| 350 | { | 349 | { |
| 351 | struct i2c_client *client = to_i2c_client(dev); | 350 | struct i2c_client *client = to_i2c_client(dev); |
| 352 | 351 | ||
| 353 | return usb3503_resume(i2c_get_clientdata(client)); | 352 | return usb3503_resume(i2c_get_clientdata(client)); |
| 354 | } | 353 | } |
| 355 | 354 | ||
| 356 | static int usb3503_platform_suspend(struct device *dev) | 355 | static int __maybe_unused usb3503_platform_suspend(struct device *dev) |
| 357 | { | 356 | { |
| 358 | return usb3503_suspend(dev_get_drvdata(dev)); | 357 | return usb3503_suspend(dev_get_drvdata(dev)); |
| 359 | } | 358 | } |
| 360 | 359 | ||
| 361 | static int usb3503_platform_resume(struct device *dev) | 360 | static int __maybe_unused usb3503_platform_resume(struct device *dev) |
| 362 | { | 361 | { |
| 363 | return usb3503_resume(dev_get_drvdata(dev)); | 362 | return usb3503_resume(dev_get_drvdata(dev)); |
| 364 | } | 363 | } |
| 365 | #endif | ||
| 366 | 364 | ||
| 367 | static SIMPLE_DEV_PM_OPS(usb3503_i2c_pm_ops, usb3503_i2c_suspend, | 365 | static SIMPLE_DEV_PM_OPS(usb3503_i2c_pm_ops, usb3503_i2c_suspend, |
| 368 | usb3503_i2c_resume); | 366 | usb3503_i2c_resume); |
| @@ -388,7 +386,7 @@ MODULE_DEVICE_TABLE(of, usb3503_of_match); · 19 unmodified lines | |||
| 388 | static struct i2c_driver usb3503_i2c_driver = { | 386 | static struct i2c_driver usb3503_i2c_driver = { |
| 389 | .driver = { | 387 | .driver = { |
| 390 | .name = USB3503_I2C_NAME, | 388 | .name = USB3503_I2C_NAME, |
| 391 | .pm = &usb3503_i2c_pm_ops, | 389 | .pm = pm_ptr(&usb3503_i2c_pm_ops), |
| 392 | .of_match_table = of_match_ptr(usb3503_of_match), | 390 | .of_match_table = of_match_ptr(usb3503_of_match), |
| 393 | }, | 391 | }, |
| 394 | .probe = usb3503_i2c_probe, | 392 | .probe = usb3503_i2c_probe, |
| @@ -400,7 +398,7 @@ static struct platform_driver usb3503_platform_driver = { · 5 unmodified lines | |||
| 400 | .driver = { | 398 | .driver = { |
| 401 | .name = USB3503_I2C_NAME, | 399 | .name = USB3503_I2C_NAME, |
| 402 | .of_match_table = of_match_ptr(usb3503_of_match), | 400 | .of_match_table = of_match_ptr(usb3503_of_match), |
| 403 | .pm = &usb3503_platform_pm_ops, | 401 | .pm = pm_ptr(&usb3503_platform_pm_ops), |
| 404 | }, | 402 | }, |
| 405 | .probe = usb3503_platform_probe, | 403 | .probe = usb3503_platform_probe, |
| 406 | .remove = usb3503_platform_remove, | 404 | .remove = usb3503_platform_remove, |
| @@ -112,8 +112,7 @@ static int usb4604_i2c_probe(struct i2c_client *i2c, · 111 unmodified lines | |||
| 112 | return usb4604_probe(hub); | 112 | return usb4604_probe(hub); |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | #ifdef CONFIG_PM_SLEEP | 115 | static int __maybe_unused usb4604_i2c_suspend(struct device *dev) |
| 116 | static int usb4604_i2c_suspend(struct device *dev) | ||
| 117 | { | 116 | { |
| 118 | struct i2c_client *client = to_i2c_client(dev); | 117 | struct i2c_client *client = to_i2c_client(dev); |
| 119 | struct usb4604 *hub = i2c_get_clientdata(client); | 118 | struct usb4604 *hub = i2c_get_clientdata(client); |
| @@ -123,7 +122,7 @@ static int usb4604_i2c_suspend(struct device *dev) · 3 unmodified lines | |||
| 123 | return 0; | 122 | return 0; |
| 124 | } | 123 | } |
| 125 | 124 | ||
| 126 | static int usb4604_i2c_resume(struct device *dev) | 125 | static int __maybe_unused usb4604_i2c_resume(struct device *dev) |
| 127 | { | 126 | { |
| 128 | struct i2c_client *client = to_i2c_client(dev); | 127 | struct i2c_client *client = to_i2c_client(dev); |
| 129 | struct usb4604 *hub = i2c_get_clientdata(client); | 128 | struct usb4604 *hub = i2c_get_clientdata(client); |
| @@ -132,7 +131,6 @@ static int usb4604_i2c_resume(struct device *dev) · 2 unmodified lines | |||
| 132 | 131 | ||
| 133 | return 0; | 132 | return 0; |
| 134 | } | 133 | } |
| 135 | #endif | ||
| 136 | 134 | ||
| 137 | static SIMPLE_DEV_PM_OPS(usb4604_i2c_pm_ops, usb4604_i2c_suspend, | 135 | static SIMPLE_DEV_PM_OPS(usb4604_i2c_pm_ops, usb4604_i2c_suspend, |
| 138 | usb4604_i2c_resume); | 136 | usb4604_i2c_resume); |
| @@ -154,7 +152,7 @@ MODULE_DEVICE_TABLE(of, usb4604_of_match); · 15 unmodified lines | |||
| 154 | static struct i2c_driver usb4604_i2c_driver = { | 152 | static struct i2c_driver usb4604_i2c_driver = { |
| 155 | .driver = { | 153 | .driver = { |
| 156 | .name = "usb4604", | 154 | .name = "usb4604", |
| 157 | .pm = &usb4604_i2c_pm_ops, | 155 | .pm = pm_ptr(&usb4604_i2c_pm_ops), |
| 158 | .of_match_table = of_match_ptr(usb4604_of_match), | 156 | .of_match_table = of_match_ptr(usb4604_of_match), |
| 159 | }, | 157 | }, |
| 160 | .probe = usb4604_i2c_probe, | 158 | .probe = usb4604_i2c_probe, |
| @@ -187,7 +187,6 @@ static long lcd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) · 186 unmodified lines | |||
| 187 | break; | 187 | break; |
| 188 | default: | 188 | default: |
| 189 | return -ENOTTY; | 189 | return -ENOTTY; |
| 190 | break; | ||
| 191 | } | 190 | } |
| 192 | 191 | ||
| 193 | return 0; | 192 | return 0; |
| @@ -96,15 +96,13 @@ static void yurex_delete(struct kref *kref) · 95 unmodified lines | |||
| 96 | if (dev->cntl_urb) { | 96 | if (dev->cntl_urb) { |
| 97 | usb_kill_urb(dev->cntl_urb); | 97 | usb_kill_urb(dev->cntl_urb); |
| 98 | kfree(dev->cntl_req); | 98 | kfree(dev->cntl_req); |
| 99 | if (dev->cntl_buffer) | 99 | usb_free_coherent(dev->udev, YUREX_BUF_SIZE, |
| 100 | usb_free_coherent(dev->udev, YUREX_BUF_SIZE, | ||
| 101 | dev->cntl_buffer, dev->cntl_urb->transfer_dma); | 100 | dev->cntl_buffer, dev->cntl_urb->transfer_dma); |
| 102 | usb_free_urb(dev->cntl_urb); | 101 | usb_free_urb(dev->cntl_urb); |
| 103 | } | 102 | } |
| 104 | if (dev->urb) { | 103 | if (dev->urb) { |
| 105 | usb_kill_urb(dev->urb); | 104 | usb_kill_urb(dev->urb); |
| 106 | if (dev->int_buffer) | 105 | usb_free_coherent(dev->udev, YUREX_BUF_SIZE, |
| 107 | usb_free_coherent(dev->udev, YUREX_BUF_SIZE, | ||
| 108 | dev->int_buffer, dev->urb->transfer_dma); | 106 | dev->int_buffer, dev->urb->transfer_dma); |
| 109 | usb_free_urb(dev->urb); | 107 | usb_free_urb(dev->urb); |
| 110 | } | 108 | } |
| @@ -370,12 +370,6 @@ static inline struct mtu3 *gadget_to_mtu3(struct usb_gadget *g) · 369 unmodified lines | |||
| 370 | return container_of(g, struct mtu3, g); | 370 | return container_of(g, struct mtu3, g); |
| 371 | } | 371 | } |
| 372 | 372 | ||
| 373 | static inline int is_first_entry(const struct list_head *list, | ||
| 374 | const struct list_head *head) | ||
| 375 | { | ||
| 376 | return list_is_last(head, list); | ||
| 377 | } | ||
| 378 | |||
| 379 | static inline struct mtu3_request *to_mtu3_request(struct usb_request *req) | 373 | static inline struct mtu3_request *to_mtu3_request(struct usb_request *req) |
| 380 | { | 374 | { |
| 381 | return req ? container_of(req, struct mtu3_request, request) : NULL; | 375 | return req ? container_of(req, struct mtu3_request, request) : NULL; |
| @@ -1024,7 +1024,7 @@ static int musb_g_ep0_halt(struct usb_ep *e, int value) · 1023 unmodified lines | |||
| 1024 | case MUSB_EP0_STAGE_ACKWAIT: /* STALL for zero-length data */ | 1024 | case MUSB_EP0_STAGE_ACKWAIT: /* STALL for zero-length data */ |
| 1025 | case MUSB_EP0_STAGE_RX: /* control-OUT data */ | 1025 | case MUSB_EP0_STAGE_RX: /* control-OUT data */ |
| 1026 | csr = musb_readw(regs, MUSB_CSR0); | 1026 | csr = musb_readw(regs, MUSB_CSR0); |
| 1027 | /* FALLTHROUGH */ | 1027 | fallthrough; |
| 1028 | 1028 | ||
| 1029 | /* It's also OK to issue stalls during callbacks when a non-empty | 1029 | /* It's also OK to issue stalls during callbacks when a non-empty |
| 1030 | * DATA stage buffer has been read (or even written). | 1030 | * DATA stage buffer has been read (or even written). |
| @@ -518,7 +518,7 @@ static int ab8500_usb_link_status_update(struct ab8500_usb *ab, · 517 unmodified lines | |||
| 518 | * 3. Enable AB regulators | 518 | * 3. Enable AB regulators |
| 519 | * 4. Enable USB phy | 519 | * 4. Enable USB phy |
| 520 | * 5. Reset the musb controller | 520 | * 5. Reset the musb controller |
| 521 | * 6. Switch the ULPI GPIO pins to fucntion mode | 521 | * 6. Switch the ULPI GPIO pins to function mode |
| 522 | * 7. Enable the musb Peripheral5 clock | 522 | * 7. Enable the musb Peripheral5 clock |
| 523 | * 8. Restore MUSB context | 523 | * 8. Restore MUSB context |
| 524 | */ | 524 | */ |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | |||
| 8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
| 9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
| 10 | #include <linux/io.h> | 10 | #include <linux/io.h> |
| 11 | #include <linux/iopoll.h> | ||
| 11 | #include <linux/uaccess.h> | 12 | #include <linux/uaccess.h> |
| 12 | #include <linux/device.h> | 13 | #include <linux/device.h> |
| 13 | #include <linux/proc_fs.h> | 14 | #include <linux/proc_fs.h> |
| @@ -135,8 +136,8 @@ static int mv_otg_set_timer(struct mv_otg *mvotg, unsigned int id, · 121 unmodified lines | |||
| 135 | 136 | ||
| 136 | static int mv_otg_reset(struct mv_otg *mvotg) | 137 | static int mv_otg_reset(struct mv_otg *mvotg) |
| 137 | { | 138 | { |
| 138 | unsigned int loops; | ||
| 139 | u32 tmp; | 139 | u32 tmp; |
| 140 | int ret; | ||
| 140 | 141 | ||
| 141 | /* Stop the controller */ | 142 | /* Stop the controller */ |
| 142 | tmp = readl(&mvotg->op_regs->usbcmd); | 143 | tmp = readl(&mvotg->op_regs->usbcmd); |
| @@ -146,15 +147,12 @@ static int mv_otg_reset(struct mv_otg *mvotg) · 3 unmodified lines | |||
| 146 | /* Reset the controller to get default values */ | 147 | /* Reset the controller to get default values */ |
| 147 | writel(USBCMD_CTRL_RESET, &mvotg->op_regs->usbcmd); | 148 | writel(USBCMD_CTRL_RESET, &mvotg->op_regs->usbcmd); |
| 148 | 149 | ||
| 149 | loops = 500; | 150 | ret = readl_poll_timeout_atomic(&mvotg->op_regs->usbcmd, tmp, |
| 150 | while (readl(&mvotg->op_regs->usbcmd) & USBCMD_CTRL_RESET) { | 151 | (tmp & USBCMD_CTRL_RESET), 10, 10000); |
| 151 | if (loops == 0) { | 152 | if (ret < 0) { |
| 152 | dev_err(&mvotg->pdev->dev, | 153 | dev_err(&mvotg->pdev->dev, |
| 153 | "Wait for RESET completed TIMEOUT\n"); | 154 | "Wait for RESET completed TIMEOUT\n"); |
| 154 | return -ETIMEDOUT; | 155 | return ret; |
| 155 | } | ||
| 156 | loops--; | ||
| 157 | udelay(20); | ||
| 158 | } | 156 | } |
| 159 | 157 | ||
| 160 | writel(0x0, &mvotg->op_regs->usbintr); | 158 | writel(0x0, &mvotg->op_regs->usbintr); |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | |||
| 7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
| 8 | #include <linux/usb.h> | 8 | #include <linux/usb.h> |
| 9 | #include <linux/io.h> | 9 | #include <linux/io.h> |
| 10 | #include <linux/iopoll.h> | ||
| 10 | #include <linux/usb/otg.h> | 11 | #include <linux/usb/otg.h> |
| 11 | #include <linux/usb/ulpi.h> | 12 | #include <linux/usb/ulpi.h> |
| 12 | 13 | ||
| @@ -20,16 +21,9 @@ · 7 unmodified lines | |||
| 20 | 21 | ||
| 21 | static int ulpi_viewport_wait(void __iomem *view, u32 mask) | 22 | static int ulpi_viewport_wait(void __iomem *view, u32 mask) |
| 22 | { | 23 | { |
| 23 | unsigned long usec = 2000; | 24 | u32 val; |
| 24 | 25 | ||
| 25 | while (usec--) { | 26 | return readl_poll_timeout_atomic(view, val, !(val & mask), 1, 2000); |
| 26 | if (!(readl(view) & mask)) | ||
| 27 | return 0; | ||
| 28 | |||
| 29 | udelay(1); | ||
| 30 | } | ||
| 31 | |||
| 32 | return -ETIMEDOUT; | ||
| 33 | } | 27 | } |
| 34 | 28 | ||
| 35 | static int ulpi_viewport_read(struct usb_phy *otg, u32 reg) | 29 | static int ulpi_viewport_read(struct usb_phy *otg, u32 reg) |
| @@ -1037,6 +1037,11 @@ static const struct usb_device_id id_table_combined[] = { · 1036 unmodified lines | |||
| 1037 | /* U-Blox devices */ | 1037 | /* U-Blox devices */ |
| 1038 | { USB_DEVICE(UBLOX_VID, UBLOX_C099F9P_ZED_PID) }, | 1038 | { USB_DEVICE(UBLOX_VID, UBLOX_C099F9P_ZED_PID) }, |
| 1039 | { USB_DEVICE(UBLOX_VID, UBLOX_C099F9P_ODIN_PID) }, | 1039 | { USB_DEVICE(UBLOX_VID, UBLOX_C099F9P_ODIN_PID) }, |
| 1040 | /* FreeCalypso USB adapters */ | ||
| 1041 | { USB_DEVICE(FTDI_VID, FTDI_FALCONIA_JTAG_BUF_PID), | ||
| 1042 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | ||
| 1043 | { USB_DEVICE(FTDI_VID, FTDI_FALCONIA_JTAG_UNBUF_PID), | ||
| 1044 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | ||
| 1040 | { } /* Terminating entry */ | 1045 | { } /* Terminating entry */ |
| 1041 | }; | 1046 | }; |
| 1042 | 1047 | ||
| @@ -1566,7 +1571,8 @@ static void ftdi_determine_type(struct usb_serial_port *port) · 523 unmodified lines | |||
| 1566 | dev_dbg(&port->dev, "%s: bcdDevice = 0x%x, bNumInterfaces = %u\n", __func__, | 1571 | dev_dbg(&port->dev, "%s: bcdDevice = 0x%x, bNumInterfaces = %u\n", __func__, |
| 1567 | version, interfaces); | 1572 | version, interfaces); |
| 1568 | if (interfaces > 1) { | 1573 | if (interfaces > 1) { |
| 1569 | int inter; | 1574 | struct usb_interface *intf = serial->interface; |
| 1575 | int ifnum = intf->cur_altsetting->desc.bInterfaceNumber; | ||
| 1570 | 1576 | ||
| 1571 | /* Multiple interfaces.*/ | 1577 | /* Multiple interfaces.*/ |
| 1572 | if (version == 0x0800) { | 1578 | if (version == 0x0800) { |
| @@ -1581,16 +1587,15 @@ static void ftdi_determine_type(struct usb_serial_port *port) · 8 unmodified lines | |||
| 1581 | priv->chip_type = FT2232C; | 1587 | priv->chip_type = FT2232C; |
| 1582 | 1588 | ||
| 1583 | /* Determine interface code. */ | 1589 | /* Determine interface code. */ |
| 1584 | inter = serial->interface->altsetting->desc.bInterfaceNumber; | 1590 | if (ifnum == 0) |
| 1585 | if (inter == 0) { | ||
| 1586 | priv->interface = INTERFACE_A; | 1591 | priv->interface = INTERFACE_A; |
| 1587 | } else if (inter == 1) { | 1592 | else if (ifnum == 1) |
| 1588 | priv->interface = INTERFACE_B; | 1593 | priv->interface = INTERFACE_B; |
| 1589 | } else if (inter == 2) { | 1594 | else if (ifnum == 2) |
| 1590 | priv->interface = INTERFACE_C; | 1595 | priv->interface = INTERFACE_C; |
| 1591 | } else if (inter == 3) { | 1596 | else if (ifnum == 3) |
| 1592 | priv->interface = INTERFACE_D; | 1597 | priv->interface = INTERFACE_D; |
| 1593 | } | 1598 | |
| 1594 | /* BM-type devices have a bug where bcdDevice gets set | 1599 | /* BM-type devices have a bug where bcdDevice gets set |
| 1595 | * to 0x200 when iSerialNumber is 0. */ | 1600 | * to 0x200 when iSerialNumber is 0. */ |
| 1596 | if (version < 0x500) { | 1601 | if (version < 0x500) { |
| @@ -2330,12 +2335,11 @@ static int ftdi_NDI_device_setup(struct usb_serial *serial) · 733 unmodified lines | |||
| 2330 | */ | 2335 | */ |
| 2331 | static int ftdi_jtag_probe(struct usb_serial *serial) | 2336 | static int ftdi_jtag_probe(struct usb_serial *serial) |
| 2332 | { | 2337 | { |
| 2333 | struct usb_device *udev = serial->dev; | 2338 | struct usb_interface *intf = serial->interface; |
| 2334 | struct usb_interface *interface = serial->interface; | 2339 | int ifnum = intf->cur_altsetting->desc.bInterfaceNumber; |
| 2335 | 2340 | ||
| 2336 | if (interface == udev->actconfig->interface[0]) { | 2341 | if (ifnum == 0) { |
| 2337 | dev_info(&udev->dev, | 2342 | dev_info(&intf->dev, "Ignoring interface reserved for JTAG\n"); |
| 2338 | "Ignoring serial port reserved for JTAG\n"); | ||
| 2339 | return -ENODEV; | 2343 | return -ENODEV; |
| 2340 | } | 2344 | } |
| 2341 | 2345 | ||
| @@ -2367,12 +2371,11 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial) · 25 unmodified lines | |||
| 2367 | */ | 2371 | */ |
| 2368 | static int ftdi_stmclite_probe(struct usb_serial *serial) | 2372 | static int ftdi_stmclite_probe(struct usb_serial *serial) |
| 2369 | { | 2373 | { |
| 2370 | struct usb_device *udev = serial->dev; | 2374 | struct usb_interface *intf = serial->interface; |
| 2371 | struct usb_interface *interface = serial->interface; | 2375 | int ifnum = intf->cur_altsetting->desc.bInterfaceNumber; |
| 2372 | 2376 | ||
| 2373 | if (interface == udev->actconfig->interface[0] || | 2377 | if (ifnum < 2) { |
| 2374 | interface == udev->actconfig->interface[1]) { | 2378 | dev_info(&intf->dev, "Ignoring interface reserved for JTAG\n"); |
| 2375 | dev_info(&udev->dev, "Ignoring serial port reserved for JTAG\n"); | ||
| 2376 | return -ENODEV; | 2379 | return -ENODEV; |
| 2377 | } | 2380 | } |
| 2378 | 2381 | ||
| @@ -39,6 +39,13 @@ · 38 unmodified lines | |||
| 39 | 39 | ||
| 40 | #define FTDI_LUMEL_PD12_PID 0x6002 | 40 | #define FTDI_LUMEL_PD12_PID 0x6002 |
| 41 | 41 | ||
| 42 | /* | ||
| 43 | * Custom USB adapters made by Falconia Partners LLC | ||
| 44 | * for FreeCalypso project, ID codes allocated to Falconia by FTDI. | ||
| 45 | */ | ||
| 46 | #define FTDI_FALCONIA_JTAG_BUF_PID 0x7150 | ||
| 47 | #define FTDI_FALCONIA_JTAG_UNBUF_PID 0x7151 | ||
| 48 | |||
| 42 | /* Sienna Serial Interface by Secyourit GmbH */ | 49 | /* Sienna Serial Interface by Secyourit GmbH */ |
| 43 | #define FTDI_SIENNA_PID 0x8348 | 50 | #define FTDI_SIENNA_PID 0x8348 |
| 44 | 51 | ||
| @@ -282,11 +282,12 @@ static void destroy_urbtracker(struct kref *kref) · 281 unmodified lines | |||
| 282 | * port callback had to be deferred because the disconnect mutex could not be | 282 | * port callback had to be deferred because the disconnect mutex could not be |
| 283 | * obtained at the time. | 283 | * obtained at the time. |
22 more lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 79 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 374 lines aren’t shown here.
This diff is large: its 263 lines aren’t shown here.
This diff is large: its 876 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 166 lines aren’t shown here.
This diff is large: its 84 lines aren’t shown here.
This diff is large: its 504 lines aren’t shown here.
This diff is large: its 213 lines aren’t shown here.
This diff is large: its 738 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 99 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 128 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.