diff options
230 files changed, 15570 insertions, 3809 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-typec b/Documentation/ABI/testing/sysfs-class-typec new file mode 100644 index 000000000000..d4a3d23eb09c --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-typec | |||
@@ -0,0 +1,276 @@ | |||
1 | USB Type-C port devices (eg. /sys/class/typec/port0/) | ||
2 | |||
3 | What: /sys/class/typec/<port>/data_role | ||
4 | Date: April 2017 | ||
5 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
6 | Description: | ||
7 | The supported USB data roles. This attribute can be used for | ||
8 | requesting data role swapping on the port. Swapping is supported | ||
9 | as synchronous operation, so write(2) to the attribute will not | ||
10 | return until the operation has finished. The attribute is | ||
11 | notified about role changes so that poll(2) on the attribute | ||
12 | wakes up. Change on the role will also generate uevent | ||
13 | KOBJ_CHANGE on the port. The current role is show in brackets, | ||
14 | for example "[host] device" when DRP port is in host mode. | ||
15 | |||
16 | Valid values: host, device | ||
17 | |||
18 | What: /sys/class/typec/<port>/power_role | ||
19 | Date: April 2017 | ||
20 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
21 | Description: | ||
22 | The supported power roles. This attribute can be used to request | ||
23 | power role swap on the port when the port supports USB Power | ||
24 | Delivery. Swapping is supported as synchronous operation, so | ||
25 | write(2) to the attribute will not return until the operation | ||
26 | has finished. The attribute is notified about role changes so | ||
27 | that poll(2) on the attribute wakes up. Change on the role will | ||
28 | also generate uevent KOBJ_CHANGE. The current role is show in | ||
29 | brackets, for example "[source] sink" when in source mode. | ||
30 | |||
31 | Valid values: source, sink | ||
32 | |||
33 | What: /sys/class/typec/<port>/vconn_source | ||
34 | Date: April 2017 | ||
35 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
36 | Description: | ||
37 | Shows is the port VCONN Source. This attribute can be used to | ||
38 | request VCONN swap to change the VCONN Source during connection | ||
39 | when both the port and the partner support USB Power Delivery. | ||
40 | Swapping is supported as synchronous operation, so write(2) to | ||
41 | the attribute will not return until the operation has finished. | ||
42 | The attribute is notified about VCONN source changes so that | ||
43 | poll(2) on the attribute wakes up. Change on VCONN source also | ||
44 | generates uevent KOBJ_CHANGE. | ||
45 | |||
46 | Valid values: | ||
47 | - "no" when the port is not the VCONN Source | ||
48 | - "yes" when the port is the VCONN Source | ||
49 | |||
50 | What: /sys/class/typec/<port>/power_operation_mode | ||
51 | Date: April 2017 | ||
52 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
53 | Description: | ||
54 | Shows the current power operational mode the port is in. The | ||
55 | power operation mode means current level for VBUS. In case USB | ||
56 | Power Delivery communication is used for negotiating the levels, | ||
57 | power operation mode should show "usb_power_delivery". | ||
58 | |||
59 | Valid values: | ||
60 | - default | ||
61 | - 1.5A | ||
62 | - 3.0A | ||
63 | - usb_power_delivery | ||
64 | |||
65 | What: /sys/class/typec/<port>/preferred_role | ||
66 | Date: April 2017 | ||
67 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
68 | Description: | ||
69 | The user space can notify the driver about the preferred role. | ||
70 | It should be handled as enabling of Try.SRC or Try.SNK, as | ||
71 | defined in USB Type-C specification, in the port drivers. By | ||
72 | default the preferred role should come from the platform. | ||
73 | |||
74 | Valid values: source, sink, none (to remove preference) | ||
75 | |||
76 | What: /sys/class/typec/<port>/supported_accessory_modes | ||
77 | Date: April 2017 | ||
78 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
79 | Description: | ||
80 | Space separated list of accessory modes, defined in the USB | ||
81 | Type-C specification, the port supports. | ||
82 | |||
83 | What: /sys/class/typec/<port>/usb_power_delivery_revision | ||
84 | Date: April 2017 | ||
85 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
86 | Description: | ||
87 | Revision number of the supported USB Power Delivery | ||
88 | specification, or 0 when USB Power Delivery is not supported. | ||
89 | |||
90 | What: /sys/class/typec/<port>/usb_typec_revision | ||
91 | Date: April 2017 | ||
92 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
93 | Description: | ||
94 | Revision number of the supported USB Type-C specification. | ||
95 | |||
96 | |||
97 | USB Type-C partner devices (eg. /sys/class/typec/port0-partner/) | ||
98 | |||
99 | What: /sys/class/typec/<port>-partner/accessory_mode | ||
100 | Date: April 2017 | ||
101 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
102 | Description: | ||
103 | Shows the Accessory Mode name when the partner is an Accessory. | ||
104 | The Accessory Modes are defined in USB Type-C Specification. | ||
105 | |||
106 | What: /sys/class/typec/<port>-partner/supports_usb_power_delivery | ||
107 | Date: April 2017 | ||
108 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
109 | Description: | ||
110 | Shows if the partner supports USB Power Delivery communication: | ||
111 | Valid values: yes, no | ||
112 | |||
113 | What: /sys/class/typec/<port>-partner>/identity/ | ||
114 | Date: April 2017 | ||
115 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
116 | Description: | ||
117 | This directory appears only if the port device driver is capable | ||
118 | of showing the result of Discover Identity USB power delivery | ||
119 | command. That will not always be possible even when USB power | ||
120 | delivery is supported, for example when USB power delivery | ||
121 | communication for the port is mostly handled in firmware. If the | ||
122 | directory exists, it will have an attribute file for every VDO | ||
123 | in Discover Identity command result. | ||
124 | |||
125 | What: /sys/class/typec/<port>-partner/identity/id_header | ||
126 | Date: April 2017 | ||
127 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
128 | Description: | ||
129 | ID Header VDO part of Discover Identity command result. The | ||
130 | value will show 0 until Discover Identity command result becomes | ||
131 | available. The value can be polled. | ||
132 | |||
133 | What: /sys/class/typec/<port>-partner/identity/cert_stat | ||
134 | Date: April 2017 | ||
135 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
136 | Description: | ||
137 | Cert Stat VDO part of Discover Identity command result. The | ||
138 | value will show 0 until Discover Identity command result becomes | ||
139 | available. The value can be polled. | ||
140 | |||
141 | What: /sys/class/typec/<port>-partner/identity/product | ||
142 | Date: April 2017 | ||
143 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
144 | Description: | ||
145 | Product VDO part of Discover Identity command result. The value | ||
146 | will show 0 until Discover Identity command result becomes | ||
147 | available. The value can be polled. | ||
148 | |||
149 | |||
150 | USB Type-C cable devices (eg. /sys/class/typec/port0-cable/) | ||
151 | |||
152 | Note: Electronically Marked Cables will have a device also for one cable plug | ||
153 | (eg. /sys/class/typec/port0-plug0). If the cable is active and has also SOP | ||
154 | Double Prime controller (USB Power Deliver specification ch. 2.4) it will have | ||
155 | second device also for the other plug. Both plugs may have alternate modes as | ||
156 | described in USB Type-C and USB Power Delivery specifications. | ||
157 | |||
158 | What: /sys/class/typec/<port>-cable/type | ||
159 | Date: April 2017 | ||
160 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
161 | Description: | ||
162 | Shows if the cable is active. | ||
163 | Valid values: active, passive | ||
164 | |||
165 | What: /sys/class/typec/<port>-cable/plug_type | ||
166 | Date: April 2017 | ||
167 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
168 | Description: | ||
169 | Shows type of the plug on the cable: | ||
170 | - type-a - Standard A | ||
171 | - type-b - Standard B | ||
172 | - type-c | ||
173 | - captive | ||
174 | |||
175 | What: /sys/class/typec/<port>-cable/identity/ | ||
176 | Date: April 2017 | ||
177 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
178 | Description: | ||
179 | This directory appears only if the port device driver is capable | ||
180 | of showing the result of Discover Identity USB power delivery | ||
181 | command. That will not always be possible even when USB power | ||
182 | delivery is supported. If the directory exists, it will have an | ||
183 | attribute for every VDO returned by Discover Identity command. | ||
184 | |||
185 | What: /sys/class/typec/<port>-cable/identity/id_header | ||
186 | Date: April 2017 | ||
187 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
188 | Description: | ||
189 | ID Header VDO part of Discover Identity command result. The | ||
190 | value will show 0 until Discover Identity command result becomes | ||
191 | available. The value can be polled. | ||
192 | |||
193 | What: /sys/class/typec/<port>-cable/identity/cert_stat | ||
194 | Date: April 2017 | ||
195 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
196 | Description: | ||
197 | Cert Stat VDO part of Discover Identity command result. The | ||
198 | value will show 0 until Discover Identity command result becomes | ||
199 | available. The value can be polled. | ||
200 | |||
201 | What: /sys/class/typec/<port>-cable/identity/product | ||
202 | Date: April 2017 | ||
203 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
204 | Description: | ||
205 | Product VDO part of Discover Identity command result. The value | ||
206 | will show 0 until Discover Identity command result becomes | ||
207 | available. The value can be polled. | ||
208 | |||
209 | |||
210 | Alternate Mode devices. | ||
211 | |||
212 | The alternate modes will have Standard or Vendor ID (SVID) assigned by USB-IF. | ||
213 | The ports, partners and cable plugs can have alternate modes. A supported SVID | ||
214 | will consist of a set of modes. Every SVID a port/partner/plug supports will | ||
215 | have a device created for it, and every supported mode for a supported SVID will | ||
216 | have its own directory under that device. Below <dev> refers to the device for | ||
217 | the alternate mode. | ||
218 | |||
219 | What: /sys/class/typec/<port|partner|cable>/<dev>/svid | ||
220 | Date: April 2017 | ||
221 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
222 | Description: | ||
223 | The SVID (Standard or Vendor ID) assigned by USB-IF for this | ||
224 | alternate mode. | ||
225 | |||
226 | What: /sys/class/typec/<port|partner|cable>/<dev>/mode<index>/ | ||
227 | Date: April 2017 | ||
228 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
229 | Description: | ||
230 | Every supported mode will have its own directory. The name of | ||
231 | a mode will be "mode<index>" (for example mode1), where <index> | ||
232 | is the actual index to the mode VDO returned by Discover Modes | ||
233 | USB power delivery command. | ||
234 | |||
235 | What: /sys/class/typec/<port|partner|cable>/<dev>/mode<index>/description | ||
236 | Date: April 2017 | ||
237 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
238 | Description: | ||
239 | Shows description of the mode. The description is optional for | ||
240 | the drivers, just like with the Billboard Devices. | ||
241 | |||
242 | What: /sys/class/typec/<port|partner|cable>/<dev>/mode<index>/vdo | ||
243 | Date: April 2017 | ||
244 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
245 | Description: | ||
246 | Shows the VDO in hexadecimal returned by Discover Modes command | ||
247 | for this mode. | ||
248 | |||
249 | What: /sys/class/typec/<port|partner|cable>/<dev>/mode<index>/active | ||
250 | Date: April 2017 | ||
251 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
252 | Description: | ||
253 | Shows if the mode is active or not. The attribute can be used | ||
254 | for entering/exiting the mode with partners and cable plugs, and | ||
255 | with the port alternate modes it can be used for disabling | ||
256 | support for specific alternate modes. Entering/exiting modes is | ||
257 | supported as synchronous operation so write(2) to the attribute | ||
258 | does not return until the enter/exit mode operation has | ||
259 | finished. The attribute is notified when the mode is | ||
260 | entered/exited so poll(2) on the attribute wakes up. | ||
261 | Entering/exiting a mode will also generate uevent KOBJ_CHANGE. | ||
262 | |||
263 | Valid values: yes, no | ||
264 | |||
265 | What: /sys/class/typec/<port>/<dev>/mode<index>/supported_roles | ||
266 | Date: April 2017 | ||
267 | Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
268 | Description: | ||
269 | Space separated list of the supported roles. | ||
270 | |||
271 | This attribute is available for the devices describing the | ||
272 | alternate modes a port supports, and it will not be exposed with | ||
273 | the devices presenting the alternate modes the partners or cable | ||
274 | plugs support. | ||
275 | |||
276 | Valid values: source, sink | ||
diff --git a/Documentation/ABI/testing/sysfs-platform-chipidea-usb2 b/Documentation/ABI/testing/sysfs-platform-chipidea-usb2 new file mode 100644 index 000000000000..b0f4684a83fe --- /dev/null +++ b/Documentation/ABI/testing/sysfs-platform-chipidea-usb2 | |||
@@ -0,0 +1,9 @@ | |||
1 | What: /sys/bus/platform/devices/ci_hdrc.0/role | ||
2 | Date: Mar 2017 | ||
3 | Contact: Peter Chen <peter.chen@nxp.com> | ||
4 | Description: | ||
5 | It returns string "gadget" or "host" when read it, it indicates | ||
6 | current controller role. | ||
7 | |||
8 | It will do role switch when write "gadget" or "host" to it. | ||
9 | Only controller at dual-role configuration supports writing. | ||
diff --git a/Documentation/ABI/testing/sysfs-platform-renesas_usb3 b/Documentation/ABI/testing/sysfs-platform-renesas_usb3 new file mode 100644 index 000000000000..5621c15d5dc0 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-platform-renesas_usb3 | |||
@@ -0,0 +1,15 @@ | |||
1 | What: /sys/devices/platform/<renesas_usb3's name>/role | ||
2 | Date: March 2017 | ||
3 | KernelVersion: 4.13 | ||
4 | Contact: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> | ||
5 | Description: | ||
6 | This file can be read and write. | ||
7 | The file can show/change the drd mode of usb. | ||
8 | |||
9 | Write the following string to change the mode: | ||
10 | "host" - switching mode from peripheral to host. | ||
11 | "peripheral" - switching mode from host to peripheral. | ||
12 | |||
13 | Read the file, then it shows the following strings: | ||
14 | "host" - The mode is host now. | ||
15 | "peripheral" - The mode is peripheral now. | ||
diff --git a/Documentation/devicetree/bindings/phy/phy-mt65xx-usb.txt b/Documentation/devicetree/bindings/phy/phy-mt65xx-usb.txt index 33a2b1ee3f3e..0acc5a99fb79 100644 --- a/Documentation/devicetree/bindings/phy/phy-mt65xx-usb.txt +++ b/Documentation/devicetree/bindings/phy/phy-mt65xx-usb.txt | |||
@@ -6,12 +6,11 @@ This binding describes a usb3.0 phy for mt65xx platforms of Medaitek SoC. | |||
6 | Required properties (controller (parent) node): | 6 | Required properties (controller (parent) node): |
7 | - compatible : should be one of | 7 | - compatible : should be one of |
8 | "mediatek,mt2701-u3phy" | 8 | "mediatek,mt2701-u3phy" |
9 | "mediatek,mt2712-u3phy" | ||
9 | "mediatek,mt8173-u3phy" | 10 | "mediatek,mt8173-u3phy" |
10 | - reg : offset and length of register for phy, exclude port's | 11 | - clocks : (deprecated, use port's clocks instead) a list of phandle + |
11 | register. | 12 | clock-specifier pairs, one for each entry in clock-names |
12 | - clocks : a list of phandle + clock-specifier pairs, one for each | 13 | - clock-names : (deprecated, use port's one instead) must contain |
13 | entry in clock-names | ||
14 | - clock-names : must contain | ||
15 | "u3phya_ref": for reference clock of usb3.0 analog phy. | 14 | "u3phya_ref": for reference clock of usb3.0 analog phy. |
16 | 15 | ||
17 | Required nodes : a sub-node is required for each port the controller | 16 | Required nodes : a sub-node is required for each port the controller |
@@ -19,8 +18,19 @@ Required nodes : a sub-node is required for each port the controller | |||
19 | 'reg' property is used inside these nodes to describe | 18 | 'reg' property is used inside these nodes to describe |
20 | the controller's topology. | 19 | the controller's topology. |
21 | 20 | ||
21 | Optional properties (controller (parent) node): | ||
22 | - reg : offset and length of register shared by multiple ports, | ||
23 | exclude port's private register. It is needed on mt2701 | ||
24 | and mt8173, but not on mt2712. | ||
25 | |||
22 | Required properties (port (child) node): | 26 | Required properties (port (child) node): |
23 | - reg : address and length of the register set for the port. | 27 | - reg : address and length of the register set for the port. |
28 | - clocks : a list of phandle + clock-specifier pairs, one for each | ||
29 | entry in clock-names | ||
30 | - clock-names : must contain | ||
31 | "ref": 48M reference clock for HighSpeed analog phy; and 26M | ||
32 | reference clock for SuperSpeed analog phy, sometimes is | ||
33 | 24M, 25M or 27M, depended on platform. | ||
24 | - #phy-cells : should be 1 (See second example) | 34 | - #phy-cells : should be 1 (See second example) |
25 | cell after port phandle is phy type from: | 35 | cell after port phandle is phy type from: |
26 | - PHY_TYPE_USB2 | 36 | - PHY_TYPE_USB2 |
@@ -31,21 +41,31 @@ Example: | |||
31 | u3phy: usb-phy@11290000 { | 41 | u3phy: usb-phy@11290000 { |
32 | compatible = "mediatek,mt8173-u3phy"; | 42 | compatible = "mediatek,mt8173-u3phy"; |
33 | reg = <0 0x11290000 0 0x800>; | 43 | reg = <0 0x11290000 0 0x800>; |
34 | clocks = <&apmixedsys CLK_APMIXED_REF2USB_TX>; | ||
35 | clock-names = "u3phya_ref"; | ||
36 | #address-cells = <2>; | 44 | #address-cells = <2>; |
37 | #size-cells = <2>; | 45 | #size-cells = <2>; |
38 | ranges; | 46 | ranges; |
39 | status = "okay"; | 47 | status = "okay"; |
40 | 48 | ||
41 | phy_port0: port@11290800 { | 49 | u2port0: usb-phy@11290800 { |
42 | reg = <0 0x11290800 0 0x800>; | 50 | reg = <0 0x11290800 0 0x100>; |
51 | clocks = <&apmixedsys CLK_APMIXED_REF2USB_TX>; | ||
52 | clock-names = "ref"; | ||
43 | #phy-cells = <1>; | 53 | #phy-cells = <1>; |
44 | status = "okay"; | 54 | status = "okay"; |
45 | }; | 55 | }; |
46 | 56 | ||
47 | phy_port1: port@11291000 { | 57 | u3port0: usb-phy@11290900 { |
48 | reg = <0 0x11291000 0 0x800>; | 58 | reg = <0 0x11290800 0 0x700>; |
59 | clocks = <&clk26m>; | ||
60 | clock-names = "ref"; | ||
61 | #phy-cells = <1>; | ||
62 | status = "okay"; | ||
63 | }; | ||
64 | |||
65 | u2port1: usb-phy@11291000 { | ||
66 | reg = <0 0x11291000 0 0x100>; | ||
67 | clocks = <&apmixedsys CLK_APMIXED_REF2USB_TX>; | ||
68 | clock-names = "ref"; | ||
49 | #phy-cells = <1>; | 69 | #phy-cells = <1>; |
50 | status = "okay"; | 70 | status = "okay"; |
51 | }; | 71 | }; |
@@ -64,7 +84,54 @@ Example: | |||
64 | 84 | ||
65 | usb30: usb@11270000 { | 85 | usb30: usb@11270000 { |
66 | ... | 86 | ... |
67 | phys = <&phy_port0 PHY_TYPE_USB3>; | 87 | phys = <&u2port0 PHY_TYPE_USB2>, <&u3port0 PHY_TYPE_USB3>; |
68 | phy-names = "usb3-0"; | 88 | phy-names = "usb2-0", "usb3-0"; |
69 | ... | 89 | ... |
70 | }; | 90 | }; |
91 | |||
92 | |||
93 | Layout differences of banks between mt8173/mt2701 and mt2712 | ||
94 | ------------------------------------------------------------- | ||
95 | mt8173 and mt2701: | ||
96 | port offset bank | ||
97 | shared 0x0000 SPLLC | ||
98 | 0x0100 FMREG | ||
99 | u2 port0 0x0800 U2PHY_COM | ||
100 | u3 port0 0x0900 U3PHYD | ||
101 | 0x0a00 U3PHYD_BANK2 | ||
102 | 0x0b00 U3PHYA | ||
103 | 0x0c00 U3PHYA_DA | ||
104 | u2 port1 0x1000 U2PHY_COM | ||
105 | u3 port1 0x1100 U3PHYD | ||
106 | 0x1200 U3PHYD_BANK2 | ||
107 | 0x1300 U3PHYA | ||
108 | 0x1400 U3PHYA_DA | ||
109 | u2 port2 0x1800 U2PHY_COM | ||
110 | ... | ||
111 | |||
112 | mt2712: | ||
113 | port offset bank | ||
114 | u2 port0 0x0000 MISC | ||
115 | 0x0100 FMREG | ||
116 | 0x0300 U2PHY_COM | ||
117 | u3 port0 0x0700 SPLLC | ||
118 | 0x0800 CHIP | ||
119 | 0x0900 U3PHYD | ||
120 | 0x0a00 U3PHYD_BANK2 | ||
121 | 0x0b00 U3PHYA | ||
122 | 0x0c00 U3PHYA_DA | ||
123 | u2 port1 0x1000 MISC | ||
124 | 0x1100 FMREG | ||
125 | 0x1300 U2PHY_COM | ||
126 | u3 port1 0x1700 SPLLC | ||
127 | 0x1800 CHIP | ||
128 | 0x1900 U3PHYD | ||
129 | 0x1a00 U3PHYD_BANK2 | ||
130 | 0x1b00 U3PHYA | ||
131 | 0x1c00 U3PHYA_DA | ||
132 | u2 port2 0x2000 MISC | ||
133 | ... | ||
134 | |||
135 | SPLLC shared by u3 ports and FMREG shared by u2 ports on | ||
136 | mt8173/mt2701 are put back into each port; a new bank MISC for | ||
137 | u2 ports and CHIP for u3 ports are added on mt2712. | ||
diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt b/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt index 3c29c77a7018..e71a8d23f4a8 100644 --- a/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt +++ b/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt | |||
@@ -2,6 +2,7 @@ ROCKCHIP USB2.0 PHY WITH INNO IP BLOCK | |||
2 | 2 | ||
3 | Required properties (phy (parent) node): | 3 | Required properties (phy (parent) node): |
4 | - compatible : should be one of the listed compatibles: | 4 | - compatible : should be one of the listed compatibles: |
5 | * "rockchip,rk3328-usb2phy" | ||
5 | * "rockchip,rk3366-usb2phy" | 6 | * "rockchip,rk3366-usb2phy" |
6 | * "rockchip,rk3399-usb2phy" | 7 | * "rockchip,rk3399-usb2phy" |
7 | - reg : the address offset of grf for usb-phy configuration. | 8 | - reg : the address offset of grf for usb-phy configuration. |
@@ -11,6 +12,11 @@ Required properties (phy (parent) node): | |||
11 | Optional properties: | 12 | Optional properties: |
12 | - clocks : phandle + phy specifier pair, for the input clock of phy. | 13 | - clocks : phandle + phy specifier pair, for the input clock of phy. |
13 | - clock-names : input clock name of phy, must be "phyclk". | 14 | - clock-names : input clock name of phy, must be "phyclk". |
15 | - assigned-clocks : phandle of usb 480m clock. | ||
16 | - assigned-clock-parents : parent of usb 480m clock, select between | ||
17 | usb-phy output 480m and xin24m. | ||
18 | Refer to clk/clock-bindings.txt for generic clock | ||
19 | consumer properties. | ||
14 | 20 | ||
15 | Required nodes : a sub-node is required for each port the phy provides. | 21 | Required nodes : a sub-node is required for each port the phy provides. |
16 | The sub-node name is used to identify host or otg port, | 22 | The sub-node name is used to identify host or otg port, |
diff --git a/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt b/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt new file mode 100644 index 000000000000..e11c563a65ec --- /dev/null +++ b/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt | |||
@@ -0,0 +1,106 @@ | |||
1 | Qualcomm QMP PHY controller | ||
2 | =========================== | ||
3 | |||
4 | QMP phy controller supports physical layer functionality for a number of | ||
5 | controllers on Qualcomm chipsets, such as, PCIe, UFS, and USB. | ||
6 | |||
7 | Required properties: | ||
8 | - compatible: compatible list, contains: | ||
9 | "qcom,msm8996-qmp-pcie-phy" for 14nm PCIe phy on msm8996, | ||
10 | "qcom,msm8996-qmp-usb3-phy" for 14nm USB3 phy on msm8996. | ||
11 | |||
12 | - reg: offset and length of register set for PHY's common serdes block. | ||
13 | |||
14 | - #clock-cells: must be 1 | ||
15 | - Phy pll outputs a bunch of clocks for Tx, Rx and Pipe | ||
16 | interface (for pipe based PHYs). These clock are then gate-controlled | ||
17 | by gcc. | ||
18 | - #address-cells: must be 1 | ||
19 | - #size-cells: must be 1 | ||
20 | - ranges: must be present | ||
21 | |||
22 | - clocks: a list of phandles and clock-specifier pairs, | ||
23 | one for each entry in clock-names. | ||
24 | - clock-names: "cfg_ahb" for phy config clock, | ||
25 | "aux" for phy aux clock, | ||
26 | "ref" for 19.2 MHz ref clk, | ||
27 | For "qcom,msm8996-qmp-pcie-phy" must contain: | ||
28 | "aux", "cfg_ahb", "ref". | ||
29 | For "qcom,msm8996-qmp-usb3-phy" must contain: | ||
30 | "aux", "cfg_ahb", "ref". | ||
31 | |||
32 | - resets: a list of phandles and reset controller specifier pairs, | ||
33 | one for each entry in reset-names. | ||
34 | - reset-names: "phy" for reset of phy block, | ||
35 | "common" for phy common block reset, | ||
36 | "cfg" for phy's ahb cfg block reset (Optional). | ||
37 | For "qcom,msm8996-qmp-pcie-phy" must contain: | ||
38 | "phy", "common", "cfg". | ||
39 | For "qcom,msm8996-qmp-usb3-phy" must contain | ||
40 | "phy", "common". | ||
41 | |||
42 | - vdda-phy-supply: Phandle to a regulator supply to PHY core block. | ||
43 | - vdda-pll-supply: Phandle to 1.8V regulator supply to PHY refclk pll block. | ||
44 | |||
45 | Optional properties: | ||
46 | - vddp-ref-clk-supply: Phandle to a regulator supply to any specific refclk | ||
47 | pll block. | ||
48 | |||
49 | Required nodes: | ||
50 | - Each device node of QMP phy is required to have as many child nodes as | ||
51 | the number of lanes the PHY has. | ||
52 | |||
53 | Required properties for child node: | ||
54 | - reg: list of offset and length pairs of register sets for PHY blocks - | ||
55 | tx, rx and pcs. | ||
56 | |||
57 | - #phy-cells: must be 0 | ||
58 | |||
59 | - clocks: a list of phandles and clock-specifier pairs, | ||
60 | one for each entry in clock-names. | ||
61 | - clock-names: Must contain following for pcie and usb qmp phys: | ||
62 | "pipe<lane-number>" for pipe clock specific to each lane. | ||
63 | |||
64 | - resets: a list of phandles and reset controller specifier pairs, | ||
65 | one for each entry in reset-names. | ||
66 | - reset-names: Must contain following for pcie qmp phys: | ||
67 | "lane<lane-number>" for reset specific to each lane. | ||
68 | |||
69 | Example: | ||
70 | phy@34000 { | ||
71 | compatible = "qcom,msm8996-qmp-pcie-phy"; | ||
72 | reg = <0x34000 0x488>; | ||
73 | #clock-cells = <1>; | ||
74 | #address-cells = <1>; | ||
75 | #size-cells = <1>; | ||
76 | ranges; | ||
77 | |||
78 | clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>, | ||
79 | <&gcc GCC_PCIE_PHY_CFG_AHB_CLK>, | ||
80 | <&gcc GCC_PCIE_CLKREF_CLK>; | ||
81 | clock-names = "aux", "cfg_ahb", "ref"; | ||
82 | |||
83 | vdda-phy-supply = <&pm8994_l28>; | ||
84 | vdda-pll-supply = <&pm8994_l12>; | ||
85 | |||
86 | resets = <&gcc GCC_PCIE_PHY_BCR>, | ||
87 | <&gcc GCC_PCIE_PHY_COM_BCR>, | ||
88 | <&gcc GCC_PCIE_PHY_COM_NOCSR_BCR>; | ||
89 | reset-names = "phy", "common", "cfg"; | ||
90 | |||
91 | pciephy_0: lane@35000 { | ||
92 | reg = <0x35000 0x130>, | ||
93 | <0x35200 0x200>, | ||
94 | <0x35400 0x1dc>; | ||
95 | #phy-cells = <0>; | ||
96 | |||
97 | clocks = <&gcc GCC_PCIE_0_PIPE_CLK>; | ||
98 | clock-names = "pipe0"; | ||
99 | resets = <&gcc GCC_PCIE_0_PHY_BCR>; | ||
100 | reset-names = "lane0"; | ||
101 | }; | ||
102 | |||
103 | pciephy_1: lane@36000 { | ||
104 | ... | ||
105 | ... | ||
106 | }; | ||
diff --git a/Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt b/Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt new file mode 100644 index 000000000000..aa0fcb05acb3 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt | |||
@@ -0,0 +1,43 @@ | |||
1 | Qualcomm QUSB2 phy controller | ||
2 | ============================= | ||
3 | |||
4 | QUSB2 controller supports LS/FS/HS usb connectivity on Qualcomm chipsets. | ||
5 | |||
6 | Required properties: | ||
7 | - compatible: compatible list, contains "qcom,msm8996-qusb2-phy". | ||
8 | - reg: offset and length of the PHY register set. | ||
9 | - #phy-cells: must be 0. | ||
10 | |||
11 | - clocks: a list of phandles and clock-specifier pairs, | ||
12 | one for each entry in clock-names. | ||
13 | - clock-names: must be "cfg_ahb" for phy config clock, | ||
14 | "ref" for 19.2 MHz ref clk, | ||
15 | "iface" for phy interface clock (Optional). | ||
16 | |||
17 | - vdda-pll-supply: Phandle to 1.8V regulator supply to PHY refclk pll block. | ||
18 | - vdda-phy-dpdm-supply: Phandle to 3.1V regulator supply to Dp/Dm port signals. | ||
19 | |||
20 | - resets: Phandle to reset to phy block. | ||
21 | |||
22 | Optional properties: | ||
23 | - nvmem-cells: Phandle to nvmem cell that contains 'HS Tx trim' | ||
24 | tuning parameter value for qusb2 phy. | ||
25 | |||
26 | - qcom,tcsr-syscon: Phandle to TCSR syscon register region. | ||
27 | |||
28 | Example: | ||
29 | hsusb_phy: phy@7411000 { | ||
30 | compatible = "qcom,msm8996-qusb2-phy"; | ||
31 | reg = <0x7411000 0x180>; | ||
32 | #phy-cells = <0>; | ||
33 | |||
34 | clocks = <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>, | ||
35 | <&gcc GCC_RX1_USB2_CLKREF_CLK>, | ||
36 | clock-names = "cfg_ahb", "ref"; | ||
37 | |||
38 | vdda-pll-supply = <&pm8994_l12>; | ||
39 | vdda-phy-dpdm-supply = <&pm8994_l24>; | ||
40 | |||
41 | resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>; | ||
42 | nvmem-cells = <&qusb2p_hstx_trim>; | ||
43 | }; | ||
diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt index 57dc388e2fa2..4ed569046daf 100644 --- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt +++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt | |||
@@ -30,6 +30,7 @@ Optional Properties: | |||
30 | - reset-names: Only allow the following entries: | 30 | - reset-names: Only allow the following entries: |
31 | - phy-reset | 31 | - phy-reset |
32 | - resets: Must contain an entry for each entry in reset-names. | 32 | - resets: Must contain an entry for each entry in reset-names. |
33 | - vbus-supply: power-supply phandle for vbus power source | ||
33 | 34 | ||
34 | Example: | 35 | Example: |
35 | 36 | ||
diff --git a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt index e42334258185..005bc22938ff 100644 --- a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt +++ b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt | |||
@@ -15,6 +15,7 @@ Required properties: | |||
15 | - reg : a list of offset + length pairs | 15 | - reg : a list of offset + length pairs |
16 | - reg-names : | 16 | - reg-names : |
17 | * "phy_ctrl" | 17 | * "phy_ctrl" |
18 | * "pmu0" for H3, V3s and A64 | ||
18 | * "pmu1" | 19 | * "pmu1" |
19 | * "pmu2" for sun4i, sun6i or sun7i | 20 | * "pmu2" for sun4i, sun6i or sun7i |
20 | - #phy-cells : from the generic phy bindings, must be 1 | 21 | - #phy-cells : from the generic phy bindings, must be 1 |
diff --git a/Documentation/devicetree/bindings/soc/rockchip/grf.txt b/Documentation/devicetree/bindings/soc/rockchip/grf.txt index a0685c209218..13ec0992de0f 100644 --- a/Documentation/devicetree/bindings/soc/rockchip/grf.txt +++ b/Documentation/devicetree/bindings/soc/rockchip/grf.txt | |||
@@ -8,6 +8,8 @@ From RK3368 SoCs, the GRF is divided into two sections, | |||
8 | - SGRF, used for general secure system, | 8 | - SGRF, used for general secure system, |
9 | - PMUGRF, used for always on system | 9 | - PMUGRF, used for always on system |
10 | 10 | ||
11 | On RK3328 SoCs, the GRF adds a section for USB2PHYGRF, | ||
12 | |||
11 | Required Properties: | 13 | Required Properties: |
12 | 14 | ||
13 | - compatible: GRF should be one of the following: | 15 | - compatible: GRF should be one of the following: |
@@ -23,6 +25,8 @@ Required Properties: | |||
23 | - "rockchip,rk3399-pmugrf", "syscon": for rk3399 | 25 | - "rockchip,rk3399-pmugrf", "syscon": for rk3399 |
24 | - compatible: SGRF should be one of the following | 26 | - compatible: SGRF should be one of the following |
25 | - "rockchip,rk3288-sgrf", "syscon": for rk3288 | 27 | - "rockchip,rk3288-sgrf", "syscon": for rk3288 |
28 | - compatible: USB2PHYGRF should be one of the followings | ||
29 | - "rockchip,rk3328-usb2phy-grf", "syscon": for rk3328 | ||
26 | - reg: physical base address of the controller and length of memory mapped | 30 | - reg: physical base address of the controller and length of memory mapped |
27 | region. | 31 | region. |
28 | 32 | ||
diff --git a/Documentation/devicetree/bindings/usb/ehci-orion.txt b/Documentation/devicetree/bindings/usb/ehci-orion.txt index 17c3bc858b86..2855bae79fda 100644 --- a/Documentation/devicetree/bindings/usb/ehci-orion.txt +++ b/Documentation/devicetree/bindings/usb/ehci-orion.txt | |||
@@ -1,7 +1,9 @@ | |||
1 | * EHCI controller, Orion Marvell variants | 1 | * EHCI controller, Orion Marvell variants |
2 | 2 | ||
3 | Required properties: | 3 | Required properties: |
4 | - compatible: must be "marvell,orion-ehci" | 4 | - compatible: must be one of the following |
5 | "marvell,orion-ehci" | ||
6 | "marvell,armada-3700-ehci" | ||
5 | - reg: physical base address of the controller and length of memory mapped | 7 | - reg: physical base address of the controller and length of memory mapped |
6 | region. | 8 | region. |
7 | - interrupts: The EHCI interrupt | 9 | - interrupts: The EHCI interrupt |
diff --git a/Documentation/devicetree/bindings/usb/generic.txt b/Documentation/devicetree/bindings/usb/generic.txt index bfadeb1c3bab..0a74ab8dfdc2 100644 --- a/Documentation/devicetree/bindings/usb/generic.txt +++ b/Documentation/devicetree/bindings/usb/generic.txt | |||
@@ -22,6 +22,7 @@ Optional properties: | |||
22 | property is used if any real OTG features(HNP/SRP/ADP) | 22 | property is used if any real OTG features(HNP/SRP/ADP) |
23 | is enabled, if ADP is required, otg-rev should be | 23 | is enabled, if ADP is required, otg-rev should be |
24 | 0x0200 or above. | 24 | 0x0200 or above. |
25 | - companion: phandle of a companion | ||
25 | - hnp-disable: tells OTG controllers we want to disable OTG HNP, normally HNP | 26 | - hnp-disable: tells OTG controllers we want to disable OTG HNP, normally HNP |
26 | is the basic function of real OTG except you want it | 27 | is the basic function of real OTG except you want it |
27 | to be a srp-capable only B device. | 28 | to be a srp-capable only B device. |
diff --git a/Documentation/media/v4l-drivers/philips.rst b/Documentation/media/v4l-drivers/philips.rst index 620bcfea7af0..4f68947e6a13 100644 --- a/Documentation/media/v4l-drivers/philips.rst +++ b/Documentation/media/v4l-drivers/philips.rst | |||
@@ -145,8 +145,8 @@ dev_hint | |||
145 | 145 | ||
146 | A camera is specified by its type (the number from the camera model, | 146 | A camera is specified by its type (the number from the camera model, |
147 | like PCA645, PCVC750VC, etc) and optionally the serial number (visible | 147 | like PCA645, PCVC750VC, etc) and optionally the serial number (visible |
148 | in /proc/bus/usb/devices). A hint consists of a string with the following | 148 | in /sys/kernel/debug/usb/devices). A hint consists of a string with the |
149 | format:: | 149 | following format:: |
150 | 150 | ||
151 | [type[.serialnumber]:]node | 151 | [type[.serialnumber]:]node |
152 | 152 | ||
diff --git a/Documentation/usb/typec.rst b/Documentation/usb/typec.rst new file mode 100644 index 000000000000..b67a46779de9 --- /dev/null +++ b/Documentation/usb/typec.rst | |||
@@ -0,0 +1,184 @@ | |||
1 | |||
2 | USB Type-C connector class | ||
3 | ========================== | ||
4 | |||
5 | Introduction | ||
6 | ------------ | ||
7 | |||
8 | The typec class is meant for describing the USB Type-C ports in a system to the | ||
9 | user space in unified fashion. The class is designed to provide nothing else | ||
10 | except the user space interface implementation in hope that it can be utilized | ||
11 | on as many platforms as possible. | ||
12 | |||
13 | The platforms are expected to register every USB Type-C port they have with the | ||
14 | class. In a normal case the registration will be done by a USB Type-C or PD PHY | ||
15 | driver, but it may be a driver for firmware interface such as UCSI, driver for | ||
16 | USB PD controller or even driver for Thunderbolt3 controller. This document | ||
17 | considers the component registering the USB Type-C ports with the class as "port | ||
18 | driver". | ||
19 | |||
20 | On top of showing the capabilities, the class also offer user space control over | ||
21 | the roles and alternate modes of ports, partners and cable plugs when the port | ||
22 | driver is capable of supporting those features. | ||
23 | |||
24 | The class provides an API for the port drivers described in this document. The | ||
25 | attributes are described in Documentation/ABI/testing/sysfs-class-typec. | ||
26 | |||
27 | User space interface | ||
28 | -------------------- | ||
29 | Every port will be presented as its own device under /sys/class/typec/. The | ||
30 | first port will be named "port0", the second "port1" and so on. | ||
31 | |||
32 | When connected, the partner will be presented also as its own device under | ||
33 | /sys/class/typec/. The parent of the partner device will always be the port it | ||
34 | is attached to. The partner attached to port "port0" will be named | ||
35 | "port0-partner". Full path to the device would be | ||
36 | /sys/class/typec/port0/port0-partner/. | ||
37 | |||
38 | The cable and the two plugs on it may also be optionally presented as their own | ||
39 | devices under /sys/class/typec/. The cable attached to the port "port0" port | ||
40 | will be named port0-cable and the plug on the SOP Prime end (see USB Power | ||
41 | Delivery Specification ch. 2.4) will be named "port0-plug0" and on the SOP | ||
42 | Double Prime end "port0-plug1". The parent of a cable will always be the port, | ||
43 | and the parent of the cable plugs will always be the cable. | ||
44 | |||
45 | If the port, partner or cable plug supports Alternate Modes, every supported | ||
46 | Alternate Mode SVID will have their own device describing them. Note that the | ||
47 | Alternate Mode devices will not be attached to the typec class. The parent of an | ||
48 | alternate mode will be the device that supports it, so for example an alternate | ||
49 | mode of port0-partner will be presented under /sys/class/typec/port0-partner/. | ||
50 | Every mode that is supported will have its own group under the Alternate Mode | ||
51 | device named "mode<index>", for example /sys/class/typec/port0/<alternate | ||
52 | mode>/mode1/. The requests for entering/exiting a mode can be done with "active" | ||
53 | attribute file in that group. | ||
54 | |||
55 | Driver API | ||
56 | ---------- | ||
57 | |||
58 | Registering the ports | ||
59 | ~~~~~~~~~~~~~~~~~~~~~ | ||
60 | |||
61 | The port drivers will describe every Type-C port they control with struct | ||
62 | typec_capability data structure, and register them with the following API: | ||
63 | |||
64 | .. kernel-doc:: drivers/usb/typec/typec.c | ||
65 | :functions: typec_register_port typec_unregister_port | ||
66 | |||
67 | When registering the ports, the prefer_role member in struct typec_capability | ||
68 | deserves special notice. If the port that is being registered does not have | ||
69 | initial role preference, which means the port does not execute Try.SNK or | ||
70 | Try.SRC by default, the member must have value TYPEC_NO_PREFERRED_ROLE. | ||
71 | Otherwise if the port executes Try.SNK by default, the member must have value | ||
72 | TYPEC_DEVICE, and with Try.SRC the value must be TYPEC_HOST. | ||
73 | |||
74 | Registering Partners | ||
75 | ~~~~~~~~~~~~~~~~~~~~ | ||
76 | |||
77 | After successful connection of a partner, the port driver needs to register the | ||
78 | partner with the class. Details about the partner need to be described in struct | ||
79 | typec_partner_desc. The class copies the details of the partner during | ||
80 | registration. The class offers the following API for registering/unregistering | ||
81 | partners. | ||
82 | |||
83 | .. kernel-doc:: drivers/usb/typec/typec.c | ||
84 | :functions: typec_register_partner typec_unregister_partner | ||
85 | |||
86 | The class will provide a handle to struct typec_partner if the registration was | ||
87 | successful, or NULL. | ||
88 | |||
89 | If the partner is USB Power Delivery capable, and the port driver is able to | ||
90 | show the result of Discover Identity command, the partner descriptor structure | ||
91 | should include handle to struct usb_pd_identity instance. The class will then | ||
92 | create a sysfs directory for the identity under the partner device. The result | ||
93 | of Discover Identity command can then be reported with the following API: | ||
94 | |||
95 | .. kernel-doc:: drivers/usb/typec/typec.c | ||
96 | :functions: typec_partner_set_identity | ||
97 | |||
98 | Registering Cables | ||
99 | ~~~~~~~~~~~~~~~~~~ | ||
100 | |||
101 | After successful connection of a cable that supports USB Power Delivery | ||
102 | Structured VDM "Discover Identity", the port driver needs to register the cable | ||
103 | and one or two plugs, depending if there is CC Double Prime controller present | ||
104 | in the cable or not. So a cable capable of SOP Prime communication, but not SOP | ||
105 | Double Prime communication, should only have one plug registered. For more | ||
106 | information about SOP communication, please read chapter about it from the | ||
107 | latest USB Power Delivery specification. | ||
108 | |||
109 | The plugs are represented as their own devices. The cable is registered first, | ||
110 | followed by registration of the cable plugs. The cable will be the parent device | ||
111 | for the plugs. Details about the cable need to be described in struct | ||
112 | typec_cable_desc and about a plug in struct typec_plug_desc. The class copies | ||
113 | the details during registration. The class offers the following API for | ||
114 | registering/unregistering cables and their plugs: | ||
115 | |||
116 | .. kernel-doc:: drivers/usb/typec/typec.c | ||
117 | :functions: typec_register_cable typec_unregister_cable typec_register_plug | ||
118 | typec_unregister_plug | ||
119 | |||
120 | The class will provide a handle to struct typec_cable and struct typec_plug if | ||
121 | the registration is successful, or NULL if it isn't. | ||
122 | |||
123 | If the cable is USB Power Delivery capable, and the port driver is able to show | ||
124 | the result of Discover Identity command, the cable descriptor structure should | ||
125 | include handle to struct usb_pd_identity instance. The class will then create a | ||
126 | sysfs directory for the identity under the cable device. The result of Discover | ||
127 | Identity command can then be reported with the following API: | ||
128 | |||
129 | .. kernel-doc:: drivers/usb/typec/typec.c | ||
130 | :functions: typec_cable_set_identity | ||
131 | |||
132 | Notifications | ||
133 | ~~~~~~~~~~~~~ | ||
134 | |||
135 | When the partner has executed a role change, or when the default roles change | ||
136 | during connection of a partner or cable, the port driver must use the following | ||
137 | APIs to report it to the class: | ||
138 | |||
139 | .. kernel-doc:: drivers/usb/typec/typec.c | ||
140 | :functions: typec_set_data_role typec_set_pwr_role typec_set_vconn_role | ||
141 | typec_set_pwr_opmode | ||
142 | |||
143 | Alternate Modes | ||
144 | ~~~~~~~~~~~~~~~ | ||
145 | |||
146 | USB Type-C ports, partners and cable plugs may support Alternate Modes. Each | ||
147 | Alternate Mode will have identifier called SVID, which is either a Standard ID | ||
148 | given by USB-IF or vendor ID, and each supported SVID can have 1 - 6 modes. The | ||
149 | class provides struct typec_mode_desc for describing individual mode of a SVID, | ||
150 | and struct typec_altmode_desc which is a container for all the supported modes. | ||
151 | |||
152 | Ports that support Alternate Modes need to register each SVID they support with | ||
153 | the following API: | ||
154 | |||
155 | .. kernel-doc:: drivers/usb/typec/typec.c | ||
156 | :functions: typec_port_register_altmode | ||
157 | |||
158 | If a partner or cable plug provides a list of SVIDs as response to USB Power | ||
159 | Delivery Structured VDM Discover SVIDs message, each SVID needs to be | ||
160 | registered. | ||
161 | |||
162 | API for the partners: | ||
163 | |||
164 | .. kernel-doc:: drivers/usb/typec/typec.c | ||
165 | :functions: typec_partner_register_altmode | ||
166 | |||
167 | API for the Cable Plugs: | ||
168 | |||
169 | .. kernel-doc:: drivers/usb/typec/typec.c | ||
170 | :functions: typec_plug_register_altmode | ||
171 | |||
172 | So ports, partners and cable plugs will register the alternate modes with their | ||
173 | own functions, but the registration will always return a handle to struct | ||
174 | typec_altmode on success, or NULL. The unregistration will happen with the same | ||
175 | function: | ||
176 | |||
177 | .. kernel-doc:: drivers/usb/typec/typec.c | ||
178 | :functions: typec_unregister_altmode | ||
179 | |||
180 | If a partner or cable plug enters or exits a mode, the port driver needs to | ||
181 | notify the class with the following API: | ||
182 | |||
183 | .. kernel-doc:: drivers/usb/typec/typec.c | ||
184 | :functions: typec_altmode_update_active | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 3f9b7d5382d7..748354f51966 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -13248,6 +13248,15 @@ F: drivers/usb/ | |||
13248 | F: include/linux/usb.h | 13248 | F: include/linux/usb.h |
13249 | F: include/linux/usb/ | 13249 | F: include/linux/usb/ |
13250 | 13250 | ||
13251 | USB TYPEC SUBSYSTEM | ||
13252 | M: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
13253 | L: linux-usb@vger.kernel.org | ||
13254 | S: Maintained | ||
13255 | F: Documentation/ABI/testing/sysfs-class-typec | ||
13256 | F: Documentation/usb/typec.rst | ||
13257 | F: drivers/usb/typec/ | ||
13258 | F: include/linux/usb/typec.h | ||
13259 | |||
13251 | USB UHCI DRIVER | 13260 | USB UHCI DRIVER |
13252 | M: Alan Stern <stern@rowland.harvard.edu> | 13261 | M: Alan Stern <stern@rowland.harvard.edu> |
13253 | L: linux-usb@vger.kernel.org | 13262 | L: linux-usb@vger.kernel.org |
diff --git a/arch/arm64/boot/dts/marvell/armada-3720-db.dts b/arch/arm64/boot/dts/marvell/armada-3720-db.dts index 86602c907a61..a07a0c1cd4e6 100644 --- a/arch/arm64/boot/dts/marvell/armada-3720-db.dts +++ b/arch/arm64/boot/dts/marvell/armada-3720-db.dts | |||
@@ -116,6 +116,12 @@ | |||
116 | status = "okay"; | 116 | status = "okay"; |
117 | }; | 117 | }; |
118 | 118 | ||
119 | /* CON27 */ | ||
120 | &usb2 { | ||
121 | status = "okay"; | ||
122 | }; | ||
123 | |||
124 | |||
119 | &mdio { | 125 | &mdio { |
120 | status = "okay"; | 126 | status = "okay"; |
121 | phy0: ethernet-phy@0 { | 127 | phy0: ethernet-phy@0 { |
diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi index b48d668a6ab6..42747b7db683 100644 --- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi | |||
@@ -200,6 +200,13 @@ | |||
200 | status = "disabled"; | 200 | status = "disabled"; |
201 | }; | 201 | }; |
202 | 202 | ||
203 | usb2: usb@5e000 { | ||
204 | compatible = "marvell,armada-3700-ehci"; | ||
205 | reg = <0x5e000 0x2000>; | ||
206 | interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>; | ||
207 | status = "disabled"; | ||
208 | }; | ||
209 | |||
203 | xor@60900 { | 210 | xor@60900 { |
204 | compatible = "marvell,armada-3700-xor"; | 211 | compatible = "marvell,armada-3700-xor"; |
205 | reg = <0x60900 0x100 | 212 | reg = <0x60900 0x100 |
diff --git a/drivers/Makefile b/drivers/Makefile index 2eced9afba53..8f8bdc9e3d29 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
@@ -104,6 +104,7 @@ obj-$(CONFIG_USB_PHY) += usb/ | |||
104 | obj-$(CONFIG_USB) += usb/ | 104 | obj-$(CONFIG_USB) += usb/ |
105 | obj-$(CONFIG_PCI) += usb/ | 105 | obj-$(CONFIG_PCI) += usb/ |
106 | obj-$(CONFIG_USB_GADGET) += usb/ | 106 | obj-$(CONFIG_USB_GADGET) += usb/ |
107 | obj-$(CONFIG_OF) += usb/ | ||
107 | obj-$(CONFIG_SERIO) += input/serio/ | 108 | obj-$(CONFIG_SERIO) += input/serio/ |
108 | obj-$(CONFIG_GAMEPORT) += input/gameport/ | 109 | obj-$(CONFIG_GAMEPORT) += input/gameport/ |
109 | obj-$(CONFIG_INPUT) += input/ | 110 | obj-$(CONFIG_INPUT) += input/ |
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 005cadb7a3f8..afaf7b643eeb 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig | |||
@@ -439,6 +439,25 @@ config PHY_STIH407_USB | |||
439 | Enable this support to enable the picoPHY device used by USB2 | 439 | Enable this support to enable the picoPHY device used by USB2 |
440 | and USB3 controllers on STMicroelectronics STiH407 SoC families. | 440 | and USB3 controllers on STMicroelectronics STiH407 SoC families. |
441 | 441 | ||
442 | config PHY_QCOM_QMP | ||
443 | tristate "Qualcomm QMP PHY Driver" | ||
444 | depends on OF && COMMON_CLK && (ARCH_QCOM || COMPILE_TEST) | ||
445 | select GENERIC_PHY | ||
446 | help | ||
447 | Enable this to support the QMP PHY transceiver that is used | ||
448 | with controllers such as PCIe, UFS, and USB on Qualcomm chips. | ||
449 | |||
450 | config PHY_QCOM_QUSB2 | ||
451 | tristate "Qualcomm QUSB2 PHY Driver" | ||
452 | depends on OF && (ARCH_QCOM || COMPILE_TEST) | ||
453 | depends on NVMEM || !NVMEM | ||
454 | select GENERIC_PHY | ||
455 | help | ||
456 | Enable this to support the HighSpeed QUSB2 PHY transceiver for USB | ||
457 | controllers on Qualcomm chips. This driver supports the high-speed | ||
458 | PHY which is usually paired with either the ChipIdea or Synopsys DWC3 | ||
459 | USB IPs on MSM SOCs. | ||
460 | |||
442 | config PHY_QCOM_UFS | 461 | config PHY_QCOM_UFS |
443 | tristate "Qualcomm UFS PHY driver" | 462 | tristate "Qualcomm UFS PHY driver" |
444 | depends on OF && ARCH_QCOM | 463 | depends on OF && ARCH_QCOM |
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index dd8f3b5d2918..f8047b4639fa 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile | |||
@@ -50,6 +50,8 @@ obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o | |||
50 | obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o | 50 | obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o |
51 | obj-$(CONFIG_PHY_XGENE) += phy-xgene.o | 51 | obj-$(CONFIG_PHY_XGENE) += phy-xgene.o |
52 | obj-$(CONFIG_PHY_STIH407_USB) += phy-stih407-usb.o | 52 | obj-$(CONFIG_PHY_STIH407_USB) += phy-stih407-usb.o |
53 | obj-$(CONFIG_PHY_QCOM_QMP) += phy-qcom-qmp.o | ||
54 | obj-$(CONFIG_PHY_QCOM_QUSB2) += phy-qcom-qusb2.o | ||
53 | obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs.o | 55 | obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs.o |
54 | obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o | 56 | obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o |
55 | obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o | 57 | obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o |
diff --git a/drivers/phy/phy-bcm-ns-usb3.c b/drivers/phy/phy-bcm-ns-usb3.c index f420fa4bebfc..22b5e7047fa6 100644 --- a/drivers/phy/phy-bcm-ns-usb3.c +++ b/drivers/phy/phy-bcm-ns-usb3.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * Broadcom Northstar USB 3.0 PHY Driver | 2 | * Broadcom Northstar USB 3.0 PHY Driver |
3 | * | 3 | * |
4 | * Copyright (C) 2016 Rafał Miłecki <rafal@milecki.pl> | 4 | * Copyright (C) 2016 Rafał Miłecki <rafal@milecki.pl> |
5 | * Copyright (C) 2016 Broadcom | ||
5 | * | 6 | * |
6 | * All magic values used for initialization (and related comments) were obtained | 7 | * All magic values used for initialization (and related comments) were obtained |
7 | * from Broadcom's SDK: | 8 | * from Broadcom's SDK: |
@@ -23,6 +24,23 @@ | |||
23 | 24 | ||
24 | #define BCM_NS_USB3_MII_MNG_TIMEOUT_US 1000 /* usecs */ | 25 | #define BCM_NS_USB3_MII_MNG_TIMEOUT_US 1000 /* usecs */ |
25 | 26 | ||
27 | #define BCM_NS_USB3_PHY_BASE_ADDR_REG 0x1f | ||
28 | #define BCM_NS_USB3_PHY_PLL30_BLOCK 0x8000 | ||
29 | #define BCM_NS_USB3_PHY_TX_PMD_BLOCK 0x8040 | ||
30 | #define BCM_NS_USB3_PHY_PIPE_BLOCK 0x8060 | ||
31 | |||
32 | /* Registers of PLL30 block */ | ||
33 | #define BCM_NS_USB3_PLL_CONTROL 0x01 | ||
34 | #define BCM_NS_USB3_PLLA_CONTROL0 0x0a | ||
35 | #define BCM_NS_USB3_PLLA_CONTROL1 0x0b | ||
36 | |||
37 | /* Registers of TX PMD block */ | ||
38 | #define BCM_NS_USB3_TX_PMD_CONTROL1 0x01 | ||
39 | |||
40 | /* Registers of PIPE block */ | ||
41 | #define BCM_NS_USB3_LFPS_CMP 0x02 | ||
42 | #define BCM_NS_USB3_LFPS_DEGLITCH 0x03 | ||
43 | |||
26 | enum bcm_ns_family { | 44 | enum bcm_ns_family { |
27 | BCM_NS_UNKNOWN, | 45 | BCM_NS_UNKNOWN, |
28 | BCM_NS_AX, | 46 | BCM_NS_AX, |
@@ -76,8 +94,10 @@ static inline int bcm_ns_usb3_mii_mng_wait_idle(struct bcm_ns_usb3 *usb3) | |||
76 | usecs_to_jiffies(BCM_NS_USB3_MII_MNG_TIMEOUT_US)); | 94 | usecs_to_jiffies(BCM_NS_USB3_MII_MNG_TIMEOUT_US)); |
77 | } | 95 | } |
78 | 96 | ||
79 | static int bcm_ns_usb3_mii_mng_write32(struct bcm_ns_usb3 *usb3, u32 value) | 97 | static int bcm_ns_usb3_mdio_phy_write(struct bcm_ns_usb3 *usb3, u16 reg, |
98 | u16 value) | ||
80 | { | 99 | { |
100 | u32 tmp = 0; | ||
81 | int err; | 101 | int err; |
82 | 102 | ||
83 | err = bcm_ns_usb3_mii_mng_wait_idle(usb3); | 103 | err = bcm_ns_usb3_mii_mng_wait_idle(usb3); |
@@ -86,7 +106,11 @@ static int bcm_ns_usb3_mii_mng_write32(struct bcm_ns_usb3 *usb3, u32 value) | |||
86 | return err; | 106 | return err; |
87 | } | 107 | } |
88 | 108 | ||
89 | writel(value, usb3->ccb_mii + BCMA_CCB_MII_MNG_CMD_DATA); | 109 | /* TODO: Use a proper MDIO bus layer */ |
110 | tmp |= 0x58020000; /* Magic value for MDIO PHY write */ | ||
111 | tmp |= reg << 18; | ||
112 | tmp |= value; | ||
113 | writel(tmp, usb3->ccb_mii + BCMA_CCB_MII_MNG_CMD_DATA); | ||
90 | 114 | ||
91 | return 0; | 115 | return 0; |
92 | } | 116 | } |
@@ -102,21 +126,22 @@ static int bcm_ns_usb3_phy_init_ns_bx(struct bcm_ns_usb3 *usb3) | |||
102 | udelay(2); | 126 | udelay(2); |
103 | 127 | ||
104 | /* USB3 PLL Block */ | 128 | /* USB3 PLL Block */ |
105 | err = bcm_ns_usb3_mii_mng_write32(usb3, 0x587e8000); | 129 | err = bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG, |
130 | BCM_NS_USB3_PHY_PLL30_BLOCK); | ||
106 | if (err < 0) | 131 | if (err < 0) |
107 | return err; | 132 | return err; |
108 | 133 | ||
109 | /* Assert Ana_Pllseq start */ | 134 | /* Assert Ana_Pllseq start */ |
110 | bcm_ns_usb3_mii_mng_write32(usb3, 0x58061000); | 135 | bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLL_CONTROL, 0x1000); |
111 | 136 | ||
112 | /* Assert CML Divider ratio to 26 */ | 137 | /* Assert CML Divider ratio to 26 */ |
113 | bcm_ns_usb3_mii_mng_write32(usb3, 0x582a6400); | 138 | bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL0, 0x6400); |
114 | 139 | ||
115 | /* Asserting PLL Reset */ | 140 | /* Asserting PLL Reset */ |
116 | bcm_ns_usb3_mii_mng_write32(usb3, 0x582ec000); | 141 | bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL1, 0xc000); |
117 | 142 | ||
118 | /* Deaaserting PLL Reset */ | 143 | /* Deaaserting PLL Reset */ |
119 | bcm_ns_usb3_mii_mng_write32(usb3, 0x582e8000); | 144 | bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL1, 0x8000); |
120 | 145 | ||
121 | /* Waiting MII Mgt interface idle */ | 146 | /* Waiting MII Mgt interface idle */ |
122 | bcm_ns_usb3_mii_mng_wait_idle(usb3); | 147 | bcm_ns_usb3_mii_mng_wait_idle(usb3); |
@@ -125,22 +150,24 @@ static int bcm_ns_usb3_phy_init_ns_bx(struct bcm_ns_usb3 *usb3) | |||
125 | writel(0, usb3->dmp + BCMA_RESET_CTL); | 150 | writel(0, usb3->dmp + BCMA_RESET_CTL); |
126 | 151 | ||
127 | /* PLL frequency monitor enable */ | 152 | /* PLL frequency monitor enable */ |
128 | bcm_ns_usb3_mii_mng_write32(usb3, 0x58069000); | 153 | bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLL_CONTROL, 0x9000); |
129 | 154 | ||
130 | /* PIPE Block */ | 155 | /* PIPE Block */ |
131 | bcm_ns_usb3_mii_mng_write32(usb3, 0x587e8060); | 156 | bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG, |
157 | BCM_NS_USB3_PHY_PIPE_BLOCK); | ||
132 | 158 | ||
133 | /* CMPMAX & CMPMINTH setting */ | 159 | /* CMPMAX & CMPMINTH setting */ |
134 | bcm_ns_usb3_mii_mng_write32(usb3, 0x580af30d); | 160 | bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_LFPS_CMP, 0xf30d); |
135 | 161 | ||
136 | /* DEGLITCH MIN & MAX setting */ | 162 | /* DEGLITCH MIN & MAX setting */ |
137 | bcm_ns_usb3_mii_mng_write32(usb3, 0x580e6302); | 163 | bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_LFPS_DEGLITCH, 0x6302); |
138 | 164 | ||
139 | /* TXPMD block */ | 165 | /* TXPMD block */ |
140 | bcm_ns_usb3_mii_mng_write32(usb3, 0x587e8040); | 166 | bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG, |
167 | BCM_NS_USB3_PHY_TX_PMD_BLOCK); | ||
141 | 168 | ||
142 | /* Enabling SSC */ | 169 | /* Enabling SSC */ |
143 | bcm_ns_usb3_mii_mng_write32(usb3, 0x58061003); | 170 | bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_TX_PMD_CONTROL1, 0x1003); |
144 | 171 | ||
145 | /* Waiting MII Mgt interface idle */ | 172 | /* Waiting MII Mgt interface idle */ |
146 | bcm_ns_usb3_mii_mng_wait_idle(usb3); | 173 | bcm_ns_usb3_mii_mng_wait_idle(usb3); |
@@ -159,22 +186,24 @@ static int bcm_ns_usb3_phy_init_ns_ax(struct bcm_ns_usb3 *usb3) | |||
159 | udelay(2); | 186 | udelay(2); |
160 | 187 | ||
161 | /* PLL30 block */ | 188 | /* PLL30 block */ |
162 | err = bcm_ns_usb3_mii_mng_write32(usb3, 0x587e8000); | 189 | err = bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG, |
190 | BCM_NS_USB3_PHY_PLL30_BLOCK); | ||
163 | if (err < 0) | 191 | if (err < 0) |
164 | return err; | 192 | return err; |
165 | 193 | ||
166 | bcm_ns_usb3_mii_mng_write32(usb3, 0x582a6400); | 194 | bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PLLA_CONTROL0, 0x6400); |
167 | 195 | ||
168 | bcm_ns_usb3_mii_mng_write32(usb3, 0x587e80e0); | 196 | bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG, 0x80e0); |
169 | 197 | ||
170 | bcm_ns_usb3_mii_mng_write32(usb3, 0x580a009c); | 198 | bcm_ns_usb3_mdio_phy_write(usb3, 0x02, 0x009c); |
171 | 199 | ||
172 | /* Enable SSC */ | 200 | /* Enable SSC */ |
173 | bcm_ns_usb3_mii_mng_write32(usb3, 0x587e8040); | 201 | bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_PHY_BASE_ADDR_REG, |
202 | BCM_NS_USB3_PHY_TX_PMD_BLOCK); | ||
174 | 203 | ||
175 | bcm_ns_usb3_mii_mng_write32(usb3, 0x580a21d3); | 204 | bcm_ns_usb3_mdio_phy_write(usb3, 0x02, 0x21d3); |
176 | 205 | ||
177 | bcm_ns_usb3_mii_mng_write32(usb3, 0x58061003); | 206 | bcm_ns_usb3_mdio_phy_write(usb3, BCM_NS_USB3_TX_PMD_CONTROL1, 0x1003); |
178 | 207 | ||
179 | /* Waiting MII Mgt interface idle */ | 208 | /* Waiting MII Mgt interface idle */ |
180 | bcm_ns_usb3_mii_mng_wait_idle(usb3); | 209 | bcm_ns_usb3_mii_mng_wait_idle(usb3); |
diff --git a/drivers/phy/phy-exynos-dp-video.c b/drivers/phy/phy-exynos-dp-video.c index 34b06154e5d9..bb3279dbf88c 100644 --- a/drivers/phy/phy-exynos-dp-video.c +++ b/drivers/phy/phy-exynos-dp-video.c | |||
@@ -14,12 +14,12 @@ | |||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/mfd/syscon.h> | 16 | #include <linux/mfd/syscon.h> |
17 | #include <linux/mfd/syscon/exynos5-pmu.h> | ||
18 | #include <linux/of.h> | 17 | #include <linux/of.h> |
19 | #include <linux/of_address.h> | 18 | #include <linux/of_address.h> |
20 | #include <linux/phy/phy.h> | 19 | #include <linux/phy/phy.h> |
21 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
22 | #include <linux/regmap.h> | 21 | #include <linux/regmap.h> |
22 | #include <linux/soc/samsung/exynos-regs-pmu.h> | ||
23 | 23 | ||
24 | struct exynos_dp_video_phy_drvdata { | 24 | struct exynos_dp_video_phy_drvdata { |
25 | u32 phy_ctrl_offset; | 25 | u32 phy_ctrl_offset; |
@@ -36,7 +36,7 @@ static int exynos_dp_video_phy_power_on(struct phy *phy) | |||
36 | 36 | ||
37 | /* Disable power isolation on DP-PHY */ | 37 | /* Disable power isolation on DP-PHY */ |
38 | return regmap_update_bits(state->regs, state->drvdata->phy_ctrl_offset, | 38 | return regmap_update_bits(state->regs, state->drvdata->phy_ctrl_offset, |
39 | EXYNOS5_PHY_ENABLE, EXYNOS5_PHY_ENABLE); | 39 | EXYNOS4_PHY_ENABLE, EXYNOS4_PHY_ENABLE); |
40 | } | 40 | } |
41 | 41 | ||
42 | static int exynos_dp_video_phy_power_off(struct phy *phy) | 42 | static int exynos_dp_video_phy_power_off(struct phy *phy) |
@@ -45,7 +45,7 @@ static int exynos_dp_video_phy_power_off(struct phy *phy) | |||
45 | 45 | ||
46 | /* Enable power isolation on DP-PHY */ | 46 | /* Enable power isolation on DP-PHY */ |
47 | return regmap_update_bits(state->regs, state->drvdata->phy_ctrl_offset, | 47 | return regmap_update_bits(state->regs, state->drvdata->phy_ctrl_offset, |
48 | EXYNOS5_PHY_ENABLE, 0); | 48 | EXYNOS4_PHY_ENABLE, 0); |
49 | } | 49 | } |
50 | 50 | ||
51 | static const struct phy_ops exynos_dp_video_phy_ops = { | 51 | static const struct phy_ops exynos_dp_video_phy_ops = { |
diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c index 6bee04cc4d53..c198886f80a3 100644 --- a/drivers/phy/phy-exynos-mipi-video.c +++ b/drivers/phy/phy-exynos-mipi-video.c | |||
@@ -12,8 +12,6 @@ | |||
12 | #include <linux/err.h> | 12 | #include <linux/err.h> |
13 | #include <linux/io.h> | 13 | #include <linux/io.h> |
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/mfd/syscon/exynos4-pmu.h> | ||
16 | #include <linux/mfd/syscon/exynos5-pmu.h> | ||
17 | #include <linux/module.h> | 15 | #include <linux/module.h> |
18 | #include <linux/of.h> | 16 | #include <linux/of.h> |
19 | #include <linux/of_address.h> | 17 | #include <linux/of_address.h> |
@@ -21,6 +19,7 @@ | |||
21 | #include <linux/phy/phy.h> | 19 | #include <linux/phy/phy.h> |
22 | #include <linux/regmap.h> | 20 | #include <linux/regmap.h> |
23 | #include <linux/spinlock.h> | 21 | #include <linux/spinlock.h> |
22 | #include <linux/soc/samsung/exynos-regs-pmu.h> | ||
24 | #include <linux/mfd/syscon.h> | 23 | #include <linux/mfd/syscon.h> |
25 | 24 | ||
26 | enum exynos_mipi_phy_id { | 25 | enum exynos_mipi_phy_id { |
@@ -64,7 +63,7 @@ static const struct mipi_phy_device_desc s5pv210_mipi_phy = { | |||
64 | { | 63 | { |
65 | /* EXYNOS_MIPI_PHY_ID_CSIS0 */ | 64 | /* EXYNOS_MIPI_PHY_ID_CSIS0 */ |
66 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM0, | 65 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM0, |
67 | .enable_val = EXYNOS4_MIPI_PHY_ENABLE, | 66 | .enable_val = EXYNOS4_PHY_ENABLE, |
68 | .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(0), | 67 | .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(0), |
69 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, | 68 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, |
70 | .resetn_val = EXYNOS4_MIPI_PHY_SRESETN, | 69 | .resetn_val = EXYNOS4_MIPI_PHY_SRESETN, |
@@ -73,7 +72,7 @@ static const struct mipi_phy_device_desc s5pv210_mipi_phy = { | |||
73 | }, { | 72 | }, { |
74 | /* EXYNOS_MIPI_PHY_ID_DSIM0 */ | 73 | /* EXYNOS_MIPI_PHY_ID_DSIM0 */ |
75 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS0, | 74 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS0, |
76 | .enable_val = EXYNOS4_MIPI_PHY_ENABLE, | 75 | .enable_val = EXYNOS4_PHY_ENABLE, |
77 | .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(0), | 76 | .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(0), |
78 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, | 77 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, |
79 | .resetn_val = EXYNOS4_MIPI_PHY_MRESETN, | 78 | .resetn_val = EXYNOS4_MIPI_PHY_MRESETN, |
@@ -82,7 +81,7 @@ static const struct mipi_phy_device_desc s5pv210_mipi_phy = { | |||
82 | }, { | 81 | }, { |
83 | /* EXYNOS_MIPI_PHY_ID_CSIS1 */ | 82 | /* EXYNOS_MIPI_PHY_ID_CSIS1 */ |
84 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM1, | 83 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM1, |
85 | .enable_val = EXYNOS4_MIPI_PHY_ENABLE, | 84 | .enable_val = EXYNOS4_PHY_ENABLE, |
86 | .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(1), | 85 | .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(1), |
87 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, | 86 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, |
88 | .resetn_val = EXYNOS4_MIPI_PHY_SRESETN, | 87 | .resetn_val = EXYNOS4_MIPI_PHY_SRESETN, |
@@ -91,7 +90,7 @@ static const struct mipi_phy_device_desc s5pv210_mipi_phy = { | |||
91 | }, { | 90 | }, { |
92 | /* EXYNOS_MIPI_PHY_ID_DSIM1 */ | 91 | /* EXYNOS_MIPI_PHY_ID_DSIM1 */ |
93 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS1, | 92 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS1, |
94 | .enable_val = EXYNOS4_MIPI_PHY_ENABLE, | 93 | .enable_val = EXYNOS4_PHY_ENABLE, |
95 | .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(1), | 94 | .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(1), |
96 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, | 95 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, |
97 | .resetn_val = EXYNOS4_MIPI_PHY_MRESETN, | 96 | .resetn_val = EXYNOS4_MIPI_PHY_MRESETN, |
@@ -109,47 +108,47 @@ static const struct mipi_phy_device_desc exynos5420_mipi_phy = { | |||
109 | { | 108 | { |
110 | /* EXYNOS_MIPI_PHY_ID_CSIS0 */ | 109 | /* EXYNOS_MIPI_PHY_ID_CSIS0 */ |
111 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM0, | 110 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM0, |
112 | .enable_val = EXYNOS5_PHY_ENABLE, | 111 | .enable_val = EXYNOS4_PHY_ENABLE, |
113 | .enable_reg = EXYNOS5420_MIPI_PHY0_CONTROL, | 112 | .enable_reg = EXYNOS5420_MIPI_PHY_CONTROL(0), |
114 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, | 113 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, |
115 | .resetn_val = EXYNOS5_MIPI_PHY_S_RESETN, | 114 | .resetn_val = EXYNOS4_MIPI_PHY_SRESETN, |
116 | .resetn_reg = EXYNOS5420_MIPI_PHY0_CONTROL, | 115 | .resetn_reg = EXYNOS5420_MIPI_PHY_CONTROL(0), |
117 | .resetn_map = EXYNOS_MIPI_REGMAP_PMU, | 116 | .resetn_map = EXYNOS_MIPI_REGMAP_PMU, |
118 | }, { | 117 | }, { |
119 | /* EXYNOS_MIPI_PHY_ID_DSIM0 */ | 118 | /* EXYNOS_MIPI_PHY_ID_DSIM0 */ |
120 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS0, | 119 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS0, |
121 | .enable_val = EXYNOS5_PHY_ENABLE, | 120 | .enable_val = EXYNOS4_PHY_ENABLE, |
122 | .enable_reg = EXYNOS5420_MIPI_PHY0_CONTROL, | 121 | .enable_reg = EXYNOS5420_MIPI_PHY_CONTROL(0), |
123 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, | 122 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, |
124 | .resetn_val = EXYNOS5_MIPI_PHY_M_RESETN, | 123 | .resetn_val = EXYNOS4_MIPI_PHY_MRESETN, |
125 | .resetn_reg = EXYNOS5420_MIPI_PHY0_CONTROL, | 124 | .resetn_reg = EXYNOS5420_MIPI_PHY_CONTROL(0), |
126 | .resetn_map = EXYNOS_MIPI_REGMAP_PMU, | 125 | .resetn_map = EXYNOS_MIPI_REGMAP_PMU, |
127 | }, { | 126 | }, { |
128 | /* EXYNOS_MIPI_PHY_ID_CSIS1 */ | 127 | /* EXYNOS_MIPI_PHY_ID_CSIS1 */ |
129 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM1, | 128 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM1, |
130 | .enable_val = EXYNOS5_PHY_ENABLE, | 129 | .enable_val = EXYNOS4_PHY_ENABLE, |
131 | .enable_reg = EXYNOS5420_MIPI_PHY1_CONTROL, | 130 | .enable_reg = EXYNOS5420_MIPI_PHY_CONTROL(1), |
132 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, | 131 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, |
133 | .resetn_val = EXYNOS5_MIPI_PHY_S_RESETN, | 132 | .resetn_val = EXYNOS4_MIPI_PHY_SRESETN, |
134 | .resetn_reg = EXYNOS5420_MIPI_PHY1_CONTROL, | 133 | .resetn_reg = EXYNOS5420_MIPI_PHY_CONTROL(1), |
135 | .resetn_map = EXYNOS_MIPI_REGMAP_PMU, | 134 | .resetn_map = EXYNOS_MIPI_REGMAP_PMU, |
136 | }, { | 135 | }, { |
137 | /* EXYNOS_MIPI_PHY_ID_DSIM1 */ | 136 | /* EXYNOS_MIPI_PHY_ID_DSIM1 */ |
138 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS1, | 137 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS1, |
139 | .enable_val = EXYNOS5_PHY_ENABLE, | 138 | .enable_val = EXYNOS4_PHY_ENABLE, |
140 | .enable_reg = EXYNOS5420_MIPI_PHY1_CONTROL, | 139 | .enable_reg = EXYNOS5420_MIPI_PHY_CONTROL(1), |
141 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, | 140 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, |
142 | .resetn_val = EXYNOS5_MIPI_PHY_M_RESETN, | 141 | .resetn_val = EXYNOS4_MIPI_PHY_MRESETN, |
143 | .resetn_reg = EXYNOS5420_MIPI_PHY1_CONTROL, | 142 | .resetn_reg = EXYNOS5420_MIPI_PHY_CONTROL(1), |
144 | .resetn_map = EXYNOS_MIPI_REGMAP_PMU, | 143 | .resetn_map = EXYNOS_MIPI_REGMAP_PMU, |
145 | }, { | 144 | }, { |
146 | /* EXYNOS_MIPI_PHY_ID_CSIS2 */ | 145 | /* EXYNOS_MIPI_PHY_ID_CSIS2 */ |
147 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_NONE, | 146 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_NONE, |
148 | .enable_val = EXYNOS5_PHY_ENABLE, | 147 | .enable_val = EXYNOS4_PHY_ENABLE, |
149 | .enable_reg = EXYNOS5420_MIPI_PHY2_CONTROL, | 148 | .enable_reg = EXYNOS5420_MIPI_PHY_CONTROL(2), |
150 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, | 149 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, |
151 | .resetn_val = EXYNOS5_MIPI_PHY_S_RESETN, | 150 | .resetn_val = EXYNOS4_MIPI_PHY_SRESETN, |
152 | .resetn_reg = EXYNOS5420_MIPI_PHY2_CONTROL, | 151 | .resetn_reg = EXYNOS5420_MIPI_PHY_CONTROL(2), |
153 | .resetn_map = EXYNOS_MIPI_REGMAP_PMU, | 152 | .resetn_map = EXYNOS_MIPI_REGMAP_PMU, |
154 | }, | 153 | }, |
155 | }, | 154 | }, |
@@ -172,8 +171,8 @@ static const struct mipi_phy_device_desc exynos5433_mipi_phy = { | |||
172 | { | 171 | { |
173 | /* EXYNOS_MIPI_PHY_ID_CSIS0 */ | 172 | /* EXYNOS_MIPI_PHY_ID_CSIS0 */ |
174 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM0, | 173 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_DSIM0, |
175 | .enable_val = EXYNOS5_PHY_ENABLE, | 174 | .enable_val = EXYNOS4_PHY_ENABLE, |
176 | .enable_reg = EXYNOS5433_MIPI_PHY0_CONTROL, | 175 | .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(0), |
177 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, | 176 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, |
178 | .resetn_val = BIT(0), | 177 | .resetn_val = BIT(0), |
179 | .resetn_reg = EXYNOS5433_SYSREG_CAM0_MIPI_DPHY_CON, | 178 | .resetn_reg = EXYNOS5433_SYSREG_CAM0_MIPI_DPHY_CON, |
@@ -181,8 +180,8 @@ static const struct mipi_phy_device_desc exynos5433_mipi_phy = { | |||
181 | }, { | 180 | }, { |
182 | /* EXYNOS_MIPI_PHY_ID_DSIM0 */ | 181 | /* EXYNOS_MIPI_PHY_ID_DSIM0 */ |
183 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS0, | 182 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_CSIS0, |
184 | .enable_val = EXYNOS5_PHY_ENABLE, | 183 | .enable_val = EXYNOS4_PHY_ENABLE, |
185 | .enable_reg = EXYNOS5433_MIPI_PHY0_CONTROL, | 184 | .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(0), |
186 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, | 185 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, |
187 | .resetn_val = BIT(0), | 186 | .resetn_val = BIT(0), |
188 | .resetn_reg = EXYNOS5433_SYSREG_DISP_MIPI_PHY, | 187 | .resetn_reg = EXYNOS5433_SYSREG_DISP_MIPI_PHY, |
@@ -190,8 +189,8 @@ static const struct mipi_phy_device_desc exynos5433_mipi_phy = { | |||
190 | }, { | 189 | }, { |
191 | /* EXYNOS_MIPI_PHY_ID_CSIS1 */ | 190 | /* EXYNOS_MIPI_PHY_ID_CSIS1 */ |
192 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_NONE, | 191 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_NONE, |
193 | .enable_val = EXYNOS5_PHY_ENABLE, | 192 | .enable_val = EXYNOS4_PHY_ENABLE, |
194 | .enable_reg = EXYNOS5433_MIPI_PHY1_CONTROL, | 193 | .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(1), |
195 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, | 194 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, |
196 | .resetn_val = BIT(1), | 195 | .resetn_val = BIT(1), |
197 | .resetn_reg = EXYNOS5433_SYSREG_CAM0_MIPI_DPHY_CON, | 196 | .resetn_reg = EXYNOS5433_SYSREG_CAM0_MIPI_DPHY_CON, |
@@ -199,8 +198,8 @@ static const struct mipi_phy_device_desc exynos5433_mipi_phy = { | |||
199 | }, { | 198 | }, { |
200 | /* EXYNOS_MIPI_PHY_ID_DSIM1 */ | 199 | /* EXYNOS_MIPI_PHY_ID_DSIM1 */ |
201 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_NONE, | 200 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_NONE, |
202 | .enable_val = EXYNOS5_PHY_ENABLE, | 201 | .enable_val = EXYNOS4_PHY_ENABLE, |
203 | .enable_reg = EXYNOS5433_MIPI_PHY1_CONTROL, | 202 | .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(1), |
204 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, | 203 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, |
205 | .resetn_val = BIT(1), | 204 | .resetn_val = BIT(1), |
206 | .resetn_reg = EXYNOS5433_SYSREG_DISP_MIPI_PHY, | 205 | .resetn_reg = EXYNOS5433_SYSREG_DISP_MIPI_PHY, |
@@ -208,8 +207,8 @@ static const struct mipi_phy_device_desc exynos5433_mipi_phy = { | |||
208 | }, { | 207 | }, { |
209 | /* EXYNOS_MIPI_PHY_ID_CSIS2 */ | 208 | /* EXYNOS_MIPI_PHY_ID_CSIS2 */ |
210 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_NONE, | 209 | .coupled_phy_id = EXYNOS_MIPI_PHY_ID_NONE, |
211 | .enable_val = EXYNOS5_PHY_ENABLE, | 210 | .enable_val = EXYNOS4_PHY_ENABLE, |
212 | .enable_reg = EXYNOS5433_MIPI_PHY2_CONTROL, | 211 | .enable_reg = EXYNOS4_MIPI_PHY_CONTROL(2), |
213 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, | 212 | .enable_map = EXYNOS_MIPI_REGMAP_PMU, |
214 | .resetn_val = BIT(0), | 213 | .resetn_val = BIT(0), |
215 | .resetn_reg = EXYNOS5433_SYSREG_CAM1_MIPI_DPHY_CON, | 214 | .resetn_reg = EXYNOS5433_SYSREG_CAM1_MIPI_DPHY_CON, |
diff --git a/drivers/phy/phy-exynos-pcie.c b/drivers/phy/phy-exynos-pcie.c index 60baf25d98e2..a89c12faff39 100644 --- a/drivers/phy/phy-exynos-pcie.c +++ b/drivers/phy/phy-exynos-pcie.c | |||
@@ -14,8 +14,8 @@ | |||
14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/iopoll.h> | 16 | #include <linux/iopoll.h> |
17 | #include <linux/init.h> | ||
17 | #include <linux/mfd/syscon.h> | 18 | #include <linux/mfd/syscon.h> |
18 | #include <linux/module.h> | ||
19 | #include <linux/of.h> | 19 | #include <linux/of.h> |
20 | #include <linux/of_address.h> | 20 | #include <linux/of_address.h> |
21 | #include <linux/of_platform.h> | 21 | #include <linux/of_platform.h> |
@@ -228,7 +228,6 @@ static const struct of_device_id exynos_pcie_phy_match[] = { | |||
228 | }, | 228 | }, |
229 | {}, | 229 | {}, |
230 | }; | 230 | }; |
231 | MODULE_DEVICE_TABLE(of, exynos_pcie_phy_match); | ||
232 | 231 | ||
233 | static int exynos_pcie_phy_probe(struct platform_device *pdev) | 232 | static int exynos_pcie_phy_probe(struct platform_device *pdev) |
234 | { | 233 | { |
@@ -278,8 +277,5 @@ static struct platform_driver exynos_pcie_phy_driver = { | |||
278 | .name = "exynos_pcie_phy", | 277 | .name = "exynos_pcie_phy", |
279 | } | 278 | } |
280 | }; | 279 | }; |
281 | module_platform_driver(exynos_pcie_phy_driver); | ||
282 | 280 | ||
283 | MODULE_DESCRIPTION("Samsung S5P/EXYNOS SoC PCIe PHY driver"); | 281 | builtin_platform_driver(exynos_pcie_phy_driver); |
284 | MODULE_AUTHOR("Jaehoon Chung <jh80.chung@samsung.com>"); | ||
285 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c index 07ed608905ac..7c41daa2c625 100644 --- a/drivers/phy/phy-exynos5-usbdrd.c +++ b/drivers/phy/phy-exynos5-usbdrd.c | |||
@@ -22,9 +22,9 @@ | |||
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
24 | #include <linux/mfd/syscon.h> | 24 | #include <linux/mfd/syscon.h> |
25 | #include <linux/mfd/syscon/exynos5-pmu.h> | ||
26 | #include <linux/regmap.h> | 25 | #include <linux/regmap.h> |
27 | #include <linux/regulator/consumer.h> | 26 | #include <linux/regulator/consumer.h> |
27 | #include <linux/soc/samsung/exynos-regs-pmu.h> | ||
28 | 28 | ||
29 | /* Exynos USB PHY registers */ | 29 | /* Exynos USB PHY registers */ |
30 | #define EXYNOS5_FSEL_9MHZ6 0x0 | 30 | #define EXYNOS5_FSEL_9MHZ6 0x0 |
@@ -235,10 +235,10 @@ static void exynos5_usbdrd_phy_isol(struct phy_usb_instance *inst, | |||
235 | if (!inst->reg_pmu) | 235 | if (!inst->reg_pmu) |
236 | return; | 236 | return; |
237 | 237 | ||
238 | val = on ? 0 : EXYNOS5_PHY_ENABLE; | 238 | val = on ? 0 : EXYNOS4_PHY_ENABLE; |
239 | 239 | ||
240 | regmap_update_bits(inst->reg_pmu, inst->pmu_offset, | 240 | regmap_update_bits(inst->reg_pmu, inst->pmu_offset, |
241 | EXYNOS5_PHY_ENABLE, val); | 241 | EXYNOS4_PHY_ENABLE, val); |
242 | } | 242 | } |
243 | 243 | ||
244 | /* | 244 | /* |
diff --git a/drivers/phy/phy-meson8b-usb2.c b/drivers/phy/phy-meson8b-usb2.c index 33c9f4ba157d..30f56a6a411f 100644 --- a/drivers/phy/phy-meson8b-usb2.c +++ b/drivers/phy/phy-meson8b-usb2.c | |||
@@ -81,9 +81,9 @@ | |||
81 | #define REG_ADP_BC_ACA_PIN_GND BIT(25) | 81 | #define REG_ADP_BC_ACA_PIN_GND BIT(25) |
82 | #define REG_ADP_BC_ACA_PIN_FLOAT BIT(26) | 82 | #define REG_ADP_BC_ACA_PIN_FLOAT BIT(26) |
83 | 83 | ||
84 | #define REG_DBG_UART 0x14 | 84 | #define REG_DBG_UART 0x10 |
85 | 85 | ||
86 | #define REG_TEST 0x18 | 86 | #define REG_TEST 0x14 |
87 | #define REG_TEST_DATA_IN_MASK GENMASK(3, 0) | 87 | #define REG_TEST_DATA_IN_MASK GENMASK(3, 0) |
88 | #define REG_TEST_EN_MASK GENMASK(7, 4) | 88 | #define REG_TEST_EN_MASK GENMASK(7, 4) |
89 | #define REG_TEST_ADDR_MASK GENMASK(11, 8) | 89 | #define REG_TEST_ADDR_MASK GENMASK(11, 8) |
@@ -93,7 +93,7 @@ | |||
93 | #define REG_TEST_DATA_OUT_MASK GENMASK(19, 16) | 93 | #define REG_TEST_DATA_OUT_MASK GENMASK(19, 16) |
94 | #define REG_TEST_DISABLE_ID_PULLUP BIT(20) | 94 | #define REG_TEST_DISABLE_ID_PULLUP BIT(20) |
95 | 95 | ||
96 | #define REG_TUNE 0x1c | 96 | #define REG_TUNE 0x18 |
97 | #define REG_TUNE_TX_RES_TUNE_MASK GENMASK(1, 0) | 97 | #define REG_TUNE_TX_RES_TUNE_MASK GENMASK(1, 0) |
98 | #define REG_TUNE_TX_HSXV_TUNE_MASK GENMASK(3, 2) | 98 | #define REG_TUNE_TX_HSXV_TUNE_MASK GENMASK(3, 2) |
99 | #define REG_TUNE_TX_VREF_TUNE_MASK GENMASK(7, 4) | 99 | #define REG_TUNE_TX_VREF_TUNE_MASK GENMASK(7, 4) |
diff --git a/drivers/phy/phy-mt65xx-usb3.c b/drivers/phy/phy-mt65xx-usb3.c index d9720675b9db..59b110f795c3 100644 --- a/drivers/phy/phy-mt65xx-usb3.c +++ b/drivers/phy/phy-mt65xx-usb3.c | |||
@@ -23,47 +23,55 @@ | |||
23 | #include <linux/phy/phy.h> | 23 | #include <linux/phy/phy.h> |
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | 25 | ||
26 | /* | 26 | /* version V1 sub-banks offset base address */ |
27 | * for sifslv2 register, but exclude port's; | 27 | /* banks shared by multiple phys */ |
28 | * relative to USB3_SIF2_BASE base address | 28 | #define SSUSB_SIFSLV_V1_SPLLC 0x000 /* shared by u3 phys */ |
29 | */ | 29 | #define SSUSB_SIFSLV_V1_U2FREQ 0x100 /* shared by u2 phys */ |
30 | #define SSUSB_SIFSLV_SPLLC 0x0000 | 30 | /* u2 phy bank */ |
31 | #define SSUSB_SIFSLV_U2FREQ 0x0100 | 31 | #define SSUSB_SIFSLV_V1_U2PHY_COM 0x000 |
32 | 32 | /* u3 phy banks */ | |
33 | /* offsets of sub-segment in each port registers */ | 33 | #define SSUSB_SIFSLV_V1_U3PHYD 0x000 |
34 | #define SSUSB_SIFSLV_U2PHY_COM_BASE 0x0000 | 34 | #define SSUSB_SIFSLV_V1_U3PHYA 0x200 |
35 | #define SSUSB_SIFSLV_U3PHYD_BASE 0x0100 | 35 | |
36 | #define SSUSB_USB30_PHYA_SIV_B_BASE 0x0300 | 36 | /* version V2 sub-banks offset base address */ |
37 | #define SSUSB_SIFSLV_U3PHYA_DA_BASE 0x0400 | 37 | /* u2 phy banks */ |
38 | 38 | #define SSUSB_SIFSLV_V2_MISC 0x000 | |
39 | #define U3P_USBPHYACR0 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0000) | 39 | #define SSUSB_SIFSLV_V2_U2FREQ 0x100 |
40 | #define SSUSB_SIFSLV_V2_U2PHY_COM 0x300 | ||
41 | /* u3 phy banks */ | ||
42 | #define SSUSB_SIFSLV_V2_SPLLC 0x000 | ||
43 | #define SSUSB_SIFSLV_V2_CHIP 0x100 | ||
44 | #define SSUSB_SIFSLV_V2_U3PHYD 0x200 | ||
45 | #define SSUSB_SIFSLV_V2_U3PHYA 0x400 | ||
46 | |||
47 | #define U3P_USBPHYACR0 0x000 | ||
40 | #define PA0_RG_U2PLL_FORCE_ON BIT(15) | 48 | #define PA0_RG_U2PLL_FORCE_ON BIT(15) |
49 | #define PA0_RG_USB20_INTR_EN BIT(5) | ||
41 | 50 | ||
42 | #define U3P_USBPHYACR2 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0008) | 51 | #define U3P_USBPHYACR2 0x008 |
43 | #define PA2_RG_SIF_U2PLL_FORCE_EN BIT(18) | 52 | #define PA2_RG_SIF_U2PLL_FORCE_EN BIT(18) |
44 | 53 | ||
45 | #define U3P_USBPHYACR5 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0014) | 54 | #define U3P_USBPHYACR5 0x014 |
46 | #define PA5_RG_U2_HSTX_SRCAL_EN BIT(15) | 55 | #define PA5_RG_U2_HSTX_SRCAL_EN BIT(15) |
47 | #define PA5_RG_U2_HSTX_SRCTRL GENMASK(14, 12) | 56 | #define PA5_RG_U2_HSTX_SRCTRL GENMASK(14, 12) |
48 | #define PA5_RG_U2_HSTX_SRCTRL_VAL(x) ((0x7 & (x)) << 12) | 57 | #define PA5_RG_U2_HSTX_SRCTRL_VAL(x) ((0x7 & (x)) << 12) |
49 | #define PA5_RG_U2_HS_100U_U3_EN BIT(11) | 58 | #define PA5_RG_U2_HS_100U_U3_EN BIT(11) |
50 | 59 | ||
51 | #define U3P_USBPHYACR6 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0018) | 60 | #define U3P_USBPHYACR6 0x018 |
52 | #define PA6_RG_U2_ISO_EN BIT(31) | ||
53 | #define PA6_RG_U2_BC11_SW_EN BIT(23) | 61 | #define PA6_RG_U2_BC11_SW_EN BIT(23) |
54 | #define PA6_RG_U2_OTG_VBUSCMP_EN BIT(20) | 62 | #define PA6_RG_U2_OTG_VBUSCMP_EN BIT(20) |
55 | #define PA6_RG_U2_SQTH GENMASK(3, 0) | 63 | #define PA6_RG_U2_SQTH GENMASK(3, 0) |
56 | #define PA6_RG_U2_SQTH_VAL(x) (0xf & (x)) | 64 | #define PA6_RG_U2_SQTH_VAL(x) (0xf & (x)) |
57 | 65 | ||
58 | #define U3P_U2PHYACR4 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0020) | 66 | #define U3P_U2PHYACR4 0x020 |
59 | #define P2C_RG_USB20_GPIO_CTL BIT(9) | 67 | #define P2C_RG_USB20_GPIO_CTL BIT(9) |
60 | #define P2C_USB20_GPIO_MODE BIT(8) | 68 | #define P2C_USB20_GPIO_MODE BIT(8) |
61 | #define P2C_U2_GPIO_CTR_MSK (P2C_RG_USB20_GPIO_CTL | P2C_USB20_GPIO_MODE) | 69 | #define P2C_U2_GPIO_CTR_MSK (P2C_RG_USB20_GPIO_CTL | P2C_USB20_GPIO_MODE) |
62 | 70 | ||
63 | #define U3D_U2PHYDCR0 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0060) | 71 | #define U3D_U2PHYDCR0 0x060 |
64 | #define P2C_RG_SIF_U2PLL_FORCE_ON BIT(24) | 72 | #define P2C_RG_SIF_U2PLL_FORCE_ON BIT(24) |
65 | 73 | ||
66 | #define U3P_U2PHYDTM0 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0068) | 74 | #define U3P_U2PHYDTM0 0x068 |
67 | #define P2C_FORCE_UART_EN BIT(26) | 75 | #define P2C_FORCE_UART_EN BIT(26) |
68 | #define P2C_FORCE_DATAIN BIT(23) | 76 | #define P2C_FORCE_DATAIN BIT(23) |
69 | #define P2C_FORCE_DM_PULLDOWN BIT(21) | 77 | #define P2C_FORCE_DM_PULLDOWN BIT(21) |
@@ -85,47 +93,56 @@ | |||
85 | P2C_FORCE_TERMSEL | P2C_RG_DMPULLDOWN | \ | 93 | P2C_FORCE_TERMSEL | P2C_RG_DMPULLDOWN | \ |
86 | P2C_RG_DPPULLDOWN | P2C_RG_TERMSEL) | 94 | P2C_RG_DPPULLDOWN | P2C_RG_TERMSEL) |
87 | 95 | ||
88 | #define U3P_U2PHYDTM1 (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x006C) | 96 | #define U3P_U2PHYDTM1 0x06C |
89 | #define P2C_RG_UART_EN BIT(16) | 97 | #define P2C_RG_UART_EN BIT(16) |
90 | #define P2C_RG_VBUSVALID BIT(5) | 98 | #define P2C_RG_VBUSVALID BIT(5) |
91 | #define P2C_RG_SESSEND BIT(4) | 99 | #define P2C_RG_SESSEND BIT(4) |
92 | #define P2C_RG_AVALID BIT(2) | 100 | #define P2C_RG_AVALID BIT(2) |
93 | 101 | ||
94 | #define U3P_U3_PHYA_REG0 (SSUSB_USB30_PHYA_SIV_B_BASE + 0x0000) | 102 | #define U3P_U3_PHYA_REG6 0x018 |
95 | #define P3A_RG_U3_VUSB10_ON BIT(5) | ||
96 | |||
97 | #define U3P_U3_PHYA_REG6 (SSUSB_USB30_PHYA_SIV_B_BASE + 0x0018) | ||
98 | #define P3A_RG_TX_EIDLE_CM GENMASK(31, 28) | 103 | #define P3A_RG_TX_EIDLE_CM GENMASK(31, 28) |
99 | #define P3A_RG_TX_EIDLE_CM_VAL(x) ((0xf & (x)) << 28) | 104 | #define P3A_RG_TX_EIDLE_CM_VAL(x) ((0xf & (x)) << 28) |
100 | 105 | ||
101 | #define U3P_U3_PHYA_REG9 (SSUSB_USB30_PHYA_SIV_B_BASE + 0x0024) | 106 | #define U3P_U3_PHYA_REG9 0x024 |
102 | #define P3A_RG_RX_DAC_MUX GENMASK(5, 1) | 107 | #define P3A_RG_RX_DAC_MUX GENMASK(5, 1) |
103 | #define P3A_RG_RX_DAC_MUX_VAL(x) ((0x1f & (x)) << 1) | 108 | #define P3A_RG_RX_DAC_MUX_VAL(x) ((0x1f & (x)) << 1) |
104 | 109 | ||
105 | #define U3P_U3PHYA_DA_REG0 (SSUSB_SIFSLV_U3PHYA_DA_BASE + 0x0000) | 110 | #define U3P_U3_PHYA_DA_REG0 0x100 |
106 | #define P3A_RG_XTAL_EXT_EN_U3 GENMASK(11, 10) | 111 | #define P3A_RG_XTAL_EXT_EN_U3 GENMASK(11, 10) |
107 | #define P3A_RG_XTAL_EXT_EN_U3_VAL(x) ((0x3 & (x)) << 10) | 112 | #define P3A_RG_XTAL_EXT_EN_U3_VAL(x) ((0x3 & (x)) << 10) |
108 | 113 | ||
109 | #define U3P_PHYD_CDR1 (SSUSB_SIFSLV_U3PHYD_BASE + 0x005c) | 114 | #define U3P_U3_PHYD_LFPS1 0x00c |
115 | #define P3D_RG_FWAKE_TH GENMASK(21, 16) | ||
116 | #define P3D_RG_FWAKE_TH_VAL(x) ((0x3f & (x)) << 16) | ||
117 | |||
118 | #define U3P_U3_PHYD_CDR1 0x05c | ||
110 | #define P3D_RG_CDR_BIR_LTD1 GENMASK(28, 24) | 119 | #define P3D_RG_CDR_BIR_LTD1 GENMASK(28, 24) |
111 | #define P3D_RG_CDR_BIR_LTD1_VAL(x) ((0x1f & (x)) << 24) | 120 | #define P3D_RG_CDR_BIR_LTD1_VAL(x) ((0x1f & (x)) << 24) |
112 | #define P3D_RG_CDR_BIR_LTD0 GENMASK(12, 8) | 121 | #define P3D_RG_CDR_BIR_LTD0 GENMASK(12, 8) |
113 | #define P3D_RG_CDR_BIR_LTD0_VAL(x) ((0x1f & (x)) << 8) | 122 | #define P3D_RG_CDR_BIR_LTD0_VAL(x) ((0x1f & (x)) << 8) |
114 | 123 | ||
115 | #define U3P_XTALCTL3 (SSUSB_SIFSLV_SPLLC + 0x0018) | 124 | #define U3P_U3_PHYD_RXDET1 0x128 |
125 | #define P3D_RG_RXDET_STB2_SET GENMASK(17, 9) | ||
126 | #define P3D_RG_RXDET_STB2_SET_VAL(x) ((0x1ff & (x)) << 9) | ||
127 | |||
128 | #define U3P_U3_PHYD_RXDET2 0x12c | ||
129 | #define P3D_RG_RXDET_STB2_SET_P3 GENMASK(8, 0) | ||
130 | #define P3D_RG_RXDET_STB2_SET_P3_VAL(x) (0x1ff & (x)) | ||
131 | |||
132 | #define U3P_SPLLC_XTALCTL3 0x018 | ||
116 | #define XC3_RG_U3_XTAL_RX_PWD BIT(9) | 133 | #define XC3_RG_U3_XTAL_RX_PWD BIT(9) |
117 | #define XC3_RG_U3_FRC_XTAL_RX_PWD BIT(8) | 134 | #define XC3_RG_U3_FRC_XTAL_RX_PWD BIT(8) |
118 | 135 | ||
119 | #define U3P_U2FREQ_FMCR0 (SSUSB_SIFSLV_U2FREQ + 0x00) | 136 | #define U3P_U2FREQ_FMCR0 0x00 |
120 | #define P2F_RG_MONCLK_SEL GENMASK(27, 26) | 137 | #define P2F_RG_MONCLK_SEL GENMASK(27, 26) |
121 | #define P2F_RG_MONCLK_SEL_VAL(x) ((0x3 & (x)) << 26) | 138 | #define P2F_RG_MONCLK_SEL_VAL(x) ((0x3 & (x)) << 26) |
122 | #define P2F_RG_FREQDET_EN BIT(24) | 139 | #define P2F_RG_FREQDET_EN BIT(24) |
123 | #define P2F_RG_CYCLECNT GENMASK(23, 0) | 140 | #define P2F_RG_CYCLECNT GENMASK(23, 0) |
124 | #define P2F_RG_CYCLECNT_VAL(x) ((P2F_RG_CYCLECNT) & (x)) | 141 | #define P2F_RG_CYCLECNT_VAL(x) ((P2F_RG_CYCLECNT) & (x)) |
125 | 142 | ||
126 | #define U3P_U2FREQ_VALUE (SSUSB_SIFSLV_U2FREQ + 0x0c) | 143 | #define U3P_U2FREQ_VALUE 0x0c |
127 | 144 | ||
128 | #define U3P_U2FREQ_FMMONR1 (SSUSB_SIFSLV_U2FREQ + 0x10) | 145 | #define U3P_U2FREQ_FMMONR1 0x10 |
129 | #define P2F_USB_FM_VALID BIT(0) | 146 | #define P2F_USB_FM_VALID BIT(0) |
130 | #define P2F_RG_FRCK_EN BIT(8) | 147 | #define P2F_RG_FRCK_EN BIT(8) |
131 | 148 | ||
@@ -134,21 +151,46 @@ | |||
134 | #define U3P_SR_COEF_DIVISOR 1000 | 151 | #define U3P_SR_COEF_DIVISOR 1000 |
135 | #define U3P_FM_DET_CYCLE_CNT 1024 | 152 | #define U3P_FM_DET_CYCLE_CNT 1024 |
136 | 153 | ||
154 | enum mt_phy_version { | ||
155 | MT_PHY_V1 = 1, | ||
156 | MT_PHY_V2, | ||
157 | }; | ||
158 | |||
137 | struct mt65xx_phy_pdata { | 159 | struct mt65xx_phy_pdata { |
138 | /* avoid RX sensitivity level degradation only for mt8173 */ | 160 | /* avoid RX sensitivity level degradation only for mt8173 */ |
139 | bool avoid_rx_sen_degradation; | 161 | bool avoid_rx_sen_degradation; |
162 | enum mt_phy_version version; | ||
163 | }; | ||
164 | |||
165 | struct u2phy_banks { | ||
166 | void __iomem *misc; | ||
167 | void __iomem *fmreg; | ||
168 | void __iomem *com; | ||
169 | }; | ||
170 | |||
171 | struct u3phy_banks { | ||
172 | void __iomem *spllc; | ||
173 | void __iomem *chip; | ||
174 | void __iomem *phyd; /* include u3phyd_bank2 */ | ||
175 | void __iomem *phya; /* include u3phya_da */ | ||
140 | }; | 176 | }; |
141 | 177 | ||
142 | struct mt65xx_phy_instance { | 178 | struct mt65xx_phy_instance { |
143 | struct phy *phy; | 179 | struct phy *phy; |
144 | void __iomem *port_base; | 180 | void __iomem *port_base; |
181 | union { | ||
182 | struct u2phy_banks u2_banks; | ||
183 | struct u3phy_banks u3_banks; | ||
184 | }; | ||
185 | struct clk *ref_clk; /* reference clock of anolog phy */ | ||
145 | u32 index; | 186 | u32 index; |
146 | u8 type; | 187 | u8 type; |
147 | }; | 188 | }; |
148 | 189 | ||
149 | struct mt65xx_u3phy { | 190 | struct mt65xx_u3phy { |
150 | struct device *dev; | 191 | struct device *dev; |
151 | void __iomem *sif_base; /* include sif2, but exclude port's */ | 192 | void __iomem *sif_base; /* only shared sif */ |
193 | /* deprecated, use @ref_clk instead in phy instance */ | ||
152 | struct clk *u3phya_ref; /* reference clock of usb3 anolog phy */ | 194 | struct clk *u3phya_ref; /* reference clock of usb3 anolog phy */ |
153 | const struct mt65xx_phy_pdata *pdata; | 195 | const struct mt65xx_phy_pdata *pdata; |
154 | struct mt65xx_phy_instance **phys; | 196 | struct mt65xx_phy_instance **phys; |
@@ -158,49 +200,53 @@ struct mt65xx_u3phy { | |||
158 | static void hs_slew_rate_calibrate(struct mt65xx_u3phy *u3phy, | 200 | static void hs_slew_rate_calibrate(struct mt65xx_u3phy *u3phy, |
159 | struct mt65xx_phy_instance *instance) | 201 | struct mt65xx_phy_instance *instance) |
160 | { | 202 | { |
161 | void __iomem *sif_base = u3phy->sif_base; | 203 | struct u2phy_banks *u2_banks = &instance->u2_banks; |
204 | void __iomem *fmreg = u2_banks->fmreg; | ||
205 | void __iomem *com = u2_banks->com; | ||
162 | int calibration_val; | 206 | int calibration_val; |
163 | int fm_out; | 207 | int fm_out; |
164 | u32 tmp; | 208 | u32 tmp; |
165 | 209 | ||
166 | /* enable USB ring oscillator */ | 210 | /* enable USB ring oscillator */ |
167 | tmp = readl(instance->port_base + U3P_USBPHYACR5); | 211 | tmp = readl(com + U3P_USBPHYACR5); |
168 | tmp |= PA5_RG_U2_HSTX_SRCAL_EN; | 212 | tmp |= PA5_RG_U2_HSTX_SRCAL_EN; |
169 | writel(tmp, instance->port_base + U3P_USBPHYACR5); | 213 | writel(tmp, com + U3P_USBPHYACR5); |
170 | udelay(1); | 214 | udelay(1); |
171 | 215 | ||
172 | /*enable free run clock */ | 216 | /*enable free run clock */ |
173 | tmp = readl(sif_base + U3P_U2FREQ_FMMONR1); | 217 | tmp = readl(fmreg + U3P_U2FREQ_FMMONR1); |
174 | tmp |= P2F_RG_FRCK_EN; | 218 | tmp |= P2F_RG_FRCK_EN; |
175 | writel(tmp, sif_base + U3P_U2FREQ_FMMONR1); | 219 | writel(tmp, fmreg + U3P_U2FREQ_FMMONR1); |
176 | 220 | ||
177 | /* set cycle count as 1024, and select u2 channel */ | 221 | /* set cycle count as 1024, and select u2 channel */ |
178 | tmp = readl(sif_base + U3P_U2FREQ_FMCR0); | 222 | tmp = readl(fmreg + U3P_U2FREQ_FMCR0); |
179 | tmp &= ~(P2F_RG_CYCLECNT | P2F_RG_MONCLK_SEL); | 223 | tmp &= ~(P2F_RG_CYCLECNT | P2F_RG_MONCLK_SEL); |
180 | tmp |= P2F_RG_CYCLECNT_VAL(U3P_FM_DET_CYCLE_CNT); | 224 | tmp |= P2F_RG_CYCLECNT_VAL(U3P_FM_DET_CYCLE_CNT); |
181 | tmp |= P2F_RG_MONCLK_SEL_VAL(instance->index); | 225 | if (u3phy->pdata->version == MT_PHY_V1) |
182 | writel(tmp, sif_base + U3P_U2FREQ_FMCR0); | 226 | tmp |= P2F_RG_MONCLK_SEL_VAL(instance->index >> 1); |
227 | |||
228 | writel(tmp, fmreg + U3P_U2FREQ_FMCR0); | ||
183 | 229 | ||
184 | /* enable frequency meter */ | 230 | /* enable frequency meter */ |
185 | tmp = readl(sif_base + U3P_U2FREQ_FMCR0); | 231 | tmp = readl(fmreg + U3P_U2FREQ_FMCR0); |
186 | tmp |= P2F_RG_FREQDET_EN; | 232 | tmp |= P2F_RG_FREQDET_EN; |
187 | writel(tmp, sif_base + U3P_U2FREQ_FMCR0); | 233 | writel(tmp, fmreg + U3P_U2FREQ_FMCR0); |
188 | 234 | ||
189 | /* ignore return value */ | 235 | /* ignore return value */ |
190 | readl_poll_timeout(sif_base + U3P_U2FREQ_FMMONR1, tmp, | 236 | readl_poll_timeout(fmreg + U3P_U2FREQ_FMMONR1, tmp, |
191 | (tmp & P2F_USB_FM_VALID), 10, 200); | 237 | (tmp & P2F_USB_FM_VALID), 10, 200); |
192 | 238 | ||
193 | fm_out = readl(sif_base + U3P_U2FREQ_VALUE); | 239 | fm_out = readl(fmreg + U3P_U2FREQ_VALUE); |
194 | 240 | ||
195 | /* disable frequency meter */ | 241 | /* disable frequency meter */ |
196 | tmp = readl(sif_base + U3P_U2FREQ_FMCR0); | 242 | tmp = readl(fmreg + U3P_U2FREQ_FMCR0); |
197 | tmp &= ~P2F_RG_FREQDET_EN; | 243 | tmp &= ~P2F_RG_FREQDET_EN; |
198 | writel(tmp, sif_base + U3P_U2FREQ_FMCR0); | 244 | writel(tmp, fmreg + U3P_U2FREQ_FMCR0); |
199 | 245 | ||
200 | /*disable free run clock */ | 246 | /*disable free run clock */ |
201 | tmp = readl(sif_base + U3P_U2FREQ_FMMONR1); | 247 | tmp = readl(fmreg + U3P_U2FREQ_FMMONR1); |
202 | tmp &= ~P2F_RG_FRCK_EN; | 248 | tmp &= ~P2F_RG_FRCK_EN; |
203 | writel(tmp, sif_base + U3P_U2FREQ_FMMONR1); | 249 | writel(tmp, fmreg + U3P_U2FREQ_FMMONR1); |
204 | 250 | ||
205 | if (fm_out) { | 251 | if (fm_out) { |
206 | /* ( 1024 / FM_OUT ) x reference clock frequency x 0.028 */ | 252 | /* ( 1024 / FM_OUT ) x reference clock frequency x 0.028 */ |
@@ -215,85 +261,125 @@ static void hs_slew_rate_calibrate(struct mt65xx_u3phy *u3phy, | |||
215 | instance->index, fm_out, calibration_val); | 261 | instance->index, fm_out, calibration_val); |
216 | 262 | ||
217 | /* set HS slew rate */ | 263 | /* set HS slew rate */ |
218 | tmp = readl(instance->port_base + U3P_USBPHYACR5); | 264 | tmp = readl(com + U3P_USBPHYACR5); |
219 | tmp &= ~PA5_RG_U2_HSTX_SRCTRL; | 265 | tmp &= ~PA5_RG_U2_HSTX_SRCTRL; |
220 | tmp |= PA5_RG_U2_HSTX_SRCTRL_VAL(calibration_val); | 266 | tmp |= PA5_RG_U2_HSTX_SRCTRL_VAL(calibration_val); |
221 | writel(tmp, instance->port_base + U3P_USBPHYACR5); | 267 | writel(tmp, com + U3P_USBPHYACR5); |
222 | 268 | ||
223 | /* disable USB ring oscillator */ | 269 | /* disable USB ring oscillator */ |
224 | tmp = readl(instance->port_base + U3P_USBPHYACR5); | 270 | tmp = readl(com + U3P_USBPHYACR5); |
225 | tmp &= ~PA5_RG_U2_HSTX_SRCAL_EN; | 271 | tmp &= ~PA5_RG_U2_HSTX_SRCAL_EN; |
226 | writel(tmp, instance->port_base + U3P_USBPHYACR5); | 272 | writel(tmp, com + U3P_USBPHYACR5); |
273 | } | ||
274 | |||
275 | static void u3_phy_instance_init(struct mt65xx_u3phy *u3phy, | ||
276 | struct mt65xx_phy_instance *instance) | ||
277 | { | ||
278 | struct u3phy_banks *u3_banks = &instance->u3_banks; | ||
279 | u32 tmp; | ||
280 | |||
281 | /* gating PCIe Analog XTAL clock */ | ||
282 | tmp = readl(u3_banks->spllc + U3P_SPLLC_XTALCTL3); | ||
283 | tmp |= XC3_RG_U3_XTAL_RX_PWD | XC3_RG_U3_FRC_XTAL_RX_PWD; | ||
284 | writel(tmp, u3_banks->spllc + U3P_SPLLC_XTALCTL3); | ||
285 | |||
286 | /* gating XSQ */ | ||
287 | tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG0); | ||
288 | tmp &= ~P3A_RG_XTAL_EXT_EN_U3; | ||
289 | tmp |= P3A_RG_XTAL_EXT_EN_U3_VAL(2); | ||
290 | writel(tmp, u3_banks->phya + U3P_U3_PHYA_DA_REG0); | ||
291 | |||
292 | tmp = readl(u3_banks->phya + U3P_U3_PHYA_REG9); | ||
293 | tmp &= ~P3A_RG_RX_DAC_MUX; | ||
294 | tmp |= P3A_RG_RX_DAC_MUX_VAL(4); | ||
295 | writel(tmp, u3_banks->phya + U3P_U3_PHYA_REG9); | ||
296 | |||
297 | tmp = readl(u3_banks->phya + U3P_U3_PHYA_REG6); | ||
298 | tmp &= ~P3A_RG_TX_EIDLE_CM; | ||
299 | tmp |= P3A_RG_TX_EIDLE_CM_VAL(0xe); | ||
300 | writel(tmp, u3_banks->phya + U3P_U3_PHYA_REG6); | ||
301 | |||
302 | tmp = readl(u3_banks->phyd + U3P_U3_PHYD_CDR1); | ||
303 | tmp &= ~(P3D_RG_CDR_BIR_LTD0 | P3D_RG_CDR_BIR_LTD1); | ||
304 | tmp |= P3D_RG_CDR_BIR_LTD0_VAL(0xc) | P3D_RG_CDR_BIR_LTD1_VAL(0x3); | ||
305 | writel(tmp, u3_banks->phyd + U3P_U3_PHYD_CDR1); | ||
306 | |||
307 | tmp = readl(u3_banks->phyd + U3P_U3_PHYD_LFPS1); | ||
308 | tmp &= ~P3D_RG_FWAKE_TH; | ||
309 | tmp |= P3D_RG_FWAKE_TH_VAL(0x34); | ||
310 | writel(tmp, u3_banks->phyd + U3P_U3_PHYD_LFPS1); | ||
311 | |||
312 | tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RXDET1); | ||
313 | tmp &= ~P3D_RG_RXDET_STB2_SET; | ||
314 | tmp |= P3D_RG_RXDET_STB2_SET_VAL(0x10); | ||
315 | writel(tmp, u3_banks->phyd + U3P_U3_PHYD_RXDET1); | ||
316 | |||
317 | tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RXDET2); | ||
318 | tmp &= ~P3D_RG_RXDET_STB2_SET_P3; | ||
319 | tmp |= P3D_RG_RXDET_STB2_SET_P3_VAL(0x10); | ||
320 | writel(tmp, u3_banks->phyd + U3P_U3_PHYD_RXDET2); | ||
321 | |||
322 | dev_dbg(u3phy->dev, "%s(%d)\n", __func__, instance->index); | ||
227 | } | 323 | } |
228 | 324 | ||
229 | static void phy_instance_init(struct mt65xx_u3phy *u3phy, | 325 | static void phy_instance_init(struct mt65xx_u3phy *u3phy, |
230 | struct mt65xx_phy_instance *instance) | 326 | struct mt65xx_phy_instance *instance) |
231 | { | 327 | { |
232 | void __iomem *port_base = instance->port_base; | 328 | struct u2phy_banks *u2_banks = &instance->u2_banks; |
329 | void __iomem *com = u2_banks->com; | ||
233 | u32 index = instance->index; | 330 | u32 index = instance->index; |
234 | u32 tmp; | 331 | u32 tmp; |
235 | 332 | ||
236 | /* switch to USB function. (system register, force ip into usb mode) */ | 333 | /* switch to USB function. (system register, force ip into usb mode) */ |
237 | tmp = readl(port_base + U3P_U2PHYDTM0); | 334 | tmp = readl(com + U3P_U2PHYDTM0); |
238 | tmp &= ~P2C_FORCE_UART_EN; | 335 | tmp &= ~P2C_FORCE_UART_EN; |
239 | tmp |= P2C_RG_XCVRSEL_VAL(1) | P2C_RG_DATAIN_VAL(0); | 336 | tmp |= P2C_RG_XCVRSEL_VAL(1) | P2C_RG_DATAIN_VAL(0); |
240 | writel(tmp, port_base + U3P_U2PHYDTM0); | 337 | writel(tmp, com + U3P_U2PHYDTM0); |
241 | 338 | ||
242 | tmp = readl(port_base + U3P_U2PHYDTM1); | 339 | tmp = readl(com + U3P_U2PHYDTM1); |
243 | tmp &= ~P2C_RG_UART_EN; | 340 | tmp &= ~P2C_RG_UART_EN; |
244 | writel(tmp, port_base + U3P_U2PHYDTM1); | 341 | writel(tmp, com + U3P_U2PHYDTM1); |
342 | |||
343 | tmp = readl(com + U3P_USBPHYACR0); | ||
344 | tmp |= PA0_RG_USB20_INTR_EN; | ||
345 | writel(tmp, com + U3P_USBPHYACR0); | ||
346 | |||
347 | /* disable switch 100uA current to SSUSB */ | ||
348 | tmp = readl(com + U3P_USBPHYACR5); | ||
349 | tmp &= ~PA5_RG_U2_HS_100U_U3_EN; | ||
350 | writel(tmp, com + U3P_USBPHYACR5); | ||
245 | 351 | ||
246 | if (!index) { | 352 | if (!index) { |
247 | tmp = readl(port_base + U3P_U2PHYACR4); | 353 | tmp = readl(com + U3P_U2PHYACR4); |
248 | tmp &= ~P2C_U2_GPIO_CTR_MSK; | 354 | tmp &= ~P2C_U2_GPIO_CTR_MSK; |
249 | writel(tmp, port_base + U3P_U2PHYACR4); | 355 | writel(tmp, com + U3P_U2PHYACR4); |
250 | } | 356 | } |
251 | 357 | ||
252 | if (u3phy->pdata->avoid_rx_sen_degradation) { | 358 | if (u3phy->pdata->avoid_rx_sen_degradation) { |
253 | if (!index) { | 359 | if (!index) { |
254 | tmp = readl(port_base + U3P_USBPHYACR2); | 360 | tmp = readl(com + U3P_USBPHYACR2); |
255 | tmp |= PA2_RG_SIF_U2PLL_FORCE_EN; | 361 | tmp |= PA2_RG_SIF_U2PLL_FORCE_EN; |
256 | writel(tmp, port_base + U3P_USBPHYACR2); | 362 | writel(tmp, com + U3P_USBPHYACR2); |
257 | 363 | ||
258 | tmp = readl(port_base + U3D_U2PHYDCR0); | 364 | tmp = readl(com + U3D_U2PHYDCR0); |
259 | tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON; | 365 | tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON; |
260 | writel(tmp, port_base + U3D_U2PHYDCR0); | 366 | writel(tmp, com + U3D_U2PHYDCR0); |
261 | } else { | 367 | } else { |
262 | tmp = readl(port_base + U3D_U2PHYDCR0); | 368 | tmp = readl(com + U3D_U2PHYDCR0); |
263 | tmp |= P2C_RG_SIF_U2PLL_FORCE_ON; | 369 | tmp |= P2C_RG_SIF_U2PLL_FORCE_ON; |
264 | writel(tmp, port_base + U3D_U2PHYDCR0); | 370 | writel(tmp, com + U3D_U2PHYDCR0); |
265 | 371 | ||
266 | tmp = readl(port_base + U3P_U2PHYDTM0); | 372 | tmp = readl(com + U3P_U2PHYDTM0); |
267 | tmp |= P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM; | 373 | tmp |= P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM; |
268 | writel(tmp, port_base + U3P_U2PHYDTM0); | 374 | writel(tmp, com + U3P_U2PHYDTM0); |
269 | } | 375 | } |
270 | } | 376 | } |
271 | 377 | ||
272 | tmp = readl(port_base + U3P_USBPHYACR6); | 378 | tmp = readl(com + U3P_USBPHYACR6); |
273 | tmp &= ~PA6_RG_U2_BC11_SW_EN; /* DP/DM BC1.1 path Disable */ | 379 | tmp &= ~PA6_RG_U2_BC11_SW_EN; /* DP/DM BC1.1 path Disable */ |
274 | tmp &= ~PA6_RG_U2_SQTH; | 380 | tmp &= ~PA6_RG_U2_SQTH; |
275 | tmp |= PA6_RG_U2_SQTH_VAL(2); | 381 | tmp |= PA6_RG_U2_SQTH_VAL(2); |
276 | writel(tmp, port_base + U3P_USBPHYACR6); | 382 | writel(tmp, com + U3P_USBPHYACR6); |
277 | |||
278 | tmp = readl(port_base + U3P_U3PHYA_DA_REG0); | ||
279 | tmp &= ~P3A_RG_XTAL_EXT_EN_U3; | ||
280 | tmp |= P3A_RG_XTAL_EXT_EN_U3_VAL(2); | ||
281 | writel(tmp, port_base + U3P_U3PHYA_DA_REG0); | ||
282 | |||
283 | tmp = readl(port_base + U3P_U3_PHYA_REG9); | ||
284 | tmp &= ~P3A_RG_RX_DAC_MUX; | ||
285 | tmp |= P3A_RG_RX_DAC_MUX_VAL(4); | ||
286 | writel(tmp, port_base + U3P_U3_PHYA_REG9); | ||
287 | |||
288 | tmp = readl(port_base + U3P_U3_PHYA_REG6); | ||
289 | tmp &= ~P3A_RG_TX_EIDLE_CM; | ||
290 | tmp |= P3A_RG_TX_EIDLE_CM_VAL(0xe); | ||
291 | writel(tmp, port_base + U3P_U3_PHYA_REG6); | ||
292 | |||
293 | tmp = readl(port_base + U3P_PHYD_CDR1); | ||
294 | tmp &= ~(P3D_RG_CDR_BIR_LTD0 | P3D_RG_CDR_BIR_LTD1); | ||
295 | tmp |= P3D_RG_CDR_BIR_LTD0_VAL(0xc) | P3D_RG_CDR_BIR_LTD1_VAL(0x3); | ||
296 | writel(tmp, port_base + U3P_PHYD_CDR1); | ||
297 | 383 | ||
298 | dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index); | 384 | dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index); |
299 | } | 385 | } |
@@ -301,58 +387,35 @@ static void phy_instance_init(struct mt65xx_u3phy *u3phy, | |||
301 | static void phy_instance_power_on(struct mt65xx_u3phy *u3phy, | 387 | static void phy_instance_power_on(struct mt65xx_u3phy *u3phy, |
302 | struct mt65xx_phy_instance *instance) | 388 | struct mt65xx_phy_instance *instance) |
303 | { | 389 | { |
304 | void __iomem *port_base = instance->port_base; | 390 | struct u2phy_banks *u2_banks = &instance->u2_banks; |
391 | void __iomem *com = u2_banks->com; | ||
305 | u32 index = instance->index; | 392 | u32 index = instance->index; |
306 | u32 tmp; | 393 | u32 tmp; |
307 | 394 | ||
308 | if (!index) { | ||
309 | /* Set RG_SSUSB_VUSB10_ON as 1 after VUSB10 ready */ | ||
310 | tmp = readl(port_base + U3P_U3_PHYA_REG0); | ||
311 | tmp |= P3A_RG_U3_VUSB10_ON; | ||
312 | writel(tmp, port_base + U3P_U3_PHYA_REG0); | ||
313 | } | ||
314 | |||
315 | /* (force_suspendm=0) (let suspendm=1, enable usb 480MHz pll) */ | 395 | /* (force_suspendm=0) (let suspendm=1, enable usb 480MHz pll) */ |
316 | tmp = readl(port_base + U3P_U2PHYDTM0); | 396 | tmp = readl(com + U3P_U2PHYDTM0); |
317 | tmp &= ~(P2C_FORCE_SUSPENDM | P2C_RG_XCVRSEL); | 397 | tmp &= ~(P2C_FORCE_SUSPENDM | P2C_RG_XCVRSEL); |
318 | tmp &= ~(P2C_RG_DATAIN | P2C_DTM0_PART_MASK); | 398 | tmp &= ~(P2C_RG_DATAIN | P2C_DTM0_PART_MASK); |
319 | writel(tmp, port_base + U3P_U2PHYDTM0); | 399 | writel(tmp, com + U3P_U2PHYDTM0); |
320 | 400 | ||
321 | /* OTG Enable */ | 401 | /* OTG Enable */ |
322 | tmp = readl(port_base + U3P_USBPHYACR6); | 402 | tmp = readl(com + U3P_USBPHYACR6); |
323 | tmp |= PA6_RG_U2_OTG_VBUSCMP_EN; | 403 | tmp |= PA6_RG_U2_OTG_VBUSCMP_EN; |
324 | writel(tmp, port_base + U3P_USBPHYACR6); | 404 | writel(tmp, com + U3P_USBPHYACR6); |
325 | 405 | ||
326 | if (!index) { | 406 | tmp = readl(com + U3P_U2PHYDTM1); |
327 | tmp = readl(u3phy->sif_base + U3P_XTALCTL3); | ||
328 | tmp |= XC3_RG_U3_XTAL_RX_PWD | XC3_RG_U3_FRC_XTAL_RX_PWD; | ||
329 | writel(tmp, u3phy->sif_base + U3P_XTALCTL3); | ||
330 | |||
331 | /* switch 100uA current to SSUSB */ | ||
332 | tmp = readl(port_base + U3P_USBPHYACR5); | ||
333 | tmp |= PA5_RG_U2_HS_100U_U3_EN; | ||
334 | writel(tmp, port_base + U3P_USBPHYACR5); | ||
335 | } | ||
336 | |||
337 | tmp = readl(port_base + U3P_U2PHYDTM1); | ||
338 | tmp |= P2C_RG_VBUSVALID | P2C_RG_AVALID; | 407 | tmp |= P2C_RG_VBUSVALID | P2C_RG_AVALID; |
339 | tmp &= ~P2C_RG_SESSEND; | 408 | tmp &= ~P2C_RG_SESSEND; |
340 | writel(tmp, port_base + U3P_U2PHYDTM1); | 409 | writel(tmp, com + U3P_U2PHYDTM1); |
341 | |||
342 | /* USB 2.0 slew rate calibration */ | ||
343 | tmp = readl(port_base + U3P_USBPHYACR5); | ||
344 | tmp &= ~PA5_RG_U2_HSTX_SRCTRL; | ||
345 | tmp |= PA5_RG_U2_HSTX_SRCTRL_VAL(4); | ||
346 | writel(tmp, port_base + U3P_USBPHYACR5); | ||
347 | 410 | ||
348 | if (u3phy->pdata->avoid_rx_sen_degradation && index) { | 411 | if (u3phy->pdata->avoid_rx_sen_degradation && index) { |
349 | tmp = readl(port_base + U3D_U2PHYDCR0); | 412 | tmp = readl(com + U3D_U2PHYDCR0); |
350 | tmp |= P2C_RG_SIF_U2PLL_FORCE_ON; | 413 | tmp |= P2C_RG_SIF_U2PLL_FORCE_ON; |
351 | writel(tmp, port_base + U3D_U2PHYDCR0); | 414 | writel(tmp, com + U3D_U2PHYDCR0); |
352 | 415 | ||
353 | tmp = readl(port_base + U3P_U2PHYDTM0); | 416 | tmp = readl(com + U3P_U2PHYDTM0); |
354 | tmp |= P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM; | 417 | tmp |= P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM; |
355 | writel(tmp, port_base + U3P_U2PHYDTM0); | 418 | writel(tmp, com + U3P_U2PHYDTM0); |
356 | } | 419 | } |
357 | dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index); | 420 | dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index); |
358 | } | 421 | } |
@@ -360,48 +423,36 @@ static void phy_instance_power_on(struct mt65xx_u3phy *u3phy, | |||
360 | static void phy_instance_power_off(struct mt65xx_u3phy *u3phy, | 423 | static void phy_instance_power_off(struct mt65xx_u3phy *u3phy, |
361 | struct mt65xx_phy_instance *instance) | 424 | struct mt65xx_phy_instance *instance) |
362 | { | 425 | { |
363 | void __iomem *port_base = instance->port_base; | 426 | struct u2phy_banks *u2_banks = &instance->u2_banks; |
427 | void __iomem *com = u2_banks->com; | ||
364 | u32 index = instance->index; | 428 | u32 index = instance->index; |
365 | u32 tmp; | 429 | u32 tmp; |
366 | 430 | ||
367 | tmp = readl(port_base + U3P_U2PHYDTM0); | 431 | tmp = readl(com + U3P_U2PHYDTM0); |
368 | tmp &= ~(P2C_RG_XCVRSEL | P2C_RG_DATAIN); | 432 | tmp &= ~(P2C_RG_XCVRSEL | P2C_RG_DATAIN); |
369 | tmp |= P2C_FORCE_SUSPENDM; | 433 | tmp |= P2C_FORCE_SUSPENDM; |
370 | writel(tmp, port_base + U3P_U2PHYDTM0); | 434 | writel(tmp, com + U3P_U2PHYDTM0); |
371 | 435 | ||
372 | /* OTG Disable */ | 436 | /* OTG Disable */ |
373 | tmp = readl(port_base + U3P_USBPHYACR6); | 437 | tmp = readl(com + U3P_USBPHYACR6); |
374 | tmp &= ~PA6_RG_U2_OTG_VBUSCMP_EN; | 438 | tmp &= ~PA6_RG_U2_OTG_VBUSCMP_EN; |
375 | writel(tmp, port_base + U3P_USBPHYACR6); | 439 | writel(tmp, com + U3P_USBPHYACR6); |
376 | |||
377 | if (!index) { | ||
378 | /* switch 100uA current back to USB2.0 */ | ||
379 | tmp = readl(port_base + U3P_USBPHYACR5); | ||
380 | tmp &= ~PA5_RG_U2_HS_100U_U3_EN; | ||
381 | writel(tmp, port_base + U3P_USBPHYACR5); | ||
382 | } | ||
383 | 440 | ||
384 | /* let suspendm=0, set utmi into analog power down */ | 441 | /* let suspendm=0, set utmi into analog power down */ |
385 | tmp = readl(port_base + U3P_U2PHYDTM0); | 442 | tmp = readl(com + U3P_U2PHYDTM0); |
386 | tmp &= ~P2C_RG_SUSPENDM; | 443 | tmp &= ~P2C_RG_SUSPENDM; |
387 | writel(tmp, port_base + U3P_U2PHYDTM0); | 444 | writel(tmp, com + U3P_U2PHYDTM0); |
388 | udelay(1); | 445 | udelay(1); |
389 | 446 | ||
390 | tmp = readl(port_base + U3P_U2PHYDTM1); | 447 | tmp = readl(com + U3P_U2PHYDTM1); |
391 | tmp &= ~(P2C_RG_VBUSVALID | P2C_RG_AVALID); | 448 | tmp &= ~(P2C_RG_VBUSVALID | P2C_RG_AVALID); |
392 | tmp |= P2C_RG_SESSEND; | 449 | tmp |= P2C_RG_SESSEND; |
393 | writel(tmp, port_base + U3P_U2PHYDTM1); | 450 | writel(tmp, com + U3P_U2PHYDTM1); |
394 | |||
395 | if (!index) { | ||
396 | tmp = readl(port_base + U3P_U3_PHYA_REG0); | ||
397 | tmp &= ~P3A_RG_U3_VUSB10_ON; | ||
398 | writel(tmp, port_base + U3P_U3_PHYA_REG0); | ||
399 | } | ||
400 | 451 | ||
401 | if (u3phy->pdata->avoid_rx_sen_degradation && index) { | 452 | if (u3phy->pdata->avoid_rx_sen_degradation && index) { |
402 | tmp = readl(port_base + U3D_U2PHYDCR0); | 453 | tmp = readl(com + U3D_U2PHYDCR0); |
403 | tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON; | 454 | tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON; |
404 | writel(tmp, port_base + U3D_U2PHYDCR0); | 455 | writel(tmp, com + U3D_U2PHYDCR0); |
405 | } | 456 | } |
406 | 457 | ||
407 | dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index); | 458 | dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index); |
@@ -410,18 +461,55 @@ static void phy_instance_power_off(struct mt65xx_u3phy *u3phy, | |||
410 | static void phy_instance_exit(struct mt65xx_u3phy *u3phy, | 461 | static void phy_instance_exit(struct mt65xx_u3phy *u3phy, |
411 | struct mt65xx_phy_instance *instance) | 462 | struct mt65xx_phy_instance *instance) |
412 | { | 463 | { |
413 | void __iomem *port_base = instance->port_base; | 464 | struct u2phy_banks *u2_banks = &instance->u2_banks; |
465 | void __iomem *com = u2_banks->com; | ||
414 | u32 index = instance->index; | 466 | u32 index = instance->index; |
415 | u32 tmp; | 467 | u32 tmp; |
416 | 468 | ||
417 | if (u3phy->pdata->avoid_rx_sen_degradation && index) { | 469 | if (u3phy->pdata->avoid_rx_sen_degradation && index) { |
418 | tmp = readl(port_base + U3D_U2PHYDCR0); | 470 | tmp = readl(com + U3D_U2PHYDCR0); |
419 | tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON; | 471 | tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON; |
420 | writel(tmp, port_base + U3D_U2PHYDCR0); | 472 | writel(tmp, com + U3D_U2PHYDCR0); |
421 | 473 | ||
422 | tmp = readl(port_base + U3P_U2PHYDTM0); | 474 | tmp = readl(com + U3P_U2PHYDTM0); |
423 | tmp &= ~P2C_FORCE_SUSPENDM; | 475 | tmp &= ~P2C_FORCE_SUSPENDM; |
424 | writel(tmp, port_base + U3P_U2PHYDTM0); | 476 | writel(tmp, com + U3P_U2PHYDTM0); |
477 | } | ||
478 | } | ||
479 | |||
480 | static void phy_v1_banks_init(struct mt65xx_u3phy *u3phy, | ||
481 | struct mt65xx_phy_instance *instance) | ||
482 | { | ||
483 | struct u2phy_banks *u2_banks = &instance->u2_banks; | ||
484 | struct u3phy_banks *u3_banks = &instance->u3_banks; | ||
485 | |||
486 | if (instance->type == PHY_TYPE_USB2) { | ||
487 | u2_banks->misc = NULL; | ||
488 | u2_banks->fmreg = u3phy->sif_base + SSUSB_SIFSLV_V1_U2FREQ; | ||
489 | u2_banks->com = instance->port_base + SSUSB_SIFSLV_V1_U2PHY_COM; | ||
490 | } else if (instance->type == PHY_TYPE_USB3) { | ||
491 | u3_banks->spllc = u3phy->sif_base + SSUSB_SIFSLV_V1_SPLLC; | ||
492 | u3_banks->chip = NULL; | ||
493 | u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V1_U3PHYD; | ||
494 | u3_banks->phya = instance->port_base + SSUSB_SIFSLV_V1_U3PHYA; | ||
495 | } | ||
496 | } | ||
497 | |||
498 | static void phy_v2_banks_init(struct mt65xx_u3phy *u3phy, | ||
499 | struct mt65xx_phy_instance *instance) | ||
500 | { | ||
501 | struct u2phy_banks *u2_banks = &instance->u2_banks; | ||
502 | struct u3phy_banks *u3_banks = &instance->u3_banks; | ||
503 | |||
504 | if (instance->type == PHY_TYPE_USB2) { | ||
505 | u2_banks->misc = instance->port_base + SSUSB_SIFSLV_V2_MISC; | ||
506 | u2_banks->fmreg = instance->port_base + SSUSB_SIFSLV_V2_U2FREQ; | ||
507 | u2_banks->com = instance->port_base + SSUSB_SIFSLV_V2_U2PHY_COM; | ||
508 | } else if (instance->type == PHY_TYPE_USB3) { | ||
509 | u3_banks->spllc = instance->port_base + SSUSB_SIFSLV_V2_SPLLC; | ||
510 | u3_banks->chip = instance->port_base + SSUSB_SIFSLV_V2_CHIP; | ||
511 | u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V2_U3PHYD; | ||
512 | u3_banks->phya = instance->port_base + SSUSB_SIFSLV_V2_U3PHYA; | ||
425 | } | 513 | } |
426 | } | 514 | } |
427 | 515 | ||
@@ -437,7 +525,17 @@ static int mt65xx_phy_init(struct phy *phy) | |||
437 | return ret; | 525 | return ret; |
438 | } | 526 | } |
439 | 527 | ||
440 | phy_instance_init(u3phy, instance); | 528 | ret = clk_prepare_enable(instance->ref_clk); |
529 | if (ret) { | ||
530 | dev_err(u3phy->dev, "failed to enable ref_clk\n"); | ||
531 | return ret; | ||
532 | } | ||
533 | |||
534 | if (instance->type == PHY_TYPE_USB2) | ||
535 | phy_instance_init(u3phy, instance); | ||
536 | else | ||
537 | u3_phy_instance_init(u3phy, instance); | ||
538 | |||
441 | return 0; | 539 | return 0; |
442 | } | 540 | } |
443 | 541 | ||
@@ -446,8 +544,10 @@ static int mt65xx_phy_power_on(struct phy *phy) | |||
446 | struct mt65xx_phy_instance *instance = phy_get_drvdata(phy); | 544 | struct mt65xx_phy_instance *instance = phy_get_drvdata(phy); |
447 | struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); | 545 | struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); |
448 | 546 | ||
449 | phy_instance_power_on(u3phy, instance); | 547 | if (instance->type == PHY_TYPE_USB2) { |
450 | hs_slew_rate_calibrate(u3phy, instance); | 548 | phy_instance_power_on(u3phy, instance); |
549 | hs_slew_rate_calibrate(u3phy, instance); | ||
550 | } | ||
451 | return 0; | 551 | return 0; |
452 | } | 552 | } |
453 | 553 | ||
@@ -456,7 +556,9 @@ static int mt65xx_phy_power_off(struct phy *phy) | |||
456 | struct mt65xx_phy_instance *instance = phy_get_drvdata(phy); | 556 | struct mt65xx_phy_instance *instance = phy_get_drvdata(phy); |
457 | struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); | 557 | struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); |
458 | 558 | ||
459 | phy_instance_power_off(u3phy, instance); | 559 | if (instance->type == PHY_TYPE_USB2) |
560 | phy_instance_power_off(u3phy, instance); | ||
561 | |||
460 | return 0; | 562 | return 0; |
461 | } | 563 | } |
462 | 564 | ||
@@ -465,7 +567,10 @@ static int mt65xx_phy_exit(struct phy *phy) | |||
465 | struct mt65xx_phy_instance *instance = phy_get_drvdata(phy); | 567 | struct mt65xx_phy_instance *instance = phy_get_drvdata(phy); |
466 | struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); | 568 | struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent); |
467 | 569 | ||
468 | phy_instance_exit(u3phy, instance); | 570 | if (instance->type == PHY_TYPE_USB2) |
571 | phy_instance_exit(u3phy, instance); | ||
572 | |||
573 | clk_disable_unprepare(instance->ref_clk); | ||
469 | clk_disable_unprepare(u3phy->u3phya_ref); | 574 | clk_disable_unprepare(u3phy->u3phya_ref); |
470 | return 0; | 575 | return 0; |
471 | } | 576 | } |
@@ -478,7 +583,6 @@ static struct phy *mt65xx_phy_xlate(struct device *dev, | |||
478 | struct device_node *phy_np = args->np; | 583 | struct device_node *phy_np = args->np; |
479 | int index; | 584 | int index; |
480 | 585 | ||
481 | |||
482 | if (args->args_count != 1) { | 586 | if (args->args_count != 1) { |
483 | dev_err(dev, "invalid number of cells in 'phy' property\n"); | 587 | dev_err(dev, "invalid number of cells in 'phy' property\n"); |
484 | return ERR_PTR(-EINVAL); | 588 | return ERR_PTR(-EINVAL); |
@@ -496,13 +600,21 @@ static struct phy *mt65xx_phy_xlate(struct device *dev, | |||
496 | } | 600 | } |
497 | 601 | ||
498 | instance->type = args->args[0]; | 602 | instance->type = args->args[0]; |
499 | |||
500 | if (!(instance->type == PHY_TYPE_USB2 || | 603 | if (!(instance->type == PHY_TYPE_USB2 || |
501 | instance->type == PHY_TYPE_USB3)) { | 604 | instance->type == PHY_TYPE_USB3)) { |
502 | dev_err(dev, "unsupported device type: %d\n", instance->type); | 605 | dev_err(dev, "unsupported device type: %d\n", instance->type); |
503 | return ERR_PTR(-EINVAL); | 606 | return ERR_PTR(-EINVAL); |
504 | } | 607 | } |
505 | 608 | ||
609 | if (u3phy->pdata->version == MT_PHY_V1) { | ||
610 | phy_v1_banks_init(u3phy, instance); | ||
611 | } else if (u3phy->pdata->version == MT_PHY_V2) { | ||
612 | phy_v2_banks_init(u3phy, instance); | ||
613 | } else { | ||
614 | dev_err(dev, "phy version is not supported\n"); | ||
615 | return ERR_PTR(-EINVAL); | ||
616 | } | ||
617 | |||
506 | return instance->phy; | 618 | return instance->phy; |
507 | } | 619 | } |
508 | 620 | ||
@@ -516,14 +628,22 @@ static const struct phy_ops mt65xx_u3phy_ops = { | |||
516 | 628 | ||
517 | static const struct mt65xx_phy_pdata mt2701_pdata = { | 629 | static const struct mt65xx_phy_pdata mt2701_pdata = { |
518 | .avoid_rx_sen_degradation = false, | 630 | .avoid_rx_sen_degradation = false, |
631 | .version = MT_PHY_V1, | ||
632 | }; | ||
633 | |||
634 | static const struct mt65xx_phy_pdata mt2712_pdata = { | ||
635 | .avoid_rx_sen_degradation = false, | ||
636 | .version = MT_PHY_V2, | ||
519 | }; | 637 | }; |
520 | 638 | ||
521 | static const struct mt65xx_phy_pdata mt8173_pdata = { | 639 | static const struct mt65xx_phy_pdata mt8173_pdata = { |
522 | .avoid_rx_sen_degradation = true, | 640 | .avoid_rx_sen_degradation = true, |
641 | .version = MT_PHY_V1, | ||
523 | }; | 642 | }; |
524 | 643 | ||
525 | static const struct of_device_id mt65xx_u3phy_id_table[] = { | 644 | static const struct of_device_id mt65xx_u3phy_id_table[] = { |
526 | { .compatible = "mediatek,mt2701-u3phy", .data = &mt2701_pdata }, | 645 | { .compatible = "mediatek,mt2701-u3phy", .data = &mt2701_pdata }, |
646 | { .compatible = "mediatek,mt2712-u3phy", .data = &mt2712_pdata }, | ||
527 | { .compatible = "mediatek,mt8173-u3phy", .data = &mt8173_pdata }, | 647 | { .compatible = "mediatek,mt8173-u3phy", .data = &mt8173_pdata }, |
528 | { }, | 648 | { }, |
529 | }; | 649 | }; |
@@ -559,17 +679,23 @@ static int mt65xx_u3phy_probe(struct platform_device *pdev) | |||
559 | u3phy->dev = dev; | 679 | u3phy->dev = dev; |
560 | platform_set_drvdata(pdev, u3phy); | 680 | platform_set_drvdata(pdev, u3phy); |
561 | 681 | ||
562 | sif_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 682 | if (u3phy->pdata->version == MT_PHY_V1) { |
563 | u3phy->sif_base = devm_ioremap_resource(dev, sif_res); | 683 | /* get banks shared by multiple phys */ |
564 | if (IS_ERR(u3phy->sif_base)) { | 684 | sif_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
565 | dev_err(dev, "failed to remap sif regs\n"); | 685 | u3phy->sif_base = devm_ioremap_resource(dev, sif_res); |
566 | return PTR_ERR(u3phy->sif_base); | 686 | if (IS_ERR(u3phy->sif_base)) { |
687 | dev_err(dev, "failed to remap sif regs\n"); | ||
688 | return PTR_ERR(u3phy->sif_base); | ||
689 | } | ||
567 | } | 690 | } |
568 | 691 | ||
692 | /* it's deprecated, make it optional for backward compatibility */ | ||
569 | u3phy->u3phya_ref = devm_clk_get(dev, "u3phya_ref"); | 693 | u3phy->u3phya_ref = devm_clk_get(dev, "u3phya_ref"); |
570 | if (IS_ERR(u3phy->u3phya_ref)) { | 694 | if (IS_ERR(u3phy->u3phya_ref)) { |
571 | dev_err(dev, "error to get u3phya_ref\n"); | 695 | if (PTR_ERR(u3phy->u3phya_ref) == -EPROBE_DEFER) |
572 | return PTR_ERR(u3phy->u3phya_ref); | 696 | return -EPROBE_DEFER; |
697 | |||
698 | u3phy->u3phya_ref = NULL; | ||
573 | } | 699 | } |
574 | 700 | ||
575 | port = 0; | 701 | port = 0; |
@@ -610,6 +736,17 @@ static int mt65xx_u3phy_probe(struct platform_device *pdev) | |||
610 | instance->index = port; | 736 | instance->index = port; |
611 | phy_set_drvdata(phy, instance); | 737 | phy_set_drvdata(phy, instance); |
612 | port++; | 738 | port++; |
739 | |||
740 | /* if deprecated clock is provided, ignore instance's one */ | ||
741 | if (u3phy->u3phya_ref) | ||
742 | continue; | ||
743 | |||
744 | instance->ref_clk = devm_clk_get(&phy->dev, "ref"); | ||
745 | if (IS_ERR(instance->ref_clk)) { | ||
746 | dev_err(dev, "failed to get ref_clk(id-%d)\n", port); | ||
747 | retval = PTR_ERR(instance->ref_clk); | ||
748 | goto put_child; | ||
749 | } | ||
613 | } | 750 | } |
614 | 751 | ||
615 | provider = devm_of_phy_provider_register(dev, mt65xx_phy_xlate); | 752 | provider = devm_of_phy_provider_register(dev, mt65xx_phy_xlate); |
diff --git a/drivers/phy/phy-qcom-qmp.c b/drivers/phy/phy-qcom-qmp.c new file mode 100644 index 000000000000..727e23be7cac --- /dev/null +++ b/drivers/phy/phy-qcom-qmp.c | |||
@@ -0,0 +1,1153 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2017, The Linux Foundation. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 and | ||
6 | * only version 2 as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/clk.h> | ||
16 | #include <linux/clk-provider.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/err.h> | ||
19 | #include <linux/io.h> | ||
20 | #include <linux/iopoll.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/of.h> | ||
24 | #include <linux/of_device.h> | ||
25 | #include <linux/of_address.h> | ||
26 | #include <linux/phy/phy.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | #include <linux/regulator/consumer.h> | ||
29 | #include <linux/reset.h> | ||
30 | #include <linux/slab.h> | ||
31 | |||
32 | #include <dt-bindings/phy/phy.h> | ||
33 | |||
34 | /* QMP PHY QSERDES COM registers */ | ||
35 | #define QSERDES_COM_BG_TIMER 0x00c | ||
36 | #define QSERDES_COM_SSC_EN_CENTER 0x010 | ||
37 | #define QSERDES_COM_SSC_ADJ_PER1 0x014 | ||
38 | #define QSERDES_COM_SSC_ADJ_PER2 0x018 | ||
39 | #define QSERDES_COM_SSC_PER1 0x01c | ||
40 | #define QSERDES_COM_SSC_PER2 0x020 | ||
41 | #define QSERDES_COM_SSC_STEP_SIZE1 0x024 | ||
42 | #define QSERDES_COM_SSC_STEP_SIZE2 0x028 | ||
43 | #define QSERDES_COM_BIAS_EN_CLKBUFLR_EN 0x034 | ||
44 | #define QSERDES_COM_CLK_ENABLE1 0x038 | ||
45 | #define QSERDES_COM_SYS_CLK_CTRL 0x03c | ||
46 | #define QSERDES_COM_SYSCLK_BUF_ENABLE 0x040 | ||
47 | #define QSERDES_COM_PLL_IVCO 0x048 | ||
48 | #define QSERDES_COM_LOCK_CMP1_MODE0 0x04c | ||
49 | #define QSERDES_COM_LOCK_CMP2_MODE0 0x050 | ||
50 | #define QSERDES_COM_LOCK_CMP3_MODE0 0x054 | ||
51 | #define QSERDES_COM_LOCK_CMP1_MODE1 0x058 | ||
52 | #define QSERDES_COM_LOCK_CMP2_MODE1 0x05c | ||
53 | #define QSERDES_COM_LOCK_CMP3_MODE1 0x060 | ||
54 | #define QSERDES_COM_BG_TRIM 0x070 | ||
55 | #define QSERDES_COM_CLK_EP_DIV 0x074 | ||
56 | #define QSERDES_COM_CP_CTRL_MODE0 0x078 | ||
57 | #define QSERDES_COM_CP_CTRL_MODE1 0x07c | ||
58 | #define QSERDES_COM_PLL_RCTRL_MODE0 0x084 | ||
59 | #define QSERDES_COM_PLL_RCTRL_MODE1 0x088 | ||
60 | #define QSERDES_COM_PLL_CCTRL_MODE0 0x090 | ||
61 | #define QSERDES_COM_PLL_CCTRL_MODE1 0x094 | ||
62 | #define QSERDES_COM_SYSCLK_EN_SEL 0x0ac | ||
63 | #define QSERDES_COM_RESETSM_CNTRL 0x0b4 | ||
64 | #define QSERDES_COM_RESTRIM_CTRL 0x0bc | ||
65 | #define QSERDES_COM_RESCODE_DIV_NUM 0x0c4 | ||
66 | #define QSERDES_COM_LOCK_CMP_EN 0x0c8 | ||
67 | #define QSERDES_COM_LOCK_CMP_CFG 0x0cc | ||
68 | #define QSERDES_COM_DEC_START_MODE0 0x0d0 | ||
69 | #define QSERDES_COM_DEC_START_MODE1 0x0d4 | ||
70 | #define QSERDES_COM_DIV_FRAC_START1_MODE0 0x0dc | ||
71 | #define QSERDES_COM_DIV_FRAC_START2_MODE0 0x0e0 | ||
72 | #define QSERDES_COM_DIV_FRAC_START3_MODE0 0x0e4 | ||
73 | #define QSERDES_COM_DIV_FRAC_START1_MODE1 0x0e8 | ||
74 | #define QSERDES_COM_DIV_FRAC_START2_MODE1 0x0ec | ||
75 | #define QSERDES_COM_DIV_FRAC_START3_MODE1 0x0f0 | ||
76 | #define QSERDES_COM_INTEGLOOP_GAIN0_MODE0 0x108 | ||
77 | #define QSERDES_COM_INTEGLOOP_GAIN1_MODE0 0x10c | ||
78 | #define QSERDES_COM_INTEGLOOP_GAIN0_MODE1 0x110 | ||
79 | #define QSERDES_COM_INTEGLOOP_GAIN1_MODE1 0x114 | ||
80 | #define QSERDES_COM_VCO_TUNE_CTRL 0x124 | ||
81 | #define QSERDES_COM_VCO_TUNE_MAP 0x128 | ||
82 | #define QSERDES_COM_VCO_TUNE1_MODE0 0x12c | ||
83 | #define QSERDES_COM_VCO_TUNE2_MODE0 0x130 | ||
84 | #define QSERDES_COM_VCO_TUNE1_MODE1 0x134 | ||
85 | #define QSERDES_COM_VCO_TUNE2_MODE1 0x138 | ||
86 | #define QSERDES_COM_VCO_TUNE_TIMER1 0x144 | ||
87 | #define QSERDES_COM_VCO_TUNE_TIMER2 0x148 | ||
88 | #define QSERDES_COM_BG_CTRL 0x170 | ||
89 | #define QSERDES_COM_CLK_SELECT 0x174 | ||
90 | #define QSERDES_COM_HSCLK_SEL 0x178 | ||
91 | #define QSERDES_COM_CORECLK_DIV 0x184 | ||
92 | #define QSERDES_COM_CORE_CLK_EN 0x18c | ||
93 | #define QSERDES_COM_C_READY_STATUS 0x190 | ||
94 | #define QSERDES_COM_CMN_CONFIG 0x194 | ||
95 | #define QSERDES_COM_SVS_MODE_CLK_SEL 0x19c | ||
96 | #define QSERDES_COM_DEBUG_BUS0 0x1a0 | ||
97 | #define QSERDES_COM_DEBUG_BUS1 0x1a4 | ||
98 | #define QSERDES_COM_DEBUG_BUS2 0x1a8 | ||
99 | #define QSERDES_COM_DEBUG_BUS3 0x1ac | ||
100 | #define QSERDES_COM_DEBUG_BUS_SEL 0x1b0 | ||
101 | #define QSERDES_COM_CORECLK_DIV_MODE1 0x1bc | ||
102 | |||
103 | /* QMP PHY TX registers */ | ||
104 | #define QSERDES_TX_RES_CODE_LANE_OFFSET 0x054 | ||
105 | #define QSERDES_TX_DEBUG_BUS_SEL 0x064 | ||
106 | #define QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN 0x068 | ||
107 | #define QSERDES_TX_LANE_MODE 0x094 | ||
108 | #define QSERDES_TX_RCV_DETECT_LVL_2 0x0ac | ||
109 | |||
110 | /* QMP PHY RX registers */ | ||
111 | #define QSERDES_RX_UCDR_SO_GAIN_HALF 0x010 | ||
112 | #define QSERDES_RX_UCDR_SO_GAIN 0x01c | ||
113 | #define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN 0x040 | ||
114 | #define QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE 0x048 | ||
115 | #define QSERDES_RX_RX_TERM_BW 0x090 | ||
116 | #define QSERDES_RX_RX_EQ_GAIN1_LSB 0x0c4 | ||
117 | #define QSERDES_RX_RX_EQ_GAIN1_MSB 0x0c8 | ||
118 | #define QSERDES_RX_RX_EQ_GAIN2_LSB 0x0cc | ||
119 | #define QSERDES_RX_RX_EQ_GAIN2_MSB 0x0d0 | ||
120 | #define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2 0x0d8 | ||
121 | #define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3 0x0dc | ||
122 | #define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4 0x0e0 | ||
123 | #define QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x108 | ||
124 | #define QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x10c | ||
125 | #define QSERDES_RX_SIGDET_ENABLES 0x110 | ||
126 | #define QSERDES_RX_SIGDET_CNTRL 0x114 | ||
127 | #define QSERDES_RX_SIGDET_LVL 0x118 | ||
128 | #define QSERDES_RX_SIGDET_DEGLITCH_CNTRL 0x11c | ||
129 | #define QSERDES_RX_RX_BAND 0x120 | ||
130 | #define QSERDES_RX_RX_INTERFACE_MODE 0x12c | ||
131 | |||
132 | /* QMP PHY PCS registers */ | ||
133 | #define QPHY_POWER_DOWN_CONTROL 0x04 | ||
134 | #define QPHY_TXDEEMPH_M6DB_V0 0x24 | ||
135 | #define QPHY_TXDEEMPH_M3P5DB_V0 0x28 | ||
136 | #define QPHY_ENDPOINT_REFCLK_DRIVE 0x54 | ||
137 | #define QPHY_RX_IDLE_DTCT_CNTRL 0x58 | ||
138 | #define QPHY_POWER_STATE_CONFIG1 0x60 | ||
139 | #define QPHY_POWER_STATE_CONFIG2 0x64 | ||
140 | #define QPHY_POWER_STATE_CONFIG4 0x6c | ||
141 | #define QPHY_LOCK_DETECT_CONFIG1 0x80 | ||
142 | #define QPHY_LOCK_DETECT_CONFIG2 0x84 | ||
143 | #define QPHY_LOCK_DETECT_CONFIG3 0x88 | ||
144 | #define QPHY_PWRUP_RESET_DLY_TIME_AUXCLK 0xa0 | ||
145 | #define QPHY_LP_WAKEUP_DLY_TIME_AUXCLK 0xa4 | ||
146 | |||
147 | /* QPHY_SW_RESET bit */ | ||
148 | #define SW_RESET BIT(0) | ||
149 | /* QPHY_POWER_DOWN_CONTROL */ | ||
150 | #define SW_PWRDN BIT(0) | ||
151 | #define REFCLK_DRV_DSBL BIT(1) | ||
152 | /* QPHY_START_CONTROL bits */ | ||
153 | #define SERDES_START BIT(0) | ||
154 | #define PCS_START BIT(1) | ||
155 | #define PLL_READY_GATE_EN BIT(3) | ||
156 | /* QPHY_PCS_STATUS bit */ | ||
157 | #define PHYSTATUS BIT(6) | ||
158 | /* QPHY_COM_PCS_READY_STATUS bit */ | ||
159 | #define PCS_READY BIT(0) | ||
160 | |||
161 | #define PHY_INIT_COMPLETE_TIMEOUT 1000 | ||
162 | #define POWER_DOWN_DELAY_US_MIN 10 | ||
163 | #define POWER_DOWN_DELAY_US_MAX 11 | ||
164 | |||
165 | #define MAX_PROP_NAME 32 | ||
166 | |||
167 | struct qmp_phy_init_tbl { | ||
168 | unsigned int offset; | ||
169 | unsigned int val; | ||
170 | /* | ||
171 | * register part of layout ? | ||
172 | * if yes, then offset gives index in the reg-layout | ||
173 | */ | ||
174 | int in_layout; | ||
175 | }; | ||
176 | |||
177 | #define QMP_PHY_INIT_CFG(o, v) \ | ||
178 | { \ | ||
179 | .offset = o, \ | ||
180 | .val = v, \ | ||
181 | } | ||
182 | |||
183 | #define QMP_PHY_INIT_CFG_L(o, v) \ | ||
184 | { \ | ||
185 | .offset = o, \ | ||
186 | .val = v, \ | ||
187 | .in_layout = 1, \ | ||
188 | } | ||
189 | |||
190 | /* set of registers with offsets different per-PHY */ | ||
191 | enum qphy_reg_layout { | ||
192 | /* Common block control registers */ | ||
193 | QPHY_COM_SW_RESET, | ||
194 | QPHY_COM_POWER_DOWN_CONTROL, | ||
195 | QPHY_COM_START_CONTROL, | ||
196 | QPHY_COM_PCS_READY_STATUS, | ||
197 | /* PCS registers */ | ||
198 | QPHY_PLL_LOCK_CHK_DLY_TIME, | ||
199 | QPHY_FLL_CNTRL1, | ||
200 | QPHY_FLL_CNTRL2, | ||
201 | QPHY_FLL_CNT_VAL_L, | ||
202 | QPHY_FLL_CNT_VAL_H_TOL, | ||
203 | QPHY_FLL_MAN_CODE, | ||
204 | QPHY_SW_RESET, | ||
205 | QPHY_START_CTRL, | ||
206 | QPHY_PCS_READY_STATUS, | ||
207 | }; | ||
208 | |||
209 | static const unsigned int pciephy_regs_layout[] = { | ||
210 | [QPHY_COM_SW_RESET] = 0x400, | ||
211 | [QPHY_COM_POWER_DOWN_CONTROL] = 0x404, | ||
212 | [QPHY_COM_START_CONTROL] = 0x408, | ||
213 | [QPHY_COM_PCS_READY_STATUS] = 0x448, | ||
214 | [QPHY_PLL_LOCK_CHK_DLY_TIME] = 0xa8, | ||
215 | [QPHY_FLL_CNTRL1] = 0xc4, | ||
216 | [QPHY_FLL_CNTRL2] = 0xc8, | ||
217 | [QPHY_FLL_CNT_VAL_L] = 0xcc, | ||
218 | [QPHY_FLL_CNT_VAL_H_TOL] = 0xd0, | ||
219 | [QPHY_FLL_MAN_CODE] = 0xd4, | ||
220 | [QPHY_SW_RESET] = 0x00, | ||
221 | [QPHY_START_CTRL] = 0x08, | ||
222 | [QPHY_PCS_READY_STATUS] = 0x174, | ||
223 | }; | ||
224 | |||
225 | static const unsigned int usb3phy_regs_layout[] = { | ||
226 | [QPHY_FLL_CNTRL1] = 0xc0, | ||
227 | [QPHY_FLL_CNTRL2] = 0xc4, | ||
228 | [QPHY_FLL_CNT_VAL_L] = 0xc8, | ||
229 | [QPHY_FLL_CNT_VAL_H_TOL] = 0xcc, | ||
230 | [QPHY_FLL_MAN_CODE] = 0xd0, | ||
231 | [QPHY_SW_RESET] = 0x00, | ||
232 | [QPHY_START_CTRL] = 0x08, | ||
233 | [QPHY_PCS_READY_STATUS] = 0x17c, | ||
234 | }; | ||
235 | |||
236 | static const struct qmp_phy_init_tbl msm8996_pcie_serdes_tbl[] = { | ||
237 | QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x1c), | ||
238 | QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10), | ||
239 | QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33), | ||
240 | QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), | ||
241 | QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x42), | ||
242 | QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), | ||
243 | QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), | ||
244 | QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x1f), | ||
245 | QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x01), | ||
246 | QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), | ||
247 | QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), | ||
248 | QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), | ||
249 | QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x09), | ||
250 | QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), | ||
251 | QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), | ||
252 | QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), | ||
253 | QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), | ||
254 | QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), | ||
255 | QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x1a), | ||
256 | QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x0a), | ||
257 | QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33), | ||
258 | QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x02), | ||
259 | QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1f), | ||
260 | QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x04), | ||
261 | QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), | ||
262 | QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), | ||
263 | QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), | ||
264 | QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), | ||
265 | QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), | ||
266 | QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), | ||
267 | QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), | ||
268 | QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), | ||
269 | QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x02), | ||
270 | QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), | ||
271 | QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0x2f), | ||
272 | QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x19), | ||
273 | QMP_PHY_INIT_CFG(QSERDES_COM_RESCODE_DIV_NUM, 0x15), | ||
274 | QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), | ||
275 | QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), | ||
276 | QMP_PHY_INIT_CFG(QSERDES_COM_CLK_EP_DIV, 0x19), | ||
277 | QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10), | ||
278 | QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), | ||
279 | QMP_PHY_INIT_CFG(QSERDES_COM_RESCODE_DIV_NUM, 0x40), | ||
280 | }; | ||
281 | |||
282 | static const struct qmp_phy_init_tbl msm8996_pcie_tx_tbl[] = { | ||
283 | QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), | ||
284 | QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), | ||
285 | }; | ||
286 | |||
287 | static const struct qmp_phy_init_tbl msm8996_pcie_rx_tbl[] = { | ||
288 | QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x1c), | ||
289 | QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x01), | ||
290 | QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x00), | ||
291 | QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xdb), | ||
292 | QMP_PHY_INIT_CFG(QSERDES_RX_RX_BAND, 0x18), | ||
293 | QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x04), | ||
294 | QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN_HALF, 0x04), | ||
295 | QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), | ||
296 | QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x14), | ||
297 | QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x19), | ||
298 | }; | ||
299 | |||
300 | static const struct qmp_phy_init_tbl msm8996_pcie_pcs_tbl[] = { | ||
301 | QMP_PHY_INIT_CFG(QPHY_RX_IDLE_DTCT_CNTRL, 0x4c), | ||
302 | QMP_PHY_INIT_CFG(QPHY_PWRUP_RESET_DLY_TIME_AUXCLK, 0x00), | ||
303 | QMP_PHY_INIT_CFG(QPHY_LP_WAKEUP_DLY_TIME_AUXCLK, 0x01), | ||
304 | |||
305 | QMP_PHY_INIT_CFG_L(QPHY_PLL_LOCK_CHK_DLY_TIME, 0x05), | ||
306 | |||
307 | QMP_PHY_INIT_CFG(QPHY_ENDPOINT_REFCLK_DRIVE, 0x05), | ||
308 | QMP_PHY_INIT_CFG(QPHY_POWER_DOWN_CONTROL, 0x02), | ||
309 | QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG4, 0x00), | ||
310 | QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG1, 0xa3), | ||
311 | QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M3P5DB_V0, 0x0e), | ||
312 | }; | ||
313 | |||
314 | static const struct qmp_phy_init_tbl msm8996_usb3_serdes_tbl[] = { | ||
315 | QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14), | ||
316 | QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), | ||
317 | QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), | ||
318 | QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), | ||
319 | QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), | ||
320 | QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), | ||
321 | QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), | ||
322 | QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), | ||
323 | QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x04), | ||
324 | /* PLL and Loop filter settings */ | ||
325 | QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), | ||
326 | QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), | ||
327 | QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), | ||
328 | QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), | ||
329 | QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), | ||
330 | QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), | ||
331 | QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), | ||
332 | QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), | ||
333 | QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x00), | ||
334 | QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x15), | ||
335 | QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x34), | ||
336 | QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), | ||
337 | QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), | ||
338 | QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), | ||
339 | QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), | ||
340 | QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), | ||
341 | /* SSC settings */ | ||
342 | QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), | ||
343 | QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), | ||
344 | QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), | ||
345 | QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00), | ||
346 | QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), | ||
347 | QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0xde), | ||
348 | QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x07), | ||
349 | }; | ||
350 | |||
351 | static const struct qmp_phy_init_tbl msm8996_usb3_tx_tbl[] = { | ||
352 | QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), | ||
353 | QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2, 0x12), | ||
354 | QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), | ||
355 | }; | ||
356 | |||
357 | static const struct qmp_phy_init_tbl msm8996_usb3_rx_tbl[] = { | ||
358 | QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), | ||
359 | QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x04), | ||
360 | QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), | ||
361 | QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4c), | ||
362 | QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xbb), | ||
363 | QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), | ||
364 | QMP_PHY_INIT_CFG(QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), | ||
365 | QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x03), | ||
366 | QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x18), | ||
367 | QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x16), | ||
368 | }; | ||
369 | |||
370 | static const struct qmp_phy_init_tbl msm8996_usb3_pcs_tbl[] = { | ||
371 | /* FLL settings */ | ||
372 | QMP_PHY_INIT_CFG_L(QPHY_FLL_CNTRL2, 0x03), | ||
373 | QMP_PHY_INIT_CFG_L(QPHY_FLL_CNTRL1, 0x02), | ||
374 | QMP_PHY_INIT_CFG_L(QPHY_FLL_CNT_VAL_L, 0x09), | ||
375 | QMP_PHY_INIT_CFG_L(QPHY_FLL_CNT_VAL_H_TOL, 0x42), | ||
376 | QMP_PHY_INIT_CFG_L(QPHY_FLL_MAN_CODE, 0x85), | ||
377 | |||
378 | /* Lock Det settings */ | ||
379 | QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG1, 0xd1), | ||
380 | QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG2, 0x1f), | ||
381 | QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG3, 0x47), | ||
382 | QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG2, 0x08), | ||
383 | }; | ||
384 | |||
385 | /* struct qmp_phy_cfg - per-PHY initialization config */ | ||
386 | struct qmp_phy_cfg { | ||
387 | /* phy-type - PCIE/UFS/USB */ | ||
388 | unsigned int type; | ||
389 | /* number of lanes provided by phy */ | ||
390 | int nlanes; | ||
391 | |||
392 | /* Init sequence for PHY blocks - serdes, tx, rx, pcs */ | ||
393 | const struct qmp_phy_init_tbl *serdes_tbl; | ||
394 | int serdes_tbl_num; | ||
395 | const struct qmp_phy_init_tbl *tx_tbl; | ||
396 | int tx_tbl_num; | ||
397 | const struct qmp_phy_init_tbl *rx_tbl; | ||
398 | int rx_tbl_num; | ||
399 | const struct qmp_phy_init_tbl *pcs_tbl; | ||
400 | int pcs_tbl_num; | ||
401 | |||
402 | /* clock ids to be requested */ | ||
403 | const char * const *clk_list; | ||
404 | int num_clks; | ||
405 | /* resets to be requested */ | ||
406 | const char * const *reset_list; | ||
407 | int num_resets; | ||
408 | /* regulators to be requested */ | ||
409 | const char * const *vreg_list; | ||
410 | int num_vregs; | ||
411 | |||
412 | /* array of registers with different offsets */ | ||
413 | const unsigned int *regs; | ||
414 | |||
415 | unsigned int start_ctrl; | ||
416 | unsigned int pwrdn_ctrl; | ||
417 | unsigned int mask_pcs_ready; | ||
418 | unsigned int mask_com_pcs_ready; | ||
419 | |||
420 | /* true, if PHY has a separate PHY_COM control block */ | ||
421 | bool has_phy_com_ctrl; | ||
422 | /* true, if PHY has a reset for individual lanes */ | ||
423 | bool has_lane_rst; | ||
424 | /* true, if PHY needs delay after POWER_DOWN */ | ||
425 | bool has_pwrdn_delay; | ||
426 | /* power_down delay in usec */ | ||
427 | int pwrdn_delay_min; | ||
428 | int pwrdn_delay_max; | ||
429 | }; | ||
430 | |||
431 | /** | ||
432 | * struct qmp_phy - per-lane phy descriptor | ||
433 | * | ||
434 | * @phy: generic phy | ||
435 | * @tx: iomapped memory space for lane's tx | ||
436 | * @rx: iomapped memory space for lane's rx | ||
437 | * @pcs: iomapped memory space for lane's pcs | ||
438 | * @pipe_clk: pipe lock | ||
439 | * @index: lane index | ||
440 | * @qmp: QMP phy to which this lane belongs | ||
441 | * @lane_rst: lane's reset controller | ||
442 | */ | ||
443 | struct qmp_phy { | ||
444 | struct phy *phy; | ||
445 | void __iomem *tx; | ||
446 | void __iomem *rx; | ||
447 | void __iomem *pcs; | ||
448 | struct clk *pipe_clk; | ||
449 | unsigned int index; | ||
450 | struct qcom_qmp *qmp; | ||
451 | struct reset_control *lane_rst; | ||
452 | }; | ||
453 | |||
454 | /** | ||
455 | * struct qcom_qmp - structure holding QMP phy block attributes | ||
456 | * | ||
457 | * @dev: device | ||
458 | * @serdes: iomapped memory space for phy's serdes | ||
459 | * | ||
460 | * @clks: array of clocks required by phy | ||
461 | * @resets: array of resets required by phy | ||
462 | * @vregs: regulator supplies bulk data | ||
463 | * | ||
464 | * @cfg: phy specific configuration | ||
465 | * @phys: array of per-lane phy descriptors | ||
466 | * @phy_mutex: mutex lock for PHY common block initialization | ||
467 | * @init_count: phy common block initialization count | ||
468 | */ | ||
469 | struct qcom_qmp { | ||
470 | struct device *dev; | ||
471 | void __iomem *serdes; | ||
472 | |||
473 | struct clk **clks; | ||
474 | struct reset_control **resets; | ||
475 | struct regulator_bulk_data *vregs; | ||
476 | |||
477 | const struct qmp_phy_cfg *cfg; | ||
478 | struct qmp_phy **phys; | ||
479 | |||
480 | struct mutex phy_mutex; | ||
481 | int init_count; | ||
482 | }; | ||
483 | |||
484 | static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val) | ||
485 | { | ||
486 | u32 reg; | ||
487 | |||
488 | reg = readl(base + offset); | ||
489 | reg |= val; | ||
490 | writel(reg, base + offset); | ||
491 | |||
492 | /* ensure that above write is through */ | ||
493 | readl(base + offset); | ||
494 | } | ||
495 | |||
496 | static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val) | ||
497 | { | ||
498 | u32 reg; | ||
499 | |||
500 | reg = readl(base + offset); | ||
501 | reg &= ~val; | ||
502 | writel(reg, base + offset); | ||
503 | |||
504 | /* ensure that above write is through */ | ||
505 | readl(base + offset); | ||
506 | } | ||
507 | |||
508 | /* list of clocks required by phy */ | ||
509 | static const char * const msm8996_phy_clk_l[] = { | ||
510 | "aux", "cfg_ahb", "ref", | ||
511 | }; | ||
512 | |||
513 | /* list of resets */ | ||
514 | static const char * const msm8996_pciephy_reset_l[] = { | ||
515 | "phy", "common", "cfg", | ||
516 | }; | ||
517 | |||
518 | static const char * const msm8996_usb3phy_reset_l[] = { | ||
519 | "phy", "common", | ||
520 | }; | ||
521 | |||
522 | /* list of regulators */ | ||
523 | static const char * const msm8996_phy_vreg_l[] = { | ||
524 | "vdda-phy", "vdda-pll", | ||
525 | }; | ||
526 | |||
527 | static const struct qmp_phy_cfg msm8996_pciephy_cfg = { | ||
528 | .type = PHY_TYPE_PCIE, | ||
529 | .nlanes = 3, | ||
530 | |||
531 | .serdes_tbl = msm8996_pcie_serdes_tbl, | ||
532 | .serdes_tbl_num = ARRAY_SIZE(msm8996_pcie_serdes_tbl), | ||
533 | .tx_tbl = msm8996_pcie_tx_tbl, | ||
534 | .tx_tbl_num = ARRAY_SIZE(msm8996_pcie_tx_tbl), | ||
535 | .rx_tbl = msm8996_pcie_rx_tbl, | ||
536 | .rx_tbl_num = ARRAY_SIZE(msm8996_pcie_rx_tbl), | ||
537 | .pcs_tbl = msm8996_pcie_pcs_tbl, | ||
538 | .pcs_tbl_num = ARRAY_SIZE(msm8996_pcie_pcs_tbl), | ||
539 | .clk_list = msm8996_phy_clk_l, | ||
540 | .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), | ||
541 | .reset_list = msm8996_pciephy_reset_l, | ||
542 | .num_resets = ARRAY_SIZE(msm8996_pciephy_reset_l), | ||
543 | .vreg_list = msm8996_phy_vreg_l, | ||
544 | .num_vregs = ARRAY_SIZE(msm8996_phy_vreg_l), | ||
545 | .regs = pciephy_regs_layout, | ||
546 | |||
547 | .start_ctrl = PCS_START | PLL_READY_GATE_EN, | ||
548 | .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, | ||
549 | .mask_com_pcs_ready = PCS_READY, | ||
550 | |||
551 | .has_phy_com_ctrl = true, | ||
552 | .has_lane_rst = true, | ||
553 | .has_pwrdn_delay = true, | ||
554 | .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, | ||
555 | .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, | ||
556 | }; | ||
557 | |||
558 | static const struct qmp_phy_cfg msm8996_usb3phy_cfg = { | ||
559 | .type = PHY_TYPE_USB3, | ||
560 | .nlanes = 1, | ||
561 | |||
562 | .serdes_tbl = msm8996_usb3_serdes_tbl, | ||
563 | .serdes_tbl_num = ARRAY_SIZE(msm8996_usb3_serdes_tbl), | ||
564 | .tx_tbl = msm8996_usb3_tx_tbl, | ||
565 | .tx_tbl_num = ARRAY_SIZE(msm8996_usb3_tx_tbl), | ||
566 | .rx_tbl = msm8996_usb3_rx_tbl, | ||
567 | .rx_tbl_num = ARRAY_SIZE(msm8996_usb3_rx_tbl), | ||
568 | .pcs_tbl = msm8996_usb3_pcs_tbl, | ||
569 | .pcs_tbl_num = ARRAY_SIZE(msm8996_usb3_pcs_tbl), | ||
570 | .clk_list = msm8996_phy_clk_l, | ||
571 | .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), | ||
572 | .reset_list = msm8996_usb3phy_reset_l, | ||
573 | .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), | ||
574 | .vreg_list = msm8996_phy_vreg_l, | ||
575 | .num_vregs = ARRAY_SIZE(msm8996_phy_vreg_l), | ||
576 | .regs = usb3phy_regs_layout, | ||
577 | |||
578 | .start_ctrl = SERDES_START | PCS_START, | ||
579 | .pwrdn_ctrl = SW_PWRDN, | ||
580 | .mask_pcs_ready = PHYSTATUS, | ||
581 | }; | ||
582 | |||
583 | static void qcom_qmp_phy_configure(void __iomem *base, | ||
584 | const unsigned int *regs, | ||
585 | const struct qmp_phy_init_tbl tbl[], | ||
586 | int num) | ||
587 | { | ||
588 | int i; | ||
589 | const struct qmp_phy_init_tbl *t = tbl; | ||
590 | |||
591 | if (!t) | ||
592 | return; | ||
593 | |||
594 | for (i = 0; i < num; i++, t++) { | ||
595 | if (t->in_layout) | ||
596 | writel(t->val, base + regs[t->offset]); | ||
597 | else | ||
598 | writel(t->val, base + t->offset); | ||
599 | } | ||
600 | } | ||
601 | |||
602 | static int qcom_qmp_phy_poweron(struct phy *phy) | ||
603 | { | ||
604 | struct qmp_phy *qphy = phy_get_drvdata(phy); | ||
605 | struct qcom_qmp *qmp = qphy->qmp; | ||
606 | int num = qmp->cfg->num_vregs; | ||
607 | int ret; | ||
608 | |||
609 | dev_vdbg(&phy->dev, "Powering on QMP phy\n"); | ||
610 | |||
611 | /* turn on regulator supplies */ | ||
612 | ret = regulator_bulk_enable(num, qmp->vregs); | ||
613 | if (ret) { | ||
614 | dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret); | ||
615 | return ret; | ||
616 | } | ||
617 | |||
618 | ret = clk_prepare_enable(qphy->pipe_clk); | ||
619 | if (ret) { | ||
620 | dev_err(qmp->dev, "pipe_clk enable failed, err=%d\n", ret); | ||
621 | regulator_bulk_disable(num, qmp->vregs); | ||
622 | return ret; | ||
623 | } | ||
624 | |||
625 | return 0; | ||
626 | } | ||
627 | |||
628 | static int qcom_qmp_phy_poweroff(struct phy *phy) | ||
629 | { | ||
630 | struct qmp_phy *qphy = phy_get_drvdata(phy); | ||
631 | struct qcom_qmp *qmp = qphy->qmp; | ||
632 | |||
633 | clk_disable_unprepare(qphy->pipe_clk); | ||
634 | |||
635 | regulator_bulk_disable(qmp->cfg->num_vregs, qmp->vregs); | ||
636 | |||
637 | return 0; | ||
638 | } | ||
639 | |||
640 | static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp) | ||
641 | { | ||
642 | const struct qmp_phy_cfg *cfg = qmp->cfg; | ||
643 | void __iomem *serdes = qmp->serdes; | ||
644 | int ret, i; | ||
645 | |||
646 | mutex_lock(&qmp->phy_mutex); | ||
647 | if (qmp->init_count++) { | ||
648 | mutex_unlock(&qmp->phy_mutex); | ||
649 | return 0; | ||
650 | } | ||
651 | |||
652 | for (i = 0; i < cfg->num_resets; i++) { | ||
653 | ret = reset_control_deassert(qmp->resets[i]); | ||
654 | if (ret) { | ||
655 | dev_err(qmp->dev, "%s reset deassert failed\n", | ||
656 | qmp->cfg->reset_list[i]); | ||
657 | while (--i >= 0) | ||
658 | reset_control_assert(qmp->resets[i]); | ||
659 | goto err_rst; | ||
660 | } | ||
661 | } | ||
662 | |||
663 | if (cfg->has_phy_com_ctrl) | ||
664 | qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL], | ||
665 | SW_PWRDN); | ||
666 | |||
667 | /* Serdes configuration */ | ||
668 | qcom_qmp_phy_configure(serdes, cfg->regs, cfg->serdes_tbl, | ||
669 | cfg->serdes_tbl_num); | ||
670 | |||
671 | if (cfg->has_phy_com_ctrl) { | ||
672 | void __iomem *status; | ||
673 | unsigned int mask, val; | ||
674 | |||
675 | qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], SW_RESET); | ||
676 | qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL], | ||
677 | SERDES_START | PCS_START); | ||
678 | |||
679 | status = serdes + cfg->regs[QPHY_COM_PCS_READY_STATUS]; | ||
680 | mask = cfg->mask_com_pcs_ready; | ||
681 | |||
682 | ret = readl_poll_timeout(status, val, (val & mask), 10, | ||
683 | PHY_INIT_COMPLETE_TIMEOUT); | ||
684 | if (ret) { | ||
685 | dev_err(qmp->dev, | ||
686 | "phy common block init timed-out\n"); | ||
687 | goto err_com_init; | ||
688 | } | ||
689 | } | ||
690 | |||
691 | mutex_unlock(&qmp->phy_mutex); | ||
692 | |||
693 | return 0; | ||
694 | |||
695 | err_com_init: | ||
696 | while (--i >= 0) | ||
697 | reset_control_assert(qmp->resets[i]); | ||
698 | err_rst: | ||
699 | mutex_unlock(&qmp->phy_mutex); | ||
700 | return ret; | ||
701 | } | ||
702 | |||
703 | static int qcom_qmp_phy_com_exit(struct qcom_qmp *qmp) | ||
704 | { | ||
705 | const struct qmp_phy_cfg *cfg = qmp->cfg; | ||
706 | void __iomem *serdes = qmp->serdes; | ||
707 | int i = cfg->num_resets; | ||
708 | |||
709 | mutex_lock(&qmp->phy_mutex); | ||
710 | if (--qmp->init_count) { | ||
711 | mutex_unlock(&qmp->phy_mutex); | ||
712 | return 0; | ||
713 | } | ||
714 | |||
715 | if (cfg->has_phy_com_ctrl) { | ||
716 | qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL], | ||
717 | SERDES_START | PCS_START); | ||
718 | qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], | ||
719 | SW_RESET); | ||
720 | qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL], | ||
721 | SW_PWRDN); | ||
722 | } | ||
723 | |||
724 | while (--i >= 0) | ||
725 | reset_control_assert(qmp->resets[i]); | ||
726 | |||
727 | mutex_unlock(&qmp->phy_mutex); | ||
728 | |||
729 | return 0; | ||
730 | } | ||
731 | |||
732 | /* PHY Initialization */ | ||
733 | static int qcom_qmp_phy_init(struct phy *phy) | ||
734 | { | ||
735 | struct qmp_phy *qphy = phy_get_drvdata(phy); | ||
736 | struct qcom_qmp *qmp = qphy->qmp; | ||
737 | const struct qmp_phy_cfg *cfg = qmp->cfg; | ||
738 | void __iomem *tx = qphy->tx; | ||
739 | void __iomem *rx = qphy->rx; | ||
740 | void __iomem *pcs = qphy->pcs; | ||
741 | void __iomem *status; | ||
742 | unsigned int mask, val; | ||
743 | int ret, i; | ||
744 | |||
745 | dev_vdbg(qmp->dev, "Initializing QMP phy\n"); | ||
746 | |||
747 | for (i = 0; i < qmp->cfg->num_clks; i++) { | ||
748 | ret = clk_prepare_enable(qmp->clks[i]); | ||
749 | if (ret) { | ||
750 | dev_err(qmp->dev, "failed to enable %s clk, err=%d\n", | ||
751 | qmp->cfg->clk_list[i], ret); | ||
752 | while (--i >= 0) | ||
753 | clk_disable_unprepare(qmp->clks[i]); | ||
754 | } | ||
755 | } | ||
756 | |||
757 | ret = qcom_qmp_phy_com_init(qmp); | ||
758 | if (ret) | ||
759 | goto err_com_init; | ||
760 | |||
761 | if (cfg->has_lane_rst) { | ||
762 | ret = reset_control_deassert(qphy->lane_rst); | ||
763 | if (ret) { | ||
764 | dev_err(qmp->dev, "lane%d reset deassert failed\n", | ||
765 | qphy->index); | ||
766 | goto err_lane_rst; | ||
767 | } | ||
768 | } | ||
769 | |||
770 | /* Tx, Rx, and PCS configurations */ | ||
771 | qcom_qmp_phy_configure(tx, cfg->regs, cfg->tx_tbl, cfg->tx_tbl_num); | ||
772 | qcom_qmp_phy_configure(rx, cfg->regs, cfg->rx_tbl, cfg->rx_tbl_num); | ||
773 | qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); | ||
774 | |||
775 | /* | ||
776 | * Pull out PHY from POWER DOWN state. | ||
777 | * This is active low enable signal to power-down PHY. | ||
778 | */ | ||
779 | qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl); | ||
780 | |||
781 | if (cfg->has_pwrdn_delay) | ||
782 | usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max); | ||
783 | |||
784 | /* start SerDes and Phy-Coding-Sublayer */ | ||
785 | qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); | ||
786 | |||
787 | /* Pull PHY out of reset state */ | ||
788 | qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); | ||
789 | |||
790 | status = pcs + cfg->regs[QPHY_PCS_READY_STATUS]; | ||
791 | mask = cfg->mask_pcs_ready; | ||
792 | |||
793 | ret = readl_poll_timeout(status, val, !(val & mask), 1, | ||
794 | PHY_INIT_COMPLETE_TIMEOUT); | ||
795 | if (ret) { | ||
796 | dev_err(qmp->dev, "phy initialization timed-out\n"); | ||
797 | goto err_pcs_ready; | ||
798 | } | ||
799 | |||
800 | return ret; | ||
801 | |||
802 | err_pcs_ready: | ||
803 | if (cfg->has_lane_rst) | ||
804 | reset_control_assert(qphy->lane_rst); | ||
805 | err_lane_rst: | ||
806 | qcom_qmp_phy_com_exit(qmp); | ||
807 | err_com_init: | ||
808 | while (--i >= 0) | ||
809 | clk_disable_unprepare(qmp->clks[i]); | ||
810 | |||
811 | return ret; | ||
812 | } | ||
813 | |||
814 | static int qcom_qmp_phy_exit(struct phy *phy) | ||
815 | { | ||
816 | struct qmp_phy *qphy = phy_get_drvdata(phy); | ||
817 | struct qcom_qmp *qmp = qphy->qmp; | ||
818 | const struct qmp_phy_cfg *cfg = qmp->cfg; | ||
819 | int i = cfg->num_clks; | ||
820 | |||
821 | /* PHY reset */ | ||
822 | qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); | ||
823 | |||
824 | /* stop SerDes and Phy-Coding-Sublayer */ | ||
825 | qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); | ||
826 | |||
827 | /* Put PHY into POWER DOWN state: active low */ | ||
828 | qphy_clrbits(qphy->pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl); | ||
829 | |||
830 | if (cfg->has_lane_rst) | ||
831 | reset_control_assert(qphy->lane_rst); | ||
832 | |||
833 | qcom_qmp_phy_com_exit(qmp); | ||
834 | |||
835 | while (--i >= 0) | ||
836 | clk_disable_unprepare(qmp->clks[i]); | ||
837 | |||
838 | return 0; | ||
839 | } | ||
840 | |||
841 | static int qcom_qmp_phy_vreg_init(struct device *dev) | ||
842 | { | ||
843 | struct qcom_qmp *qmp = dev_get_drvdata(dev); | ||
844 | int num = qmp->cfg->num_vregs; | ||
845 | int i; | ||
846 | |||
847 | qmp->vregs = devm_kcalloc(dev, num, sizeof(qmp->vregs), GFP_KERNEL); | ||
848 | if (!qmp->vregs) | ||
849 | return -ENOMEM; | ||
850 | |||
851 | for (i = 0; i < num; i++) | ||
852 | qmp->vregs[i].supply = qmp->cfg->vreg_list[i]; | ||
853 | |||
854 | return devm_regulator_bulk_get(dev, num, qmp->vregs); | ||
855 | } | ||
856 | |||
857 | static int qcom_qmp_phy_reset_init(struct device *dev) | ||
858 | { | ||
859 | struct qcom_qmp *qmp = dev_get_drvdata(dev); | ||
860 | int i; | ||
861 | |||
862 | qmp->resets = devm_kcalloc(dev, qmp->cfg->num_resets, | ||
863 | sizeof(*qmp->resets), GFP_KERNEL); | ||
864 | if (!qmp->resets) | ||
865 | return -ENOMEM; | ||
866 | |||
867 | for (i = 0; i < qmp->cfg->num_resets; i++) { | ||
868 | struct reset_control *rst; | ||
869 | const char *name = qmp->cfg->reset_list[i]; | ||
870 | |||
871 | rst = devm_reset_control_get(dev, name); | ||
872 | if (IS_ERR(rst)) { | ||
873 | dev_err(dev, "failed to get %s reset\n", name); | ||
874 | return PTR_ERR(rst); | ||
875 | } | ||
876 | qmp->resets[i] = rst; | ||
877 | } | ||
878 | |||
879 | return 0; | ||
880 | } | ||
881 | |||
882 | static int qcom_qmp_phy_clk_init(struct device *dev) | ||
883 | { | ||
884 | struct qcom_qmp *qmp = dev_get_drvdata(dev); | ||
885 | int ret, i; | ||
886 | |||
887 | qmp->clks = devm_kcalloc(dev, qmp->cfg->num_clks, | ||
888 | sizeof(*qmp->clks), GFP_KERNEL); | ||
889 | if (!qmp->clks) | ||
890 | return -ENOMEM; | ||
891 | |||
892 | for (i = 0; i < qmp->cfg->num_clks; i++) { | ||
893 | struct clk *_clk; | ||
894 | const char *name = qmp->cfg->clk_list[i]; | ||
895 | |||
896 | _clk = devm_clk_get(dev, name); | ||
897 | if (IS_ERR(_clk)) { | ||
898 | ret = PTR_ERR(_clk); | ||
899 | if (ret != -EPROBE_DEFER) | ||
900 | dev_err(dev, "failed to get %s clk, %d\n", | ||
901 | name, ret); | ||
902 | return ret; | ||
903 | } | ||
904 | qmp->clks[i] = _clk; | ||
905 | } | ||
906 | |||
907 | return 0; | ||
908 | } | ||
909 | |||
910 | /* | ||
911 | * Register a fixed rate pipe clock. | ||
912 | * | ||
913 | * The <s>_pipe_clksrc generated by PHY goes to the GCC that gate | ||
914 | * controls it. The <s>_pipe_clk coming out of the GCC is requested | ||
915 | * by the PHY driver for its operations. | ||
916 | * We register the <s>_pipe_clksrc here. The gcc driver takes care | ||
917 | * of assigning this <s>_pipe_clksrc as parent to <s>_pipe_clk. | ||
918 | * Below picture shows this relationship. | ||
919 | * | ||
920 | * +---------------+ | ||
921 | * | PHY block |<<---------------------------------------+ | ||
922 | * | | | | ||
923 | * | +-------+ | +-----+ | | ||
924 | * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+ | ||
925 | * clk | +-------+ | +-----+ | ||
926 | * +---------------+ | ||
927 | */ | ||
928 | static int phy_pipe_clk_register(struct qcom_qmp *qmp, int id) | ||
929 | { | ||
930 | char name[24]; | ||
931 | struct clk_fixed_rate *fixed; | ||
932 | struct clk_init_data init = { }; | ||
933 | |||
934 | switch (qmp->cfg->type) { | ||
935 | case PHY_TYPE_USB3: | ||
936 | snprintf(name, sizeof(name), "usb3_phy_pipe_clk_src"); | ||
937 | break; | ||
938 | case PHY_TYPE_PCIE: | ||
939 | snprintf(name, sizeof(name), "pcie_%d_pipe_clk_src", id); | ||
940 | break; | ||
941 | default: | ||
942 | /* not all phys register pipe clocks, so return success */ | ||
943 | return 0; | ||
944 | } | ||
945 | |||
946 | fixed = devm_kzalloc(qmp->dev, sizeof(*fixed), GFP_KERNEL); | ||
947 | if (!fixed) | ||
948 | return -ENOMEM; | ||
949 | |||
950 | init.name = name; | ||
951 | init.ops = &clk_fixed_rate_ops; | ||
952 | |||
953 | /* controllers using QMP phys use 125MHz pipe clock interface */ | ||
954 | fixed->fixed_rate = 125000000; | ||
955 | fixed->hw.init = &init; | ||
956 | |||
957 | return devm_clk_hw_register(qmp->dev, &fixed->hw); | ||
958 | } | ||
959 | |||
960 | static const struct phy_ops qcom_qmp_phy_gen_ops = { | ||
961 | .init = qcom_qmp_phy_init, | ||
962 | .exit = qcom_qmp_phy_exit, | ||
963 | .power_on = qcom_qmp_phy_poweron, | ||
964 | .power_off = qcom_qmp_phy_poweroff, | ||
965 | .owner = THIS_MODULE, | ||
966 | }; | ||
967 | |||
968 | static | ||
969 | int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id) | ||
970 | { | ||
971 | struct qcom_qmp *qmp = dev_get_drvdata(dev); | ||
972 | struct phy *generic_phy; | ||
973 | struct qmp_phy *qphy; | ||
974 | char prop_name[MAX_PROP_NAME]; | ||
975 | int ret; | ||
976 | |||
977 | qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL); | ||
978 | if (!qphy) | ||
979 | return -ENOMEM; | ||
980 | |||
981 | /* | ||
982 | * Get memory resources for each phy lane: | ||
983 | * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2. | ||
984 | */ | ||
985 | qphy->tx = of_iomap(np, 0); | ||
986 | if (IS_ERR(qphy->tx)) | ||
987 | return PTR_ERR(qphy->tx); | ||
988 | |||
989 | qphy->rx = of_iomap(np, 1); | ||
990 | if (IS_ERR(qphy->rx)) | ||
991 | return PTR_ERR(qphy->rx); | ||
992 | |||
993 | qphy->pcs = of_iomap(np, 2); | ||
994 | if (IS_ERR(qphy->pcs)) | ||
995 | return PTR_ERR(qphy->pcs); | ||
996 | |||
997 | /* | ||
998 | * Get PHY's Pipe clock, if any. USB3 and PCIe are PIPE3 | ||
999 | * based phys, so they essentially have pipe clock. So, | ||
1000 | * we return error in case phy is USB3 or PIPE type. | ||
1001 | * Otherwise, we initialize pipe clock to NULL for | ||
1002 | * all phys that don't need this. | ||
1003 | */ | ||
1004 | snprintf(prop_name, sizeof(prop_name), "pipe%d", id); | ||
1005 | qphy->pipe_clk = of_clk_get_by_name(np, prop_name); | ||
1006 | if (IS_ERR(qphy->pipe_clk)) { | ||
1007 | if (qmp->cfg->type == PHY_TYPE_PCIE || | ||
1008 | qmp->cfg->type == PHY_TYPE_USB3) { | ||
1009 | ret = PTR_ERR(qphy->pipe_clk); | ||
1010 | if (ret != -EPROBE_DEFER) | ||
1011 | dev_err(dev, | ||
1012 | "failed to get lane%d pipe_clk, %d\n", | ||
1013 | id, ret); | ||
1014 | return ret; | ||
1015 | } | ||
1016 | qphy->pipe_clk = NULL; | ||
1017 | } | ||
1018 | |||
1019 | /* Get lane reset, if any */ | ||
1020 | if (qmp->cfg->has_lane_rst) { | ||
1021 | snprintf(prop_name, sizeof(prop_name), "lane%d", id); | ||
1022 | qphy->lane_rst = of_reset_control_get(np, prop_name); | ||
1023 | if (IS_ERR(qphy->lane_rst)) { | ||
1024 | dev_err(dev, "failed to get lane%d reset\n", id); | ||
1025 | return PTR_ERR(qphy->lane_rst); | ||
1026 | } | ||
1027 | } | ||
1028 | |||
1029 | generic_phy = devm_phy_create(dev, np, &qcom_qmp_phy_gen_ops); | ||
1030 | if (IS_ERR(generic_phy)) { | ||
1031 | ret = PTR_ERR(generic_phy); | ||
1032 | dev_err(dev, "failed to create qphy %d\n", ret); | ||
1033 | return ret; | ||
1034 | } | ||
1035 | |||
1036 | qphy->phy = generic_phy; | ||
1037 | qphy->index = id; | ||
1038 | qphy->qmp = qmp; | ||
1039 | qmp->phys[id] = qphy; | ||
1040 | phy_set_drvdata(generic_phy, qphy); | ||
1041 | |||
1042 | return 0; | ||
1043 | } | ||
1044 | |||
1045 | static const struct of_device_id qcom_qmp_phy_of_match_table[] = { | ||
1046 | { | ||
1047 | .compatible = "qcom,msm8996-qmp-pcie-phy", | ||
1048 | .data = &msm8996_pciephy_cfg, | ||
1049 | }, { | ||
1050 | .compatible = "qcom,msm8996-qmp-usb3-phy", | ||
1051 | .data = &msm8996_usb3phy_cfg, | ||
1052 | }, | ||
1053 | { }, | ||
1054 | }; | ||
1055 | MODULE_DEVICE_TABLE(of, qcom_qmp_phy_of_match_table); | ||
1056 | |||
1057 | static int qcom_qmp_phy_probe(struct platform_device *pdev) | ||
1058 | { | ||
1059 | struct qcom_qmp *qmp; | ||
1060 | struct device *dev = &pdev->dev; | ||
1061 | struct resource *res; | ||
1062 | struct device_node *child; | ||
1063 | struct phy_provider *phy_provider; | ||
1064 | void __iomem *base; | ||
1065 | int num, id; | ||
1066 | int ret; | ||
1067 | |||
1068 | qmp = devm_kzalloc(dev, sizeof(*qmp), GFP_KERNEL); | ||
1069 | if (!qmp) | ||
1070 | return -ENOMEM; | ||
1071 | |||
1072 | qmp->dev = dev; | ||
1073 | dev_set_drvdata(dev, qmp); | ||
1074 | |||
1075 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1076 | base = devm_ioremap_resource(dev, res); | ||
1077 | if (IS_ERR(base)) | ||
1078 | return PTR_ERR(base); | ||
1079 | |||
1080 | /* per PHY serdes; usually located at base address */ | ||
1081 | qmp->serdes = base; | ||
1082 | |||
1083 | mutex_init(&qmp->phy_mutex); | ||
1084 | |||
1085 | /* Get the specific init parameters of QMP phy */ | ||
1086 | qmp->cfg = of_device_get_match_data(dev); | ||
1087 | |||
1088 | ret = qcom_qmp_phy_clk_init(dev); | ||
1089 | if (ret) | ||
1090 | return ret; | ||
1091 | |||
1092 | ret = qcom_qmp_phy_reset_init(dev); | ||
1093 | if (ret) | ||
1094 | return ret; | ||
1095 | |||
1096 | ret = qcom_qmp_phy_vreg_init(dev); | ||
1097 | if (ret) { | ||
1098 | dev_err(dev, "failed to get regulator supplies\n"); | ||
1099 | return ret; | ||
1100 | } | ||
1101 | |||
1102 | num = of_get_available_child_count(dev->of_node); | ||
1103 | /* do we have a rogue child node ? */ | ||
1104 | if (num > qmp->cfg->nlanes) | ||
1105 | return -EINVAL; | ||
1106 | |||
1107 | qmp->phys = devm_kcalloc(dev, num, sizeof(*qmp->phys), GFP_KERNEL); | ||
1108 | if (!qmp->phys) | ||
1109 | return -ENOMEM; | ||
1110 | |||
1111 | id = 0; | ||
1112 | for_each_available_child_of_node(dev->of_node, child) { | ||
1113 | /* Create per-lane phy */ | ||
1114 | ret = qcom_qmp_phy_create(dev, child, id); | ||
1115 | if (ret) { | ||
1116 | dev_err(dev, "failed to create lane%d phy, %d\n", | ||
1117 | id, ret); | ||
1118 | return ret; | ||
1119 | } | ||
1120 | |||
1121 | /* | ||
1122 | * Register the pipe clock provided by phy. | ||
1123 | * See function description to see details of this pipe clock. | ||
1124 | */ | ||
1125 | ret = phy_pipe_clk_register(qmp, id); | ||
1126 | if (ret) { | ||
1127 | dev_err(qmp->dev, | ||
1128 | "failed to register pipe clock source\n"); | ||
1129 | return ret; | ||
1130 | } | ||
1131 | id++; | ||
1132 | } | ||
1133 | |||
1134 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | ||
1135 | if (!IS_ERR(phy_provider)) | ||
1136 | dev_info(dev, "Registered Qcom-QMP phy\n"); | ||
1137 | |||
1138 | return PTR_ERR_OR_ZERO(phy_provider); | ||
1139 | } | ||
1140 | |||
1141 | static struct platform_driver qcom_qmp_phy_driver = { | ||
1142 | .probe = qcom_qmp_phy_probe, | ||
1143 | .driver = { | ||
1144 | .name = "qcom-qmp-phy", | ||
1145 | .of_match_table = qcom_qmp_phy_of_match_table, | ||
1146 | }, | ||
1147 | }; | ||
1148 | |||
1149 | module_platform_driver(qcom_qmp_phy_driver); | ||
1150 | |||
1151 | MODULE_AUTHOR("Vivek Gautam <vivek.gautam@codeaurora.org>"); | ||
1152 | MODULE_DESCRIPTION("Qualcomm QMP PHY driver"); | ||
1153 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/phy/phy-qcom-qusb2.c b/drivers/phy/phy-qcom-qusb2.c new file mode 100644 index 000000000000..6c575244c0fb --- /dev/null +++ b/drivers/phy/phy-qcom-qusb2.c | |||
@@ -0,0 +1,493 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2017, The Linux Foundation. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 and | ||
6 | * only version 2 as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | |||
14 | #include <linux/clk.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/mfd/syscon.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/nvmem-consumer.h> | ||
22 | #include <linux/of.h> | ||
23 | #include <linux/of_device.h> | ||
24 | #include <linux/phy/phy.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/regmap.h> | ||
27 | #include <linux/regulator/consumer.h> | ||
28 | #include <linux/reset.h> | ||
29 | #include <linux/slab.h> | ||
30 | |||
31 | #define QUSB2PHY_PLL_TEST 0x04 | ||
32 | #define CLK_REF_SEL BIT(7) | ||
33 | |||
34 | #define QUSB2PHY_PLL_TUNE 0x08 | ||
35 | #define QUSB2PHY_PLL_USER_CTL1 0x0c | ||
36 | #define QUSB2PHY_PLL_USER_CTL2 0x10 | ||
37 | #define QUSB2PHY_PLL_AUTOPGM_CTL1 0x1c | ||
38 | #define QUSB2PHY_PLL_PWR_CTRL 0x18 | ||
39 | |||
40 | #define QUSB2PHY_PLL_STATUS 0x38 | ||
41 | #define PLL_LOCKED BIT(5) | ||
42 | |||
43 | #define QUSB2PHY_PORT_TUNE1 0x80 | ||
44 | #define QUSB2PHY_PORT_TUNE2 0x84 | ||
45 | #define QUSB2PHY_PORT_TUNE3 0x88 | ||
46 | #define QUSB2PHY_PORT_TUNE4 0x8c | ||
47 | #define QUSB2PHY_PORT_TUNE5 0x90 | ||
48 | #define QUSB2PHY_PORT_TEST2 0x9c | ||
49 | |||
50 | #define QUSB2PHY_PORT_POWERDOWN 0xb4 | ||
51 | #define CLAMP_N_EN BIT(5) | ||
52 | #define FREEZIO_N BIT(1) | ||
53 | #define POWER_DOWN BIT(0) | ||
54 | |||
55 | #define QUSB2PHY_REFCLK_ENABLE BIT(0) | ||
56 | |||
57 | #define PHY_CLK_SCHEME_SEL BIT(0) | ||
58 | |||
59 | struct qusb2_phy_init_tbl { | ||
60 | unsigned int offset; | ||
61 | unsigned int val; | ||
62 | }; | ||
63 | |||
64 | #define QUSB2_PHY_INIT_CFG(o, v) \ | ||
65 | { \ | ||
66 | .offset = o, \ | ||
67 | .val = v, \ | ||
68 | } | ||
69 | |||
70 | static const struct qusb2_phy_init_tbl msm8996_init_tbl[] = { | ||
71 | QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE1, 0xf8), | ||
72 | QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE2, 0xb3), | ||
73 | QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE3, 0x83), | ||
74 | QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE4, 0xc0), | ||
75 | QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_TUNE, 0x30), | ||
76 | QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL1, 0x79), | ||
77 | QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL2, 0x21), | ||
78 | QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TEST2, 0x14), | ||
79 | QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_AUTOPGM_CTL1, 0x9f), | ||
80 | QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_PWR_CTRL, 0x00), | ||
81 | }; | ||
82 | |||
83 | struct qusb2_phy_cfg { | ||
84 | const struct qusb2_phy_init_tbl *tbl; | ||
85 | /* number of entries in the table */ | ||
86 | unsigned int tbl_num; | ||
87 | /* offset to PHY_CLK_SCHEME register in TCSR map */ | ||
88 | unsigned int clk_scheme_offset; | ||
89 | }; | ||
90 | |||
91 | static const struct qusb2_phy_cfg msm8996_phy_cfg = { | ||
92 | .tbl = msm8996_init_tbl, | ||
93 | .tbl_num = ARRAY_SIZE(msm8996_init_tbl), | ||
94 | }; | ||
95 | |||
96 | static const char * const qusb2_phy_vreg_names[] = { | ||
97 | "vdda-pll", "vdda-phy-dpdm", | ||
98 | }; | ||
99 | |||
100 | #define QUSB2_NUM_VREGS ARRAY_SIZE(qusb2_phy_vreg_names) | ||
101 | |||
102 | /** | ||
103 | * struct qusb2_phy - structure holding qusb2 phy attributes | ||
104 | * | ||
105 | * @phy: generic phy | ||
106 | * @base: iomapped memory space for qubs2 phy | ||
107 | * | ||
108 | * @cfg_ahb_clk: AHB2PHY interface clock | ||
109 | * @ref_clk: phy reference clock | ||
110 | * @iface_clk: phy interface clock | ||
111 | * @phy_reset: phy reset control | ||
112 | * @vregs: regulator supplies bulk data | ||
113 | * | ||
114 | * @tcsr: TCSR syscon register map | ||
115 | * @cell: nvmem cell containing phy tuning value | ||
116 | * | ||
117 | * @cfg: phy config data | ||
118 | * @has_se_clk_scheme: indicate if PHY has single-ended ref clock scheme | ||
119 | */ | ||
120 | struct qusb2_phy { | ||
121 | struct phy *phy; | ||
122 | void __iomem *base; | ||
123 | |||
124 | struct clk *cfg_ahb_clk; | ||
125 | struct clk *ref_clk; | ||
126 | struct clk *iface_clk; | ||
127 | struct reset_control *phy_reset; | ||
128 | struct regulator_bulk_data vregs[QUSB2_NUM_VREGS]; | ||
129 | |||
130 | struct regmap *tcsr; | ||
131 | struct nvmem_cell *cell; | ||
132 | |||
133 | const struct qusb2_phy_cfg *cfg; | ||
134 | bool has_se_clk_scheme; | ||
135 | }; | ||
136 | |||
137 | static inline void qusb2_setbits(void __iomem *base, u32 offset, u32 val) | ||
138 | { | ||
139 | u32 reg; | ||
140 | |||
141 | reg = readl(base + offset); | ||
142 | reg |= val; | ||
143 | writel(reg, base + offset); | ||
144 | |||
145 | /* Ensure above write is completed */ | ||
146 | readl(base + offset); | ||
147 | } | ||
148 | |||
149 | static inline void qusb2_clrbits(void __iomem *base, u32 offset, u32 val) | ||
150 | { | ||
151 | u32 reg; | ||
152 | |||
153 | reg = readl(base + offset); | ||
154 | reg &= ~val; | ||
155 | writel(reg, base + offset); | ||
156 | |||
157 | /* Ensure above write is completed */ | ||
158 | readl(base + offset); | ||
159 | } | ||
160 | |||
161 | static inline | ||
162 | void qcom_qusb2_phy_configure(void __iomem *base, | ||
163 | const struct qusb2_phy_init_tbl tbl[], int num) | ||
164 | { | ||
165 | int i; | ||
166 | |||
167 | for (i = 0; i < num; i++) | ||
168 | writel(tbl[i].val, base + tbl[i].offset); | ||
169 | } | ||
170 | |||
171 | /* | ||
172 | * Fetches HS Tx tuning value from nvmem and sets the | ||
173 | * QUSB2PHY_PORT_TUNE2 register. | ||
174 | * For error case, skip setting the value and use the default value. | ||
175 | */ | ||
176 | static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy) | ||
177 | { | ||
178 | struct device *dev = &qphy->phy->dev; | ||
179 | u8 *val; | ||
180 | |||
181 | /* | ||
182 | * Read efuse register having TUNE2 parameter's high nibble. | ||
183 | * If efuse register shows value as 0x0, or if we fail to find | ||
184 | * a valid efuse register settings, then use default value | ||
185 | * as 0xB for high nibble that we have already set while | ||
186 | * configuring phy. | ||
187 | */ | ||
188 | val = nvmem_cell_read(qphy->cell, NULL); | ||
189 | if (IS_ERR(val) || !val[0]) { | ||
190 | dev_dbg(dev, "failed to read a valid hs-tx trim value\n"); | ||
191 | return; | ||
192 | } | ||
193 | |||
194 | /* Fused TUNE2 value is the higher nibble only */ | ||
195 | qusb2_setbits(qphy->base, QUSB2PHY_PORT_TUNE2, val[0] << 0x4); | ||
196 | } | ||
197 | |||
198 | static int qusb2_phy_poweron(struct phy *phy) | ||
199 | { | ||
200 | struct qusb2_phy *qphy = phy_get_drvdata(phy); | ||
201 | int num = ARRAY_SIZE(qphy->vregs); | ||
202 | int ret; | ||
203 | |||
204 | dev_vdbg(&phy->dev, "%s(): Powering-on QUSB2 phy\n", __func__); | ||
205 | |||
206 | /* turn on regulator supplies */ | ||
207 | ret = regulator_bulk_enable(num, qphy->vregs); | ||
208 | if (ret) | ||
209 | return ret; | ||
210 | |||
211 | ret = clk_prepare_enable(qphy->iface_clk); | ||
212 | if (ret) { | ||
213 | dev_err(&phy->dev, "failed to enable iface_clk, %d\n", ret); | ||
214 | regulator_bulk_disable(num, qphy->vregs); | ||
215 | return ret; | ||
216 | } | ||
217 | |||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static int qusb2_phy_poweroff(struct phy *phy) | ||
222 | { | ||
223 | struct qusb2_phy *qphy = phy_get_drvdata(phy); | ||
224 | |||
225 | clk_disable_unprepare(qphy->iface_clk); | ||
226 | |||
227 | regulator_bulk_disable(ARRAY_SIZE(qphy->vregs), qphy->vregs); | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | static int qusb2_phy_init(struct phy *phy) | ||
233 | { | ||
234 | struct qusb2_phy *qphy = phy_get_drvdata(phy); | ||
235 | unsigned int val; | ||
236 | unsigned int clk_scheme; | ||
237 | int ret; | ||
238 | |||
239 | dev_vdbg(&phy->dev, "%s(): Initializing QUSB2 phy\n", __func__); | ||
240 | |||
241 | /* enable ahb interface clock to program phy */ | ||
242 | ret = clk_prepare_enable(qphy->cfg_ahb_clk); | ||
243 | if (ret) { | ||
244 | dev_err(&phy->dev, "failed to enable cfg ahb clock, %d\n", ret); | ||
245 | return ret; | ||
246 | } | ||
247 | |||
248 | /* Perform phy reset */ | ||
249 | ret = reset_control_assert(qphy->phy_reset); | ||
250 | if (ret) { | ||
251 | dev_err(&phy->dev, "failed to assert phy_reset, %d\n", ret); | ||
252 | goto disable_ahb_clk; | ||
253 | } | ||
254 | |||
255 | /* 100 us delay to keep PHY in reset mode */ | ||
256 | usleep_range(100, 150); | ||
257 | |||
258 | ret = reset_control_deassert(qphy->phy_reset); | ||
259 | if (ret) { | ||
260 | dev_err(&phy->dev, "failed to de-assert phy_reset, %d\n", ret); | ||
261 | goto disable_ahb_clk; | ||
262 | } | ||
263 | |||
264 | /* Disable the PHY */ | ||
265 | qusb2_setbits(qphy->base, QUSB2PHY_PORT_POWERDOWN, | ||
266 | CLAMP_N_EN | FREEZIO_N | POWER_DOWN); | ||
267 | |||
268 | /* save reset value to override reference clock scheme later */ | ||
269 | val = readl(qphy->base + QUSB2PHY_PLL_TEST); | ||
270 | |||
271 | qcom_qusb2_phy_configure(qphy->base, qphy->cfg->tbl, | ||
272 | qphy->cfg->tbl_num); | ||
273 | |||
274 | /* Set efuse value for tuning the PHY */ | ||
275 | qusb2_phy_set_tune2_param(qphy); | ||
276 | |||
277 | /* Enable the PHY */ | ||
278 | qusb2_clrbits(qphy->base, QUSB2PHY_PORT_POWERDOWN, POWER_DOWN); | ||
279 | |||
280 | /* Required to get phy pll lock successfully */ | ||
281 | usleep_range(150, 160); | ||
282 | |||
283 | /* Default is single-ended clock on msm8996 */ | ||
284 | qphy->has_se_clk_scheme = true; | ||
285 | /* | ||
286 | * read TCSR_PHY_CLK_SCHEME register to check if single-ended | ||
287 | * clock scheme is selected. If yes, then disable differential | ||
288 | * ref_clk and use single-ended clock, otherwise use differential | ||
289 | * ref_clk only. | ||
290 | */ | ||
291 | if (qphy->tcsr) { | ||
292 | ret = regmap_read(qphy->tcsr, qphy->cfg->clk_scheme_offset, | ||
293 | &clk_scheme); | ||
294 | if (ret) { | ||
295 | dev_err(&phy->dev, "failed to read clk scheme reg\n"); | ||
296 | goto assert_phy_reset; | ||
297 | } | ||
298 | |||
299 | /* is it a differential clock scheme ? */ | ||
300 | if (!(clk_scheme & PHY_CLK_SCHEME_SEL)) { | ||
301 | dev_vdbg(&phy->dev, "%s(): select differential clk\n", | ||
302 | __func__); | ||
303 | qphy->has_se_clk_scheme = false; | ||
304 | } else { | ||
305 | dev_vdbg(&phy->dev, "%s(): select single-ended clk\n", | ||
306 | __func__); | ||
307 | } | ||
308 | } | ||
309 | |||
310 | if (!qphy->has_se_clk_scheme) { | ||
311 | val &= ~CLK_REF_SEL; | ||
312 | ret = clk_prepare_enable(qphy->ref_clk); | ||
313 | if (ret) { | ||
314 | dev_err(&phy->dev, "failed to enable ref clk, %d\n", | ||
315 | ret); | ||
316 | goto assert_phy_reset; | ||
317 | } | ||
318 | } else { | ||
319 | val |= CLK_REF_SEL; | ||
320 | } | ||
321 | |||
322 | writel(val, qphy->base + QUSB2PHY_PLL_TEST); | ||
323 | |||
324 | /* ensure above write is through */ | ||
325 | readl(qphy->base + QUSB2PHY_PLL_TEST); | ||
326 | |||
327 | /* Required to get phy pll lock successfully */ | ||
328 | usleep_range(100, 110); | ||
329 | |||
330 | val = readb(qphy->base + QUSB2PHY_PLL_STATUS); | ||
331 | if (!(val & PLL_LOCKED)) { | ||
332 | dev_err(&phy->dev, | ||
333 | "QUSB2PHY pll lock failed: status reg = %x\n", val); | ||
334 | ret = -EBUSY; | ||
335 | goto disable_ref_clk; | ||
336 | } | ||
337 | |||
338 | return 0; | ||
339 | |||
340 | disable_ref_clk: | ||
341 | if (!qphy->has_se_clk_scheme) | ||
342 | clk_disable_unprepare(qphy->ref_clk); | ||
343 | assert_phy_reset: | ||
344 | reset_control_assert(qphy->phy_reset); | ||
345 | disable_ahb_clk: | ||
346 | clk_disable_unprepare(qphy->cfg_ahb_clk); | ||
347 | return ret; | ||
348 | } | ||
349 | |||
350 | static int qusb2_phy_exit(struct phy *phy) | ||
351 | { | ||
352 | struct qusb2_phy *qphy = phy_get_drvdata(phy); | ||
353 | |||
354 | /* Disable the PHY */ | ||
355 | qusb2_setbits(qphy->base, QUSB2PHY_PORT_POWERDOWN, | ||
356 | CLAMP_N_EN | FREEZIO_N | POWER_DOWN); | ||
357 | |||
358 | if (!qphy->has_se_clk_scheme) | ||
359 | clk_disable_unprepare(qphy->ref_clk); | ||
360 | |||
361 | reset_control_assert(qphy->phy_reset); | ||
362 | |||
363 | clk_disable_unprepare(qphy->cfg_ahb_clk); | ||
364 | |||
365 | return 0; | ||
366 | } | ||
367 | |||
368 | static const struct phy_ops qusb2_phy_gen_ops = { | ||
369 | .init = qusb2_phy_init, | ||
370 | .exit = qusb2_phy_exit, | ||
371 | .power_on = qusb2_phy_poweron, | ||
372 | .power_off = qusb2_phy_poweroff, | ||
373 | .owner = THIS_MODULE, | ||
374 | }; | ||
375 | |||
376 | static const struct of_device_id qusb2_phy_of_match_table[] = { | ||
377 | { | ||
378 | .compatible = "qcom,msm8996-qusb2-phy", | ||
379 | .data = &msm8996_phy_cfg, | ||
380 | }, | ||
381 | { }, | ||
382 | }; | ||
383 | MODULE_DEVICE_TABLE(of, qusb2_phy_of_match_table); | ||
384 | |||
385 | static int qusb2_phy_probe(struct platform_device *pdev) | ||
386 | { | ||
387 | struct device *dev = &pdev->dev; | ||
388 | struct qusb2_phy *qphy; | ||
389 | struct phy_provider *phy_provider; | ||
390 | struct phy *generic_phy; | ||
391 | struct resource *res; | ||
392 | int ret, i; | ||
393 | int num; | ||
394 | |||
395 | qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL); | ||
396 | if (!qphy) | ||
397 | return -ENOMEM; | ||
398 | |||
399 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
400 | qphy->base = devm_ioremap_resource(dev, res); | ||
401 | if (IS_ERR(qphy->base)) | ||
402 | return PTR_ERR(qphy->base); | ||
403 | |||
404 | qphy->cfg_ahb_clk = devm_clk_get(dev, "cfg_ahb"); | ||
405 | if (IS_ERR(qphy->cfg_ahb_clk)) { | ||
406 | ret = PTR_ERR(qphy->cfg_ahb_clk); | ||
407 | if (ret != -EPROBE_DEFER) | ||
408 | dev_err(dev, "failed to get cfg ahb clk, %d\n", ret); | ||
409 | return ret; | ||
410 | } | ||
411 | |||
412 | qphy->ref_clk = devm_clk_get(dev, "ref"); | ||
413 | if (IS_ERR(qphy->ref_clk)) { | ||
414 | ret = PTR_ERR(qphy->ref_clk); | ||
415 | if (ret != -EPROBE_DEFER) | ||
416 | dev_err(dev, "failed to get ref clk, %d\n", ret); | ||
417 | return ret; | ||
418 | } | ||
419 | |||
420 | qphy->iface_clk = devm_clk_get(dev, "iface"); | ||
421 | if (IS_ERR(qphy->iface_clk)) { | ||
422 | ret = PTR_ERR(qphy->iface_clk); | ||
423 | if (ret == -EPROBE_DEFER) | ||
424 | return ret; | ||
425 | qphy->iface_clk = NULL; | ||
426 | dev_dbg(dev, "failed to get iface clk, %d\n", ret); | ||
427 | } | ||
428 | |||
429 | qphy->phy_reset = devm_reset_control_get_by_index(&pdev->dev, 0); | ||
430 | if (IS_ERR(qphy->phy_reset)) { | ||
431 | dev_err(dev, "failed to get phy core reset\n"); | ||
432 | return PTR_ERR(qphy->phy_reset); | ||
433 | } | ||
434 | |||
435 | num = ARRAY_SIZE(qphy->vregs); | ||
436 | for (i = 0; i < num; i++) | ||
437 | qphy->vregs[i].supply = qusb2_phy_vreg_names[i]; | ||
438 | |||
439 | ret = devm_regulator_bulk_get(dev, num, qphy->vregs); | ||
440 | if (ret) { | ||
441 | dev_err(dev, "failed to get regulator supplies\n"); | ||
442 | return ret; | ||
443 | } | ||
444 | |||
445 | /* Get the specific init parameters of QMP phy */ | ||
446 | qphy->cfg = of_device_get_match_data(dev); | ||
447 | |||
448 | qphy->tcsr = syscon_regmap_lookup_by_phandle(dev->of_node, | ||
449 | "qcom,tcsr-syscon"); | ||
450 | if (IS_ERR(qphy->tcsr)) { | ||
451 | dev_dbg(dev, "failed to lookup TCSR regmap\n"); | ||
452 | qphy->tcsr = NULL; | ||
453 | } | ||
454 | |||
455 | qphy->cell = devm_nvmem_cell_get(dev, NULL); | ||
456 | if (IS_ERR(qphy->cell)) { | ||
457 | if (PTR_ERR(qphy->cell) == -EPROBE_DEFER) | ||
458 | return -EPROBE_DEFER; | ||
459 | qphy->cell = NULL; | ||
460 | dev_dbg(dev, "failed to lookup tune2 hstx trim value\n"); | ||
461 | } | ||
462 | |||
463 | generic_phy = devm_phy_create(dev, NULL, &qusb2_phy_gen_ops); | ||
464 | if (IS_ERR(generic_phy)) { | ||
465 | ret = PTR_ERR(generic_phy); | ||
466 | dev_err(dev, "failed to create phy, %d\n", ret); | ||
467 | return ret; | ||
468 | } | ||
469 | qphy->phy = generic_phy; | ||
470 | |||
471 | dev_set_drvdata(dev, qphy); | ||
472 | phy_set_drvdata(generic_phy, qphy); | ||
473 | |||
474 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | ||
475 | if (!IS_ERR(phy_provider)) | ||
476 | dev_info(dev, "Registered Qcom-QUSB2 phy\n"); | ||
477 | |||
478 | return PTR_ERR_OR_ZERO(phy_provider); | ||
479 | } | ||
480 | |||
481 | static struct platform_driver qusb2_phy_driver = { | ||
482 | .probe = qusb2_phy_probe, | ||
483 | .driver = { | ||
484 | .name = "qcom-qusb2-phy", | ||
485 | .of_match_table = qusb2_phy_of_match_table, | ||
486 | }, | ||
487 | }; | ||
488 | |||
489 | module_platform_driver(qusb2_phy_driver); | ||
490 | |||
491 | MODULE_AUTHOR("Vivek Gautam <vivek.gautam@codeaurora.org>"); | ||
492 | MODULE_DESCRIPTION("Qualcomm QUSB2 PHY driver"); | ||
493 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/phy/phy-rcar-gen3-usb2.c b/drivers/phy/phy-rcar-gen3-usb2.c index afb4d048d3e9..54c34298a000 100644 --- a/drivers/phy/phy-rcar-gen3-usb2.c +++ b/drivers/phy/phy-rcar-gen3-usb2.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/of_address.h> | 20 | #include <linux/of_address.h> |
21 | #include <linux/phy/phy.h> | 21 | #include <linux/phy/phy.h> |
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/pm_runtime.h> | ||
23 | #include <linux/regulator/consumer.h> | 24 | #include <linux/regulator/consumer.h> |
24 | #include <linux/workqueue.h> | 25 | #include <linux/workqueue.h> |
25 | 26 | ||
@@ -395,7 +396,7 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) | |||
395 | struct rcar_gen3_chan *channel; | 396 | struct rcar_gen3_chan *channel; |
396 | struct phy_provider *provider; | 397 | struct phy_provider *provider; |
397 | struct resource *res; | 398 | struct resource *res; |
398 | int irq; | 399 | int irq, ret = 0; |
399 | 400 | ||
400 | if (!dev->of_node) { | 401 | if (!dev->of_node) { |
401 | dev_err(dev, "This driver needs device tree\n"); | 402 | dev_err(dev, "This driver needs device tree\n"); |
@@ -434,17 +435,24 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) | |||
434 | } | 435 | } |
435 | } | 436 | } |
436 | 437 | ||
437 | /* devm_phy_create() will call pm_runtime_enable(dev); */ | 438 | /* |
439 | * devm_phy_create() will call pm_runtime_enable(&phy->dev); | ||
440 | * And then, phy-core will manage runtime pm for this device. | ||
441 | */ | ||
442 | pm_runtime_enable(dev); | ||
438 | channel->phy = devm_phy_create(dev, NULL, &rcar_gen3_phy_usb2_ops); | 443 | channel->phy = devm_phy_create(dev, NULL, &rcar_gen3_phy_usb2_ops); |
439 | if (IS_ERR(channel->phy)) { | 444 | if (IS_ERR(channel->phy)) { |
440 | dev_err(dev, "Failed to create USB2 PHY\n"); | 445 | dev_err(dev, "Failed to create USB2 PHY\n"); |
441 | return PTR_ERR(channel->phy); | 446 | ret = PTR_ERR(channel->phy); |
447 | goto error; | ||
442 | } | 448 | } |
443 | 449 | ||
444 | channel->vbus = devm_regulator_get_optional(dev, "vbus"); | 450 | channel->vbus = devm_regulator_get_optional(dev, "vbus"); |
445 | if (IS_ERR(channel->vbus)) { | 451 | if (IS_ERR(channel->vbus)) { |
446 | if (PTR_ERR(channel->vbus) == -EPROBE_DEFER) | 452 | if (PTR_ERR(channel->vbus) == -EPROBE_DEFER) { |
447 | return PTR_ERR(channel->vbus); | 453 | ret = PTR_ERR(channel->vbus); |
454 | goto error; | ||
455 | } | ||
448 | channel->vbus = NULL; | 456 | channel->vbus = NULL; |
449 | } | 457 | } |
450 | 458 | ||
@@ -454,15 +462,22 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) | |||
454 | provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | 462 | provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); |
455 | if (IS_ERR(provider)) { | 463 | if (IS_ERR(provider)) { |
456 | dev_err(dev, "Failed to register PHY provider\n"); | 464 | dev_err(dev, "Failed to register PHY provider\n"); |
465 | ret = PTR_ERR(provider); | ||
466 | goto error; | ||
457 | } else if (channel->has_otg) { | 467 | } else if (channel->has_otg) { |
458 | int ret; | 468 | int ret; |
459 | 469 | ||
460 | ret = device_create_file(dev, &dev_attr_role); | 470 | ret = device_create_file(dev, &dev_attr_role); |
461 | if (ret < 0) | 471 | if (ret < 0) |
462 | return ret; | 472 | goto error; |
463 | } | 473 | } |
464 | 474 | ||
465 | return PTR_ERR_OR_ZERO(provider); | 475 | return 0; |
476 | |||
477 | error: | ||
478 | pm_runtime_disable(dev); | ||
479 | |||
480 | return ret; | ||
466 | } | 481 | } |
467 | 482 | ||
468 | static int rcar_gen3_phy_usb2_remove(struct platform_device *pdev) | 483 | static int rcar_gen3_phy_usb2_remove(struct platform_device *pdev) |
@@ -472,6 +487,8 @@ static int rcar_gen3_phy_usb2_remove(struct platform_device *pdev) | |||
472 | if (channel->has_otg) | 487 | if (channel->has_otg) |
473 | device_remove_file(&pdev->dev, &dev_attr_role); | 488 | device_remove_file(&pdev->dev, &dev_attr_role); |
474 | 489 | ||
490 | pm_runtime_disable(&pdev->dev); | ||
491 | |||
475 | return 0; | 492 | return 0; |
476 | }; | 493 | }; |
477 | 494 | ||
diff --git a/drivers/phy/phy-rockchip-inno-usb2.c b/drivers/phy/phy-rockchip-inno-usb2.c index 4ea95c28a66f..8efe78a49916 100644 --- a/drivers/phy/phy-rockchip-inno-usb2.c +++ b/drivers/phy/phy-rockchip-inno-usb2.c | |||
@@ -554,8 +554,7 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work) | |||
554 | case USB_CHG_STATE_DETECTED: | 554 | case USB_CHG_STATE_DETECTED: |
555 | switch (rphy->chg_type) { | 555 | switch (rphy->chg_type) { |
556 | case POWER_SUPPLY_TYPE_USB: | 556 | case POWER_SUPPLY_TYPE_USB: |
557 | dev_dbg(&rport->phy->dev, | 557 | dev_dbg(&rport->phy->dev, "sdp cable is connected\n"); |
558 | "sdp cable is connecetd\n"); | ||
559 | rockchip_usb2phy_power_on(rport->phy); | 558 | rockchip_usb2phy_power_on(rport->phy); |
560 | rport->state = OTG_STATE_B_PERIPHERAL; | 559 | rport->state = OTG_STATE_B_PERIPHERAL; |
561 | notify_charger = true; | 560 | notify_charger = true; |
@@ -563,16 +562,14 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work) | |||
563 | cable = EXTCON_CHG_USB_SDP; | 562 | cable = EXTCON_CHG_USB_SDP; |
564 | break; | 563 | break; |
565 | case POWER_SUPPLY_TYPE_USB_DCP: | 564 | case POWER_SUPPLY_TYPE_USB_DCP: |
566 | dev_dbg(&rport->phy->dev, | 565 | dev_dbg(&rport->phy->dev, "dcp cable is connected\n"); |
567 | "dcp cable is connecetd\n"); | ||
568 | rockchip_usb2phy_power_off(rport->phy); | 566 | rockchip_usb2phy_power_off(rport->phy); |
569 | notify_charger = true; | 567 | notify_charger = true; |
570 | sch_work = true; | 568 | sch_work = true; |
571 | cable = EXTCON_CHG_USB_DCP; | 569 | cable = EXTCON_CHG_USB_DCP; |
572 | break; | 570 | break; |
573 | case POWER_SUPPLY_TYPE_USB_CDP: | 571 | case POWER_SUPPLY_TYPE_USB_CDP: |
574 | dev_dbg(&rport->phy->dev, | 572 | dev_dbg(&rport->phy->dev, "cdp cable is connected\n"); |
575 | "cdp cable is connecetd\n"); | ||
576 | rockchip_usb2phy_power_on(rport->phy); | 573 | rockchip_usb2phy_power_on(rport->phy); |
577 | rport->state = OTG_STATE_B_PERIPHERAL; | 574 | rport->state = OTG_STATE_B_PERIPHERAL; |
578 | notify_charger = true; | 575 | notify_charger = true; |
@@ -1141,6 +1138,49 @@ disable_clks: | |||
1141 | return ret; | 1138 | return ret; |
1142 | } | 1139 | } |
1143 | 1140 | ||
1141 | static const struct rockchip_usb2phy_cfg rk3328_phy_cfgs[] = { | ||
1142 | { | ||
1143 | .reg = 0x100, | ||
1144 | .num_ports = 2, | ||
1145 | .clkout_ctl = { 0x108, 4, 4, 1, 0 }, | ||
1146 | .port_cfgs = { | ||
1147 | [USB2PHY_PORT_OTG] = { | ||
1148 | .phy_sus = { 0x0100, 15, 0, 0, 0x1d1 }, | ||
1149 | .bvalid_det_en = { 0x0110, 2, 2, 0, 1 }, | ||
1150 | .bvalid_det_st = { 0x0114, 2, 2, 0, 1 }, | ||
1151 | .bvalid_det_clr = { 0x0118, 2, 2, 0, 1 }, | ||
1152 | .ls_det_en = { 0x0110, 0, 0, 0, 1 }, | ||
1153 | .ls_det_st = { 0x0114, 0, 0, 0, 1 }, | ||
1154 | .ls_det_clr = { 0x0118, 0, 0, 0, 1 }, | ||
1155 | .utmi_avalid = { 0x0120, 10, 10, 0, 1 }, | ||
1156 | .utmi_bvalid = { 0x0120, 9, 9, 0, 1 }, | ||
1157 | .utmi_ls = { 0x0120, 5, 4, 0, 1 }, | ||
1158 | }, | ||
1159 | [USB2PHY_PORT_HOST] = { | ||
1160 | .phy_sus = { 0x104, 15, 0, 0, 0x1d1 }, | ||
1161 | .ls_det_en = { 0x110, 1, 1, 0, 1 }, | ||
1162 | .ls_det_st = { 0x114, 1, 1, 0, 1 }, | ||
1163 | .ls_det_clr = { 0x118, 1, 1, 0, 1 }, | ||
1164 | .utmi_ls = { 0x120, 17, 16, 0, 1 }, | ||
1165 | .utmi_hstdet = { 0x120, 19, 19, 0, 1 } | ||
1166 | } | ||
1167 | }, | ||
1168 | .chg_det = { | ||
1169 | .opmode = { 0x0100, 3, 0, 5, 1 }, | ||
1170 | .cp_det = { 0x0120, 24, 24, 0, 1 }, | ||
1171 | .dcp_det = { 0x0120, 23, 23, 0, 1 }, | ||
1172 | .dp_det = { 0x0120, 25, 25, 0, 1 }, | ||
1173 | .idm_sink_en = { 0x0108, 8, 8, 0, 1 }, | ||
1174 | .idp_sink_en = { 0x0108, 7, 7, 0, 1 }, | ||
1175 | .idp_src_en = { 0x0108, 9, 9, 0, 1 }, | ||
1176 | .rdm_pdwn_en = { 0x0108, 10, 10, 0, 1 }, | ||
1177 | .vdm_src_en = { 0x0108, 12, 12, 0, 1 }, | ||
1178 | .vdp_src_en = { 0x0108, 11, 11, 0, 1 }, | ||
1179 | }, | ||
1180 | }, | ||
1181 | { /* sentinel */ } | ||
1182 | }; | ||
1183 | |||
1144 | static const struct rockchip_usb2phy_cfg rk3366_phy_cfgs[] = { | 1184 | static const struct rockchip_usb2phy_cfg rk3366_phy_cfgs[] = { |
1145 | { | 1185 | { |
1146 | .reg = 0x700, | 1186 | .reg = 0x700, |
@@ -1223,6 +1263,7 @@ static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = { | |||
1223 | }; | 1263 | }; |
1224 | 1264 | ||
1225 | static const struct of_device_id rockchip_usb2phy_dt_match[] = { | 1265 | static const struct of_device_id rockchip_usb2phy_dt_match[] = { |
1266 | { .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs }, | ||
1226 | { .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs }, | 1267 | { .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs }, |
1227 | { .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs }, | 1268 | { .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs }, |
1228 | {} | 1269 | {} |
diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c index 734987fa0ad7..3378eeb7a562 100644 --- a/drivers/phy/phy-rockchip-usb.c +++ b/drivers/phy/phy-rockchip-usb.c | |||
@@ -66,6 +66,7 @@ struct rockchip_usb_phy { | |||
66 | struct phy *phy; | 66 | struct phy *phy; |
67 | bool uart_enabled; | 67 | bool uart_enabled; |
68 | struct reset_control *reset; | 68 | struct reset_control *reset; |
69 | struct regulator *vbus; | ||
69 | }; | 70 | }; |
70 | 71 | ||
71 | static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy, | 72 | static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy, |
@@ -88,6 +89,9 @@ static void rockchip_usb_phy480m_disable(struct clk_hw *hw) | |||
88 | struct rockchip_usb_phy, | 89 | struct rockchip_usb_phy, |
89 | clk480m_hw); | 90 | clk480m_hw); |
90 | 91 | ||
92 | if (phy->vbus) | ||
93 | regulator_disable(phy->vbus); | ||
94 | |||
91 | /* Power down usb phy analog blocks by set siddq 1 */ | 95 | /* Power down usb phy analog blocks by set siddq 1 */ |
92 | rockchip_usb_phy_power(phy, 1); | 96 | rockchip_usb_phy_power(phy, 1); |
93 | } | 97 | } |
@@ -143,6 +147,14 @@ static int rockchip_usb_phy_power_on(struct phy *_phy) | |||
143 | if (phy->uart_enabled) | 147 | if (phy->uart_enabled) |
144 | return -EBUSY; | 148 | return -EBUSY; |
145 | 149 | ||
150 | if (phy->vbus) { | ||
151 | int ret; | ||
152 | |||
153 | ret = regulator_enable(phy->vbus); | ||
154 | if (ret) | ||
155 | return ret; | ||
156 | } | ||
157 | |||
146 | return clk_prepare_enable(phy->clk480m); | 158 | return clk_prepare_enable(phy->clk480m); |
147 | } | 159 | } |
148 | 160 | ||
@@ -268,6 +280,13 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base, | |||
268 | } | 280 | } |
269 | phy_set_drvdata(rk_phy->phy, rk_phy); | 281 | phy_set_drvdata(rk_phy->phy, rk_phy); |
270 | 282 | ||
283 | rk_phy->vbus = devm_regulator_get_optional(&rk_phy->phy->dev, "vbus"); | ||
284 | if (IS_ERR(rk_phy->vbus)) { | ||
285 | if (PTR_ERR(rk_phy->vbus) == -EPROBE_DEFER) | ||
286 | return PTR_ERR(rk_phy->vbus); | ||
287 | rk_phy->vbus = NULL; | ||
288 | } | ||
289 | |||
271 | /* | 290 | /* |
272 | * When acting as uart-pipe, just keep clock on otherwise | 291 | * When acting as uart-pipe, just keep clock on otherwise |
273 | * only power up usb phy when it use, so disable it when init | 292 | * only power up usb phy when it use, so disable it when init |
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c index a21b5f24a340..bbf06cfe5898 100644 --- a/drivers/phy/phy-sun4i-usb.c +++ b/drivers/phy/phy-sun4i-usb.c | |||
@@ -49,12 +49,14 @@ | |||
49 | #define REG_PHYBIST 0x08 | 49 | #define REG_PHYBIST 0x08 |
50 | #define REG_PHYTUNE 0x0c | 50 | #define REG_PHYTUNE 0x0c |
51 | #define REG_PHYCTL_A33 0x10 | 51 | #define REG_PHYCTL_A33 0x10 |
52 | #define REG_PHY_UNK_H3 0x20 | 52 | #define REG_PHY_OTGCTL 0x20 |
53 | 53 | ||
54 | #define REG_PMU_UNK1 0x10 | 54 | #define REG_PMU_UNK1 0x10 |
55 | 55 | ||
56 | #define PHYCTL_DATA BIT(7) | 56 | #define PHYCTL_DATA BIT(7) |
57 | 57 | ||
58 | #define OTGCTL_ROUTE_MUSB BIT(0) | ||
59 | |||
58 | #define SUNXI_AHB_ICHR8_EN BIT(10) | 60 | #define SUNXI_AHB_ICHR8_EN BIT(10) |
59 | #define SUNXI_AHB_INCR4_BURST_EN BIT(9) | 61 | #define SUNXI_AHB_INCR4_BURST_EN BIT(9) |
60 | #define SUNXI_AHB_INCRX_ALIGN_EN BIT(8) | 62 | #define SUNXI_AHB_INCRX_ALIGN_EN BIT(8) |
@@ -110,6 +112,7 @@ struct sun4i_usb_phy_cfg { | |||
110 | u8 phyctl_offset; | 112 | u8 phyctl_offset; |
111 | bool dedicated_clocks; | 113 | bool dedicated_clocks; |
112 | bool enable_pmu_unk1; | 114 | bool enable_pmu_unk1; |
115 | bool phy0_dual_route; | ||
113 | }; | 116 | }; |
114 | 117 | ||
115 | struct sun4i_usb_phy_data { | 118 | struct sun4i_usb_phy_data { |
@@ -188,10 +191,8 @@ static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data, | |||
188 | 191 | ||
189 | spin_lock_irqsave(&phy_data->reg_lock, flags); | 192 | spin_lock_irqsave(&phy_data->reg_lock, flags); |
190 | 193 | ||
191 | if (phy_data->cfg->type == sun8i_a33_phy || | 194 | if (phy_data->cfg->phyctl_offset == REG_PHYCTL_A33) { |
192 | phy_data->cfg->type == sun50i_a64_phy || | 195 | /* SoCs newer than A33 need us to set phyctl to 0 explicitly */ |
193 | phy_data->cfg->type == sun8i_v3s_phy) { | ||
194 | /* A33 or A64 needs us to set phyctl to 0 explicitly */ | ||
195 | writel(0, phyctl); | 196 | writel(0, phyctl); |
196 | } | 197 | } |
197 | 198 | ||
@@ -271,23 +272,16 @@ static int sun4i_usb_phy_init(struct phy *_phy) | |||
271 | writel(val & ~2, phy->pmu + REG_PMU_UNK1); | 272 | writel(val & ~2, phy->pmu + REG_PMU_UNK1); |
272 | } | 273 | } |
273 | 274 | ||
274 | if (data->cfg->type == sun8i_h3_phy) { | 275 | /* Enable USB 45 Ohm resistor calibration */ |
275 | if (phy->index == 0) { | 276 | if (phy->index == 0) |
276 | val = readl(data->base + REG_PHY_UNK_H3); | 277 | sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 0x01, 1); |
277 | writel(val & ~1, data->base + REG_PHY_UNK_H3); | ||
278 | } | ||
279 | } else { | ||
280 | /* Enable USB 45 Ohm resistor calibration */ | ||
281 | if (phy->index == 0) | ||
282 | sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 0x01, 1); | ||
283 | 278 | ||
284 | /* Adjust PHY's magnitude and rate */ | 279 | /* Adjust PHY's magnitude and rate */ |
285 | sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5); | 280 | sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5); |
286 | 281 | ||
287 | /* Disconnect threshold adjustment */ | 282 | /* Disconnect threshold adjustment */ |
288 | sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL, | 283 | sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL, |
289 | data->cfg->disc_thresh, 2); | 284 | data->cfg->disc_thresh, 2); |
290 | } | ||
291 | 285 | ||
292 | sun4i_usb_phy_passby(phy, 1); | 286 | sun4i_usb_phy_passby(phy, 1); |
293 | 287 | ||
@@ -486,6 +480,21 @@ static const struct phy_ops sun4i_usb_phy_ops = { | |||
486 | .owner = THIS_MODULE, | 480 | .owner = THIS_MODULE, |
487 | }; | 481 | }; |
488 | 482 | ||
483 | static void sun4i_usb_phy0_reroute(struct sun4i_usb_phy_data *data, int id_det) | ||
484 | { | ||
485 | u32 regval; | ||
486 | |||
487 | regval = readl(data->base + REG_PHY_OTGCTL); | ||
488 | if (id_det == 0) { | ||
489 | /* Host mode. Route phy0 to EHCI/OHCI */ | ||
490 | regval &= ~OTGCTL_ROUTE_MUSB; | ||
491 | } else { | ||
492 | /* Peripheral mode. Route phy0 to MUSB */ | ||
493 | regval |= OTGCTL_ROUTE_MUSB; | ||
494 | } | ||
495 | writel(regval, data->base + REG_PHY_OTGCTL); | ||
496 | } | ||
497 | |||
489 | static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work) | 498 | static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work) |
490 | { | 499 | { |
491 | struct sun4i_usb_phy_data *data = | 500 | struct sun4i_usb_phy_data *data = |
@@ -546,6 +555,10 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work) | |||
546 | sun4i_usb_phy0_set_vbus_detect(phy0, 1); | 555 | sun4i_usb_phy0_set_vbus_detect(phy0, 1); |
547 | mutex_unlock(&phy0->mutex); | 556 | mutex_unlock(&phy0->mutex); |
548 | } | 557 | } |
558 | |||
559 | /* Re-route PHY0 if necessary */ | ||
560 | if (data->cfg->phy0_dual_route) | ||
561 | sun4i_usb_phy0_reroute(data, id_det); | ||
549 | } | 562 | } |
550 | 563 | ||
551 | if (vbus_notify) | 564 | if (vbus_notify) |
@@ -700,7 +713,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) | |||
700 | return PTR_ERR(phy->reset); | 713 | return PTR_ERR(phy->reset); |
701 | } | 714 | } |
702 | 715 | ||
703 | if (i) { /* No pmu for usbc0 */ | 716 | if (i || data->cfg->phy0_dual_route) { /* No pmu for musb */ |
704 | snprintf(name, sizeof(name), "pmu%d", i); | 717 | snprintf(name, sizeof(name), "pmu%d", i); |
705 | res = platform_get_resource_byname(pdev, | 718 | res = platform_get_resource_byname(pdev, |
706 | IORESOURCE_MEM, name); | 719 | IORESOURCE_MEM, name); |
@@ -823,8 +836,10 @@ static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = { | |||
823 | .num_phys = 4, | 836 | .num_phys = 4, |
824 | .type = sun8i_h3_phy, | 837 | .type = sun8i_h3_phy, |
825 | .disc_thresh = 3, | 838 | .disc_thresh = 3, |
839 | .phyctl_offset = REG_PHYCTL_A33, | ||
826 | .dedicated_clocks = true, | 840 | .dedicated_clocks = true, |
827 | .enable_pmu_unk1 = true, | 841 | .enable_pmu_unk1 = true, |
842 | .phy0_dual_route = true, | ||
828 | }; | 843 | }; |
829 | 844 | ||
830 | static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = { | 845 | static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = { |
@@ -843,6 +858,7 @@ static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = { | |||
843 | .phyctl_offset = REG_PHYCTL_A33, | 858 | .phyctl_offset = REG_PHYCTL_A33, |
844 | .dedicated_clocks = true, | 859 | .dedicated_clocks = true, |
845 | .enable_pmu_unk1 = true, | 860 | .enable_pmu_unk1 = true, |
861 | .phy0_dual_route = true, | ||
846 | }; | 862 | }; |
847 | 863 | ||
848 | static const struct of_device_id sun4i_usb_phy_of_match[] = { | 864 | static const struct of_device_id sun4i_usb_phy_of_match[] = { |
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 4c360f8071a8..b1fc626125aa 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig | |||
@@ -104,4 +104,6 @@ source "drivers/staging/vc04_services/Kconfig" | |||
104 | 104 | ||
105 | source "drivers/staging/bcm2835-audio/Kconfig" | 105 | source "drivers/staging/bcm2835-audio/Kconfig" |
106 | 106 | ||
107 | source "drivers/staging/typec/Kconfig" | ||
108 | |||
107 | endif # STAGING | 109 | endif # STAGING |
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 29cec5aa2945..682127c20da5 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile | |||
@@ -1,6 +1,7 @@ | |||
1 | # Makefile for staging directory | 1 | # Makefile for staging directory |
2 | 2 | ||
3 | obj-y += media/ | 3 | obj-y += media/ |
4 | obj-y += typec/ | ||
4 | obj-$(CONFIG_PRISM2_USB) += wlan-ng/ | 5 | obj-$(CONFIG_PRISM2_USB) += wlan-ng/ |
5 | obj-$(CONFIG_COMEDI) += comedi/ | 6 | obj-$(CONFIG_COMEDI) += comedi/ |
6 | obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/ | 7 | obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/ |
@@ -41,4 +42,3 @@ obj-$(CONFIG_KS7010) += ks7010/ | |||
41 | obj-$(CONFIG_GREYBUS) += greybus/ | 42 | obj-$(CONFIG_GREYBUS) += greybus/ |
42 | obj-$(CONFIG_BCM2835_VCHIQ) += vc04_services/ | 43 | obj-$(CONFIG_BCM2835_VCHIQ) += vc04_services/ |
43 | obj-$(CONFIG_SND_BCM2835) += bcm2835-audio/ | 44 | obj-$(CONFIG_SND_BCM2835) += bcm2835-audio/ |
44 | |||
diff --git a/drivers/staging/typec/Kconfig b/drivers/staging/typec/Kconfig new file mode 100644 index 000000000000..37a0781b0d0c --- /dev/null +++ b/drivers/staging/typec/Kconfig | |||
@@ -0,0 +1,24 @@ | |||
1 | menu "USB Power Delivery and Type-C drivers" | ||
2 | |||
3 | config TYPEC_TCPM | ||
4 | tristate "USB Type-C Port Controller Manager" | ||
5 | depends on USB | ||
6 | select TYPEC | ||
7 | help | ||
8 | The Type-C Port Controller Manager provides a USB PD and USB Type-C | ||
9 | state machine for use with Type-C Port Controllers. | ||
10 | |||
11 | if TYPEC_TCPM | ||
12 | |||
13 | config TYPEC_TCPCI | ||
14 | tristate "Type-C Port Controller Interface driver" | ||
15 | depends on I2C | ||
16 | select REGMAP_I2C | ||
17 | help | ||
18 | Type-C Port Controller driver for TCPCI-compliant controller. | ||
19 | |||
20 | source "drivers/staging/typec/fusb302/Kconfig" | ||
21 | |||
22 | endif | ||
23 | |||
24 | endmenu | ||
diff --git a/drivers/staging/typec/Makefile b/drivers/staging/typec/Makefile new file mode 100644 index 000000000000..30a7e29cbc9e --- /dev/null +++ b/drivers/staging/typec/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | obj-$(CONFIG_TYPEC_TCPM) += tcpm.o | ||
2 | obj-$(CONFIG_TYPEC_TCPCI) += tcpci.o | ||
3 | obj-y += fusb302/ | ||
diff --git a/drivers/staging/typec/TODO b/drivers/staging/typec/TODO new file mode 100644 index 000000000000..bc1f97a2d1bf --- /dev/null +++ b/drivers/staging/typec/TODO | |||
@@ -0,0 +1,15 @@ | |||
1 | tcpm: | ||
2 | - Add documentation (at the very least for the API to low level drivers) | ||
3 | - Split PD code into separate file | ||
4 | - Check if it makes sense to use tracepoints instead of debugfs for debug logs | ||
5 | - Implement Alternate Mode handling | ||
6 | - Address "#if 0" code if not addressed with the above | ||
7 | - Validate all comments marked with "XXX"; either address or remove comments | ||
8 | - Add support for USB PD 3.0. While not mandatory, at least fast role swap | ||
9 | as well as authentication support would be very desirable. | ||
10 | |||
11 | tcpci: | ||
12 | - Test with real hardware | ||
13 | |||
14 | Please send patches to Guenter Roeck <linux@roeck-us.net> and copy | ||
15 | Heikki Krogerus <heikki.krogerus@linux.intel.com>. | ||
diff --git a/drivers/staging/typec/fusb302/Kconfig b/drivers/staging/typec/fusb302/Kconfig new file mode 100644 index 000000000000..fce099ff39fe --- /dev/null +++ b/drivers/staging/typec/fusb302/Kconfig | |||
@@ -0,0 +1,7 @@ | |||
1 | config TYPEC_FUSB302 | ||
2 | tristate "Fairchild FUSB302 Type-C chip driver" | ||
3 | depends on I2C | ||
4 | help | ||
5 | The Fairchild FUSB302 Type-C chip driver that works with | ||
6 | Type-C Port Controller Manager to provide USB PD and USB | ||
7 | Type-C functionalities. | ||
diff --git a/drivers/staging/typec/fusb302/Makefile b/drivers/staging/typec/fusb302/Makefile new file mode 100644 index 000000000000..207efa5fbab8 --- /dev/null +++ b/drivers/staging/typec/fusb302/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_TYPEC_FUSB302) += fusb302.o | |||
diff --git a/drivers/staging/typec/fusb302/TODO b/drivers/staging/typec/fusb302/TODO new file mode 100644 index 000000000000..4933a1d92c32 --- /dev/null +++ b/drivers/staging/typec/fusb302/TODO | |||
@@ -0,0 +1,6 @@ | |||
1 | fusb302: | ||
2 | - Find a better logging scheme, at least not having the same debugging/logging | ||
3 | code replicated here and in tcpm | ||
4 | - Find a non-hacky way to coordinate between PM and I2C access | ||
5 | - Documentation? The FUSB302 datasheet provides information on the chip to help | ||
6 | understand the code. But it may still be helpful to have a documentation. | ||
diff --git a/drivers/staging/typec/fusb302/fusb302.c b/drivers/staging/typec/fusb302/fusb302.c new file mode 100644 index 000000000000..2cee9a952c9b --- /dev/null +++ b/drivers/staging/typec/fusb302/fusb302.c | |||
@@ -0,0 +1,1815 @@ | |||
1 | /* | ||
2 | * Copyright 2016-2017 Google, Inc | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * Fairchild FUSB302 Type-C Chip Driver | ||
15 | */ | ||
16 | |||
17 | #include <linux/debugfs.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/gpio.h> | ||
21 | #include <linux/i2c.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/mutex.h> | ||
26 | #include <linux/of_device.h> | ||
27 | #include <linux/of_device.h> | ||
28 | #include <linux/of_gpio.h> | ||
29 | #include <linux/pinctrl/consumer.h> | ||
30 | #include <linux/proc_fs.h> | ||
31 | #include <linux/regulator/consumer.h> | ||
32 | #include <linux/sched/clock.h> | ||
33 | #include <linux/seq_file.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <linux/string.h> | ||
36 | #include <linux/types.h> | ||
37 | #include <linux/usb/typec.h> | ||
38 | #include <linux/workqueue.h> | ||
39 | |||
40 | #include "fusb302_reg.h" | ||
41 | #include "../tcpm.h" | ||
42 | #include "../pd.h" | ||
43 | |||
44 | /* | ||
45 | * When the device is SNK, BC_LVL interrupt is used to monitor cc pins | ||
46 | * for the current capability offered by the SRC. As FUSB302 chip fires | ||
47 | * the BC_LVL interrupt on PD signalings, cc lvl should be handled after | ||
48 | * a delay to avoid measuring on PD activities. The delay is slightly | ||
49 | * longer than PD_T_PD_DEBPUNCE (10-20ms). | ||
50 | */ | ||
51 | #define T_BC_LVL_DEBOUNCE_DELAY_MS 30 | ||
52 | |||
53 | enum toggling_mode { | ||
54 | TOGGLINE_MODE_OFF, | ||
55 | TOGGLING_MODE_DRP, | ||
56 | TOGGLING_MODE_SNK, | ||
57 | TOGGLING_MODE_SRC, | ||
58 | }; | ||
59 | |||
60 | static const char * const toggling_mode_name[] = { | ||
61 | [TOGGLINE_MODE_OFF] = "toggling_OFF", | ||
62 | [TOGGLING_MODE_DRP] = "toggling_DRP", | ||
63 | [TOGGLING_MODE_SNK] = "toggling_SNK", | ||
64 | [TOGGLING_MODE_SRC] = "toggling_SRC", | ||
65 | }; | ||
66 | |||
67 | enum src_current_status { | ||
68 | SRC_CURRENT_DEFAULT, | ||
69 | SRC_CURRENT_MEDIUM, | ||
70 | SRC_CURRENT_HIGH, | ||
71 | }; | ||
72 | |||
73 | static const u8 ra_mda_value[] = { | ||
74 | [SRC_CURRENT_DEFAULT] = 4, /* 210mV */ | ||
75 | [SRC_CURRENT_MEDIUM] = 9, /* 420mV */ | ||
76 | [SRC_CURRENT_HIGH] = 18, /* 798mV */ | ||
77 | }; | ||
78 | |||
79 | static const u8 rd_mda_value[] = { | ||
80 | [SRC_CURRENT_DEFAULT] = 38, /* 1638mV */ | ||
81 | [SRC_CURRENT_MEDIUM] = 38, /* 1638mV */ | ||
82 | [SRC_CURRENT_HIGH] = 61, /* 2604mV */ | ||
83 | }; | ||
84 | |||
85 | #define LOG_BUFFER_ENTRIES 1024 | ||
86 | #define LOG_BUFFER_ENTRY_SIZE 128 | ||
87 | |||
88 | struct fusb302_chip { | ||
89 | struct device *dev; | ||
90 | struct i2c_client *i2c_client; | ||
91 | struct tcpm_port *tcpm_port; | ||
92 | struct tcpc_dev tcpc_dev; | ||
93 | |||
94 | struct regulator *vbus; | ||
95 | |||
96 | int gpio_int_n; | ||
97 | int gpio_int_n_irq; | ||
98 | |||
99 | struct workqueue_struct *wq; | ||
100 | struct delayed_work bc_lvl_handler; | ||
101 | |||
102 | atomic_t pm_suspend; | ||
103 | atomic_t i2c_busy; | ||
104 | |||
105 | /* lock for sharing chip states */ | ||
106 | struct mutex lock; | ||
107 | |||
108 | /* chip status */ | ||
109 | enum toggling_mode toggling_mode; | ||
110 | enum src_current_status src_current_status; | ||
111 | bool intr_togdone; | ||
112 | bool intr_bc_lvl; | ||
113 | bool intr_comp_chng; | ||
114 | |||
115 | /* port status */ | ||
116 | bool pull_up; | ||
117 | bool vconn_on; | ||
118 | bool vbus_on; | ||
119 | bool charge_on; | ||
120 | bool vbus_present; | ||
121 | enum typec_cc_polarity cc_polarity; | ||
122 | enum typec_cc_status cc1; | ||
123 | enum typec_cc_status cc2; | ||
124 | |||
125 | #ifdef CONFIG_DEBUG_FS | ||
126 | struct dentry *dentry; | ||
127 | /* lock for log buffer access */ | ||
128 | struct mutex logbuffer_lock; | ||
129 | int logbuffer_head; | ||
130 | int logbuffer_tail; | ||
131 | u8 *logbuffer[LOG_BUFFER_ENTRIES]; | ||
132 | #endif | ||
133 | }; | ||
134 | |||
135 | /* | ||
136 | * Logging | ||
137 | */ | ||
138 | |||
139 | #ifdef CONFIG_DEBUG_FS | ||
140 | |||
141 | static bool fusb302_log_full(struct fusb302_chip *chip) | ||
142 | { | ||
143 | return chip->logbuffer_tail == | ||
144 | (chip->logbuffer_head + 1) % LOG_BUFFER_ENTRIES; | ||
145 | } | ||
146 | |||
147 | static void _fusb302_log(struct fusb302_chip *chip, const char *fmt, | ||
148 | va_list args) | ||
149 | { | ||
150 | char tmpbuffer[LOG_BUFFER_ENTRY_SIZE]; | ||
151 | u64 ts_nsec = local_clock(); | ||
152 | unsigned long rem_nsec; | ||
153 | |||
154 | if (!chip->logbuffer[chip->logbuffer_head]) { | ||
155 | chip->logbuffer[chip->logbuffer_head] = | ||
156 | kzalloc(LOG_BUFFER_ENTRY_SIZE, GFP_KERNEL); | ||
157 | if (!chip->logbuffer[chip->logbuffer_head]) | ||
158 | return; | ||
159 | } | ||
160 | |||
161 | vsnprintf(tmpbuffer, sizeof(tmpbuffer), fmt, args); | ||
162 | |||
163 | mutex_lock(&chip->logbuffer_lock); | ||
164 | |||
165 | if (fusb302_log_full(chip)) { | ||
166 | chip->logbuffer_head = max(chip->logbuffer_head - 1, 0); | ||
167 | strlcpy(tmpbuffer, "overflow", sizeof(tmpbuffer)); | ||
168 | } | ||
169 | |||
170 | if (chip->logbuffer_head < 0 || | ||
171 | chip->logbuffer_head >= LOG_BUFFER_ENTRIES) { | ||
172 | dev_warn(chip->dev, | ||
173 | "Bad log buffer index %d\n", chip->logbuffer_head); | ||
174 | goto abort; | ||
175 | } | ||
176 | |||
177 | if (!chip->logbuffer[chip->logbuffer_head]) { | ||
178 | dev_warn(chip->dev, | ||
179 | "Log buffer index %d is NULL\n", chip->logbuffer_head); | ||
180 | goto abort; | ||
181 | } | ||
182 | |||
183 | rem_nsec = do_div(ts_nsec, 1000000000); | ||
184 | scnprintf(chip->logbuffer[chip->logbuffer_head], | ||
185 | LOG_BUFFER_ENTRY_SIZE, "[%5lu.%06lu] %s", | ||
186 | (unsigned long)ts_nsec, rem_nsec / 1000, | ||
187 | tmpbuffer); | ||
188 | chip->logbuffer_head = (chip->logbuffer_head + 1) % LOG_BUFFER_ENTRIES; | ||
189 | |||
190 | abort: | ||
191 | mutex_unlock(&chip->logbuffer_lock); | ||
192 | } | ||
193 | |||
194 | static void fusb302_log(struct fusb302_chip *chip, const char *fmt, ...) | ||
195 | { | ||
196 | va_list args; | ||
197 | |||
198 | va_start(args, fmt); | ||
199 | _fusb302_log(chip, fmt, args); | ||
200 | va_end(args); | ||
201 | } | ||
202 | |||
203 | static int fusb302_seq_show(struct seq_file *s, void *v) | ||
204 | { | ||
205 | struct fusb302_chip *chip = (struct fusb302_chip *)s->private; | ||
206 | int tail; | ||
207 | |||
208 | mutex_lock(&chip->logbuffer_lock); | ||
209 | tail = chip->logbuffer_tail; | ||
210 | while (tail != chip->logbuffer_head) { | ||
211 | seq_printf(s, "%s\n", chip->logbuffer[tail]); | ||
212 | tail = (tail + 1) % LOG_BUFFER_ENTRIES; | ||
213 | } | ||
214 | if (!seq_has_overflowed(s)) | ||
215 | chip->logbuffer_tail = tail; | ||
216 | mutex_unlock(&chip->logbuffer_lock); | ||
217 | |||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static int fusb302_debug_open(struct inode *inode, struct file *file) | ||
222 | { | ||
223 | return single_open(file, fusb302_seq_show, inode->i_private); | ||
224 | } | ||
225 | |||
226 | static const struct file_operations fusb302_debug_operations = { | ||
227 | .open = fusb302_debug_open, | ||
228 | .llseek = seq_lseek, | ||
229 | .read = seq_read, | ||
230 | .release = single_release, | ||
231 | }; | ||
232 | |||
233 | static struct dentry *rootdir; | ||
234 | |||
235 | static int fusb302_debugfs_init(struct fusb302_chip *chip) | ||
236 | { | ||
237 | mutex_init(&chip->logbuffer_lock); | ||
238 | if (!rootdir) { | ||
239 | rootdir = debugfs_create_dir("fusb302", NULL); | ||
240 | if (!rootdir) | ||
241 | return -ENOMEM; | ||
242 | } | ||
243 | |||
244 | chip->dentry = debugfs_create_file(dev_name(chip->dev), | ||
245 | S_IFREG | 0444, rootdir, | ||
246 | chip, &fusb302_debug_operations); | ||
247 | |||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | static void fusb302_debugfs_exit(struct fusb302_chip *chip) | ||
252 | { | ||
253 | debugfs_remove(chip->dentry); | ||
254 | } | ||
255 | |||
256 | #else | ||
257 | |||
258 | static void fusb302_log(const struct fusb302_chip *chip, | ||
259 | const char *fmt, ...) { } | ||
260 | static int fusb302_debugfs_init(const struct fusb302_chip *chip) { return 0; } | ||
261 | static void fusb302_debugfs_exit(const struct fusb302_chip *chip) { } | ||
262 | |||
263 | #endif | ||
264 | |||
265 | #define FUSB302_RESUME_RETRY 10 | ||
266 | #define FUSB302_RESUME_RETRY_SLEEP 50 | ||
267 | static int fusb302_i2c_write(struct fusb302_chip *chip, | ||
268 | u8 address, u8 data) | ||
269 | { | ||
270 | int retry_cnt; | ||
271 | int ret = 0; | ||
272 | |||
273 | atomic_set(&chip->i2c_busy, 1); | ||
274 | for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) { | ||
275 | if (atomic_read(&chip->pm_suspend)) { | ||
276 | pr_err("fusb302_i2c: pm suspend, retry %d/%d\n", | ||
277 | retry_cnt + 1, FUSB302_RESUME_RETRY); | ||
278 | msleep(FUSB302_RESUME_RETRY_SLEEP); | ||
279 | } else { | ||
280 | break; | ||
281 | } | ||
282 | } | ||
283 | ret = i2c_smbus_write_byte_data(chip->i2c_client, address, data); | ||
284 | if (ret < 0) | ||
285 | fusb302_log(chip, "cannot write 0x%02x to 0x%02x, ret=%d", | ||
286 | data, address, ret); | ||
287 | atomic_set(&chip->i2c_busy, 0); | ||
288 | |||
289 | return ret; | ||
290 | } | ||
291 | |||
292 | static int fusb302_i2c_block_write(struct fusb302_chip *chip, u8 address, | ||
293 | u8 length, const u8 *data) | ||
294 | { | ||
295 | int retry_cnt; | ||
296 | int ret = 0; | ||
297 | |||
298 | if (length <= 0) | ||
299 | return ret; | ||
300 | atomic_set(&chip->i2c_busy, 1); | ||
301 | for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) { | ||
302 | if (atomic_read(&chip->pm_suspend)) { | ||
303 | pr_err("fusb302_i2c: pm suspend, retry %d/%d\n", | ||
304 | retry_cnt + 1, FUSB302_RESUME_RETRY); | ||
305 | msleep(FUSB302_RESUME_RETRY_SLEEP); | ||
306 | } else { | ||
307 | break; | ||
308 | } | ||
309 | } | ||
310 | ret = i2c_smbus_write_i2c_block_data(chip->i2c_client, address, | ||
311 | length, data); | ||
312 | if (ret < 0) | ||
313 | fusb302_log(chip, "cannot block write 0x%02x, len=%d, ret=%d", | ||
314 | address, length, ret); | ||
315 | atomic_set(&chip->i2c_busy, 0); | ||
316 | |||
317 | return ret; | ||
318 | } | ||
319 | |||
320 | static int fusb302_i2c_read(struct fusb302_chip *chip, | ||
321 | u8 address, u8 *data) | ||
322 | { | ||
323 | int retry_cnt; | ||
324 | int ret = 0; | ||
325 | |||
326 | atomic_set(&chip->i2c_busy, 1); | ||
327 | for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) { | ||
328 | if (atomic_read(&chip->pm_suspend)) { | ||
329 | pr_err("fusb302_i2c: pm suspend, retry %d/%d\n", | ||
330 | retry_cnt + 1, FUSB302_RESUME_RETRY); | ||
331 | msleep(FUSB302_RESUME_RETRY_SLEEP); | ||
332 | } else { | ||
333 | break; | ||
334 | } | ||
335 | } | ||
336 | ret = i2c_smbus_read_byte_data(chip->i2c_client, address); | ||
337 | *data = (u8)ret; | ||
338 | if (ret < 0) | ||
339 | fusb302_log(chip, "cannot read %02x, ret=%d", address, ret); | ||
340 | atomic_set(&chip->i2c_busy, 0); | ||
341 | |||
342 | return ret; | ||
343 | } | ||
344 | |||
345 | static int fusb302_i2c_block_read(struct fusb302_chip *chip, u8 address, | ||
346 | u8 length, u8 *data) | ||
347 | { | ||
348 | int retry_cnt; | ||
349 | int ret = 0; | ||
350 | |||
351 | if (length <= 0) | ||
352 | return ret; | ||
353 | atomic_set(&chip->i2c_busy, 1); | ||
354 | for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) { | ||
355 | if (atomic_read(&chip->pm_suspend)) { | ||
356 | pr_err("fusb302_i2c: pm suspend, retry %d/%d\n", | ||
357 | retry_cnt + 1, FUSB302_RESUME_RETRY); | ||
358 | msleep(FUSB302_RESUME_RETRY_SLEEP); | ||
359 | } else { | ||
360 | break; | ||
361 | } | ||
362 | } | ||
363 | ret = i2c_smbus_read_i2c_block_data(chip->i2c_client, address, | ||
364 | length, data); | ||
365 | if (ret < 0) { | ||
366 | fusb302_log(chip, "cannot block read 0x%02x, len=%d, ret=%d", | ||
367 | address, length, ret); | ||
368 | return ret; | ||
369 | } | ||
370 | if (ret != length) { | ||
371 | fusb302_log(chip, "only read %d/%d bytes from 0x%02x", | ||
372 | ret, length, address); | ||
373 | return -EIO; | ||
374 | } | ||
375 | atomic_set(&chip->i2c_busy, 0); | ||
376 | |||
377 | return ret; | ||
378 | } | ||
379 | |||
380 | static int fusb302_i2c_mask_write(struct fusb302_chip *chip, u8 address, | ||
381 | u8 mask, u8 value) | ||
382 | { | ||
383 | int ret = 0; | ||
384 | u8 data; | ||
385 | |||
386 | ret = fusb302_i2c_read(chip, address, &data); | ||
387 | if (ret < 0) | ||
388 | return ret; | ||
389 | data &= ~mask; | ||
390 | data |= value; | ||
391 | ret = fusb302_i2c_write(chip, address, data); | ||
392 | if (ret < 0) | ||
393 | return ret; | ||
394 | |||
395 | return ret; | ||
396 | } | ||
397 | |||
398 | static int fusb302_i2c_set_bits(struct fusb302_chip *chip, u8 address, | ||
399 | u8 set_bits) | ||
400 | { | ||
401 | return fusb302_i2c_mask_write(chip, address, 0x00, set_bits); | ||
402 | } | ||
403 | |||
404 | static int fusb302_i2c_clear_bits(struct fusb302_chip *chip, u8 address, | ||
405 | u8 clear_bits) | ||
406 | { | ||
407 | return fusb302_i2c_mask_write(chip, address, clear_bits, 0x00); | ||
408 | } | ||
409 | |||
410 | static int fusb302_sw_reset(struct fusb302_chip *chip) | ||
411 | { | ||
412 | int ret = 0; | ||
413 | |||
414 | ret = fusb302_i2c_write(chip, FUSB_REG_RESET, | ||
415 | FUSB_REG_RESET_SW_RESET); | ||
416 | if (ret < 0) | ||
417 | fusb302_log(chip, "cannot sw reset the chip, ret=%d", ret); | ||
418 | else | ||
419 | fusb302_log(chip, "sw reset"); | ||
420 | |||
421 | return ret; | ||
422 | } | ||
423 | |||
424 | static int fusb302_enable_tx_auto_retries(struct fusb302_chip *chip) | ||
425 | { | ||
426 | int ret = 0; | ||
427 | |||
428 | ret = fusb302_i2c_set_bits(chip, FUSB_REG_CONTROL3, | ||
429 | FUSB_REG_CONTROL3_N_RETRIES_3 | | ||
430 | FUSB_REG_CONTROL3_AUTO_RETRY); | ||
431 | |||
432 | return ret; | ||
433 | } | ||
434 | |||
435 | /* | ||
436 | * initialize interrupt on the chip | ||
437 | * - unmasked interrupt: VBUS_OK | ||
438 | */ | ||
439 | static int fusb302_init_interrupt(struct fusb302_chip *chip) | ||
440 | { | ||
441 | int ret = 0; | ||
442 | |||
443 | ret = fusb302_i2c_write(chip, FUSB_REG_MASK, | ||
444 | 0xFF & ~FUSB_REG_MASK_VBUSOK); | ||
445 | if (ret < 0) | ||
446 | return ret; | ||
447 | ret = fusb302_i2c_write(chip, FUSB_REG_MASKA, 0xFF); | ||
448 | if (ret < 0) | ||
449 | return ret; | ||
450 | ret = fusb302_i2c_write(chip, FUSB_REG_MASKB, 0xFF); | ||
451 | if (ret < 0) | ||
452 | return ret; | ||
453 | ret = fusb302_i2c_clear_bits(chip, FUSB_REG_CONTROL0, | ||
454 | FUSB_REG_CONTROL0_INT_MASK); | ||
455 | if (ret < 0) | ||
456 | return ret; | ||
457 | |||
458 | return ret; | ||
459 | } | ||
460 | |||
461 | static int fusb302_set_power_mode(struct fusb302_chip *chip, u8 power_mode) | ||
462 | { | ||
463 | int ret = 0; | ||
464 | |||
465 | ret = fusb302_i2c_write(chip, FUSB_REG_POWER, power_mode); | ||
466 | |||
467 | return ret; | ||
468 | } | ||
469 | |||
470 | static int tcpm_init(struct tcpc_dev *dev) | ||
471 | { | ||
472 | struct fusb302_chip *chip = container_of(dev, struct fusb302_chip, | ||
473 | tcpc_dev); | ||
474 | int ret = 0; | ||
475 | u8 data; | ||
476 | |||
477 | ret = fusb302_sw_reset(chip); | ||
478 | if (ret < 0) | ||
479 | return ret; | ||
480 | ret = fusb302_enable_tx_auto_retries(chip); | ||
481 | if (ret < 0) | ||
482 | return ret; | ||
483 | ret = fusb302_init_interrupt(chip); | ||
484 | if (ret < 0) | ||
485 | return ret; | ||
486 | ret = fusb302_set_power_mode(chip, FUSB_REG_POWER_PWR_ALL); | ||
487 | if (ret < 0) | ||
488 | return ret; | ||
489 | ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &data); | ||
490 | if (ret < 0) | ||
491 | return ret; | ||
492 | chip->vbus_present = !!(FUSB_REG_STATUS0 & FUSB_REG_STATUS0_VBUSOK); | ||
493 | ret = fusb302_i2c_read(chip, FUSB_REG_DEVICE_ID, &data); | ||
494 | if (ret < 0) | ||
495 | return ret; | ||
496 | fusb302_log(chip, "fusb302 device ID: 0x%02x", data); | ||
497 | |||
498 | return ret; | ||
499 | } | ||
500 | |||
501 | static int tcpm_get_vbus(struct tcpc_dev *dev) | ||
502 | { | ||
503 | struct fusb302_chip *chip = container_of(dev, struct fusb302_chip, | ||
504 | tcpc_dev); | ||
505 | int ret = 0; | ||
506 | |||
507 | mutex_lock(&chip->lock); | ||
508 | ret = chip->vbus_present ? 1 : 0; | ||
509 | mutex_unlock(&chip->lock); | ||
510 | |||
511 | return ret; | ||
512 | } | ||
513 | |||
514 | static int fusb302_set_cc_pull(struct fusb302_chip *chip, | ||
515 | bool pull_up, bool pull_down) | ||
516 | { | ||
517 | int ret = 0; | ||
518 | u8 data = 0x00; | ||
519 | u8 mask = FUSB_REG_SWITCHES0_CC1_PU_EN | | ||
520 | FUSB_REG_SWITCHES0_CC2_PU_EN | | ||
521 | FUSB_REG_SWITCHES0_CC1_PD_EN | | ||
522 | FUSB_REG_SWITCHES0_CC2_PD_EN; | ||
523 | |||
524 | if (pull_up) | ||
525 | data |= (chip->cc_polarity == TYPEC_POLARITY_CC1) ? | ||
526 | FUSB_REG_SWITCHES0_CC1_PU_EN : | ||
527 | FUSB_REG_SWITCHES0_CC2_PU_EN; | ||
528 | if (pull_down) | ||
529 | data |= FUSB_REG_SWITCHES0_CC1_PD_EN | | ||
530 | FUSB_REG_SWITCHES0_CC2_PD_EN; | ||
531 | ret = fusb302_i2c_mask_write(chip, FUSB_REG_SWITCHES0, | ||
532 | mask, data); | ||
533 | if (ret < 0) | ||
534 | return ret; | ||
535 | chip->pull_up = pull_up; | ||
536 | |||
537 | return ret; | ||
538 | } | ||
539 | |||
540 | static int fusb302_set_src_current(struct fusb302_chip *chip, | ||
541 | enum src_current_status status) | ||
542 | { | ||
543 | int ret = 0; | ||
544 | |||
545 | chip->src_current_status = status; | ||
546 | switch (status) { | ||
547 | case SRC_CURRENT_DEFAULT: | ||
548 | ret = fusb302_i2c_mask_write(chip, FUSB_REG_CONTROL0, | ||
549 | FUSB_REG_CONTROL0_HOST_CUR_MASK, | ||
550 | FUSB_REG_CONTROL0_HOST_CUR_DEF); | ||
551 | break; | ||
552 | case SRC_CURRENT_MEDIUM: | ||
553 | ret = fusb302_i2c_mask_write(chip, FUSB_REG_CONTROL0, | ||
554 | FUSB_REG_CONTROL0_HOST_CUR_MASK, | ||
555 | FUSB_REG_CONTROL0_HOST_CUR_MED); | ||
556 | break; | ||
557 | case SRC_CURRENT_HIGH: | ||
558 | ret = fusb302_i2c_mask_write(chip, FUSB_REG_CONTROL0, | ||
559 | FUSB_REG_CONTROL0_HOST_CUR_MASK, | ||
560 | FUSB_REG_CONTROL0_HOST_CUR_HIGH); | ||
561 | break; | ||
562 | default: | ||
563 | break; | ||
564 | } | ||
565 | |||
566 | return ret; | ||
567 | } | ||
568 | |||
569 | static int fusb302_set_toggling(struct fusb302_chip *chip, | ||
570 | enum toggling_mode mode) | ||
571 | { | ||
572 | int ret = 0; | ||
573 | |||
574 | /* first disable toggling */ | ||
575 | ret = fusb302_i2c_clear_bits(chip, FUSB_REG_CONTROL2, | ||
576 | FUSB_REG_CONTROL2_TOGGLE); | ||
577 | if (ret < 0) | ||
578 | return ret; | ||
579 | /* mask interrupts for SRC or SNK */ | ||
580 | ret = fusb302_i2c_set_bits(chip, FUSB_REG_MASK, | ||
581 | FUSB_REG_MASK_BC_LVL | | ||
582 | FUSB_REG_MASK_COMP_CHNG); | ||
583 | if (ret < 0) | ||
584 | return ret; | ||
585 | chip->intr_bc_lvl = false; | ||
586 | chip->intr_comp_chng = false; | ||
587 | /* configure toggling mode: none/snk/src/drp */ | ||
588 | switch (mode) { | ||
589 | case TOGGLINE_MODE_OFF: | ||
590 | ret = fusb302_i2c_mask_write(chip, FUSB_REG_CONTROL2, | ||
591 | FUSB_REG_CONTROL2_MODE_MASK, | ||
592 | FUSB_REG_CONTROL2_MODE_NONE); | ||
593 | if (ret < 0) | ||
594 | return ret; | ||
595 | break; | ||
596 | case TOGGLING_MODE_SNK: | ||
597 | ret = fusb302_i2c_mask_write(chip, FUSB_REG_CONTROL2, | ||
598 | FUSB_REG_CONTROL2_MODE_MASK, | ||
599 | FUSB_REG_CONTROL2_MODE_UFP); | ||
600 | if (ret < 0) | ||
601 | return ret; | ||
602 | break; | ||
603 | case TOGGLING_MODE_SRC: | ||
604 | ret = fusb302_i2c_mask_write(chip, FUSB_REG_CONTROL2, | ||
605 | FUSB_REG_CONTROL2_MODE_MASK, | ||
606 | FUSB_REG_CONTROL2_MODE_DFP); | ||
607 | if (ret < 0) | ||
608 | return ret; | ||
609 | break; | ||
610 | case TOGGLING_MODE_DRP: | ||
611 | ret = fusb302_i2c_mask_write(chip, FUSB_REG_CONTROL2, | ||
612 | FUSB_REG_CONTROL2_MODE_MASK, | ||
613 | FUSB_REG_CONTROL2_MODE_DRP); | ||
614 | if (ret < 0) | ||
615 | return ret; | ||
616 | break; | ||
617 | default: | ||
618 | break; | ||
619 | } | ||
620 | |||
621 | if (mode == TOGGLINE_MODE_OFF) { | ||
622 | /* mask TOGDONE interrupt */ | ||
623 | ret = fusb302_i2c_set_bits(chip, FUSB_REG_MASKA, | ||
624 | FUSB_REG_MASKA_TOGDONE); | ||
625 | if (ret < 0) | ||
626 | return ret; | ||
627 | chip->intr_togdone = false; | ||
628 | } else { | ||
629 | /* unmask TOGDONE interrupt */ | ||
630 | ret = fusb302_i2c_clear_bits(chip, FUSB_REG_MASKA, | ||
631 | FUSB_REG_MASKA_TOGDONE); | ||
632 | if (ret < 0) | ||
633 | return ret; | ||
634 | chip->intr_togdone = true; | ||
635 | /* start toggling */ | ||
636 | ret = fusb302_i2c_set_bits(chip, FUSB_REG_CONTROL2, | ||
637 | FUSB_REG_CONTROL2_TOGGLE); | ||
638 | if (ret < 0) | ||
639 | return ret; | ||
640 | /* during toggling, consider cc as Open */ | ||
641 | chip->cc1 = TYPEC_CC_OPEN; | ||
642 | chip->cc2 = TYPEC_CC_OPEN; | ||
643 | } | ||
644 | chip->toggling_mode = mode; | ||
645 | |||
646 | return ret; | ||
647 | } | ||
648 | |||
649 | static const char * const typec_cc_status_name[] = { | ||
650 | [TYPEC_CC_OPEN] = "Open", | ||
651 | [TYPEC_CC_RA] = "Ra", | ||
652 | [TYPEC_CC_RD] = "Rd", | ||
653 | [TYPEC_CC_RP_DEF] = "Rp-def", | ||
654 | [TYPEC_CC_RP_1_5] = "Rp-1.5", | ||
655 | [TYPEC_CC_RP_3_0] = "Rp-3.0", | ||
656 | }; | ||
657 | |||
658 | static const enum src_current_status cc_src_current[] = { | ||
659 | [TYPEC_CC_OPEN] = SRC_CURRENT_DEFAULT, | ||
660 | [TYPEC_CC_RA] = SRC_CURRENT_DEFAULT, | ||
661 | [TYPEC_CC_RD] = SRC_CURRENT_DEFAULT, | ||
662 | [TYPEC_CC_RP_DEF] = SRC_CURRENT_DEFAULT, | ||
663 | [TYPEC_CC_RP_1_5] = SRC_CURRENT_MEDIUM, | ||
664 | [TYPEC_CC_RP_3_0] = SRC_CURRENT_HIGH, | ||
665 | }; | ||
666 | |||
667 | static int tcpm_set_cc(struct tcpc_dev *dev, enum typec_cc_status cc) | ||
668 | { | ||
669 | struct fusb302_chip *chip = container_of(dev, struct fusb302_chip, | ||
670 | tcpc_dev); | ||
671 | int ret = 0; | ||
672 | bool pull_up, pull_down; | ||
673 | u8 rd_mda; | ||
674 | |||
675 | mutex_lock(&chip->lock); | ||
676 | switch (cc) { | ||
677 | case TYPEC_CC_OPEN: | ||
678 | pull_up = false; | ||
679 | pull_down = false; | ||
680 | break; | ||
681 | case TYPEC_CC_RD: | ||
682 | pull_up = false; | ||
683 | pull_down = true; | ||
684 | break; | ||
685 | case TYPEC_CC_RP_DEF: | ||
686 | case TYPEC_CC_RP_1_5: | ||
687 | case TYPEC_CC_RP_3_0: | ||
688 | pull_up = true; | ||
689 | pull_down = false; | ||
690 | break; | ||
691 | default: | ||
692 | fusb302_log(chip, "unsupported cc value %s", | ||
693 | typec_cc_status_name[cc]); | ||
694 | ret = -EINVAL; | ||
695 | goto done; | ||
696 | } | ||
697 | ret = fusb302_set_toggling(chip, TOGGLINE_MODE_OFF); | ||
698 | if (ret < 0) { | ||
699 | fusb302_log(chip, "cannot stop toggling, ret=%d", ret); | ||
700 | goto done; | ||
701 | } | ||
702 | ret = fusb302_set_cc_pull(chip, pull_up, pull_down); | ||
703 | if (ret < 0) { | ||
704 | fusb302_log(chip, | ||
705 | "cannot set cc pulling up %s, down %s, ret = %d", | ||
706 | pull_up ? "True" : "False", | ||
707 | pull_down ? "True" : "False", | ||
708 | ret); | ||
709 | goto done; | ||
710 | } | ||
711 | /* reset the cc status */ | ||
712 | chip->cc1 = TYPEC_CC_OPEN; | ||
713 | chip->cc2 = TYPEC_CC_OPEN; | ||
714 | /* adjust current for SRC */ | ||
715 | if (pull_up) { | ||
716 | ret = fusb302_set_src_current(chip, cc_src_current[cc]); | ||
717 | if (ret < 0) { | ||
718 | fusb302_log(chip, "cannot set src current %s, ret=%d", | ||
719 | typec_cc_status_name[cc], ret); | ||
720 | goto done; | ||
721 | } | ||
722 | } | ||
723 | /* enable/disable interrupts, BC_LVL for SNK and COMP_CHNG for SRC */ | ||
724 | if (pull_up) { | ||
725 | rd_mda = rd_mda_value[cc_src_current[cc]]; | ||
726 | ret = fusb302_i2c_write(chip, FUSB_REG_MEASURE, rd_mda); | ||
727 | if (ret < 0) { | ||
728 | fusb302_log(chip, | ||
729 | "cannot set SRC measure value, ret=%d", | ||
730 | ret); | ||
731 | goto done; | ||
732 | } | ||
733 | ret = fusb302_i2c_mask_write(chip, FUSB_REG_MASK, | ||
734 | FUSB_REG_MASK_BC_LVL | | ||
735 | FUSB_REG_MASK_COMP_CHNG, | ||
736 | FUSB_REG_MASK_COMP_CHNG); | ||
737 | if (ret < 0) { | ||
738 | fusb302_log(chip, "cannot set SRC interrupt, ret=%d", | ||
739 | ret); | ||
740 | goto done; | ||
741 | } | ||
742 | chip->intr_bc_lvl = false; | ||
743 | chip->intr_comp_chng = true; | ||
744 | } | ||
745 | if (pull_down) { | ||
746 | ret = fusb302_i2c_mask_write(chip, FUSB_REG_MASK, | ||
747 | FUSB_REG_MASK_BC_LVL | | ||
748 | FUSB_REG_MASK_COMP_CHNG, | ||
749 | FUSB_REG_MASK_BC_LVL); | ||
750 | if (ret < 0) { | ||
751 | fusb302_log(chip, "cannot set SRC interrupt, ret=%d", | ||
752 | ret); | ||
753 | goto done; | ||
754 | } | ||
755 | chip->intr_bc_lvl = true; | ||
756 | chip->intr_comp_chng = false; | ||
757 | } | ||
758 | fusb302_log(chip, "cc := %s", typec_cc_status_name[cc]); | ||
759 | done: | ||
760 | mutex_unlock(&chip->lock); | ||
761 | |||
762 | return ret; | ||
763 | } | ||
764 | |||
765 | static int tcpm_get_cc(struct tcpc_dev *dev, enum typec_cc_status *cc1, | ||
766 | enum typec_cc_status *cc2) | ||
767 | { | ||
768 | struct fusb302_chip *chip = container_of(dev, struct fusb302_chip, | ||
769 | tcpc_dev); | ||
770 | |||
771 | mutex_lock(&chip->lock); | ||
772 | *cc1 = chip->cc1; | ||
773 | *cc2 = chip->cc2; | ||
774 | fusb302_log(chip, "cc1=%s, cc2=%s", typec_cc_status_name[*cc1], | ||
775 | typec_cc_status_name[*cc2]); | ||
776 | mutex_unlock(&chip->lock); | ||
777 | |||
778 | return 0; | ||
779 | } | ||
780 | |||
781 | static int tcpm_set_polarity(struct tcpc_dev *dev, | ||
782 | enum typec_cc_polarity polarity) | ||
783 | { | ||
784 | return 0; | ||
785 | } | ||
786 | |||
787 | static int tcpm_set_vconn(struct tcpc_dev *dev, bool on) | ||
788 | { | ||
789 | struct fusb302_chip *chip = container_of(dev, struct fusb302_chip, | ||
790 | tcpc_dev); | ||
791 | int ret = 0; | ||
792 | u8 switches0_data = 0x00; | ||
793 | u8 switches0_mask = FUSB_REG_SWITCHES0_VCONN_CC1 | | ||
794 | FUSB_REG_SWITCHES0_VCONN_CC2; | ||
795 | |||
796 | mutex_lock(&chip->lock); | ||
797 | if (chip->vconn_on == on) { | ||
798 | fusb302_log(chip, "vconn is already %s", on ? "On" : "Off"); | ||
799 | goto done; | ||
800 | } | ||
801 | if (on) { | ||
802 | switches0_data = (chip->cc_polarity == TYPEC_POLARITY_CC1) ? | ||
803 | FUSB_REG_SWITCHES0_VCONN_CC2 : | ||
804 | FUSB_REG_SWITCHES0_VCONN_CC1; | ||
805 | } | ||
806 | ret = fusb302_i2c_mask_write(chip, FUSB_REG_SWITCHES0, | ||
807 | switches0_mask, switches0_data); | ||
808 | if (ret < 0) | ||
809 | goto done; | ||
810 | chip->vconn_on = on; | ||
811 | fusb302_log(chip, "vconn := %s", on ? "On" : "Off"); | ||
812 | done: | ||
813 | mutex_unlock(&chip->lock); | ||
814 | |||
815 | return ret; | ||
816 | } | ||
817 | |||
818 | static int tcpm_set_vbus(struct tcpc_dev *dev, bool on, bool charge) | ||
819 | { | ||
820 | struct fusb302_chip *chip = container_of(dev, struct fusb302_chip, | ||
821 | tcpc_dev); | ||
822 | int ret = 0; | ||
823 | |||
824 | mutex_lock(&chip->lock); | ||
825 | if (chip->vbus_on == on) { | ||
826 | fusb302_log(chip, "vbus is already %s", on ? "On" : "Off"); | ||
827 | } else { | ||
828 | if (on) | ||
829 | ret = regulator_enable(chip->vbus); | ||
830 | else | ||
831 | ret = regulator_disable(chip->vbus); | ||
832 | if (ret < 0) { | ||
833 | fusb302_log(chip, "cannot %s vbus regulator, ret=%d", | ||
834 | on ? "enable" : "disable", ret); | ||
835 | goto done; | ||
836 | } | ||
837 | chip->vbus_on = on; | ||
838 | fusb302_log(chip, "vbus := %s", on ? "On" : "Off"); | ||
839 | } | ||
840 | if (chip->charge_on == charge) | ||
841 | fusb302_log(chip, "charge is already %s", | ||
842 | charge ? "On" : "Off"); | ||
843 | else | ||
844 | chip->charge_on = charge; | ||
845 | |||
846 | done: | ||
847 | mutex_unlock(&chip->lock); | ||
848 | |||
849 | return ret; | ||
850 | } | ||
851 | |||
852 | static int tcpm_set_current_limit(struct tcpc_dev *dev, u32 max_ma, u32 mv) | ||
853 | { | ||
854 | struct fusb302_chip *chip = container_of(dev, struct fusb302_chip, | ||
855 | tcpc_dev); | ||
856 | |||
857 | fusb302_log(chip, "current limit: %d ma, %d mv (not implemented)", | ||
858 | max_ma, mv); | ||
859 | |||
860 | return 0; | ||
861 | } | ||
862 | |||
863 | static int fusb302_pd_tx_flush(struct fusb302_chip *chip) | ||
864 | { | ||
865 | return fusb302_i2c_set_bits(chip, FUSB_REG_CONTROL0, | ||
866 | FUSB_REG_CONTROL0_TX_FLUSH); | ||
867 | } | ||
868 | |||
869 | static int fusb302_pd_rx_flush(struct fusb302_chip *chip) | ||
870 | { | ||
871 | return fusb302_i2c_set_bits(chip, FUSB_REG_CONTROL1, | ||
872 | FUSB_REG_CONTROL1_RX_FLUSH); | ||
873 | } | ||
874 | |||
875 | static int fusb302_pd_set_auto_goodcrc(struct fusb302_chip *chip, bool on) | ||
876 | { | ||
877 | if (on) | ||
878 | return fusb302_i2c_set_bits(chip, FUSB_REG_SWITCHES1, | ||
879 | FUSB_REG_SWITCHES1_AUTO_GCRC); | ||
880 | return fusb302_i2c_clear_bits(chip, FUSB_REG_SWITCHES1, | ||
881 | FUSB_REG_SWITCHES1_AUTO_GCRC); | ||
882 | } | ||
883 | |||
884 | static int fusb302_pd_set_interrupts(struct fusb302_chip *chip, bool on) | ||
885 | { | ||
886 | int ret = 0; | ||
887 | u8 mask_interrupts = FUSB_REG_MASK_COLLISION; | ||
888 | u8 maska_interrupts = FUSB_REG_MASKA_RETRYFAIL | | ||
889 | FUSB_REG_MASKA_HARDSENT | | ||
890 | FUSB_REG_MASKA_TX_SUCCESS | | ||
891 | FUSB_REG_MASKA_HARDRESET; | ||
892 | u8 maskb_interrupts = FUSB_REG_MASKB_GCRCSENT; | ||
893 | |||
894 | ret = on ? | ||
895 | fusb302_i2c_clear_bits(chip, FUSB_REG_MASK, mask_interrupts) : | ||
896 | fusb302_i2c_set_bits(chip, FUSB_REG_MASK, mask_interrupts); | ||
897 | if (ret < 0) | ||
898 | return ret; | ||
899 | ret = on ? | ||
900 | fusb302_i2c_clear_bits(chip, FUSB_REG_MASKA, maska_interrupts) : | ||
901 | fusb302_i2c_set_bits(chip, FUSB_REG_MASKA, maska_interrupts); | ||
902 | if (ret < 0) | ||
903 | return ret; | ||
904 | ret = on ? | ||
905 | fusb302_i2c_clear_bits(chip, FUSB_REG_MASKB, maskb_interrupts) : | ||
906 | fusb302_i2c_set_bits(chip, FUSB_REG_MASKB, maskb_interrupts); | ||
907 | return ret; | ||
908 | } | ||
909 | |||
910 | static int tcpm_set_pd_rx(struct tcpc_dev *dev, bool on) | ||
911 | { | ||
912 | struct fusb302_chip *chip = container_of(dev, struct fusb302_chip, | ||
913 | tcpc_dev); | ||
914 | int ret = 0; | ||
915 | |||
916 | mutex_lock(&chip->lock); | ||
917 | ret = fusb302_pd_rx_flush(chip); | ||
918 | if (ret < 0) { | ||
919 | fusb302_log(chip, "cannot flush pd rx buffer, ret=%d", ret); | ||
920 | goto done; | ||
921 | } | ||
922 | ret = fusb302_pd_tx_flush(chip); | ||
923 | if (ret < 0) { | ||
924 | fusb302_log(chip, "cannot flush pd tx buffer, ret=%d", ret); | ||
925 | goto done; | ||
926 | } | ||
927 | ret = fusb302_pd_set_auto_goodcrc(chip, on); | ||
928 | if (ret < 0) { | ||
929 | fusb302_log(chip, "cannot turn %s auto GCRC, ret=%d", | ||
930 | on ? "on" : "off", ret); | ||
931 | goto done; | ||
932 | } | ||
933 | ret = fusb302_pd_set_interrupts(chip, on); | ||
934 | if (ret < 0) { | ||
935 | fusb302_log(chip, "cannot turn %s pd interrupts, ret=%d", | ||
936 | on ? "on" : "off", ret); | ||
937 | goto done; | ||
938 | } | ||
939 | fusb302_log(chip, "pd := %s", on ? "on" : "off"); | ||
940 | done: | ||
941 | mutex_unlock(&chip->lock); | ||
942 | |||
943 | return ret; | ||
944 | } | ||
945 | |||
946 | static const char * const typec_role_name[] = { | ||
947 | [TYPEC_SINK] = "Sink", | ||
948 | [TYPEC_SOURCE] = "Source", | ||
949 | }; | ||
950 | |||
951 | static const char * const typec_data_role_name[] = { | ||
952 | [TYPEC_DEVICE] = "Device", | ||
953 | [TYPEC_HOST] = "Host", | ||
954 | }; | ||
955 | |||
956 | static int tcpm_set_roles(struct tcpc_dev *dev, bool attached, | ||
957 | enum typec_role pwr, enum typec_data_role data) | ||
958 | { | ||
959 | struct fusb302_chip *chip = container_of(dev, struct fusb302_chip, | ||
960 | tcpc_dev); | ||
961 | int ret = 0; | ||
962 | u8 switches1_mask = FUSB_REG_SWITCHES1_POWERROLE | | ||
963 | FUSB_REG_SWITCHES1_DATAROLE; | ||
964 | u8 switches1_data = 0x00; | ||
965 | |||
966 | mutex_lock(&chip->lock); | ||
967 | if (pwr == TYPEC_SOURCE) | ||
968 | switches1_data |= FUSB_REG_SWITCHES1_POWERROLE; | ||
969 | if (data == TYPEC_HOST) | ||
970 | switches1_data |= FUSB_REG_SWITCHES1_DATAROLE; | ||
971 | ret = fusb302_i2c_mask_write(chip, FUSB_REG_SWITCHES1, | ||
972 | switches1_mask, switches1_data); | ||
973 | if (ret < 0) { | ||
974 | fusb302_log(chip, "unable to set pd header %s, %s, ret=%d", | ||
975 | typec_role_name[pwr], typec_data_role_name[data], | ||
976 | ret); | ||
977 | goto done; | ||
978 | } | ||
979 | fusb302_log(chip, "pd header := %s, %s", typec_role_name[pwr], | ||
980 | typec_data_role_name[data]); | ||
981 | done: | ||
982 | mutex_unlock(&chip->lock); | ||
983 | |||
984 | return ret; | ||
985 | } | ||
986 | |||
987 | static int tcpm_start_drp_toggling(struct tcpc_dev *dev, | ||
988 | enum typec_cc_status cc) | ||
989 | { | ||
990 | struct fusb302_chip *chip = container_of(dev, struct fusb302_chip, | ||
991 | tcpc_dev); | ||
992 | int ret = 0; | ||
993 | |||
994 | mutex_lock(&chip->lock); | ||
995 | ret = fusb302_set_src_current(chip, cc_src_current[cc]); | ||
996 | if (ret < 0) { | ||
997 | fusb302_log(chip, "unable to set src current %s, ret=%d", | ||
998 | typec_cc_status_name[cc], ret); | ||
999 | goto done; | ||
1000 | } | ||
1001 | ret = fusb302_set_toggling(chip, TOGGLING_MODE_DRP); | ||
1002 | if (ret < 0) { | ||
1003 | fusb302_log(chip, | ||
1004 | "unable to start drp toggling, ret=%d", ret); | ||
1005 | goto done; | ||
1006 | } | ||
1007 | fusb302_log(chip, "start drp toggling"); | ||
1008 | done: | ||
1009 | mutex_unlock(&chip->lock); | ||
1010 | |||
1011 | return ret; | ||
1012 | } | ||
1013 | |||
1014 | static int fusb302_pd_send_message(struct fusb302_chip *chip, | ||
1015 | const struct pd_message *msg) | ||
1016 | { | ||
1017 | int ret = 0; | ||
1018 | u8 buf[40]; | ||
1019 | u8 pos = 0; | ||
1020 | int len; | ||
1021 | |||
1022 | /* SOP tokens */ | ||
1023 | buf[pos++] = FUSB302_TKN_SYNC1; | ||
1024 | buf[pos++] = FUSB302_TKN_SYNC1; | ||
1025 | buf[pos++] = FUSB302_TKN_SYNC1; | ||
1026 | buf[pos++] = FUSB302_TKN_SYNC2; | ||
1027 | |||
1028 | len = pd_header_cnt(msg->header) * 4; | ||
1029 | /* plug 2 for header */ | ||
1030 | len += 2; | ||
1031 | if (len > 0x1F) { | ||
1032 | fusb302_log(chip, | ||
1033 | "PD message too long %d (incl. header)", len); | ||
1034 | return -EINVAL; | ||
1035 | } | ||
1036 | /* packsym tells the FUSB302 chip that the next X bytes are payload */ | ||
1037 | buf[pos++] = FUSB302_TKN_PACKSYM | (len & 0x1F); | ||
1038 | buf[pos++] = msg->header & 0xFF; | ||
1039 | buf[pos++] = (msg->header >> 8) & 0xFF; | ||
1040 | |||
1041 | len -= 2; | ||
1042 | memcpy(&buf[pos], msg->payload, len); | ||
1043 | pos += len; | ||
1044 | |||
1045 | /* CRC */ | ||
1046 | buf[pos++] = FUSB302_TKN_JAMCRC; | ||
1047 | /* EOP */ | ||
1048 | buf[pos++] = FUSB302_TKN_EOP; | ||
1049 | /* turn tx off after sending message */ | ||
1050 | buf[pos++] = FUSB302_TKN_TXOFF; | ||
1051 | /* start transmission */ | ||
1052 | buf[pos++] = FUSB302_TKN_TXON; | ||
1053 | |||
1054 | ret = fusb302_i2c_block_write(chip, FUSB_REG_FIFOS, pos, buf); | ||
1055 | if (ret < 0) | ||
1056 | return ret; | ||
1057 | fusb302_log(chip, "sending PD message header: %x", msg->header); | ||
1058 | fusb302_log(chip, "sending PD message len: %d", len); | ||
1059 | |||
1060 | return ret; | ||
1061 | } | ||
1062 | |||
1063 | static int fusb302_pd_send_hardreset(struct fusb302_chip *chip) | ||
1064 | { | ||
1065 | return fusb302_i2c_set_bits(chip, FUSB_REG_CONTROL3, | ||
1066 | FUSB_REG_CONTROL3_SEND_HARDRESET); | ||
1067 | } | ||
1068 | |||
1069 | static const char * const transmit_type_name[] = { | ||
1070 | [TCPC_TX_SOP] = "SOP", | ||
1071 | [TCPC_TX_SOP_PRIME] = "SOP'", | ||
1072 | [TCPC_TX_SOP_PRIME_PRIME] = "SOP''", | ||
1073 | [TCPC_TX_SOP_DEBUG_PRIME] = "DEBUG'", | ||
1074 | [TCPC_TX_SOP_DEBUG_PRIME_PRIME] = "DEBUG''", | ||
1075 | [TCPC_TX_HARD_RESET] = "HARD_RESET", | ||
1076 | [TCPC_TX_CABLE_RESET] = "CABLE_RESET", | ||
1077 | [TCPC_TX_BIST_MODE_2] = "BIST_MODE_2", | ||
1078 | }; | ||
1079 | |||
1080 | static int tcpm_pd_transmit(struct tcpc_dev *dev, enum tcpm_transmit_type type, | ||
1081 | const struct pd_message *msg) | ||
1082 | { | ||
1083 | struct fusb302_chip *chip = container_of(dev, struct fusb302_chip, | ||
1084 | tcpc_dev); | ||
1085 | int ret = 0; | ||
1086 | |||
1087 | mutex_lock(&chip->lock); | ||
1088 | switch (type) { | ||
1089 | case TCPC_TX_SOP: | ||
1090 | ret = fusb302_pd_send_message(chip, msg); | ||
1091 | if (ret < 0) | ||
1092 | fusb302_log(chip, | ||
1093 | "cannot send PD message, ret=%d", ret); | ||
1094 | break; | ||
1095 | case TCPC_TX_HARD_RESET: | ||
1096 | ret = fusb302_pd_send_hardreset(chip); | ||
1097 | if (ret < 0) | ||
1098 | fusb302_log(chip, | ||
1099 | "cannot send hardreset, ret=%d", ret); | ||
1100 | break; | ||
1101 | default: | ||
1102 | fusb302_log(chip, "type %s not supported", | ||
1103 | transmit_type_name[type]); | ||
1104 | ret = -EINVAL; | ||
1105 | } | ||
1106 | mutex_unlock(&chip->lock); | ||
1107 | |||
1108 | return ret; | ||
1109 | } | ||
1110 | |||
1111 | static enum typec_cc_status fusb302_bc_lvl_to_cc(u8 bc_lvl) | ||
1112 | { | ||
1113 | if (bc_lvl == FUSB_REG_STATUS0_BC_LVL_1230_MAX) | ||
1114 | return TYPEC_CC_RP_3_0; | ||
1115 | if (bc_lvl == FUSB_REG_STATUS0_BC_LVL_600_1230) | ||
1116 | return TYPEC_CC_RP_1_5; | ||
1117 | if (bc_lvl == FUSB_REG_STATUS0_BC_LVL_200_600) | ||
1118 | return TYPEC_CC_RP_DEF; | ||
1119 | return TYPEC_CC_OPEN; | ||
1120 | } | ||
1121 | |||
1122 | static void fusb302_bc_lvl_handler_work(struct work_struct *work) | ||
1123 | { | ||
1124 | struct fusb302_chip *chip = container_of(work, struct fusb302_chip, | ||
1125 | bc_lvl_handler.work); | ||
1126 | int ret = 0; | ||
1127 | u8 status0; | ||
1128 | u8 bc_lvl; | ||
1129 | enum typec_cc_status cc_status; | ||
1130 | |||
1131 | mutex_lock(&chip->lock); | ||
1132 | if (!chip->intr_bc_lvl) { | ||
1133 | fusb302_log(chip, "BC_LVL interrupt is turned off, abort"); | ||
1134 | goto done; | ||
1135 | } | ||
1136 | ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &status0); | ||
1137 | if (ret < 0) | ||
1138 | goto done; | ||
1139 | fusb302_log(chip, "BC_LVL handler, status0=0x%02x", status0); | ||
1140 | if (status0 & FUSB_REG_STATUS0_ACTIVITY) { | ||
1141 | fusb302_log(chip, "CC activities detected, delay handling"); | ||
1142 | mod_delayed_work(chip->wq, &chip->bc_lvl_handler, | ||
1143 | msecs_to_jiffies(T_BC_LVL_DEBOUNCE_DELAY_MS)); | ||
1144 | goto done; | ||
1145 | } | ||
1146 | bc_lvl = status0 & FUSB_REG_STATUS0_BC_LVL_MASK; | ||
1147 | cc_status = fusb302_bc_lvl_to_cc(bc_lvl); | ||
1148 | if (chip->cc_polarity == TYPEC_POLARITY_CC1) { | ||
1149 | if (chip->cc1 != cc_status) { | ||
1150 | fusb302_log(chip, "cc1: %s -> %s", | ||
1151 | typec_cc_status_name[chip->cc1], | ||
1152 | typec_cc_status_name[cc_status]); | ||
1153 | chip->cc1 = cc_status; | ||
1154 | tcpm_cc_change(chip->tcpm_port); | ||
1155 | } | ||
1156 | } else { | ||
1157 | if (chip->cc2 != cc_status) { | ||
1158 | fusb302_log(chip, "cc2: %s -> %s", | ||
1159 | typec_cc_status_name[chip->cc2], | ||
1160 | typec_cc_status_name[cc_status]); | ||
1161 | chip->cc2 = cc_status; | ||
1162 | tcpm_cc_change(chip->tcpm_port); | ||
1163 | } | ||
1164 | } | ||
1165 | |||
1166 | done: | ||
1167 | mutex_unlock(&chip->lock); | ||
1168 | } | ||
1169 | |||
1170 | #define PDO_FIXED_FLAGS \ | ||
1171 | (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP | PDO_FIXED_USB_COMM) | ||
1172 | |||
1173 | static const u32 src_pdo[] = { | ||
1174 | PDO_FIXED(5000, 400, PDO_FIXED_FLAGS), | ||
1175 | }; | ||
1176 | |||
1177 | static const u32 snk_pdo[] = { | ||
1178 | PDO_FIXED(5000, 400, PDO_FIXED_FLAGS), | ||
1179 | }; | ||
1180 | |||
1181 | static const struct tcpc_config fusb302_tcpc_config = { | ||
1182 | .src_pdo = src_pdo, | ||
1183 | .nr_src_pdo = ARRAY_SIZE(src_pdo), | ||
1184 | .snk_pdo = snk_pdo, | ||
1185 | .nr_snk_pdo = ARRAY_SIZE(snk_pdo), | ||
1186 | .max_snk_mv = 9000, | ||
1187 | .max_snk_ma = 3000, | ||
1188 | .max_snk_mw = 27000, | ||
1189 | .operating_snk_mw = 2500, | ||
1190 | .type = TYPEC_PORT_DRP, | ||
1191 | .default_role = TYPEC_SINK, | ||
1192 | .alt_modes = NULL, | ||
1193 | }; | ||
1194 | |||
1195 | static void init_tcpc_dev(struct tcpc_dev *fusb302_tcpc_dev) | ||
1196 | { | ||
1197 | fusb302_tcpc_dev->config = &fusb302_tcpc_config; | ||
1198 | fusb302_tcpc_dev->init = tcpm_init; | ||
1199 | fusb302_tcpc_dev->get_vbus = tcpm_get_vbus; | ||
1200 | fusb302_tcpc_dev->set_cc = tcpm_set_cc; | ||
1201 | fusb302_tcpc_dev->get_cc = tcpm_get_cc; | ||
1202 | fusb302_tcpc_dev->set_polarity = tcpm_set_polarity; | ||
1203 | fusb302_tcpc_dev->set_vconn = tcpm_set_vconn; | ||
1204 | fusb302_tcpc_dev->set_vbus = tcpm_set_vbus; | ||
1205 | fusb302_tcpc_dev->set_current_limit = tcpm_set_current_limit; | ||
1206 | fusb302_tcpc_dev->set_pd_rx = tcpm_set_pd_rx; | ||
1207 | fusb302_tcpc_dev->set_roles = tcpm_set_roles; | ||
1208 | fusb302_tcpc_dev->start_drp_toggling = tcpm_start_drp_toggling; | ||
1209 | fusb302_tcpc_dev->pd_transmit = tcpm_pd_transmit; | ||
1210 | fusb302_tcpc_dev->mux = NULL; | ||
1211 | } | ||
1212 | |||
1213 | static const char * const cc_polarity_name[] = { | ||
1214 | [TYPEC_POLARITY_CC1] = "Polarity_CC1", | ||
1215 | [TYPEC_POLARITY_CC2] = "Polarity_CC2", | ||
1216 | }; | ||
1217 | |||
1218 | static int fusb302_set_cc_polarity(struct fusb302_chip *chip, | ||
1219 | enum typec_cc_polarity cc_polarity) | ||
1220 | { | ||
1221 | int ret = 0; | ||
1222 | u8 switches0_mask = FUSB_REG_SWITCHES0_CC1_PU_EN | | ||
1223 | FUSB_REG_SWITCHES0_CC2_PU_EN | | ||
1224 | FUSB_REG_SWITCHES0_VCONN_CC1 | | ||
1225 | FUSB_REG_SWITCHES0_VCONN_CC2 | | ||
1226 | FUSB_REG_SWITCHES0_MEAS_CC1 | | ||
1227 | FUSB_REG_SWITCHES0_MEAS_CC2; | ||
1228 | u8 switches0_data = 0x00; | ||
1229 | u8 switches1_mask = FUSB_REG_SWITCHES1_TXCC1_EN | | ||
1230 | FUSB_REG_SWITCHES1_TXCC2_EN; | ||
1231 | u8 switches1_data = 0x00; | ||
1232 | |||
1233 | if (cc_polarity == TYPEC_POLARITY_CC1) { | ||
1234 | switches0_data = FUSB_REG_SWITCHES0_MEAS_CC1; | ||
1235 | if (chip->vconn_on) | ||
1236 | switches0_data |= FUSB_REG_SWITCHES0_VCONN_CC2; | ||
1237 | if (chip->pull_up) | ||
1238 | switches0_data |= FUSB_REG_SWITCHES0_CC1_PU_EN; | ||
1239 | switches1_data = FUSB_REG_SWITCHES1_TXCC1_EN; | ||
1240 | } else { | ||
1241 | switches0_data = FUSB_REG_SWITCHES0_MEAS_CC2; | ||
1242 | if (chip->vconn_on) | ||
1243 | switches0_data |= FUSB_REG_SWITCHES0_VCONN_CC1; | ||
1244 | if (chip->pull_up) | ||
1245 | switches0_data |= FUSB_REG_SWITCHES0_CC2_PU_EN; | ||
1246 | switches1_data = FUSB_REG_SWITCHES1_TXCC2_EN; | ||
1247 | } | ||
1248 | ret = fusb302_i2c_mask_write(chip, FUSB_REG_SWITCHES0, | ||
1249 | switches0_mask, switches0_data); | ||
1250 | if (ret < 0) | ||
1251 | return ret; | ||
1252 | ret = fusb302_i2c_mask_write(chip, FUSB_REG_SWITCHES1, | ||
1253 | switches1_mask, switches1_data); | ||
1254 | if (ret < 0) | ||
1255 | return ret; | ||
1256 | chip->cc_polarity = cc_polarity; | ||
1257 | |||
1258 | return ret; | ||
1259 | } | ||
1260 | |||
1261 | static int fusb302_handle_togdone_snk(struct fusb302_chip *chip, | ||
1262 | u8 togdone_result) | ||
1263 | { | ||
1264 | int ret = 0; | ||
1265 | u8 status0; | ||
1266 | u8 bc_lvl; | ||
1267 | enum typec_cc_polarity cc_polarity; | ||
1268 | enum typec_cc_status cc_status_active, cc1, cc2; | ||
1269 | |||
1270 | /* set pull_up, pull_down */ | ||
1271 | ret = fusb302_set_cc_pull(chip, false, true); | ||
1272 | if (ret < 0) { | ||
1273 | fusb302_log(chip, "cannot set cc to pull down, ret=%d", ret); | ||
1274 | return ret; | ||
1275 | } | ||
1276 | /* set polarity */ | ||
1277 | cc_polarity = (togdone_result == FUSB_REG_STATUS1A_TOGSS_SNK1) ? | ||
1278 | TYPEC_POLARITY_CC1 : TYPEC_POLARITY_CC2; | ||
1279 | ret = fusb302_set_cc_polarity(chip, cc_polarity); | ||
1280 | if (ret < 0) { | ||
1281 | fusb302_log(chip, "cannot set cc polarity %s, ret=%d", | ||
1282 | cc_polarity_name[cc_polarity], ret); | ||
1283 | return ret; | ||
1284 | } | ||
1285 | /* fusb302_set_cc_polarity() has set the correct measure block */ | ||
1286 | ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &status0); | ||
1287 | if (ret < 0) | ||
1288 | return ret; | ||
1289 | bc_lvl = status0 & FUSB_REG_STATUS0_BC_LVL_MASK; | ||
1290 | cc_status_active = fusb302_bc_lvl_to_cc(bc_lvl); | ||
1291 | /* restart toggling if the cc status on the active line is OPEN */ | ||
1292 | if (cc_status_active == TYPEC_CC_OPEN) { | ||
1293 | fusb302_log(chip, "restart toggling as CC_OPEN detected"); | ||
1294 | ret = fusb302_set_toggling(chip, chip->toggling_mode); | ||
1295 | return ret; | ||
1296 | } | ||
1297 | /* update tcpm with the new cc value */ | ||
1298 | cc1 = (cc_polarity == TYPEC_POLARITY_CC1) ? | ||
1299 | cc_status_active : TYPEC_CC_OPEN; | ||
1300 | cc2 = (cc_polarity == TYPEC_POLARITY_CC2) ? | ||
1301 | cc_status_active : TYPEC_CC_OPEN; | ||
1302 | if ((chip->cc1 != cc1) || (chip->cc2 != cc2)) { | ||
1303 | chip->cc1 = cc1; | ||
1304 | chip->cc2 = cc2; | ||
1305 | tcpm_cc_change(chip->tcpm_port); | ||
1306 | } | ||
1307 | /* turn off toggling */ | ||
1308 | ret = fusb302_set_toggling(chip, TOGGLINE_MODE_OFF); | ||
1309 | if (ret < 0) { | ||
1310 | fusb302_log(chip, | ||
1311 | "cannot set toggling mode off, ret=%d", ret); | ||
1312 | return ret; | ||
1313 | } | ||
1314 | /* unmask bc_lvl interrupt */ | ||
1315 | ret = fusb302_i2c_clear_bits(chip, FUSB_REG_MASK, FUSB_REG_MASK_BC_LVL); | ||
1316 | if (ret < 0) { | ||
1317 | fusb302_log(chip, | ||
1318 | "cannot unmask bc_lcl interrupt, ret=%d", ret); | ||
1319 | return ret; | ||
1320 | } | ||
1321 | chip->intr_bc_lvl = true; | ||
1322 | fusb302_log(chip, "detected cc1=%s, cc2=%s", | ||
1323 | typec_cc_status_name[cc1], | ||
1324 | typec_cc_status_name[cc2]); | ||
1325 | |||
1326 | return ret; | ||
1327 | } | ||
1328 | |||
1329 | static int fusb302_handle_togdone_src(struct fusb302_chip *chip, | ||
1330 | u8 togdone_result) | ||
1331 | { | ||
1332 | /* | ||
1333 | * - set polarity (measure cc, vconn, tx) | ||
1334 | * - set pull_up, pull_down | ||
1335 | * - set cc1, cc2, and update to tcpm_port | ||
1336 | * - set I_COMP interrupt on | ||
1337 | */ | ||
1338 | int ret = 0; | ||
1339 | u8 status0; | ||
1340 | u8 ra_mda = ra_mda_value[chip->src_current_status]; | ||
1341 | u8 rd_mda = rd_mda_value[chip->src_current_status]; | ||
1342 | bool ra_comp, rd_comp; | ||
1343 | enum typec_cc_polarity cc_polarity; | ||
1344 | enum typec_cc_status cc_status_active, cc1, cc2; | ||
1345 | |||
1346 | /* set pull_up, pull_down */ | ||
1347 | ret = fusb302_set_cc_pull(chip, true, false); | ||
1348 | if (ret < 0) { | ||
1349 | fusb302_log(chip, "cannot set cc to pull up, ret=%d", ret); | ||
1350 | return ret; | ||
1351 | } | ||
1352 | /* set polarity */ | ||
1353 | cc_polarity = (togdone_result == FUSB_REG_STATUS1A_TOGSS_SRC1) ? | ||
1354 | TYPEC_POLARITY_CC1 : TYPEC_POLARITY_CC2; | ||
1355 | ret = fusb302_set_cc_polarity(chip, cc_polarity); | ||
1356 | if (ret < 0) { | ||
1357 | fusb302_log(chip, "cannot set cc polarity %s, ret=%d", | ||
1358 | cc_polarity_name[cc_polarity], ret); | ||
1359 | return ret; | ||
1360 | } | ||
1361 | /* fusb302_set_cc_polarity() has set the correct measure block */ | ||
1362 | ret = fusb302_i2c_write(chip, FUSB_REG_MEASURE, rd_mda); | ||
1363 | if (ret < 0) | ||
1364 | return ret; | ||
1365 | usleep_range(50, 100); | ||
1366 | ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &status0); | ||
1367 | if (ret < 0) | ||
1368 | return ret; | ||
1369 | rd_comp = !!(status0 & FUSB_REG_STATUS0_COMP); | ||
1370 | if (!rd_comp) { | ||
1371 | ret = fusb302_i2c_write(chip, FUSB_REG_MEASURE, ra_mda); | ||
1372 | if (ret < 0) | ||
1373 | return ret; | ||
1374 | usleep_range(50, 100); | ||
1375 | ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &status0); | ||
1376 | if (ret < 0) | ||
1377 | return ret; | ||
1378 | ra_comp = !!(status0 & FUSB_REG_STATUS0_COMP); | ||
1379 | } | ||
1380 | if (rd_comp) | ||
1381 | cc_status_active = TYPEC_CC_OPEN; | ||
1382 | else if (ra_comp) | ||
1383 | cc_status_active = TYPEC_CC_RD; | ||
1384 | else | ||
1385 | /* Ra is not supported, report as Open */ | ||
1386 | cc_status_active = TYPEC_CC_OPEN; | ||
1387 | /* restart toggling if the cc status on the active line is OPEN */ | ||
1388 | if (cc_status_active == TYPEC_CC_OPEN) { | ||
1389 | fusb302_log(chip, "restart toggling as CC_OPEN detected"); | ||
1390 | ret = fusb302_set_toggling(chip, chip->toggling_mode); | ||
1391 | return ret; | ||
1392 | } | ||
1393 | /* update tcpm with the new cc value */ | ||
1394 | cc1 = (cc_polarity == TYPEC_POLARITY_CC1) ? | ||
1395 | cc_status_active : TYPEC_CC_OPEN; | ||
1396 | cc2 = (cc_polarity == TYPEC_POLARITY_CC2) ? | ||
1397 | cc_status_active : TYPEC_CC_OPEN; | ||
1398 | if ((chip->cc1 != cc1) || (chip->cc2 != cc2)) { | ||
1399 | chip->cc1 = cc1; | ||
1400 | chip->cc2 = cc2; | ||
1401 | tcpm_cc_change(chip->tcpm_port); | ||
1402 | } | ||
1403 | /* turn off toggling */ | ||
1404 | ret = fusb302_set_toggling(chip, TOGGLINE_MODE_OFF); | ||
1405 | if (ret < 0) { | ||
1406 | fusb302_log(chip, | ||
1407 | "cannot set toggling mode off, ret=%d", ret); | ||
1408 | return ret; | ||
1409 | } | ||
1410 | /* set MDAC to Rd threshold, and unmask I_COMP for unplug detection */ | ||
1411 | ret = fusb302_i2c_write(chip, FUSB_REG_MEASURE, rd_mda); | ||
1412 | if (ret < 0) | ||
1413 | return ret; | ||
1414 | /* unmask comp_chng interrupt */ | ||
1415 | ret = fusb302_i2c_clear_bits(chip, FUSB_REG_MASK, | ||
1416 | FUSB_REG_MASK_COMP_CHNG); | ||
1417 | if (ret < 0) { | ||
1418 | fusb302_log(chip, | ||
1419 | "cannot unmask bc_lcl interrupt, ret=%d", ret); | ||
1420 | return ret; | ||
1421 | } | ||
1422 | chip->intr_comp_chng = true; | ||
1423 | fusb302_log(chip, "detected cc1=%s, cc2=%s", | ||
1424 | typec_cc_status_name[cc1], | ||
1425 | typec_cc_status_name[cc2]); | ||
1426 | |||
1427 | return ret; | ||
1428 | } | ||
1429 | |||
1430 | static int fusb302_handle_togdone(struct fusb302_chip *chip) | ||
1431 | { | ||
1432 | int ret = 0; | ||
1433 | u8 status1a; | ||
1434 | u8 togdone_result; | ||
1435 | |||
1436 | ret = fusb302_i2c_read(chip, FUSB_REG_STATUS1A, &status1a); | ||
1437 | if (ret < 0) | ||
1438 | return ret; | ||
1439 | togdone_result = (status1a >> FUSB_REG_STATUS1A_TOGSS_POS) & | ||
1440 | FUSB_REG_STATUS1A_TOGSS_MASK; | ||
1441 | switch (togdone_result) { | ||
1442 | case FUSB_REG_STATUS1A_TOGSS_SNK1: | ||
1443 | case FUSB_REG_STATUS1A_TOGSS_SNK2: | ||
1444 | return fusb302_handle_togdone_snk(chip, togdone_result); | ||
1445 | case FUSB_REG_STATUS1A_TOGSS_SRC1: | ||
1446 | case FUSB_REG_STATUS1A_TOGSS_SRC2: | ||
1447 | return fusb302_handle_togdone_src(chip, togdone_result); | ||
1448 | case FUSB_REG_STATUS1A_TOGSS_AA: | ||
1449 | /* doesn't support */ | ||
1450 | fusb302_log(chip, "AudioAccessory not supported"); | ||
1451 | fusb302_set_toggling(chip, chip->toggling_mode); | ||
1452 | break; | ||
1453 | default: | ||
1454 | fusb302_log(chip, "TOGDONE with an invalid state: %d", | ||
1455 | togdone_result); | ||
1456 | fusb302_set_toggling(chip, chip->toggling_mode); | ||
1457 | break; | ||
1458 | } | ||
1459 | return ret; | ||
1460 | } | ||
1461 | |||
1462 | static int fusb302_pd_reset(struct fusb302_chip *chip) | ||
1463 | { | ||
1464 | return fusb302_i2c_set_bits(chip, FUSB_REG_RESET, | ||
1465 | FUSB_REG_RESET_PD_RESET); | ||
1466 | } | ||
1467 | |||
1468 | static int fusb302_pd_read_message(struct fusb302_chip *chip, | ||
1469 | struct pd_message *msg) | ||
1470 | { | ||
1471 | int ret = 0; | ||
1472 | u8 token; | ||
1473 | u8 crc[4]; | ||
1474 | int len; | ||
1475 | |||
1476 | /* first SOP token */ | ||
1477 | ret = fusb302_i2c_read(chip, FUSB_REG_FIFOS, &token); | ||
1478 | if (ret < 0) | ||
1479 | return ret; | ||
1480 | ret = fusb302_i2c_block_read(chip, FUSB_REG_FIFOS, 2, | ||
1481 | (u8 *)&msg->header); | ||
1482 | if (ret < 0) | ||
1483 | return ret; | ||
1484 | len = pd_header_cnt(msg->header) * 4; | ||
1485 | /* add 4 to length to include the CRC */ | ||
1486 | if (len > PD_MAX_PAYLOAD * 4) { | ||
1487 | fusb302_log(chip, "PD message too long %d", len); | ||
1488 | return -EINVAL; | ||
1489 | } | ||
1490 | if (len > 0) { | ||
1491 | ret = fusb302_i2c_block_read(chip, FUSB_REG_FIFOS, len, | ||
1492 | (u8 *)msg->payload); | ||
1493 | if (ret < 0) | ||
1494 | return ret; | ||
1495 | } | ||
1496 | /* another 4 bytes to read CRC out */ | ||
1497 | ret = fusb302_i2c_block_read(chip, FUSB_REG_FIFOS, 4, crc); | ||
1498 | if (ret < 0) | ||
1499 | return ret; | ||
1500 | fusb302_log(chip, "PD message header: %x", msg->header); | ||
1501 | fusb302_log(chip, "PD message len: %d", len); | ||
1502 | |||
1503 | return ret; | ||
1504 | } | ||
1505 | |||
1506 | static irqreturn_t fusb302_irq_intn(int irq, void *dev_id) | ||
1507 | { | ||
1508 | struct fusb302_chip *chip = dev_id; | ||
1509 | int ret = 0; | ||
1510 | u8 interrupt; | ||
1511 | u8 interrupta; | ||
1512 | u8 interruptb; | ||
1513 | u8 status0; | ||
1514 | bool vbus_present; | ||
1515 | bool comp_result; | ||
1516 | bool intr_togdone; | ||
1517 | bool intr_bc_lvl; | ||
1518 | bool intr_comp_chng; | ||
1519 | struct pd_message pd_msg; | ||
1520 | |||
1521 | mutex_lock(&chip->lock); | ||
1522 | /* grab a snapshot of intr flags */ | ||
1523 | intr_togdone = chip->intr_togdone; | ||
1524 | intr_bc_lvl = chip->intr_bc_lvl; | ||
1525 | intr_comp_chng = chip->intr_comp_chng; | ||
1526 | |||
1527 | ret = fusb302_i2c_read(chip, FUSB_REG_INTERRUPT, &interrupt); | ||
1528 | if (ret < 0) | ||
1529 | goto done; | ||
1530 | ret = fusb302_i2c_read(chip, FUSB_REG_INTERRUPTA, &interrupta); | ||
1531 | if (ret < 0) | ||
1532 | goto done; | ||
1533 | ret = fusb302_i2c_read(chip, FUSB_REG_INTERRUPTB, &interruptb); | ||
1534 | if (ret < 0) | ||
1535 | goto done; | ||
1536 | ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &status0); | ||
1537 | if (ret < 0) | ||
1538 | goto done; | ||
1539 | fusb302_log(chip, | ||
1540 | "IRQ: 0x%02x, a: 0x%02x, b: 0x%02x, status0: 0x%02x", | ||
1541 | interrupt, interrupta, interruptb, status0); | ||
1542 | |||
1543 | if (interrupt & FUSB_REG_INTERRUPT_VBUSOK) { | ||
1544 | vbus_present = !!(status0 & FUSB_REG_STATUS0_VBUSOK); | ||
1545 | fusb302_log(chip, "IRQ: VBUS_OK, vbus=%s", | ||
1546 | vbus_present ? "On" : "Off"); | ||
1547 | if (vbus_present != chip->vbus_present) { | ||
1548 | chip->vbus_present = vbus_present; | ||
1549 | tcpm_vbus_change(chip->tcpm_port); | ||
1550 | } | ||
1551 | } | ||
1552 | |||
1553 | if ((interrupta & FUSB_REG_INTERRUPTA_TOGDONE) && intr_togdone) { | ||
1554 | fusb302_log(chip, "IRQ: TOGDONE"); | ||
1555 | ret = fusb302_handle_togdone(chip); | ||
1556 | if (ret < 0) { | ||
1557 | fusb302_log(chip, | ||
1558 | "handle togdone error, ret=%d", ret); | ||
1559 | goto done; | ||
1560 | } | ||
1561 | } | ||
1562 | |||
1563 | if ((interrupt & FUSB_REG_INTERRUPT_BC_LVL) && intr_bc_lvl) { | ||
1564 | fusb302_log(chip, "IRQ: BC_LVL, handler pending"); | ||
1565 | /* | ||
1566 | * as BC_LVL interrupt can be affected by PD activity, | ||
1567 | * apply delay to for the handler to wait for the PD | ||
1568 | * signaling to finish. | ||
1569 | */ | ||
1570 | mod_delayed_work(chip->wq, &chip->bc_lvl_handler, | ||
1571 | msecs_to_jiffies(T_BC_LVL_DEBOUNCE_DELAY_MS)); | ||
1572 | } | ||
1573 | |||
1574 | if ((interrupt & FUSB_REG_INTERRUPT_COMP_CHNG) && intr_comp_chng) { | ||
1575 | comp_result = !!(status0 & FUSB_REG_STATUS0_COMP); | ||
1576 | fusb302_log(chip, "IRQ: COMP_CHNG, comp=%s", | ||
1577 | comp_result ? "true" : "false"); | ||
1578 | if (comp_result) { | ||
1579 | /* cc level > Rd_threashold, detach */ | ||
1580 | if (chip->cc_polarity == TYPEC_POLARITY_CC1) | ||
1581 | chip->cc1 = TYPEC_CC_OPEN; | ||
1582 | else | ||
1583 | chip->cc2 = TYPEC_CC_OPEN; | ||
1584 | tcpm_cc_change(chip->tcpm_port); | ||
1585 | } | ||
1586 | } | ||
1587 | |||
1588 | if (interrupt & FUSB_REG_INTERRUPT_COLLISION) { | ||
1589 | fusb302_log(chip, "IRQ: PD collision"); | ||
1590 | tcpm_pd_transmit_complete(chip->tcpm_port, TCPC_TX_FAILED); | ||
1591 | } | ||
1592 | |||
1593 | if (interrupta & FUSB_REG_INTERRUPTA_RETRYFAIL) { | ||
1594 | fusb302_log(chip, "IRQ: PD retry failed"); | ||
1595 | tcpm_pd_transmit_complete(chip->tcpm_port, TCPC_TX_FAILED); | ||
1596 | } | ||
1597 | |||
1598 | if (interrupta & FUSB_REG_INTERRUPTA_HARDSENT) { | ||
1599 | fusb302_log(chip, "IRQ: PD hardreset sent"); | ||
1600 | ret = fusb302_pd_reset(chip); | ||
1601 | if (ret < 0) { | ||
1602 | fusb302_log(chip, "cannot PD reset, ret=%d", ret); | ||
1603 | goto done; | ||
1604 | } | ||
1605 | tcpm_pd_transmit_complete(chip->tcpm_port, TCPC_TX_SUCCESS); | ||
1606 | } | ||
1607 | |||
1608 | if (interrupta & FUSB_REG_INTERRUPTA_TX_SUCCESS) { | ||
1609 | fusb302_log(chip, "IRQ: PD tx success"); | ||
1610 | /* read out the received good CRC */ | ||
1611 | ret = fusb302_pd_read_message(chip, &pd_msg); | ||
1612 | if (ret < 0) { | ||
1613 | fusb302_log(chip, "cannot read in GCRC, ret=%d", ret); | ||
1614 | goto done; | ||
1615 | } | ||
1616 | tcpm_pd_transmit_complete(chip->tcpm_port, TCPC_TX_SUCCESS); | ||
1617 | } | ||
1618 | |||
1619 | if (interrupta & FUSB_REG_INTERRUPTA_HARDRESET) { | ||
1620 | fusb302_log(chip, "IRQ: PD received hardreset"); | ||
1621 | ret = fusb302_pd_reset(chip); | ||
1622 | if (ret < 0) { | ||
1623 | fusb302_log(chip, "cannot PD reset, ret=%d", ret); | ||
1624 | goto done; | ||
1625 | } | ||
1626 | tcpm_pd_hard_reset(chip->tcpm_port); | ||
1627 | } | ||
1628 | |||
1629 | if (interruptb & FUSB_REG_INTERRUPTB_GCRCSENT) { | ||
1630 | fusb302_log(chip, "IRQ: PD sent good CRC"); | ||
1631 | ret = fusb302_pd_read_message(chip, &pd_msg); | ||
1632 | if (ret < 0) { | ||
1633 | fusb302_log(chip, | ||
1634 | "cannot read in PD message, ret=%d", ret); | ||
1635 | goto done; | ||
1636 | } | ||
1637 | tcpm_pd_receive(chip->tcpm_port, &pd_msg); | ||
1638 | } | ||
1639 | done: | ||
1640 | mutex_unlock(&chip->lock); | ||
1641 | |||
1642 | return IRQ_HANDLED; | ||
1643 | } | ||
1644 | |||
1645 | static int init_gpio(struct fusb302_chip *chip) | ||
1646 | { | ||
1647 | struct device_node *node; | ||
1648 | int ret = 0; | ||
1649 | |||
1650 | node = chip->dev->of_node; | ||
1651 | chip->gpio_int_n = of_get_named_gpio(node, "fcs,int_n", 0); | ||
1652 | if (!gpio_is_valid(chip->gpio_int_n)) { | ||
1653 | ret = chip->gpio_int_n; | ||
1654 | fusb302_log(chip, "cannot get named GPIO Int_N, ret=%d", ret); | ||
1655 | return ret; | ||
1656 | } | ||
1657 | ret = devm_gpio_request(chip->dev, chip->gpio_int_n, "fcs,int_n"); | ||
1658 | if (ret < 0) { | ||
1659 | fusb302_log(chip, "cannot request GPIO Int_N, ret=%d", ret); | ||
1660 | return ret; | ||
1661 | } | ||
1662 | ret = gpio_direction_input(chip->gpio_int_n); | ||
1663 | if (ret < 0) { | ||
1664 | fusb302_log(chip, | ||
1665 | "cannot set GPIO Int_N to input, ret=%d", ret); | ||
1666 | gpio_free(chip->gpio_int_n); | ||
1667 | return ret; | ||
1668 | } | ||
1669 | ret = gpio_to_irq(chip->gpio_int_n); | ||
1670 | if (ret < 0) { | ||
1671 | fusb302_log(chip, | ||
1672 | "cannot request IRQ for GPIO Int_N, ret=%d", ret); | ||
1673 | gpio_free(chip->gpio_int_n); | ||
1674 | return ret; | ||
1675 | } | ||
1676 | chip->gpio_int_n_irq = ret; | ||
1677 | return 0; | ||
1678 | } | ||
1679 | |||
1680 | static int fusb302_probe(struct i2c_client *client, | ||
1681 | const struct i2c_device_id *id) | ||
1682 | { | ||
1683 | struct fusb302_chip *chip; | ||
1684 | struct i2c_adapter *adapter; | ||
1685 | int ret = 0; | ||
1686 | |||
1687 | adapter = to_i2c_adapter(client->dev.parent); | ||
1688 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { | ||
1689 | dev_err(&client->dev, | ||
1690 | "I2C/SMBus block functionality not supported!\n"); | ||
1691 | return -ENODEV; | ||
1692 | } | ||
1693 | chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); | ||
1694 | if (!chip) | ||
1695 | return -ENOMEM; | ||
1696 | |||
1697 | chip->i2c_client = client; | ||
1698 | i2c_set_clientdata(client, chip); | ||
1699 | chip->dev = &client->dev; | ||
1700 | mutex_init(&chip->lock); | ||
1701 | |||
1702 | ret = fusb302_debugfs_init(chip); | ||
1703 | if (ret < 0) | ||
1704 | return ret; | ||
1705 | |||
1706 | chip->wq = create_singlethread_workqueue(dev_name(chip->dev)); | ||
1707 | if (!chip->wq) { | ||
1708 | ret = -ENOMEM; | ||
1709 | goto clear_client_data; | ||
1710 | } | ||
1711 | INIT_DELAYED_WORK(&chip->bc_lvl_handler, fusb302_bc_lvl_handler_work); | ||
1712 | init_tcpc_dev(&chip->tcpc_dev); | ||
1713 | |||
1714 | chip->vbus = devm_regulator_get(chip->dev, "vbus"); | ||
1715 | if (IS_ERR(chip->vbus)) { | ||
1716 | ret = PTR_ERR(chip->vbus); | ||
1717 | goto destroy_workqueue; | ||
1718 | } | ||
1719 | |||
1720 | ret = init_gpio(chip); | ||
1721 | if (ret < 0) | ||
1722 | goto destroy_workqueue; | ||
1723 | |||
1724 | chip->tcpm_port = tcpm_register_port(&client->dev, &chip->tcpc_dev); | ||
1725 | if (IS_ERR(chip->tcpm_port)) { | ||
1726 | ret = PTR_ERR(chip->tcpm_port); | ||
1727 | fusb302_log(chip, "cannot register tcpm port, ret=%d", ret); | ||
1728 | goto destroy_workqueue; | ||
1729 | } | ||
1730 | |||
1731 | ret = devm_request_threaded_irq(chip->dev, chip->gpio_int_n_irq, | ||
1732 | NULL, fusb302_irq_intn, | ||
1733 | IRQF_ONESHOT | IRQF_TRIGGER_LOW, | ||
1734 | "fsc_interrupt_int_n", chip); | ||
1735 | if (ret < 0) { | ||
1736 | fusb302_log(chip, | ||
1737 | "cannot request IRQ for GPIO Int_N, ret=%d", ret); | ||
1738 | goto tcpm_unregister_port; | ||
1739 | } | ||
1740 | enable_irq_wake(chip->gpio_int_n_irq); | ||
1741 | return ret; | ||
1742 | |||
1743 | tcpm_unregister_port: | ||
1744 | tcpm_unregister_port(chip->tcpm_port); | ||
1745 | destroy_workqueue: | ||
1746 | destroy_workqueue(chip->wq); | ||
1747 | clear_client_data: | ||
1748 | i2c_set_clientdata(client, NULL); | ||
1749 | fusb302_debugfs_exit(chip); | ||
1750 | |||
1751 | return ret; | ||
1752 | } | ||
1753 | |||
1754 | static int fusb302_remove(struct i2c_client *client) | ||
1755 | { | ||
1756 | struct fusb302_chip *chip = i2c_get_clientdata(client); | ||
1757 | |||
1758 | tcpm_unregister_port(chip->tcpm_port); | ||
1759 | destroy_workqueue(chip->wq); | ||
1760 | i2c_set_clientdata(client, NULL); | ||
1761 | fusb302_debugfs_exit(chip); | ||
1762 | |||
1763 | return 0; | ||
1764 | } | ||
1765 | |||
1766 | static int fusb302_pm_suspend(struct device *dev) | ||
1767 | { | ||
1768 | struct fusb302_chip *chip = dev->driver_data; | ||
1769 | |||
1770 | if (atomic_read(&chip->i2c_busy)) | ||
1771 | return -EBUSY; | ||
1772 | atomic_set(&chip->pm_suspend, 1); | ||
1773 | |||
1774 | return 0; | ||
1775 | } | ||
1776 | |||
1777 | static int fusb302_pm_resume(struct device *dev) | ||
1778 | { | ||
1779 | struct fusb302_chip *chip = dev->driver_data; | ||
1780 | |||
1781 | atomic_set(&chip->pm_suspend, 0); | ||
1782 | |||
1783 | return 0; | ||
1784 | } | ||
1785 | |||
1786 | static const struct of_device_id fusb302_dt_match[] = { | ||
1787 | {.compatible = "fcs,fusb302"}, | ||
1788 | {}, | ||
1789 | }; | ||
1790 | |||
1791 | static const struct i2c_device_id fusb302_i2c_device_id[] = { | ||
1792 | {"typec_fusb302", 0}, | ||
1793 | {}, | ||
1794 | }; | ||
1795 | |||
1796 | static const struct dev_pm_ops fusb302_pm_ops = { | ||
1797 | .suspend = fusb302_pm_suspend, | ||
1798 | .resume = fusb302_pm_resume, | ||
1799 | }; | ||
1800 | |||
1801 | static struct i2c_driver fusb302_driver = { | ||
1802 | .driver = { | ||
1803 | .name = "typec_fusb302", | ||
1804 | .pm = &fusb302_pm_ops, | ||
1805 | .of_match_table = of_match_ptr(fusb302_dt_match), | ||
1806 | }, | ||
1807 | .probe = fusb302_probe, | ||
1808 | .remove = fusb302_remove, | ||
1809 | .id_table = fusb302_i2c_device_id, | ||
1810 | }; | ||
1811 | module_i2c_driver(fusb302_driver); | ||
1812 | |||
1813 | MODULE_AUTHOR("Yueyao Zhu <yueyao.zhu@gmail.com>"); | ||
1814 | MODULE_DESCRIPTION("Fairchild FUSB302 Type-C Chip Driver"); | ||
1815 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/staging/typec/fusb302/fusb302_reg.h b/drivers/staging/typec/fusb302/fusb302_reg.h new file mode 100644 index 000000000000..0682e63de773 --- /dev/null +++ b/drivers/staging/typec/fusb302/fusb302_reg.h | |||
@@ -0,0 +1,186 @@ | |||
1 | /* | ||
2 | * Copyright 2016-2017 Google, Inc | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * Fairchild FUSB302 Type-C Chip Driver | ||
15 | */ | ||
16 | |||
17 | #ifndef FUSB302_REG_H | ||
18 | #define FUSB302_REG_H | ||
19 | |||
20 | #define FUSB_REG_DEVICE_ID 0x01 | ||
21 | #define FUSB_REG_SWITCHES0 0x02 | ||
22 | #define FUSB_REG_SWITCHES0_CC2_PU_EN BIT(7) | ||
23 | #define FUSB_REG_SWITCHES0_CC1_PU_EN BIT(6) | ||
24 | #define FUSB_REG_SWITCHES0_VCONN_CC2 BIT(5) | ||
25 | #define FUSB_REG_SWITCHES0_VCONN_CC1 BIT(4) | ||
26 | #define FUSB_REG_SWITCHES0_MEAS_CC2 BIT(3) | ||
27 | #define FUSB_REG_SWITCHES0_MEAS_CC1 BIT(2) | ||
28 | #define FUSB_REG_SWITCHES0_CC2_PD_EN BIT(1) | ||
29 | #define FUSB_REG_SWITCHES0_CC1_PD_EN BIT(0) | ||
30 | #define FUSB_REG_SWITCHES1 0x03 | ||
31 | #define FUSB_REG_SWITCHES1_POWERROLE BIT(7) | ||
32 | #define FUSB_REG_SWITCHES1_SPECREV1 BIT(6) | ||
33 | #define FUSB_REG_SWITCHES1_SPECREV0 BIT(5) | ||
34 | #define FUSB_REG_SWITCHES1_DATAROLE BIT(4) | ||
35 | #define FUSB_REG_SWITCHES1_AUTO_GCRC BIT(2) | ||
36 | #define FUSB_REG_SWITCHES1_TXCC2_EN BIT(1) | ||
37 | #define FUSB_REG_SWITCHES1_TXCC1_EN BIT(0) | ||
38 | #define FUSB_REG_MEASURE 0x04 | ||
39 | #define FUSB_REG_MEASURE_MDAC5 BIT(7) | ||
40 | #define FUSB_REG_MEASURE_MDAC4 BIT(6) | ||
41 | #define FUSB_REG_MEASURE_MDAC3 BIT(5) | ||
42 | #define FUSB_REG_MEASURE_MDAC2 BIT(4) | ||
43 | #define FUSB_REG_MEASURE_MDAC1 BIT(3) | ||
44 | #define FUSB_REG_MEASURE_MDAC0 BIT(2) | ||
45 | #define FUSB_REG_MEASURE_VBUS BIT(1) | ||
46 | #define FUSB_REG_MEASURE_XXXX5 BIT(0) | ||
47 | #define FUSB_REG_CONTROL0 0x06 | ||
48 | #define FUSB_REG_CONTROL0_TX_FLUSH BIT(6) | ||
49 | #define FUSB_REG_CONTROL0_INT_MASK BIT(5) | ||
50 | #define FUSB_REG_CONTROL0_HOST_CUR_MASK (0xC) | ||
51 | #define FUSB_REG_CONTROL0_HOST_CUR_HIGH (0xC) | ||
52 | #define FUSB_REG_CONTROL0_HOST_CUR_MED (0x8) | ||
53 | #define FUSB_REG_CONTROL0_HOST_CUR_DEF (0x4) | ||
54 | #define FUSB_REG_CONTROL0_TX_START BIT(0) | ||
55 | #define FUSB_REG_CONTROL1 0x07 | ||
56 | #define FUSB_REG_CONTROL1_ENSOP2DB BIT(6) | ||
57 | #define FUSB_REG_CONTROL1_ENSOP1DB BIT(5) | ||
58 | #define FUSB_REG_CONTROL1_BIST_MODE2 BIT(4) | ||
59 | #define FUSB_REG_CONTROL1_RX_FLUSH BIT(2) | ||
60 | #define FUSB_REG_CONTROL1_ENSOP2 BIT(1) | ||
61 | #define FUSB_REG_CONTROL1_ENSOP1 BIT(0) | ||
62 | #define FUSB_REG_CONTROL2 0x08 | ||
63 | #define FUSB_REG_CONTROL2_MODE BIT(1) | ||
64 | #define FUSB_REG_CONTROL2_MODE_MASK (0x6) | ||
65 | #define FUSB_REG_CONTROL2_MODE_DFP (0x6) | ||
66 | #define FUSB_REG_CONTROL2_MODE_UFP (0x4) | ||
67 | #define FUSB_REG_CONTROL2_MODE_DRP (0x2) | ||
68 | #define FUSB_REG_CONTROL2_MODE_NONE (0x0) | ||
69 | #define FUSB_REG_CONTROL2_TOGGLE BIT(0) | ||
70 | #define FUSB_REG_CONTROL3 0x09 | ||
71 | #define FUSB_REG_CONTROL3_SEND_HARDRESET BIT(6) | ||
72 | #define FUSB_REG_CONTROL3_BIST_TMODE BIT(5) /* 302B Only */ | ||
73 | #define FUSB_REG_CONTROL3_AUTO_HARDRESET BIT(4) | ||
74 | #define FUSB_REG_CONTROL3_AUTO_SOFTRESET BIT(3) | ||
75 | #define FUSB_REG_CONTROL3_N_RETRIES BIT(1) | ||
76 | #define FUSB_REG_CONTROL3_N_RETRIES_MASK (0x6) | ||
77 | #define FUSB_REG_CONTROL3_N_RETRIES_3 (0x6) | ||
78 | #define FUSB_REG_CONTROL3_N_RETRIES_2 (0x4) | ||
79 | #define FUSB_REG_CONTROL3_N_RETRIES_1 (0x2) | ||
80 | #define FUSB_REG_CONTROL3_AUTO_RETRY BIT(0) | ||
81 | #define FUSB_REG_MASK 0x0A | ||
82 | #define FUSB_REG_MASK_VBUSOK BIT(7) | ||
83 | #define FUSB_REG_MASK_ACTIVITY BIT(6) | ||
84 | #define FUSB_REG_MASK_COMP_CHNG BIT(5) | ||
85 | #define FUSB_REG_MASK_CRC_CHK BIT(4) | ||
86 | #define FUSB_REG_MASK_ALERT BIT(3) | ||
87 | #define FUSB_REG_MASK_WAKE BIT(2) | ||
88 | #define FUSB_REG_MASK_COLLISION BIT(1) | ||
89 | #define FUSB_REG_MASK_BC_LVL BIT(0) | ||
90 | #define FUSB_REG_POWER 0x0B | ||
91 | #define FUSB_REG_POWER_PWR BIT(0) | ||
92 | #define FUSB_REG_POWER_PWR_LOW 0x1 | ||
93 | #define FUSB_REG_POWER_PWR_MEDIUM 0x3 | ||
94 | #define FUSB_REG_POWER_PWR_HIGH 0x7 | ||
95 | #define FUSB_REG_POWER_PWR_ALL 0xF | ||
96 | #define FUSB_REG_RESET 0x0C | ||
97 | #define FUSB_REG_RESET_PD_RESET BIT(1) | ||
98 | #define FUSB_REG_RESET_SW_RESET BIT(0) | ||
99 | #define FUSB_REG_MASKA 0x0E | ||
100 | #define FUSB_REG_MASKA_OCP_TEMP BIT(7) | ||
101 | #define FUSB_REG_MASKA_TOGDONE BIT(6) | ||
102 | #define FUSB_REG_MASKA_SOFTFAIL BIT(5) | ||
103 | #define FUSB_REG_MASKA_RETRYFAIL BIT(4) | ||
104 | #define FUSB_REG_MASKA_HARDSENT BIT(3) | ||
105 | #define FUSB_REG_MASKA_TX_SUCCESS BIT(2) | ||
106 | #define FUSB_REG_MASKA_SOFTRESET BIT(1) | ||
107 | #define FUSB_REG_MASKA_HARDRESET BIT(0) | ||
108 | #define FUSB_REG_MASKB 0x0F | ||
109 | #define FUSB_REG_MASKB_GCRCSENT BIT(0) | ||
110 | #define FUSB_REG_STATUS0A 0x3C | ||
111 | #define FUSB_REG_STATUS0A_SOFTFAIL BIT(5) | ||
112 | #define FUSB_REG_STATUS0A_RETRYFAIL BIT(4) | ||
113 | #define FUSB_REG_STATUS0A_POWER BIT(2) | ||
114 | #define FUSB_REG_STATUS0A_RX_SOFT_RESET BIT(1) | ||
115 | #define FUSB_REG_STATUS0A_RX_HARD_RESET BIT(0) | ||
116 | #define FUSB_REG_STATUS1A 0x3D | ||
117 | #define FUSB_REG_STATUS1A_TOGSS BIT(3) | ||
118 | #define FUSB_REG_STATUS1A_TOGSS_RUNNING 0x0 | ||
119 | #define FUSB_REG_STATUS1A_TOGSS_SRC1 0x1 | ||
120 | #define FUSB_REG_STATUS1A_TOGSS_SRC2 0x2 | ||
121 | #define FUSB_REG_STATUS1A_TOGSS_SNK1 0x5 | ||
122 | #define FUSB_REG_STATUS1A_TOGSS_SNK2 0x6 | ||
123 | #define FUSB_REG_STATUS1A_TOGSS_AA 0x7 | ||
124 | #define FUSB_REG_STATUS1A_TOGSS_POS (3) | ||
125 | #define FUSB_REG_STATUS1A_TOGSS_MASK (0x7) | ||
126 | #define FUSB_REG_STATUS1A_RXSOP2DB BIT(2) | ||
127 | #define FUSB_REG_STATUS1A_RXSOP1DB BIT(1) | ||
128 | #define FUSB_REG_STATUS1A_RXSOP BIT(0) | ||
129 | #define FUSB_REG_INTERRUPTA 0x3E | ||
130 | #define FUSB_REG_INTERRUPTA_OCP_TEMP BIT(7) | ||
131 | #define FUSB_REG_INTERRUPTA_TOGDONE BIT(6) | ||
132 | #define FUSB_REG_INTERRUPTA_SOFTFAIL BIT(5) | ||
133 | #define FUSB_REG_INTERRUPTA_RETRYFAIL BIT(4) | ||
134 | #define FUSB_REG_INTERRUPTA_HARDSENT BIT(3) | ||
135 | #define FUSB_REG_INTERRUPTA_TX_SUCCESS BIT(2) | ||
136 | #define FUSB_REG_INTERRUPTA_SOFTRESET BIT(1) | ||
137 | #define FUSB_REG_INTERRUPTA_HARDRESET BIT(0) | ||
138 | #define FUSB_REG_INTERRUPTB 0x3F | ||
139 | #define FUSB_REG_INTERRUPTB_GCRCSENT BIT(0) | ||
140 | #define FUSB_REG_STATUS0 0x40 | ||
141 | #define FUSB_REG_STATUS0_VBUSOK BIT(7) | ||
142 | #define FUSB_REG_STATUS0_ACTIVITY BIT(6) | ||
143 | #define FUSB_REG_STATUS0_COMP BIT(5) | ||
144 | #define FUSB_REG_STATUS0_CRC_CHK BIT(4) | ||
145 | #define FUSB_REG_STATUS0_ALERT BIT(3) | ||
146 | #define FUSB_REG_STATUS0_WAKE BIT(2) | ||
147 | #define FUSB_REG_STATUS0_BC_LVL_MASK 0x03 | ||
148 | #define FUSB_REG_STATUS0_BC_LVL_0_200 0x0 | ||
149 | #define FUSB_REG_STATUS0_BC_LVL_200_600 0x1 | ||
150 | #define FUSB_REG_STATUS0_BC_LVL_600_1230 0x2 | ||
151 | #define FUSB_REG_STATUS0_BC_LVL_1230_MAX 0x3 | ||
152 | #define FUSB_REG_STATUS0_BC_LVL1 BIT(1) | ||
153 | #define FUSB_REG_STATUS0_BC_LVL0 BIT(0) | ||
154 | #define FUSB_REG_STATUS1 0x41 | ||
155 | #define FUSB_REG_STATUS1_RXSOP2 BIT(7) | ||
156 | #define FUSB_REG_STATUS1_RXSOP1 BIT(6) | ||
157 | #define FUSB_REG_STATUS1_RX_EMPTY BIT(5) | ||
158 | #define FUSB_REG_STATUS1_RX_FULL BIT(4) | ||
159 | #define FUSB_REG_STATUS1_TX_EMPTY BIT(3) | ||
160 | #define FUSB_REG_STATUS1_TX_FULL BIT(2) | ||
161 | #define FUSB_REG_INTERRUPT 0x42 | ||
162 | #define FUSB_REG_INTERRUPT_VBUSOK BIT(7) | ||
163 | #define FUSB_REG_INTERRUPT_ACTIVITY BIT(6) | ||
164 | #define FUSB_REG_INTERRUPT_COMP_CHNG BIT(5) | ||
165 | #define FUSB_REG_INTERRUPT_CRC_CHK BIT(4) | ||
166 | #define FUSB_REG_INTERRUPT_ALERT BIT(3) | ||
167 | #define FUSB_REG_INTERRUPT_WAKE BIT(2) | ||
168 | #define FUSB_REG_INTERRUPT_COLLISION BIT(1) | ||
169 | #define FUSB_REG_INTERRUPT_BC_LVL BIT(0) | ||
170 | #define FUSB_REG_FIFOS 0x43 | ||
171 | |||
172 | /* Tokens defined for the FUSB302 TX FIFO */ | ||
173 | enum fusb302_txfifo_tokens { | ||
174 | FUSB302_TKN_TXON = 0xA1, | ||
175 | FUSB302_TKN_SYNC1 = 0x12, | ||
176 | FUSB302_TKN_SYNC2 = 0x13, | ||
177 | FUSB302_TKN_SYNC3 = 0x1B, | ||
178 | FUSB302_TKN_RST1 = 0x15, | ||
179 | FUSB302_TKN_RST2 = 0x16, | ||
180 | FUSB302_TKN_PACKSYM = 0x80, | ||
181 | FUSB302_TKN_JAMCRC = 0xFF, | ||
182 | FUSB302_TKN_EOP = 0x14, | ||
183 | FUSB302_TKN_TXOFF = 0xFE, | ||
184 | }; | ||
185 | |||
186 | #endif | ||
diff --git a/drivers/staging/typec/pd.h b/drivers/staging/typec/pd.h new file mode 100644 index 000000000000..8d97bdb95f23 --- /dev/null +++ b/drivers/staging/typec/pd.h | |||
@@ -0,0 +1,281 @@ | |||
1 | /* | ||
2 | * Copyright 2015-2017 Google, Inc | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | */ | ||
14 | |||
15 | #ifndef __LINUX_USB_PD_H | ||
16 | #define __LINUX_USB_PD_H | ||
17 | |||
18 | #include <linux/types.h> | ||
19 | #include <linux/usb/typec.h> | ||
20 | |||
21 | /* USB PD Messages */ | ||
22 | enum pd_ctrl_msg_type { | ||
23 | /* 0 Reserved */ | ||
24 | PD_CTRL_GOOD_CRC = 1, | ||
25 | PD_CTRL_GOTO_MIN = 2, | ||
26 | PD_CTRL_ACCEPT = 3, | ||
27 | PD_CTRL_REJECT = 4, | ||
28 | PD_CTRL_PING = 5, | ||
29 | PD_CTRL_PS_RDY = 6, | ||
30 | PD_CTRL_GET_SOURCE_CAP = 7, | ||
31 | PD_CTRL_GET_SINK_CAP = 8, | ||
32 | PD_CTRL_DR_SWAP = 9, | ||
33 | PD_CTRL_PR_SWAP = 10, | ||
34 | PD_CTRL_VCONN_SWAP = 11, | ||
35 | PD_CTRL_WAIT = 12, | ||
36 | PD_CTRL_SOFT_RESET = 13, | ||
37 | /* 14-15 Reserved */ | ||
38 | }; | ||
39 | |||
40 | enum pd_data_msg_type { | ||
41 | /* 0 Reserved */ | ||
42 | PD_DATA_SOURCE_CAP = 1, | ||
43 | PD_DATA_REQUEST = 2, | ||
44 | PD_DATA_BIST = 3, | ||
45 | PD_DATA_SINK_CAP = 4, | ||
46 | /* 5-14 Reserved */ | ||
47 | PD_DATA_VENDOR_DEF = 15, | ||
48 | }; | ||
49 | |||
50 | #define PD_REV10 0x0 | ||
51 | #define PD_REV20 0x1 | ||
52 | |||
53 | #define PD_HEADER_CNT_SHIFT 12 | ||
54 | #define PD_HEADER_CNT_MASK 0x7 | ||
55 | #define PD_HEADER_ID_SHIFT 9 | ||
56 | #define PD_HEADER_ID_MASK 0x7 | ||
57 | #define PD_HEADER_PWR_ROLE BIT(8) | ||
58 | #define PD_HEADER_REV_SHIFT 6 | ||
59 | #define PD_HEADER_REV_MASK 0x3 | ||
60 | #define PD_HEADER_DATA_ROLE BIT(5) | ||
61 | #define PD_HEADER_TYPE_SHIFT 0 | ||
62 | #define PD_HEADER_TYPE_MASK 0xf | ||
63 | |||
64 | #define PD_HEADER(type, pwr, data, id, cnt) \ | ||
65 | ((((type) & PD_HEADER_TYPE_MASK) << PD_HEADER_TYPE_SHIFT) | \ | ||
66 | ((pwr) == TYPEC_SOURCE ? PD_HEADER_PWR_ROLE : 0) | \ | ||
67 | ((data) == TYPEC_HOST ? PD_HEADER_DATA_ROLE : 0) | \ | ||
68 | (PD_REV20 << PD_HEADER_REV_SHIFT) | \ | ||
69 | (((id) & PD_HEADER_ID_MASK) << PD_HEADER_ID_SHIFT) | \ | ||
70 | (((cnt) & PD_HEADER_CNT_MASK) << PD_HEADER_CNT_SHIFT)) | ||
71 | |||
72 | #define PD_HEADER_LE(type, pwr, data, id, cnt) \ | ||
73 | cpu_to_le16(PD_HEADER((type), (pwr), (data), (id), (cnt))) | ||
74 | |||
75 | static inline unsigned int pd_header_cnt(u16 header) | ||
76 | { | ||
77 | return (header >> PD_HEADER_CNT_SHIFT) & PD_HEADER_CNT_MASK; | ||
78 | } | ||
79 | |||
80 | static inline unsigned int pd_header_cnt_le(__le16 header) | ||
81 | { | ||
82 | return pd_header_cnt(le16_to_cpu(header)); | ||
83 | } | ||
84 | |||
85 | static inline unsigned int pd_header_type(u16 header) | ||
86 | { | ||
87 | return (header >> PD_HEADER_TYPE_SHIFT) & PD_HEADER_TYPE_MASK; | ||
88 | } | ||
89 | |||
90 | static inline unsigned int pd_header_type_le(__le16 header) | ||
91 | { | ||
92 | return pd_header_type(le16_to_cpu(header)); | ||
93 | } | ||
94 | |||
95 | #define PD_MAX_PAYLOAD 7 | ||
96 | |||
97 | struct pd_message { | ||
98 | __le16 header; | ||
99 | __le32 payload[PD_MAX_PAYLOAD]; | ||
100 | } __packed; | ||
101 | |||
102 | /* PDO: Power Data Object */ | ||
103 | #define PDO_MAX_OBJECTS 7 | ||
104 | |||
105 | enum pd_pdo_type { | ||
106 | PDO_TYPE_FIXED = 0, | ||
107 | PDO_TYPE_BATT = 1, | ||
108 | PDO_TYPE_VAR = 2, | ||
109 | }; | ||
110 | |||
111 | #define PDO_TYPE_SHIFT 30 | ||
112 | #define PDO_TYPE_MASK 0x3 | ||
113 | |||
114 | #define PDO_TYPE(t) ((t) << PDO_TYPE_SHIFT) | ||
115 | |||
116 | #define PDO_VOLT_MASK 0x3ff | ||
117 | #define PDO_CURR_MASK 0x3ff | ||
118 | #define PDO_PWR_MASK 0x3ff | ||
119 | |||
120 | #define PDO_FIXED_DUAL_ROLE BIT(29) /* Power role swap supported */ | ||
121 | #define PDO_FIXED_SUSPEND BIT(28) /* USB Suspend supported (Source) */ | ||
122 | #define PDO_FIXED_HIGHER_CAP BIT(28) /* Requires more than vSafe5V (Sink) */ | ||
123 | #define PDO_FIXED_EXTPOWER BIT(27) /* Externally powered */ | ||
124 | #define PDO_FIXED_USB_COMM BIT(26) /* USB communications capable */ | ||
125 | #define PDO_FIXED_DATA_SWAP BIT(25) /* Data role swap supported */ | ||
126 | #define PDO_FIXED_VOLT_SHIFT 10 /* 50mV units */ | ||
127 | #define PDO_FIXED_CURR_SHIFT 0 /* 10mA units */ | ||
128 | |||
129 | #define PDO_FIXED_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_FIXED_VOLT_SHIFT) | ||
130 | #define PDO_FIXED_CURR(ma) ((((ma) / 10) & PDO_CURR_MASK) << PDO_FIXED_CURR_SHIFT) | ||
131 | |||
132 | #define PDO_FIXED(mv, ma, flags) \ | ||
133 | (PDO_TYPE(PDO_TYPE_FIXED) | (flags) | \ | ||
134 | PDO_FIXED_VOLT(mv) | PDO_FIXED_CURR(ma)) | ||
135 | |||
136 | #define PDO_BATT_MAX_VOLT_SHIFT 20 /* 50mV units */ | ||
137 | #define PDO_BATT_MIN_VOLT_SHIFT 10 /* 50mV units */ | ||
138 | #define PDO_BATT_MAX_PWR_SHIFT 0 /* 250mW units */ | ||
139 | |||
140 | #define PDO_BATT_MIN_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_BATT_MIN_VOLT_SHIFT) | ||
141 | #define PDO_BATT_MAX_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_BATT_MAX_VOLT_SHIFT) | ||
142 | #define PDO_BATT_MAX_POWER(mw) ((((mw) / 250) & PDO_PWR_MASK) << PDO_BATT_MAX_PWR_SHIFT) | ||
143 | |||
144 | #define PDO_BATT(min_mv, max_mv, max_mw) \ | ||
145 | (PDO_TYPE(PDO_TYPE_BATT) | PDO_BATT_MIN_VOLT(min_mv) | \ | ||
146 | PDO_BATT_MAX_VOLT(max_mv) | PDO_BATT_MAX_POWER(max_mw)) | ||
147 | |||
148 | #define PDO_VAR_MAX_VOLT_SHIFT 20 /* 50mV units */ | ||
149 | #define PDO_VAR_MIN_VOLT_SHIFT 10 /* 50mV units */ | ||
150 | #define PDO_VAR_MAX_CURR_SHIFT 0 /* 10mA units */ | ||
151 | |||
152 | #define PDO_VAR_MIN_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_VAR_MIN_VOLT_SHIFT) | ||
153 | #define PDO_VAR_MAX_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_VAR_MAX_VOLT_SHIFT) | ||
154 | #define PDO_VAR_MAX_CURR(ma) ((((ma) / 10) & PDO_CURR_MASK) << PDO_VAR_MAX_CURR_SHIFT) | ||
155 | |||
156 | #define PDO_VAR(min_mv, max_mv, max_ma) \ | ||
157 | (PDO_TYPE(PDO_TYPE_VAR) | PDO_VAR_MIN_VOLT(min_mv) | \ | ||
158 | PDO_VAR_MAX_VOLT(max_mv) | PDO_VAR_MAX_CURR(max_ma)) | ||
159 | |||
160 | static inline enum pd_pdo_type pdo_type(u32 pdo) | ||
161 | { | ||
162 | return (pdo >> PDO_TYPE_SHIFT) & PDO_TYPE_MASK; | ||
163 | } | ||
164 | |||
165 | static inline unsigned int pdo_fixed_voltage(u32 pdo) | ||
166 | { | ||
167 | return ((pdo >> PDO_FIXED_VOLT_SHIFT) & PDO_VOLT_MASK) * 50; | ||
168 | } | ||
169 | |||
170 | static inline unsigned int pdo_min_voltage(u32 pdo) | ||
171 | { | ||
172 | return ((pdo >> PDO_VAR_MIN_VOLT_SHIFT) & PDO_VOLT_MASK) * 50; | ||
173 | } | ||
174 | |||
175 | static inline unsigned int pdo_max_voltage(u32 pdo) | ||
176 | { | ||
177 | return ((pdo >> PDO_VAR_MAX_VOLT_SHIFT) & PDO_VOLT_MASK) * 50; | ||
178 | } | ||
179 | |||
180 | static inline unsigned int pdo_max_current(u32 pdo) | ||
181 | { | ||
182 | return ((pdo >> PDO_VAR_MAX_CURR_SHIFT) & PDO_CURR_MASK) * 10; | ||
183 | } | ||
184 | |||
185 | static inline unsigned int pdo_max_power(u32 pdo) | ||
186 | { | ||
187 | return ((pdo >> PDO_BATT_MAX_PWR_SHIFT) & PDO_PWR_MASK) * 250; | ||
188 | } | ||
189 | |||
190 | /* RDO: Request Data Object */ | ||
191 | #define RDO_OBJ_POS_SHIFT 28 | ||
192 | #define RDO_OBJ_POS_MASK 0x7 | ||
193 | #define RDO_GIVE_BACK BIT(27) /* Supports reduced operating current */ | ||
194 | #define RDO_CAP_MISMATCH BIT(26) /* Not satisfied by source caps */ | ||
195 | #define RDO_USB_COMM BIT(25) /* USB communications capable */ | ||
196 | #define RDO_NO_SUSPEND BIT(24) /* USB Suspend not supported */ | ||
197 | |||
198 | #define RDO_PWR_MASK 0x3ff | ||
199 | #define RDO_CURR_MASK 0x3ff | ||
200 | |||
201 | #define RDO_FIXED_OP_CURR_SHIFT 10 | ||
202 | #define RDO_FIXED_MAX_CURR_SHIFT 0 | ||
203 | |||
204 | #define RDO_OBJ(idx) (((idx) & RDO_OBJ_POS_MASK) << RDO_OBJ_POS_SHIFT) | ||
205 | |||
206 | #define PDO_FIXED_OP_CURR(ma) ((((ma) / 10) & RDO_CURR_MASK) << RDO_FIXED_OP_CURR_SHIFT) | ||
207 | #define PDO_FIXED_MAX_CURR(ma) ((((ma) / 10) & RDO_CURR_MASK) << RDO_FIXED_MAX_CURR_SHIFT) | ||
208 | |||
209 | #define RDO_FIXED(idx, op_ma, max_ma, flags) \ | ||
210 | (RDO_OBJ(idx) | (flags) | \ | ||
211 | PDO_FIXED_OP_CURR(op_ma) | PDO_FIXED_MAX_CURR(max_ma)) | ||
212 | |||
213 | #define RDO_BATT_OP_PWR_SHIFT 10 /* 250mW units */ | ||
214 | #define RDO_BATT_MAX_PWR_SHIFT 0 /* 250mW units */ | ||
215 | |||
216 | #define RDO_BATT_OP_PWR(mw) ((((mw) / 250) & RDO_PWR_MASK) << RDO_BATT_OP_PWR_SHIFT) | ||
217 | #define RDO_BATT_MAX_PWR(mw) ((((mw) / 250) & RDO_PWR_MASK) << RDO_BATT_MAX_PWR_SHIFT) | ||
218 | |||
219 | #define RDO_BATT(idx, op_mw, max_mw, flags) \ | ||
220 | (RDO_OBJ(idx) | (flags) | \ | ||
221 | RDO_BATT_OP_PWR(op_mw) | RDO_BATT_MAX_PWR(max_mw)) | ||
222 | |||
223 | static inline unsigned int rdo_index(u32 rdo) | ||
224 | { | ||
225 | return (rdo >> RDO_OBJ_POS_SHIFT) & RDO_OBJ_POS_MASK; | ||
226 | } | ||
227 | |||
228 | static inline unsigned int rdo_op_current(u32 rdo) | ||
229 | { | ||
230 | return ((rdo >> RDO_FIXED_OP_CURR_SHIFT) & RDO_CURR_MASK) * 10; | ||
231 | } | ||
232 | |||
233 | static inline unsigned int rdo_max_current(u32 rdo) | ||
234 | { | ||
235 | return ((rdo >> RDO_FIXED_MAX_CURR_SHIFT) & | ||
236 | RDO_CURR_MASK) * 10; | ||
237 | } | ||
238 | |||
239 | static inline unsigned int rdo_op_power(u32 rdo) | ||
240 | { | ||
241 | return ((rdo >> RDO_BATT_OP_PWR_SHIFT) & RDO_PWR_MASK) * 250; | ||
242 | } | ||
243 | |||
244 | static inline unsigned int rdo_max_power(u32 rdo) | ||
245 | { | ||
246 | return ((rdo >> RDO_BATT_MAX_PWR_SHIFT) & RDO_PWR_MASK) * 250; | ||
247 | } | ||
248 | |||
249 | /* USB PD timers and counters */ | ||
250 | #define PD_T_NO_RESPONSE 5000 /* 4.5 - 5.5 seconds */ | ||
251 | #define PD_T_DB_DETECT 10000 /* 10 - 15 seconds */ | ||
252 | #define PD_T_SEND_SOURCE_CAP 150 /* 100 - 200 ms */ | ||
253 | #define PD_T_SENDER_RESPONSE 60 /* 24 - 30 ms, relaxed */ | ||
254 | #define PD_T_SOURCE_ACTIVITY 45 | ||
255 | #define PD_T_SINK_ACTIVITY 135 | ||
256 | #define PD_T_SINK_WAIT_CAP 240 | ||
257 | #define PD_T_PS_TRANSITION 500 | ||
258 | #define PD_T_SRC_TRANSITION 35 | ||
259 | #define PD_T_DRP_SNK 40 | ||
260 | #define PD_T_DRP_SRC 30 | ||
261 | #define PD_T_PS_SOURCE_OFF 920 | ||
262 | #define PD_T_PS_SOURCE_ON 480 | ||
263 | #define PD_T_PS_HARD_RESET 30 | ||
264 | #define PD_T_SRC_RECOVER 760 | ||
265 | #define PD_T_SRC_RECOVER_MAX 1000 | ||
266 | #define PD_T_SRC_TURN_ON 275 | ||
267 | #define PD_T_SAFE_0V 650 | ||
268 | #define PD_T_VCONN_SOURCE_ON 100 | ||
269 | #define PD_T_SINK_REQUEST 100 /* 100 ms minimum */ | ||
270 | #define PD_T_ERROR_RECOVERY 100 /* minimum 25 is insufficient */ | ||
271 | |||
272 | #define PD_T_DRP_TRY 100 /* 75 - 150 ms */ | ||
273 | #define PD_T_DRP_TRYWAIT 600 /* 400 - 800 ms */ | ||
274 | |||
275 | #define PD_T_CC_DEBOUNCE 200 /* 100 - 200 ms */ | ||
276 | #define PD_T_PD_DEBOUNCE 20 /* 10 - 20 ms */ | ||
277 | |||
278 | #define PD_N_CAPS_COUNT (PD_T_NO_RESPONSE / PD_T_SEND_SOURCE_CAP) | ||
279 | #define PD_N_HARD_RESET_COUNT 2 | ||
280 | |||
281 | #endif /* __LINUX_USB_PD_H */ | ||
diff --git a/drivers/staging/typec/pd_bdo.h b/drivers/staging/typec/pd_bdo.h new file mode 100644 index 000000000000..90b94d9fea5d --- /dev/null +++ b/drivers/staging/typec/pd_bdo.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * Copyright 2015-2017 Google, Inc | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | */ | ||
14 | |||
15 | #ifndef __LINUX_USB_PD_BDO_H | ||
16 | #define __LINUX_USB_PD_BDO_H | ||
17 | |||
18 | /* BDO : BIST Data Object */ | ||
19 | #define BDO_MODE_RECV (0 << 28) | ||
20 | #define BDO_MODE_TRANSMIT (1 << 28) | ||
21 | #define BDO_MODE_COUNTERS (2 << 28) | ||
22 | #define BDO_MODE_CARRIER0 (3 << 28) | ||
23 | #define BDO_MODE_CARRIER1 (4 << 28) | ||
24 | #define BDO_MODE_CARRIER2 (5 << 28) | ||
25 | #define BDO_MODE_CARRIER3 (6 << 28) | ||
26 | #define BDO_MODE_EYE (7 << 28) | ||
27 | #define BDO_MODE_TESTDATA (8 << 28) | ||
28 | |||
29 | #define BDO_MODE_MASK(mode) ((mode) & 0xf0000000) | ||
30 | |||
31 | #endif | ||
diff --git a/drivers/staging/typec/pd_vdo.h b/drivers/staging/typec/pd_vdo.h new file mode 100644 index 000000000000..dba172e0e0d1 --- /dev/null +++ b/drivers/staging/typec/pd_vdo.h | |||
@@ -0,0 +1,249 @@ | |||
1 | /* | ||
2 | * Copyright 2015-2017 Google, Inc | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | */ | ||
14 | |||
15 | #ifndef __LINUX_USB_PD_VDO_H | ||
16 | #define __LINUX_USB_PD_VDO_H | ||
17 | |||
18 | #include "pd.h" | ||
19 | |||
20 | /* | ||
21 | * VDO : Vendor Defined Message Object | ||
22 | * VDM object is minimum of VDM header + 6 additional data objects. | ||
23 | */ | ||
24 | |||
25 | /* | ||
26 | * VDM header | ||
27 | * ---------- | ||
28 | * <31:16> :: SVID | ||
29 | * <15> :: VDM type ( 1b == structured, 0b == unstructured ) | ||
30 | * <14:13> :: Structured VDM version (can only be 00 == 1.0 currently) | ||
31 | * <12:11> :: reserved | ||
32 | * <10:8> :: object position (1-7 valid ... used for enter/exit mode only) | ||
33 | * <7:6> :: command type (SVDM only?) | ||
34 | * <5> :: reserved (SVDM), command type (UVDM) | ||
35 | * <4:0> :: command | ||
36 | */ | ||
37 | #define VDO_MAX_SIZE 7 | ||
38 | #define VDO(vid, type, custom) \ | ||
39 | (((vid) << 16) | \ | ||
40 | ((type) << 15) | \ | ||
41 | ((custom) & 0x7FFF)) | ||
42 | |||
43 | #define VDO_SVDM_TYPE (1 << 15) | ||
44 | #define VDO_SVDM_VERS(x) ((x) << 13) | ||
45 | #define VDO_OPOS(x) ((x) << 8) | ||
46 | #define VDO_CMDT(x) ((x) << 6) | ||
47 | #define VDO_OPOS_MASK VDO_OPOS(0x7) | ||
48 | #define VDO_CMDT_MASK VDO_CMDT(0x3) | ||
49 | |||
50 | #define CMDT_INIT 0 | ||
51 | #define CMDT_RSP_ACK 1 | ||
52 | #define CMDT_RSP_NAK 2 | ||
53 | #define CMDT_RSP_BUSY 3 | ||
54 | |||
55 | /* reserved for SVDM ... for Google UVDM */ | ||
56 | #define VDO_SRC_INITIATOR (0 << 5) | ||
57 | #define VDO_SRC_RESPONDER (1 << 5) | ||
58 | |||
59 | #define CMD_DISCOVER_IDENT 1 | ||
60 | #define CMD_DISCOVER_SVID 2 | ||
61 | #define CMD_DISCOVER_MODES 3 | ||
62 | #define CMD_ENTER_MODE 4 | ||
63 | #define CMD_EXIT_MODE 5 | ||
64 | #define CMD_ATTENTION 6 | ||
65 | |||
66 | #define VDO_CMD_VENDOR(x) (((10 + (x)) & 0x1f)) | ||
67 | |||
68 | /* ChromeOS specific commands */ | ||
69 | #define VDO_CMD_VERSION VDO_CMD_VENDOR(0) | ||
70 | #define VDO_CMD_SEND_INFO VDO_CMD_VENDOR(1) | ||
71 | #define VDO_CMD_READ_INFO VDO_CMD_VENDOR(2) | ||
72 | #define VDO_CMD_REBOOT VDO_CMD_VENDOR(5) | ||
73 | #define VDO_CMD_FLASH_ERASE VDO_CMD_VENDOR(6) | ||
74 | #define VDO_CMD_FLASH_WRITE VDO_CMD_VENDOR(7) | ||
75 | #define VDO_CMD_ERASE_SIG VDO_CMD_VENDOR(8) | ||
76 | #define VDO_CMD_PING_ENABLE VDO_CMD_VENDOR(10) | ||
77 | #define VDO_CMD_CURRENT VDO_CMD_VENDOR(11) | ||
78 | #define VDO_CMD_FLIP VDO_CMD_VENDOR(12) | ||
79 | #define VDO_CMD_GET_LOG VDO_CMD_VENDOR(13) | ||
80 | #define VDO_CMD_CCD_EN VDO_CMD_VENDOR(14) | ||
81 | |||
82 | #define PD_VDO_VID(vdo) ((vdo) >> 16) | ||
83 | #define PD_VDO_SVDM(vdo) (((vdo) >> 15) & 1) | ||
84 | #define PD_VDO_OPOS(vdo) (((vdo) >> 8) & 0x7) | ||
85 | #define PD_VDO_CMD(vdo) ((vdo) & 0x1f) | ||
86 | #define PD_VDO_CMDT(vdo) (((vdo) >> 6) & 0x3) | ||
87 | |||
88 | /* | ||
89 | * SVDM Identity request -> response | ||
90 | * | ||
91 | * Request is simply properly formatted SVDM header | ||
92 | * | ||
93 | * Response is 4 data objects: | ||
94 | * [0] :: SVDM header | ||
95 | * [1] :: Identitiy header | ||
96 | * [2] :: Cert Stat VDO | ||
97 | * [3] :: (Product | Cable) VDO | ||
98 | * [4] :: AMA VDO | ||
99 | * | ||
100 | */ | ||
101 | #define VDO_INDEX_HDR 0 | ||
102 | #define VDO_INDEX_IDH 1 | ||
103 | #define VDO_INDEX_CSTAT 2 | ||
104 | #define VDO_INDEX_CABLE 3 | ||
105 | #define VDO_INDEX_PRODUCT 3 | ||
106 | #define VDO_INDEX_AMA 4 | ||
107 | |||
108 | /* | ||
109 | * SVDM Identity Header | ||
110 | * -------------------- | ||
111 | * <31> :: data capable as a USB host | ||
112 | * <30> :: data capable as a USB device | ||
113 | * <29:27> :: product type | ||
114 | * <26> :: modal operation supported (1b == yes) | ||
115 | * <25:16> :: Reserved, Shall be set to zero | ||
116 | * <15:0> :: USB-IF assigned VID for this cable vendor | ||
117 | */ | ||
118 | #define IDH_PTYPE_UNDEF 0 | ||
119 | #define IDH_PTYPE_HUB 1 | ||
120 | #define IDH_PTYPE_PERIPH 2 | ||
121 | #define IDH_PTYPE_PCABLE 3 | ||
122 | #define IDH_PTYPE_ACABLE 4 | ||
123 | #define IDH_PTYPE_AMA 5 | ||
124 | |||
125 | #define VDO_IDH(usbh, usbd, ptype, is_modal, vid) \ | ||
126 | ((usbh) << 31 | (usbd) << 30 | ((ptype) & 0x7) << 27 \ | ||
127 | | (is_modal) << 26 | ((vid) & 0xffff)) | ||
128 | |||
129 | #define PD_IDH_PTYPE(vdo) (((vdo) >> 27) & 0x7) | ||
130 | #define PD_IDH_VID(vdo) ((vdo) & 0xffff) | ||
131 | #define PD_IDH_MODAL_SUPP(vdo) ((vdo) & (1 << 26)) | ||
132 | |||
133 | /* | ||
134 | * Cert Stat VDO | ||
135 | * ------------- | ||
136 | * <31:0> : USB-IF assigned XID for this cable | ||
137 | */ | ||
138 | #define PD_CSTAT_XID(vdo) (vdo) | ||
139 | |||
140 | /* | ||
141 | * Product VDO | ||
142 | * ----------- | ||
143 | * <31:16> : USB Product ID | ||
144 | * <15:0> : USB bcdDevice | ||
145 | */ | ||
146 | #define VDO_PRODUCT(pid, bcd) (((pid) & 0xffff) << 16 | ((bcd) & 0xffff)) | ||
147 | #define PD_PRODUCT_PID(vdo) (((vdo) >> 16) & 0xffff) | ||
148 | |||
149 | /* | ||
150 | * Cable VDO | ||
151 | * --------- | ||
152 | * <31:28> :: Cable HW version | ||
153 | * <27:24> :: Cable FW version | ||
154 | * <23:20> :: Reserved, Shall be set to zero | ||
155 | * <19:18> :: type-C to Type-A/B/C (00b == A, 01 == B, 10 == C) | ||
156 | * <17> :: Type-C to Plug/Receptacle (0b == plug, 1b == receptacle) | ||
157 | * <16:13> :: cable latency (0001 == <10ns(~1m length)) | ||
158 | * <12:11> :: cable termination type (11b == both ends active VCONN req) | ||
159 | * <10> :: SSTX1 Directionality support (0b == fixed, 1b == cfgable) | ||
160 | * <9> :: SSTX2 Directionality support | ||
161 | * <8> :: SSRX1 Directionality support | ||
162 | * <7> :: SSRX2 Directionality support | ||
163 | * <6:5> :: Vbus current handling capability | ||
164 | * <4> :: Vbus through cable (0b == no, 1b == yes) | ||
165 | * <3> :: SOP" controller present? (0b == no, 1b == yes) | ||
166 | * <2:0> :: USB SS Signaling support | ||
167 | */ | ||
168 | #define CABLE_ATYPE 0 | ||
169 | #define CABLE_BTYPE 1 | ||
170 | #define CABLE_CTYPE 2 | ||
171 | #define CABLE_PLUG 0 | ||
172 | #define CABLE_RECEPTACLE 1 | ||
173 | #define CABLE_CURR_1A5 0 | ||
174 | #define CABLE_CURR_3A 1 | ||
175 | #define CABLE_CURR_5A 2 | ||
176 | #define CABLE_USBSS_U2_ONLY 0 | ||
177 | #define CABLE_USBSS_U31_GEN1 1 | ||
178 | #define CABLE_USBSS_U31_GEN2 2 | ||
179 | #define VDO_CABLE(hw, fw, cbl, gdr, lat, term, tx1d, tx2d, rx1d, rx2d, cur,\ | ||
180 | vps, sopp, usbss) \ | ||
181 | (((hw) & 0x7) << 28 | ((fw) & 0x7) << 24 | ((cbl) & 0x3) << 18 \ | ||
182 | | (gdr) << 17 | ((lat) & 0x7) << 13 | ((term) & 0x3) << 11 \ | ||
183 | | (tx1d) << 10 | (tx2d) << 9 | (rx1d) << 8 | (rx2d) << 7 \ | ||
184 | | ((cur) & 0x3) << 5 | (vps) << 4 | (sopp) << 3 \ | ||
185 | | ((usbss) & 0x7)) | ||
186 | |||
187 | /* | ||
188 | * AMA VDO | ||
189 | * --------- | ||
190 | * <31:28> :: Cable HW version | ||
191 | * <27:24> :: Cable FW version | ||
192 | * <23:12> :: Reserved, Shall be set to zero | ||
193 | * <11> :: SSTX1 Directionality support (0b == fixed, 1b == cfgable) | ||
194 | * <10> :: SSTX2 Directionality support | ||
195 | * <9> :: SSRX1 Directionality support | ||
196 | * <8> :: SSRX2 Directionality support | ||
197 | * <7:5> :: Vconn power | ||
198 | * <4> :: Vconn power required | ||
199 | * <3> :: Vbus power required | ||
200 | * <2:0> :: USB SS Signaling support | ||
201 | */ | ||
202 | #define VDO_AMA(hw, fw, tx1d, tx2d, rx1d, rx2d, vcpwr, vcr, vbr, usbss) \ | ||
203 | (((hw) & 0x7) << 28 | ((fw) & 0x7) << 24 \ | ||
204 | | (tx1d) << 11 | (tx2d) << 10 | (rx1d) << 9 | (rx2d) << 8 \ | ||
205 | | ((vcpwr) & 0x7) << 5 | (vcr) << 4 | (vbr) << 3 \ | ||
206 | | ((usbss) & 0x7)) | ||
207 | |||
208 | #define PD_VDO_AMA_VCONN_REQ(vdo) (((vdo) >> 4) & 1) | ||
209 | #define PD_VDO_AMA_VBUS_REQ(vdo) (((vdo) >> 3) & 1) | ||
210 | |||
211 | #define AMA_VCONN_PWR_1W 0 | ||
212 | #define AMA_VCONN_PWR_1W5 1 | ||
213 | #define AMA_VCONN_PWR_2W 2 | ||
214 | #define AMA_VCONN_PWR_3W 3 | ||
215 | #define AMA_VCONN_PWR_4W 4 | ||
216 | #define AMA_VCONN_PWR_5W 5 | ||
217 | #define AMA_VCONN_PWR_6W 6 | ||
218 | #define AMA_USBSS_U2_ONLY 0 | ||
219 | #define AMA_USBSS_U31_GEN1 1 | ||
220 | #define AMA_USBSS_U31_GEN2 2 | ||
221 | #define AMA_USBSS_BBONLY 3 | ||
222 | |||
223 | /* | ||
224 | * SVDM Discover SVIDs request -> response | ||
225 | * | ||
226 | * Request is properly formatted VDM Header with discover SVIDs command. | ||
227 | * Response is a set of SVIDs of all all supported SVIDs with all zero's to | ||
228 | * mark the end of SVIDs. If more than 12 SVIDs are supported command SHOULD be | ||
229 | * repeated. | ||
230 | */ | ||
231 | #define VDO_SVID(svid0, svid1) (((svid0) & 0xffff) << 16 | ((svid1) & 0xffff)) | ||
232 | #define PD_VDO_SVID_SVID0(vdo) ((vdo) >> 16) | ||
233 | #define PD_VDO_SVID_SVID1(vdo) ((vdo) & 0xffff) | ||
234 | |||
235 | /* USB-IF SIDs */ | ||
236 | #define USB_SID_PD 0xff00 /* power delivery */ | ||
237 | #define USB_SID_DISPLAYPORT 0xff01 | ||
238 | #define USB_SID_MHL 0xff02 /* Mobile High-Definition Link */ | ||
239 | |||
240 | /* VDM command timeouts (in ms) */ | ||
241 | |||
242 | #define PD_T_VDM_UNSTRUCTURED 500 | ||
243 | #define PD_T_VDM_BUSY 100 | ||
244 | #define PD_T_VDM_WAIT_MODE_E 100 | ||
245 | #define PD_T_VDM_SNDR_RSP 30 | ||
246 | #define PD_T_VDM_E_MODE 25 | ||
247 | #define PD_T_VDM_RCVR_RSP 15 | ||
248 | |||
249 | #endif /* __LINUX_USB_PD_VDO_H */ | ||
diff --git a/drivers/staging/typec/tcpci.c b/drivers/staging/typec/tcpci.c new file mode 100644 index 000000000000..5e5be74c7850 --- /dev/null +++ b/drivers/staging/typec/tcpci.c | |||
@@ -0,0 +1,526 @@ | |||
1 | /* | ||
2 | * Copyright 2015-2017 Google, Inc | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * USB Type-C Port Controller Interface. | ||
15 | */ | ||
16 | |||
17 | #include <linux/delay.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/regmap.h> | ||
23 | #include <linux/usb/typec.h> | ||
24 | |||
25 | #include "pd.h" | ||
26 | #include "tcpci.h" | ||
27 | #include "tcpm.h" | ||
28 | |||
29 | #define PD_RETRY_COUNT 3 | ||
30 | |||
31 | struct tcpci { | ||
32 | struct device *dev; | ||
33 | struct i2c_client *client; | ||
34 | |||
35 | struct tcpm_port *port; | ||
36 | |||
37 | struct regmap *regmap; | ||
38 | |||
39 | bool controls_vbus; | ||
40 | |||
41 | struct tcpc_dev tcpc; | ||
42 | }; | ||
43 | |||
44 | static inline struct tcpci *tcpc_to_tcpci(struct tcpc_dev *tcpc) | ||
45 | { | ||
46 | return container_of(tcpc, struct tcpci, tcpc); | ||
47 | } | ||
48 | |||
49 | static int tcpci_read16(struct tcpci *tcpci, unsigned int reg, | ||
50 | unsigned int *val) | ||
51 | { | ||
52 | return regmap_raw_read(tcpci->regmap, reg, val, sizeof(u16)); | ||
53 | } | ||
54 | |||
55 | static int tcpci_write16(struct tcpci *tcpci, unsigned int reg, u16 val) | ||
56 | { | ||
57 | return regmap_raw_write(tcpci->regmap, reg, &val, sizeof(u16)); | ||
58 | } | ||
59 | |||
60 | static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc) | ||
61 | { | ||
62 | struct tcpci *tcpci = tcpc_to_tcpci(tcpc); | ||
63 | unsigned int reg; | ||
64 | int ret; | ||
65 | |||
66 | switch (cc) { | ||
67 | case TYPEC_CC_RA: | ||
68 | reg = (TCPC_ROLE_CTRL_CC_RA << TCPC_ROLE_CTRL_CC1_SHIFT) | | ||
69 | (TCPC_ROLE_CTRL_CC_RA << TCPC_ROLE_CTRL_CC2_SHIFT); | ||
70 | break; | ||
71 | case TYPEC_CC_RD: | ||
72 | reg = (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC1_SHIFT) | | ||
73 | (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC2_SHIFT); | ||
74 | break; | ||
75 | case TYPEC_CC_RP_DEF: | ||
76 | reg = (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT) | | ||
77 | (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT) | | ||
78 | (TCPC_ROLE_CTRL_RP_VAL_DEF << | ||
79 | TCPC_ROLE_CTRL_RP_VAL_SHIFT); | ||
80 | break; | ||
81 | case TYPEC_CC_RP_1_5: | ||
82 | reg = (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT) | | ||
83 | (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT) | | ||
84 | (TCPC_ROLE_CTRL_RP_VAL_1_5 << | ||
85 | TCPC_ROLE_CTRL_RP_VAL_SHIFT); | ||
86 | break; | ||
87 | case TYPEC_CC_RP_3_0: | ||
88 | reg = (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT) | | ||
89 | (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT) | | ||
90 | (TCPC_ROLE_CTRL_RP_VAL_3_0 << | ||
91 | TCPC_ROLE_CTRL_RP_VAL_SHIFT); | ||
92 | break; | ||
93 | case TYPEC_CC_OPEN: | ||
94 | default: | ||
95 | reg = (TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC1_SHIFT) | | ||
96 | (TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC2_SHIFT); | ||
97 | break; | ||
98 | } | ||
99 | |||
100 | ret = regmap_write(tcpci->regmap, TCPC_ROLE_CTRL, reg); | ||
101 | if (ret < 0) | ||
102 | return ret; | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static int tcpci_start_drp_toggling(struct tcpc_dev *tcpc, | ||
108 | enum typec_cc_status cc) | ||
109 | { | ||
110 | struct tcpci *tcpci = tcpc_to_tcpci(tcpc); | ||
111 | unsigned int reg = TCPC_ROLE_CTRL_DRP; | ||
112 | |||
113 | switch (cc) { | ||
114 | default: | ||
115 | case TYPEC_CC_RP_DEF: | ||
116 | reg |= (TCPC_ROLE_CTRL_RP_VAL_DEF << | ||
117 | TCPC_ROLE_CTRL_RP_VAL_SHIFT); | ||
118 | break; | ||
119 | case TYPEC_CC_RP_1_5: | ||
120 | reg |= (TCPC_ROLE_CTRL_RP_VAL_1_5 << | ||
121 | TCPC_ROLE_CTRL_RP_VAL_SHIFT); | ||
122 | break; | ||
123 | case TYPEC_CC_RP_3_0: | ||
124 | reg |= (TCPC_ROLE_CTRL_RP_VAL_3_0 << | ||
125 | TCPC_ROLE_CTRL_RP_VAL_SHIFT); | ||
126 | break; | ||
127 | } | ||
128 | |||
129 | return regmap_write(tcpci->regmap, TCPC_ROLE_CTRL, reg); | ||
130 | } | ||
131 | |||
132 | static enum typec_cc_status tcpci_to_typec_cc(unsigned int cc, bool sink) | ||
133 | { | ||
134 | switch (cc) { | ||
135 | case 0x1: | ||
136 | return sink ? TYPEC_CC_RP_DEF : TYPEC_CC_RA; | ||
137 | case 0x2: | ||
138 | return sink ? TYPEC_CC_RP_1_5 : TYPEC_CC_RD; | ||
139 | case 0x3: | ||
140 | if (sink) | ||
141 | return TYPEC_CC_RP_3_0; | ||
142 | case 0x0: | ||
143 | default: | ||
144 | return TYPEC_CC_OPEN; | ||
145 | } | ||
146 | } | ||
147 | |||
148 | static int tcpci_get_cc(struct tcpc_dev *tcpc, | ||
149 | enum typec_cc_status *cc1, enum typec_cc_status *cc2) | ||
150 | { | ||
151 | struct tcpci *tcpci = tcpc_to_tcpci(tcpc); | ||
152 | unsigned int reg; | ||
153 | int ret; | ||
154 | |||
155 | ret = regmap_read(tcpci->regmap, TCPC_CC_STATUS, ®); | ||
156 | if (ret < 0) | ||
157 | return ret; | ||
158 | |||
159 | *cc1 = tcpci_to_typec_cc((reg >> TCPC_CC_STATUS_CC1_SHIFT) & | ||
160 | TCPC_CC_STATUS_CC1_MASK, | ||
161 | reg & TCPC_CC_STATUS_TERM); | ||
162 | *cc2 = tcpci_to_typec_cc((reg >> TCPC_CC_STATUS_CC2_SHIFT) & | ||
163 | TCPC_CC_STATUS_CC2_MASK, | ||
164 | reg & TCPC_CC_STATUS_TERM); | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | static int tcpci_set_polarity(struct tcpc_dev *tcpc, | ||
170 | enum typec_cc_polarity polarity) | ||
171 | { | ||
172 | struct tcpci *tcpci = tcpc_to_tcpci(tcpc); | ||
173 | int ret; | ||
174 | |||
175 | ret = regmap_write(tcpci->regmap, TCPC_TCPC_CTRL, | ||
176 | (polarity == TYPEC_POLARITY_CC2) ? | ||
177 | TCPC_TCPC_CTRL_ORIENTATION : 0); | ||
178 | if (ret < 0) | ||
179 | return ret; | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static int tcpci_set_vconn(struct tcpc_dev *tcpc, bool enable) | ||
185 | { | ||
186 | struct tcpci *tcpci = tcpc_to_tcpci(tcpc); | ||
187 | int ret; | ||
188 | |||
189 | ret = regmap_write(tcpci->regmap, TCPC_POWER_CTRL, | ||
190 | enable ? TCPC_POWER_CTRL_VCONN_ENABLE : 0); | ||
191 | if (ret < 0) | ||
192 | return ret; | ||
193 | |||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | static int tcpci_set_roles(struct tcpc_dev *tcpc, bool attached, | ||
198 | enum typec_role role, enum typec_data_role data) | ||
199 | { | ||
200 | struct tcpci *tcpci = tcpc_to_tcpci(tcpc); | ||
201 | unsigned int reg; | ||
202 | int ret; | ||
203 | |||
204 | reg = PD_REV20 << TCPC_MSG_HDR_INFO_REV_SHIFT; | ||
205 | if (role == TYPEC_SOURCE) | ||
206 | reg |= TCPC_MSG_HDR_INFO_PWR_ROLE; | ||
207 | if (data == TYPEC_HOST) | ||
208 | reg |= TCPC_MSG_HDR_INFO_DATA_ROLE; | ||
209 | ret = regmap_write(tcpci->regmap, TCPC_MSG_HDR_INFO, reg); | ||
210 | if (ret < 0) | ||
211 | return ret; | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static int tcpci_set_pd_rx(struct tcpc_dev *tcpc, bool enable) | ||
217 | { | ||
218 | struct tcpci *tcpci = tcpc_to_tcpci(tcpc); | ||
219 | unsigned int reg = 0; | ||
220 | int ret; | ||
221 | |||
222 | if (enable) | ||
223 | reg = TCPC_RX_DETECT_SOP | TCPC_RX_DETECT_HARD_RESET; | ||
224 | ret = regmap_write(tcpci->regmap, TCPC_RX_DETECT, reg); | ||
225 | if (ret < 0) | ||
226 | return ret; | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static int tcpci_get_vbus(struct tcpc_dev *tcpc) | ||
232 | { | ||
233 | struct tcpci *tcpci = tcpc_to_tcpci(tcpc); | ||
234 | unsigned int reg; | ||
235 | int ret; | ||
236 | |||
237 | ret = regmap_read(tcpci->regmap, TCPC_POWER_STATUS, ®); | ||
238 | if (ret < 0) | ||
239 | return ret; | ||
240 | |||
241 | return !!(reg & TCPC_POWER_STATUS_VBUS_PRES); | ||
242 | } | ||
243 | |||
244 | static int tcpci_set_vbus(struct tcpc_dev *tcpc, bool source, bool sink) | ||
245 | { | ||
246 | struct tcpci *tcpci = tcpc_to_tcpci(tcpc); | ||
247 | int ret; | ||
248 | |||
249 | /* Disable both source and sink first before enabling anything */ | ||
250 | |||
251 | if (!source) { | ||
252 | ret = regmap_write(tcpci->regmap, TCPC_COMMAND, | ||
253 | TCPC_CMD_DISABLE_SRC_VBUS); | ||
254 | if (ret < 0) | ||
255 | return ret; | ||
256 | } | ||
257 | |||
258 | if (!sink) { | ||
259 | ret = regmap_write(tcpci->regmap, TCPC_COMMAND, | ||
260 | TCPC_CMD_DISABLE_SINK_VBUS); | ||
261 | if (ret < 0) | ||
262 | return ret; | ||
263 | } | ||
264 | |||
265 | if (source) { | ||
266 | ret = regmap_write(tcpci->regmap, TCPC_COMMAND, | ||
267 | TCPC_CMD_SRC_VBUS_DEFAULT); | ||
268 | if (ret < 0) | ||
269 | return ret; | ||
270 | } | ||
271 | |||
272 | if (sink) { | ||
273 | ret = regmap_write(tcpci->regmap, TCPC_COMMAND, | ||
274 | TCPC_CMD_SINK_VBUS); | ||
275 | if (ret < 0) | ||
276 | return ret; | ||
277 | } | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | static int tcpci_pd_transmit(struct tcpc_dev *tcpc, | ||
283 | enum tcpm_transmit_type type, | ||
284 | const struct pd_message *msg) | ||
285 | { | ||
286 | struct tcpci *tcpci = tcpc_to_tcpci(tcpc); | ||
287 | unsigned int reg, cnt, header; | ||
288 | int ret; | ||
289 | |||
290 | cnt = msg ? pd_header_cnt(msg->header) * 4 : 0; | ||
291 | ret = regmap_write(tcpci->regmap, TCPC_TX_BYTE_CNT, cnt + 2); | ||
292 | if (ret < 0) | ||
293 | return ret; | ||
294 | |||
295 | header = msg ? msg->header : 0; | ||
296 | ret = tcpci_write16(tcpci, TCPC_TX_HDR, header); | ||
297 | if (ret < 0) | ||
298 | return ret; | ||
299 | |||
300 | if (cnt > 0) { | ||
301 | ret = regmap_raw_write(tcpci->regmap, TCPC_TX_DATA, | ||
302 | &msg->payload, cnt); | ||
303 | if (ret < 0) | ||
304 | return ret; | ||
305 | } | ||
306 | |||
307 | reg = (PD_RETRY_COUNT << TCPC_TRANSMIT_RETRY_SHIFT) | | ||
308 | (type << TCPC_TRANSMIT_TYPE_SHIFT); | ||
309 | ret = regmap_write(tcpci->regmap, TCPC_TRANSMIT, reg); | ||
310 | if (ret < 0) | ||
311 | return ret; | ||
312 | |||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | static int tcpci_init(struct tcpc_dev *tcpc) | ||
317 | { | ||
318 | struct tcpci *tcpci = tcpc_to_tcpci(tcpc); | ||
319 | unsigned long timeout = jiffies + msecs_to_jiffies(2000); /* XXX */ | ||
320 | unsigned int reg; | ||
321 | int ret; | ||
322 | |||
323 | while (time_before_eq(jiffies, timeout)) { | ||
324 | ret = regmap_read(tcpci->regmap, TCPC_POWER_STATUS, ®); | ||
325 | if (ret < 0) | ||
326 | return ret; | ||
327 | if (!(reg & TCPC_POWER_STATUS_UNINIT)) | ||
328 | break; | ||
329 | usleep_range(10000, 20000); | ||
330 | } | ||
331 | if (time_after(jiffies, timeout)) | ||
332 | return -ETIMEDOUT; | ||
333 | |||
334 | /* Clear all events */ | ||
335 | ret = tcpci_write16(tcpci, TCPC_ALERT, 0xffff); | ||
336 | if (ret < 0) | ||
337 | return ret; | ||
338 | |||
339 | if (tcpci->controls_vbus) | ||
340 | reg = TCPC_POWER_STATUS_VBUS_PRES; | ||
341 | else | ||
342 | reg = 0; | ||
343 | ret = regmap_write(tcpci->regmap, TCPC_POWER_STATUS_MASK, reg); | ||
344 | if (ret < 0) | ||
345 | return ret; | ||
346 | |||
347 | reg = TCPC_ALERT_TX_SUCCESS | TCPC_ALERT_TX_FAILED | | ||
348 | TCPC_ALERT_TX_DISCARDED | TCPC_ALERT_RX_STATUS | | ||
349 | TCPC_ALERT_RX_HARD_RST | TCPC_ALERT_CC_STATUS; | ||
350 | if (tcpci->controls_vbus) | ||
351 | reg |= TCPC_ALERT_POWER_STATUS; | ||
352 | return tcpci_write16(tcpci, TCPC_ALERT_MASK, reg); | ||
353 | } | ||
354 | |||
355 | static irqreturn_t tcpci_irq(int irq, void *dev_id) | ||
356 | { | ||
357 | struct tcpci *tcpci = dev_id; | ||
358 | unsigned int status, reg; | ||
359 | |||
360 | tcpci_read16(tcpci, TCPC_ALERT, &status); | ||
361 | |||
362 | /* | ||
363 | * Clear alert status for everything except RX_STATUS, which shouldn't | ||
364 | * be cleared until we have successfully retrieved message. | ||
365 | */ | ||
366 | if (status & ~TCPC_ALERT_RX_STATUS) | ||
367 | tcpci_write16(tcpci, TCPC_ALERT, | ||
368 | status & ~TCPC_ALERT_RX_STATUS); | ||
369 | |||
370 | if (status & TCPC_ALERT_CC_STATUS) | ||
371 | tcpm_cc_change(tcpci->port); | ||
372 | |||
373 | if (status & TCPC_ALERT_POWER_STATUS) { | ||
374 | regmap_read(tcpci->regmap, TCPC_POWER_STATUS_MASK, ®); | ||
375 | |||
376 | /* | ||
377 | * If power status mask has been reset, then the TCPC | ||
378 | * has reset. | ||
379 | */ | ||
380 | if (reg == 0xff) | ||
381 | tcpm_tcpc_reset(tcpci->port); | ||
382 | else | ||
383 | tcpm_vbus_change(tcpci->port); | ||
384 | } | ||
385 | |||
386 | if (status & TCPC_ALERT_RX_STATUS) { | ||
387 | struct pd_message msg; | ||
388 | unsigned int cnt; | ||
389 | |||
390 | regmap_read(tcpci->regmap, TCPC_RX_BYTE_CNT, &cnt); | ||
391 | |||
392 | tcpci_read16(tcpci, TCPC_RX_HDR, ®); | ||
393 | msg.header = reg; | ||
394 | |||
395 | if (WARN_ON(cnt > sizeof(msg.payload))) | ||
396 | cnt = sizeof(msg.payload); | ||
397 | |||
398 | if (cnt > 0) | ||
399 | regmap_raw_read(tcpci->regmap, TCPC_RX_DATA, | ||
400 | &msg.payload, cnt); | ||
401 | |||
402 | /* Read complete, clear RX status alert bit */ | ||
403 | tcpci_write16(tcpci, TCPC_ALERT, TCPC_ALERT_RX_STATUS); | ||
404 | |||
405 | tcpm_pd_receive(tcpci->port, &msg); | ||
406 | } | ||
407 | |||
408 | if (status & TCPC_ALERT_RX_HARD_RST) | ||
409 | tcpm_pd_hard_reset(tcpci->port); | ||
410 | |||
411 | if (status & TCPC_ALERT_TX_SUCCESS) | ||
412 | tcpm_pd_transmit_complete(tcpci->port, TCPC_TX_SUCCESS); | ||
413 | else if (status & TCPC_ALERT_TX_DISCARDED) | ||
414 | tcpm_pd_transmit_complete(tcpci->port, TCPC_TX_DISCARDED); | ||
415 | else if (status & TCPC_ALERT_TX_FAILED) | ||
416 | tcpm_pd_transmit_complete(tcpci->port, TCPC_TX_FAILED); | ||
417 | |||
418 | return IRQ_HANDLED; | ||
419 | } | ||
420 | |||
421 | static const struct regmap_config tcpci_regmap_config = { | ||
422 | .reg_bits = 8, | ||
423 | .val_bits = 8, | ||
424 | |||
425 | .max_register = 0x7F, /* 0x80 .. 0xFF are vendor defined */ | ||
426 | }; | ||
427 | |||
428 | const struct tcpc_config tcpci_tcpc_config = { | ||
429 | .type = TYPEC_PORT_DFP, | ||
430 | .default_role = TYPEC_SINK, | ||
431 | }; | ||
432 | |||
433 | static int tcpci_parse_config(struct tcpci *tcpci) | ||
434 | { | ||
435 | tcpci->controls_vbus = true; /* XXX */ | ||
436 | |||
437 | /* TODO: Populate struct tcpc_config from ACPI/device-tree */ | ||
438 | tcpci->tcpc.config = &tcpci_tcpc_config; | ||
439 | |||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | static int tcpci_probe(struct i2c_client *client, | ||
444 | const struct i2c_device_id *i2c_id) | ||
445 | { | ||
446 | struct tcpci *tcpci; | ||
447 | int err; | ||
448 | |||
449 | tcpci = devm_kzalloc(&client->dev, sizeof(*tcpci), GFP_KERNEL); | ||
450 | if (!tcpci) | ||
451 | return -ENOMEM; | ||
452 | |||
453 | tcpci->client = client; | ||
454 | tcpci->dev = &client->dev; | ||
455 | i2c_set_clientdata(client, tcpci); | ||
456 | tcpci->regmap = devm_regmap_init_i2c(client, &tcpci_regmap_config); | ||
457 | if (IS_ERR(tcpci->regmap)) | ||
458 | return PTR_ERR(tcpci->regmap); | ||
459 | |||
460 | tcpci->tcpc.init = tcpci_init; | ||
461 | tcpci->tcpc.get_vbus = tcpci_get_vbus; | ||
462 | tcpci->tcpc.set_vbus = tcpci_set_vbus; | ||
463 | tcpci->tcpc.set_cc = tcpci_set_cc; | ||
464 | tcpci->tcpc.get_cc = tcpci_get_cc; | ||
465 | tcpci->tcpc.set_polarity = tcpci_set_polarity; | ||
466 | tcpci->tcpc.set_vconn = tcpci_set_vconn; | ||
467 | tcpci->tcpc.start_drp_toggling = tcpci_start_drp_toggling; | ||
468 | |||
469 | tcpci->tcpc.set_pd_rx = tcpci_set_pd_rx; | ||
470 | tcpci->tcpc.set_roles = tcpci_set_roles; | ||
471 | tcpci->tcpc.pd_transmit = tcpci_pd_transmit; | ||
472 | |||
473 | err = tcpci_parse_config(tcpci); | ||
474 | if (err < 0) | ||
475 | return err; | ||
476 | |||
477 | /* Disable chip interrupts */ | ||
478 | tcpci_write16(tcpci, TCPC_ALERT_MASK, 0); | ||
479 | |||
480 | err = devm_request_threaded_irq(tcpci->dev, client->irq, NULL, | ||
481 | tcpci_irq, | ||
482 | IRQF_ONESHOT | IRQF_TRIGGER_LOW, | ||
483 | dev_name(tcpci->dev), tcpci); | ||
484 | if (err < 0) | ||
485 | return err; | ||
486 | |||
487 | tcpci->port = tcpm_register_port(tcpci->dev, &tcpci->tcpc); | ||
488 | return PTR_ERR_OR_ZERO(tcpci->port); | ||
489 | } | ||
490 | |||
491 | static int tcpci_remove(struct i2c_client *client) | ||
492 | { | ||
493 | struct tcpci *tcpci = i2c_get_clientdata(client); | ||
494 | |||
495 | tcpm_unregister_port(tcpci->port); | ||
496 | |||
497 | return 0; | ||
498 | } | ||
499 | |||
500 | static const struct i2c_device_id tcpci_id[] = { | ||
501 | { "tcpci", 0 }, | ||
502 | { } | ||
503 | }; | ||
504 | MODULE_DEVICE_TABLE(i2c, tcpci_id); | ||
505 | |||
506 | #ifdef CONFIG_OF | ||
507 | static const struct of_device_id tcpci_of_match[] = { | ||
508 | { .compatible = "usb,tcpci", }, | ||
509 | {}, | ||
510 | }; | ||
511 | MODULE_DEVICE_TABLE(of, tcpci_of_match); | ||
512 | #endif | ||
513 | |||
514 | static struct i2c_driver tcpci_i2c_driver = { | ||
515 | .driver = { | ||
516 | .name = "tcpci", | ||
517 | .of_match_table = of_match_ptr(tcpci_of_match), | ||
518 | }, | ||
519 | .probe = tcpci_probe, | ||
520 | .remove = tcpci_remove, | ||
521 | .id_table = tcpci_id, | ||
522 | }; | ||
523 | module_i2c_driver(tcpci_i2c_driver); | ||
524 | |||
525 | MODULE_DESCRIPTION("USB Type-C Port Controller Interface driver"); | ||
526 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/staging/typec/tcpci.h b/drivers/staging/typec/tcpci.h new file mode 100644 index 000000000000..10b04c8723da --- /dev/null +++ b/drivers/staging/typec/tcpci.h | |||
@@ -0,0 +1,133 @@ | |||
1 | /* | ||
2 | * Copyright 2015-2017 Google, Inc | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * USB Type-C Port Controller Interface. | ||
15 | */ | ||
16 | |||
17 | #ifndef __LINUX_USB_TCPCI_H | ||
18 | #define __LINUX_USB_TCPCI_H | ||
19 | |||
20 | #define TCPC_VENDOR_ID 0x0 | ||
21 | #define TCPC_PRODUCT_ID 0x2 | ||
22 | #define TCPC_BCD_DEV 0x4 | ||
23 | #define TCPC_TC_REV 0x6 | ||
24 | #define TCPC_PD_REV 0x8 | ||
25 | #define TCPC_PD_INT_REV 0xa | ||
26 | |||
27 | #define TCPC_ALERT 0x10 | ||
28 | #define TCPC_ALERT_VBUS_DISCNCT BIT(11) | ||
29 | #define TCPC_ALERT_RX_BUF_OVF BIT(10) | ||
30 | #define TCPC_ALERT_FAULT BIT(9) | ||
31 | #define TCPC_ALERT_V_ALARM_LO BIT(8) | ||
32 | #define TCPC_ALERT_V_ALARM_HI BIT(7) | ||
33 | #define TCPC_ALERT_TX_SUCCESS BIT(6) | ||
34 | #define TCPC_ALERT_TX_DISCARDED BIT(5) | ||
35 | #define TCPC_ALERT_TX_FAILED BIT(4) | ||
36 | #define TCPC_ALERT_RX_HARD_RST BIT(3) | ||
37 | #define TCPC_ALERT_RX_STATUS BIT(2) | ||
38 | #define TCPC_ALERT_POWER_STATUS BIT(1) | ||
39 | #define TCPC_ALERT_CC_STATUS BIT(0) | ||
40 | |||
41 | #define TCPC_ALERT_MASK 0x12 | ||
42 | #define TCPC_POWER_STATUS_MASK 0x14 | ||
43 | #define TCPC_FAULT_STATUS_MASK 0x15 | ||
44 | #define TCPC_CONFIG_STD_OUTPUT 0x18 | ||
45 | |||
46 | #define TCPC_TCPC_CTRL 0x19 | ||
47 | #define TCPC_TCPC_CTRL_ORIENTATION BIT(0) | ||
48 | |||
49 | #define TCPC_ROLE_CTRL 0x1a | ||
50 | #define TCPC_ROLE_CTRL_DRP BIT(6) | ||
51 | #define TCPC_ROLE_CTRL_RP_VAL_SHIFT 4 | ||
52 | #define TCPC_ROLE_CTRL_RP_VAL_MASK 0x3 | ||
53 | #define TCPC_ROLE_CTRL_RP_VAL_DEF 0x0 | ||
54 | #define TCPC_ROLE_CTRL_RP_VAL_1_5 0x1 | ||
55 | #define TCPC_ROLE_CTRL_RP_VAL_3_0 0x2 | ||
56 | #define TCPC_ROLE_CTRL_CC2_SHIFT 2 | ||
57 | #define TCPC_ROLE_CTRL_CC2_MASK 0x3 | ||
58 | #define TCPC_ROLE_CTRL_CC1_SHIFT 0 | ||
59 | #define TCPC_ROLE_CTRL_CC1_MASK 0x3 | ||
60 | #define TCPC_ROLE_CTRL_CC_RA 0x0 | ||
61 | #define TCPC_ROLE_CTRL_CC_RP 0x1 | ||
62 | #define TCPC_ROLE_CTRL_CC_RD 0x2 | ||
63 | #define TCPC_ROLE_CTRL_CC_OPEN 0x3 | ||
64 | |||
65 | #define TCPC_FAULT_CTRL 0x1b | ||
66 | |||
67 | #define TCPC_POWER_CTRL 0x1c | ||
68 | #define TCPC_POWER_CTRL_VCONN_ENABLE BIT(0) | ||
69 | |||
70 | #define TCPC_CC_STATUS 0x1d | ||
71 | #define TCPC_CC_STATUS_TERM BIT(4) | ||
72 | #define TCPC_CC_STATUS_CC2_SHIFT 2 | ||
73 | #define TCPC_CC_STATUS_CC2_MASK 0x3 | ||
74 | #define TCPC_CC_STATUS_CC1_SHIFT 0 | ||
75 | #define TCPC_CC_STATUS_CC1_MASK 0x3 | ||
76 | |||
77 | #define TCPC_POWER_STATUS 0x1e | ||
78 | #define TCPC_POWER_STATUS_UNINIT BIT(6) | ||
79 | #define TCPC_POWER_STATUS_VBUS_DET BIT(3) | ||
80 | #define TCPC_POWER_STATUS_VBUS_PRES BIT(2) | ||
81 | |||
82 | #define TCPC_FAULT_STATUS 0x1f | ||
83 | |||
84 | #define TCPC_COMMAND 0x23 | ||
85 | #define TCPC_CMD_WAKE_I2C 0x11 | ||
86 | #define TCPC_CMD_DISABLE_VBUS_DETECT 0x22 | ||
87 | #define TCPC_CMD_ENABLE_VBUS_DETECT 0x33 | ||
88 | #define TCPC_CMD_DISABLE_SINK_VBUS 0x44 | ||
89 | #define TCPC_CMD_SINK_VBUS 0x55 | ||
90 | #define TCPC_CMD_DISABLE_SRC_VBUS 0x66 | ||
91 | #define TCPC_CMD_SRC_VBUS_DEFAULT 0x77 | ||
92 | #define TCPC_CMD_SRC_VBUS_HIGH 0x88 | ||
93 | #define TCPC_CMD_LOOK4CONNECTION 0x99 | ||
94 | #define TCPC_CMD_RXONEMORE 0xAA | ||
95 | #define TCPC_CMD_I2C_IDLE 0xFF | ||
96 | |||
97 | #define TCPC_DEV_CAP_1 0x24 | ||
98 | #define TCPC_DEV_CAP_2 0x26 | ||
99 | #define TCPC_STD_INPUT_CAP 0x28 | ||
100 | #define TCPC_STD_OUTPUT_CAP 0x29 | ||
101 | |||
102 | #define TCPC_MSG_HDR_INFO 0x2e | ||
103 | #define TCPC_MSG_HDR_INFO_DATA_ROLE BIT(3) | ||
104 | #define TCPC_MSG_HDR_INFO_PWR_ROLE BIT(0) | ||
105 | #define TCPC_MSG_HDR_INFO_REV_SHIFT 1 | ||
106 | #define TCPC_MSG_HDR_INFO_REV_MASK 0x3 | ||
107 | |||
108 | #define TCPC_RX_DETECT 0x2f | ||
109 | #define TCPC_RX_DETECT_HARD_RESET BIT(5) | ||
110 | #define TCPC_RX_DETECT_SOP BIT(0) | ||
111 | |||
112 | #define TCPC_RX_BYTE_CNT 0x30 | ||
113 | #define TCPC_RX_BUF_FRAME_TYPE 0x31 | ||
114 | #define TCPC_RX_HDR 0x32 | ||
115 | #define TCPC_RX_DATA 0x34 /* through 0x4f */ | ||
116 | |||
117 | #define TCPC_TRANSMIT 0x50 | ||
118 | #define TCPC_TRANSMIT_RETRY_SHIFT 4 | ||
119 | #define TCPC_TRANSMIT_RETRY_MASK 0x3 | ||
120 | #define TCPC_TRANSMIT_TYPE_SHIFT 0 | ||
121 | #define TCPC_TRANSMIT_TYPE_MASK 0x7 | ||
122 | |||
123 | #define TCPC_TX_BYTE_CNT 0x51 | ||
124 | #define TCPC_TX_HDR 0x52 | ||
125 | #define TCPC_TX_DATA 0x54 /* through 0x6f */ | ||
126 | |||
127 | #define TCPC_VBUS_VOLTAGE 0x70 | ||
128 | #define TCPC_VBUS_SINK_DISCONNECT_THRESH 0x72 | ||
129 | #define TCPC_VBUS_STOP_DISCHARGE_THRESH 0x74 | ||
130 | #define TCPC_VBUS_VOLTAGE_ALARM_HI_CFG 0x76 | ||
131 | #define TCPC_VBUS_VOLTAGE_ALARM_LO_CFG 0x78 | ||
132 | |||
133 | #endif /* __LINUX_USB_TCPCI_H */ | ||
diff --git a/drivers/staging/typec/tcpm.c b/drivers/staging/typec/tcpm.c new file mode 100644 index 000000000000..abba655ba00a --- /dev/null +++ b/drivers/staging/typec/tcpm.c | |||
@@ -0,0 +1,3465 @@ | |||
1 | /* | ||
2 | * Copyright 2015-2017 Google, Inc | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * USB Power Delivery protocol stack. | ||
15 | */ | ||
16 | |||
17 | #include <linux/completion.h> | ||
18 | #include <linux/debugfs.h> | ||
19 | #include <linux/device.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/mutex.h> | ||
23 | #include <linux/proc_fs.h> | ||
24 | #include <linux/sched/clock.h> | ||
25 | #include <linux/seq_file.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/spinlock.h> | ||
28 | #include <linux/usb/typec.h> | ||
29 | #include <linux/workqueue.h> | ||
30 | |||
31 | #include "pd.h" | ||
32 | #include "pd_vdo.h" | ||
33 | #include "pd_bdo.h" | ||
34 | #include "tcpm.h" | ||
35 | |||
36 | #define FOREACH_STATE(S) \ | ||
37 | S(INVALID_STATE), \ | ||
38 | S(DRP_TOGGLING), \ | ||
39 | S(SRC_UNATTACHED), \ | ||
40 | S(SRC_ATTACH_WAIT), \ | ||
41 | S(SRC_ATTACHED), \ | ||
42 | S(SRC_STARTUP), \ | ||
43 | S(SRC_SEND_CAPABILITIES), \ | ||
44 | S(SRC_NEGOTIATE_CAPABILITIES), \ | ||
45 | S(SRC_TRANSITION_SUPPLY), \ | ||
46 | S(SRC_READY), \ | ||
47 | S(SRC_WAIT_NEW_CAPABILITIES), \ | ||
48 | \ | ||
49 | S(SNK_UNATTACHED), \ | ||
50 | S(SNK_ATTACH_WAIT), \ | ||
51 | S(SNK_DEBOUNCED), \ | ||
52 | S(SNK_ATTACHED), \ | ||
53 | S(SNK_STARTUP), \ | ||
54 | S(SNK_DISCOVERY), \ | ||
55 | S(SNK_DISCOVERY_DEBOUNCE), \ | ||
56 | S(SNK_DISCOVERY_DEBOUNCE_DONE), \ | ||
57 | S(SNK_WAIT_CAPABILITIES), \ | ||
58 | S(SNK_NEGOTIATE_CAPABILITIES), \ | ||
59 | S(SNK_TRANSITION_SINK), \ | ||
60 | S(SNK_TRANSITION_SINK_VBUS), \ | ||
61 | S(SNK_READY), \ | ||
62 | \ | ||
63 | S(ACC_UNATTACHED), \ | ||
64 | S(DEBUG_ACC_ATTACHED), \ | ||
65 | S(AUDIO_ACC_ATTACHED), \ | ||
66 | S(AUDIO_ACC_DEBOUNCE), \ | ||
67 | \ | ||
68 | S(HARD_RESET_SEND), \ | ||
69 | S(HARD_RESET_START), \ | ||
70 | S(SRC_HARD_RESET_VBUS_OFF), \ | ||
71 | S(SRC_HARD_RESET_VBUS_ON), \ | ||
72 | S(SNK_HARD_RESET_SINK_OFF), \ | ||
73 | S(SNK_HARD_RESET_WAIT_VBUS), \ | ||
74 | S(SNK_HARD_RESET_SINK_ON), \ | ||
75 | \ | ||
76 | S(SOFT_RESET), \ | ||
77 | S(SOFT_RESET_SEND), \ | ||
78 | \ | ||
79 | S(DR_SWAP_ACCEPT), \ | ||
80 | S(DR_SWAP_SEND), \ | ||
81 | S(DR_SWAP_SEND_TIMEOUT), \ | ||
82 | S(DR_SWAP_CANCEL), \ | ||
83 | S(DR_SWAP_CHANGE_DR), \ | ||
84 | \ | ||
85 | S(PR_SWAP_ACCEPT), \ | ||
86 | S(PR_SWAP_SEND), \ | ||
87 | S(PR_SWAP_SEND_TIMEOUT), \ | ||
88 | S(PR_SWAP_CANCEL), \ | ||
89 | S(PR_SWAP_START), \ | ||
90 | S(PR_SWAP_SRC_SNK_TRANSITION_OFF), \ | ||
91 | S(PR_SWAP_SRC_SNK_SOURCE_OFF), \ | ||
92 | S(PR_SWAP_SRC_SNK_SINK_ON), \ | ||
93 | S(PR_SWAP_SNK_SRC_SINK_OFF), \ | ||
94 | S(PR_SWAP_SNK_SRC_SOURCE_ON), \ | ||
95 | \ | ||
96 | S(VCONN_SWAP_ACCEPT), \ | ||
97 | S(VCONN_SWAP_SEND), \ | ||
98 | S(VCONN_SWAP_SEND_TIMEOUT), \ | ||
99 | S(VCONN_SWAP_CANCEL), \ | ||
100 | S(VCONN_SWAP_START), \ | ||
101 | S(VCONN_SWAP_WAIT_FOR_VCONN), \ | ||
102 | S(VCONN_SWAP_TURN_ON_VCONN), \ | ||
103 | S(VCONN_SWAP_TURN_OFF_VCONN), \ | ||
104 | \ | ||
105 | S(SNK_TRY), \ | ||
106 | S(SNK_TRY_WAIT), \ | ||
107 | S(SRC_TRYWAIT), \ | ||
108 | S(SRC_TRYWAIT_UNATTACHED), \ | ||
109 | \ | ||
110 | S(SRC_TRY), \ | ||
111 | S(SRC_TRY_DEBOUNCE), \ | ||
112 | S(SNK_TRYWAIT), \ | ||
113 | S(SNK_TRYWAIT_DEBOUNCE), \ | ||
114 | S(SNK_TRYWAIT_VBUS), \ | ||
115 | S(BIST_RX), \ | ||
116 | \ | ||
117 | S(ERROR_RECOVERY), \ | ||
118 | S(ERROR_RECOVERY_WAIT_OFF) | ||
119 | |||
120 | #define GENERATE_ENUM(e) e | ||
121 | #define GENERATE_STRING(s) #s | ||
122 | |||
123 | enum tcpm_state { | ||
124 | FOREACH_STATE(GENERATE_ENUM) | ||
125 | }; | ||
126 | |||
127 | static const char * const tcpm_states[] = { | ||
128 | FOREACH_STATE(GENERATE_STRING) | ||
129 | }; | ||
130 | |||
131 | enum vdm_states { | ||
132 | VDM_STATE_ERR_BUSY = -3, | ||
133 | VDM_STATE_ERR_SEND = -2, | ||
134 | VDM_STATE_ERR_TMOUT = -1, | ||
135 | VDM_STATE_DONE = 0, | ||
136 | /* Anything >0 represents an active state */ | ||
137 | VDM_STATE_READY = 1, | ||
138 | VDM_STATE_BUSY = 2, | ||
139 | VDM_STATE_WAIT_RSP_BUSY = 3, | ||
140 | }; | ||
141 | |||
142 | enum pd_msg_request { | ||
143 | PD_MSG_NONE = 0, | ||
144 | PD_MSG_CTRL_REJECT, | ||
145 | PD_MSG_CTRL_WAIT, | ||
146 | PD_MSG_DATA_SINK_CAP, | ||
147 | PD_MSG_DATA_SOURCE_CAP, | ||
148 | }; | ||
149 | |||
150 | /* Events from low level driver */ | ||
151 | |||
152 | #define TCPM_CC_EVENT BIT(0) | ||
153 | #define TCPM_VBUS_EVENT BIT(1) | ||
154 | #define TCPM_RESET_EVENT BIT(2) | ||
155 | |||
156 | #define LOG_BUFFER_ENTRIES 1024 | ||
157 | #define LOG_BUFFER_ENTRY_SIZE 128 | ||
158 | |||
159 | /* Alternate mode support */ | ||
160 | |||
161 | #define SVID_DISCOVERY_MAX 16 | ||
162 | |||
163 | struct pd_mode_data { | ||
164 | int svid_index; /* current SVID index */ | ||
165 | int nsvids; | ||
166 | u16 svids[SVID_DISCOVERY_MAX]; | ||
167 | int altmodes; /* number of alternate modes */ | ||
168 | struct typec_altmode_desc altmode_desc[SVID_DISCOVERY_MAX]; | ||
169 | }; | ||
170 | |||
171 | struct tcpm_port { | ||
172 | struct device *dev; | ||
173 | |||
174 | struct mutex lock; /* tcpm state machine lock */ | ||
175 | struct workqueue_struct *wq; | ||
176 | |||
177 | struct typec_capability typec_caps; | ||
178 | struct typec_port *typec_port; | ||
179 | |||
180 | struct tcpc_dev *tcpc; | ||
181 | |||
182 | enum typec_role vconn_role; | ||
183 | enum typec_role pwr_role; | ||
184 | enum typec_data_role data_role; | ||
185 | enum typec_pwr_opmode pwr_opmode; | ||
186 | |||
187 | struct usb_pd_identity partner_ident; | ||
188 | struct typec_partner_desc partner_desc; | ||
189 | struct typec_partner *partner; | ||
190 | |||
191 | enum typec_cc_status cc_req; | ||
192 | |||
193 | enum typec_cc_status cc1; | ||
194 | enum typec_cc_status cc2; | ||
195 | enum typec_cc_polarity polarity; | ||
196 | |||
197 | bool attached; | ||
198 | bool connected; | ||
199 | bool vbus_present; | ||
200 | bool vbus_never_low; | ||
201 | bool vbus_source; | ||
202 | bool vbus_charge; | ||
203 | |||
204 | bool send_discover; | ||
205 | bool op_vsafe5v; | ||
206 | |||
207 | int try_role; | ||
208 | int try_snk_count; | ||
209 | int try_src_count; | ||
210 | |||
211 | enum pd_msg_request queued_message; | ||
212 | |||
213 | enum tcpm_state enter_state; | ||
214 | enum tcpm_state prev_state; | ||
215 | enum tcpm_state state; | ||
216 | enum tcpm_state delayed_state; | ||
217 | unsigned long delayed_runtime; | ||
218 | unsigned long delay_ms; | ||
219 | |||
220 | spinlock_t pd_event_lock; | ||
221 | u32 pd_events; | ||
222 | |||
223 | struct work_struct event_work; | ||
224 | struct delayed_work state_machine; | ||
225 | struct delayed_work vdm_state_machine; | ||
226 | bool state_machine_running; | ||
227 | |||
228 | struct completion tx_complete; | ||
229 | enum tcpm_transmit_status tx_status; | ||
230 | |||
231 | struct mutex swap_lock; /* swap command lock */ | ||
232 | bool swap_pending; | ||
233 | struct completion swap_complete; | ||
234 | int swap_status; | ||
235 | |||
236 | unsigned int message_id; | ||
237 | unsigned int caps_count; | ||
238 | unsigned int hard_reset_count; | ||
239 | bool pd_capable; | ||
240 | bool explicit_contract; | ||
241 | |||
242 | /* Partner capabilities/requests */ | ||
243 | u32 sink_request; | ||
244 | u32 source_caps[PDO_MAX_OBJECTS]; | ||
245 | unsigned int nr_source_caps; | ||
246 | u32 sink_caps[PDO_MAX_OBJECTS]; | ||
247 | unsigned int nr_sink_caps; | ||
248 | |||
249 | /* Local capabilities */ | ||
250 | u32 src_pdo[PDO_MAX_OBJECTS]; | ||
251 | unsigned int nr_src_pdo; | ||
252 | u32 snk_pdo[PDO_MAX_OBJECTS]; | ||
253 | unsigned int nr_snk_pdo; | ||
254 | |||
255 | unsigned int max_snk_mv; | ||
256 | unsigned int max_snk_ma; | ||
257 | unsigned int max_snk_mw; | ||
258 | unsigned int operating_snk_mw; | ||
259 | |||
260 | /* Requested current / voltage */ | ||
261 | u32 current_limit; | ||
262 | u32 supply_voltage; | ||
263 | |||
264 | u32 bist_request; | ||
265 | |||
266 | /* PD state for Vendor Defined Messages */ | ||
267 | enum vdm_states vdm_state; | ||
268 | u32 vdm_retries; | ||
269 | /* next Vendor Defined Message to send */ | ||
270 | u32 vdo_data[VDO_MAX_SIZE]; | ||
271 | u8 vdo_count; | ||
272 | /* VDO to retry if UFP responder replied busy */ | ||
273 | u32 vdo_retry; | ||
274 | |||
275 | /* Alternate mode data */ | ||
276 | |||
277 | struct pd_mode_data mode_data; | ||
278 | struct typec_altmode *partner_altmode[SVID_DISCOVERY_MAX]; | ||
279 | struct typec_altmode *port_altmode[SVID_DISCOVERY_MAX]; | ||
280 | |||
281 | #ifdef CONFIG_DEBUG_FS | ||
282 | struct dentry *dentry; | ||
283 | struct mutex logbuffer_lock; /* log buffer access lock */ | ||
284 | int logbuffer_head; | ||
285 | int logbuffer_tail; | ||
286 | u8 *logbuffer[LOG_BUFFER_ENTRIES]; | ||
287 | #endif | ||
288 | }; | ||
289 | |||
290 | struct pd_rx_event { | ||
291 | struct work_struct work; | ||
292 | struct tcpm_port *port; | ||
293 | struct pd_message msg; | ||
294 | }; | ||
295 | |||
296 | #define tcpm_cc_is_sink(cc) \ | ||
297 | ((cc) == TYPEC_CC_RP_DEF || (cc) == TYPEC_CC_RP_1_5 || \ | ||
298 | (cc) == TYPEC_CC_RP_3_0) | ||
299 | |||
300 | #define tcpm_port_is_sink(port) \ | ||
301 | ((tcpm_cc_is_sink((port)->cc1) && !tcpm_cc_is_sink((port)->cc2)) || \ | ||
302 | (tcpm_cc_is_sink((port)->cc2) && !tcpm_cc_is_sink((port)->cc1))) | ||
303 | |||
304 | #define tcpm_cc_is_source(cc) ((cc) == TYPEC_CC_RD) | ||
305 | #define tcpm_cc_is_audio(cc) ((cc) == TYPEC_CC_RA) | ||
306 | #define tcpm_cc_is_open(cc) ((cc) == TYPEC_CC_OPEN) | ||
307 | |||
308 | #define tcpm_port_is_source(port) \ | ||
309 | ((tcpm_cc_is_source((port)->cc1) && \ | ||
310 | !tcpm_cc_is_source((port)->cc2)) || \ | ||
311 | (tcpm_cc_is_source((port)->cc2) && \ | ||
312 | !tcpm_cc_is_source((port)->cc1))) | ||
313 | |||
314 | #define tcpm_port_is_debug(port) \ | ||
315 | (tcpm_cc_is_source((port)->cc1) && tcpm_cc_is_source((port)->cc2)) | ||
316 | |||
317 | #define tcpm_port_is_audio(port) \ | ||
318 | (tcpm_cc_is_audio((port)->cc1) && tcpm_cc_is_audio((port)->cc2)) | ||
319 | |||
320 | #define tcpm_port_is_audio_detached(port) \ | ||
321 | ((tcpm_cc_is_audio((port)->cc1) && tcpm_cc_is_open((port)->cc2)) || \ | ||
322 | (tcpm_cc_is_audio((port)->cc2) && tcpm_cc_is_open((port)->cc1))) | ||
323 | |||
324 | #define tcpm_try_snk(port) \ | ||
325 | ((port)->try_snk_count == 0 && (port)->try_role == TYPEC_SINK) | ||
326 | |||
327 | #define tcpm_try_src(port) \ | ||
328 | ((port)->try_src_count == 0 && (port)->try_role == TYPEC_SOURCE) | ||
329 | |||
330 | static enum tcpm_state tcpm_default_state(struct tcpm_port *port) | ||
331 | { | ||
332 | if (port->try_role == TYPEC_SINK) | ||
333 | return SNK_UNATTACHED; | ||
334 | else if (port->try_role == TYPEC_SOURCE) | ||
335 | return SRC_UNATTACHED; | ||
336 | else if (port->tcpc->config->default_role == TYPEC_SINK) | ||
337 | return SNK_UNATTACHED; | ||
338 | return SRC_UNATTACHED; | ||
339 | } | ||
340 | |||
341 | static inline | ||
342 | struct tcpm_port *typec_cap_to_tcpm(const struct typec_capability *cap) | ||
343 | { | ||
344 | return container_of(cap, struct tcpm_port, typec_caps); | ||
345 | } | ||
346 | |||
347 | static bool tcpm_port_is_disconnected(struct tcpm_port *port) | ||
348 | { | ||
349 | return (!port->attached && port->cc1 == TYPEC_CC_OPEN && | ||
350 | port->cc2 == TYPEC_CC_OPEN) || | ||
351 | (port->attached && ((port->polarity == TYPEC_POLARITY_CC1 && | ||
352 | port->cc1 == TYPEC_CC_OPEN) || | ||
353 | (port->polarity == TYPEC_POLARITY_CC2 && | ||
354 | port->cc2 == TYPEC_CC_OPEN))); | ||
355 | } | ||
356 | |||
357 | /* | ||
358 | * Logging | ||
359 | */ | ||
360 | |||
361 | #ifdef CONFIG_DEBUG_FS | ||
362 | |||
363 | static bool tcpm_log_full(struct tcpm_port *port) | ||
364 | { | ||
365 | return port->logbuffer_tail == | ||
366 | (port->logbuffer_head + 1) % LOG_BUFFER_ENTRIES; | ||
367 | } | ||
368 | |||
369 | static void _tcpm_log(struct tcpm_port *port, const char *fmt, va_list args) | ||
370 | { | ||
371 | char tmpbuffer[LOG_BUFFER_ENTRY_SIZE]; | ||
372 | u64 ts_nsec = local_clock(); | ||
373 | unsigned long rem_nsec; | ||
374 | |||
375 | if (!port->logbuffer[port->logbuffer_head]) { | ||
376 | port->logbuffer[port->logbuffer_head] = | ||
377 | kzalloc(LOG_BUFFER_ENTRY_SIZE, GFP_KERNEL); | ||
378 | if (!port->logbuffer[port->logbuffer_head]) | ||
379 | return; | ||
380 | } | ||
381 | |||
382 | vsnprintf(tmpbuffer, sizeof(tmpbuffer), fmt, args); | ||
383 | |||
384 | mutex_lock(&port->logbuffer_lock); | ||
385 | |||
386 | if (tcpm_log_full(port)) { | ||
387 | port->logbuffer_head = max(port->logbuffer_head - 1, 0); | ||
388 | strcpy(tmpbuffer, "overflow"); | ||
389 | } | ||
390 | |||
391 | if (port->logbuffer_head < 0 || | ||
392 | port->logbuffer_head >= LOG_BUFFER_ENTRIES) { | ||
393 | dev_warn(port->dev, | ||
394 | "Bad log buffer index %d\n", port->logbuffer_head); | ||
395 | goto abort; | ||
396 | } | ||
397 | |||
398 | if (!port->logbuffer[port->logbuffer_head]) { | ||
399 | dev_warn(port->dev, | ||
400 | "Log buffer index %d is NULL\n", port->logbuffer_head); | ||
401 | goto abort; | ||
402 | } | ||
403 | |||
404 | rem_nsec = do_div(ts_nsec, 1000000000); | ||
405 | scnprintf(port->logbuffer[port->logbuffer_head], | ||
406 | LOG_BUFFER_ENTRY_SIZE, "[%5lu.%06lu] %s", | ||
407 | (unsigned long)ts_nsec, rem_nsec / 1000, | ||
408 | tmpbuffer); | ||
409 | port->logbuffer_head = (port->logbuffer_head + 1) % LOG_BUFFER_ENTRIES; | ||
410 | |||
411 | abort: | ||
412 | mutex_unlock(&port->logbuffer_lock); | ||
413 | } | ||
414 | |||
415 | static void tcpm_log(struct tcpm_port *port, const char *fmt, ...) | ||
416 | { | ||
417 | va_list args; | ||
418 | |||
419 | /* Do not log while disconnected and unattached */ | ||
420 | if (tcpm_port_is_disconnected(port) && | ||
421 | (port->state == SRC_UNATTACHED || port->state == SNK_UNATTACHED || | ||
422 | port->state == DRP_TOGGLING)) | ||
423 | return; | ||
424 | |||
425 | va_start(args, fmt); | ||
426 | _tcpm_log(port, fmt, args); | ||
427 | va_end(args); | ||
428 | } | ||
429 | |||
430 | static void tcpm_log_force(struct tcpm_port *port, const char *fmt, ...) | ||
431 | { | ||
432 | va_list args; | ||
433 | |||
434 | va_start(args, fmt); | ||
435 | _tcpm_log(port, fmt, args); | ||
436 | va_end(args); | ||
437 | } | ||
438 | |||
439 | static void tcpm_log_source_caps(struct tcpm_port *port) | ||
440 | { | ||
441 | int i; | ||
442 | |||
443 | for (i = 0; i < port->nr_source_caps; i++) { | ||
444 | u32 pdo = port->source_caps[i]; | ||
445 | enum pd_pdo_type type = pdo_type(pdo); | ||
446 | char msg[64]; | ||
447 | |||
448 | switch (type) { | ||
449 | case PDO_TYPE_FIXED: | ||
450 | scnprintf(msg, sizeof(msg), | ||
451 | "%u mV, %u mA [%s%s%s%s%s%s]", | ||
452 | pdo_fixed_voltage(pdo), | ||
453 | pdo_max_current(pdo), | ||
454 | (pdo & PDO_FIXED_DUAL_ROLE) ? | ||
455 | "R" : "", | ||
456 | (pdo & PDO_FIXED_SUSPEND) ? | ||
457 | "S" : "", | ||
458 | (pdo & PDO_FIXED_HIGHER_CAP) ? | ||
459 | "H" : "", | ||
460 | (pdo & PDO_FIXED_USB_COMM) ? | ||
461 | "U" : "", | ||
462 | (pdo & PDO_FIXED_DATA_SWAP) ? | ||
463 | "D" : "", | ||
464 | (pdo & PDO_FIXED_EXTPOWER) ? | ||
465 | "E" : ""); | ||
466 | break; | ||
467 | case PDO_TYPE_VAR: | ||
468 | scnprintf(msg, sizeof(msg), | ||
469 | "%u-%u mV, %u mA", | ||
470 | pdo_min_voltage(pdo), | ||
471 | pdo_max_voltage(pdo), | ||
472 | pdo_max_current(pdo)); | ||
473 | break; | ||
474 | case PDO_TYPE_BATT: | ||
475 | scnprintf(msg, sizeof(msg), | ||
476 | "%u-%u mV, %u mW", | ||
477 | pdo_min_voltage(pdo), | ||
478 | pdo_max_voltage(pdo), | ||
479 | pdo_max_power(pdo)); | ||
480 | break; | ||
481 | default: | ||
482 | strcpy(msg, "undefined"); | ||
483 | break; | ||
484 | } | ||
485 | tcpm_log(port, " PDO %d: type %d, %s", | ||
486 | i, type, msg); | ||
487 | } | ||
488 | } | ||
489 | |||
490 | static int tcpm_seq_show(struct seq_file *s, void *v) | ||
491 | { | ||
492 | struct tcpm_port *port = (struct tcpm_port *)s->private; | ||
493 | int tail; | ||
494 | |||
495 | mutex_lock(&port->logbuffer_lock); | ||
496 | tail = port->logbuffer_tail; | ||
497 | while (tail != port->logbuffer_head) { | ||
498 | seq_printf(s, "%s\n", port->logbuffer[tail]); | ||
499 | tail = (tail + 1) % LOG_BUFFER_ENTRIES; | ||
500 | } | ||
501 | if (!seq_has_overflowed(s)) | ||
502 | port->logbuffer_tail = tail; | ||
503 | mutex_unlock(&port->logbuffer_lock); | ||
504 | |||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | static int tcpm_debug_open(struct inode *inode, struct file *file) | ||
509 | { | ||
510 | return single_open(file, tcpm_seq_show, inode->i_private); | ||
511 | } | ||
512 | |||
513 | static const struct file_operations tcpm_debug_operations = { | ||
514 | .open = tcpm_debug_open, | ||
515 | .llseek = seq_lseek, | ||
516 | .read = seq_read, | ||
517 | .release = single_release, | ||
518 | }; | ||
519 | |||
520 | static struct dentry *rootdir; | ||
521 | |||
522 | static int tcpm_debugfs_init(struct tcpm_port *port) | ||
523 | { | ||
524 | mutex_init(&port->logbuffer_lock); | ||
525 | /* /sys/kernel/debug/tcpm/usbcX */ | ||
526 | if (!rootdir) { | ||
527 | rootdir = debugfs_create_dir("tcpm", NULL); | ||
528 | if (!rootdir) | ||
529 | return -ENOMEM; | ||
530 | } | ||
531 | |||
532 | port->dentry = debugfs_create_file(dev_name(port->dev), | ||
533 | S_IFREG | 0444, rootdir, | ||
534 | port, &tcpm_debug_operations); | ||
535 | |||
536 | return 0; | ||
537 | } | ||
538 | |||
539 | static void tcpm_debugfs_exit(struct tcpm_port *port) | ||
540 | { | ||
541 | debugfs_remove(port->dentry); | ||
542 | } | ||
543 | |||
544 | #else | ||
545 | |||
546 | static void tcpm_log(const struct tcpm_port *port, const char *fmt, ...) { } | ||
547 | static void tcpm_log_force(struct tcpm_port *port, const char *fmt, ...) { } | ||
548 | static void tcpm_log_source_caps(struct tcpm_port *port) { } | ||
549 | static int tcpm_debugfs_init(const struct tcpm_port *port) { return 0; } | ||
550 | static void tcpm_debugfs_exit(const struct tcpm_port *port) { } | ||
551 | |||
552 | #endif | ||
553 | |||
554 | static int tcpm_pd_transmit(struct tcpm_port *port, | ||
555 | enum tcpm_transmit_type type, | ||
556 | const struct pd_message *msg) | ||
557 | { | ||
558 | unsigned long timeout; | ||
559 | int ret; | ||
560 | |||
561 | if (msg) | ||
562 | tcpm_log(port, "PD TX, header: %#x", le16_to_cpu(msg->header)); | ||
563 | else | ||
564 | tcpm_log(port, "PD TX, type: %#x", type); | ||
565 | |||
566 | reinit_completion(&port->tx_complete); | ||
567 | ret = port->tcpc->pd_transmit(port->tcpc, type, msg); | ||
568 | if (ret < 0) | ||
569 | return ret; | ||
570 | |||
571 | mutex_unlock(&port->lock); | ||
572 | timeout = wait_for_completion_timeout(&port->tx_complete, | ||
573 | msecs_to_jiffies(PD_T_TCPC_TX_TIMEOUT)); | ||
574 | mutex_lock(&port->lock); | ||
575 | if (!timeout) | ||
576 | return -ETIMEDOUT; | ||
577 | |||
578 | switch (port->tx_status) { | ||
579 | case TCPC_TX_SUCCESS: | ||
580 | port->message_id = (port->message_id + 1) & PD_HEADER_ID_MASK; | ||
581 | return 0; | ||
582 | case TCPC_TX_DISCARDED: | ||
583 | return -EAGAIN; | ||
584 | case TCPC_TX_FAILED: | ||
585 | default: | ||
586 | return -EIO; | ||
587 | } | ||
588 | } | ||
589 | |||
590 | void tcpm_pd_transmit_complete(struct tcpm_port *port, | ||
591 | enum tcpm_transmit_status status) | ||
592 | { | ||
593 | tcpm_log(port, "PD TX complete, status: %u", status); | ||
594 | port->tx_status = status; | ||
595 | complete(&port->tx_complete); | ||
596 | } | ||
597 | EXPORT_SYMBOL_GPL(tcpm_pd_transmit_complete); | ||
598 | |||
599 | static int tcpm_mux_set(struct tcpm_port *port, enum tcpc_mux_mode mode, | ||
600 | enum tcpc_usb_switch config) | ||
601 | { | ||
602 | int ret = 0; | ||
603 | |||
604 | tcpm_log(port, "Requesting mux mode %d, config %d, polarity %d", | ||
605 | mode, config, port->polarity); | ||
606 | |||
607 | if (port->tcpc->mux) | ||
608 | ret = port->tcpc->mux->set(port->tcpc->mux, mode, config, | ||
609 | port->polarity); | ||
610 | |||
611 | return ret; | ||
612 | } | ||
613 | |||
614 | static int tcpm_set_polarity(struct tcpm_port *port, | ||
615 | enum typec_cc_polarity polarity) | ||
616 | { | ||
617 | int ret; | ||
618 | |||
619 | tcpm_log(port, "polarity %d", polarity); | ||
620 | |||
621 | ret = port->tcpc->set_polarity(port->tcpc, polarity); | ||
622 | if (ret < 0) | ||
623 | return ret; | ||
624 | |||
625 | port->polarity = polarity; | ||
626 | |||
627 | return 0; | ||
628 | } | ||
629 | |||
630 | static int tcpm_set_vconn(struct tcpm_port *port, bool enable) | ||
631 | { | ||
632 | int ret; | ||
633 | |||
634 | tcpm_log(port, "vconn:=%d", enable); | ||
635 | |||
636 | ret = port->tcpc->set_vconn(port->tcpc, enable); | ||
637 | if (!ret) { | ||
638 | port->vconn_role = enable ? TYPEC_SOURCE : TYPEC_SINK; | ||
639 | typec_set_vconn_role(port->typec_port, port->vconn_role); | ||
640 | } | ||
641 | |||
642 | return ret; | ||
643 | } | ||
644 | |||
645 | static u32 tcpm_get_current_limit(struct tcpm_port *port) | ||
646 | { | ||
647 | enum typec_cc_status cc; | ||
648 | u32 limit; | ||
649 | |||
650 | cc = port->polarity ? port->cc2 : port->cc1; | ||
651 | switch (cc) { | ||
652 | case TYPEC_CC_RP_1_5: | ||
653 | limit = 1500; | ||
654 | break; | ||
655 | case TYPEC_CC_RP_3_0: | ||
656 | limit = 3000; | ||
657 | break; | ||
658 | case TYPEC_CC_RP_DEF: | ||
659 | default: | ||
660 | limit = 0; | ||
661 | break; | ||
662 | } | ||
663 | |||
664 | return limit; | ||
665 | } | ||
666 | |||
667 | static int tcpm_set_current_limit(struct tcpm_port *port, u32 max_ma, u32 mv) | ||
668 | { | ||
669 | int ret = -EOPNOTSUPP; | ||
670 | |||
671 | tcpm_log(port, "Setting voltage/current limit %u mV %u mA", mv, max_ma); | ||
672 | |||
673 | if (port->tcpc->set_current_limit) | ||
674 | ret = port->tcpc->set_current_limit(port->tcpc, max_ma, mv); | ||
675 | |||
676 | return ret; | ||
677 | } | ||
678 | |||
679 | /* | ||
680 | * Determine RP value to set based on maximum current supported | ||
681 | * by a port if configured as source. | ||
682 | * Returns CC value to report to link partner. | ||
683 | */ | ||
684 | static enum typec_cc_status tcpm_rp_cc(struct tcpm_port *port) | ||
685 | { | ||
686 | const u32 *src_pdo = port->src_pdo; | ||
687 | int nr_pdo = port->nr_src_pdo; | ||
688 | int i; | ||
689 | |||
690 | /* | ||
691 | * Search for first entry with matching voltage. | ||
692 | * It should report the maximum supported current. | ||
693 | */ | ||
694 | for (i = 0; i < nr_pdo; i++) { | ||
695 | const u32 pdo = src_pdo[i]; | ||
696 | |||
697 | if (pdo_type(pdo) == PDO_TYPE_FIXED && | ||
698 | pdo_fixed_voltage(pdo) == 5000) { | ||
699 | unsigned int curr = pdo_max_current(pdo); | ||
700 | |||
701 | if (curr >= 3000) | ||
702 | return TYPEC_CC_RP_3_0; | ||
703 | else if (curr >= 1500) | ||
704 | return TYPEC_CC_RP_1_5; | ||
705 | return TYPEC_CC_RP_DEF; | ||
706 | } | ||
707 | } | ||
708 | |||
709 | return TYPEC_CC_RP_DEF; | ||
710 | } | ||
711 | |||
712 | static int tcpm_set_attached_state(struct tcpm_port *port, bool attached) | ||
713 | { | ||
714 | return port->tcpc->set_roles(port->tcpc, attached, port->pwr_role, | ||
715 | port->data_role); | ||
716 | } | ||
717 | |||
718 | static int tcpm_set_roles(struct tcpm_port *port, bool attached, | ||
719 | enum typec_role role, enum typec_data_role data) | ||
720 | { | ||
721 | int ret; | ||
722 | |||
723 | if (data == TYPEC_HOST) | ||
724 | ret = tcpm_mux_set(port, TYPEC_MUX_USB, | ||
725 | TCPC_USB_SWITCH_CONNECT); | ||
726 | else | ||
727 | ret = tcpm_mux_set(port, TYPEC_MUX_NONE, | ||
728 | TCPC_USB_SWITCH_DISCONNECT); | ||
729 | if (ret < 0) | ||
730 | return ret; | ||
731 | |||
732 | ret = port->tcpc->set_roles(port->tcpc, attached, role, data); | ||
733 | if (ret < 0) | ||
734 | return ret; | ||
735 | |||
736 | port->pwr_role = role; | ||
737 | port->data_role = data; | ||
738 | typec_set_data_role(port->typec_port, data); | ||
739 | typec_set_pwr_role(port->typec_port, role); | ||
740 | |||
741 | return 0; | ||
742 | } | ||
743 | |||
744 | static int tcpm_set_pwr_role(struct tcpm_port *port, enum typec_role role) | ||
745 | { | ||
746 | int ret; | ||
747 | |||
748 | ret = port->tcpc->set_roles(port->tcpc, true, role, | ||
749 | port->data_role); | ||
750 | if (ret < 0) | ||
751 | return ret; | ||
752 | |||
753 | port->pwr_role = role; | ||
754 | typec_set_pwr_role(port->typec_port, role); | ||
755 | |||
756 | return 0; | ||
757 | } | ||
758 | |||
759 | static int tcpm_pd_send_source_caps(struct tcpm_port *port) | ||
760 | { | ||
761 | struct pd_message msg; | ||
762 | int i; | ||
763 | |||
764 | memset(&msg, 0, sizeof(msg)); | ||
765 | if (!port->nr_src_pdo) { | ||
766 | /* No source capabilities defined, sink only */ | ||
767 | msg.header = PD_HEADER_LE(PD_CTRL_REJECT, | ||
768 | port->pwr_role, | ||
769 | port->data_role, | ||
770 | port->message_id, 0); | ||
771 | } else { | ||
772 | msg.header = PD_HEADER_LE(PD_DATA_SOURCE_CAP, | ||
773 | port->pwr_role, | ||
774 | port->data_role, | ||
775 | port->message_id, | ||
776 | port->nr_src_pdo); | ||
777 | } | ||
778 | for (i = 0; i < port->nr_src_pdo; i++) | ||
779 | msg.payload[i] = cpu_to_le32(port->src_pdo[i]); | ||
780 | |||
781 | return tcpm_pd_transmit(port, TCPC_TX_SOP, &msg); | ||
782 | } | ||
783 | |||
784 | static int tcpm_pd_send_sink_caps(struct tcpm_port *port) | ||
785 | { | ||
786 | struct pd_message msg; | ||
787 | int i; | ||
788 | |||
789 | memset(&msg, 0, sizeof(msg)); | ||
790 | if (!port->nr_snk_pdo) { | ||
791 | /* No sink capabilities defined, source only */ | ||
792 | msg.header = PD_HEADER_LE(PD_CTRL_REJECT, | ||
793 | port->pwr_role, | ||
794 | port->data_role, | ||
795 | port->message_id, 0); | ||
796 | } else { | ||
797 | msg.header = PD_HEADER_LE(PD_DATA_SINK_CAP, | ||
798 | port->pwr_role, | ||
799 | port->data_role, | ||
800 | port->message_id, | ||
801 | port->nr_snk_pdo); | ||
802 | } | ||
803 | for (i = 0; i < port->nr_snk_pdo; i++) | ||
804 | msg.payload[i] = cpu_to_le32(port->snk_pdo[i]); | ||
805 | |||
806 | return tcpm_pd_transmit(port, TCPC_TX_SOP, &msg); | ||
807 | } | ||
808 | |||
809 | static void tcpm_set_state(struct tcpm_port *port, enum tcpm_state state, | ||
810 | unsigned int delay_ms) | ||
811 | { | ||
812 | if (delay_ms) { | ||
813 | tcpm_log(port, "pending state change %s -> %s @ %u ms", | ||
814 | tcpm_states[port->state], tcpm_states[state], | ||
815 | delay_ms); | ||
816 | port->delayed_state = state; | ||
817 | mod_delayed_work(port->wq, &port->state_machine, | ||
818 | msecs_to_jiffies(delay_ms)); | ||
819 | port->delayed_runtime = jiffies + msecs_to_jiffies(delay_ms); | ||
820 | port->delay_ms = delay_ms; | ||
821 | } else { | ||
822 | tcpm_log(port, "state change %s -> %s", | ||
823 | tcpm_states[port->state], tcpm_states[state]); | ||
824 | port->delayed_state = INVALID_STATE; | ||
825 | port->prev_state = port->state; | ||
826 | port->state = state; | ||
827 | /* | ||
828 | * Don't re-queue the state machine work item if we're currently | ||
829 | * in the state machine and we're immediately changing states. | ||
830 | * tcpm_state_machine_work() will continue running the state | ||
831 | * machine. | ||
832 | */ | ||
833 | if (!port->state_machine_running) | ||
834 | mod_delayed_work(port->wq, &port->state_machine, 0); | ||
835 | } | ||
836 | } | ||
837 | |||
838 | static void tcpm_set_state_cond(struct tcpm_port *port, enum tcpm_state state, | ||
839 | unsigned int delay_ms) | ||
840 | { | ||
841 | if (port->enter_state == port->state) | ||
842 | tcpm_set_state(port, state, delay_ms); | ||
843 | else | ||
844 | tcpm_log(port, | ||
845 | "skipped %sstate change %s -> %s [%u ms], context state %s", | ||
846 | delay_ms ? "delayed " : "", | ||
847 | tcpm_states[port->state], tcpm_states[state], | ||
848 | delay_ms, tcpm_states[port->enter_state]); | ||
849 | } | ||
850 | |||
851 | static void tcpm_queue_message(struct tcpm_port *port, | ||
852 | enum pd_msg_request message) | ||
853 | { | ||
854 | port->queued_message = message; | ||
855 | mod_delayed_work(port->wq, &port->state_machine, 0); | ||
856 | } | ||
857 | |||
858 | /* | ||
859 | * VDM/VDO handling functions | ||
860 | */ | ||
861 | static void tcpm_queue_vdm(struct tcpm_port *port, const u32 header, | ||
862 | const u32 *data, int cnt) | ||
863 | { | ||
864 | port->vdo_count = cnt + 1; | ||
865 | port->vdo_data[0] = header; | ||
866 | memcpy(&port->vdo_data[1], data, sizeof(u32) * cnt); | ||
867 | /* Set ready, vdm state machine will actually send */ | ||
868 | port->vdm_retries = 0; | ||
869 | port->vdm_state = VDM_STATE_READY; | ||
870 | } | ||
871 | |||
872 | static void svdm_consume_identity(struct tcpm_port *port, const __le32 *payload, | ||
873 | int cnt) | ||
874 | { | ||
875 | u32 vdo = le32_to_cpu(payload[VDO_INDEX_IDH]); | ||
876 | u32 product = le32_to_cpu(payload[VDO_INDEX_PRODUCT]); | ||
877 | |||
878 | memset(&port->mode_data, 0, sizeof(port->mode_data)); | ||
879 | |||
880 | #if 0 /* Not really a match */ | ||
881 | switch (PD_IDH_PTYPE(vdo)) { | ||
882 | case IDH_PTYPE_UNDEF: | ||
883 | port->partner.type = TYPEC_PARTNER_NONE; /* no longer exists */ | ||
884 | break; | ||
885 | case IDH_PTYPE_HUB: | ||
886 | break; | ||
887 | case IDH_PTYPE_PERIPH: | ||
888 | break; | ||
889 | case IDH_PTYPE_PCABLE: | ||
890 | break; | ||
891 | case IDH_PTYPE_ACABLE: | ||
892 | break; | ||
893 | case IDH_PTYPE_AMA: | ||
894 | port->partner.type = TYPEC_PARTNER_ALTMODE; | ||
895 | break; | ||
896 | default: | ||
897 | break; | ||
898 | } | ||
899 | #endif | ||
900 | |||
901 | port->partner_ident.id_header = vdo; | ||
902 | port->partner_ident.cert_stat = le32_to_cpu(payload[VDO_INDEX_CSTAT]); | ||
903 | port->partner_ident.product = product; | ||
904 | |||
905 | typec_partner_set_identity(port->partner); | ||
906 | |||
907 | tcpm_log(port, "Identity: %04x:%04x.%04x", | ||
908 | PD_IDH_VID(vdo), | ||
909 | PD_PRODUCT_PID(product), product & 0xffff); | ||
910 | } | ||
911 | |||
912 | static bool svdm_consume_svids(struct tcpm_port *port, const __le32 *payload, | ||
913 | int cnt) | ||
914 | { | ||
915 | struct pd_mode_data *pmdata = &port->mode_data; | ||
916 | int i; | ||
917 | |||
918 | for (i = 1; i < cnt; i++) { | ||
919 | u32 p = le32_to_cpu(payload[i]); | ||
920 | u16 svid; | ||
921 | |||
922 | svid = (p >> 16) & 0xffff; | ||
923 | if (!svid) | ||
924 | return false; | ||
925 | |||
926 | if (pmdata->nsvids >= SVID_DISCOVERY_MAX) | ||
927 | goto abort; | ||
928 | |||
929 | pmdata->svids[pmdata->nsvids++] = svid; | ||
930 | tcpm_log(port, "SVID %d: 0x%x", pmdata->nsvids, svid); | ||
931 | |||
932 | svid = p & 0xffff; | ||
933 | if (!svid) | ||
934 | return false; | ||
935 | |||
936 | if (pmdata->nsvids >= SVID_DISCOVERY_MAX) | ||
937 | goto abort; | ||
938 | |||
939 | pmdata->svids[pmdata->nsvids++] = svid; | ||
940 | tcpm_log(port, "SVID %d: 0x%x", pmdata->nsvids, svid); | ||
941 | } | ||
942 | return true; | ||
943 | abort: | ||
944 | tcpm_log(port, "SVID_DISCOVERY_MAX(%d) too low!", SVID_DISCOVERY_MAX); | ||
945 | return false; | ||
946 | } | ||
947 | |||
948 | static void svdm_consume_modes(struct tcpm_port *port, const __le32 *payload, | ||
949 | int cnt) | ||
950 | { | ||
951 | struct pd_mode_data *pmdata = &port->mode_data; | ||
952 | struct typec_altmode_desc *paltmode; | ||
953 | struct typec_mode_desc *pmode; | ||
954 | int i; | ||
955 | |||
956 | if (pmdata->altmodes >= ARRAY_SIZE(port->partner_altmode)) { | ||
957 | /* Already logged in svdm_consume_svids() */ | ||
958 | return; | ||
959 | } | ||
960 | |||
961 | paltmode = &pmdata->altmode_desc[pmdata->altmodes]; | ||
962 | memset(paltmode, 0, sizeof(*paltmode)); | ||
963 | |||
964 | paltmode->svid = pmdata->svids[pmdata->svid_index]; | ||
965 | |||
966 | tcpm_log(port, " Alternate mode %d: SVID 0x%04x", | ||
967 | pmdata->altmodes, paltmode->svid); | ||
968 | |||
969 | for (i = 1; i < cnt && paltmode->n_modes < ALTMODE_MAX_MODES; i++) { | ||
970 | pmode = &paltmode->modes[paltmode->n_modes]; | ||
971 | memset(pmode, 0, sizeof(*pmode)); | ||
972 | pmode->vdo = le32_to_cpu(payload[i]); | ||
973 | pmode->index = i - 1; | ||
974 | paltmode->n_modes++; | ||
975 | tcpm_log(port, " VDO %d: 0x%08x", | ||
976 | pmode->index, pmode->vdo); | ||
977 | } | ||
978 | port->partner_altmode[pmdata->altmodes] = | ||
979 | typec_partner_register_altmode(port->partner, paltmode); | ||
980 | if (port->partner_altmode[pmdata->altmodes] == NULL) { | ||
981 | tcpm_log(port, | ||
982 | "Failed to register alternate modes for SVID 0x%04x", | ||
983 | paltmode->svid); | ||
984 | return; | ||
985 | } | ||
986 | pmdata->altmodes++; | ||
987 | } | ||
988 | |||
989 | #define supports_modal(port) PD_IDH_MODAL_SUPP((port)->partner_ident.id_header) | ||
990 | |||
991 | static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt, | ||
992 | u32 *response) | ||
993 | { | ||
994 | u32 p0 = le32_to_cpu(payload[0]); | ||
995 | int cmd_type = PD_VDO_CMDT(p0); | ||
996 | int cmd = PD_VDO_CMD(p0); | ||
997 | struct pd_mode_data *modep; | ||
998 | int rlen = 0; | ||
999 | u16 svid; | ||
1000 | |||
1001 | tcpm_log(port, "Rx VDM cmd 0x%x type %d cmd %d len %d", | ||
1002 | p0, cmd_type, cmd, cnt); | ||
1003 | |||
1004 | modep = &port->mode_data; | ||
1005 | |||
1006 | switch (cmd_type) { | ||
1007 | case CMDT_INIT: | ||
1008 | switch (cmd) { | ||
1009 | case CMD_DISCOVER_IDENT: | ||
1010 | break; | ||
1011 | case CMD_DISCOVER_SVID: | ||
1012 | break; | ||
1013 | case CMD_DISCOVER_MODES: | ||
1014 | break; | ||
1015 | case CMD_ENTER_MODE: | ||
1016 | break; | ||
1017 | case CMD_EXIT_MODE: | ||
1018 | break; | ||
1019 | case CMD_ATTENTION: | ||
1020 | break; | ||
1021 | default: | ||
1022 | break; | ||
1023 | } | ||
1024 | if (rlen >= 1) { | ||
1025 | response[0] = p0 | VDO_CMDT(CMDT_RSP_ACK); | ||
1026 | } else if (rlen == 0) { | ||
1027 | response[0] = p0 | VDO_CMDT(CMDT_RSP_NAK); | ||
1028 | rlen = 1; | ||
1029 | } else { | ||
1030 | response[0] = p0 | VDO_CMDT(CMDT_RSP_BUSY); | ||
1031 | rlen = 1; | ||
1032 | } | ||
1033 | break; | ||
1034 | case CMDT_RSP_ACK: | ||
1035 | /* silently drop message if we are not connected */ | ||
1036 | if (!port->partner) | ||
1037 | break; | ||
1038 | |||
1039 | switch (cmd) { | ||
1040 | case CMD_DISCOVER_IDENT: | ||
1041 | /* 6.4.4.3.1 */ | ||
1042 | svdm_consume_identity(port, payload, cnt); | ||
1043 | response[0] = VDO(USB_SID_PD, 1, CMD_DISCOVER_SVID); | ||
1044 | rlen = 1; | ||
1045 | break; | ||
1046 | case CMD_DISCOVER_SVID: | ||
1047 | /* 6.4.4.3.2 */ | ||
1048 | if (svdm_consume_svids(port, payload, cnt)) { | ||
1049 | response[0] = VDO(USB_SID_PD, 1, | ||
1050 | CMD_DISCOVER_SVID); | ||
1051 | rlen = 1; | ||
1052 | } else if (modep->nsvids && supports_modal(port)) { | ||
1053 | response[0] = VDO(modep->svids[0], 1, | ||
1054 | CMD_DISCOVER_MODES); | ||
1055 | rlen = 1; | ||
1056 | } | ||
1057 | break; | ||
1058 | case CMD_DISCOVER_MODES: | ||
1059 | /* 6.4.4.3.3 */ | ||
1060 | svdm_consume_modes(port, payload, cnt); | ||
1061 | modep->svid_index++; | ||
1062 | if (modep->svid_index < modep->nsvids) { | ||
1063 | svid = modep->svids[modep->svid_index]; | ||
1064 | response[0] = VDO(svid, 1, CMD_DISCOVER_MODES); | ||
1065 | rlen = 1; | ||
1066 | } else { | ||
1067 | #if 0 | ||
1068 | response[0] = pd_dfp_enter_mode(port, 0, 0); | ||
1069 | if (response[0]) | ||
1070 | rlen = 1; | ||
1071 | #endif | ||
1072 | } | ||
1073 | break; | ||
1074 | case CMD_ENTER_MODE: | ||
1075 | break; | ||
1076 | default: | ||
1077 | break; | ||
1078 | } | ||
1079 | break; | ||
1080 | default: | ||
1081 | break; | ||
1082 | } | ||
1083 | |||
1084 | return rlen; | ||
1085 | } | ||
1086 | |||
1087 | static void tcpm_handle_vdm_request(struct tcpm_port *port, | ||
1088 | const __le32 *payload, int cnt) | ||
1089 | { | ||
1090 | int rlen = 0; | ||
1091 | u32 response[8] = { }; | ||
1092 | u32 p0 = le32_to_cpu(payload[0]); | ||
1093 | |||
1094 | if (port->vdm_state == VDM_STATE_BUSY) { | ||
1095 | /* If UFP responded busy retry after timeout */ | ||
1096 | if (PD_VDO_CMDT(p0) == CMDT_RSP_BUSY) { | ||
1097 | port->vdm_state = VDM_STATE_WAIT_RSP_BUSY; | ||
1098 | port->vdo_retry = (p0 & ~VDO_CMDT_MASK) | | ||
1099 | CMDT_INIT; | ||
1100 | mod_delayed_work(port->wq, &port->vdm_state_machine, | ||
1101 | msecs_to_jiffies(PD_T_VDM_BUSY)); | ||
1102 | return; | ||
1103 | } | ||
1104 | port->vdm_state = VDM_STATE_DONE; | ||
1105 | } | ||
1106 | |||
1107 | if (PD_VDO_SVDM(p0)) | ||
1108 | rlen = tcpm_pd_svdm(port, payload, cnt, response); | ||
1109 | #if 0 | ||
1110 | else | ||
1111 | rlen = tcpm_pd_custom_vdm(port, cnt, payload, response); | ||
1112 | #endif | ||
1113 | |||
1114 | if (rlen > 0) { | ||
1115 | tcpm_queue_vdm(port, response[0], &response[1], rlen - 1); | ||
1116 | mod_delayed_work(port->wq, &port->vdm_state_machine, 0); | ||
1117 | } | ||
1118 | } | ||
1119 | |||
1120 | static void tcpm_send_vdm(struct tcpm_port *port, u32 vid, int cmd, | ||
1121 | const u32 *data, int count) | ||
1122 | { | ||
1123 | u32 header; | ||
1124 | |||
1125 | if (WARN_ON(count > VDO_MAX_SIZE - 1)) | ||
1126 | count = VDO_MAX_SIZE - 1; | ||
1127 | |||
1128 | /* set VDM header with VID & CMD */ | ||
1129 | header = VDO(vid, ((vid & USB_SID_PD) == USB_SID_PD) ? | ||
1130 | 1 : (PD_VDO_CMD(cmd) <= CMD_ATTENTION), cmd); | ||
1131 | tcpm_queue_vdm(port, header, data, count); | ||
1132 | |||
1133 | mod_delayed_work(port->wq, &port->vdm_state_machine, 0); | ||
1134 | } | ||
1135 | |||
1136 | static unsigned int vdm_ready_timeout(u32 vdm_hdr) | ||
1137 | { | ||
1138 | unsigned int timeout; | ||
1139 | int cmd = PD_VDO_CMD(vdm_hdr); | ||
1140 | |||
1141 | /* its not a structured VDM command */ | ||
1142 | if (!PD_VDO_SVDM(vdm_hdr)) | ||
1143 | return PD_T_VDM_UNSTRUCTURED; | ||
1144 | |||
1145 | switch (PD_VDO_CMDT(vdm_hdr)) { | ||
1146 | case CMDT_INIT: | ||
1147 | if (cmd == CMD_ENTER_MODE || cmd == CMD_EXIT_MODE) | ||
1148 | timeout = PD_T_VDM_WAIT_MODE_E; | ||
1149 | else | ||
1150 | timeout = PD_T_VDM_SNDR_RSP; | ||
1151 | break; | ||
1152 | default: | ||
1153 | if (cmd == CMD_ENTER_MODE || cmd == CMD_EXIT_MODE) | ||
1154 | timeout = PD_T_VDM_E_MODE; | ||
1155 | else | ||
1156 | timeout = PD_T_VDM_RCVR_RSP; | ||
1157 | break; | ||
1158 | } | ||
1159 | return timeout; | ||
1160 | } | ||
1161 | |||
1162 | static void vdm_run_state_machine(struct tcpm_port *port) | ||
1163 | { | ||
1164 | struct pd_message msg; | ||
1165 | int i, res; | ||
1166 | |||
1167 | switch (port->vdm_state) { | ||
1168 | case VDM_STATE_READY: | ||
1169 | /* Only transmit VDM if attached */ | ||
1170 | if (!port->attached) { | ||
1171 | port->vdm_state = VDM_STATE_ERR_BUSY; | ||
1172 | break; | ||
1173 | } | ||
1174 | |||
1175 | /* | ||
1176 | * if there's traffic or we're not in PDO ready state don't send | ||
1177 | * a VDM. | ||
1178 | */ | ||
1179 | if (port->state != SRC_READY && port->state != SNK_READY) | ||
1180 | break; | ||
1181 | |||
1182 | /* Prepare and send VDM */ | ||
1183 | memset(&msg, 0, sizeof(msg)); | ||
1184 | msg.header = PD_HEADER_LE(PD_DATA_VENDOR_DEF, | ||
1185 | port->pwr_role, | ||
1186 | port->data_role, | ||
1187 | port->message_id, port->vdo_count); | ||
1188 | for (i = 0; i < port->vdo_count; i++) | ||
1189 | msg.payload[i] = cpu_to_le32(port->vdo_data[i]); | ||
1190 | res = tcpm_pd_transmit(port, TCPC_TX_SOP, &msg); | ||
1191 | if (res < 0) { | ||
1192 | port->vdm_state = VDM_STATE_ERR_SEND; | ||
1193 | } else { | ||
1194 | unsigned long timeout; | ||
1195 | |||
1196 | port->vdm_retries = 0; | ||
1197 | port->vdm_state = VDM_STATE_BUSY; | ||
1198 | timeout = vdm_ready_timeout(port->vdo_data[0]); | ||
1199 | mod_delayed_work(port->wq, &port->vdm_state_machine, | ||
1200 | timeout); | ||
1201 | } | ||
1202 | break; | ||
1203 | case VDM_STATE_WAIT_RSP_BUSY: | ||
1204 | port->vdo_data[0] = port->vdo_retry; | ||
1205 | port->vdo_count = 1; | ||
1206 | port->vdm_state = VDM_STATE_READY; | ||
1207 | break; | ||
1208 | case VDM_STATE_BUSY: | ||
1209 | port->vdm_state = VDM_STATE_ERR_TMOUT; | ||
1210 | break; | ||
1211 | case VDM_STATE_ERR_SEND: | ||
1212 | /* | ||
1213 | * A partner which does not support USB PD will not reply, | ||
1214 | * so this is not a fatal error. At the same time, some | ||
1215 | * devices may not return GoodCRC under some circumstances, | ||
1216 | * so we need to retry. | ||
1217 | */ | ||
1218 | if (port->vdm_retries < 3) { | ||
1219 | tcpm_log(port, "VDM Tx error, retry"); | ||
1220 | port->vdm_retries++; | ||
1221 | port->vdm_state = VDM_STATE_READY; | ||
1222 | } | ||
1223 | break; | ||
1224 | default: | ||
1225 | break; | ||
1226 | } | ||
1227 | } | ||
1228 | |||
1229 | static void vdm_state_machine_work(struct work_struct *work) | ||
1230 | { | ||
1231 | struct tcpm_port *port = container_of(work, struct tcpm_port, | ||
1232 | vdm_state_machine.work); | ||
1233 | enum vdm_states prev_state; | ||
1234 | |||
1235 | mutex_lock(&port->lock); | ||
1236 | |||
1237 | /* | ||
1238 | * Continue running as long as the port is not busy and there was | ||
1239 | * a state change. | ||
1240 | */ | ||
1241 | do { | ||
1242 | prev_state = port->vdm_state; | ||
1243 | vdm_run_state_machine(port); | ||
1244 | } while (port->vdm_state != prev_state && | ||
1245 | port->vdm_state != VDM_STATE_BUSY); | ||
1246 | |||
1247 | mutex_unlock(&port->lock); | ||
1248 | } | ||
1249 | |||
1250 | /* | ||
1251 | * PD (data, control) command handling functions | ||
1252 | */ | ||
1253 | static void tcpm_pd_data_request(struct tcpm_port *port, | ||
1254 | const struct pd_message *msg) | ||
1255 | { | ||
1256 | enum pd_data_msg_type type = pd_header_type_le(msg->header); | ||
1257 | unsigned int cnt = pd_header_cnt_le(msg->header); | ||
1258 | unsigned int i; | ||
1259 | |||
1260 | switch (type) { | ||
1261 | case PD_DATA_SOURCE_CAP: | ||
1262 | if (port->pwr_role != TYPEC_SINK) | ||
1263 | break; | ||
1264 | |||
1265 | for (i = 0; i < cnt; i++) | ||
1266 | port->source_caps[i] = le32_to_cpu(msg->payload[i]); | ||
1267 | |||
1268 | port->nr_source_caps = cnt; | ||
1269 | |||
1270 | tcpm_log_source_caps(port); | ||
1271 | |||
1272 | /* | ||
1273 | * This message may be received even if VBUS is not | ||
1274 | * present. This is quite unexpected; see USB PD | ||
1275 | * specification, sections 8.3.3.6.3.1 and 8.3.3.6.3.2. | ||
1276 | * However, at the same time, we must be ready to | ||
1277 | * receive this message and respond to it 15ms after | ||
1278 | * receiving PS_RDY during power swap operations, no matter | ||
1279 | * if VBUS is available or not (USB PD specification, | ||
1280 | * section 6.5.9.2). | ||
1281 | * So we need to accept the message either way, | ||
1282 | * but be prepared to keep waiting for VBUS after it was | ||
1283 | * handled. | ||
1284 | */ | ||
1285 | tcpm_set_state(port, SNK_NEGOTIATE_CAPABILITIES, 0); | ||
1286 | break; | ||
1287 | case PD_DATA_REQUEST: | ||
1288 | if (port->pwr_role != TYPEC_SOURCE || | ||
1289 | cnt != 1) { | ||
1290 | tcpm_queue_message(port, PD_MSG_CTRL_REJECT); | ||
1291 | break; | ||
1292 | } | ||
1293 | port->sink_request = le32_to_cpu(msg->payload[0]); | ||
1294 | tcpm_set_state(port, SRC_NEGOTIATE_CAPABILITIES, 0); | ||
1295 | break; | ||
1296 | case PD_DATA_SINK_CAP: | ||
1297 | /* We don't do anything with this at the moment... */ | ||
1298 | for (i = 0; i < cnt; i++) | ||
1299 | port->sink_caps[i] = le32_to_cpu(msg->payload[i]); | ||
1300 | port->nr_sink_caps = cnt; | ||
1301 | break; | ||
1302 | case PD_DATA_VENDOR_DEF: | ||
1303 | tcpm_handle_vdm_request(port, msg->payload, cnt); | ||
1304 | break; | ||
1305 | case PD_DATA_BIST: | ||
1306 | if (port->state == SRC_READY || port->state == SNK_READY) { | ||
1307 | port->bist_request = le32_to_cpu(msg->payload[0]); | ||
1308 | tcpm_set_state(port, BIST_RX, 0); | ||
1309 | } | ||
1310 | break; | ||
1311 | default: | ||
1312 | tcpm_log(port, "Unhandled data message type %#x", type); | ||
1313 | break; | ||
1314 | } | ||
1315 | } | ||
1316 | |||
1317 | static void tcpm_pd_ctrl_request(struct tcpm_port *port, | ||
1318 | const struct pd_message *msg) | ||
1319 | { | ||
1320 | enum pd_ctrl_msg_type type = pd_header_type_le(msg->header); | ||
1321 | enum tcpm_state next_state; | ||
1322 | |||
1323 | switch (type) { | ||
1324 | case PD_CTRL_GOOD_CRC: | ||
1325 | case PD_CTRL_PING: | ||
1326 | break; | ||
1327 | case PD_CTRL_GET_SOURCE_CAP: | ||
1328 | switch (port->state) { | ||
1329 | case SRC_READY: | ||
1330 | case SNK_READY: | ||
1331 | tcpm_queue_message(port, PD_MSG_DATA_SOURCE_CAP); | ||
1332 | break; | ||
1333 | default: | ||
1334 | tcpm_queue_message(port, PD_MSG_CTRL_REJECT); | ||
1335 | break; | ||
1336 | } | ||
1337 | break; | ||
1338 | case PD_CTRL_GET_SINK_CAP: | ||
1339 | switch (port->state) { | ||
1340 | case SRC_READY: | ||
1341 | case SNK_READY: | ||
1342 | tcpm_queue_message(port, PD_MSG_DATA_SINK_CAP); | ||
1343 | break; | ||
1344 | default: | ||
1345 | tcpm_queue_message(port, PD_MSG_CTRL_REJECT); | ||
1346 | break; | ||
1347 | } | ||
1348 | break; | ||
1349 | case PD_CTRL_GOTO_MIN: | ||
1350 | break; | ||
1351 | case PD_CTRL_PS_RDY: | ||
1352 | switch (port->state) { | ||
1353 | case SNK_TRANSITION_SINK: | ||
1354 | if (port->vbus_present) { | ||
1355 | tcpm_set_current_limit(port, | ||
1356 | port->current_limit, | ||
1357 | port->supply_voltage); | ||
1358 | tcpm_set_state(port, SNK_READY, 0); | ||
1359 | } else { | ||
1360 | /* | ||
1361 | * Seen after power swap. Keep waiting for VBUS | ||
1362 | * in a transitional state. | ||
1363 | */ | ||
1364 | tcpm_set_state(port, | ||
1365 | SNK_TRANSITION_SINK_VBUS, 0); | ||
1366 | } | ||
1367 | break; | ||
1368 | case PR_SWAP_SRC_SNK_SOURCE_OFF: | ||
1369 | tcpm_set_state(port, PR_SWAP_SRC_SNK_SINK_ON, 0); | ||
1370 | break; | ||
1371 | case PR_SWAP_SNK_SRC_SINK_OFF: | ||
1372 | tcpm_set_state(port, PR_SWAP_SNK_SRC_SOURCE_ON, 0); | ||
1373 | break; | ||
1374 | case VCONN_SWAP_WAIT_FOR_VCONN: | ||
1375 | tcpm_set_state(port, VCONN_SWAP_TURN_OFF_VCONN, 0); | ||
1376 | break; | ||
1377 | default: | ||
1378 | break; | ||
1379 | } | ||
1380 | break; | ||
1381 | case PD_CTRL_REJECT: | ||
1382 | case PD_CTRL_WAIT: | ||
1383 | switch (port->state) { | ||
1384 | case SNK_NEGOTIATE_CAPABILITIES: | ||
1385 | /* USB PD specification, Figure 8-43 */ | ||
1386 | if (port->explicit_contract) | ||
1387 | next_state = SNK_READY; | ||
1388 | else | ||
1389 | next_state = SNK_WAIT_CAPABILITIES; | ||
1390 | tcpm_set_state(port, next_state, 0); | ||
1391 | break; | ||
1392 | case DR_SWAP_SEND: | ||
1393 | port->swap_status = (type == PD_CTRL_WAIT ? | ||
1394 | -EAGAIN : -EOPNOTSUPP); | ||
1395 | tcpm_set_state(port, DR_SWAP_CANCEL, 0); | ||
1396 | break; | ||
1397 | case PR_SWAP_SEND: | ||
1398 | port->swap_status = (type == PD_CTRL_WAIT ? | ||
1399 | -EAGAIN : -EOPNOTSUPP); | ||
1400 | tcpm_set_state(port, PR_SWAP_CANCEL, 0); | ||
1401 | break; | ||
1402 | case VCONN_SWAP_SEND: | ||
1403 | port->swap_status = (type == PD_CTRL_WAIT ? | ||
1404 | -EAGAIN : -EOPNOTSUPP); | ||
1405 | tcpm_set_state(port, VCONN_SWAP_CANCEL, 0); | ||
1406 | break; | ||
1407 | default: | ||
1408 | break; | ||
1409 | } | ||
1410 | break; | ||
1411 | case PD_CTRL_ACCEPT: | ||
1412 | switch (port->state) { | ||
1413 | case SNK_NEGOTIATE_CAPABILITIES: | ||
1414 | tcpm_set_state(port, SNK_TRANSITION_SINK, 0); | ||
1415 | break; | ||
1416 | case SOFT_RESET_SEND: | ||
1417 | port->message_id = 0; | ||
1418 | if (port->pwr_role == TYPEC_SOURCE) | ||
1419 | next_state = SRC_SEND_CAPABILITIES; | ||
1420 | else | ||
1421 | next_state = SNK_WAIT_CAPABILITIES; | ||
1422 | tcpm_set_state(port, next_state, 0); | ||
1423 | break; | ||
1424 | case DR_SWAP_SEND: | ||
1425 | tcpm_set_state(port, DR_SWAP_CHANGE_DR, 0); | ||
1426 | break; | ||
1427 | case PR_SWAP_SEND: | ||
1428 | tcpm_set_state(port, PR_SWAP_START, 0); | ||
1429 | break; | ||
1430 | case VCONN_SWAP_SEND: | ||
1431 | tcpm_set_state(port, VCONN_SWAP_START, 0); | ||
1432 | break; | ||
1433 | default: | ||
1434 | break; | ||
1435 | } | ||
1436 | break; | ||
1437 | case PD_CTRL_SOFT_RESET: | ||
1438 | tcpm_set_state(port, SOFT_RESET, 0); | ||
1439 | break; | ||
1440 | case PD_CTRL_DR_SWAP: | ||
1441 | if (port->typec_caps.type != TYPEC_PORT_DRP) { | ||
1442 | tcpm_queue_message(port, PD_MSG_CTRL_REJECT); | ||
1443 | break; | ||
1444 | } | ||
1445 | /* | ||
1446 | * XXX | ||
1447 | * 6.3.9: If an alternate mode is active, a request to swap | ||
1448 | * alternate modes shall trigger a port reset. | ||
1449 | */ | ||
1450 | switch (port->state) { | ||
1451 | case SRC_READY: | ||
1452 | case SNK_READY: | ||
1453 | tcpm_set_state(port, DR_SWAP_ACCEPT, 0); | ||
1454 | break; | ||
1455 | default: | ||
1456 | tcpm_queue_message(port, PD_MSG_CTRL_WAIT); | ||
1457 | break; | ||
1458 | } | ||
1459 | break; | ||
1460 | case PD_CTRL_PR_SWAP: | ||
1461 | if (port->typec_caps.type != TYPEC_PORT_DRP) { | ||
1462 | tcpm_queue_message(port, PD_MSG_CTRL_REJECT); | ||
1463 | break; | ||
1464 | } | ||
1465 | switch (port->state) { | ||
1466 | case SRC_READY: | ||
1467 | case SNK_READY: | ||
1468 | tcpm_set_state(port, PR_SWAP_ACCEPT, 0); | ||
1469 | break; | ||
1470 | default: | ||
1471 | tcpm_queue_message(port, PD_MSG_CTRL_WAIT); | ||
1472 | break; | ||
1473 | } | ||
1474 | break; | ||
1475 | case PD_CTRL_VCONN_SWAP: | ||
1476 | switch (port->state) { | ||
1477 | case SRC_READY: | ||
1478 | case SNK_READY: | ||
1479 | tcpm_set_state(port, VCONN_SWAP_ACCEPT, 0); | ||
1480 | break; | ||
1481 | default: | ||
1482 | tcpm_queue_message(port, PD_MSG_CTRL_WAIT); | ||
1483 | break; | ||
1484 | } | ||
1485 | break; | ||
1486 | default: | ||
1487 | tcpm_log(port, "Unhandled ctrl message type %#x", type); | ||
1488 | break; | ||
1489 | } | ||
1490 | } | ||
1491 | |||
1492 | static void tcpm_pd_rx_handler(struct work_struct *work) | ||
1493 | { | ||
1494 | struct pd_rx_event *event = container_of(work, | ||
1495 | struct pd_rx_event, work); | ||
1496 | const struct pd_message *msg = &event->msg; | ||
1497 | unsigned int cnt = pd_header_cnt_le(msg->header); | ||
1498 | struct tcpm_port *port = event->port; | ||
1499 | |||
1500 | mutex_lock(&port->lock); | ||
1501 | |||
1502 | tcpm_log(port, "PD RX, header: %#x [%d]", le16_to_cpu(msg->header), | ||
1503 | port->attached); | ||
1504 | |||
1505 | if (port->attached) { | ||
1506 | /* | ||
1507 | * If both ends believe to be DFP/host, we have a data role | ||
1508 | * mismatch. | ||
1509 | */ | ||
1510 | if (!!(le16_to_cpu(msg->header) & PD_HEADER_DATA_ROLE) == | ||
1511 | (port->data_role == TYPEC_HOST)) { | ||
1512 | tcpm_log(port, | ||
1513 | "Data role mismatch, initiating error recovery"); | ||
1514 | tcpm_set_state(port, ERROR_RECOVERY, 0); | ||
1515 | } else { | ||
1516 | if (cnt) | ||
1517 | tcpm_pd_data_request(port, msg); | ||
1518 | else | ||
1519 | tcpm_pd_ctrl_request(port, msg); | ||
1520 | } | ||
1521 | } | ||
1522 | |||
1523 | mutex_unlock(&port->lock); | ||
1524 | kfree(event); | ||
1525 | } | ||
1526 | |||
1527 | void tcpm_pd_receive(struct tcpm_port *port, const struct pd_message *msg) | ||
1528 | { | ||
1529 | struct pd_rx_event *event; | ||
1530 | |||
1531 | event = kzalloc(sizeof(*event), GFP_ATOMIC); | ||
1532 | if (!event) | ||
1533 | return; | ||
1534 | |||
1535 | INIT_WORK(&event->work, tcpm_pd_rx_handler); | ||
1536 | event->port = port; | ||
1537 | memcpy(&event->msg, msg, sizeof(*msg)); | ||
1538 | queue_work(port->wq, &event->work); | ||
1539 | } | ||
1540 | EXPORT_SYMBOL_GPL(tcpm_pd_receive); | ||
1541 | |||
1542 | static int tcpm_pd_send_control(struct tcpm_port *port, | ||
1543 | enum pd_ctrl_msg_type type) | ||
1544 | { | ||
1545 | struct pd_message msg; | ||
1546 | |||
1547 | memset(&msg, 0, sizeof(msg)); | ||
1548 | msg.header = PD_HEADER_LE(type, port->pwr_role, | ||
1549 | port->data_role, | ||
1550 | port->message_id, 0); | ||
1551 | |||
1552 | return tcpm_pd_transmit(port, TCPC_TX_SOP, &msg); | ||
1553 | } | ||
1554 | |||
1555 | /* | ||
1556 | * Send queued message without affecting state. | ||
1557 | * Return true if state machine should go back to sleep, | ||
1558 | * false otherwise. | ||
1559 | */ | ||
1560 | static bool tcpm_send_queued_message(struct tcpm_port *port) | ||
1561 | { | ||
1562 | enum pd_msg_request queued_message; | ||
1563 | |||
1564 | do { | ||
1565 | queued_message = port->queued_message; | ||
1566 | port->queued_message = PD_MSG_NONE; | ||
1567 | |||
1568 | switch (queued_message) { | ||
1569 | case PD_MSG_CTRL_WAIT: | ||
1570 | tcpm_pd_send_control(port, PD_CTRL_WAIT); | ||
1571 | break; | ||
1572 | case PD_MSG_CTRL_REJECT: | ||
1573 | tcpm_pd_send_control(port, PD_CTRL_REJECT); | ||
1574 | break; | ||
1575 | case PD_MSG_DATA_SINK_CAP: | ||
1576 | tcpm_pd_send_sink_caps(port); | ||
1577 | break; | ||
1578 | case PD_MSG_DATA_SOURCE_CAP: | ||
1579 | tcpm_pd_send_source_caps(port); | ||
1580 | break; | ||
1581 | default: | ||
1582 | break; | ||
1583 | } | ||
1584 | } while (port->queued_message != PD_MSG_NONE); | ||
1585 | |||
1586 | if (port->delayed_state != INVALID_STATE) { | ||
1587 | if (time_is_after_jiffies(port->delayed_runtime)) { | ||
1588 | mod_delayed_work(port->wq, &port->state_machine, | ||
1589 | port->delayed_runtime - jiffies); | ||
1590 | return true; | ||
1591 | } | ||
1592 | port->delayed_state = INVALID_STATE; | ||
1593 | } | ||
1594 | return false; | ||
1595 | } | ||
1596 | |||
1597 | static int tcpm_pd_check_request(struct tcpm_port *port) | ||
1598 | { | ||
1599 | u32 pdo, rdo = port->sink_request; | ||
1600 | unsigned int max, op, pdo_max, index; | ||
1601 | enum pd_pdo_type type; | ||
1602 | |||
1603 | index = rdo_index(rdo); | ||
1604 | if (!index || index > port->nr_src_pdo) | ||
1605 | return -EINVAL; | ||
1606 | |||
1607 | pdo = port->src_pdo[index - 1]; | ||
1608 | type = pdo_type(pdo); | ||
1609 | switch (type) { | ||
1610 | case PDO_TYPE_FIXED: | ||
1611 | case PDO_TYPE_VAR: | ||
1612 | max = rdo_max_current(rdo); | ||
1613 | op = rdo_op_current(rdo); | ||
1614 | pdo_max = pdo_max_current(pdo); | ||
1615 | |||
1616 | if (op > pdo_max) | ||
1617 | return -EINVAL; | ||
1618 | if (max > pdo_max && !(rdo & RDO_CAP_MISMATCH)) | ||
1619 | return -EINVAL; | ||
1620 | |||
1621 | if (type == PDO_TYPE_FIXED) | ||
1622 | tcpm_log(port, | ||
1623 | "Requested %u mV, %u mA for %u / %u mA", | ||
1624 | pdo_fixed_voltage(pdo), pdo_max, op, max); | ||
1625 | else | ||
1626 | tcpm_log(port, | ||
1627 | "Requested %u -> %u mV, %u mA for %u / %u mA", | ||
1628 | pdo_min_voltage(pdo), pdo_max_voltage(pdo), | ||
1629 | pdo_max, op, max); | ||
1630 | break; | ||
1631 | case PDO_TYPE_BATT: | ||
1632 | max = rdo_max_power(rdo); | ||
1633 | op = rdo_op_power(rdo); | ||
1634 | pdo_max = pdo_max_power(pdo); | ||
1635 | |||
1636 | if (op > pdo_max) | ||
1637 | return -EINVAL; | ||
1638 | if (max > pdo_max && !(rdo & RDO_CAP_MISMATCH)) | ||
1639 | return -EINVAL; | ||
1640 | tcpm_log(port, | ||
1641 | "Requested %u -> %u mV, %u mW for %u / %u mW", | ||
1642 | pdo_min_voltage(pdo), pdo_max_voltage(pdo), | ||
1643 | pdo_max, op, max); | ||
1644 | break; | ||
1645 | default: | ||
1646 | return -EINVAL; | ||
1647 | } | ||
1648 | |||
1649 | port->op_vsafe5v = index == 1; | ||
1650 | |||
1651 | return 0; | ||
1652 | } | ||
1653 | |||
1654 | static int tcpm_pd_select_pdo(struct tcpm_port *port) | ||
1655 | { | ||
1656 | unsigned int i, max_mw = 0, max_mv = 0; | ||
1657 | int ret = -EINVAL; | ||
1658 | |||
1659 | /* | ||
1660 | * Select the source PDO providing the most power while staying within | ||
1661 | * the board's voltage limits. Prefer PDO providing exp | ||
1662 | */ | ||
1663 | for (i = 0; i < port->nr_source_caps; i++) { | ||
1664 | u32 pdo = port->source_caps[i]; | ||
1665 | enum pd_pdo_type type = pdo_type(pdo); | ||
1666 | unsigned int mv, ma, mw; | ||
1667 | |||
1668 | if (type == PDO_TYPE_FIXED) | ||
1669 | mv = pdo_fixed_voltage(pdo); | ||
1670 | else | ||
1671 | mv = pdo_min_voltage(pdo); | ||
1672 | |||
1673 | if (type == PDO_TYPE_BATT) { | ||
1674 | mw = pdo_max_power(pdo); | ||
1675 | } else { | ||
1676 | ma = min(pdo_max_current(pdo), | ||
1677 | port->max_snk_ma); | ||
1678 | mw = ma * mv / 1000; | ||
1679 | } | ||
1680 | |||
1681 | /* Perfer higher voltages if available */ | ||
1682 | if ((mw > max_mw || (mw == max_mw && mv > max_mv)) && | ||
1683 | mv <= port->max_snk_mv) { | ||
1684 | ret = i; | ||
1685 | max_mw = mw; | ||
1686 | max_mv = mv; | ||
1687 | } | ||
1688 | } | ||
1689 | |||
1690 | return ret; | ||
1691 | } | ||
1692 | |||
1693 | static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo) | ||
1694 | { | ||
1695 | unsigned int mv, ma, mw, flags; | ||
1696 | unsigned int max_ma, max_mw; | ||
1697 | enum pd_pdo_type type; | ||
1698 | int index; | ||
1699 | u32 pdo; | ||
1700 | |||
1701 | index = tcpm_pd_select_pdo(port); | ||
1702 | if (index < 0) | ||
1703 | return -EINVAL; | ||
1704 | pdo = port->source_caps[index]; | ||
1705 | type = pdo_type(pdo); | ||
1706 | |||
1707 | if (type == PDO_TYPE_FIXED) | ||
1708 | mv = pdo_fixed_voltage(pdo); | ||
1709 | else | ||
1710 | mv = pdo_min_voltage(pdo); | ||
1711 | |||
1712 | /* Select maximum available current within the board's power limit */ | ||
1713 | if (type == PDO_TYPE_BATT) { | ||
1714 | mw = pdo_max_power(pdo); | ||
1715 | ma = 1000 * min(mw, port->max_snk_mw) / mv; | ||
1716 | } else { | ||
1717 | ma = min(pdo_max_current(pdo), | ||
1718 | 1000 * port->max_snk_mw / mv); | ||
1719 | } | ||
1720 | ma = min(ma, port->max_snk_ma); | ||
1721 | |||
1722 | /* XXX: Any other flags need to be set? */ | ||
1723 | flags = 0; | ||
1724 | |||
1725 | /* Set mismatch bit if offered power is less than operating power */ | ||
1726 | mw = ma * mv / 1000; | ||
1727 | max_ma = ma; | ||
1728 | max_mw = mw; | ||
1729 | if (mw < port->operating_snk_mw) { | ||
1730 | flags |= RDO_CAP_MISMATCH; | ||
1731 | max_mw = port->operating_snk_mw; | ||
1732 | max_ma = max_mw * 1000 / mv; | ||
1733 | } | ||
1734 | |||
1735 | tcpm_log(port, "cc=%d cc1=%d cc2=%d vbus=%d vconn=%s polarity=%d", | ||
1736 | port->cc_req, port->cc1, port->cc2, port->vbus_source, | ||
1737 | port->vconn_role == TYPEC_SOURCE ? "source" : "sink", | ||
1738 | port->polarity); | ||
1739 | |||
1740 | if (type == PDO_TYPE_BATT) { | ||
1741 | *rdo = RDO_BATT(index + 1, mw, max_mw, flags); | ||
1742 | |||
1743 | tcpm_log(port, "Requesting PDO %d: %u mV, %u mW%s", | ||
1744 | index, mv, mw, | ||
1745 | flags & RDO_CAP_MISMATCH ? " [mismatch]" : ""); | ||
1746 | } else { | ||
1747 | *rdo = RDO_FIXED(index + 1, ma, max_ma, flags); | ||
1748 | |||
1749 | tcpm_log(port, "Requesting PDO %d: %u mV, %u mA%s", | ||
1750 | index, mv, ma, | ||
1751 | flags & RDO_CAP_MISMATCH ? " [mismatch]" : ""); | ||
1752 | } | ||
1753 | |||
1754 | port->current_limit = ma; | ||
1755 | port->supply_voltage = mv; | ||
1756 | |||
1757 | return 0; | ||
1758 | } | ||
1759 | |||
1760 | static int tcpm_pd_send_request(struct tcpm_port *port) | ||
1761 | { | ||
1762 | struct pd_message msg; | ||
1763 | int ret; | ||
1764 | u32 rdo; | ||
1765 | |||
1766 | ret = tcpm_pd_build_request(port, &rdo); | ||
1767 | if (ret < 0) | ||
1768 | return ret; | ||
1769 | |||
1770 | memset(&msg, 0, sizeof(msg)); | ||
1771 | msg.header = PD_HEADER_LE(PD_DATA_REQUEST, | ||
1772 | port->pwr_role, | ||
1773 | port->data_role, | ||
1774 | port->message_id, 1); | ||
1775 | msg.payload[0] = cpu_to_le32(rdo); | ||
1776 | |||
1777 | return tcpm_pd_transmit(port, TCPC_TX_SOP, &msg); | ||
1778 | } | ||
1779 | |||
1780 | static int tcpm_set_vbus(struct tcpm_port *port, bool enable) | ||
1781 | { | ||
1782 | int ret; | ||
1783 | |||
1784 | if (enable && port->vbus_charge) | ||
1785 | return -EINVAL; | ||
1786 | |||
1787 | tcpm_log(port, "vbus:=%d charge=%d", enable, port->vbus_charge); | ||
1788 | |||
1789 | ret = port->tcpc->set_vbus(port->tcpc, enable, port->vbus_charge); | ||
1790 | if (ret < 0) | ||
1791 | return ret; | ||
1792 | |||
1793 | port->vbus_source = enable; | ||
1794 | return 0; | ||
1795 | } | ||
1796 | |||
1797 | static int tcpm_set_charge(struct tcpm_port *port, bool charge) | ||
1798 | { | ||
1799 | int ret; | ||
1800 | |||
1801 | if (charge && port->vbus_source) | ||
1802 | return -EINVAL; | ||
1803 | |||
1804 | if (charge != port->vbus_charge) { | ||
1805 | tcpm_log(port, "vbus=%d charge:=%d", port->vbus_source, charge); | ||
1806 | ret = port->tcpc->set_vbus(port->tcpc, port->vbus_source, | ||
1807 | charge); | ||
1808 | if (ret < 0) | ||
1809 | return ret; | ||
1810 | } | ||
1811 | port->vbus_charge = charge; | ||
1812 | return 0; | ||
1813 | } | ||
1814 | |||
1815 | static bool tcpm_start_drp_toggling(struct tcpm_port *port) | ||
1816 | { | ||
1817 | int ret; | ||
1818 | |||
1819 | if (port->tcpc->start_drp_toggling && | ||
1820 | port->typec_caps.type == TYPEC_PORT_DRP) { | ||
1821 | tcpm_log_force(port, "Start DRP toggling"); | ||
1822 | ret = port->tcpc->start_drp_toggling(port->tcpc, | ||
1823 | tcpm_rp_cc(port)); | ||
1824 | if (!ret) | ||
1825 | return true; | ||
1826 | } | ||
1827 | |||
1828 | return false; | ||
1829 | } | ||
1830 | |||
1831 | static void tcpm_set_cc(struct tcpm_port *port, enum typec_cc_status cc) | ||
1832 | { | ||
1833 | tcpm_log(port, "cc:=%d", cc); | ||
1834 | port->cc_req = cc; | ||
1835 | port->tcpc->set_cc(port->tcpc, cc); | ||
1836 | } | ||
1837 | |||
1838 | static int tcpm_init_vbus(struct tcpm_port *port) | ||
1839 | { | ||
1840 | int ret; | ||
1841 | |||
1842 | ret = port->tcpc->set_vbus(port->tcpc, false, false); | ||
1843 | port->vbus_source = false; | ||
1844 | port->vbus_charge = false; | ||
1845 | return ret; | ||
1846 | } | ||
1847 | |||
1848 | static int tcpm_init_vconn(struct tcpm_port *port) | ||
1849 | { | ||
1850 | int ret; | ||
1851 | |||
1852 | ret = port->tcpc->set_vconn(port->tcpc, false); | ||
1853 | port->vconn_role = TYPEC_SINK; | ||
1854 | return ret; | ||
1855 | } | ||
1856 | |||
1857 | static void tcpm_typec_connect(struct tcpm_port *port) | ||
1858 | { | ||
1859 | if (!port->connected) { | ||
1860 | /* Make sure we don't report stale identity information */ | ||
1861 | memset(&port->partner_ident, 0, sizeof(port->partner_ident)); | ||
1862 | port->partner_desc.usb_pd = port->pd_capable; | ||
1863 | if (tcpm_port_is_debug(port)) | ||
1864 | port->partner_desc.accessory = TYPEC_ACCESSORY_DEBUG; | ||
1865 | else if (tcpm_port_is_audio(port)) | ||
1866 | port->partner_desc.accessory = TYPEC_ACCESSORY_AUDIO; | ||
1867 | else | ||
1868 | port->partner_desc.accessory = TYPEC_ACCESSORY_NONE; | ||
1869 | port->partner = typec_register_partner(port->typec_port, | ||
1870 | &port->partner_desc); | ||
1871 | port->connected = true; | ||
1872 | } | ||
1873 | } | ||
1874 | |||
1875 | static int tcpm_src_attach(struct tcpm_port *port) | ||
1876 | { | ||
1877 | enum typec_cc_polarity polarity = | ||
1878 | port->cc2 == TYPEC_CC_RD ? TYPEC_POLARITY_CC2 | ||
1879 | : TYPEC_POLARITY_CC1; | ||
1880 | int ret; | ||
1881 | |||
1882 | if (port->attached) | ||
1883 | return 0; | ||
1884 | |||
1885 | ret = tcpm_set_polarity(port, polarity); | ||
1886 | if (ret < 0) | ||
1887 | return ret; | ||
1888 | |||
1889 | ret = tcpm_set_roles(port, true, TYPEC_SOURCE, TYPEC_HOST); | ||
1890 | if (ret < 0) | ||
1891 | return ret; | ||
1892 | |||
1893 | ret = port->tcpc->set_pd_rx(port->tcpc, true); | ||
1894 | if (ret < 0) | ||
1895 | goto out_disable_mux; | ||
1896 | |||
1897 | /* | ||
1898 | * USB Type-C specification, version 1.2, | ||
1899 | * chapter 4.5.2.2.8.1 (Attached.SRC Requirements) | ||
1900 | * Enable VCONN only if the non-RD port is set to RA. | ||
1901 | */ | ||
1902 | if ((polarity == TYPEC_POLARITY_CC1 && port->cc2 == TYPEC_CC_RA) || | ||
1903 | (polarity == TYPEC_POLARITY_CC2 && port->cc1 == TYPEC_CC_RA)) { | ||
1904 | ret = tcpm_set_vconn(port, true); | ||
1905 | if (ret < 0) | ||
1906 | goto out_disable_pd; | ||
1907 | } | ||
1908 | |||
1909 | ret = tcpm_set_vbus(port, true); | ||
1910 | if (ret < 0) | ||
1911 | goto out_disable_vconn; | ||
1912 | |||
1913 | port->pd_capable = false; | ||
1914 | |||
1915 | port->partner = NULL; | ||
1916 | |||
1917 | port->attached = true; | ||
1918 | port->send_discover = true; | ||
1919 | |||
1920 | return 0; | ||
1921 | |||
1922 | out_disable_vconn: | ||
1923 | tcpm_set_vconn(port, false); | ||
1924 | out_disable_pd: | ||
1925 | port->tcpc->set_pd_rx(port->tcpc, false); | ||
1926 | out_disable_mux: | ||
1927 | tcpm_mux_set(port, TYPEC_MUX_NONE, TCPC_USB_SWITCH_DISCONNECT); | ||
1928 | return ret; | ||
1929 | } | ||
1930 | |||
1931 | static void tcpm_typec_disconnect(struct tcpm_port *port) | ||
1932 | { | ||
1933 | if (port->connected) { | ||
1934 | typec_unregister_partner(port->partner); | ||
1935 | port->partner = NULL; | ||
1936 | port->connected = false; | ||
1937 | } | ||
1938 | } | ||
1939 | |||
1940 | static void tcpm_unregister_altmodes(struct tcpm_port *port) | ||
1941 | { | ||
1942 | struct pd_mode_data *modep = &port->mode_data; | ||
1943 | int i; | ||
1944 | |||
1945 | for (i = 0; i < modep->altmodes; i++) { | ||
1946 | typec_unregister_altmode(port->partner_altmode[i]); | ||
1947 | port->partner_altmode[i] = NULL; | ||
1948 | } | ||
1949 | |||
1950 | memset(modep, 0, sizeof(*modep)); | ||
1951 | } | ||
1952 | |||
1953 | static void tcpm_reset_port(struct tcpm_port *port) | ||
1954 | { | ||
1955 | tcpm_unregister_altmodes(port); | ||
1956 | tcpm_typec_disconnect(port); | ||
1957 | port->attached = false; | ||
1958 | port->pd_capable = false; | ||
1959 | |||
1960 | port->tcpc->set_pd_rx(port->tcpc, false); | ||
1961 | tcpm_init_vbus(port); /* also disables charging */ | ||
1962 | tcpm_init_vconn(port); | ||
1963 | tcpm_set_current_limit(port, 0, 0); | ||
1964 | tcpm_set_polarity(port, TYPEC_POLARITY_CC1); | ||
1965 | tcpm_set_attached_state(port, false); | ||
1966 | port->try_src_count = 0; | ||
1967 | port->try_snk_count = 0; | ||
1968 | } | ||
1969 | |||
1970 | static void tcpm_detach(struct tcpm_port *port) | ||
1971 | { | ||
1972 | if (!port->attached) | ||
1973 | return; | ||
1974 | |||
1975 | if (tcpm_port_is_disconnected(port)) | ||
1976 | port->hard_reset_count = 0; | ||
1977 | |||
1978 | tcpm_reset_port(port); | ||
1979 | } | ||
1980 | |||
1981 | static void tcpm_src_detach(struct tcpm_port *port) | ||
1982 | { | ||
1983 | tcpm_detach(port); | ||
1984 | } | ||
1985 | |||
1986 | static int tcpm_snk_attach(struct tcpm_port *port) | ||
1987 | { | ||
1988 | int ret; | ||
1989 | |||
1990 | if (port->attached) | ||
1991 | return 0; | ||
1992 | |||
1993 | ret = tcpm_set_polarity(port, port->cc2 != TYPEC_CC_OPEN ? | ||
1994 | TYPEC_POLARITY_CC2 : TYPEC_POLARITY_CC1); | ||
1995 | if (ret < 0) | ||
1996 | return ret; | ||
1997 | |||
1998 | ret = tcpm_set_roles(port, true, TYPEC_SINK, TYPEC_DEVICE); | ||
1999 | if (ret < 0) | ||
2000 | return ret; | ||
2001 | |||
2002 | port->pd_capable = false; | ||
2003 | |||
2004 | port->partner = NULL; | ||
2005 | |||
2006 | port->attached = true; | ||
2007 | port->send_discover = true; | ||
2008 | |||
2009 | return 0; | ||
2010 | } | ||
2011 | |||
2012 | static void tcpm_snk_detach(struct tcpm_port *port) | ||
2013 | { | ||
2014 | tcpm_detach(port); | ||
2015 | |||
2016 | /* XXX: (Dis)connect SuperSpeed mux? */ | ||
2017 | } | ||
2018 | |||
2019 | static int tcpm_acc_attach(struct tcpm_port *port) | ||
2020 | { | ||
2021 | int ret; | ||
2022 | |||
2023 | if (port->attached) | ||
2024 | return 0; | ||
2025 | |||
2026 | ret = tcpm_set_roles(port, true, TYPEC_SOURCE, TYPEC_HOST); | ||
2027 | if (ret < 0) | ||
2028 | return ret; | ||
2029 | |||
2030 | port->partner = NULL; | ||
2031 | |||
2032 | tcpm_typec_connect(port); | ||
2033 | |||
2034 | port->attached = true; | ||
2035 | |||
2036 | return 0; | ||
2037 | } | ||
2038 | |||
2039 | static void tcpm_acc_detach(struct tcpm_port *port) | ||
2040 | { | ||
2041 | tcpm_detach(port); | ||
2042 | } | ||
2043 | |||
2044 | static inline enum tcpm_state hard_reset_state(struct tcpm_port *port) | ||
2045 | { | ||
2046 | if (port->hard_reset_count < PD_N_HARD_RESET_COUNT) | ||
2047 | return HARD_RESET_SEND; | ||
2048 | if (port->pd_capable) | ||
2049 | return ERROR_RECOVERY; | ||
2050 | if (port->pwr_role == TYPEC_SOURCE) | ||
2051 | return SRC_UNATTACHED; | ||
2052 | if (port->state == SNK_WAIT_CAPABILITIES) | ||
2053 | return SNK_READY; | ||
2054 | return SNK_UNATTACHED; | ||
2055 | } | ||
2056 | |||
2057 | static inline enum tcpm_state ready_state(struct tcpm_port *port) | ||
2058 | { | ||
2059 | if (port->pwr_role == TYPEC_SOURCE) | ||
2060 | return SRC_READY; | ||
2061 | else | ||
2062 | return SNK_READY; | ||
2063 | } | ||
2064 | |||
2065 | static inline enum tcpm_state unattached_state(struct tcpm_port *port) | ||
2066 | { | ||
2067 | if (port->pwr_role == TYPEC_SOURCE) | ||
2068 | return SRC_UNATTACHED; | ||
2069 | else | ||
2070 | return SNK_UNATTACHED; | ||
2071 | } | ||
2072 | |||
2073 | static void tcpm_check_send_discover(struct tcpm_port *port) | ||
2074 | { | ||
2075 | if (port->data_role == TYPEC_HOST && port->send_discover && | ||
2076 | port->pd_capable) { | ||
2077 | tcpm_send_vdm(port, USB_SID_PD, CMD_DISCOVER_IDENT, NULL, 0); | ||
2078 | port->send_discover = false; | ||
2079 | } | ||
2080 | } | ||
2081 | |||
2082 | static void tcpm_swap_complete(struct tcpm_port *port, int result) | ||
2083 | { | ||
2084 | if (port->swap_pending) { | ||
2085 | port->swap_status = result; | ||
2086 | port->swap_pending = false; | ||
2087 | complete(&port->swap_complete); | ||
2088 | } | ||
2089 | } | ||
2090 | |||
2091 | static void run_state_machine(struct tcpm_port *port) | ||
2092 | { | ||
2093 | int ret; | ||
2094 | |||
2095 | port->enter_state = port->state; | ||
2096 | switch (port->state) { | ||
2097 | case DRP_TOGGLING: | ||
2098 | break; | ||
2099 | /* SRC states */ | ||
2100 | case SRC_UNATTACHED: | ||
2101 | tcpm_swap_complete(port, -ENOTCONN); | ||
2102 | tcpm_src_detach(port); | ||
2103 | if (tcpm_start_drp_toggling(port)) { | ||
2104 | tcpm_set_state(port, DRP_TOGGLING, 0); | ||
2105 | break; | ||
2106 | } | ||
2107 | tcpm_set_cc(port, tcpm_rp_cc(port)); | ||
2108 | if (port->typec_caps.type == TYPEC_PORT_DRP) | ||
2109 | tcpm_set_state(port, SNK_UNATTACHED, PD_T_DRP_SNK); | ||
2110 | break; | ||
2111 | case SRC_ATTACH_WAIT: | ||
2112 | if (tcpm_port_is_debug(port)) | ||
2113 | tcpm_set_state(port, DEBUG_ACC_ATTACHED, | ||
2114 | PD_T_CC_DEBOUNCE); | ||
2115 | else if (tcpm_port_is_audio(port)) | ||
2116 | tcpm_set_state(port, AUDIO_ACC_ATTACHED, | ||
2117 | PD_T_CC_DEBOUNCE); | ||
2118 | else if (tcpm_port_is_source(port)) | ||
2119 | tcpm_set_state(port, | ||
2120 | tcpm_try_snk(port) ? SNK_TRY | ||
2121 | : SRC_ATTACHED, | ||
2122 | PD_T_CC_DEBOUNCE); | ||
2123 | break; | ||
2124 | |||
2125 | case SNK_TRY: | ||
2126 | port->try_snk_count++; | ||
2127 | /* | ||
2128 | * Requirements: | ||
2129 | * - Do not drive vconn or vbus | ||
2130 | * - Terminate CC pins (both) to Rd | ||
2131 | * Action: | ||
2132 | * - Wait for tDRPTry (PD_T_DRP_TRY). | ||
2133 | * Until then, ignore any state changes. | ||
2134 | */ | ||
2135 | tcpm_set_cc(port, TYPEC_CC_RD); | ||
2136 | tcpm_set_state(port, SNK_TRY_WAIT, PD_T_DRP_TRY); | ||
2137 | break; | ||
2138 | case SNK_TRY_WAIT: | ||
2139 | if (port->vbus_present && tcpm_port_is_sink(port)) { | ||
2140 | tcpm_set_state(port, SNK_ATTACHED, 0); | ||
2141 | break; | ||
2142 | } | ||
2143 | if (!tcpm_port_is_sink(port)) { | ||
2144 | tcpm_set_state(port, SRC_TRYWAIT, | ||
2145 | PD_T_PD_DEBOUNCE); | ||
2146 | break; | ||
2147 | } | ||
2148 | /* No vbus, cc state is sink or open */ | ||
2149 | tcpm_set_state(port, SRC_TRYWAIT_UNATTACHED, PD_T_DRP_TRYWAIT); | ||
2150 | break; | ||
2151 | case SRC_TRYWAIT: | ||
2152 | tcpm_set_cc(port, tcpm_rp_cc(port)); | ||
2153 | if (!port->vbus_present && tcpm_port_is_source(port)) | ||
2154 | tcpm_set_state(port, SRC_ATTACHED, PD_T_CC_DEBOUNCE); | ||
2155 | else | ||
2156 | tcpm_set_state(port, SRC_TRYWAIT_UNATTACHED, | ||
2157 | PD_T_DRP_TRY); | ||
2158 | break; | ||
2159 | case SRC_TRYWAIT_UNATTACHED: | ||
2160 | tcpm_set_state(port, SNK_UNATTACHED, 0); | ||
2161 | break; | ||
2162 | |||
2163 | case SRC_ATTACHED: | ||
2164 | ret = tcpm_src_attach(port); | ||
2165 | tcpm_set_state(port, SRC_UNATTACHED, | ||
2166 | ret < 0 ? 0 : PD_T_PS_SOURCE_ON); | ||
2167 | break; | ||
2168 | case SRC_STARTUP: | ||
2169 | typec_set_pwr_opmode(port->typec_port, TYPEC_PWR_MODE_USB); | ||
2170 | port->pwr_opmode = TYPEC_PWR_MODE_USB; | ||
2171 | port->caps_count = 0; | ||
2172 | port->message_id = 0; | ||
2173 | port->explicit_contract = false; | ||
2174 | tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0); | ||
2175 | break; | ||
2176 | case SRC_SEND_CAPABILITIES: | ||
2177 | port->caps_count++; | ||
2178 | if (port->caps_count > PD_N_CAPS_COUNT) { | ||
2179 | tcpm_set_state(port, SRC_READY, 0); | ||
2180 | break; | ||
2181 | } | ||
2182 | ret = tcpm_pd_send_source_caps(port); | ||
2183 | if (ret < 0) { | ||
2184 | tcpm_set_state(port, SRC_SEND_CAPABILITIES, | ||
2185 | PD_T_SEND_SOURCE_CAP); | ||
2186 | } else { | ||
2187 | /* | ||
2188 | * Per standard, we should clear the reset counter here. | ||
2189 | * However, that can result in state machine hang-ups. | ||
2190 | * Reset it only in READY state to improve stability. | ||
2191 | */ | ||
2192 | /* port->hard_reset_count = 0; */ | ||
2193 | port->caps_count = 0; | ||
2194 | port->pd_capable = true; | ||
2195 | tcpm_set_state_cond(port, hard_reset_state(port), | ||
2196 | PD_T_SEND_SOURCE_CAP); | ||
2197 | } | ||
2198 | break; | ||
2199 | case SRC_NEGOTIATE_CAPABILITIES: | ||
2200 | ret = tcpm_pd_check_request(port); | ||
2201 | if (ret < 0) { | ||
2202 | tcpm_pd_send_control(port, PD_CTRL_REJECT); | ||
2203 | if (!port->explicit_contract) { | ||
2204 | tcpm_set_state(port, | ||
2205 | SRC_WAIT_NEW_CAPABILITIES, 0); | ||
2206 | } else { | ||
2207 | tcpm_set_state(port, SRC_READY, 0); | ||
2208 | } | ||
2209 | } else { | ||
2210 | tcpm_pd_send_control(port, PD_CTRL_ACCEPT); | ||
2211 | tcpm_set_state(port, SRC_TRANSITION_SUPPLY, | ||
2212 | PD_T_SRC_TRANSITION); | ||
2213 | } | ||
2214 | break; | ||
2215 | case SRC_TRANSITION_SUPPLY: | ||
2216 | /* XXX: regulator_set_voltage(vbus, ...) */ | ||
2217 | tcpm_pd_send_control(port, PD_CTRL_PS_RDY); | ||
2218 | port->explicit_contract = true; | ||
2219 | typec_set_pwr_opmode(port->typec_port, TYPEC_PWR_MODE_PD); | ||
2220 | port->pwr_opmode = TYPEC_PWR_MODE_PD; | ||
2221 | tcpm_set_state_cond(port, SRC_READY, 0); | ||
2222 | break; | ||
2223 | case SRC_READY: | ||
2224 | #if 1 | ||
2225 | port->hard_reset_count = 0; | ||
2226 | #endif | ||
2227 | port->try_src_count = 0; | ||
2228 | |||
2229 | tcpm_typec_connect(port); | ||
2230 | |||
2231 | tcpm_check_send_discover(port); | ||
2232 | /* | ||
2233 | * 6.3.5 | ||
2234 | * Sending ping messages is not necessary if | ||
2235 | * - the source operates at vSafe5V | ||
2236 | * or | ||
2237 | * - The system is not operating in PD mode | ||
2238 | * or | ||
2239 | * - Both partners are connected using a Type-C connector | ||
2240 | * XXX How do we know that ? | ||
2241 | */ | ||
2242 | if (port->pwr_opmode == TYPEC_PWR_MODE_PD && | ||
2243 | !port->op_vsafe5v) { | ||
2244 | tcpm_pd_send_control(port, PD_CTRL_PING); | ||
2245 | tcpm_set_state_cond(port, SRC_READY, | ||
2246 | PD_T_SOURCE_ACTIVITY); | ||
2247 | } | ||
2248 | break; | ||
2249 | case SRC_WAIT_NEW_CAPABILITIES: | ||
2250 | /* Nothing to do... */ | ||
2251 | break; | ||
2252 | |||
2253 | /* SNK states */ | ||
2254 | case SNK_UNATTACHED: | ||
2255 | tcpm_swap_complete(port, -ENOTCONN); | ||
2256 | tcpm_snk_detach(port); | ||
2257 | if (tcpm_start_drp_toggling(port)) { | ||
2258 | tcpm_set_state(port, DRP_TOGGLING, 0); | ||
2259 | break; | ||
2260 | } | ||
2261 | tcpm_set_cc(port, TYPEC_CC_RD); | ||
2262 | if (port->typec_caps.type == TYPEC_PORT_DRP) | ||
2263 | tcpm_set_state(port, SRC_UNATTACHED, PD_T_DRP_SRC); | ||
2264 | break; | ||
2265 | case SNK_ATTACH_WAIT: | ||
2266 | if ((port->cc1 == TYPEC_CC_OPEN && | ||
2267 | port->cc2 != TYPEC_CC_OPEN) || | ||
2268 | (port->cc1 != TYPEC_CC_OPEN && | ||
2269 | port->cc2 == TYPEC_CC_OPEN)) | ||
2270 | tcpm_set_state(port, SNK_DEBOUNCED, | ||
2271 | PD_T_CC_DEBOUNCE); | ||
2272 | else if (tcpm_port_is_disconnected(port)) | ||
2273 | tcpm_set_state(port, SNK_UNATTACHED, | ||
2274 | PD_T_PD_DEBOUNCE); | ||
2275 | break; | ||
2276 | case SNK_DEBOUNCED: | ||
2277 | if (tcpm_port_is_disconnected(port)) | ||
2278 | tcpm_set_state(port, SNK_UNATTACHED, | ||
2279 | PD_T_PD_DEBOUNCE); | ||
2280 | else if (port->vbus_present) | ||
2281 | tcpm_set_state(port, | ||
2282 | tcpm_try_src(port) ? SRC_TRY | ||
2283 | : SNK_ATTACHED, | ||
2284 | 0); | ||
2285 | else | ||
2286 | /* Wait for VBUS, but not forever */ | ||
2287 | tcpm_set_state(port, SNK_UNATTACHED, PD_T_PS_SOURCE_ON); | ||
2288 | break; | ||
2289 | |||
2290 | case SRC_TRY: | ||
2291 | port->try_src_count++; | ||
2292 | tcpm_set_cc(port, tcpm_rp_cc(port)); | ||
2293 | tcpm_set_state(port, SNK_TRYWAIT, PD_T_DRP_TRY); | ||
2294 | break; | ||
2295 | case SRC_TRY_DEBOUNCE: | ||
2296 | tcpm_set_state(port, SRC_ATTACHED, PD_T_PD_DEBOUNCE); | ||
2297 | break; | ||
2298 | case SNK_TRYWAIT: | ||
2299 | tcpm_set_cc(port, TYPEC_CC_RD); | ||
2300 | tcpm_set_state(port, SNK_TRYWAIT_DEBOUNCE, PD_T_CC_DEBOUNCE); | ||
2301 | break; | ||
2302 | case SNK_TRYWAIT_DEBOUNCE: | ||
2303 | if (port->vbus_present) { | ||
2304 | tcpm_set_state(port, SNK_ATTACHED, 0); | ||
2305 | break; | ||
2306 | } | ||
2307 | if (tcpm_port_is_disconnected(port)) { | ||
2308 | tcpm_set_state(port, SNK_UNATTACHED, | ||
2309 | PD_T_PD_DEBOUNCE); | ||
2310 | break; | ||
2311 | } | ||
2312 | if (tcpm_port_is_source(port)) | ||
2313 | tcpm_set_state(port, SRC_ATTACHED, 0); | ||
2314 | /* XXX Are we supposed to stay in this state ? */ | ||
2315 | break; | ||
2316 | case SNK_TRYWAIT_VBUS: | ||
2317 | tcpm_set_state(port, SNK_ATTACHED, PD_T_CC_DEBOUNCE); | ||
2318 | break; | ||
2319 | |||
2320 | case SNK_ATTACHED: | ||
2321 | ret = tcpm_snk_attach(port); | ||
2322 | if (ret < 0) | ||
2323 | tcpm_set_state(port, SNK_UNATTACHED, 0); | ||
2324 | else | ||
2325 | tcpm_set_state(port, SNK_STARTUP, 0); | ||
2326 | break; | ||
2327 | case SNK_STARTUP: | ||
2328 | /* XXX: callback into infrastructure */ | ||
2329 | typec_set_pwr_opmode(port->typec_port, TYPEC_PWR_MODE_USB); | ||
2330 | port->pwr_opmode = TYPEC_PWR_MODE_USB; | ||
2331 | port->message_id = 0; | ||
2332 | port->explicit_contract = false; | ||
2333 | tcpm_set_state(port, SNK_DISCOVERY, 0); | ||
2334 | break; | ||
2335 | case SNK_DISCOVERY: | ||
2336 | if (port->vbus_present) { | ||
2337 | tcpm_set_current_limit(port, | ||
2338 | tcpm_get_current_limit(port), | ||
2339 | 5000); | ||
2340 | tcpm_set_charge(port, true); | ||
2341 | tcpm_set_state(port, SNK_WAIT_CAPABILITIES, 0); | ||
2342 | break; | ||
2343 | } | ||
2344 | /* | ||
2345 | * For DRP, timeouts differ. Also, handling is supposed to be | ||
2346 | * different and much more complex (dead battery detection; | ||
2347 | * see USB power delivery specification, section 8.3.3.6.1.5.1). | ||
2348 | */ | ||
2349 | tcpm_set_state(port, hard_reset_state(port), | ||
2350 | port->typec_caps.type == TYPEC_PORT_DRP ? | ||
2351 | PD_T_DB_DETECT : PD_T_NO_RESPONSE); | ||
2352 | break; | ||
2353 | case SNK_DISCOVERY_DEBOUNCE: | ||
2354 | tcpm_set_state(port, SNK_DISCOVERY_DEBOUNCE_DONE, | ||
2355 | PD_T_CC_DEBOUNCE); | ||
2356 | break; | ||
2357 | case SNK_DISCOVERY_DEBOUNCE_DONE: | ||
2358 | if (!tcpm_port_is_disconnected(port) && | ||
2359 | tcpm_port_is_sink(port) && | ||
2360 | time_is_after_jiffies(port->delayed_runtime)) { | ||
2361 | tcpm_set_state(port, SNK_DISCOVERY, | ||
2362 | port->delayed_runtime - jiffies); | ||
2363 | break; | ||
2364 | } | ||
2365 | tcpm_set_state(port, unattached_state(port), 0); | ||
2366 | break; | ||
2367 | case SNK_WAIT_CAPABILITIES: | ||
2368 | ret = port->tcpc->set_pd_rx(port->tcpc, true); | ||
2369 | if (ret < 0) { | ||
2370 | tcpm_set_state(port, SNK_READY, 0); | ||
2371 | break; | ||
2372 | } | ||
2373 | /* | ||
2374 | * If VBUS has never been low, and we time out waiting | ||
2375 | * for source cap, try a soft reset first, in case we | ||
2376 | * were already in a stable contract before this boot. | ||
2377 | * Do this only once. | ||
2378 | */ | ||
2379 | if (port->vbus_never_low) { | ||
2380 | port->vbus_never_low = false; | ||
2381 | tcpm_set_state(port, SOFT_RESET_SEND, | ||
2382 | PD_T_SINK_WAIT_CAP); | ||
2383 | } else { | ||
2384 | tcpm_set_state(port, hard_reset_state(port), | ||
2385 | PD_T_SINK_WAIT_CAP); | ||
2386 | } | ||
2387 | break; | ||
2388 | case SNK_NEGOTIATE_CAPABILITIES: | ||
2389 | port->pd_capable = true; | ||
2390 | port->hard_reset_count = 0; | ||
2391 | ret = tcpm_pd_send_request(port); | ||
2392 | if (ret < 0) { | ||
2393 | /* Let the Source send capabilities again. */ | ||
2394 | tcpm_set_state(port, SNK_WAIT_CAPABILITIES, 0); | ||
2395 | } else { | ||
2396 | tcpm_set_state_cond(port, hard_reset_state(port), | ||
2397 | PD_T_SENDER_RESPONSE); | ||
2398 | } | ||
2399 | break; | ||
2400 | case SNK_TRANSITION_SINK: | ||
2401 | case SNK_TRANSITION_SINK_VBUS: | ||
2402 | tcpm_set_state(port, hard_reset_state(port), | ||
2403 | PD_T_PS_TRANSITION); | ||
2404 | break; | ||
2405 | case SNK_READY: | ||
2406 | port->try_snk_count = 0; | ||
2407 | port->explicit_contract = true; | ||
2408 | typec_set_pwr_opmode(port->typec_port, TYPEC_PWR_MODE_PD); | ||
2409 | port->pwr_opmode = TYPEC_PWR_MODE_PD; | ||
2410 | |||
2411 | tcpm_typec_connect(port); | ||
2412 | |||
2413 | tcpm_check_send_discover(port); | ||
2414 | break; | ||
2415 | |||
2416 | /* Accessory states */ | ||
2417 | case ACC_UNATTACHED: | ||
2418 | tcpm_acc_detach(port); | ||
2419 | tcpm_set_state(port, SRC_UNATTACHED, 0); | ||
2420 | break; | ||
2421 | case DEBUG_ACC_ATTACHED: | ||
2422 | case AUDIO_ACC_ATTACHED: | ||
2423 | ret = tcpm_acc_attach(port); | ||
2424 | if (ret < 0) | ||
2425 | tcpm_set_state(port, ACC_UNATTACHED, 0); | ||
2426 | break; | ||
2427 | case AUDIO_ACC_DEBOUNCE: | ||
2428 | tcpm_set_state(port, ACC_UNATTACHED, PD_T_CC_DEBOUNCE); | ||
2429 | break; | ||
2430 | |||
2431 | /* Hard_Reset states */ | ||
2432 | case HARD_RESET_SEND: | ||
2433 | tcpm_pd_transmit(port, TCPC_TX_HARD_RESET, NULL); | ||
2434 | tcpm_set_state(port, HARD_RESET_START, 0); | ||
2435 | break; | ||
2436 | case HARD_RESET_START: | ||
2437 | port->hard_reset_count++; | ||
2438 | port->tcpc->set_pd_rx(port->tcpc, false); | ||
2439 | tcpm_unregister_altmodes(port); | ||
2440 | port->send_discover = true; | ||
2441 | if (port->pwr_role == TYPEC_SOURCE) | ||
2442 | tcpm_set_state(port, SRC_HARD_RESET_VBUS_OFF, | ||
2443 | PD_T_PS_HARD_RESET); | ||
2444 | else | ||
2445 | tcpm_set_state(port, SNK_HARD_RESET_SINK_OFF, 0); | ||
2446 | break; | ||
2447 | case SRC_HARD_RESET_VBUS_OFF: | ||
2448 | tcpm_set_vconn(port, true); | ||
2449 | tcpm_set_vbus(port, false); | ||
2450 | tcpm_set_roles(port, false, TYPEC_SOURCE, TYPEC_HOST); | ||
2451 | tcpm_set_state(port, SRC_HARD_RESET_VBUS_ON, PD_T_SRC_RECOVER); | ||
2452 | break; | ||
2453 | case SRC_HARD_RESET_VBUS_ON: | ||
2454 | tcpm_set_vbus(port, true); | ||
2455 | port->tcpc->set_pd_rx(port->tcpc, true); | ||
2456 | tcpm_set_attached_state(port, true); | ||
2457 | tcpm_set_state(port, SRC_UNATTACHED, PD_T_PS_SOURCE_ON); | ||
2458 | break; | ||
2459 | case SNK_HARD_RESET_SINK_OFF: | ||
2460 | tcpm_set_vconn(port, false); | ||
2461 | tcpm_set_charge(port, false); | ||
2462 | tcpm_set_roles(port, false, TYPEC_SINK, TYPEC_DEVICE); | ||
2463 | /* | ||
2464 | * VBUS may or may not toggle, depending on the adapter. | ||
2465 | * If it doesn't toggle, transition to SNK_HARD_RESET_SINK_ON | ||
2466 | * directly after timeout. | ||
2467 | */ | ||
2468 | tcpm_set_state(port, SNK_HARD_RESET_SINK_ON, PD_T_SAFE_0V); | ||
2469 | break; | ||
2470 | case SNK_HARD_RESET_WAIT_VBUS: | ||
2471 | /* Assume we're disconnected if VBUS doesn't come back. */ | ||
2472 | tcpm_set_state(port, SNK_UNATTACHED, | ||
2473 | PD_T_SRC_RECOVER_MAX + PD_T_SRC_TURN_ON); | ||
2474 | break; | ||
2475 | case SNK_HARD_RESET_SINK_ON: | ||
2476 | /* Note: There is no guarantee that VBUS is on in this state */ | ||
2477 | /* | ||
2478 | * XXX: | ||
2479 | * The specification suggests that dual mode ports in sink | ||
2480 | * mode should transition to state PE_SRC_Transition_to_default. | ||
2481 | * See USB power delivery specification chapter 8.3.3.6.1.3. | ||
2482 | * This would mean to to | ||
2483 | * - turn off VCONN, reset power supply | ||
2484 | * - request hardware reset | ||
2485 | * - turn on VCONN | ||
2486 | * - Transition to state PE_Src_Startup | ||
2487 | * SNK only ports shall transition to state Snk_Startup | ||
2488 | * (see chapter 8.3.3.3.8). | ||
2489 | * Similar, dual-mode ports in source mode should transition | ||
2490 | * to PE_SNK_Transition_to_default. | ||
2491 | */ | ||
2492 | tcpm_set_attached_state(port, true); | ||
2493 | tcpm_set_state(port, SNK_STARTUP, 0); | ||
2494 | break; | ||
2495 | |||
2496 | /* Soft_Reset states */ | ||
2497 | case SOFT_RESET: | ||
2498 | port->message_id = 0; | ||
2499 | tcpm_pd_send_control(port, PD_CTRL_ACCEPT); | ||
2500 | if (port->pwr_role == TYPEC_SOURCE) | ||
2501 | tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0); | ||
2502 | else | ||
2503 | tcpm_set_state(port, SNK_WAIT_CAPABILITIES, 0); | ||
2504 | break; | ||
2505 | case SOFT_RESET_SEND: | ||
2506 | port->message_id = 0; | ||
2507 | if (tcpm_pd_send_control(port, PD_CTRL_SOFT_RESET)) | ||
2508 | tcpm_set_state_cond(port, hard_reset_state(port), 0); | ||
2509 | else | ||
2510 | tcpm_set_state_cond(port, hard_reset_state(port), | ||
2511 | PD_T_SENDER_RESPONSE); | ||
2512 | break; | ||
2513 | |||
2514 | /* DR_Swap states */ | ||
2515 | case DR_SWAP_SEND: | ||
2516 | tcpm_pd_send_control(port, PD_CTRL_DR_SWAP); | ||
2517 | tcpm_set_state_cond(port, DR_SWAP_SEND_TIMEOUT, | ||
2518 | PD_T_SENDER_RESPONSE); | ||
2519 | break; | ||
2520 | case DR_SWAP_ACCEPT: | ||
2521 | tcpm_pd_send_control(port, PD_CTRL_ACCEPT); | ||
2522 | tcpm_set_state_cond(port, DR_SWAP_CHANGE_DR, 0); | ||
2523 | break; | ||
2524 | case DR_SWAP_SEND_TIMEOUT: | ||
2525 | tcpm_swap_complete(port, -ETIMEDOUT); | ||
2526 | tcpm_set_state(port, ready_state(port), 0); | ||
2527 | break; | ||
2528 | case DR_SWAP_CHANGE_DR: | ||
2529 | if (port->data_role == TYPEC_HOST) { | ||
2530 | tcpm_unregister_altmodes(port); | ||
2531 | tcpm_set_roles(port, true, port->pwr_role, | ||
2532 | TYPEC_DEVICE); | ||
2533 | } else { | ||
2534 | tcpm_set_roles(port, true, port->pwr_role, | ||
2535 | TYPEC_HOST); | ||
2536 | port->send_discover = true; | ||
2537 | } | ||
2538 | tcpm_swap_complete(port, 0); | ||
2539 | tcpm_set_state(port, ready_state(port), 0); | ||
2540 | break; | ||
2541 | |||
2542 | /* PR_Swap states */ | ||
2543 | case PR_SWAP_ACCEPT: | ||
2544 | tcpm_pd_send_control(port, PD_CTRL_ACCEPT); | ||
2545 | tcpm_set_state(port, PR_SWAP_START, 0); | ||
2546 | break; | ||
2547 | case PR_SWAP_SEND: | ||
2548 | tcpm_pd_send_control(port, PD_CTRL_PR_SWAP); | ||
2549 | tcpm_set_state_cond(port, PR_SWAP_SEND_TIMEOUT, | ||
2550 | PD_T_SENDER_RESPONSE); | ||
2551 | break; | ||
2552 | case PR_SWAP_SEND_TIMEOUT: | ||
2553 | tcpm_swap_complete(port, -ETIMEDOUT); | ||
2554 | tcpm_set_state(port, ready_state(port), 0); | ||
2555 | break; | ||
2556 | case PR_SWAP_START: | ||
2557 | if (port->pwr_role == TYPEC_SOURCE) | ||
2558 | tcpm_set_state(port, PR_SWAP_SRC_SNK_TRANSITION_OFF, | ||
2559 | PD_T_SRC_TRANSITION); | ||
2560 | else | ||
2561 | tcpm_set_state(port, PR_SWAP_SNK_SRC_SINK_OFF, 0); | ||
2562 | break; | ||
2563 | case PR_SWAP_SRC_SNK_TRANSITION_OFF: | ||
2564 | tcpm_set_vbus(port, false); | ||
2565 | port->explicit_contract = false; | ||
2566 | tcpm_set_state(port, PR_SWAP_SRC_SNK_SOURCE_OFF, | ||
2567 | PD_T_PS_SOURCE_OFF); | ||
2568 | break; | ||
2569 | case PR_SWAP_SRC_SNK_SOURCE_OFF: | ||
2570 | tcpm_set_cc(port, TYPEC_CC_RD); | ||
2571 | if (tcpm_pd_send_control(port, PD_CTRL_PS_RDY)) { | ||
2572 | tcpm_set_state(port, ERROR_RECOVERY, 0); | ||
2573 | break; | ||
2574 | } | ||
2575 | tcpm_set_state_cond(port, SNK_UNATTACHED, PD_T_PS_SOURCE_ON); | ||
2576 | break; | ||
2577 | case PR_SWAP_SRC_SNK_SINK_ON: | ||
2578 | tcpm_set_pwr_role(port, TYPEC_SINK); | ||
2579 | tcpm_swap_complete(port, 0); | ||
2580 | tcpm_set_state(port, SNK_STARTUP, 0); | ||
2581 | break; | ||
2582 | case PR_SWAP_SNK_SRC_SINK_OFF: | ||
2583 | tcpm_set_charge(port, false); | ||
2584 | tcpm_set_state(port, hard_reset_state(port), | ||
2585 | PD_T_PS_SOURCE_OFF); | ||
2586 | break; | ||
2587 | case PR_SWAP_SNK_SRC_SOURCE_ON: | ||
2588 | tcpm_set_cc(port, tcpm_rp_cc(port)); | ||
2589 | tcpm_set_vbus(port, true); | ||
2590 | tcpm_pd_send_control(port, PD_CTRL_PS_RDY); | ||
2591 | tcpm_set_pwr_role(port, TYPEC_SOURCE); | ||
2592 | tcpm_swap_complete(port, 0); | ||
2593 | tcpm_set_state(port, SRC_STARTUP, 0); | ||
2594 | break; | ||
2595 | |||
2596 | case VCONN_SWAP_ACCEPT: | ||
2597 | tcpm_pd_send_control(port, PD_CTRL_ACCEPT); | ||
2598 | tcpm_set_state(port, VCONN_SWAP_START, 0); | ||
2599 | break; | ||
2600 | case VCONN_SWAP_SEND: | ||
2601 | tcpm_pd_send_control(port, PD_CTRL_VCONN_SWAP); | ||
2602 | tcpm_set_state(port, VCONN_SWAP_SEND_TIMEOUT, | ||
2603 | PD_T_SENDER_RESPONSE); | ||
2604 | break; | ||
2605 | case VCONN_SWAP_SEND_TIMEOUT: | ||
2606 | tcpm_swap_complete(port, -ETIMEDOUT); | ||
2607 | tcpm_set_state(port, ready_state(port), 0); | ||
2608 | break; | ||
2609 | case VCONN_SWAP_START: | ||
2610 | if (port->vconn_role == TYPEC_SOURCE) | ||
2611 | tcpm_set_state(port, VCONN_SWAP_WAIT_FOR_VCONN, 0); | ||
2612 | else | ||
2613 | tcpm_set_state(port, VCONN_SWAP_TURN_ON_VCONN, 0); | ||
2614 | break; | ||
2615 | case VCONN_SWAP_WAIT_FOR_VCONN: | ||
2616 | tcpm_set_state(port, hard_reset_state(port), | ||
2617 | PD_T_VCONN_SOURCE_ON); | ||
2618 | break; | ||
2619 | case VCONN_SWAP_TURN_ON_VCONN: | ||
2620 | tcpm_set_vconn(port, true); | ||
2621 | tcpm_pd_send_control(port, PD_CTRL_PS_RDY); | ||
2622 | tcpm_swap_complete(port, 0); | ||
2623 | tcpm_set_state(port, ready_state(port), 0); | ||
2624 | break; | ||
2625 | case VCONN_SWAP_TURN_OFF_VCONN: | ||
2626 | tcpm_set_vconn(port, false); | ||
2627 | tcpm_swap_complete(port, 0); | ||
2628 | tcpm_set_state(port, ready_state(port), 0); | ||
2629 | break; | ||
2630 | |||
2631 | case DR_SWAP_CANCEL: | ||
2632 | case PR_SWAP_CANCEL: | ||
2633 | case VCONN_SWAP_CANCEL: | ||
2634 | tcpm_swap_complete(port, port->swap_status); | ||
2635 | if (port->pwr_role == TYPEC_SOURCE) | ||
2636 | tcpm_set_state(port, SRC_READY, 0); | ||
2637 | else | ||
2638 | tcpm_set_state(port, SNK_READY, 0); | ||
2639 | break; | ||
2640 | |||
2641 | case BIST_RX: | ||
2642 | switch (BDO_MODE_MASK(port->bist_request)) { | ||
2643 | case BDO_MODE_CARRIER2: | ||
2644 | tcpm_pd_transmit(port, TCPC_TX_BIST_MODE_2, NULL); | ||
2645 | break; | ||
2646 | default: | ||
2647 | break; | ||
2648 | } | ||
2649 | /* Always switch to unattached state */ | ||
2650 | tcpm_set_state(port, unattached_state(port), 0); | ||
2651 | break; | ||
2652 | case ERROR_RECOVERY: | ||
2653 | tcpm_swap_complete(port, -EPROTO); | ||
2654 | tcpm_reset_port(port); | ||
2655 | |||
2656 | tcpm_set_cc(port, TYPEC_CC_OPEN); | ||
2657 | tcpm_set_state(port, ERROR_RECOVERY_WAIT_OFF, | ||
2658 | PD_T_ERROR_RECOVERY); | ||
2659 | break; | ||
2660 | case ERROR_RECOVERY_WAIT_OFF: | ||
2661 | tcpm_set_state(port, | ||
2662 | tcpm_default_state(port), | ||
2663 | port->vbus_present ? PD_T_PS_SOURCE_OFF : 0); | ||
2664 | break; | ||
2665 | default: | ||
2666 | WARN(1, "Unexpected port state %d\n", port->state); | ||
2667 | break; | ||
2668 | } | ||
2669 | } | ||
2670 | |||
2671 | static void tcpm_state_machine_work(struct work_struct *work) | ||
2672 | { | ||
2673 | struct tcpm_port *port = container_of(work, struct tcpm_port, | ||
2674 | state_machine.work); | ||
2675 | enum tcpm_state prev_state; | ||
2676 | |||
2677 | mutex_lock(&port->lock); | ||
2678 | port->state_machine_running = true; | ||
2679 | |||
2680 | if (port->queued_message && tcpm_send_queued_message(port)) | ||
2681 | goto done; | ||
2682 | |||
2683 | /* If we were queued due to a delayed state change, update it now */ | ||
2684 | if (port->delayed_state) { | ||
2685 | tcpm_log(port, "state change %s -> %s [delayed %ld ms]", | ||
2686 | tcpm_states[port->state], | ||
2687 | tcpm_states[port->delayed_state], port->delay_ms); | ||
2688 | port->prev_state = port->state; | ||
2689 | port->state = port->delayed_state; | ||
2690 | port->delayed_state = INVALID_STATE; | ||
2691 | } | ||
2692 | |||
2693 | /* | ||
2694 | * Continue running as long as we have (non-delayed) state changes | ||
2695 | * to make. | ||
2696 | */ | ||
2697 | do { | ||
2698 | prev_state = port->state; | ||
2699 | run_state_machine(port); | ||
2700 | if (port->queued_message) | ||
2701 | tcpm_send_queued_message(port); | ||
2702 | } while (port->state != prev_state && !port->delayed_state); | ||
2703 | |||
2704 | done: | ||
2705 | port->state_machine_running = false; | ||
2706 | mutex_unlock(&port->lock); | ||
2707 | } | ||
2708 | |||
2709 | static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1, | ||
2710 | enum typec_cc_status cc2) | ||
2711 | { | ||
2712 | enum typec_cc_status old_cc1, old_cc2; | ||
2713 | enum tcpm_state new_state; | ||
2714 | |||
2715 | old_cc1 = port->cc1; | ||
2716 | old_cc2 = port->cc2; | ||
2717 | port->cc1 = cc1; | ||
2718 | port->cc2 = cc2; | ||
2719 | |||
2720 | tcpm_log_force(port, | ||
2721 | "CC1: %u -> %u, CC2: %u -> %u [state %s, polarity %d, %s]", | ||
2722 | old_cc1, cc1, old_cc2, cc2, tcpm_states[port->state], | ||
2723 | port->polarity, | ||
2724 | tcpm_port_is_disconnected(port) ? "disconnected" | ||
2725 | : "connected"); | ||
2726 | |||
2727 | switch (port->state) { | ||
2728 | case DRP_TOGGLING: | ||
2729 | if (tcpm_port_is_debug(port) || tcpm_port_is_audio(port) || | ||
2730 | tcpm_port_is_source(port)) | ||
2731 | tcpm_set_state(port, SRC_ATTACH_WAIT, 0); | ||
2732 | else if (tcpm_port_is_sink(port)) | ||
2733 | tcpm_set_state(port, SNK_ATTACH_WAIT, 0); | ||
2734 | break; | ||
2735 | case SRC_UNATTACHED: | ||
2736 | case ACC_UNATTACHED: | ||
2737 | if (tcpm_port_is_debug(port) || tcpm_port_is_audio(port) || | ||
2738 | tcpm_port_is_source(port)) | ||
2739 | tcpm_set_state(port, SRC_ATTACH_WAIT, 0); | ||
2740 | break; | ||
2741 | case SRC_ATTACH_WAIT: | ||
2742 | if (tcpm_port_is_disconnected(port) || | ||
2743 | tcpm_port_is_audio_detached(port)) | ||
2744 | tcpm_set_state(port, SRC_UNATTACHED, 0); | ||
2745 | else if (cc1 != old_cc1 || cc2 != old_cc2) | ||
2746 | tcpm_set_state(port, SRC_ATTACH_WAIT, 0); | ||
2747 | break; | ||
2748 | case SRC_ATTACHED: | ||
2749 | if (tcpm_port_is_disconnected(port)) | ||
2750 | tcpm_set_state(port, SRC_UNATTACHED, 0); | ||
2751 | break; | ||
2752 | |||
2753 | case SNK_UNATTACHED: | ||
2754 | if (tcpm_port_is_sink(port)) | ||
2755 | tcpm_set_state(port, SNK_ATTACH_WAIT, 0); | ||
2756 | break; | ||
2757 | case SNK_ATTACH_WAIT: | ||
2758 | if ((port->cc1 == TYPEC_CC_OPEN && | ||
2759 | port->cc2 != TYPEC_CC_OPEN) || | ||
2760 | (port->cc1 != TYPEC_CC_OPEN && | ||
2761 | port->cc2 == TYPEC_CC_OPEN)) | ||
2762 | new_state = SNK_DEBOUNCED; | ||
2763 | else if (tcpm_port_is_disconnected(port)) | ||
2764 | new_state = SNK_UNATTACHED; | ||
2765 | else | ||
2766 | break; | ||
2767 | if (new_state != port->delayed_state) | ||
2768 | tcpm_set_state(port, SNK_ATTACH_WAIT, 0); | ||
2769 | break; | ||
2770 | case SNK_DEBOUNCED: | ||
2771 | if (tcpm_port_is_disconnected(port)) | ||
2772 | new_state = SNK_UNATTACHED; | ||
2773 | else if (port->vbus_present) | ||
2774 | new_state = tcpm_try_src(port) ? SRC_TRY : SNK_ATTACHED; | ||
2775 | else | ||
2776 | new_state = SNK_UNATTACHED; | ||
2777 | if (new_state != port->delayed_state) | ||
2778 | tcpm_set_state(port, SNK_DEBOUNCED, 0); | ||
2779 | break; | ||
2780 | case SNK_READY: | ||
2781 | if (tcpm_port_is_disconnected(port)) | ||
2782 | tcpm_set_state(port, unattached_state(port), 0); | ||
2783 | else if (!port->pd_capable && | ||
2784 | (cc1 != old_cc1 || cc2 != old_cc2)) | ||
2785 | tcpm_set_current_limit(port, | ||
2786 | tcpm_get_current_limit(port), | ||
2787 | 5000); | ||
2788 | break; | ||
2789 | |||
2790 | case AUDIO_ACC_ATTACHED: | ||
2791 | if (cc1 == TYPEC_CC_OPEN || cc2 == TYPEC_CC_OPEN) | ||
2792 | tcpm_set_state(port, AUDIO_ACC_DEBOUNCE, 0); | ||
2793 | break; | ||
2794 | case AUDIO_ACC_DEBOUNCE: | ||
2795 | if (tcpm_port_is_audio(port)) | ||
2796 | tcpm_set_state(port, AUDIO_ACC_ATTACHED, 0); | ||
2797 | break; | ||
2798 | |||
2799 | case DEBUG_ACC_ATTACHED: | ||
2800 | if (cc1 == TYPEC_CC_OPEN || cc2 == TYPEC_CC_OPEN) | ||
2801 | tcpm_set_state(port, ACC_UNATTACHED, 0); | ||
2802 | break; | ||
2803 | |||
2804 | case SNK_TRY: | ||
2805 | /* Do nothing, waiting for timeout */ | ||
2806 | break; | ||
2807 | |||
2808 | case SNK_DISCOVERY: | ||
2809 | /* CC line is unstable, wait for debounce */ | ||
2810 | if (tcpm_port_is_disconnected(port)) | ||
2811 | tcpm_set_state(port, SNK_DISCOVERY_DEBOUNCE, 0); | ||
2812 | break; | ||
2813 | case SNK_DISCOVERY_DEBOUNCE: | ||
2814 | break; | ||
2815 | |||
2816 | case SRC_TRYWAIT: | ||
2817 | /* Hand over to state machine if needed */ | ||
2818 | if (!port->vbus_present && tcpm_port_is_source(port)) | ||
2819 | new_state = SRC_ATTACHED; | ||
2820 | else | ||
2821 | new_state = SRC_TRYWAIT_UNATTACHED; | ||
2822 | |||
2823 | if (new_state != port->delayed_state) | ||
2824 | tcpm_set_state(port, SRC_TRYWAIT, 0); | ||
2825 | break; | ||
2826 | case SNK_TRY_WAIT: | ||
2827 | if (port->vbus_present && tcpm_port_is_sink(port)) { | ||
2828 | tcpm_set_state(port, SNK_ATTACHED, 0); | ||
2829 | break; | ||
2830 | } | ||
2831 | if (!tcpm_port_is_sink(port)) | ||
2832 | new_state = SRC_TRYWAIT; | ||
2833 | else | ||
2834 | new_state = SRC_TRYWAIT_UNATTACHED; | ||
2835 | |||
2836 | if (new_state != port->delayed_state) | ||
2837 | tcpm_set_state(port, SNK_TRY_WAIT, 0); | ||
2838 | break; | ||
2839 | |||
2840 | case SRC_TRY: | ||
2841 | tcpm_set_state(port, SRC_TRY_DEBOUNCE, 0); | ||
2842 | break; | ||
2843 | case SRC_TRY_DEBOUNCE: | ||
2844 | tcpm_set_state(port, SRC_TRY, 0); | ||
2845 | break; | ||
2846 | case SNK_TRYWAIT_DEBOUNCE: | ||
2847 | if (port->vbus_present) { | ||
2848 | tcpm_set_state(port, SNK_ATTACHED, 0); | ||
2849 | break; | ||
2850 | } | ||
2851 | if (tcpm_port_is_source(port)) { | ||
2852 | tcpm_set_state(port, SRC_ATTACHED, 0); | ||
2853 | break; | ||
2854 | } | ||
2855 | if (tcpm_port_is_disconnected(port) && | ||
2856 | port->delayed_state != SNK_UNATTACHED) | ||
2857 | tcpm_set_state(port, SNK_TRYWAIT_DEBOUNCE, 0); | ||
2858 | break; | ||
2859 | |||
2860 | case PR_SWAP_SNK_SRC_SINK_OFF: | ||
2861 | case PR_SWAP_SRC_SNK_TRANSITION_OFF: | ||
2862 | case PR_SWAP_SRC_SNK_SOURCE_OFF: | ||
2863 | /* | ||
2864 | * CC state change is expected here; we just turned off power. | ||
2865 | * Ignore it. | ||
2866 | */ | ||
2867 | break; | ||
2868 | |||
2869 | default: | ||
2870 | if (tcpm_port_is_disconnected(port)) | ||
2871 | tcpm_set_state(port, unattached_state(port), 0); | ||
2872 | break; | ||
2873 | } | ||
2874 | } | ||
2875 | |||
2876 | static void _tcpm_pd_vbus_on(struct tcpm_port *port) | ||
2877 | { | ||
2878 | enum tcpm_state new_state; | ||
2879 | |||
2880 | tcpm_log_force(port, "VBUS on"); | ||
2881 | port->vbus_present = true; | ||
2882 | switch (port->state) { | ||
2883 | case SNK_TRANSITION_SINK_VBUS: | ||
2884 | tcpm_set_state(port, SNK_READY, 0); | ||
2885 | break; | ||
2886 | case SNK_DISCOVERY: | ||
2887 | tcpm_set_state(port, SNK_DISCOVERY, 0); | ||
2888 | break; | ||
2889 | |||
2890 | case SNK_DEBOUNCED: | ||
2891 | tcpm_set_state(port, tcpm_try_src(port) ? SRC_TRY | ||
2892 | : SNK_ATTACHED, | ||
2893 | 0); | ||
2894 | break; | ||
2895 | case SNK_HARD_RESET_WAIT_VBUS: | ||
2896 | tcpm_set_state(port, SNK_HARD_RESET_SINK_ON, 0); | ||
2897 | break; | ||
2898 | case SRC_ATTACHED: | ||
2899 | tcpm_set_state(port, SRC_STARTUP, 0); | ||
2900 | break; | ||
2901 | case SRC_HARD_RESET_VBUS_ON: | ||
2902 | tcpm_set_state(port, SRC_STARTUP, 0); | ||
2903 | break; | ||
2904 | |||
2905 | case SNK_TRY: | ||
2906 | /* Do nothing, waiting for timeout */ | ||
2907 | break; | ||
2908 | case SRC_TRYWAIT: | ||
2909 | /* Hand over to state machine if needed */ | ||
2910 | if (port->delayed_state != SRC_TRYWAIT_UNATTACHED) | ||
2911 | tcpm_set_state(port, SRC_TRYWAIT, 0); | ||
2912 | break; | ||
2913 | case SNK_TRY_WAIT: | ||
2914 | if (tcpm_port_is_sink(port)) { | ||
2915 | tcpm_set_state(port, SNK_ATTACHED, 0); | ||
2916 | break; | ||
2917 | } | ||
2918 | if (!tcpm_port_is_sink(port)) | ||
2919 | new_state = SRC_TRYWAIT; | ||
2920 | else | ||
2921 | new_state = SRC_TRYWAIT_UNATTACHED; | ||
2922 | |||
2923 | if (new_state != port->delayed_state) | ||
2924 | tcpm_set_state(port, SNK_TRY_WAIT, 0); | ||
2925 | break; | ||
2926 | case SNK_TRYWAIT: | ||
2927 | tcpm_set_state(port, SNK_TRYWAIT_VBUS, 0); | ||
2928 | break; | ||
2929 | |||
2930 | default: | ||
2931 | break; | ||
2932 | } | ||
2933 | } | ||
2934 | |||
2935 | static void _tcpm_pd_vbus_off(struct tcpm_port *port) | ||
2936 | { | ||
2937 | enum tcpm_state new_state; | ||
2938 | |||
2939 | tcpm_log_force(port, "VBUS off"); | ||
2940 | port->vbus_present = false; | ||
2941 | port->vbus_never_low = false; | ||
2942 | switch (port->state) { | ||
2943 | case SNK_HARD_RESET_SINK_OFF: | ||
2944 | tcpm_set_state(port, SNK_HARD_RESET_WAIT_VBUS, 0); | ||
2945 | break; | ||
2946 | case SRC_HARD_RESET_VBUS_OFF: | ||
2947 | tcpm_set_state(port, SRC_HARD_RESET_VBUS_ON, 0); | ||
2948 | break; | ||
2949 | case HARD_RESET_SEND: | ||
2950 | break; | ||
2951 | |||
2952 | case SNK_TRY: | ||
2953 | /* Do nothing, waiting for timeout */ | ||
2954 | break; | ||
2955 | case SRC_TRYWAIT: | ||
2956 | /* Hand over to state machine if needed */ | ||
2957 | if (tcpm_port_is_source(port)) | ||
2958 | new_state = SRC_ATTACHED; | ||
2959 | else | ||
2960 | new_state = SRC_TRYWAIT_UNATTACHED; | ||
2961 | if (new_state != port->delayed_state) | ||
2962 | tcpm_set_state(port, SRC_TRYWAIT, 0); | ||
2963 | break; | ||
2964 | case SNK_TRY_WAIT: | ||
2965 | if (!tcpm_port_is_sink(port)) | ||
2966 | new_state = SRC_TRYWAIT; | ||
2967 | else | ||
2968 | new_state = SRC_TRYWAIT_UNATTACHED; | ||
2969 | |||
2970 | if (new_state != port->delayed_state) | ||
2971 | tcpm_set_state(port, SNK_TRY_WAIT, 0); | ||
2972 | break; | ||
2973 | case SNK_TRYWAIT_VBUS: | ||
2974 | tcpm_set_state(port, SNK_TRYWAIT, 0); | ||
2975 | break; | ||
2976 | |||
2977 | case SNK_ATTACH_WAIT: | ||
2978 | tcpm_set_state(port, SNK_UNATTACHED, 0); | ||
2979 | break; | ||
2980 | |||
2981 | case SNK_NEGOTIATE_CAPABILITIES: | ||
2982 | break; | ||
2983 | |||
2984 | case PR_SWAP_SRC_SNK_TRANSITION_OFF: | ||
2985 | tcpm_set_state(port, PR_SWAP_SRC_SNK_SOURCE_OFF, 0); | ||
2986 | break; | ||
2987 | |||
2988 | case PR_SWAP_SNK_SRC_SINK_OFF: | ||
2989 | /* Do nothing, expected */ | ||
2990 | break; | ||
2991 | |||
2992 | case ERROR_RECOVERY_WAIT_OFF: | ||
2993 | tcpm_set_state(port, | ||
2994 | port->pwr_role == TYPEC_SOURCE ? | ||
2995 | SRC_UNATTACHED : SNK_UNATTACHED, | ||
2996 | 0); | ||
2997 | break; | ||
2998 | |||
2999 | default: | ||
3000 | if (port->pwr_role == TYPEC_SINK && | ||
3001 | port->attached) | ||
3002 | tcpm_set_state(port, SNK_UNATTACHED, 0); | ||
3003 | break; | ||
3004 | } | ||
3005 | } | ||
3006 | |||
3007 | static void _tcpm_pd_hard_reset(struct tcpm_port *port) | ||
3008 | { | ||
3009 | tcpm_log_force(port, "Received hard reset"); | ||
3010 | /* | ||
3011 | * If we keep receiving hard reset requests, executing the hard reset | ||
3012 | * must have failed. Revert to error recovery if that happens. | ||
3013 | */ | ||
3014 | tcpm_set_state(port, | ||
3015 | port->hard_reset_count < PD_N_HARD_RESET_COUNT ? | ||
3016 | HARD_RESET_START : ERROR_RECOVERY, | ||
3017 | 0); | ||
3018 | } | ||
3019 | |||
3020 | static void tcpm_pd_event_handler(struct work_struct *work) | ||
3021 | { | ||
3022 | struct tcpm_port *port = container_of(work, struct tcpm_port, | ||
3023 | event_work); | ||
3024 | u32 events; | ||
3025 | |||
3026 | mutex_lock(&port->lock); | ||
3027 | |||
3028 | spin_lock(&port->pd_event_lock); | ||
3029 | while (port->pd_events) { | ||
3030 | events = port->pd_events; | ||
3031 | port->pd_events = 0; | ||
3032 | spin_unlock(&port->pd_event_lock); | ||
3033 | if (events & TCPM_RESET_EVENT) | ||
3034 | _tcpm_pd_hard_reset(port); | ||
3035 | if (events & TCPM_VBUS_EVENT) { | ||
3036 | bool vbus; | ||
3037 | |||
3038 | vbus = port->tcpc->get_vbus(port->tcpc); | ||
3039 | if (vbus) | ||
3040 | _tcpm_pd_vbus_on(port); | ||
3041 | else | ||
3042 | _tcpm_pd_vbus_off(port); | ||
3043 | } | ||
3044 | if (events & TCPM_CC_EVENT) { | ||
3045 | enum typec_cc_status cc1, cc2; | ||
3046 | |||
3047 | if (port->tcpc->get_cc(port->tcpc, &cc1, &cc2) == 0) | ||
3048 | _tcpm_cc_change(port, cc1, cc2); | ||
3049 | } | ||
3050 | spin_lock(&port->pd_event_lock); | ||
3051 | } | ||
3052 | spin_unlock(&port->pd_event_lock); | ||
3053 | mutex_unlock(&port->lock); | ||
3054 | } | ||
3055 | |||
3056 | void tcpm_cc_change(struct tcpm_port *port) | ||
3057 | { | ||
3058 | spin_lock(&port->pd_event_lock); | ||
3059 | port->pd_events |= TCPM_CC_EVENT; | ||
3060 | spin_unlock(&port->pd_event_lock); | ||
3061 | queue_work(port->wq, &port->event_work); | ||
3062 | } | ||
3063 | EXPORT_SYMBOL_GPL(tcpm_cc_change); | ||
3064 | |||
3065 | void tcpm_vbus_change(struct tcpm_port *port) | ||
3066 | { | ||
3067 | spin_lock(&port->pd_event_lock); | ||
3068 | port->pd_events |= TCPM_VBUS_EVENT; | ||
3069 | spin_unlock(&port->pd_event_lock); | ||
3070 | queue_work(port->wq, &port->event_work); | ||
3071 | } | ||
3072 | EXPORT_SYMBOL_GPL(tcpm_vbus_change); | ||
3073 | |||
3074 | void tcpm_pd_hard_reset(struct tcpm_port *port) | ||
3075 | { | ||
3076 | spin_lock(&port->pd_event_lock); | ||
3077 | port->pd_events = TCPM_RESET_EVENT; | ||
3078 | spin_unlock(&port->pd_event_lock); | ||
3079 | queue_work(port->wq, &port->event_work); | ||
3080 | } | ||
3081 | EXPORT_SYMBOL_GPL(tcpm_pd_hard_reset); | ||
3082 | |||
3083 | static int tcpm_dr_set(const struct typec_capability *cap, | ||
3084 | enum typec_data_role data) | ||
3085 | { | ||
3086 | struct tcpm_port *port = typec_cap_to_tcpm(cap); | ||
3087 | int ret; | ||
3088 | |||
3089 | mutex_lock(&port->swap_lock); | ||
3090 | mutex_lock(&port->lock); | ||
3091 | |||
3092 | if (port->typec_caps.type != TYPEC_PORT_DRP || !port->pd_capable) { | ||
3093 | ret = -EINVAL; | ||
3094 | goto port_unlock; | ||
3095 | } | ||
3096 | if (port->state != SRC_READY && port->state != SNK_READY) { | ||
3097 | ret = -EAGAIN; | ||
3098 | goto port_unlock; | ||
3099 | } | ||
3100 | |||
3101 | if (port->data_role == data) { | ||
3102 | ret = 0; | ||
3103 | goto port_unlock; | ||
3104 | } | ||
3105 | |||
3106 | /* | ||
3107 | * XXX | ||
3108 | * 6.3.9: If an alternate mode is active, a request to swap | ||
3109 | * alternate modes shall trigger a port reset. | ||
3110 | * Reject data role swap request in this case. | ||
3111 | */ | ||
3112 | |||
3113 | port->swap_status = 0; | ||
3114 | port->swap_pending = true; | ||
3115 | reinit_completion(&port->swap_complete); | ||
3116 | tcpm_set_state(port, DR_SWAP_SEND, 0); | ||
3117 | mutex_unlock(&port->lock); | ||
3118 | |||
3119 | wait_for_completion(&port->swap_complete); | ||
3120 | |||
3121 | ret = port->swap_status; | ||
3122 | goto swap_unlock; | ||
3123 | |||
3124 | port_unlock: | ||
3125 | mutex_unlock(&port->lock); | ||
3126 | swap_unlock: | ||
3127 | mutex_unlock(&port->swap_lock); | ||
3128 | return ret; | ||
3129 | } | ||
3130 | |||
3131 | static int tcpm_pr_set(const struct typec_capability *cap, | ||
3132 | enum typec_role role) | ||
3133 | { | ||
3134 | struct tcpm_port *port = typec_cap_to_tcpm(cap); | ||
3135 | int ret; | ||
3136 | |||
3137 | mutex_lock(&port->swap_lock); | ||
3138 | mutex_lock(&port->lock); | ||
3139 | |||
3140 | if (port->typec_caps.type != TYPEC_PORT_DRP) { | ||
3141 | ret = -EINVAL; | ||
3142 | goto port_unlock; | ||
3143 | } | ||
3144 | if (port->state != SRC_READY && port->state != SNK_READY) { | ||
3145 | ret = -EAGAIN; | ||
3146 | goto port_unlock; | ||
3147 | } | ||
3148 | |||
3149 | if (role == port->pwr_role) { | ||
3150 | ret = 0; | ||
3151 | goto port_unlock; | ||
3152 | } | ||
3153 | |||
3154 | if (!port->pd_capable) { | ||
3155 | /* | ||
3156 | * If the partner is not PD capable, reset the port to | ||
3157 | * trigger a role change. This can only work if a preferred | ||
3158 | * role is configured, and if it matches the requested role. | ||
3159 | */ | ||
3160 | if (port->try_role == TYPEC_NO_PREFERRED_ROLE || | ||
3161 | port->try_role == port->pwr_role) { | ||
3162 | ret = -EINVAL; | ||
3163 | goto port_unlock; | ||
3164 | } | ||
3165 | tcpm_set_state(port, HARD_RESET_SEND, 0); | ||
3166 | ret = 0; | ||
3167 | goto port_unlock; | ||
3168 | } | ||
3169 | |||
3170 | port->swap_status = 0; | ||
3171 | port->swap_pending = true; | ||
3172 | reinit_completion(&port->swap_complete); | ||
3173 | tcpm_set_state(port, PR_SWAP_SEND, 0); | ||
3174 | mutex_unlock(&port->lock); | ||
3175 | |||
3176 | wait_for_completion(&port->swap_complete); | ||
3177 | |||
3178 | ret = port->swap_status; | ||
3179 | goto swap_unlock; | ||
3180 | |||
3181 | port_unlock: | ||
3182 | mutex_unlock(&port->lock); | ||
3183 | swap_unlock: | ||
3184 | mutex_unlock(&port->swap_lock); | ||
3185 | return ret; | ||
3186 | } | ||
3187 | |||
3188 | static int tcpm_vconn_set(const struct typec_capability *cap, | ||
3189 | enum typec_role role) | ||
3190 | { | ||
3191 | struct tcpm_port *port = typec_cap_to_tcpm(cap); | ||
3192 | int ret; | ||
3193 | |||
3194 | mutex_lock(&port->swap_lock); | ||
3195 | mutex_lock(&port->lock); | ||
3196 | |||
3197 | if (port->state != SRC_READY && port->state != SNK_READY) { | ||
3198 | ret = -EAGAIN; | ||
3199 | goto port_unlock; | ||
3200 | } | ||
3201 | |||
3202 | if (role == port->vconn_role) { | ||
3203 | ret = 0; | ||
3204 | goto port_unlock; | ||
3205 | } | ||
3206 | |||
3207 | port->swap_status = 0; | ||
3208 | port->swap_pending = true; | ||
3209 | reinit_completion(&port->swap_complete); | ||
3210 | tcpm_set_state(port, VCONN_SWAP_SEND, 0); | ||
3211 | mutex_unlock(&port->lock); | ||
3212 | |||
3213 | wait_for_completion(&port->swap_complete); | ||
3214 | |||
3215 | ret = port->swap_status; | ||
3216 | goto swap_unlock; | ||
3217 | |||
3218 | port_unlock: | ||
3219 | mutex_unlock(&port->lock); | ||
3220 | swap_unlock: | ||
3221 | mutex_unlock(&port->swap_lock); | ||
3222 | return ret; | ||
3223 | } | ||
3224 | |||
3225 | static int tcpm_try_role(const struct typec_capability *cap, int role) | ||
3226 | { | ||
3227 | struct tcpm_port *port = typec_cap_to_tcpm(cap); | ||
3228 | struct tcpc_dev *tcpc = port->tcpc; | ||
3229 | int ret = 0; | ||
3230 | |||
3231 | mutex_lock(&port->lock); | ||
3232 | if (tcpc->try_role) | ||
3233 | ret = tcpc->try_role(tcpc, role); | ||
3234 | if (!ret && !tcpc->config->try_role_hw) | ||
3235 | port->try_role = role; | ||
3236 | port->try_src_count = 0; | ||
3237 | port->try_snk_count = 0; | ||
3238 | mutex_unlock(&port->lock); | ||
3239 | |||
3240 | return ret; | ||
3241 | } | ||
3242 | |||
3243 | static void tcpm_init(struct tcpm_port *port) | ||
3244 | { | ||
3245 | enum typec_cc_status cc1, cc2; | ||
3246 | |||
3247 | port->tcpc->init(port->tcpc); | ||
3248 | |||
3249 | tcpm_reset_port(port); | ||
3250 | |||
3251 | /* | ||
3252 | * XXX | ||
3253 | * Should possibly wait for VBUS to settle if it was enabled locally | ||
3254 | * since tcpm_reset_port() will disable VBUS. | ||
3255 | */ | ||
3256 | port->vbus_present = port->tcpc->get_vbus(port->tcpc); | ||
3257 | if (port->vbus_present) | ||
3258 | port->vbus_never_low = true; | ||
3259 | |||
3260 | tcpm_set_state(port, tcpm_default_state(port), 0); | ||
3261 | |||
3262 | if (port->tcpc->get_cc(port->tcpc, &cc1, &cc2) == 0) | ||
3263 | _tcpm_cc_change(port, cc1, cc2); | ||
3264 | |||
3265 | /* | ||
3266 | * Some adapters need a clean slate at startup, and won't recover | ||
3267 | * otherwise. So do not try to be fancy and force a clean disconnect. | ||
3268 | */ | ||
3269 | tcpm_set_state(port, ERROR_RECOVERY, 0); | ||
3270 | } | ||
3271 | |||
3272 | void tcpm_tcpc_reset(struct tcpm_port *port) | ||
3273 | { | ||
3274 | mutex_lock(&port->lock); | ||
3275 | /* XXX: Maintain PD connection if possible? */ | ||
3276 | tcpm_init(port); | ||
3277 | mutex_unlock(&port->lock); | ||
3278 | } | ||
3279 | EXPORT_SYMBOL_GPL(tcpm_tcpc_reset); | ||
3280 | |||
3281 | static int tcpm_copy_pdos(u32 *dest_pdo, const u32 *src_pdo, | ||
3282 | unsigned int nr_pdo) | ||
3283 | { | ||
3284 | unsigned int i; | ||
3285 | |||
3286 | if (nr_pdo > PDO_MAX_OBJECTS) | ||
3287 | nr_pdo = PDO_MAX_OBJECTS; | ||
3288 | |||
3289 | for (i = 0; i < nr_pdo; i++) | ||
3290 | dest_pdo[i] = src_pdo[i]; | ||
3291 | |||
3292 | return nr_pdo; | ||
3293 | } | ||
3294 | |||
3295 | void tcpm_update_source_capabilities(struct tcpm_port *port, const u32 *pdo, | ||
3296 | unsigned int nr_pdo) | ||
3297 | { | ||
3298 | mutex_lock(&port->lock); | ||
3299 | port->nr_src_pdo = tcpm_copy_pdos(port->src_pdo, pdo, nr_pdo); | ||
3300 | switch (port->state) { | ||
3301 | case SRC_UNATTACHED: | ||
3302 | case SRC_ATTACH_WAIT: | ||
3303 | case SRC_TRYWAIT: | ||
3304 | tcpm_set_cc(port, tcpm_rp_cc(port)); | ||
3305 | break; | ||
3306 | case SRC_SEND_CAPABILITIES: | ||
3307 | case SRC_NEGOTIATE_CAPABILITIES: | ||
3308 | case SRC_READY: | ||
3309 | case SRC_WAIT_NEW_CAPABILITIES: | ||
3310 | tcpm_set_cc(port, tcpm_rp_cc(port)); | ||
3311 | tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0); | ||
3312 | break; | ||
3313 | default: | ||
3314 | break; | ||
3315 | } | ||
3316 | mutex_unlock(&port->lock); | ||
3317 | } | ||
3318 | EXPORT_SYMBOL_GPL(tcpm_update_source_capabilities); | ||
3319 | |||
3320 | void tcpm_update_sink_capabilities(struct tcpm_port *port, const u32 *pdo, | ||
3321 | unsigned int nr_pdo, | ||
3322 | unsigned int max_snk_mv, | ||
3323 | unsigned int max_snk_ma, | ||
3324 | unsigned int max_snk_mw, | ||
3325 | unsigned int operating_snk_mw) | ||
3326 | { | ||
3327 | mutex_lock(&port->lock); | ||
3328 | port->nr_snk_pdo = tcpm_copy_pdos(port->snk_pdo, pdo, nr_pdo); | ||
3329 | port->max_snk_mv = max_snk_mv; | ||
3330 | port->max_snk_ma = max_snk_ma; | ||
3331 | port->max_snk_mw = max_snk_mw; | ||
3332 | port->operating_snk_mw = operating_snk_mw; | ||
3333 | |||
3334 | switch (port->state) { | ||
3335 | case SNK_NEGOTIATE_CAPABILITIES: | ||
3336 | case SNK_READY: | ||
3337 | case SNK_TRANSITION_SINK: | ||
3338 | case SNK_TRANSITION_SINK_VBUS: | ||
3339 | tcpm_set_state(port, SNK_NEGOTIATE_CAPABILITIES, 0); | ||
3340 | break; | ||
3341 | default: | ||
3342 | break; | ||
3343 | } | ||
3344 | mutex_unlock(&port->lock); | ||
3345 | } | ||
3346 | EXPORT_SYMBOL_GPL(tcpm_update_sink_capabilities); | ||
3347 | |||
3348 | struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) | ||
3349 | { | ||
3350 | struct tcpm_port *port; | ||
3351 | int i, err; | ||
3352 | |||
3353 | if (!dev || !tcpc || !tcpc->config || | ||
3354 | !tcpc->get_vbus || !tcpc->set_cc || !tcpc->get_cc || | ||
3355 | !tcpc->set_polarity || !tcpc->set_vconn || !tcpc->set_vbus || | ||
3356 | !tcpc->set_pd_rx || !tcpc->set_roles || !tcpc->pd_transmit) | ||
3357 | return ERR_PTR(-EINVAL); | ||
3358 | |||
3359 | port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); | ||
3360 | if (!port) | ||
3361 | return ERR_PTR(-ENOMEM); | ||
3362 | |||
3363 | port->dev = dev; | ||
3364 | port->tcpc = tcpc; | ||
3365 | |||
3366 | mutex_init(&port->lock); | ||
3367 | mutex_init(&port->swap_lock); | ||
3368 | |||
3369 | port->wq = create_singlethread_workqueue(dev_name(dev)); | ||
3370 | if (!port->wq) | ||
3371 | return ERR_PTR(-ENOMEM); | ||
3372 | INIT_DELAYED_WORK(&port->state_machine, tcpm_state_machine_work); | ||
3373 | INIT_DELAYED_WORK(&port->vdm_state_machine, vdm_state_machine_work); | ||
3374 | INIT_WORK(&port->event_work, tcpm_pd_event_handler); | ||
3375 | |||
3376 | spin_lock_init(&port->pd_event_lock); | ||
3377 | |||
3378 | init_completion(&port->tx_complete); | ||
3379 | init_completion(&port->swap_complete); | ||
3380 | |||
3381 | port->nr_src_pdo = tcpm_copy_pdos(port->src_pdo, tcpc->config->src_pdo, | ||
3382 | tcpc->config->nr_src_pdo); | ||
3383 | port->nr_snk_pdo = tcpm_copy_pdos(port->snk_pdo, tcpc->config->snk_pdo, | ||
3384 | tcpc->config->nr_snk_pdo); | ||
3385 | |||
3386 | port->max_snk_mv = tcpc->config->max_snk_mv; | ||
3387 | port->max_snk_ma = tcpc->config->max_snk_ma; | ||
3388 | port->max_snk_mw = tcpc->config->max_snk_mw; | ||
3389 | port->operating_snk_mw = tcpc->config->operating_snk_mw; | ||
3390 | if (!tcpc->config->try_role_hw) | ||
3391 | port->try_role = tcpc->config->default_role; | ||
3392 | else | ||
3393 | port->try_role = TYPEC_NO_PREFERRED_ROLE; | ||
3394 | |||
3395 | port->typec_caps.prefer_role = tcpc->config->default_role; | ||
3396 | port->typec_caps.type = tcpc->config->type; | ||
3397 | port->typec_caps.revision = 0x0120; /* Type-C spec release 1.2 */ | ||
3398 | port->typec_caps.pd_revision = 0x0200; /* USB-PD spec release 2.0 */ | ||
3399 | port->typec_caps.dr_set = tcpm_dr_set; | ||
3400 | port->typec_caps.pr_set = tcpm_pr_set; | ||
3401 | port->typec_caps.vconn_set = tcpm_vconn_set; | ||
3402 | port->typec_caps.try_role = tcpm_try_role; | ||
3403 | |||
3404 | port->partner_desc.identity = &port->partner_ident; | ||
3405 | |||
3406 | /* | ||
3407 | * TODO: | ||
3408 | * - alt_modes, set_alt_mode | ||
3409 | * - {debug,audio}_accessory | ||
3410 | */ | ||
3411 | |||
3412 | port->typec_port = typec_register_port(port->dev, &port->typec_caps); | ||
3413 | if (!port->typec_port) { | ||
3414 | err = -ENOMEM; | ||
3415 | goto out_destroy_wq; | ||
3416 | } | ||
3417 | |||
3418 | if (tcpc->config->alt_modes) { | ||
3419 | struct typec_altmode_desc *paltmode = tcpc->config->alt_modes; | ||
3420 | |||
3421 | i = 0; | ||
3422 | while (paltmode->svid && i < ARRAY_SIZE(port->port_altmode)) { | ||
3423 | port->port_altmode[i] = | ||
3424 | typec_port_register_altmode(port->typec_port, | ||
3425 | paltmode); | ||
3426 | if (!port->port_altmode[i]) { | ||
3427 | tcpm_log(port, | ||
3428 | "%s: failed to register port alternate mode 0x%x", | ||
3429 | dev_name(dev), paltmode->svid); | ||
3430 | break; | ||
3431 | } | ||
3432 | i++; | ||
3433 | paltmode++; | ||
3434 | } | ||
3435 | } | ||
3436 | |||
3437 | tcpm_debugfs_init(port); | ||
3438 | mutex_lock(&port->lock); | ||
3439 | tcpm_init(port); | ||
3440 | mutex_unlock(&port->lock); | ||
3441 | |||
3442 | tcpm_log(port, "%s: registered", dev_name(dev)); | ||
3443 | return port; | ||
3444 | |||
3445 | out_destroy_wq: | ||
3446 | destroy_workqueue(port->wq); | ||
3447 | return ERR_PTR(err); | ||
3448 | } | ||
3449 | EXPORT_SYMBOL_GPL(tcpm_register_port); | ||
3450 | |||
3451 | void tcpm_unregister_port(struct tcpm_port *port) | ||
3452 | { | ||
3453 | int i; | ||
3454 | |||
3455 | for (i = 0; i < ARRAY_SIZE(port->port_altmode); i++) | ||
3456 | typec_unregister_altmode(port->port_altmode[i]); | ||
3457 | typec_unregister_port(port->typec_port); | ||
3458 | tcpm_debugfs_exit(port); | ||
3459 | destroy_workqueue(port->wq); | ||
3460 | } | ||
3461 | EXPORT_SYMBOL_GPL(tcpm_unregister_port); | ||
3462 | |||
3463 | MODULE_AUTHOR("Guenter Roeck <groeck@chromium.org>"); | ||
3464 | MODULE_DESCRIPTION("USB Type-C Port Manager"); | ||
3465 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/staging/typec/tcpm.h b/drivers/staging/typec/tcpm.h new file mode 100644 index 000000000000..969b365e6549 --- /dev/null +++ b/drivers/staging/typec/tcpm.h | |||
@@ -0,0 +1,150 @@ | |||
1 | /* | ||
2 | * Copyright 2015-2017 Google, Inc | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | */ | ||
14 | |||
15 | #ifndef __LINUX_USB_TCPM_H | ||
16 | #define __LINUX_USB_TCPM_H | ||
17 | |||
18 | #include <linux/bitops.h> | ||
19 | #include <linux/usb/typec.h> | ||
20 | #include "pd.h" | ||
21 | |||
22 | enum typec_cc_status { | ||
23 | TYPEC_CC_OPEN, | ||
24 | TYPEC_CC_RA, | ||
25 | TYPEC_CC_RD, | ||
26 | TYPEC_CC_RP_DEF, | ||
27 | TYPEC_CC_RP_1_5, | ||
28 | TYPEC_CC_RP_3_0, | ||
29 | }; | ||
30 | |||
31 | enum typec_cc_polarity { | ||
32 | TYPEC_POLARITY_CC1, | ||
33 | TYPEC_POLARITY_CC2, | ||
34 | }; | ||
35 | |||
36 | /* Time to wait for TCPC to complete transmit */ | ||
37 | #define PD_T_TCPC_TX_TIMEOUT 100 | ||
38 | |||
39 | enum tcpm_transmit_status { | ||
40 | TCPC_TX_SUCCESS = 0, | ||
41 | TCPC_TX_DISCARDED = 1, | ||
42 | TCPC_TX_FAILED = 2, | ||
43 | }; | ||
44 | |||
45 | enum tcpm_transmit_type { | ||
46 | TCPC_TX_SOP = 0, | ||
47 | TCPC_TX_SOP_PRIME = 1, | ||
48 | TCPC_TX_SOP_PRIME_PRIME = 2, | ||
49 | TCPC_TX_SOP_DEBUG_PRIME = 3, | ||
50 | TCPC_TX_SOP_DEBUG_PRIME_PRIME = 4, | ||
51 | TCPC_TX_HARD_RESET = 5, | ||
52 | TCPC_TX_CABLE_RESET = 6, | ||
53 | TCPC_TX_BIST_MODE_2 = 7 | ||
54 | }; | ||
55 | |||
56 | struct tcpc_config { | ||
57 | const u32 *src_pdo; | ||
58 | unsigned int nr_src_pdo; | ||
59 | |||
60 | const u32 *snk_pdo; | ||
61 | unsigned int nr_snk_pdo; | ||
62 | |||
63 | unsigned int max_snk_mv; | ||
64 | unsigned int max_snk_ma; | ||
65 | unsigned int max_snk_mw; | ||
66 | unsigned int operating_snk_mw; | ||
67 | |||
68 | enum typec_port_type type; | ||
69 | enum typec_role default_role; | ||
70 | bool try_role_hw; /* try.{src,snk} implemented in hardware */ | ||
71 | |||
72 | struct typec_altmode_desc *alt_modes; | ||
73 | }; | ||
74 | |||
75 | enum tcpc_usb_switch { | ||
76 | TCPC_USB_SWITCH_CONNECT, | ||
77 | TCPC_USB_SWITCH_DISCONNECT, | ||
78 | TCPC_USB_SWITCH_RESTORE, /* TODO FIXME */ | ||
79 | }; | ||
80 | |||
81 | /* Mux state attributes */ | ||
82 | #define TCPC_MUX_USB_ENABLED BIT(0) /* USB enabled */ | ||
83 | #define TCPC_MUX_DP_ENABLED BIT(1) /* DP enabled */ | ||
84 | #define TCPC_MUX_POLARITY_INVERTED BIT(2) /* Polarity inverted */ | ||
85 | |||
86 | /* Mux modes, decoded to attributes */ | ||
87 | enum tcpc_mux_mode { | ||
88 | TYPEC_MUX_NONE = 0, /* Open switch */ | ||
89 | TYPEC_MUX_USB = TCPC_MUX_USB_ENABLED, /* USB only */ | ||
90 | TYPEC_MUX_DP = TCPC_MUX_DP_ENABLED, /* DP only */ | ||
91 | TYPEC_MUX_DOCK = TCPC_MUX_USB_ENABLED | /* Both USB and DP */ | ||
92 | TCPC_MUX_DP_ENABLED, | ||
93 | }; | ||
94 | |||
95 | struct tcpc_mux_dev { | ||
96 | int (*set)(struct tcpc_mux_dev *dev, enum tcpc_mux_mode mux_mode, | ||
97 | enum tcpc_usb_switch usb_config, | ||
98 | enum typec_cc_polarity polarity); | ||
99 | bool dfp_only; | ||
100 | void *priv_data; | ||
101 | }; | ||
102 | |||
103 | struct tcpc_dev { | ||
104 | const struct tcpc_config *config; | ||
105 | |||
106 | int (*init)(struct tcpc_dev *dev); | ||
107 | int (*get_vbus)(struct tcpc_dev *dev); | ||
108 | int (*set_cc)(struct tcpc_dev *dev, enum typec_cc_status cc); | ||
109 | int (*get_cc)(struct tcpc_dev *dev, enum typec_cc_status *cc1, | ||
110 | enum typec_cc_status *cc2); | ||
111 | int (*set_polarity)(struct tcpc_dev *dev, | ||
112 | enum typec_cc_polarity polarity); | ||
113 | int (*set_vconn)(struct tcpc_dev *dev, bool on); | ||
114 | int (*set_vbus)(struct tcpc_dev *dev, bool on, bool charge); | ||
115 | int (*set_current_limit)(struct tcpc_dev *dev, u32 max_ma, u32 mv); | ||
116 | int (*set_pd_rx)(struct tcpc_dev *dev, bool on); | ||
117 | int (*set_roles)(struct tcpc_dev *dev, bool attached, | ||
118 | enum typec_role role, enum typec_data_role data); | ||
119 | int (*start_drp_toggling)(struct tcpc_dev *dev, | ||
120 | enum typec_cc_status cc); | ||
121 | int (*try_role)(struct tcpc_dev *dev, int role); | ||
122 | int (*pd_transmit)(struct tcpc_dev *dev, enum tcpm_transmit_type type, | ||
123 | const struct pd_message *msg); | ||
124 | struct tcpc_mux_dev *mux; | ||
125 | }; | ||
126 | |||
127 | struct tcpm_port; | ||
128 | |||
129 | struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc); | ||
130 | void tcpm_unregister_port(struct tcpm_port *port); | ||
131 | |||
132 | void tcpm_update_source_capabilities(struct tcpm_port *port, const u32 *pdo, | ||
133 | unsigned int nr_pdo); | ||
134 | void tcpm_update_sink_capabilities(struct tcpm_port *port, const u32 *pdo, | ||
135 | unsigned int nr_pdo, | ||
136 | unsigned int max_snk_mv, | ||
137 | unsigned int max_snk_ma, | ||
138 | unsigned int max_snk_mw, | ||
139 | unsigned int operating_snk_mw); | ||
140 | |||
141 | void tcpm_vbus_change(struct tcpm_port *port); | ||
142 | void tcpm_cc_change(struct tcpm_port *port); | ||
143 | void tcpm_pd_receive(struct tcpm_port *port, | ||
144 | const struct pd_message *msg); | ||
145 | void tcpm_pd_transmit_complete(struct tcpm_port *port, | ||
146 | enum tcpm_transmit_status status); | ||
147 | void tcpm_pd_hard_reset(struct tcpm_port *port); | ||
148 | void tcpm_tcpc_reset(struct tcpm_port *port); | ||
149 | |||
150 | #endif /* __LINUX_USB_TCPM_H */ | ||
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index fbe493d44e81..939a63bca82f 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig | |||
@@ -35,7 +35,6 @@ config USB_COMMON | |||
35 | config USB_ARCH_HAS_HCD | 35 | config USB_ARCH_HAS_HCD |
36 | def_bool y | 36 | def_bool y |
37 | 37 | ||
38 | # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. | ||
39 | config USB | 38 | config USB |
40 | tristate "Support for Host-side USB" | 39 | tristate "Support for Host-side USB" |
41 | depends on USB_ARCH_HAS_HCD | 40 | depends on USB_ARCH_HAS_HCD |
@@ -73,6 +72,17 @@ config USB | |||
73 | To compile this driver as a module, choose M here: the | 72 | To compile this driver as a module, choose M here: the |
74 | module will be called usbcore. | 73 | module will be called usbcore. |
75 | 74 | ||
75 | config USB_PCI | ||
76 | bool "PCI based USB host interface" | ||
77 | depends on PCI | ||
78 | default y | ||
79 | ---help--- | ||
80 | A lot of embeded system SOC (e.g. freescale T2080) have both | ||
81 | PCI and USB modules. But USB module is controlled by registers | ||
82 | directly, it have no relationship with PCI module. | ||
83 | |||
84 | When say N here it will not build PCI related code in USB driver. | ||
85 | |||
76 | if USB | 86 | if USB |
77 | 87 | ||
78 | source "drivers/usb/core/Kconfig" | 88 | source "drivers/usb/core/Kconfig" |
@@ -152,6 +162,8 @@ source "drivers/usb/phy/Kconfig" | |||
152 | 162 | ||
153 | source "drivers/usb/gadget/Kconfig" | 163 | source "drivers/usb/gadget/Kconfig" |
154 | 164 | ||
165 | source "drivers/usb/typec/Kconfig" | ||
166 | |||
155 | config USB_LED_TRIG | 167 | config USB_LED_TRIG |
156 | bool "USB LED Triggers" | 168 | bool "USB LED Triggers" |
157 | depends on LEDS_CLASS && LEDS_TRIGGERS | 169 | depends on LEDS_CLASS && LEDS_TRIGGERS |
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 53d1356bbd06..9650b351c26c 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile | |||
@@ -14,7 +14,7 @@ obj-$(CONFIG_USB_ISP1760) += isp1760/ | |||
14 | obj-$(CONFIG_USB_MON) += mon/ | 14 | obj-$(CONFIG_USB_MON) += mon/ |
15 | obj-$(CONFIG_USB_MTU3) += mtu3/ | 15 | obj-$(CONFIG_USB_MTU3) += mtu3/ |
16 | 16 | ||
17 | obj-$(CONFIG_PCI) += host/ | 17 | obj-$(CONFIG_USB_PCI) += host/ |
18 | obj-$(CONFIG_USB_EHCI_HCD) += host/ | 18 | obj-$(CONFIG_USB_EHCI_HCD) += host/ |
19 | obj-$(CONFIG_USB_ISP116X_HCD) += host/ | 19 | obj-$(CONFIG_USB_ISP116X_HCD) += host/ |
20 | obj-$(CONFIG_USB_OHCI_HCD) += host/ | 20 | obj-$(CONFIG_USB_OHCI_HCD) += host/ |
@@ -62,3 +62,5 @@ obj-$(CONFIG_USB_GADGET) += gadget/ | |||
62 | obj-$(CONFIG_USB_COMMON) += common/ | 62 | obj-$(CONFIG_USB_COMMON) += common/ |
63 | 63 | ||
64 | obj-$(CONFIG_USBIP_CORE) += usbip/ | 64 | obj-$(CONFIG_USBIP_CORE) += usbip/ |
65 | |||
66 | obj-$(CONFIG_TYPEC) += typec/ | ||
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index f9fe86b6f7b5..d65a64c29b85 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c | |||
@@ -474,7 +474,7 @@ static ssize_t cxacru_sysfs_store_adsl_config(struct device *dev, | |||
474 | ret = sscanf(buf + pos, "%x=%x%n", &index, &value, &tmp); | 474 | ret = sscanf(buf + pos, "%x=%x%n", &index, &value, &tmp); |
475 | if (ret < 2) | 475 | if (ret < 2) |
476 | return -EINVAL; | 476 | return -EINVAL; |
477 | if (index < 0 || index > 0x7f) | 477 | if (index > 0x7f) |
478 | return -EINVAL; | 478 | return -EINVAL; |
479 | if (tmp < 0 || tmp > len - pos) | 479 | if (tmp < 0 || tmp > len - pos) |
480 | return -EINVAL; | 480 | return -EINVAL; |
diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig index fc96f5cdcb5c..51f4157bbecf 100644 --- a/drivers/usb/chipidea/Kconfig +++ b/drivers/usb/chipidea/Kconfig | |||
@@ -20,7 +20,7 @@ config USB_CHIPIDEA_OF | |||
20 | 20 | ||
21 | config USB_CHIPIDEA_PCI | 21 | config USB_CHIPIDEA_PCI |
22 | tristate | 22 | tristate |
23 | depends on PCI | 23 | depends on USB_PCI |
24 | depends on NOP_USB_XCEIV | 24 | depends on NOP_USB_XCEIV |
25 | default USB_CHIPIDEA | 25 | default USB_CHIPIDEA |
26 | 26 | ||
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h index 59e22389c10b..6743f85b1b7a 100644 --- a/drivers/usb/chipidea/ci.h +++ b/drivers/usb/chipidea/ci.h | |||
@@ -177,6 +177,7 @@ struct hw_bank { | |||
177 | * @td_pool: allocation pool for transfer descriptors | 177 | * @td_pool: allocation pool for transfer descriptors |
178 | * @gadget: device side representation for peripheral controller | 178 | * @gadget: device side representation for peripheral controller |
179 | * @driver: gadget driver | 179 | * @driver: gadget driver |
180 | * @resume_state: save the state of gadget suspend from | ||
180 | * @hw_ep_max: total number of endpoints supported by hardware | 181 | * @hw_ep_max: total number of endpoints supported by hardware |
181 | * @ci_hw_ep: array of endpoints | 182 | * @ci_hw_ep: array of endpoints |
182 | * @ep0_dir: ep0 direction | 183 | * @ep0_dir: ep0 direction |
@@ -227,6 +228,7 @@ struct ci_hdrc { | |||
227 | 228 | ||
228 | struct usb_gadget gadget; | 229 | struct usb_gadget gadget; |
229 | struct usb_gadget_driver *driver; | 230 | struct usb_gadget_driver *driver; |
231 | enum usb_device_state resume_state; | ||
230 | unsigned hw_ep_max; | 232 | unsigned hw_ep_max; |
231 | struct ci_hw_ep ci_hw_ep[ENDPT_MAX]; | 233 | struct ci_hw_ep ci_hw_ep[ENDPT_MAX]; |
232 | u32 ep0_dir; | 234 | u32 ep0_dir; |
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 79ad8e91632e..9e217b1361ea 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c | |||
@@ -783,9 +783,6 @@ struct platform_device *ci_hdrc_add_device(struct device *dev, | |||
783 | } | 783 | } |
784 | 784 | ||
785 | pdev->dev.parent = dev; | 785 | pdev->dev.parent = dev; |
786 | pdev->dev.dma_mask = dev->dma_mask; | ||
787 | pdev->dev.dma_parms = dev->dma_parms; | ||
788 | dma_set_coherent_mask(&pdev->dev, dev->coherent_dma_mask); | ||
789 | 786 | ||
790 | ret = platform_device_add_resources(pdev, res, nres); | 787 | ret = platform_device_add_resources(pdev, res, nres); |
791 | if (ret) | 788 | if (ret) |
@@ -841,6 +838,56 @@ static void ci_get_otg_capable(struct ci_hdrc *ci) | |||
841 | } | 838 | } |
842 | } | 839 | } |
843 | 840 | ||
841 | static ssize_t ci_role_show(struct device *dev, struct device_attribute *attr, | ||
842 | char *buf) | ||
843 | { | ||
844 | struct ci_hdrc *ci = dev_get_drvdata(dev); | ||
845 | |||
846 | return sprintf(buf, "%s\n", ci_role(ci)->name); | ||
847 | } | ||
848 | |||
849 | static ssize_t ci_role_store(struct device *dev, | ||
850 | struct device_attribute *attr, const char *buf, size_t n) | ||
851 | { | ||
852 | struct ci_hdrc *ci = dev_get_drvdata(dev); | ||
853 | enum ci_role role; | ||
854 | int ret; | ||
855 | |||
856 | if (!(ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET])) { | ||
857 | dev_warn(dev, "Current configuration is not dual-role, quit\n"); | ||
858 | return -EPERM; | ||
859 | } | ||
860 | |||
861 | for (role = CI_ROLE_HOST; role < CI_ROLE_END; role++) | ||
862 | if (!strncmp(buf, ci->roles[role]->name, | ||
863 | strlen(ci->roles[role]->name))) | ||
864 | break; | ||
865 | |||
866 | if (role == CI_ROLE_END || role == ci->role) | ||
867 | return -EINVAL; | ||
868 | |||
869 | pm_runtime_get_sync(dev); | ||
870 | disable_irq(ci->irq); | ||
871 | ci_role_stop(ci); | ||
872 | ret = ci_role_start(ci, role); | ||
873 | if (!ret && ci->role == CI_ROLE_GADGET) | ||
874 | ci_handle_vbus_change(ci); | ||
875 | enable_irq(ci->irq); | ||
876 | pm_runtime_put_sync(dev); | ||
877 | |||
878 | return (ret == 0) ? n : ret; | ||
879 | } | ||
880 | static DEVICE_ATTR(role, 0644, ci_role_show, ci_role_store); | ||
881 | |||
882 | static struct attribute *ci_attrs[] = { | ||
883 | &dev_attr_role.attr, | ||
884 | NULL, | ||
885 | }; | ||
886 | |||
887 | static struct attribute_group ci_attr_group = { | ||
888 | .attrs = ci_attrs, | ||
889 | }; | ||
890 | |||
844 | static int ci_hdrc_probe(struct platform_device *pdev) | 891 | static int ci_hdrc_probe(struct platform_device *pdev) |
845 | { | 892 | { |
846 | struct device *dev = &pdev->dev; | 893 | struct device *dev = &pdev->dev; |
@@ -1007,11 +1054,18 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
1007 | ci_hdrc_otg_fsm_start(ci); | 1054 | ci_hdrc_otg_fsm_start(ci); |
1008 | 1055 | ||
1009 | device_set_wakeup_capable(&pdev->dev, true); | 1056 | device_set_wakeup_capable(&pdev->dev, true); |
1010 | |||
1011 | ret = dbg_create_files(ci); | 1057 | ret = dbg_create_files(ci); |
1012 | if (!ret) | 1058 | if (ret) |
1013 | return 0; | 1059 | goto stop; |
1060 | |||
1061 | ret = sysfs_create_group(&dev->kobj, &ci_attr_group); | ||
1062 | if (ret) | ||
1063 | goto remove_debug; | ||
1064 | |||
1065 | return 0; | ||
1014 | 1066 | ||
1067 | remove_debug: | ||
1068 | dbg_remove_files(ci); | ||
1015 | stop: | 1069 | stop: |
1016 | ci_role_destroy(ci); | 1070 | ci_role_destroy(ci); |
1017 | deinit_phy: | 1071 | deinit_phy: |
@@ -1033,6 +1087,7 @@ static int ci_hdrc_remove(struct platform_device *pdev) | |||
1033 | } | 1087 | } |
1034 | 1088 | ||
1035 | dbg_remove_files(ci); | 1089 | dbg_remove_files(ci); |
1090 | sysfs_remove_group(&ci->dev->kobj, &ci_attr_group); | ||
1036 | ci_role_destroy(ci); | 1091 | ci_role_destroy(ci); |
1037 | ci_hdrc_enter_lpm(ci, true); | 1092 | ci_hdrc_enter_lpm(ci, true); |
1038 | ci_usb_phy_exit(ci); | 1093 | ci_usb_phy_exit(ci); |
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c index 915f3e91586e..18cb8e46262d 100644 --- a/drivers/usb/chipidea/host.c +++ b/drivers/usb/chipidea/host.c | |||
@@ -123,7 +123,8 @@ static int host_start(struct ci_hdrc *ci) | |||
123 | if (usb_disabled()) | 123 | if (usb_disabled()) |
124 | return -ENODEV; | 124 | return -ENODEV; |
125 | 125 | ||
126 | hcd = usb_create_hcd(&ci_ehci_hc_driver, ci->dev, dev_name(ci->dev)); | 126 | hcd = __usb_create_hcd(&ci_ehci_hc_driver, ci->dev->parent, |
127 | ci->dev, dev_name(ci->dev), NULL); | ||
127 | if (!hcd) | 128 | if (!hcd) |
128 | return -ENOMEM; | 129 | return -ENOMEM; |
129 | 130 | ||
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index f88e9157fad0..56d2d3213076 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c | |||
@@ -423,7 +423,8 @@ static int _hardware_enqueue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq) | |||
423 | 423 | ||
424 | hwreq->req.status = -EALREADY; | 424 | hwreq->req.status = -EALREADY; |
425 | 425 | ||
426 | ret = usb_gadget_map_request(&ci->gadget, &hwreq->req, hwep->dir); | 426 | ret = usb_gadget_map_request_by_dev(ci->dev->parent, |
427 | &hwreq->req, hwep->dir); | ||
427 | if (ret) | 428 | if (ret) |
428 | return ret; | 429 | return ret; |
429 | 430 | ||
@@ -603,7 +604,8 @@ static int _hardware_dequeue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq) | |||
603 | list_del_init(&node->td); | 604 | list_del_init(&node->td); |
604 | } | 605 | } |
605 | 606 | ||
606 | usb_gadget_unmap_request(&hwep->ci->gadget, &hwreq->req, hwep->dir); | 607 | usb_gadget_unmap_request_by_dev(hwep->ci->dev->parent, |
608 | &hwreq->req, hwep->dir); | ||
607 | 609 | ||
608 | hwreq->req.actual += actual; | 610 | hwreq->req.actual += actual; |
609 | 611 | ||
@@ -1845,27 +1847,32 @@ static irqreturn_t udc_irq(struct ci_hdrc *ci) | |||
1845 | if (USBi_PCI & intr) { | 1847 | if (USBi_PCI & intr) { |
1846 | ci->gadget.speed = hw_port_is_high_speed(ci) ? | 1848 | ci->gadget.speed = hw_port_is_high_speed(ci) ? |
1847 | USB_SPEED_HIGH : USB_SPEED_FULL; | 1849 | USB_SPEED_HIGH : USB_SPEED_FULL; |
1848 | if (ci->suspended && ci->driver->resume) { | 1850 | if (ci->suspended) { |
1849 | spin_unlock(&ci->lock); | 1851 | if (ci->driver->resume) { |
1850 | ci->driver->resume(&ci->gadget); | 1852 | spin_unlock(&ci->lock); |
1851 | spin_lock(&ci->lock); | 1853 | ci->driver->resume(&ci->gadget); |
1854 | spin_lock(&ci->lock); | ||
1855 | } | ||
1852 | ci->suspended = 0; | 1856 | ci->suspended = 0; |
1857 | usb_gadget_set_state(&ci->gadget, | ||
1858 | ci->resume_state); | ||
1853 | } | 1859 | } |
1854 | } | 1860 | } |
1855 | 1861 | ||
1856 | if (USBi_UI & intr) | 1862 | if (USBi_UI & intr) |
1857 | isr_tr_complete_handler(ci); | 1863 | isr_tr_complete_handler(ci); |
1858 | 1864 | ||
1859 | if (USBi_SLI & intr) { | 1865 | if ((USBi_SLI & intr) && !(ci->suspended)) { |
1866 | ci->suspended = 1; | ||
1867 | ci->resume_state = ci->gadget.state; | ||
1860 | if (ci->gadget.speed != USB_SPEED_UNKNOWN && | 1868 | if (ci->gadget.speed != USB_SPEED_UNKNOWN && |
1861 | ci->driver->suspend) { | 1869 | ci->driver->suspend) { |
1862 | ci->suspended = 1; | ||
1863 | spin_unlock(&ci->lock); | 1870 | spin_unlock(&ci->lock); |
1864 | ci->driver->suspend(&ci->gadget); | 1871 | ci->driver->suspend(&ci->gadget); |
1865 | usb_gadget_set_state(&ci->gadget, | ||
1866 | USB_STATE_SUSPENDED); | ||
1867 | spin_lock(&ci->lock); | 1872 | spin_lock(&ci->lock); |
1868 | } | 1873 | } |
1874 | usb_gadget_set_state(&ci->gadget, | ||
1875 | USB_STATE_SUSPENDED); | ||
1869 | } | 1876 | } |
1870 | retval = IRQ_HANDLED; | 1877 | retval = IRQ_HANDLED; |
1871 | } else { | 1878 | } else { |
@@ -1899,13 +1906,13 @@ static int udc_start(struct ci_hdrc *ci) | |||
1899 | INIT_LIST_HEAD(&ci->gadget.ep_list); | 1906 | INIT_LIST_HEAD(&ci->gadget.ep_list); |
1900 | 1907 | ||
1901 | /* alloc resources */ | 1908 | /* alloc resources */ |
1902 | ci->qh_pool = dma_pool_create("ci_hw_qh", dev, | 1909 | ci->qh_pool = dma_pool_create("ci_hw_qh", dev->parent, |
1903 | sizeof(struct ci_hw_qh), | 1910 | sizeof(struct ci_hw_qh), |
1904 | 64, CI_HDRC_PAGE_SIZE); | 1911 | 64, CI_HDRC_PAGE_SIZE); |
1905 | if (ci->qh_pool == NULL) | 1912 | if (ci->qh_pool == NULL) |
1906 | return -ENOMEM; | 1913 | return -ENOMEM; |
1907 | 1914 | ||
1908 | ci->td_pool = dma_pool_create("ci_hw_td", dev, | 1915 | ci->td_pool = dma_pool_create("ci_hw_td", dev->parent, |
1909 | sizeof(struct ci_hw_td), | 1916 | sizeof(struct ci_hw_td), |
1910 | 64, CI_HDRC_PAGE_SIZE); | 1917 | 64, CI_HDRC_PAGE_SIZE); |
1911 | if (ci->td_pool == NULL) { | 1918 | if (ci->td_pool == NULL) { |
@@ -1973,6 +1980,8 @@ static void udc_id_switch_for_host(struct ci_hdrc *ci) | |||
1973 | */ | 1980 | */ |
1974 | if (ci->is_otg) | 1981 | if (ci->is_otg) |
1975 | hw_write_otgsc(ci, OTGSC_BSVIE | OTGSC_BSVIS, OTGSC_BSVIS); | 1982 | hw_write_otgsc(ci, OTGSC_BSVIE | OTGSC_BSVIS, OTGSC_BSVIS); |
1983 | |||
1984 | ci->vbus_active = 0; | ||
1976 | } | 1985 | } |
1977 | 1986 | ||
1978 | /** | 1987 | /** |
diff --git a/drivers/usb/class/Kconfig b/drivers/usb/class/Kconfig index bb8b73682a70..971385fe9abc 100644 --- a/drivers/usb/class/Kconfig +++ b/drivers/usb/class/Kconfig | |||
@@ -12,7 +12,7 @@ config USB_ACM | |||
12 | Please read <file:Documentation/usb/acm.txt> for details. | 12 | Please read <file:Documentation/usb/acm.txt> for details. |
13 | 13 | ||
14 | If your modem only reports "Cls=ff(vend.)" in the descriptors in | 14 | If your modem only reports "Cls=ff(vend.)" in the descriptors in |
15 | /proc/bus/usb/devices, then your modem will not work with this | 15 | /sys/kernel/debug/usb/devices, then your modem will not work with this |
16 | driver. | 16 | driver. |
17 | 17 | ||
18 | To compile this driver as a module, choose M here: the | 18 | To compile this driver as a module, choose M here: the |
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index d5388938bc7a..5357d83bbda2 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/errno.h> | 36 | #include <linux/errno.h> |
37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/log2.h> | ||
39 | #include <linux/tty.h> | 40 | #include <linux/tty.h> |
40 | #include <linux/serial.h> | 41 | #include <linux/serial.h> |
41 | #include <linux/tty_driver.h> | 42 | #include <linux/tty_driver.h> |
@@ -283,39 +284,13 @@ static DEVICE_ATTR(iCountryCodeRelDate, S_IRUGO, show_country_rel_date, NULL); | |||
283 | * Interrupt handlers for various ACM device responses | 284 | * Interrupt handlers for various ACM device responses |
284 | */ | 285 | */ |
285 | 286 | ||
286 | /* control interface reports status changes with "interrupt" transfers */ | 287 | static void acm_process_notification(struct acm *acm, unsigned char *buf) |
287 | static void acm_ctrl_irq(struct urb *urb) | ||
288 | { | 288 | { |
289 | struct acm *acm = urb->context; | ||
290 | struct usb_cdc_notification *dr = urb->transfer_buffer; | ||
291 | unsigned char *data; | ||
292 | int newctrl; | 289 | int newctrl; |
293 | int difference; | 290 | int difference; |
294 | int retval; | 291 | struct usb_cdc_notification *dr = (struct usb_cdc_notification *)buf; |
295 | int status = urb->status; | 292 | unsigned char *data = buf + sizeof(struct usb_cdc_notification); |
296 | 293 | ||
297 | switch (status) { | ||
298 | case 0: | ||
299 | /* success */ | ||
300 | break; | ||
301 | case -ECONNRESET: | ||
302 | case -ENOENT: | ||
303 | case -ESHUTDOWN: | ||
304 | /* this urb is terminated, clean up */ | ||
305 | dev_dbg(&acm->control->dev, | ||
306 | "%s - urb shutting down with status: %d\n", | ||
307 | __func__, status); | ||
308 | return; | ||
309 | default: | ||
310 | dev_dbg(&acm->control->dev, | ||
311 | "%s - nonzero urb status received: %d\n", | ||
312 | __func__, status); | ||
313 | goto exit; | ||
314 | } | ||
315 | |||
316 | usb_mark_last_busy(acm->dev); | ||
317 | |||
318 | data = (unsigned char *)(dr + 1); | ||
319 | switch (dr->bNotificationType) { | 294 | switch (dr->bNotificationType) { |
320 | case USB_CDC_NOTIFY_NETWORK_CONNECTION: | 295 | case USB_CDC_NOTIFY_NETWORK_CONNECTION: |
321 | dev_dbg(&acm->control->dev, | 296 | dev_dbg(&acm->control->dev, |
@@ -323,7 +298,15 @@ static void acm_ctrl_irq(struct urb *urb) | |||
323 | break; | 298 | break; |
324 | 299 | ||
325 | case USB_CDC_NOTIFY_SERIAL_STATE: | 300 | case USB_CDC_NOTIFY_SERIAL_STATE: |
301 | if (le16_to_cpu(dr->wLength) != 2) { | ||
302 | dev_dbg(&acm->control->dev, | ||
303 | "%s - malformed serial state\n", __func__); | ||
304 | break; | ||
305 | } | ||
306 | |||
326 | newctrl = get_unaligned_le16(data); | 307 | newctrl = get_unaligned_le16(data); |
308 | dev_dbg(&acm->control->dev, | ||
309 | "%s - serial state: 0x%x\n", __func__, newctrl); | ||
327 | 310 | ||
328 | if (!acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) { | 311 | if (!acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) { |
329 | dev_dbg(&acm->control->dev, | 312 | dev_dbg(&acm->control->dev, |
@@ -359,13 +342,86 @@ static void acm_ctrl_irq(struct urb *urb) | |||
359 | 342 | ||
360 | default: | 343 | default: |
361 | dev_dbg(&acm->control->dev, | 344 | dev_dbg(&acm->control->dev, |
362 | "%s - unknown notification %d received: index %d " | 345 | "%s - unknown notification %d received: index %d len %d\n", |
363 | "len %d data0 %d data1 %d\n", | ||
364 | __func__, | 346 | __func__, |
365 | dr->bNotificationType, dr->wIndex, | 347 | dr->bNotificationType, dr->wIndex, dr->wLength); |
366 | dr->wLength, data[0], data[1]); | 348 | } |
349 | } | ||
350 | |||
351 | /* control interface reports status changes with "interrupt" transfers */ | ||
352 | static void acm_ctrl_irq(struct urb *urb) | ||
353 | { | ||
354 | struct acm *acm = urb->context; | ||
355 | struct usb_cdc_notification *dr = urb->transfer_buffer; | ||
356 | unsigned int current_size = urb->actual_length; | ||
357 | unsigned int expected_size, copy_size, alloc_size; | ||
358 | int retval; | ||
359 | int status = urb->status; | ||
360 | |||
361 | switch (status) { | ||
362 | case 0: | ||
363 | /* success */ | ||
367 | break; | 364 | break; |
365 | case -ECONNRESET: | ||
366 | case -ENOENT: | ||
367 | case -ESHUTDOWN: | ||
368 | /* this urb is terminated, clean up */ | ||
369 | acm->nb_index = 0; | ||
370 | dev_dbg(&acm->control->dev, | ||
371 | "%s - urb shutting down with status: %d\n", | ||
372 | __func__, status); | ||
373 | return; | ||
374 | default: | ||
375 | dev_dbg(&acm->control->dev, | ||
376 | "%s - nonzero urb status received: %d\n", | ||
377 | __func__, status); | ||
378 | goto exit; | ||
379 | } | ||
380 | |||
381 | usb_mark_last_busy(acm->dev); | ||
382 | |||
383 | if (acm->nb_index) | ||
384 | dr = (struct usb_cdc_notification *)acm->notification_buffer; | ||
385 | |||
386 | /* size = notification-header + (optional) data */ | ||
387 | expected_size = sizeof(struct usb_cdc_notification) + | ||
388 | le16_to_cpu(dr->wLength); | ||
389 | |||
390 | if (current_size < expected_size) { | ||
391 | /* notification is transmitted fragmented, reassemble */ | ||
392 | if (acm->nb_size < expected_size) { | ||
393 | if (acm->nb_size) { | ||
394 | kfree(acm->notification_buffer); | ||
395 | acm->nb_size = 0; | ||
396 | } | ||
397 | alloc_size = roundup_pow_of_two(expected_size); | ||
398 | /* | ||
399 | * kmalloc ensures a valid notification_buffer after a | ||
400 | * use of kfree in case the previous allocation was too | ||
401 | * small. Final freeing is done on disconnect. | ||
402 | */ | ||
403 | acm->notification_buffer = | ||
404 | kmalloc(alloc_size, GFP_ATOMIC); | ||
405 | if (!acm->notification_buffer) | ||
406 | goto exit; | ||
407 | acm->nb_size = alloc_size; | ||
408 | } | ||
409 | |||
410 | copy_size = min(current_size, | ||
411 | expected_size - acm->nb_index); | ||
412 | |||
413 | memcpy(&acm->notification_buffer[acm->nb_index], | ||
414 | urb->transfer_buffer, copy_size); | ||
415 | acm->nb_index += copy_size; | ||
416 | current_size = acm->nb_index; | ||
417 | } | ||
418 | |||
419 | if (current_size >= expected_size) { | ||
420 | /* notification complete */ | ||
421 | acm_process_notification(acm, (unsigned char *)dr); | ||
422 | acm->nb_index = 0; | ||
368 | } | 423 | } |
424 | |||
369 | exit: | 425 | exit: |
370 | retval = usb_submit_urb(urb, GFP_ATOMIC); | 426 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
371 | if (retval && retval != -EPERM) | 427 | if (retval && retval != -EPERM) |
@@ -1174,6 +1230,7 @@ static int acm_probe(struct usb_interface *intf, | |||
1174 | int combined_interfaces = 0; | 1230 | int combined_interfaces = 0; |
1175 | struct device *tty_dev; | 1231 | struct device *tty_dev; |
1176 | int rv = -ENOMEM; | 1232 | int rv = -ENOMEM; |
1233 | int res; | ||
1177 | 1234 | ||
1178 | /* normal quirks */ | 1235 | /* normal quirks */ |
1179 | quirks = (unsigned long)id->driver_info; | 1236 | quirks = (unsigned long)id->driver_info; |
@@ -1274,23 +1331,12 @@ static int acm_probe(struct usb_interface *intf, | |||
1274 | return -EINVAL; | 1331 | return -EINVAL; |
1275 | } | 1332 | } |
1276 | look_for_collapsed_interface: | 1333 | look_for_collapsed_interface: |
1277 | for (i = 0; i < 3; i++) { | 1334 | res = usb_find_common_endpoints(data_interface->cur_altsetting, |
1278 | struct usb_endpoint_descriptor *ep; | 1335 | &epread, &epwrite, &epctrl, NULL); |
1279 | ep = &data_interface->cur_altsetting->endpoint[i].desc; | 1336 | if (res) |
1280 | 1337 | return res; | |
1281 | if (usb_endpoint_is_int_in(ep)) | 1338 | |
1282 | epctrl = ep; | 1339 | goto made_compressed_probe; |
1283 | else if (usb_endpoint_is_bulk_out(ep)) | ||
1284 | epwrite = ep; | ||
1285 | else if (usb_endpoint_is_bulk_in(ep)) | ||
1286 | epread = ep; | ||
1287 | else | ||
1288 | return -EINVAL; | ||
1289 | } | ||
1290 | if (!epctrl || !epread || !epwrite) | ||
1291 | return -ENODEV; | ||
1292 | else | ||
1293 | goto made_compressed_probe; | ||
1294 | } | 1340 | } |
1295 | 1341 | ||
1296 | skip_normal_probe: | 1342 | skip_normal_probe: |
@@ -1488,6 +1534,9 @@ skip_countries: | |||
1488 | epctrl->bInterval ? epctrl->bInterval : 16); | 1534 | epctrl->bInterval ? epctrl->bInterval : 16); |
1489 | acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 1535 | acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
1490 | acm->ctrlurb->transfer_dma = acm->ctrl_dma; | 1536 | acm->ctrlurb->transfer_dma = acm->ctrl_dma; |
1537 | acm->notification_buffer = NULL; | ||
1538 | acm->nb_index = 0; | ||
1539 | acm->nb_size = 0; | ||
1491 | 1540 | ||
1492 | dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor); | 1541 | dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor); |
1493 | 1542 | ||
@@ -1580,6 +1629,8 @@ static void acm_disconnect(struct usb_interface *intf) | |||
1580 | usb_free_coherent(acm->dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); | 1629 | usb_free_coherent(acm->dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); |
1581 | acm_read_buffers_free(acm); | 1630 | acm_read_buffers_free(acm); |
1582 | 1631 | ||
1632 | kfree(acm->notification_buffer); | ||
1633 | |||
1583 | if (!acm->combined_interfaces) | 1634 | if (!acm->combined_interfaces) |
1584 | usb_driver_release_interface(&acm_driver, intf == acm->control ? | 1635 | usb_driver_release_interface(&acm_driver, intf == acm->control ? |
1585 | acm->data : acm->control); | 1636 | acm->data : acm->control); |
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h index c980f11cdf56..7a2b3deafc90 100644 --- a/drivers/usb/class/cdc-acm.h +++ b/drivers/usb/class/cdc-acm.h | |||
@@ -98,7 +98,9 @@ struct acm { | |||
98 | struct acm_wb *putbuffer; /* for acm_tty_put_char() */ | 98 | struct acm_wb *putbuffer; /* for acm_tty_put_char() */ |
99 | int rx_buflimit; | 99 | int rx_buflimit; |
100 | spinlock_t read_lock; | 100 | spinlock_t read_lock; |
101 | int write_used; /* number of non-empty write buffers */ | 101 | u8 *notification_buffer; /* to reassemble fragmented notifications */ |
102 | unsigned int nb_index; | ||
103 | unsigned int nb_size; | ||
102 | int transmitting; | 104 | int transmitting; |
103 | spinlock_t write_lock; | 105 | spinlock_t write_lock; |
104 | struct mutex mutex; | 106 | struct mutex mutex; |
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 8fda45a45bd3..08669fee6d7f 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c | |||
@@ -58,7 +58,6 @@ MODULE_DEVICE_TABLE (usb, wdm_ids); | |||
58 | #define WDM_SUSPENDING 8 | 58 | #define WDM_SUSPENDING 8 |
59 | #define WDM_RESETTING 9 | 59 | #define WDM_RESETTING 9 |
60 | #define WDM_OVERFLOW 10 | 60 | #define WDM_OVERFLOW 10 |
61 | #define WDM_DRAIN_ON_OPEN 11 | ||
62 | 61 | ||
63 | #define WDM_MAX 16 | 62 | #define WDM_MAX 16 |
64 | 63 | ||
@@ -182,7 +181,7 @@ static void wdm_in_callback(struct urb *urb) | |||
182 | "nonzero urb status received: -ESHUTDOWN\n"); | 181 | "nonzero urb status received: -ESHUTDOWN\n"); |
183 | goto skip_error; | 182 | goto skip_error; |
184 | case -EPIPE: | 183 | case -EPIPE: |
185 | dev_dbg(&desc->intf->dev, | 184 | dev_err(&desc->intf->dev, |
186 | "nonzero urb status received: -EPIPE\n"); | 185 | "nonzero urb status received: -EPIPE\n"); |
187 | break; | 186 | break; |
188 | default: | 187 | default: |
@@ -210,25 +209,6 @@ static void wdm_in_callback(struct urb *urb) | |||
210 | desc->reslength = length; | 209 | desc->reslength = length; |
211 | } | 210 | } |
212 | } | 211 | } |
213 | |||
214 | /* | ||
215 | * Handling devices with the WDM_DRAIN_ON_OPEN flag set: | ||
216 | * If desc->resp_count is unset, then the urb was submitted | ||
217 | * without a prior notification. If the device returned any | ||
218 | * data, then this implies that it had messages queued without | ||
219 | * notifying us. Continue reading until that queue is flushed. | ||
220 | */ | ||
221 | if (!desc->resp_count) { | ||
222 | if (!length) { | ||
223 | /* do not propagate the expected -EPIPE */ | ||
224 | desc->rerr = 0; | ||
225 | goto unlock; | ||
226 | } | ||
227 | dev_dbg(&desc->intf->dev, "got %d bytes without notification\n", length); | ||
228 | set_bit(WDM_RESPONDING, &desc->flags); | ||
229 | usb_submit_urb(desc->response, GFP_ATOMIC); | ||
230 | } | ||
231 | |||
232 | skip_error: | 212 | skip_error: |
233 | set_bit(WDM_READ, &desc->flags); | 213 | set_bit(WDM_READ, &desc->flags); |
234 | wake_up(&desc->wait); | 214 | wake_up(&desc->wait); |
@@ -243,7 +223,6 @@ skip_error: | |||
243 | service_outstanding_interrupt(desc); | 223 | service_outstanding_interrupt(desc); |
244 | } | 224 | } |
245 | 225 | ||
246 | unlock: | ||
247 | spin_unlock(&desc->iuspin); | 226 | spin_unlock(&desc->iuspin); |
248 | } | 227 | } |
249 | 228 | ||
@@ -686,17 +665,6 @@ static int wdm_open(struct inode *inode, struct file *file) | |||
686 | dev_err(&desc->intf->dev, | 665 | dev_err(&desc->intf->dev, |
687 | "Error submitting int urb - %d\n", rv); | 666 | "Error submitting int urb - %d\n", rv); |
688 | rv = usb_translate_errors(rv); | 667 | rv = usb_translate_errors(rv); |
689 | } else if (test_bit(WDM_DRAIN_ON_OPEN, &desc->flags)) { | ||
690 | /* | ||
691 | * Some devices keep pending messages queued | ||
692 | * without resending notifications. We must | ||
693 | * flush the message queue before we can | ||
694 | * assume a one-to-one relationship between | ||
695 | * notifications and messages in the queue | ||
696 | */ | ||
697 | dev_dbg(&desc->intf->dev, "draining queued data\n"); | ||
698 | set_bit(WDM_RESPONDING, &desc->flags); | ||
699 | rv = usb_submit_urb(desc->response, GFP_KERNEL); | ||
700 | } | 668 | } |
701 | } else { | 669 | } else { |
702 | rv = 0; | 670 | rv = 0; |
@@ -803,8 +771,7 @@ static void wdm_rxwork(struct work_struct *work) | |||
803 | /* --- hotplug --- */ | 771 | /* --- hotplug --- */ |
804 | 772 | ||
805 | static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor *ep, | 773 | static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor *ep, |
806 | u16 bufsize, int (*manage_power)(struct usb_interface *, int), | 774 | u16 bufsize, int (*manage_power)(struct usb_interface *, int)) |
807 | bool drain_on_open) | ||
808 | { | 775 | { |
809 | int rv = -ENOMEM; | 776 | int rv = -ENOMEM; |
810 | struct wdm_device *desc; | 777 | struct wdm_device *desc; |
@@ -891,68 +858,6 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor | |||
891 | 858 | ||
892 | desc->manage_power = manage_power; | 859 | desc->manage_power = manage_power; |
893 | 860 | ||
894 | /* | ||
895 | * "drain_on_open" enables a hack to work around a firmware | ||
896 | * issue observed on network functions, in particular MBIM | ||
897 | * functions. | ||
898 | * | ||
899 | * Quoting section 7 of the CDC-WMC r1.1 specification: | ||
900 | * | ||
901 | * "The firmware shall interpret GetEncapsulatedResponse as a | ||
902 | * request to read response bytes. The firmware shall send | ||
903 | * the next wLength bytes from the response. The firmware | ||
904 | * shall allow the host to retrieve data using any number of | ||
905 | * GetEncapsulatedResponse requests. The firmware shall | ||
906 | * return a zero- length reply if there are no data bytes | ||
907 | * available. | ||
908 | * | ||
909 | * The firmware shall send ResponseAvailable notifications | ||
910 | * periodically, using any appropriate algorithm, to inform | ||
911 | * the host that there is data available in the reply | ||
912 | * buffer. The firmware is allowed to send ResponseAvailable | ||
913 | * notifications even if there is no data available, but | ||
914 | * this will obviously reduce overall performance." | ||
915 | * | ||
916 | * These requirements, although they make equally sense, are | ||
917 | * often not implemented by network functions. Some firmwares | ||
918 | * will queue data indefinitely, without ever resending a | ||
919 | * notification. The result is that the driver and firmware | ||
920 | * loses "syncronization" if the driver ever fails to respond | ||
921 | * to a single notification, something which easily can happen | ||
922 | * on release(). When this happens, the driver will appear to | ||
923 | * never receive notifications for the most current data. Each | ||
924 | * notification will only cause a single read, which returns | ||
925 | * the oldest data in the firmware's queue. | ||
926 | * | ||
927 | * The "drain_on_open" hack resolves the situation by draining | ||
928 | * data from the firmware until none is returned, without a | ||
929 | * prior notification. | ||
930 | * | ||
931 | * This will inevitably race with the firmware, risking that | ||
932 | * we read data from the device before handling the associated | ||
933 | * notification. To make things worse, some of the devices | ||
934 | * needing the hack do not implement the "return zero if no | ||
935 | * data is available" requirement either. Instead they return | ||
936 | * an error on the subsequent read in this case. This means | ||
937 | * that "winning" the race can cause an unexpected EIO to | ||
938 | * userspace. | ||
939 | * | ||
940 | * "winning" the race is more likely on resume() than on | ||
941 | * open(), and the unexpected error is more harmful in the | ||
942 | * middle of an open session. The hack is therefore only | ||
943 | * applied on open(), and not on resume() where it logically | ||
944 | * would be equally necessary. So we define open() as the only | ||
945 | * driver <-> device "syncronization point". Should we happen | ||
946 | * to lose a notification after open(), then syncronization | ||
947 | * will be lost until release() | ||
948 | * | ||
949 | * The hack should not be enabled for CDC WDM devices | ||
950 | * conforming to the CDC-WMC r1.1 specification. This is | ||
951 | * ensured by setting drain_on_open to false in wdm_probe(). | ||
952 | */ | ||
953 | if (drain_on_open) | ||
954 | set_bit(WDM_DRAIN_ON_OPEN, &desc->flags); | ||
955 | |||
956 | spin_lock(&wdm_device_list_lock); | 861 | spin_lock(&wdm_device_list_lock); |
957 | list_add(&desc->device_list, &wdm_device_list); | 862 | list_add(&desc->device_list, &wdm_device_list); |
958 | spin_unlock(&wdm_device_list_lock); | 863 | spin_unlock(&wdm_device_list_lock); |
@@ -1006,7 +911,7 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
1006 | goto err; | 911 | goto err; |
1007 | ep = &iface->endpoint[0].desc; | 912 | ep = &iface->endpoint[0].desc; |
1008 | 913 | ||
1009 | rv = wdm_create(intf, ep, maxcom, &wdm_manage_power, false); | 914 | rv = wdm_create(intf, ep, maxcom, &wdm_manage_power); |
1010 | 915 | ||
1011 | err: | 916 | err: |
1012 | return rv; | 917 | return rv; |
@@ -1038,7 +943,7 @@ struct usb_driver *usb_cdc_wdm_register(struct usb_interface *intf, | |||
1038 | { | 943 | { |
1039 | int rv = -EINVAL; | 944 | int rv = -EINVAL; |
1040 | 945 | ||
1041 | rv = wdm_create(intf, ep, bufsize, manage_power, true); | 946 | rv = wdm_create(intf, ep, bufsize, manage_power); |
1042 | if (rv < 0) | 947 | if (rv < 0) |
1043 | goto err; | 948 | goto err; |
1044 | 949 | ||
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index cc61055fb9be..fb87c17ed6fa 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c | |||
@@ -294,7 +294,7 @@ static int usblp_ctrl_msg(struct usblp *usblp, int request, int type, int dir, i | |||
294 | 294 | ||
295 | /* | 295 | /* |
296 | * See the description for usblp_select_alts() below for the usage | 296 | * See the description for usblp_select_alts() below for the usage |
297 | * explanation. Look into your /proc/bus/usb/devices and dmesg in | 297 | * explanation. Look into your /sys/kernel/debug/usb/devices and dmesg in |
298 | * case of any trouble. | 298 | * case of any trouble. |
299 | */ | 299 | */ |
300 | static int proto_bias = -1; | 300 | static int proto_bias = -1; |
@@ -1239,8 +1239,9 @@ static int usblp_select_alts(struct usblp *usblp) | |||
1239 | { | 1239 | { |
1240 | struct usb_interface *if_alt; | 1240 | struct usb_interface *if_alt; |
1241 | struct usb_host_interface *ifd; | 1241 | struct usb_host_interface *ifd; |
1242 | struct usb_endpoint_descriptor *epd, *epwrite, *epread; | 1242 | struct usb_endpoint_descriptor *epwrite, *epread; |
1243 | int p, i, e; | 1243 | int p, i; |
1244 | int res; | ||
1244 | 1245 | ||
1245 | if_alt = usblp->intf; | 1246 | if_alt = usblp->intf; |
1246 | 1247 | ||
@@ -1260,31 +1261,21 @@ static int usblp_select_alts(struct usblp *usblp) | |||
1260 | ifd->desc.bInterfaceProtocol > USBLP_LAST_PROTOCOL) | 1261 | ifd->desc.bInterfaceProtocol > USBLP_LAST_PROTOCOL) |
1261 | continue; | 1262 | continue; |
1262 | 1263 | ||
1263 | /* Look for bulk OUT and IN endpoints. */ | 1264 | /* Look for the expected bulk endpoints. */ |
1264 | epwrite = epread = NULL; | 1265 | if (ifd->desc.bInterfaceProtocol > 1) { |
1265 | for (e = 0; e < ifd->desc.bNumEndpoints; e++) { | 1266 | res = usb_find_common_endpoints(ifd, |
1266 | epd = &ifd->endpoint[e].desc; | 1267 | &epread, &epwrite, NULL, NULL); |
1267 | 1268 | } else { | |
1268 | if (usb_endpoint_is_bulk_out(epd)) | 1269 | epread = NULL; |
1269 | if (!epwrite) | 1270 | res = usb_find_bulk_out_endpoint(ifd, &epwrite); |
1270 | epwrite = epd; | ||
1271 | |||
1272 | if (usb_endpoint_is_bulk_in(epd)) | ||
1273 | if (!epread) | ||
1274 | epread = epd; | ||
1275 | } | 1271 | } |
1276 | 1272 | ||
1277 | /* Ignore buggy hardware without the right endpoints. */ | 1273 | /* Ignore buggy hardware without the right endpoints. */ |
1278 | if (!epwrite || (ifd->desc.bInterfaceProtocol > 1 && !epread)) | 1274 | if (res) |
1279 | continue; | 1275 | continue; |
1280 | 1276 | ||
1281 | /* | 1277 | /* Turn off reads for buggy bidirectional printers. */ |
1282 | * Turn off reads for USB_CLASS_PRINTER/1/1 (unidirectional) | 1278 | if (usblp->quirks & USBLP_QUIRK_BIDIR) { |
1283 | * interfaces and buggy bidirectional printers. | ||
1284 | */ | ||
1285 | if (ifd->desc.bInterfaceProtocol == 1) { | ||
1286 | epread = NULL; | ||
1287 | } else if (usblp->quirks & USBLP_QUIRK_BIDIR) { | ||
1288 | printk(KERN_INFO "usblp%d: Disabling reads from " | 1279 | printk(KERN_INFO "usblp%d: Disabling reads from " |
1289 | "problematic bidirectional printer\n", | 1280 | "problematic bidirectional printer\n", |
1290 | usblp->minor); | 1281 | usblp->minor); |
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 8fb309a0ff6b..578f424decc2 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c | |||
@@ -1375,7 +1375,7 @@ static int usbtmc_probe(struct usb_interface *intf, | |||
1375 | { | 1375 | { |
1376 | struct usbtmc_device_data *data; | 1376 | struct usbtmc_device_data *data; |
1377 | struct usb_host_interface *iface_desc; | 1377 | struct usb_host_interface *iface_desc; |
1378 | struct usb_endpoint_descriptor *endpoint; | 1378 | struct usb_endpoint_descriptor *bulk_in, *bulk_out, *int_in; |
1379 | int n; | 1379 | int n; |
1380 | int retcode; | 1380 | int retcode; |
1381 | 1381 | ||
@@ -1421,49 +1421,29 @@ static int usbtmc_probe(struct usb_interface *intf, | |||
1421 | iface_desc = data->intf->cur_altsetting; | 1421 | iface_desc = data->intf->cur_altsetting; |
1422 | data->ifnum = iface_desc->desc.bInterfaceNumber; | 1422 | data->ifnum = iface_desc->desc.bInterfaceNumber; |
1423 | 1423 | ||
1424 | /* Find bulk in endpoint */ | 1424 | /* Find bulk endpoints */ |
1425 | for (n = 0; n < iface_desc->desc.bNumEndpoints; n++) { | 1425 | retcode = usb_find_common_endpoints(iface_desc, |
1426 | endpoint = &iface_desc->endpoint[n].desc; | 1426 | &bulk_in, &bulk_out, NULL, NULL); |
1427 | 1427 | if (retcode) { | |
1428 | if (usb_endpoint_is_bulk_in(endpoint)) { | ||
1429 | data->bulk_in = endpoint->bEndpointAddress; | ||
1430 | dev_dbg(&intf->dev, "Found bulk in endpoint at %u\n", | ||
1431 | data->bulk_in); | ||
1432 | break; | ||
1433 | } | ||
1434 | } | ||
1435 | |||
1436 | /* Find bulk out endpoint */ | ||
1437 | for (n = 0; n < iface_desc->desc.bNumEndpoints; n++) { | ||
1438 | endpoint = &iface_desc->endpoint[n].desc; | ||
1439 | |||
1440 | if (usb_endpoint_is_bulk_out(endpoint)) { | ||
1441 | data->bulk_out = endpoint->bEndpointAddress; | ||
1442 | dev_dbg(&intf->dev, "Found Bulk out endpoint at %u\n", | ||
1443 | data->bulk_out); | ||
1444 | break; | ||
1445 | } | ||
1446 | } | ||
1447 | |||
1448 | if (!data->bulk_out || !data->bulk_in) { | ||
1449 | dev_err(&intf->dev, "bulk endpoints not found\n"); | 1428 | dev_err(&intf->dev, "bulk endpoints not found\n"); |
1450 | retcode = -ENODEV; | ||
1451 | goto err_put; | 1429 | goto err_put; |
1452 | } | 1430 | } |
1453 | 1431 | ||
1432 | data->bulk_in = bulk_in->bEndpointAddress; | ||
1433 | dev_dbg(&intf->dev, "Found bulk in endpoint at %u\n", data->bulk_in); | ||
1434 | |||
1435 | data->bulk_out = bulk_out->bEndpointAddress; | ||
1436 | dev_dbg(&intf->dev, "Found Bulk out endpoint at %u\n", data->bulk_out); | ||
1437 | |||
1454 | /* Find int endpoint */ | 1438 | /* Find int endpoint */ |
1455 | for (n = 0; n < iface_desc->desc.bNumEndpoints; n++) { | 1439 | retcode = usb_find_int_in_endpoint(iface_desc, &int_in); |
1456 | endpoint = &iface_desc->endpoint[n].desc; | 1440 | if (!retcode) { |
1457 | 1441 | data->iin_ep_present = 1; | |
1458 | if (usb_endpoint_is_int_in(endpoint)) { | 1442 | data->iin_ep = int_in->bEndpointAddress; |
1459 | data->iin_ep_present = 1; | 1443 | data->iin_wMaxPacketSize = usb_endpoint_maxp(int_in); |
1460 | data->iin_ep = endpoint->bEndpointAddress; | 1444 | data->iin_interval = int_in->bInterval; |
1461 | data->iin_wMaxPacketSize = usb_endpoint_maxp(endpoint); | 1445 | dev_dbg(&intf->dev, "Found Int in endpoint at %u\n", |
1462 | data->iin_interval = endpoint->bInterval; | ||
1463 | dev_dbg(&intf->dev, "Found Int in endpoint at %u\n", | ||
1464 | data->iin_ep); | 1446 | data->iin_ep); |
1465 | break; | ||
1466 | } | ||
1467 | } | 1447 | } |
1468 | 1448 | ||
1469 | retcode = get_capabilities(data); | 1449 | retcode = get_capabilities(data); |
diff --git a/drivers/usb/common/usb-otg-fsm.c b/drivers/usb/common/usb-otg-fsm.c index 2f537bbdda09..b8fe31e409a5 100644 --- a/drivers/usb/common/usb-otg-fsm.c +++ b/drivers/usb/common/usb-otg-fsm.c | |||
@@ -31,6 +31,13 @@ | |||
31 | #include <linux/usb/otg.h> | 31 | #include <linux/usb/otg.h> |
32 | #include <linux/usb/otg-fsm.h> | 32 | #include <linux/usb/otg-fsm.h> |
33 | 33 | ||
34 | #ifdef VERBOSE | ||
35 | #define VDBG(fmt, args...) pr_debug("[%s] " fmt, \ | ||
36 | __func__, ## args) | ||
37 | #else | ||
38 | #define VDBG(stuff...) do {} while (0) | ||
39 | #endif | ||
40 | |||
34 | /* Change USB protocol when there is a protocol change */ | 41 | /* Change USB protocol when there is a protocol change */ |
35 | static int otg_set_protocol(struct otg_fsm *fsm, int protocol) | 42 | static int otg_set_protocol(struct otg_fsm *fsm, int protocol) |
36 | { | 43 | { |
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile index b99b871c4b9d..250ec1d662d9 100644 --- a/drivers/usb/core/Makefile +++ b/drivers/usb/core/Makefile | |||
@@ -8,7 +8,7 @@ usbcore-y += devio.o notify.o generic.o quirks.o devices.o | |||
8 | usbcore-y += port.o | 8 | usbcore-y += port.o |
9 | 9 | ||
10 | usbcore-$(CONFIG_OF) += of.o | 10 | usbcore-$(CONFIG_OF) += of.o |
11 | usbcore-$(CONFIG_PCI) += hcd-pci.o | 11 | usbcore-$(CONFIG_USB_PCI) += hcd-pci.o |
12 | usbcore-$(CONFIG_ACPI) += usb-acpi.o | 12 | usbcore-$(CONFIG_ACPI) += usb-acpi.o |
13 | 13 | ||
14 | obj-$(CONFIG_USB) += usbcore.o | 14 | obj-$(CONFIG_USB) += usbcore.o |
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c index b9bf6e2eb6fe..b64568cf572c 100644 --- a/drivers/usb/core/buffer.c +++ b/drivers/usb/core/buffer.c | |||
@@ -66,7 +66,7 @@ int hcd_buffer_create(struct usb_hcd *hcd) | |||
66 | int i, size; | 66 | int i, size; |
67 | 67 | ||
68 | if (!IS_ENABLED(CONFIG_HAS_DMA) || | 68 | if (!IS_ENABLED(CONFIG_HAS_DMA) || |
69 | (!hcd->self.controller->dma_mask && | 69 | (!is_device_dma_capable(hcd->self.sysdev) && |
70 | !(hcd->driver->flags & HCD_LOCAL_MEM))) | 70 | !(hcd->driver->flags & HCD_LOCAL_MEM))) |
71 | return 0; | 71 | return 0; |
72 | 72 | ||
@@ -75,7 +75,7 @@ int hcd_buffer_create(struct usb_hcd *hcd) | |||
75 | if (!size) | 75 | if (!size) |
76 | continue; | 76 | continue; |
77 | snprintf(name, sizeof(name), "buffer-%d", size); | 77 | snprintf(name, sizeof(name), "buffer-%d", size); |
78 | hcd->pool[i] = dma_pool_create(name, hcd->self.controller, | 78 | hcd->pool[i] = dma_pool_create(name, hcd->self.sysdev, |
79 | size, size, 0); | 79 | size, size, 0); |
80 | if (!hcd->pool[i]) { | 80 | if (!hcd->pool[i]) { |
81 | hcd_buffer_destroy(hcd); | 81 | hcd_buffer_destroy(hcd); |
@@ -130,7 +130,7 @@ void *hcd_buffer_alloc( | |||
130 | 130 | ||
131 | /* some USB hosts just use PIO */ | 131 | /* some USB hosts just use PIO */ |
132 | if (!IS_ENABLED(CONFIG_HAS_DMA) || | 132 | if (!IS_ENABLED(CONFIG_HAS_DMA) || |
133 | (!bus->controller->dma_mask && | 133 | (!is_device_dma_capable(bus->sysdev) && |
134 | !(hcd->driver->flags & HCD_LOCAL_MEM))) { | 134 | !(hcd->driver->flags & HCD_LOCAL_MEM))) { |
135 | *dma = ~(dma_addr_t) 0; | 135 | *dma = ~(dma_addr_t) 0; |
136 | return kmalloc(size, mem_flags); | 136 | return kmalloc(size, mem_flags); |
@@ -140,7 +140,7 @@ void *hcd_buffer_alloc( | |||
140 | if (size <= pool_max[i]) | 140 | if (size <= pool_max[i]) |
141 | return dma_pool_alloc(hcd->pool[i], mem_flags, dma); | 141 | return dma_pool_alloc(hcd->pool[i], mem_flags, dma); |
142 | } | 142 | } |
143 | return dma_alloc_coherent(hcd->self.controller, size, dma, mem_flags); | 143 | return dma_alloc_coherent(hcd->self.sysdev, size, dma, mem_flags); |
144 | } | 144 | } |
145 | 145 | ||
146 | void hcd_buffer_free( | 146 | void hcd_buffer_free( |
@@ -157,7 +157,7 @@ void hcd_buffer_free( | |||
157 | return; | 157 | return; |
158 | 158 | ||
159 | if (!IS_ENABLED(CONFIG_HAS_DMA) || | 159 | if (!IS_ENABLED(CONFIG_HAS_DMA) || |
160 | (!bus->controller->dma_mask && | 160 | (!is_device_dma_capable(bus->sysdev) && |
161 | !(hcd->driver->flags & HCD_LOCAL_MEM))) { | 161 | !(hcd->driver->flags & HCD_LOCAL_MEM))) { |
162 | kfree(addr); | 162 | kfree(addr); |
163 | return; | 163 | return; |
@@ -169,5 +169,5 @@ void hcd_buffer_free( | |||
169 | return; | 169 | return; |
170 | } | 170 | } |
171 | } | 171 | } |
172 | dma_free_coherent(hcd->self.controller, size, addr, dma); | 172 | dma_free_coherent(hcd->self.sysdev, size, addr, dma); |
173 | } | 173 | } |
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index f2987ddb1cde..55dea2e7828f 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c | |||
@@ -24,7 +24,7 @@ | |||
24 | * <mountpoint>/devices contains USB topology, device, config, class, | 24 | * <mountpoint>/devices contains USB topology, device, config, class, |
25 | * interface, & endpoint data. | 25 | * interface, & endpoint data. |
26 | * | 26 | * |
27 | * I considered using /proc/bus/usb/devices/device# for each device | 27 | * I considered using /dev/bus/usb/device# for each device |
28 | * as it is attached or detached, but I didn't like this for some | 28 | * as it is attached or detached, but I didn't like this for some |
29 | * reason -- maybe it's just too deep of a directory structure. | 29 | * reason -- maybe it's just too deep of a directory structure. |
30 | * I also don't like looking in multiple places to gather and view | 30 | * I also don't like looking in multiple places to gather and view |
@@ -40,7 +40,7 @@ | |||
40 | * Converted the whole proc stuff to real | 40 | * Converted the whole proc stuff to real |
41 | * read methods. Now not the whole device list needs to fit | 41 | * read methods. Now not the whole device list needs to fit |
42 | * into one page, only the device list for one bus. | 42 | * into one page, only the device list for one bus. |
43 | * Added a poll method to /proc/bus/usb/devices, to wake | 43 | * Added a poll method to /sys/kernel/debug/usb/devices, to wake |
44 | * up an eventual usbd | 44 | * up an eventual usbd |
45 | * 2000-01-04: Thomas Sailer <sailer@ife.ee.ethz.ch> | 45 | * 2000-01-04: Thomas Sailer <sailer@ife.ee.ethz.ch> |
46 | * Turned into its own filesystem | 46 | * Turned into its own filesystem |
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index cdee5130638b..eb87a259d55c 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -1331,6 +1331,24 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |||
1331 | */ | 1331 | */ |
1332 | if (udev->parent && !PMSG_IS_AUTO(msg)) | 1332 | if (udev->parent && !PMSG_IS_AUTO(msg)) |
1333 | status = 0; | 1333 | status = 0; |
1334 | |||
1335 | /* | ||
1336 | * If the device is inaccessible, don't try to resume | ||
1337 | * suspended interfaces and just return the error. | ||
1338 | */ | ||
1339 | if (status && status != -EBUSY) { | ||
1340 | int err; | ||
1341 | u16 devstat; | ||
1342 | |||
1343 | err = usb_get_status(udev, USB_RECIP_DEVICE, 0, | ||
1344 | &devstat); | ||
1345 | if (err) { | ||
1346 | dev_err(&udev->dev, | ||
1347 | "Failed to suspend device, error %d\n", | ||
1348 | status); | ||
1349 | goto done; | ||
1350 | } | ||
1351 | } | ||
1334 | } | 1352 | } |
1335 | 1353 | ||
1336 | /* If the suspend failed, resume interfaces that did get suspended */ | 1354 | /* If the suspend failed, resume interfaces that did get suspended */ |
@@ -1763,6 +1781,9 @@ static int autosuspend_check(struct usb_device *udev) | |||
1763 | int w, i; | 1781 | int w, i; |
1764 | struct usb_interface *intf; | 1782 | struct usb_interface *intf; |
1765 | 1783 | ||
1784 | if (udev->state == USB_STATE_NOTATTACHED) | ||
1785 | return -ENODEV; | ||
1786 | |||
1766 | /* Fail if autosuspend is disabled, or any interfaces are in use, or | 1787 | /* Fail if autosuspend is disabled, or any interfaces are in use, or |
1767 | * any interface drivers require remote wakeup but it isn't available. | 1788 | * any interface drivers require remote wakeup but it isn't available. |
1768 | */ | 1789 | */ |
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index e26bd5e773ad..87ad6b6bfee8 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #define MAX_USB_MINORS 256 | 29 | #define MAX_USB_MINORS 256 |
30 | static const struct file_operations *usb_minors[MAX_USB_MINORS]; | 30 | static const struct file_operations *usb_minors[MAX_USB_MINORS]; |
31 | static DECLARE_RWSEM(minor_rwsem); | 31 | static DECLARE_RWSEM(minor_rwsem); |
32 | static DEFINE_MUTEX(init_usb_class_mutex); | ||
32 | 33 | ||
33 | static int usb_open(struct inode *inode, struct file *file) | 34 | static int usb_open(struct inode *inode, struct file *file) |
34 | { | 35 | { |
@@ -111,8 +112,9 @@ static void release_usb_class(struct kref *kref) | |||
111 | 112 | ||
112 | static void destroy_usb_class(void) | 113 | static void destroy_usb_class(void) |
113 | { | 114 | { |
114 | if (usb_class) | 115 | mutex_lock(&init_usb_class_mutex); |
115 | kref_put(&usb_class->kref, release_usb_class); | 116 | kref_put(&usb_class->kref, release_usb_class); |
117 | mutex_unlock(&init_usb_class_mutex); | ||
116 | } | 118 | } |
117 | 119 | ||
118 | int usb_major_init(void) | 120 | int usb_major_init(void) |
@@ -173,7 +175,10 @@ int usb_register_dev(struct usb_interface *intf, | |||
173 | if (intf->minor >= 0) | 175 | if (intf->minor >= 0) |
174 | return -EADDRINUSE; | 176 | return -EADDRINUSE; |
175 | 177 | ||
178 | mutex_lock(&init_usb_class_mutex); | ||
176 | retval = init_usb_class(); | 179 | retval = init_usb_class(); |
180 | mutex_unlock(&init_usb_class_mutex); | ||
181 | |||
177 | if (retval) | 182 | if (retval) |
178 | return retval; | 183 | return retval; |
179 | 184 | ||
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 79bdca5cb9c7..49550790a3cb 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -1076,6 +1076,7 @@ static void usb_deregister_bus (struct usb_bus *bus) | |||
1076 | static int register_root_hub(struct usb_hcd *hcd) | 1076 | static int register_root_hub(struct usb_hcd *hcd) |
1077 | { | 1077 | { |
1078 | struct device *parent_dev = hcd->self.controller; | 1078 | struct device *parent_dev = hcd->self.controller; |
1079 | struct device *sysdev = hcd->self.sysdev; | ||
1079 | struct usb_device *usb_dev = hcd->self.root_hub; | 1080 | struct usb_device *usb_dev = hcd->self.root_hub; |
1080 | const int devnum = 1; | 1081 | const int devnum = 1; |
1081 | int retval; | 1082 | int retval; |
@@ -1122,7 +1123,7 @@ static int register_root_hub(struct usb_hcd *hcd) | |||
1122 | /* Did the HC die before the root hub was registered? */ | 1123 | /* Did the HC die before the root hub was registered? */ |
1123 | if (HCD_DEAD(hcd)) | 1124 | if (HCD_DEAD(hcd)) |
1124 | usb_hc_died (hcd); /* This time clean up */ | 1125 | usb_hc_died (hcd); /* This time clean up */ |
1125 | usb_dev->dev.of_node = parent_dev->of_node; | 1126 | usb_dev->dev.of_node = sysdev->of_node; |
1126 | } | 1127 | } |
1127 | mutex_unlock(&usb_bus_idr_lock); | 1128 | mutex_unlock(&usb_bus_idr_lock); |
1128 | 1129 | ||
@@ -1435,7 +1436,7 @@ void usb_hcd_unmap_urb_setup_for_dma(struct usb_hcd *hcd, struct urb *urb) | |||
1435 | { | 1436 | { |
1436 | if (IS_ENABLED(CONFIG_HAS_DMA) && | 1437 | if (IS_ENABLED(CONFIG_HAS_DMA) && |
1437 | (urb->transfer_flags & URB_SETUP_MAP_SINGLE)) | 1438 | (urb->transfer_flags & URB_SETUP_MAP_SINGLE)) |
1438 | dma_unmap_single(hcd->self.controller, | 1439 | dma_unmap_single(hcd->self.sysdev, |
1439 | urb->setup_dma, | 1440 | urb->setup_dma, |
1440 | sizeof(struct usb_ctrlrequest), | 1441 | sizeof(struct usb_ctrlrequest), |
1441 | DMA_TO_DEVICE); | 1442 | DMA_TO_DEVICE); |
@@ -1468,19 +1469,19 @@ void usb_hcd_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) | |||
1468 | dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | 1469 | dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; |
1469 | if (IS_ENABLED(CONFIG_HAS_DMA) && | 1470 | if (IS_ENABLED(CONFIG_HAS_DMA) && |
1470 | (urb->transfer_flags & URB_DMA_MAP_SG)) | 1471 | (urb->transfer_flags & URB_DMA_MAP_SG)) |
1471 | dma_unmap_sg(hcd->self.controller, | 1472 | dma_unmap_sg(hcd->self.sysdev, |
1472 | urb->sg, | 1473 | urb->sg, |
1473 | urb->num_sgs, | 1474 | urb->num_sgs, |
1474 | dir); | 1475 | dir); |
1475 | else if (IS_ENABLED(CONFIG_HAS_DMA) && | 1476 | else if (IS_ENABLED(CONFIG_HAS_DMA) && |
1476 | (urb->transfer_flags & URB_DMA_MAP_PAGE)) | 1477 | (urb->transfer_flags & URB_DMA_MAP_PAGE)) |
1477 | dma_unmap_page(hcd->self.controller, | 1478 | dma_unmap_page(hcd->self.sysdev, |
1478 | urb->transfer_dma, | 1479 | urb->transfer_dma, |
1479 | urb->transfer_buffer_length, | 1480 | urb->transfer_buffer_length, |
1480 | dir); | 1481 | dir); |
1481 | else if (IS_ENABLED(CONFIG_HAS_DMA) && | 1482 | else if (IS_ENABLED(CONFIG_HAS_DMA) && |
1482 | (urb->transfer_flags & URB_DMA_MAP_SINGLE)) | 1483 | (urb->transfer_flags & URB_DMA_MAP_SINGLE)) |
1483 | dma_unmap_single(hcd->self.controller, | 1484 | dma_unmap_single(hcd->self.sysdev, |
1484 | urb->transfer_dma, | 1485 | urb->transfer_dma, |
1485 | urb->transfer_buffer_length, | 1486 | urb->transfer_buffer_length, |
1486 | dir); | 1487 | dir); |
@@ -1523,11 +1524,11 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, | |||
1523 | return ret; | 1524 | return ret; |
1524 | if (IS_ENABLED(CONFIG_HAS_DMA) && hcd->self.uses_dma) { | 1525 | if (IS_ENABLED(CONFIG_HAS_DMA) && hcd->self.uses_dma) { |
1525 | urb->setup_dma = dma_map_single( | 1526 | urb->setup_dma = dma_map_single( |
1526 | hcd->self.controller, | 1527 | hcd->self.sysdev, |
1527 | urb->setup_packet, | 1528 | urb->setup_packet, |
1528 | sizeof(struct usb_ctrlrequest), | 1529 | sizeof(struct usb_ctrlrequest), |
1529 | DMA_TO_DEVICE); | 1530 | DMA_TO_DEVICE); |
1530 | if (dma_mapping_error(hcd->self.controller, | 1531 | if (dma_mapping_error(hcd->self.sysdev, |
1531 | urb->setup_dma)) | 1532 | urb->setup_dma)) |
1532 | return -EAGAIN; | 1533 | return -EAGAIN; |
1533 | urb->transfer_flags |= URB_SETUP_MAP_SINGLE; | 1534 | urb->transfer_flags |= URB_SETUP_MAP_SINGLE; |
@@ -1558,7 +1559,7 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, | |||
1558 | } | 1559 | } |
1559 | 1560 | ||
1560 | n = dma_map_sg( | 1561 | n = dma_map_sg( |
1561 | hcd->self.controller, | 1562 | hcd->self.sysdev, |
1562 | urb->sg, | 1563 | urb->sg, |
1563 | urb->num_sgs, | 1564 | urb->num_sgs, |
1564 | dir); | 1565 | dir); |
@@ -1573,12 +1574,12 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, | |||
1573 | } else if (urb->sg) { | 1574 | } else if (urb->sg) { |
1574 | struct scatterlist *sg = urb->sg; | 1575 | struct scatterlist *sg = urb->sg; |
1575 | urb->transfer_dma = dma_map_page( | 1576 | urb->transfer_dma = dma_map_page( |
1576 | hcd->self.controller, | 1577 | hcd->self.sysdev, |
1577 | sg_page(sg), | 1578 | sg_page(sg), |
1578 | sg->offset, | 1579 | sg->offset, |
1579 | urb->transfer_buffer_length, | 1580 | urb->transfer_buffer_length, |
1580 | dir); | 1581 | dir); |
1581 | if (dma_mapping_error(hcd->self.controller, | 1582 | if (dma_mapping_error(hcd->self.sysdev, |
1582 | urb->transfer_dma)) | 1583 | urb->transfer_dma)) |
1583 | ret = -EAGAIN; | 1584 | ret = -EAGAIN; |
1584 | else | 1585 | else |
@@ -1588,11 +1589,11 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, | |||
1588 | ret = -EAGAIN; | 1589 | ret = -EAGAIN; |
1589 | } else { | 1590 | } else { |
1590 | urb->transfer_dma = dma_map_single( | 1591 | urb->transfer_dma = dma_map_single( |
1591 | hcd->self.controller, | 1592 | hcd->self.sysdev, |
1592 | urb->transfer_buffer, | 1593 | urb->transfer_buffer, |
1593 | urb->transfer_buffer_length, | 1594 | urb->transfer_buffer_length, |
1594 | dir); | 1595 | dir); |
1595 | if (dma_mapping_error(hcd->self.controller, | 1596 | if (dma_mapping_error(hcd->self.sysdev, |
1596 | urb->transfer_dma)) | 1597 | urb->transfer_dma)) |
1597 | ret = -EAGAIN; | 1598 | ret = -EAGAIN; |
1598 | else | 1599 | else |
@@ -2498,24 +2499,8 @@ static void init_giveback_urb_bh(struct giveback_urb_bh *bh) | |||
2498 | tasklet_init(&bh->bh, usb_giveback_urb_bh, (unsigned long)bh); | 2499 | tasklet_init(&bh->bh, usb_giveback_urb_bh, (unsigned long)bh); |
2499 | } | 2500 | } |
2500 | 2501 | ||
2501 | /** | 2502 | struct usb_hcd *__usb_create_hcd(const struct hc_driver *driver, |
2502 | * usb_create_shared_hcd - create and initialize an HCD structure | 2503 | struct device *sysdev, struct device *dev, const char *bus_name, |
2503 | * @driver: HC driver that will use this hcd | ||
2504 | * @dev: device for this HC, stored in hcd->self.controller | ||
2505 | * @bus_name: value to store in hcd->self.bus_name | ||
2506 | * @primary_hcd: a pointer to the usb_hcd structure that is sharing the | ||
2507 | * PCI device. Only allocate certain resources for the primary HCD | ||
2508 | * Context: !in_interrupt() | ||
2509 | * | ||
2510 | * Allocate a struct usb_hcd, with extra space at the end for the | ||
2511 | * HC driver's private data. Initialize the generic members of the | ||
2512 | * hcd structure. | ||
2513 | * | ||
2514 | * Return: On success, a pointer to the created and initialized HCD structure. | ||
2515 | * On failure (e.g. if memory is unavailable), %NULL. | ||
2516 | */ | ||
2517 | struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver, | ||
2518 | struct device *dev, const char *bus_name, | ||
2519 | struct usb_hcd *primary_hcd) | 2504 | struct usb_hcd *primary_hcd) |
2520 | { | 2505 | { |
2521 | struct usb_hcd *hcd; | 2506 | struct usb_hcd *hcd; |
@@ -2556,8 +2541,9 @@ struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver, | |||
2556 | 2541 | ||
2557 | usb_bus_init(&hcd->self); | 2542 | usb_bus_init(&hcd->self); |
2558 | hcd->self.controller = dev; | 2543 | hcd->self.controller = dev; |
2544 | hcd->self.sysdev = sysdev; | ||
2559 | hcd->self.bus_name = bus_name; | 2545 | hcd->self.bus_name = bus_name; |
2560 | hcd->self.uses_dma = (dev->dma_mask != NULL); | 2546 | hcd->self.uses_dma = (sysdev->dma_mask != NULL); |
2561 | 2547 | ||
2562 | init_timer(&hcd->rh_timer); | 2548 | init_timer(&hcd->rh_timer); |
2563 | hcd->rh_timer.function = rh_timer_func; | 2549 | hcd->rh_timer.function = rh_timer_func; |
@@ -2572,6 +2558,30 @@ struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver, | |||
2572 | "USB Host Controller"; | 2558 | "USB Host Controller"; |
2573 | return hcd; | 2559 | return hcd; |
2574 | } | 2560 | } |
2561 | EXPORT_SYMBOL_GPL(__usb_create_hcd); | ||
2562 | |||
2563 | /** | ||
2564 | * usb_create_shared_hcd - create and initialize an HCD structure | ||
2565 | * @driver: HC driver that will use this hcd | ||
2566 | * @dev: device for this HC, stored in hcd->self.controller | ||
2567 | * @bus_name: value to store in hcd->self.bus_name | ||
2568 | * @primary_hcd: a pointer to the usb_hcd structure that is sharing the | ||
2569 | * PCI device. Only allocate certain resources for the primary HCD | ||
2570 | * Context: !in_interrupt() | ||
2571 | * | ||
2572 | * Allocate a struct usb_hcd, with extra space at the end for the | ||
2573 | * HC driver's private data. Initialize the generic members of the | ||
2574 | * hcd structure. | ||
2575 | * | ||
2576 | * Return: On success, a pointer to the created and initialized HCD structure. | ||
2577 | * On failure (e.g. if memory is unavailable), %NULL. | ||
2578 | */ | ||
2579 | struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver, | ||
2580 | struct device *dev, const char *bus_name, | ||
2581 | struct usb_hcd *primary_hcd) | ||
2582 | { | ||
2583 | return __usb_create_hcd(driver, dev, dev, bus_name, primary_hcd); | ||
2584 | } | ||
2575 | EXPORT_SYMBOL_GPL(usb_create_shared_hcd); | 2585 | EXPORT_SYMBOL_GPL(usb_create_shared_hcd); |
2576 | 2586 | ||
2577 | /** | 2587 | /** |
@@ -2591,7 +2601,7 @@ EXPORT_SYMBOL_GPL(usb_create_shared_hcd); | |||
2591 | struct usb_hcd *usb_create_hcd(const struct hc_driver *driver, | 2601 | struct usb_hcd *usb_create_hcd(const struct hc_driver *driver, |
2592 | struct device *dev, const char *bus_name) | 2602 | struct device *dev, const char *bus_name) |
2593 | { | 2603 | { |
2594 | return usb_create_shared_hcd(driver, dev, bus_name, NULL); | 2604 | return __usb_create_hcd(driver, dev, dev, bus_name, NULL); |
2595 | } | 2605 | } |
2596 | EXPORT_SYMBOL_GPL(usb_create_hcd); | 2606 | EXPORT_SYMBOL_GPL(usb_create_hcd); |
2597 | 2607 | ||
@@ -2718,7 +2728,7 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
2718 | struct usb_device *rhdev; | 2728 | struct usb_device *rhdev; |
2719 | 2729 | ||
2720 | if (IS_ENABLED(CONFIG_USB_PHY) && !hcd->usb_phy) { | 2730 | if (IS_ENABLED(CONFIG_USB_PHY) && !hcd->usb_phy) { |
2721 | struct usb_phy *phy = usb_get_phy_dev(hcd->self.controller, 0); | 2731 | struct usb_phy *phy = usb_get_phy_dev(hcd->self.sysdev, 0); |
2722 | 2732 | ||
2723 | if (IS_ERR(phy)) { | 2733 | if (IS_ERR(phy)) { |
2724 | retval = PTR_ERR(phy); | 2734 | retval = PTR_ERR(phy); |
@@ -2736,7 +2746,7 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
2736 | } | 2746 | } |
2737 | 2747 | ||
2738 | if (IS_ENABLED(CONFIG_GENERIC_PHY) && !hcd->phy) { | 2748 | if (IS_ENABLED(CONFIG_GENERIC_PHY) && !hcd->phy) { |
2739 | struct phy *phy = phy_get(hcd->self.controller, "usb"); | 2749 | struct phy *phy = phy_get(hcd->self.sysdev, "usb"); |
2740 | 2750 | ||
2741 | if (IS_ERR(phy)) { | 2751 | if (IS_ERR(phy)) { |
2742 | retval = PTR_ERR(phy); | 2752 | retval = PTR_ERR(phy); |
@@ -2784,7 +2794,7 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
2784 | */ | 2794 | */ |
2785 | retval = hcd_buffer_create(hcd); | 2795 | retval = hcd_buffer_create(hcd); |
2786 | if (retval != 0) { | 2796 | if (retval != 0) { |
2787 | dev_dbg(hcd->self.controller, "pool alloc failed\n"); | 2797 | dev_dbg(hcd->self.sysdev, "pool alloc failed\n"); |
2788 | goto err_create_buf; | 2798 | goto err_create_buf; |
2789 | } | 2799 | } |
2790 | 2800 | ||
@@ -2794,7 +2804,7 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
2794 | 2804 | ||
2795 | rhdev = usb_alloc_dev(NULL, &hcd->self, 0); | 2805 | rhdev = usb_alloc_dev(NULL, &hcd->self, 0); |
2796 | if (rhdev == NULL) { | 2806 | if (rhdev == NULL) { |
2797 | dev_err(hcd->self.controller, "unable to allocate root hub\n"); | 2807 | dev_err(hcd->self.sysdev, "unable to allocate root hub\n"); |
2798 | retval = -ENOMEM; | 2808 | retval = -ENOMEM; |
2799 | goto err_allocate_root_hub; | 2809 | goto err_allocate_root_hub; |
2800 | } | 2810 | } |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 5286bf67869a..9dca59ef18b3 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -1066,6 +1066,9 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) | |||
1066 | 1066 | ||
1067 | portstatus = portchange = 0; | 1067 | portstatus = portchange = 0; |
1068 | status = hub_port_status(hub, port1, &portstatus, &portchange); | 1068 | status = hub_port_status(hub, port1, &portstatus, &portchange); |
1069 | if (status) | ||
1070 | goto abort; | ||
1071 | |||
1069 | if (udev || (portstatus & USB_PORT_STAT_CONNECTION)) | 1072 | if (udev || (portstatus & USB_PORT_STAT_CONNECTION)) |
1070 | dev_dbg(&port_dev->dev, "status %04x change %04x\n", | 1073 | dev_dbg(&port_dev->dev, "status %04x change %04x\n", |
1071 | portstatus, portchange); | 1074 | portstatus, portchange); |
@@ -1198,7 +1201,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) | |||
1198 | 1201 | ||
1199 | /* Scan all ports that need attention */ | 1202 | /* Scan all ports that need attention */ |
1200 | kick_hub_wq(hub); | 1203 | kick_hub_wq(hub); |
1201 | 1204 | abort: | |
1202 | if (type == HUB_INIT2 || type == HUB_INIT3) { | 1205 | if (type == HUB_INIT2 || type == HUB_INIT3) { |
1203 | /* Allow autosuspend if it was suppressed */ | 1206 | /* Allow autosuspend if it was suppressed */ |
1204 | disconnected: | 1207 | disconnected: |
@@ -2084,6 +2087,12 @@ void usb_disconnect(struct usb_device **pdev) | |||
2084 | dev_info(&udev->dev, "USB disconnect, device number %d\n", | 2087 | dev_info(&udev->dev, "USB disconnect, device number %d\n", |
2085 | udev->devnum); | 2088 | udev->devnum); |
2086 | 2089 | ||
2090 | /* | ||
2091 | * Ensure that the pm runtime code knows that the USB device | ||
2092 | * is in the process of being disconnected. | ||
2093 | */ | ||
2094 | pm_runtime_barrier(&udev->dev); | ||
2095 | |||
2087 | usb_lock_device(udev); | 2096 | usb_lock_device(udev); |
2088 | 2097 | ||
2089 | hub_disconnect_children(udev); | 2098 | hub_disconnect_children(udev); |
diff --git a/drivers/usb/core/of.c b/drivers/usb/core/of.c index 3de4f8873984..d787f195a9a6 100644 --- a/drivers/usb/core/of.c +++ b/drivers/usb/core/of.c | |||
@@ -18,6 +18,7 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/of.h> | 20 | #include <linux/of.h> |
21 | #include <linux/of_platform.h> | ||
21 | #include <linux/usb/of.h> | 22 | #include <linux/usb/of.h> |
22 | 23 | ||
23 | /** | 24 | /** |
@@ -46,3 +47,25 @@ struct device_node *usb_of_get_child_node(struct device_node *parent, | |||
46 | } | 47 | } |
47 | EXPORT_SYMBOL_GPL(usb_of_get_child_node); | 48 | EXPORT_SYMBOL_GPL(usb_of_get_child_node); |
48 | 49 | ||
50 | /** | ||
51 | * usb_of_get_companion_dev - Find the companion device | ||
52 | * @dev: the device pointer to find a companion | ||
53 | * | ||
54 | * Find the companion device from platform bus. | ||
55 | * | ||
56 | * Return: On success, a pointer to the companion device, %NULL on failure. | ||
57 | */ | ||
58 | struct device *usb_of_get_companion_dev(struct device *dev) | ||
59 | { | ||
60 | struct device_node *node; | ||
61 | struct platform_device *pdev = NULL; | ||
62 | |||
63 | node = of_parse_phandle(dev->of_node, "companion", 0); | ||
64 | if (node) | ||
65 | pdev = of_find_device_by_node(node); | ||
66 | |||
67 | of_node_put(node); | ||
68 | |||
69 | return pdev ? &pdev->dev : NULL; | ||
70 | } | ||
71 | EXPORT_SYMBOL_GPL(usb_of_get_companion_dev); | ||
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index a2ccc69fb45c..28b053cacc90 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c | |||
@@ -74,6 +74,140 @@ MODULE_PARM_DESC(autosuspend, "default autosuspend delay"); | |||
74 | #define usb_autosuspend_delay 0 | 74 | #define usb_autosuspend_delay 0 |
75 | #endif | 75 | #endif |
76 | 76 | ||
77 | static bool match_endpoint(struct usb_endpoint_descriptor *epd, | ||
78 | struct usb_endpoint_descriptor **bulk_in, | ||
79 | struct usb_endpoint_descriptor **bulk_out, | ||
80 | struct usb_endpoint_descriptor **int_in, | ||
81 | struct usb_endpoint_descriptor **int_out) | ||
82 | { | ||
83 | switch (usb_endpoint_type(epd)) { | ||
84 | case USB_ENDPOINT_XFER_BULK: | ||
85 | if (usb_endpoint_dir_in(epd)) { | ||
86 | if (bulk_in && !*bulk_in) { | ||
87 | *bulk_in = epd; | ||
88 | break; | ||
89 | } | ||
90 | } else { | ||
91 | if (bulk_out && !*bulk_out) { | ||
92 | *bulk_out = epd; | ||
93 | break; | ||
94 | } | ||
95 | } | ||
96 | |||
97 | return false; | ||
98 | case USB_ENDPOINT_XFER_INT: | ||
99 | if (usb_endpoint_dir_in(epd)) { | ||
100 | if (int_in && !*int_in) { | ||
101 | *int_in = epd; | ||
102 | break; | ||
103 | } | ||
104 | } else { | ||
105 | if (int_out && !*int_out) { | ||
106 | *int_out = epd; | ||
107 | break; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | return false; | ||
112 | default: | ||
113 | return false; | ||
114 | } | ||
115 | |||
116 | return (!bulk_in || *bulk_in) && (!bulk_out || *bulk_out) && | ||
117 | (!int_in || *int_in) && (!int_out || *int_out); | ||
118 | } | ||
119 | |||
120 | /** | ||
121 | * usb_find_common_endpoints() -- look up common endpoint descriptors | ||
122 | * @alt: alternate setting to search | ||
123 | * @bulk_in: pointer to descriptor pointer, or NULL | ||
124 | * @bulk_out: pointer to descriptor pointer, or NULL | ||
125 | * @int_in: pointer to descriptor pointer, or NULL | ||
126 | * @int_out: pointer to descriptor pointer, or NULL | ||
127 | * | ||
128 | * Search the alternate setting's endpoint descriptors for the first bulk-in, | ||
129 | * bulk-out, interrupt-in and interrupt-out endpoints and return them in the | ||
130 | * provided pointers (unless they are NULL). | ||
131 | * | ||
132 | * If a requested endpoint is not found, the corresponding pointer is set to | ||
133 | * NULL. | ||
134 | * | ||
135 | * Return: Zero if all requested descriptors were found, or -ENXIO otherwise. | ||
136 | */ | ||
137 | int usb_find_common_endpoints(struct usb_host_interface *alt, | ||
138 | struct usb_endpoint_descriptor **bulk_in, | ||
139 | struct usb_endpoint_descriptor **bulk_out, | ||
140 | struct usb_endpoint_descriptor **int_in, | ||
141 | struct usb_endpoint_descriptor **int_out) | ||
142 | { | ||
143 | struct usb_endpoint_descriptor *epd; | ||
144 | int i; | ||
145 | |||
146 | if (bulk_in) | ||
147 | *bulk_in = NULL; | ||
148 | if (bulk_out) | ||
149 | *bulk_out = NULL; | ||
150 | if (int_in) | ||
151 | *int_in = NULL; | ||
152 | if (int_out) | ||
153 | *int_out = NULL; | ||
154 | |||
155 | for (i = 0; i < alt->desc.bNumEndpoints; ++i) { | ||
156 | epd = &alt->endpoint[i].desc; | ||
157 | |||
158 | if (match_endpoint(epd, bulk_in, bulk_out, int_in, int_out)) | ||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | return -ENXIO; | ||
163 | } | ||
164 | EXPORT_SYMBOL_GPL(usb_find_common_endpoints); | ||
165 | |||
166 | /** | ||
167 | * usb_find_common_endpoints_reverse() -- look up common endpoint descriptors | ||
168 | * @alt: alternate setting to search | ||
169 | * @bulk_in: pointer to descriptor pointer, or NULL | ||
170 | * @bulk_out: pointer to descriptor pointer, or NULL | ||
171 | * @int_in: pointer to descriptor pointer, or NULL | ||
172 | * @int_out: pointer to descriptor pointer, or NULL | ||
173 | * | ||
174 | * Search the alternate setting's endpoint descriptors for the last bulk-in, | ||
175 | * bulk-out, interrupt-in and interrupt-out endpoints and return them in the | ||
176 | * provided pointers (unless they are NULL). | ||
177 | * | ||
178 | * If a requested endpoint is not found, the corresponding pointer is set to | ||
179 | * NULL. | ||
180 | * | ||
181 | * Return: Zero if all requested descriptors were found, or -ENXIO otherwise. | ||
182 | */ | ||
183 | int usb_find_common_endpoints_reverse(struct usb_host_interface *alt, | ||
184 | struct usb_endpoint_descriptor **bulk_in, | ||
185 | struct usb_endpoint_descriptor **bulk_out, | ||
186 | struct usb_endpoint_descriptor **int_in, | ||
187 | struct usb_endpoint_descriptor **int_out) | ||
188 | { | ||
189 | struct usb_endpoint_descriptor *epd; | ||
190 | int i; | ||
191 | |||
192 | if (bulk_in) | ||
193 | *bulk_in = NULL; | ||
194 | if (bulk_out) | ||
195 | *bulk_out = NULL; | ||
196 | if (int_in) | ||
197 | *int_in = NULL; | ||
198 | if (int_out) | ||
199 | *int_out = NULL; | ||
200 | |||
201 | for (i = alt->desc.bNumEndpoints - 1; i >= 0; --i) { | ||
202 | epd = &alt->endpoint[i].desc; | ||
203 | |||
204 | if (match_endpoint(epd, bulk_in, bulk_out, int_in, int_out)) | ||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | return -ENXIO; | ||
209 | } | ||
210 | EXPORT_SYMBOL_GPL(usb_find_common_endpoints_reverse); | ||
77 | 211 | ||
78 | /** | 212 | /** |
79 | * usb_find_alt_setting() - Given a configuration, find the alternate setting | 213 | * usb_find_alt_setting() - Given a configuration, find the alternate setting |
@@ -453,9 +587,9 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, | |||
453 | * Note: calling dma_set_mask() on a USB device would set the | 587 | * Note: calling dma_set_mask() on a USB device would set the |
454 | * mask for the entire HCD, so don't do that. | 588 | * mask for the entire HCD, so don't do that. |
455 | */ | 589 | */ |
456 | dev->dev.dma_mask = bus->controller->dma_mask; | 590 | dev->dev.dma_mask = bus->sysdev->dma_mask; |
457 | dev->dev.dma_pfn_offset = bus->controller->dma_pfn_offset; | 591 | dev->dev.dma_pfn_offset = bus->sysdev->dma_pfn_offset; |
458 | set_dev_node(&dev->dev, dev_to_node(bus->controller)); | 592 | set_dev_node(&dev->dev, dev_to_node(bus->sysdev)); |
459 | dev->state = USB_STATE_ATTACHED; | 593 | dev->state = USB_STATE_ATTACHED; |
460 | dev->lpm_disable_count = 1; | 594 | dev->lpm_disable_count = 1; |
461 | atomic_set(&dev->urbnum, 0); | 595 | atomic_set(&dev->urbnum, 0); |
@@ -803,7 +937,7 @@ struct urb *usb_buffer_map(struct urb *urb) | |||
803 | if (!urb | 937 | if (!urb |
804 | || !urb->dev | 938 | || !urb->dev |
805 | || !(bus = urb->dev->bus) | 939 | || !(bus = urb->dev->bus) |
806 | || !(controller = bus->controller)) | 940 | || !(controller = bus->sysdev)) |
807 | return NULL; | 941 | return NULL; |
808 | 942 | ||
809 | if (controller->dma_mask) { | 943 | if (controller->dma_mask) { |
@@ -841,7 +975,7 @@ void usb_buffer_dmasync(struct urb *urb) | |||
841 | || !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) | 975 | || !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) |
842 | || !urb->dev | 976 | || !urb->dev |
843 | || !(bus = urb->dev->bus) | 977 | || !(bus = urb->dev->bus) |
844 | || !(controller = bus->controller)) | 978 | || !(controller = bus->sysdev)) |
845 | return; | 979 | return; |
846 | 980 | ||
847 | if (controller->dma_mask) { | 981 | if (controller->dma_mask) { |
@@ -875,7 +1009,7 @@ void usb_buffer_unmap(struct urb *urb) | |||
875 | || !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) | 1009 | || !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) |
876 | || !urb->dev | 1010 | || !urb->dev |
877 | || !(bus = urb->dev->bus) | 1011 | || !(bus = urb->dev->bus) |
878 | || !(controller = bus->controller)) | 1012 | || !(controller = bus->sysdev)) |
879 | return; | 1013 | return; |
880 | 1014 | ||
881 | if (controller->dma_mask) { | 1015 | if (controller->dma_mask) { |
@@ -925,7 +1059,7 @@ int usb_buffer_map_sg(const struct usb_device *dev, int is_in, | |||
925 | 1059 | ||
926 | if (!dev | 1060 | if (!dev |
927 | || !(bus = dev->bus) | 1061 | || !(bus = dev->bus) |
928 | || !(controller = bus->controller) | 1062 | || !(controller = bus->sysdev) |
929 | || !controller->dma_mask) | 1063 | || !controller->dma_mask) |
930 | return -EINVAL; | 1064 | return -EINVAL; |
931 | 1065 | ||
@@ -961,7 +1095,7 @@ void usb_buffer_dmasync_sg(const struct usb_device *dev, int is_in, | |||
961 | 1095 | ||
962 | if (!dev | 1096 | if (!dev |
963 | || !(bus = dev->bus) | 1097 | || !(bus = dev->bus) |
964 | || !(controller = bus->controller) | 1098 | || !(controller = bus->sysdev) |
965 | || !controller->dma_mask) | 1099 | || !controller->dma_mask) |
966 | return; | 1100 | return; |
967 | 1101 | ||
@@ -989,7 +1123,7 @@ void usb_buffer_unmap_sg(const struct usb_device *dev, int is_in, | |||
989 | 1123 | ||
990 | if (!dev | 1124 | if (!dev |
991 | || !(bus = dev->bus) | 1125 | || !(bus = dev->bus) |
992 | || !(controller = bus->controller) | 1126 | || !(controller = bus->sysdev) |
993 | || !controller->dma_mask) | 1127 | || !controller->dma_mask) |
994 | return; | 1128 | return; |
995 | 1129 | ||
diff --git a/drivers/usb/dwc2/Kconfig b/drivers/usb/dwc2/Kconfig index e838701d6dd5..b6a495e98fd8 100644 --- a/drivers/usb/dwc2/Kconfig +++ b/drivers/usb/dwc2/Kconfig | |||
@@ -54,7 +54,7 @@ endchoice | |||
54 | 54 | ||
55 | config USB_DWC2_PCI | 55 | config USB_DWC2_PCI |
56 | tristate "DWC2 PCI" | 56 | tristate "DWC2 PCI" |
57 | depends on PCI | 57 | depends on USB_PCI |
58 | depends on USB_GADGET || !USB_GADGET | 58 | depends on USB_GADGET || !USB_GADGET |
59 | default n | 59 | default n |
60 | select NOP_USB_XCEIV | 60 | select NOP_USB_XCEIV |
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index 1a7e83005082..8367d4f985c1 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h | |||
@@ -423,6 +423,10 @@ enum dwc2_ep0_state { | |||
423 | * needed. | 423 | * needed. |
424 | * 0 - No (default) | 424 | * 0 - No (default) |
425 | * 1 - Yes | 425 | * 1 - Yes |
426 | * @activate_stm_fs_transceiver: Activate internal transceiver using GGPIO | ||
427 | * register. | ||
428 | * 0 - Deactivate the transceiver (default) | ||
429 | * 1 - Activate the transceiver | ||
426 | * @g_dma: Enables gadget dma usage (default: autodetect). | 430 | * @g_dma: Enables gadget dma usage (default: autodetect). |
427 | * @g_dma_desc: Enables gadget descriptor DMA (default: autodetect). | 431 | * @g_dma_desc: Enables gadget descriptor DMA (default: autodetect). |
428 | * @g_rx_fifo_size: The periodic rx fifo size for the device, in | 432 | * @g_rx_fifo_size: The periodic rx fifo size for the device, in |
@@ -477,6 +481,7 @@ struct dwc2_core_params { | |||
477 | bool uframe_sched; | 481 | bool uframe_sched; |
478 | bool external_id_pin_ctl; | 482 | bool external_id_pin_ctl; |
479 | bool hibernation; | 483 | bool hibernation; |
484 | bool activate_stm_fs_transceiver; | ||
480 | u16 max_packet_count; | 485 | u16 max_packet_count; |
481 | u32 max_transfer_size; | 486 | u32 max_transfer_size; |
482 | u32 ahbcfg; | 487 | u32 ahbcfg; |
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index a73722e27d07..740c7e86d31b 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c | |||
@@ -121,7 +121,7 @@ static void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg) | |||
121 | 121 | ||
122 | static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) | 122 | static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) |
123 | { | 123 | { |
124 | u32 usbcfg, i2cctl; | 124 | u32 usbcfg, ggpio, i2cctl; |
125 | int retval = 0; | 125 | int retval = 0; |
126 | 126 | ||
127 | /* | 127 | /* |
@@ -145,6 +145,19 @@ static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) | |||
145 | return retval; | 145 | return retval; |
146 | } | 146 | } |
147 | } | 147 | } |
148 | |||
149 | if (hsotg->params.activate_stm_fs_transceiver) { | ||
150 | ggpio = dwc2_readl(hsotg->regs + GGPIO); | ||
151 | if (!(ggpio & GGPIO_STM32_OTG_GCCFG_PWRDWN)) { | ||
152 | dev_dbg(hsotg->dev, "Activating transceiver\n"); | ||
153 | /* | ||
154 | * STM32F4x9 uses the GGPIO register as general | ||
155 | * core configuration register. | ||
156 | */ | ||
157 | ggpio |= GGPIO_STM32_OTG_GCCFG_PWRDWN; | ||
158 | dwc2_writel(ggpio, hsotg->regs + GGPIO); | ||
159 | } | ||
160 | } | ||
148 | } | 161 | } |
149 | 162 | ||
150 | /* | 163 | /* |
@@ -3264,6 +3277,7 @@ static void dwc2_conn_id_status_change(struct work_struct *work) | |||
3264 | dwc2_core_init(hsotg, false); | 3277 | dwc2_core_init(hsotg, false); |
3265 | dwc2_enable_global_interrupts(hsotg); | 3278 | dwc2_enable_global_interrupts(hsotg); |
3266 | spin_lock_irqsave(&hsotg->lock, flags); | 3279 | spin_lock_irqsave(&hsotg->lock, flags); |
3280 | dwc2_hsotg_disconnect(hsotg); | ||
3267 | dwc2_hsotg_core_init_disconnected(hsotg, false); | 3281 | dwc2_hsotg_core_init_disconnected(hsotg, false); |
3268 | spin_unlock_irqrestore(&hsotg->lock, flags); | 3282 | spin_unlock_irqrestore(&hsotg->lock, flags); |
3269 | dwc2_hsotg_core_connect(hsotg); | 3283 | dwc2_hsotg_core_connect(hsotg); |
diff --git a/drivers/usb/dwc2/hw.h b/drivers/usb/dwc2/hw.h index bde72489ae66..4592012c4743 100644 --- a/drivers/usb/dwc2/hw.h +++ b/drivers/usb/dwc2/hw.h | |||
@@ -225,6 +225,8 @@ | |||
225 | 225 | ||
226 | #define GPVNDCTL HSOTG_REG(0x0034) | 226 | #define GPVNDCTL HSOTG_REG(0x0034) |
227 | #define GGPIO HSOTG_REG(0x0038) | 227 | #define GGPIO HSOTG_REG(0x0038) |
228 | #define GGPIO_STM32_OTG_GCCFG_PWRDWN BIT(16) | ||
229 | |||
228 | #define GUID HSOTG_REG(0x003c) | 230 | #define GUID HSOTG_REG(0x003c) |
229 | #define GSNPSID HSOTG_REG(0x0040) | 231 | #define GSNPSID HSOTG_REG(0x0040) |
230 | #define GHWCFG1 HSOTG_REG(0x0044) | 232 | #define GHWCFG1 HSOTG_REG(0x0044) |
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index 2990c347289f..9cd8722f24f6 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c | |||
@@ -120,6 +120,22 @@ static void dwc2_set_amcc_params(struct dwc2_hsotg *hsotg) | |||
120 | p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 << GAHBCFG_HBSTLEN_SHIFT; | 120 | p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 << GAHBCFG_HBSTLEN_SHIFT; |
121 | } | 121 | } |
122 | 122 | ||
123 | static void dwc2_set_stm32f4x9_fsotg_params(struct dwc2_hsotg *hsotg) | ||
124 | { | ||
125 | struct dwc2_core_params *p = &hsotg->params; | ||
126 | |||
127 | p->otg_cap = DWC2_CAP_PARAM_NO_HNP_SRP_CAPABLE; | ||
128 | p->speed = DWC2_SPEED_PARAM_FULL; | ||
129 | p->host_rx_fifo_size = 128; | ||
130 | p->host_nperio_tx_fifo_size = 96; | ||
131 | p->host_perio_tx_fifo_size = 96; | ||
132 | p->max_packet_count = 256; | ||
133 | p->phy_type = DWC2_PHY_TYPE_PARAM_FS; | ||
134 | p->i2c_enable = false; | ||
135 | p->uframe_sched = false; | ||
136 | p->activate_stm_fs_transceiver = true; | ||
137 | } | ||
138 | |||
123 | const struct of_device_id dwc2_of_match_table[] = { | 139 | const struct of_device_id dwc2_of_match_table[] = { |
124 | { .compatible = "brcm,bcm2835-usb", .data = dwc2_set_bcm_params }, | 140 | { .compatible = "brcm,bcm2835-usb", .data = dwc2_set_bcm_params }, |
125 | { .compatible = "hisilicon,hi6220-usb", .data = dwc2_set_his_params }, | 141 | { .compatible = "hisilicon,hi6220-usb", .data = dwc2_set_his_params }, |
@@ -133,6 +149,9 @@ const struct of_device_id dwc2_of_match_table[] = { | |||
133 | { .compatible = "amlogic,meson-gxbb-usb", | 149 | { .compatible = "amlogic,meson-gxbb-usb", |
134 | .data = dwc2_set_amlogic_params }, | 150 | .data = dwc2_set_amlogic_params }, |
135 | { .compatible = "amcc,dwc-otg", .data = dwc2_set_amcc_params }, | 151 | { .compatible = "amcc,dwc-otg", .data = dwc2_set_amcc_params }, |
152 | { .compatible = "st,stm32f4x9-fsotg", | ||
153 | .data = dwc2_set_stm32f4x9_fsotg_params }, | ||
154 | { .compatible = "st,stm32f4x9-hsotg" }, | ||
136 | {}, | 155 | {}, |
137 | }; | 156 | }; |
138 | MODULE_DEVICE_TABLE(of, dwc2_of_match_table); | 157 | MODULE_DEVICE_TABLE(of, dwc2_of_match_table); |
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 9564bc76c56f..daf0d37acb37 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c | |||
@@ -214,20 +214,11 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) | |||
214 | hsotg->reset = devm_reset_control_get_optional(hsotg->dev, "dwc2"); | 214 | hsotg->reset = devm_reset_control_get_optional(hsotg->dev, "dwc2"); |
215 | if (IS_ERR(hsotg->reset)) { | 215 | if (IS_ERR(hsotg->reset)) { |
216 | ret = PTR_ERR(hsotg->reset); | 216 | ret = PTR_ERR(hsotg->reset); |
217 | switch (ret) { | 217 | dev_err(hsotg->dev, "error getting reset control %d\n", ret); |
218 | case -ENOENT: | 218 | return ret; |
219 | case -ENOTSUPP: | ||
220 | hsotg->reset = NULL; | ||
221 | break; | ||
222 | default: | ||
223 | dev_err(hsotg->dev, "error getting reset control %d\n", | ||
224 | ret); | ||
225 | return ret; | ||
226 | } | ||
227 | } | 219 | } |
228 | 220 | ||
229 | if (hsotg->reset) | 221 | reset_control_deassert(hsotg->reset); |
230 | reset_control_deassert(hsotg->reset); | ||
231 | 222 | ||
232 | /* Set default UTMI width */ | 223 | /* Set default UTMI width */ |
233 | hsotg->phyif = GUSBCFG_PHYIF16; | 224 | hsotg->phyif = GUSBCFG_PHYIF16; |
@@ -326,8 +317,7 @@ static int dwc2_driver_remove(struct platform_device *dev) | |||
326 | if (hsotg->ll_hw_enabled) | 317 | if (hsotg->ll_hw_enabled) |
327 | dwc2_lowlevel_hw_disable(hsotg); | 318 | dwc2_lowlevel_hw_disable(hsotg); |
328 | 319 | ||
329 | if (hsotg->reset) | 320 | reset_control_assert(hsotg->reset); |
330 | reset_control_assert(hsotg->reset); | ||
331 | 321 | ||
332 | return 0; | 322 | return 0; |
333 | } | 323 | } |
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index c5aa235863e8..ab8c0e0d3b60 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig | |||
@@ -41,6 +41,7 @@ config USB_DWC3_GADGET | |||
41 | config USB_DWC3_DUAL_ROLE | 41 | config USB_DWC3_DUAL_ROLE |
42 | bool "Dual Role mode" | 42 | bool "Dual Role mode" |
43 | depends on ((USB=y || USB=USB_DWC3) && (USB_GADGET=y || USB_GADGET=USB_DWC3)) | 43 | depends on ((USB=y || USB=USB_DWC3) && (USB_GADGET=y || USB_GADGET=USB_DWC3)) |
44 | depends on (EXTCON=y || EXTCON=USB_DWC3) | ||
44 | help | 45 | help |
45 | This is the default mode of working of DWC3 controller where | 46 | This is the default mode of working of DWC3 controller where |
46 | both host and gadget features are enabled. | 47 | both host and gadget features are enabled. |
@@ -70,7 +71,7 @@ config USB_DWC3_EXYNOS | |||
70 | 71 | ||
71 | config USB_DWC3_PCI | 72 | config USB_DWC3_PCI |
72 | tristate "PCIe-based Platforms" | 73 | tristate "PCIe-based Platforms" |
73 | depends on PCI && ACPI | 74 | depends on USB_PCI && ACPI |
74 | default USB_DWC3 | 75 | default USB_DWC3 |
75 | help | 76 | help |
76 | If you're using the DesignWare Core IP with a PCIe, please say | 77 | If you're using the DesignWare Core IP with a PCIe, please say |
diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index ffca34029b21..f15fabbd1e59 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile | |||
@@ -17,6 +17,10 @@ ifneq ($(filter y,$(CONFIG_USB_DWC3_GADGET) $(CONFIG_USB_DWC3_DUAL_ROLE)),) | |||
17 | dwc3-y += gadget.o ep0.o | 17 | dwc3-y += gadget.o ep0.o |
18 | endif | 18 | endif |
19 | 19 | ||
20 | ifneq ($(CONFIG_USB_DWC3_DUAL_ROLE),) | ||
21 | dwc3-y += drd.o | ||
22 | endif | ||
23 | |||
20 | ifneq ($(CONFIG_USB_DWC3_ULPI),) | 24 | ifneq ($(CONFIG_USB_DWC3_ULPI),) |
21 | dwc3-y += ulpi.o | 25 | dwc3-y += ulpi.o |
22 | endif | 26 | endif |
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 369bab16a824..455d89a1cd6d 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c | |||
@@ -100,7 +100,10 @@ static int dwc3_get_dr_mode(struct dwc3 *dwc) | |||
100 | return 0; | 100 | return 0; |
101 | } | 101 | } |
102 | 102 | ||
103 | void dwc3_set_mode(struct dwc3 *dwc, u32 mode) | 103 | static void dwc3_event_buffers_cleanup(struct dwc3 *dwc); |
104 | static int dwc3_event_buffers_setup(struct dwc3 *dwc); | ||
105 | |||
106 | static void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode) | ||
104 | { | 107 | { |
105 | u32 reg; | 108 | u32 reg; |
106 | 109 | ||
@@ -110,6 +113,69 @@ void dwc3_set_mode(struct dwc3 *dwc, u32 mode) | |||
110 | dwc3_writel(dwc->regs, DWC3_GCTL, reg); | 113 | dwc3_writel(dwc->regs, DWC3_GCTL, reg); |
111 | } | 114 | } |
112 | 115 | ||
116 | static void __dwc3_set_mode(struct work_struct *work) | ||
117 | { | ||
118 | struct dwc3 *dwc = work_to_dwc(work); | ||
119 | unsigned long flags; | ||
120 | int ret; | ||
121 | |||
122 | if (!dwc->desired_dr_role) | ||
123 | return; | ||
124 | |||
125 | if (dwc->desired_dr_role == dwc->current_dr_role) | ||
126 | return; | ||
127 | |||
128 | if (dwc->dr_mode != USB_DR_MODE_OTG) | ||
129 | return; | ||
130 | |||
131 | switch (dwc->current_dr_role) { | ||
132 | case DWC3_GCTL_PRTCAP_HOST: | ||
133 | dwc3_host_exit(dwc); | ||
134 | break; | ||
135 | case DWC3_GCTL_PRTCAP_DEVICE: | ||
136 | dwc3_gadget_exit(dwc); | ||
137 | dwc3_event_buffers_cleanup(dwc); | ||
138 | break; | ||
139 | default: | ||
140 | break; | ||
141 | } | ||
142 | |||
143 | spin_lock_irqsave(&dwc->lock, flags); | ||
144 | |||
145 | dwc3_set_prtcap(dwc, dwc->desired_dr_role); | ||
146 | |||
147 | dwc->current_dr_role = dwc->desired_dr_role; | ||
148 | |||
149 | spin_unlock_irqrestore(&dwc->lock, flags); | ||
150 | |||
151 | switch (dwc->desired_dr_role) { | ||
152 | case DWC3_GCTL_PRTCAP_HOST: | ||
153 | ret = dwc3_host_init(dwc); | ||
154 | if (ret) | ||
155 | dev_err(dwc->dev, "failed to initialize host\n"); | ||
156 | break; | ||
157 | case DWC3_GCTL_PRTCAP_DEVICE: | ||
158 | dwc3_event_buffers_setup(dwc); | ||
159 | ret = dwc3_gadget_init(dwc); | ||
160 | if (ret) | ||
161 | dev_err(dwc->dev, "failed to initialize peripheral\n"); | ||
162 | break; | ||
163 | default: | ||
164 | break; | ||
165 | } | ||
166 | } | ||
167 | |||
168 | void dwc3_set_mode(struct dwc3 *dwc, u32 mode) | ||
169 | { | ||
170 | unsigned long flags; | ||
171 | |||
172 | spin_lock_irqsave(&dwc->lock, flags); | ||
173 | dwc->desired_dr_role = mode; | ||
174 | spin_unlock_irqrestore(&dwc->lock, flags); | ||
175 | |||
176 | queue_work(system_power_efficient_wq, &dwc->drd_work); | ||
177 | } | ||
178 | |||
113 | u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type) | 179 | u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type) |
114 | { | 180 | { |
115 | struct dwc3 *dwc = dep->dwc; | 181 | struct dwc3 *dwc = dep->dwc; |
@@ -397,8 +463,7 @@ static void dwc3_core_num_eps(struct dwc3 *dwc) | |||
397 | { | 463 | { |
398 | struct dwc3_hwparams *parms = &dwc->hwparams; | 464 | struct dwc3_hwparams *parms = &dwc->hwparams; |
399 | 465 | ||
400 | dwc->num_in_eps = DWC3_NUM_IN_EPS(parms); | 466 | dwc->num_eps = DWC3_NUM_EPS(parms); |
401 | dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps; | ||
402 | } | 467 | } |
403 | 468 | ||
404 | static void dwc3_cache_hwparams(struct dwc3 *dwc) | 469 | static void dwc3_cache_hwparams(struct dwc3 *dwc) |
@@ -432,6 +497,12 @@ static int dwc3_phy_setup(struct dwc3 *dwc) | |||
432 | reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); | 497 | reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); |
433 | 498 | ||
434 | /* | 499 | /* |
500 | * Make sure UX_EXIT_PX is cleared as that causes issues with some | ||
501 | * PHYs. Also, this bit is not supposed to be used in normal operation. | ||
502 | */ | ||
503 | reg &= ~DWC3_GUSB3PIPECTL_UX_EXIT_PX; | ||
504 | |||
505 | /* | ||
435 | * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY | 506 | * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY |
436 | * to '0' during coreConsultant configuration. So default value | 507 | * to '0' during coreConsultant configuration. So default value |
437 | * will be '0' when the core is reset. Application needs to set it | 508 | * will be '0' when the core is reset. Application needs to set it |
@@ -714,21 +785,6 @@ static int dwc3_core_init(struct dwc3 *dwc) | |||
714 | goto err4; | 785 | goto err4; |
715 | } | 786 | } |
716 | 787 | ||
717 | switch (dwc->dr_mode) { | ||
718 | case USB_DR_MODE_PERIPHERAL: | ||
719 | dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); | ||
720 | break; | ||
721 | case USB_DR_MODE_HOST: | ||
722 | dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); | ||
723 | break; | ||
724 | case USB_DR_MODE_OTG: | ||
725 | dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); | ||
726 | break; | ||
727 | default: | ||
728 | dev_warn(dwc->dev, "Unsupported mode %d\n", dwc->dr_mode); | ||
729 | break; | ||
730 | } | ||
731 | |||
732 | /* | 788 | /* |
733 | * ENDXFER polling is available on version 3.10a and later of | 789 | * ENDXFER polling is available on version 3.10a and later of |
734 | * the DWC_usb3 controller. It is NOT available in the | 790 | * the DWC_usb3 controller. It is NOT available in the |
@@ -846,6 +902,7 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) | |||
846 | 902 | ||
847 | switch (dwc->dr_mode) { | 903 | switch (dwc->dr_mode) { |
848 | case USB_DR_MODE_PERIPHERAL: | 904 | case USB_DR_MODE_PERIPHERAL: |
905 | dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); | ||
849 | ret = dwc3_gadget_init(dwc); | 906 | ret = dwc3_gadget_init(dwc); |
850 | if (ret) { | 907 | if (ret) { |
851 | if (ret != -EPROBE_DEFER) | 908 | if (ret != -EPROBE_DEFER) |
@@ -854,6 +911,7 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) | |||
854 | } | 911 | } |
855 | break; | 912 | break; |
856 | case USB_DR_MODE_HOST: | 913 | case USB_DR_MODE_HOST: |
914 | dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); | ||
857 | ret = dwc3_host_init(dwc); | 915 | ret = dwc3_host_init(dwc); |
858 | if (ret) { | 916 | if (ret) { |
859 | if (ret != -EPROBE_DEFER) | 917 | if (ret != -EPROBE_DEFER) |
@@ -862,17 +920,11 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) | |||
862 | } | 920 | } |
863 | break; | 921 | break; |
864 | case USB_DR_MODE_OTG: | 922 | case USB_DR_MODE_OTG: |
865 | ret = dwc3_host_init(dwc); | 923 | INIT_WORK(&dwc->drd_work, __dwc3_set_mode); |
866 | if (ret) { | 924 | ret = dwc3_drd_init(dwc); |
867 | if (ret != -EPROBE_DEFER) | ||
868 | dev_err(dev, "failed to initialize host\n"); | ||
869 | return ret; | ||
870 | } | ||
871 | |||
872 | ret = dwc3_gadget_init(dwc); | ||
873 | if (ret) { | 925 | if (ret) { |
874 | if (ret != -EPROBE_DEFER) | 926 | if (ret != -EPROBE_DEFER) |
875 | dev_err(dev, "failed to initialize gadget\n"); | 927 | dev_err(dev, "failed to initialize dual-role\n"); |
876 | return ret; | 928 | return ret; |
877 | } | 929 | } |
878 | break; | 930 | break; |
@@ -894,8 +946,7 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc) | |||
894 | dwc3_host_exit(dwc); | 946 | dwc3_host_exit(dwc); |
895 | break; | 947 | break; |
896 | case USB_DR_MODE_OTG: | 948 | case USB_DR_MODE_OTG: |
897 | dwc3_host_exit(dwc); | 949 | dwc3_drd_exit(dwc); |
898 | dwc3_gadget_exit(dwc); | ||
899 | break; | 950 | break; |
900 | default: | 951 | default: |
901 | /* do nothing */ | 952 | /* do nothing */ |
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 2b9e4ca3c932..981c77f5628e 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h | |||
@@ -23,10 +23,12 @@ | |||
23 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
24 | #include <linux/ioport.h> | 24 | #include <linux/ioport.h> |
25 | #include <linux/list.h> | 25 | #include <linux/list.h> |
26 | #include <linux/bitops.h> | ||
26 | #include <linux/dma-mapping.h> | 27 | #include <linux/dma-mapping.h> |
27 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |
28 | #include <linux/debugfs.h> | 29 | #include <linux/debugfs.h> |
29 | #include <linux/wait.h> | 30 | #include <linux/wait.h> |
31 | #include <linux/workqueue.h> | ||
30 | 32 | ||
31 | #include <linux/usb/ch9.h> | 33 | #include <linux/usb/ch9.h> |
32 | #include <linux/usb/gadget.h> | 34 | #include <linux/usb/gadget.h> |
@@ -39,9 +41,8 @@ | |||
39 | 41 | ||
40 | /* Global constants */ | 42 | /* Global constants */ |
41 | #define DWC3_PULL_UP_TIMEOUT 500 /* ms */ | 43 | #define DWC3_PULL_UP_TIMEOUT 500 /* ms */ |
42 | #define DWC3_ZLP_BUF_SIZE 1024 /* size of a superspeed bulk */ | ||
43 | #define DWC3_BOUNCE_SIZE 1024 /* size of a superspeed bulk */ | 44 | #define DWC3_BOUNCE_SIZE 1024 /* size of a superspeed bulk */ |
44 | #define DWC3_EP0_BOUNCE_SIZE 512 | 45 | #define DWC3_EP0_SETUP_SIZE 512 |
45 | #define DWC3_ENDPOINTS_NUM 32 | 46 | #define DWC3_ENDPOINTS_NUM 32 |
46 | #define DWC3_XHCI_RESOURCES_NUM 2 | 47 | #define DWC3_XHCI_RESOURCES_NUM 2 |
47 | 48 | ||
@@ -66,7 +67,7 @@ | |||
66 | #define DWC3_DEVICE_EVENT_OVERFLOW 11 | 67 | #define DWC3_DEVICE_EVENT_OVERFLOW 11 |
67 | 68 | ||
68 | #define DWC3_GEVNTCOUNT_MASK 0xfffc | 69 | #define DWC3_GEVNTCOUNT_MASK 0xfffc |
69 | #define DWC3_GEVNTCOUNT_EHB (1 << 31) | 70 | #define DWC3_GEVNTCOUNT_EHB BIT(31) |
70 | #define DWC3_GSNPSID_MASK 0xffff0000 | 71 | #define DWC3_GSNPSID_MASK 0xffff0000 |
71 | #define DWC3_GSNPSREV_MASK 0xffff | 72 | #define DWC3_GSNPSREV_MASK 0xffff |
72 | 73 | ||
@@ -116,20 +117,20 @@ | |||
116 | #define DWC3_VER_NUMBER 0xc1a0 | 117 | #define DWC3_VER_NUMBER 0xc1a0 |
117 | #define DWC3_VER_TYPE 0xc1a4 | 118 | #define DWC3_VER_TYPE 0xc1a4 |
118 | 119 | ||
119 | #define DWC3_GUSB2PHYCFG(n) (0xc200 + (n * 0x04)) | 120 | #define DWC3_GUSB2PHYCFG(n) (0xc200 + ((n) * 0x04)) |
120 | #define DWC3_GUSB2I2CCTL(n) (0xc240 + (n * 0x04)) | 121 | #define DWC3_GUSB2I2CCTL(n) (0xc240 + ((n) * 0x04)) |
121 | 122 | ||
122 | #define DWC3_GUSB2PHYACC(n) (0xc280 + (n * 0x04)) | 123 | #define DWC3_GUSB2PHYACC(n) (0xc280 + ((n) * 0x04)) |
123 | 124 | ||
124 | #define DWC3_GUSB3PIPECTL(n) (0xc2c0 + (n * 0x04)) | 125 | #define DWC3_GUSB3PIPECTL(n) (0xc2c0 + ((n) * 0x04)) |
125 | 126 | ||
126 | #define DWC3_GTXFIFOSIZ(n) (0xc300 + (n * 0x04)) | 127 | #define DWC3_GTXFIFOSIZ(n) (0xc300 + ((n) * 0x04)) |
127 | #define DWC3_GRXFIFOSIZ(n) (0xc380 + (n * 0x04)) | 128 | #define DWC3_GRXFIFOSIZ(n) (0xc380 + ((n) * 0x04)) |
128 | 129 | ||
129 | #define DWC3_GEVNTADRLO(n) (0xc400 + (n * 0x10)) | 130 | #define DWC3_GEVNTADRLO(n) (0xc400 + ((n) * 0x10)) |
130 | #define DWC3_GEVNTADRHI(n) (0xc404 + (n * 0x10)) | 131 | #define DWC3_GEVNTADRHI(n) (0xc404 + ((n) * 0x10)) |
131 | #define DWC3_GEVNTSIZ(n) (0xc408 + (n * 0x10)) | 132 | #define DWC3_GEVNTSIZ(n) (0xc408 + ((n) * 0x10)) |
132 | #define DWC3_GEVNTCOUNT(n) (0xc40c + (n * 0x10)) | 133 | #define DWC3_GEVNTCOUNT(n) (0xc40c + ((n) * 0x10)) |
133 | 134 | ||
134 | #define DWC3_GHWPARAMS8 0xc600 | 135 | #define DWC3_GHWPARAMS8 0xc600 |
135 | #define DWC3_GFLADJ 0xc630 | 136 | #define DWC3_GFLADJ 0xc630 |
@@ -143,13 +144,13 @@ | |||
143 | #define DWC3_DGCMD 0xc714 | 144 | #define DWC3_DGCMD 0xc714 |
144 | #define DWC3_DALEPENA 0xc720 | 145 | #define DWC3_DALEPENA 0xc720 |
145 | 146 | ||
146 | #define DWC3_DEP_BASE(n) (0xc800 + (n * 0x10)) | 147 | #define DWC3_DEP_BASE(n) (0xc800 + ((n) * 0x10)) |
147 | #define DWC3_DEPCMDPAR2 0x00 | 148 | #define DWC3_DEPCMDPAR2 0x00 |
148 | #define DWC3_DEPCMDPAR1 0x04 | 149 | #define DWC3_DEPCMDPAR1 0x04 |
149 | #define DWC3_DEPCMDPAR0 0x08 | 150 | #define DWC3_DEPCMDPAR0 0x08 |
150 | #define DWC3_DEPCMD 0x0c | 151 | #define DWC3_DEPCMD 0x0c |
151 | 152 | ||
152 | #define DWC3_DEV_IMOD(n) (0xca00 + (n * 0x4)) | 153 | #define DWC3_DEV_IMOD(n) (0xca00 + ((n) * 0x4)) |
153 | 154 | ||
154 | /* OTG Registers */ | 155 | /* OTG Registers */ |
155 | #define DWC3_OCFG 0xcc00 | 156 | #define DWC3_OCFG 0xcc00 |
@@ -176,11 +177,11 @@ | |||
176 | /* Global RX Threshold Configuration Register */ | 177 | /* Global RX Threshold Configuration Register */ |
177 | #define DWC3_GRXTHRCFG_MAXRXBURSTSIZE(n) (((n) & 0x1f) << 19) | 178 | #define DWC3_GRXTHRCFG_MAXRXBURSTSIZE(n) (((n) & 0x1f) << 19) |
178 | #define DWC3_GRXTHRCFG_RXPKTCNT(n) (((n) & 0xf) << 24) | 179 | #define DWC3_GRXTHRCFG_RXPKTCNT(n) (((n) & 0xf) << 24) |
179 | #define DWC3_GRXTHRCFG_PKTCNTSEL (1 << 29) | 180 | #define DWC3_GRXTHRCFG_PKTCNTSEL BIT(29) |
180 | 181 | ||
181 | /* Global Configuration Register */ | 182 | /* Global Configuration Register */ |
182 | #define DWC3_GCTL_PWRDNSCALE(n) ((n) << 19) | 183 | #define DWC3_GCTL_PWRDNSCALE(n) ((n) << 19) |
183 | #define DWC3_GCTL_U2RSTECN (1 << 16) | 184 | #define DWC3_GCTL_U2RSTECN BIT(16) |
184 | #define DWC3_GCTL_RAMCLKSEL(x) (((x) & DWC3_GCTL_CLK_MASK) << 6) | 185 | #define DWC3_GCTL_RAMCLKSEL(x) (((x) & DWC3_GCTL_CLK_MASK) << 6) |
185 | #define DWC3_GCTL_CLK_BUS (0) | 186 | #define DWC3_GCTL_CLK_BUS (0) |
186 | #define DWC3_GCTL_CLK_PIPE (1) | 187 | #define DWC3_GCTL_CLK_PIPE (1) |
@@ -193,24 +194,24 @@ | |||
193 | #define DWC3_GCTL_PRTCAP_DEVICE 2 | 194 | #define DWC3_GCTL_PRTCAP_DEVICE 2 |
194 | #define DWC3_GCTL_PRTCAP_OTG 3 | 195 | #define DWC3_GCTL_PRTCAP_OTG 3 |
195 | 196 | ||
196 | #define DWC3_GCTL_CORESOFTRESET (1 << 11) | 197 | #define DWC3_GCTL_CORESOFTRESET BIT(11) |
197 | #define DWC3_GCTL_SOFITPSYNC (1 << 10) | 198 | #define DWC3_GCTL_SOFITPSYNC BIT(10) |
198 | #define DWC3_GCTL_SCALEDOWN(n) ((n) << 4) | 199 | #define DWC3_GCTL_SCALEDOWN(n) ((n) << 4) |
199 | #define DWC3_GCTL_SCALEDOWN_MASK DWC3_GCTL_SCALEDOWN(3) | 200 | #define DWC3_GCTL_SCALEDOWN_MASK DWC3_GCTL_SCALEDOWN(3) |
200 | #define DWC3_GCTL_DISSCRAMBLE (1 << 3) | 201 | #define DWC3_GCTL_DISSCRAMBLE BIT(3) |
201 | #define DWC3_GCTL_U2EXIT_LFPS (1 << 2) | 202 | #define DWC3_GCTL_U2EXIT_LFPS BIT(2) |
202 | #define DWC3_GCTL_GBLHIBERNATIONEN (1 << 1) | 203 | #define DWC3_GCTL_GBLHIBERNATIONEN BIT(1) |
203 | #define DWC3_GCTL_DSBLCLKGTNG (1 << 0) | 204 | #define DWC3_GCTL_DSBLCLKGTNG BIT(0) |
204 | 205 | ||
205 | /* Global User Control 1 Register */ | 206 | /* Global User Control 1 Register */ |
206 | #define DWC3_GUCTL1_DEV_L1_EXIT_BY_HW (1 << 24) | 207 | #define DWC3_GUCTL1_DEV_L1_EXIT_BY_HW BIT(24) |
207 | 208 | ||
208 | /* Global USB2 PHY Configuration Register */ | 209 | /* Global USB2 PHY Configuration Register */ |
209 | #define DWC3_GUSB2PHYCFG_PHYSOFTRST (1 << 31) | 210 | #define DWC3_GUSB2PHYCFG_PHYSOFTRST BIT(31) |
210 | #define DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS (1 << 30) | 211 | #define DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS BIT(30) |
211 | #define DWC3_GUSB2PHYCFG_SUSPHY (1 << 6) | 212 | #define DWC3_GUSB2PHYCFG_SUSPHY BIT(6) |
212 | #define DWC3_GUSB2PHYCFG_ULPI_UTMI (1 << 4) | 213 | #define DWC3_GUSB2PHYCFG_ULPI_UTMI BIT(4) |
213 | #define DWC3_GUSB2PHYCFG_ENBLSLPM (1 << 8) | 214 | #define DWC3_GUSB2PHYCFG_ENBLSLPM BIT(8) |
214 | #define DWC3_GUSB2PHYCFG_PHYIF(n) (n << 3) | 215 | #define DWC3_GUSB2PHYCFG_PHYIF(n) (n << 3) |
215 | #define DWC3_GUSB2PHYCFG_PHYIF_MASK DWC3_GUSB2PHYCFG_PHYIF(1) | 216 | #define DWC3_GUSB2PHYCFG_PHYIF_MASK DWC3_GUSB2PHYCFG_PHYIF(1) |
216 | #define DWC3_GUSB2PHYCFG_USBTRDTIM(n) (n << 10) | 217 | #define DWC3_GUSB2PHYCFG_USBTRDTIM(n) (n << 10) |
@@ -221,25 +222,26 @@ | |||
221 | #define UTMI_PHYIF_8_BIT 0 | 222 | #define UTMI_PHYIF_8_BIT 0 |
222 | 223 | ||
223 | /* Global USB2 PHY Vendor Control Register */ | 224 | /* Global USB2 PHY Vendor Control Register */ |
224 | #define DWC3_GUSB2PHYACC_NEWREGREQ (1 << 25) | 225 | #define DWC3_GUSB2PHYACC_NEWREGREQ BIT(25) |
225 | #define DWC3_GUSB2PHYACC_BUSY (1 << 23) | 226 | #define DWC3_GUSB2PHYACC_BUSY BIT(23) |
226 | #define DWC3_GUSB2PHYACC_WRITE (1 << 22) | 227 | #define DWC3_GUSB2PHYACC_WRITE BIT(22) |
227 | #define DWC3_GUSB2PHYACC_ADDR(n) (n << 16) | 228 | #define DWC3_GUSB2PHYACC_ADDR(n) (n << 16) |
228 | #define DWC3_GUSB2PHYACC_EXTEND_ADDR(n) (n << 8) | 229 | #define DWC3_GUSB2PHYACC_EXTEND_ADDR(n) (n << 8) |
229 | #define DWC3_GUSB2PHYACC_DATA(n) (n & 0xff) | 230 | #define DWC3_GUSB2PHYACC_DATA(n) (n & 0xff) |
230 | 231 | ||
231 | /* Global USB3 PIPE Control Register */ | 232 | /* Global USB3 PIPE Control Register */ |
232 | #define DWC3_GUSB3PIPECTL_PHYSOFTRST (1 << 31) | 233 | #define DWC3_GUSB3PIPECTL_PHYSOFTRST BIT(31) |
233 | #define DWC3_GUSB3PIPECTL_U2SSINP3OK (1 << 29) | 234 | #define DWC3_GUSB3PIPECTL_U2SSINP3OK BIT(29) |
234 | #define DWC3_GUSB3PIPECTL_DISRXDETINP3 (1 << 28) | 235 | #define DWC3_GUSB3PIPECTL_DISRXDETINP3 BIT(28) |
235 | #define DWC3_GUSB3PIPECTL_REQP1P2P3 (1 << 24) | 236 | #define DWC3_GUSB3PIPECTL_UX_EXIT_PX BIT(27) |
237 | #define DWC3_GUSB3PIPECTL_REQP1P2P3 BIT(24) | ||
236 | #define DWC3_GUSB3PIPECTL_DEP1P2P3(n) ((n) << 19) | 238 | #define DWC3_GUSB3PIPECTL_DEP1P2P3(n) ((n) << 19) |
237 | #define DWC3_GUSB3PIPECTL_DEP1P2P3_MASK DWC3_GUSB3PIPECTL_DEP1P2P3(7) | 239 | #define DWC3_GUSB3PIPECTL_DEP1P2P3_MASK DWC3_GUSB3PIPECTL_DEP1P2P3(7) |
238 | #define DWC3_GUSB3PIPECTL_DEP1P2P3_EN DWC3_GUSB3PIPECTL_DEP1P2P3(1) | 240 | #define DWC3_GUSB3PIPECTL_DEP1P2P3_EN DWC3_GUSB3PIPECTL_DEP1P2P3(1) |
239 | #define DWC3_GUSB3PIPECTL_DEPOCHANGE (1 << 18) | 241 | #define DWC3_GUSB3PIPECTL_DEPOCHANGE BIT(18) |
240 | #define DWC3_GUSB3PIPECTL_SUSPHY (1 << 17) | 242 | #define DWC3_GUSB3PIPECTL_SUSPHY BIT(17) |
241 | #define DWC3_GUSB3PIPECTL_LFPSFILT (1 << 9) | 243 | #define DWC3_GUSB3PIPECTL_LFPSFILT BIT(9) |
242 | #define DWC3_GUSB3PIPECTL_RX_DETOPOLL (1 << 8) | 244 | #define DWC3_GUSB3PIPECTL_RX_DETOPOLL BIT(8) |
243 | #define DWC3_GUSB3PIPECTL_TX_DEEPH_MASK DWC3_GUSB3PIPECTL_TX_DEEPH(3) | 245 | #define DWC3_GUSB3PIPECTL_TX_DEEPH_MASK DWC3_GUSB3PIPECTL_TX_DEEPH(3) |
244 | #define DWC3_GUSB3PIPECTL_TX_DEEPH(n) ((n) << 1) | 246 | #define DWC3_GUSB3PIPECTL_TX_DEEPH(n) ((n) << 1) |
245 | 247 | ||
@@ -248,7 +250,7 @@ | |||
248 | #define DWC3_GTXFIFOSIZ_TXFSTADDR(n) ((n) & 0xffff0000) | 250 | #define DWC3_GTXFIFOSIZ_TXFSTADDR(n) ((n) & 0xffff0000) |
249 | 251 | ||
250 | /* Global Event Size Registers */ | 252 | /* Global Event Size Registers */ |
251 | #define DWC3_GEVNTSIZ_INTMASK (1 << 31) | 253 | #define DWC3_GEVNTSIZ_INTMASK BIT(31) |
252 | #define DWC3_GEVNTSIZ_SIZE(n) ((n) & 0xffff) | 254 | #define DWC3_GEVNTSIZ_SIZE(n) ((n) & 0xffff) |
253 | 255 | ||
254 | /* Global HWPARAMS0 Register */ | 256 | /* Global HWPARAMS0 Register */ |
@@ -289,18 +291,18 @@ | |||
289 | #define DWC3_MAX_HIBER_SCRATCHBUFS 15 | 291 | #define DWC3_MAX_HIBER_SCRATCHBUFS 15 |
290 | 292 | ||
291 | /* Global HWPARAMS6 Register */ | 293 | /* Global HWPARAMS6 Register */ |
292 | #define DWC3_GHWPARAMS6_EN_FPGA (1 << 7) | 294 | #define DWC3_GHWPARAMS6_EN_FPGA BIT(7) |
293 | 295 | ||
294 | /* Global HWPARAMS7 Register */ | 296 | /* Global HWPARAMS7 Register */ |
295 | #define DWC3_GHWPARAMS7_RAM1_DEPTH(n) ((n) & 0xffff) | 297 | #define DWC3_GHWPARAMS7_RAM1_DEPTH(n) ((n) & 0xffff) |
296 | #define DWC3_GHWPARAMS7_RAM2_DEPTH(n) (((n) >> 16) & 0xffff) | 298 | #define DWC3_GHWPARAMS7_RAM2_DEPTH(n) (((n) >> 16) & 0xffff) |
297 | 299 | ||
298 | /* Global Frame Length Adjustment Register */ | 300 | /* Global Frame Length Adjustment Register */ |
299 | #define DWC3_GFLADJ_30MHZ_SDBND_SEL (1 << 7) | 301 | #define DWC3_GFLADJ_30MHZ_SDBND_SEL BIT(7) |
300 | #define DWC3_GFLADJ_30MHZ_MASK 0x3f | 302 | #define DWC3_GFLADJ_30MHZ_MASK 0x3f |
301 | 303 | ||
302 | /* Global User Control Register 2 */ | 304 | /* Global User Control Register 2 */ |
303 | #define DWC3_GUCTL2_RST_ACTBITLATER (1 << 14) | 305 | #define DWC3_GUCTL2_RST_ACTBITLATER BIT(14) |
304 | 306 | ||
305 | /* Device Configuration Register */ | 307 | /* Device Configuration Register */ |
306 | #define DWC3_DCFG_DEVADDR(addr) ((addr) << 3) | 308 | #define DWC3_DCFG_DEVADDR(addr) ((addr) << 3) |
@@ -310,23 +312,23 @@ | |||
310 | #define DWC3_DCFG_SUPERSPEED_PLUS (5 << 0) /* DWC_usb31 only */ | 312 | #define DWC3_DCFG_SUPERSPEED_PLUS (5 << 0) /* DWC_usb31 only */ |
311 | #define DWC3_DCFG_SUPERSPEED (4 << 0) | 313 | #define DWC3_DCFG_SUPERSPEED (4 << 0) |
312 | #define DWC3_DCFG_HIGHSPEED (0 << 0) | 314 | #define DWC3_DCFG_HIGHSPEED (0 << 0) |
313 | #define DWC3_DCFG_FULLSPEED (1 << 0) | 315 | #define DWC3_DCFG_FULLSPEED BIT(0) |
314 | #define DWC3_DCFG_LOWSPEED (2 << 0) | 316 | #define DWC3_DCFG_LOWSPEED (2 << 0) |
315 | 317 | ||
316 | #define DWC3_DCFG_NUMP_SHIFT 17 | 318 | #define DWC3_DCFG_NUMP_SHIFT 17 |
317 | #define DWC3_DCFG_NUMP(n) (((n) >> DWC3_DCFG_NUMP_SHIFT) & 0x1f) | 319 | #define DWC3_DCFG_NUMP(n) (((n) >> DWC3_DCFG_NUMP_SHIFT) & 0x1f) |
318 | #define DWC3_DCFG_NUMP_MASK (0x1f << DWC3_DCFG_NUMP_SHIFT) | 320 | #define DWC3_DCFG_NUMP_MASK (0x1f << DWC3_DCFG_NUMP_SHIFT) |
319 | #define DWC3_DCFG_LPM_CAP (1 << 22) | 321 | #define DWC3_DCFG_LPM_CAP BIT(22) |
320 | 322 | ||
321 | /* Device Control Register */ | 323 | /* Device Control Register */ |
322 | #define DWC3_DCTL_RUN_STOP (1 << 31) | 324 | #define DWC3_DCTL_RUN_STOP BIT(31) |
323 | #define DWC3_DCTL_CSFTRST (1 << 30) | 325 | #define DWC3_DCTL_CSFTRST BIT(30) |
324 | #define DWC3_DCTL_LSFTRST (1 << 29) | 326 | #define DWC3_DCTL_LSFTRST BIT(29) |
325 | 327 | ||
326 | #define DWC3_DCTL_HIRD_THRES_MASK (0x1f << 24) | 328 | #define DWC3_DCTL_HIRD_THRES_MASK (0x1f << 24) |
327 | #define DWC3_DCTL_HIRD_THRES(n) ((n) << 24) | 329 | #define DWC3_DCTL_HIRD_THRES(n) ((n) << 24) |
328 | 330 | ||
329 | #define DWC3_DCTL_APPL1RES (1 << 23) | 331 | #define DWC3_DCTL_APPL1RES BIT(23) |
330 | 332 | ||
331 | /* These apply for core versions 1.87a and earlier */ | 333 | /* These apply for core versions 1.87a and earlier */ |
332 | #define DWC3_DCTL_TRGTULST_MASK (0x0f << 17) | 334 | #define DWC3_DCTL_TRGTULST_MASK (0x0f << 17) |
@@ -341,15 +343,15 @@ | |||
341 | #define DWC3_DCTL_LPM_ERRATA_MASK DWC3_DCTL_LPM_ERRATA(0xf) | 343 | #define DWC3_DCTL_LPM_ERRATA_MASK DWC3_DCTL_LPM_ERRATA(0xf) |
342 | #define DWC3_DCTL_LPM_ERRATA(n) ((n) << 20) | 344 | #define DWC3_DCTL_LPM_ERRATA(n) ((n) << 20) |
343 | 345 | ||
344 | #define DWC3_DCTL_KEEP_CONNECT (1 << 19) | 346 | #define DWC3_DCTL_KEEP_CONNECT BIT(19) |
345 | #define DWC3_DCTL_L1_HIBER_EN (1 << 18) | 347 | #define DWC3_DCTL_L1_HIBER_EN BIT(18) |
346 | #define DWC3_DCTL_CRS (1 << 17) | 348 | #define DWC3_DCTL_CRS BIT(17) |
347 | #define DWC3_DCTL_CSS (1 << 16) | 349 | #define DWC3_DCTL_CSS BIT(16) |
348 | 350 | ||
349 | #define DWC3_DCTL_INITU2ENA (1 << 12) | 351 | #define DWC3_DCTL_INITU2ENA BIT(12) |
350 | #define DWC3_DCTL_ACCEPTU2ENA (1 << 11) | 352 | #define DWC3_DCTL_ACCEPTU2ENA BIT(11) |
351 | #define DWC3_DCTL_INITU1ENA (1 << 10) | 353 | #define DWC3_DCTL_INITU1ENA BIT(10) |
352 | #define DWC3_DCTL_ACCEPTU1ENA (1 << 9) | 354 | #define DWC3_DCTL_ACCEPTU1ENA BIT(9) |
353 | #define DWC3_DCTL_TSTCTRL_MASK (0xf << 1) | 355 | #define DWC3_DCTL_TSTCTRL_MASK (0xf << 1) |
354 | 356 | ||
355 | #define DWC3_DCTL_ULSTCHNGREQ_MASK (0x0f << 5) | 357 | #define DWC3_DCTL_ULSTCHNGREQ_MASK (0x0f << 5) |
@@ -364,36 +366,36 @@ | |||
364 | #define DWC3_DCTL_ULSTCHNG_LOOPBACK (DWC3_DCTL_ULSTCHNGREQ(11)) | 366 | #define DWC3_DCTL_ULSTCHNG_LOOPBACK (DWC3_DCTL_ULSTCHNGREQ(11)) |
365 | 367 | ||
366 | /* Device Event Enable Register */ | 368 | /* Device Event Enable Register */ |
367 | #define DWC3_DEVTEN_VNDRDEVTSTRCVEDEN (1 << 12) | 369 | #define DWC3_DEVTEN_VNDRDEVTSTRCVEDEN BIT(12) |
368 | #define DWC3_DEVTEN_EVNTOVERFLOWEN (1 << 11) | 370 | #define DWC3_DEVTEN_EVNTOVERFLOWEN BIT(11) |
369 | #define DWC3_DEVTEN_CMDCMPLTEN (1 << 10) | 371 | #define DWC3_DEVTEN_CMDCMPLTEN BIT(10) |
370 | #define DWC3_DEVTEN_ERRTICERREN (1 << 9) | 372 | #define DWC3_DEVTEN_ERRTICERREN BIT(9) |
371 | #define DWC3_DEVTEN_SOFEN (1 << 7) | 373 | #define DWC3_DEVTEN_SOFEN BIT(7) |
372 | #define DWC3_DEVTEN_EOPFEN (1 << 6) | 374 | #define DWC3_DEVTEN_EOPFEN BIT(6) |
373 | #define DWC3_DEVTEN_HIBERNATIONREQEVTEN (1 << 5) | 375 | #define DWC3_DEVTEN_HIBERNATIONREQEVTEN BIT(5) |
374 | #define DWC3_DEVTEN_WKUPEVTEN (1 << 4) | 376 | #define DWC3_DEVTEN_WKUPEVTEN BIT(4) |
375 | #define DWC3_DEVTEN_ULSTCNGEN (1 << 3) | 377 | #define DWC3_DEVTEN_ULSTCNGEN BIT(3) |
376 | #define DWC3_DEVTEN_CONNECTDONEEN (1 << 2) | 378 | #define DWC3_DEVTEN_CONNECTDONEEN BIT(2) |
377 | #define DWC3_DEVTEN_USBRSTEN (1 << 1) | 379 | #define DWC3_DEVTEN_USBRSTEN BIT(1) |
378 | #define DWC3_DEVTEN_DISCONNEVTEN (1 << 0) | 380 | #define DWC3_DEVTEN_DISCONNEVTEN BIT(0) |
379 | 381 | ||
380 | /* Device Status Register */ | 382 | /* Device Status Register */ |
381 | #define DWC3_DSTS_DCNRD (1 << 29) | 383 | #define DWC3_DSTS_DCNRD BIT(29) |
382 | 384 | ||
383 | /* This applies for core versions 1.87a and earlier */ | 385 | /* This applies for core versions 1.87a and earlier */ |
384 | #define DWC3_DSTS_PWRUPREQ (1 << 24) | 386 | #define DWC3_DSTS_PWRUPREQ BIT(24) |
385 | 387 | ||
386 | /* These apply for core versions 1.94a and later */ | 388 | /* These apply for core versions 1.94a and later */ |
387 | #define DWC3_DSTS_RSS (1 << 25) | 389 | #define DWC3_DSTS_RSS BIT(25) |
388 | #define DWC3_DSTS_SSS (1 << 24) | 390 | #define DWC3_DSTS_SSS BIT(24) |
389 | 391 | ||
390 | #define DWC3_DSTS_COREIDLE (1 << 23) | 392 | #define DWC3_DSTS_COREIDLE BIT(23) |
391 | #define DWC3_DSTS_DEVCTRLHLT (1 << 22) | 393 | #define DWC3_DSTS_DEVCTRLHLT BIT(22) |
392 | 394 | ||
393 | #define DWC3_DSTS_USBLNKST_MASK (0x0f << 18) | 395 | #define DWC3_DSTS_USBLNKST_MASK (0x0f << 18) |
394 | #define DWC3_DSTS_USBLNKST(n) (((n) & DWC3_DSTS_USBLNKST_MASK) >> 18) | 396 | #define DWC3_DSTS_USBLNKST(n) (((n) & DWC3_DSTS_USBLNKST_MASK) >> 18) |
395 | 397 | ||
396 | #define DWC3_DSTS_RXFIFOEMPTY (1 << 17) | 398 | #define DWC3_DSTS_RXFIFOEMPTY BIT(17) |
397 | 399 | ||
398 | #define DWC3_DSTS_SOFFN_MASK (0x3fff << 3) | 400 | #define DWC3_DSTS_SOFFN_MASK (0x3fff << 3) |
399 | #define DWC3_DSTS_SOFFN(n) (((n) & DWC3_DSTS_SOFFN_MASK) >> 3) | 401 | #define DWC3_DSTS_SOFFN(n) (((n) & DWC3_DSTS_SOFFN_MASK) >> 3) |
@@ -403,7 +405,7 @@ | |||
403 | #define DWC3_DSTS_SUPERSPEED_PLUS (5 << 0) /* DWC_usb31 only */ | 405 | #define DWC3_DSTS_SUPERSPEED_PLUS (5 << 0) /* DWC_usb31 only */ |
404 | #define DWC3_DSTS_SUPERSPEED (4 << 0) | 406 | #define DWC3_DSTS_SUPERSPEED (4 << 0) |
405 | #define DWC3_DSTS_HIGHSPEED (0 << 0) | 407 | #define DWC3_DSTS_HIGHSPEED (0 << 0) |
406 | #define DWC3_DSTS_FULLSPEED (1 << 0) | 408 | #define DWC3_DSTS_FULLSPEED BIT(0) |
407 | #define DWC3_DSTS_LOWSPEED (2 << 0) | 409 | #define DWC3_DSTS_LOWSPEED (2 << 0) |
408 | 410 | ||
409 | /* Device Generic Command Register */ | 411 | /* Device Generic Command Register */ |
@@ -421,26 +423,26 @@ | |||
421 | #define DWC3_DGCMD_RUN_SOC_BUS_LOOPBACK 0x10 | 423 | #define DWC3_DGCMD_RUN_SOC_BUS_LOOPBACK 0x10 |
422 | 424 | ||
423 | #define DWC3_DGCMD_STATUS(n) (((n) >> 12) & 0x0F) | 425 | #define DWC3_DGCMD_STATUS(n) (((n) >> 12) & 0x0F) |
424 | #define DWC3_DGCMD_CMDACT (1 << 10) | 426 | #define DWC3_DGCMD_CMDACT BIT(10) |
425 | #define DWC3_DGCMD_CMDIOC (1 << 8) | 427 | #define DWC3_DGCMD_CMDIOC BIT(8) |
426 | 428 | ||
427 | /* Device Generic Command Parameter Register */ | 429 | /* Device Generic Command Parameter Register */ |
428 | #define DWC3_DGCMDPAR_FORCE_LINKPM_ACCEPT (1 << 0) | 430 | #define DWC3_DGCMDPAR_FORCE_LINKPM_ACCEPT BIT(0) |
429 | #define DWC3_DGCMDPAR_FIFO_NUM(n) ((n) << 0) | 431 | #define DWC3_DGCMDPAR_FIFO_NUM(n) ((n) << 0) |
430 | #define DWC3_DGCMDPAR_RX_FIFO (0 << 5) | 432 | #define DWC3_DGCMDPAR_RX_FIFO (0 << 5) |
431 | #define DWC3_DGCMDPAR_TX_FIFO (1 << 5) | 433 | #define DWC3_DGCMDPAR_TX_FIFO BIT(5) |
432 | #define DWC3_DGCMDPAR_LOOPBACK_DIS (0 << 0) | 434 | #define DWC3_DGCMDPAR_LOOPBACK_DIS (0 << 0) |
433 | #define DWC3_DGCMDPAR_LOOPBACK_ENA (1 << 0) | 435 | #define DWC3_DGCMDPAR_LOOPBACK_ENA BIT(0) |
434 | 436 | ||
435 | /* Device Endpoint Command Register */ | 437 | /* Device Endpoint Command Register */ |
436 | #define DWC3_DEPCMD_PARAM_SHIFT 16 | 438 | #define DWC3_DEPCMD_PARAM_SHIFT 16 |
437 | #define DWC3_DEPCMD_PARAM(x) ((x) << DWC3_DEPCMD_PARAM_SHIFT) | 439 | #define DWC3_DEPCMD_PARAM(x) ((x) << DWC3_DEPCMD_PARAM_SHIFT) |
438 | #define DWC3_DEPCMD_GET_RSC_IDX(x) (((x) >> DWC3_DEPCMD_PARAM_SHIFT) & 0x7f) | 440 | #define DWC3_DEPCMD_GET_RSC_IDX(x) (((x) >> DWC3_DEPCMD_PARAM_SHIFT) & 0x7f) |
439 | #define DWC3_DEPCMD_STATUS(x) (((x) >> 12) & 0x0F) | 441 | #define DWC3_DEPCMD_STATUS(x) (((x) >> 12) & 0x0F) |
440 | #define DWC3_DEPCMD_HIPRI_FORCERM (1 << 11) | 442 | #define DWC3_DEPCMD_HIPRI_FORCERM BIT(11) |
441 | #define DWC3_DEPCMD_CLEARPENDIN (1 << 11) | 443 | #define DWC3_DEPCMD_CLEARPENDIN BIT(11) |
442 | #define DWC3_DEPCMD_CMDACT (1 << 10) | 444 | #define DWC3_DEPCMD_CMDACT BIT(10) |
443 | #define DWC3_DEPCMD_CMDIOC (1 << 8) | 445 | #define DWC3_DEPCMD_CMDIOC BIT(8) |
444 | 446 | ||
445 | #define DWC3_DEPCMD_DEPSTARTCFG (0x09 << 0) | 447 | #define DWC3_DEPCMD_DEPSTARTCFG (0x09 << 0) |
446 | #define DWC3_DEPCMD_ENDTRANSFER (0x08 << 0) | 448 | #define DWC3_DEPCMD_ENDTRANSFER (0x08 << 0) |
@@ -458,7 +460,7 @@ | |||
458 | #define DWC3_DEPCMD_CMD(x) ((x) & 0xf) | 460 | #define DWC3_DEPCMD_CMD(x) ((x) & 0xf) |
459 | 461 | ||
460 | /* The EP number goes 0..31 so ep0 is always out and ep1 is always in */ | 462 | /* The EP number goes 0..31 so ep0 is always out and ep1 is always in */ |
461 | #define DWC3_DALEPENA_EP(n) (1 << n) | 463 | #define DWC3_DALEPENA_EP(n) BIT(n) |
462 | 464 | ||
463 | #define DWC3_DEPCMD_TYPE_CONTROL 0 | 465 | #define DWC3_DEPCMD_TYPE_CONTROL 0 |
464 | #define DWC3_DEPCMD_TYPE_ISOC 1 | 466 | #define DWC3_DEPCMD_TYPE_ISOC 1 |
@@ -500,8 +502,8 @@ struct dwc3_event_buffer { | |||
500 | struct dwc3 *dwc; | 502 | struct dwc3 *dwc; |
501 | }; | 503 | }; |
502 | 504 | ||
503 | #define DWC3_EP_FLAG_STALLED (1 << 0) | 505 | #define DWC3_EP_FLAG_STALLED BIT(0) |
504 | #define DWC3_EP_FLAG_WEDGED (1 << 1) | 506 | #define DWC3_EP_FLAG_WEDGED BIT(1) |
505 | 507 | ||
506 | #define DWC3_EP_DIRECTION_TX true | 508 | #define DWC3_EP_DIRECTION_TX true |
507 | #define DWC3_EP_DIRECTION_RX false | 509 | #define DWC3_EP_DIRECTION_RX false |
@@ -550,17 +552,17 @@ struct dwc3_ep { | |||
550 | 552 | ||
551 | u32 saved_state; | 553 | u32 saved_state; |
552 | unsigned flags; | 554 | unsigned flags; |
553 | #define DWC3_EP_ENABLED (1 << 0) | 555 | #define DWC3_EP_ENABLED BIT(0) |
554 | #define DWC3_EP_STALL (1 << 1) | 556 | #define DWC3_EP_STALL BIT(1) |
555 | #define DWC3_EP_WEDGE (1 << 2) | 557 | #define DWC3_EP_WEDGE BIT(2) |
556 | #define DWC3_EP_BUSY (1 << 4) | 558 | #define DWC3_EP_BUSY BIT(4) |
557 | #define DWC3_EP_PENDING_REQUEST (1 << 5) | 559 | #define DWC3_EP_PENDING_REQUEST BIT(5) |
558 | #define DWC3_EP_MISSED_ISOC (1 << 6) | 560 | #define DWC3_EP_MISSED_ISOC BIT(6) |
559 | #define DWC3_EP_END_TRANSFER_PENDING (1 << 7) | 561 | #define DWC3_EP_END_TRANSFER_PENDING BIT(7) |
560 | #define DWC3_EP_TRANSFER_STARTED (1 << 8) | 562 | #define DWC3_EP_TRANSFER_STARTED BIT(8) |
561 | 563 | ||
562 | /* This last one is specific to EP0 */ | 564 | /* This last one is specific to EP0 */ |
563 | #define DWC3_EP0_DIR_IN (1 << 31) | 565 | #define DWC3_EP0_DIR_IN BIT(31) |
564 | 566 | ||
565 | /* | 567 | /* |
566 | * IMPORTANT: we *know* we have 256 TRBs in our @trb_pool, so we will | 568 | * IMPORTANT: we *know* we have 256 TRBs in our @trb_pool, so we will |
@@ -638,13 +640,13 @@ enum dwc3_link_state { | |||
638 | #define DWC3_TRB_STS_XFER_IN_PROG 4 | 640 | #define DWC3_TRB_STS_XFER_IN_PROG 4 |
639 | 641 | ||
640 | /* TRB Control */ | 642 | /* TRB Control */ |
641 | #define DWC3_TRB_CTRL_HWO (1 << 0) | 643 | #define DWC3_TRB_CTRL_HWO BIT(0) |
642 | #define DWC3_TRB_CTRL_LST (1 << 1) | 644 | #define DWC3_TRB_CTRL_LST BIT(1) |
643 | #define DWC3_TRB_CTRL_CHN (1 << 2) | 645 | #define DWC3_TRB_CTRL_CHN BIT(2) |
644 | #define DWC3_TRB_CTRL_CSP (1 << 3) | 646 | #define DWC3_TRB_CTRL_CSP BIT(3) |
645 | #define DWC3_TRB_CTRL_TRBCTL(n) (((n) & 0x3f) << 4) | 647 | #define DWC3_TRB_CTRL_TRBCTL(n) (((n) & 0x3f) << 4) |
646 | #define DWC3_TRB_CTRL_ISP_IMI (1 << 10) | 648 | #define DWC3_TRB_CTRL_ISP_IMI BIT(10) |
647 | #define DWC3_TRB_CTRL_IOC (1 << 11) | 649 | #define DWC3_TRB_CTRL_IOC BIT(11) |
648 | #define DWC3_TRB_CTRL_SID_SOFN(n) (((n) & 0xffff) << 14) | 650 | #define DWC3_TRB_CTRL_SID_SOFN(n) (((n) & 0xffff) << 14) |
649 | 651 | ||
650 | #define DWC3_TRBCTL_TYPE(n) ((n) & (0x3f << 4)) | 652 | #define DWC3_TRBCTL_TYPE(n) ((n) & (0x3f << 4)) |
@@ -746,6 +748,7 @@ struct dwc3_request { | |||
746 | unsigned direction:1; | 748 | unsigned direction:1; |
747 | unsigned mapped:1; | 749 | unsigned mapped:1; |
748 | unsigned started:1; | 750 | unsigned started:1; |
751 | unsigned zero:1; | ||
749 | }; | 752 | }; |
750 | 753 | ||
751 | /* | 754 | /* |
@@ -758,15 +761,11 @@ struct dwc3_scratchpad_array { | |||
758 | 761 | ||
759 | /** | 762 | /** |
760 | * struct dwc3 - representation of our controller | 763 | * struct dwc3 - representation of our controller |
761 | * @ctrl_req: usb control request which is used for ep0 | 764 | * @drd_work - workqueue used for role swapping |
762 | * @ep0_trb: trb which is used for the ctrl_req | 765 | * @ep0_trb: trb which is used for the ctrl_req |
763 | * @ep0_bounce: bounce buffer for ep0 | ||
764 | * @zlp_buf: used when request->zero is set | ||
765 | * @setup_buf: used while precessing STD USB requests | 766 | * @setup_buf: used while precessing STD USB requests |
766 | * @ctrl_req_addr: dma address of ctrl_req | ||
767 | * @ep0_trb: dma address of ep0_trb | 767 | * @ep0_trb: dma address of ep0_trb |
768 | * @ep0_usb_req: dummy req used while handling STD USB requests | 768 | * @ep0_usb_req: dummy req used while handling STD USB requests |
769 | * @ep0_bounce_addr: dma address of ep0_bounce | ||
770 | * @scratch_addr: dma address of scratchbuf | 769 | * @scratch_addr: dma address of scratchbuf |
771 | * @ep0_in_setup: one control transfer is completed and enter setup phase | 770 | * @ep0_in_setup: one control transfer is completed and enter setup phase |
772 | * @lock: for synchronizing | 771 | * @lock: for synchronizing |
@@ -784,6 +783,10 @@ struct dwc3_scratchpad_array { | |||
784 | * @maximum_speed: maximum speed requested (mainly for testing purposes) | 783 | * @maximum_speed: maximum speed requested (mainly for testing purposes) |
785 | * @revision: revision register contents | 784 | * @revision: revision register contents |
786 | * @dr_mode: requested mode of operation | 785 | * @dr_mode: requested mode of operation |
786 | * @current_dr_role: current role of operation when in dual-role mode | ||
787 | * @desired_dr_role: desired role of operation when in dual-role mode | ||
788 | * @edev: extcon handle | ||
789 | * @edev_nb: extcon notifier | ||
787 | * @hsphy_mode: UTMI phy mode, one of following: | 790 | * @hsphy_mode: UTMI phy mode, one of following: |
788 | * - USBPHY_INTERFACE_MODE_UTMI | 791 | * - USBPHY_INTERFACE_MODE_UTMI |
789 | * - USBPHY_INTERFACE_MODE_UTMIW | 792 | * - USBPHY_INTERFACE_MODE_UTMIW |
@@ -799,8 +802,7 @@ struct dwc3_scratchpad_array { | |||
799 | * @u2pel: parameter from Set SEL request. | 802 | * @u2pel: parameter from Set SEL request. |
800 | * @u1sel: parameter from Set SEL request. | 803 | * @u1sel: parameter from Set SEL request. |
801 | * @u1pel: parameter from Set SEL request. | 804 | * @u1pel: parameter from Set SEL request. |
802 | * @num_out_eps: number of out endpoints | 805 | * @num_eps: number of endpoints |
803 | * @num_in_eps: number of in endpoints | ||
804 | * @ep0_next_event: hold the next expected event | 806 | * @ep0_next_event: hold the next expected event |
805 | * @ep0state: state of endpoint zero | 807 | * @ep0state: state of endpoint zero |
806 | * @link_state: link state | 808 | * @link_state: link state |
@@ -858,17 +860,13 @@ struct dwc3_scratchpad_array { | |||
858 | * increments or 0 to disable. | 860 | * increments or 0 to disable. |
859 | */ | 861 | */ |
860 | struct dwc3 { | 862 | struct dwc3 { |
861 | struct usb_ctrlrequest *ctrl_req; | 863 | struct work_struct drd_work; |
862 | struct dwc3_trb *ep0_trb; | 864 | struct dwc3_trb *ep0_trb; |
863 | void *bounce; | 865 | void *bounce; |
864 | void *ep0_bounce; | ||
865 | void *zlp_buf; | ||
866 | void *scratchbuf; | 866 | void *scratchbuf; |
867 | u8 *setup_buf; | 867 | u8 *setup_buf; |
868 | dma_addr_t ctrl_req_addr; | ||
869 | dma_addr_t ep0_trb_addr; | 868 | dma_addr_t ep0_trb_addr; |
870 | dma_addr_t bounce_addr; | 869 | dma_addr_t bounce_addr; |
871 | dma_addr_t ep0_bounce_addr; | ||
872 | dma_addr_t scratch_addr; | 870 | dma_addr_t scratch_addr; |
873 | struct dwc3_request ep0_usb_req; | 871 | struct dwc3_request ep0_usb_req; |
874 | struct completion ep0_in_setup; | 872 | struct completion ep0_in_setup; |
@@ -900,6 +898,10 @@ struct dwc3 { | |||
900 | size_t regs_size; | 898 | size_t regs_size; |
901 | 899 | ||
902 | enum usb_dr_mode dr_mode; | 900 | enum usb_dr_mode dr_mode; |
901 | u32 current_dr_role; | ||
902 | u32 desired_dr_role; | ||
903 | struct extcon_dev *edev; | ||
904 | struct notifier_block edev_nb; | ||
903 | enum usb_phy_interface hsphy_mode; | 905 | enum usb_phy_interface hsphy_mode; |
904 | 906 | ||
905 | u32 fladj; | 907 | u32 fladj; |
@@ -960,8 +962,7 @@ struct dwc3 { | |||
960 | 962 | ||
961 | u8 speed; | 963 | u8 speed; |
962 | 964 | ||
963 | u8 num_out_eps; | 965 | u8 num_eps; |
964 | u8 num_in_eps; | ||
965 | 966 | ||
966 | struct dwc3_hwparams hwparams; | 967 | struct dwc3_hwparams hwparams; |
967 | struct dentry *root; | 968 | struct dentry *root; |
@@ -1010,7 +1011,7 @@ struct dwc3 { | |||
1010 | u16 imod_interval; | 1011 | u16 imod_interval; |
1011 | }; | 1012 | }; |
1012 | 1013 | ||
1013 | /* -------------------------------------------------------------------------- */ | 1014 | #define work_to_dwc(w) (container_of((w), struct dwc3, drd_work)) |
1014 | 1015 | ||
1015 | /* -------------------------------------------------------------------------- */ | 1016 | /* -------------------------------------------------------------------------- */ |
1016 | 1017 | ||
@@ -1054,13 +1055,13 @@ struct dwc3_event_depevt { | |||
1054 | u32 status:4; | 1055 | u32 status:4; |
1055 | 1056 | ||
1056 | /* Within XferNotReady */ | 1057 | /* Within XferNotReady */ |
1057 | #define DEPEVT_STATUS_TRANSFER_ACTIVE (1 << 3) | 1058 | #define DEPEVT_STATUS_TRANSFER_ACTIVE BIT(3) |
1058 | 1059 | ||
1059 | /* Within XferComplete */ | 1060 | /* Within XferComplete */ |
1060 | #define DEPEVT_STATUS_BUSERR (1 << 0) | 1061 | #define DEPEVT_STATUS_BUSERR BIT(0) |
1061 | #define DEPEVT_STATUS_SHORT (1 << 1) | 1062 | #define DEPEVT_STATUS_SHORT BIT(1) |
1062 | #define DEPEVT_STATUS_IOC (1 << 2) | 1063 | #define DEPEVT_STATUS_IOC BIT(2) |
1063 | #define DEPEVT_STATUS_LST (1 << 3) | 1064 | #define DEPEVT_STATUS_LST BIT(3) |
1064 | 1065 | ||
1065 | /* Stream event only */ | 1066 | /* Stream event only */ |
1066 | #define DEPEVT_STREAMEVT_FOUND 1 | 1067 | #define DEPEVT_STREAMEVT_FOUND 1 |
@@ -1221,6 +1222,16 @@ static inline int dwc3_send_gadget_generic_command(struct dwc3 *dwc, | |||
1221 | { return 0; } | 1222 | { return 0; } |
1222 | #endif | 1223 | #endif |
1223 | 1224 | ||
1225 | #if IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) | ||
1226 | int dwc3_drd_init(struct dwc3 *dwc); | ||
1227 | void dwc3_drd_exit(struct dwc3 *dwc); | ||
1228 | #else | ||
1229 | static inline int dwc3_drd_init(struct dwc3 *dwc) | ||
1230 | { return 0; } | ||
1231 | static inline void dwc3_drd_exit(struct dwc3 *dwc) | ||
1232 | { } | ||
1233 | #endif | ||
1234 | |||
1224 | /* power management interface */ | 1235 | /* power management interface */ |
1225 | #if !IS_ENABLED(CONFIG_USB_DWC3_HOST) | 1236 | #if !IS_ENABLED(CONFIG_USB_DWC3_HOST) |
1226 | int dwc3_gadget_suspend(struct dwc3 *dwc); | 1237 | int dwc3_gadget_suspend(struct dwc3 *dwc); |
diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h index eeed4ffd8131..cb2d8d3f7f3d 100644 --- a/drivers/usb/dwc3/debug.h +++ b/drivers/usb/dwc3/debug.h | |||
@@ -124,6 +124,34 @@ dwc3_gadget_link_string(enum dwc3_link_state link_state) | |||
124 | } | 124 | } |
125 | } | 125 | } |
126 | 126 | ||
127 | /** | ||
128 | * dwc3_trb_type_string - returns TRB type as a string | ||
129 | * @type: the type of the TRB | ||
130 | */ | ||
131 | static inline const char *dwc3_trb_type_string(unsigned int type) | ||
132 | { | ||
133 | switch (type) { | ||
134 | case DWC3_TRBCTL_NORMAL: | ||
135 | return "normal"; | ||
136 | case DWC3_TRBCTL_CONTROL_SETUP: | ||
137 | return "setup"; | ||
138 | case DWC3_TRBCTL_CONTROL_STATUS2: | ||
139 | return "status2"; | ||
140 | case DWC3_TRBCTL_CONTROL_STATUS3: | ||
141 | return "status3"; | ||
142 | case DWC3_TRBCTL_CONTROL_DATA: | ||
143 | return "data"; | ||
144 | case DWC3_TRBCTL_ISOCHRONOUS_FIRST: | ||
145 | return "isoc-first"; | ||
146 | case DWC3_TRBCTL_ISOCHRONOUS: | ||
147 | return "isoc"; | ||
148 | case DWC3_TRBCTL_LINK_TRB: | ||
149 | return "link"; | ||
150 | default: | ||
151 | return "UNKNOWN"; | ||
152 | } | ||
153 | } | ||
154 | |||
127 | static inline const char *dwc3_ep0_state_string(enum dwc3_ep0_state state) | 155 | static inline const char *dwc3_ep0_state_string(enum dwc3_ep0_state state) |
128 | { | 156 | { |
129 | switch (state) { | 157 | switch (state) { |
diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 31926dda43c9..7be963dd8e3b 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c | |||
@@ -300,7 +300,7 @@ static int dwc3_mode_show(struct seq_file *s, void *unused) | |||
300 | seq_printf(s, "device\n"); | 300 | seq_printf(s, "device\n"); |
301 | break; | 301 | break; |
302 | case DWC3_GCTL_PRTCAP_OTG: | 302 | case DWC3_GCTL_PRTCAP_OTG: |
303 | seq_printf(s, "OTG\n"); | 303 | seq_printf(s, "otg\n"); |
304 | break; | 304 | break; |
305 | default: | 305 | default: |
306 | seq_printf(s, "UNKNOWN %08x\n", DWC3_GCTL_PRTCAP(reg)); | 306 | seq_printf(s, "UNKNOWN %08x\n", DWC3_GCTL_PRTCAP(reg)); |
@@ -319,7 +319,6 @@ static ssize_t dwc3_mode_write(struct file *file, | |||
319 | { | 319 | { |
320 | struct seq_file *s = file->private_data; | 320 | struct seq_file *s = file->private_data; |
321 | struct dwc3 *dwc = s->private; | 321 | struct dwc3 *dwc = s->private; |
322 | unsigned long flags; | ||
323 | u32 mode = 0; | 322 | u32 mode = 0; |
324 | char buf[32]; | 323 | char buf[32]; |
325 | 324 | ||
@@ -327,19 +326,16 @@ static ssize_t dwc3_mode_write(struct file *file, | |||
327 | return -EFAULT; | 326 | return -EFAULT; |
328 | 327 | ||
329 | if (!strncmp(buf, "host", 4)) | 328 | if (!strncmp(buf, "host", 4)) |
330 | mode |= DWC3_GCTL_PRTCAP_HOST; | 329 | mode = DWC3_GCTL_PRTCAP_HOST; |
331 | 330 | ||
332 | if (!strncmp(buf, "device", 6)) | 331 | if (!strncmp(buf, "device", 6)) |
333 | mode |= DWC3_GCTL_PRTCAP_DEVICE; | 332 | mode = DWC3_GCTL_PRTCAP_DEVICE; |
334 | 333 | ||
335 | if (!strncmp(buf, "otg", 3)) | 334 | if (!strncmp(buf, "otg", 3)) |
336 | mode |= DWC3_GCTL_PRTCAP_OTG; | 335 | mode = DWC3_GCTL_PRTCAP_OTG; |
336 | |||
337 | dwc3_set_mode(dwc, mode); | ||
337 | 338 | ||
338 | if (mode) { | ||
339 | spin_lock_irqsave(&dwc->lock, flags); | ||
340 | dwc3_set_mode(dwc, mode); | ||
341 | spin_unlock_irqrestore(&dwc->lock, flags); | ||
342 | } | ||
343 | return count; | 339 | return count; |
344 | } | 340 | } |
345 | 341 | ||
@@ -446,52 +442,7 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused) | |||
446 | state = DWC3_DSTS_USBLNKST(reg); | 442 | state = DWC3_DSTS_USBLNKST(reg); |
447 | spin_unlock_irqrestore(&dwc->lock, flags); | 443 | spin_unlock_irqrestore(&dwc->lock, flags); |
448 | 444 | ||
449 | switch (state) { | 445 | seq_printf(s, "%s\n", dwc3_gadget_link_string(state)); |
450 | case DWC3_LINK_STATE_U0: | ||
451 | seq_printf(s, "U0\n"); | ||
452 | break; | ||
453 | case DWC3_LINK_STATE_U1: | ||
454 | seq_printf(s, "U1\n"); | ||
455 | break; | ||
456 | case DWC3_LINK_STATE_U2: | ||
457 | seq_printf(s, "U2\n"); | ||
458 | break; | ||
459 | case DWC3_LINK_STATE_U3: | ||
460 | seq_printf(s, "U3\n"); | ||
461 | break; | ||
462 | case DWC3_LINK_STATE_SS_DIS: | ||
463 | seq_printf(s, "SS.Disabled\n"); | ||
464 | break; | ||
465 | case DWC3_LINK_STATE_RX_DET: | ||
466 | seq_printf(s, "Rx.Detect\n"); | ||
467 | break; | ||
468 | case DWC3_LINK_STATE_SS_INACT: | ||
469 | seq_printf(s, "SS.Inactive\n"); | ||
470 | break; | ||
471 | case DWC3_LINK_STATE_POLL: | ||
472 | seq_printf(s, "Poll\n"); | ||
473 | break; | ||
474 | case DWC3_LINK_STATE_RECOV: | ||
475 | seq_printf(s, "Recovery\n"); | ||
476 | break; | ||
477 | case DWC3_LINK_STATE_HRESET: | ||
478 | seq_printf(s, "HRESET\n"); | ||
479 | break; | ||
480 | case DWC3_LINK_STATE_CMPLY: | ||
481 | seq_printf(s, "Compliance\n"); | ||
482 | break; | ||
483 | case DWC3_LINK_STATE_LPBK: | ||
484 | seq_printf(s, "Loopback\n"); | ||
485 | break; | ||
486 | case DWC3_LINK_STATE_RESET: | ||
487 | seq_printf(s, "Reset\n"); | ||
488 | break; | ||
489 | case DWC3_LINK_STATE_RESUME: | ||
490 | seq_printf(s, "Resume\n"); | ||
491 | break; | ||
492 | default: | ||
493 | seq_printf(s, "UNKNOWN %d\n", state); | ||
494 | } | ||
495 | 446 | ||
496 | return 0; | 447 | return 0; |
497 | } | 448 | } |
@@ -689,30 +640,6 @@ out: | |||
689 | return 0; | 640 | return 0; |
690 | } | 641 | } |
691 | 642 | ||
692 | static inline const char *dwc3_trb_type_string(struct dwc3_trb *trb) | ||
693 | { | ||
694 | switch (DWC3_TRBCTL_TYPE(trb->ctrl)) { | ||
695 | case DWC3_TRBCTL_NORMAL: | ||
696 | return "normal"; | ||
697 | case DWC3_TRBCTL_CONTROL_SETUP: | ||
698 | return "control-setup"; | ||
699 | case DWC3_TRBCTL_CONTROL_STATUS2: | ||
700 | return "control-status2"; | ||
701 | case DWC3_TRBCTL_CONTROL_STATUS3: | ||
702 | return "control-status3"; | ||
703 | case DWC3_TRBCTL_CONTROL_DATA: | ||
704 | return "control-data"; | ||
705 | case DWC3_TRBCTL_ISOCHRONOUS_FIRST: | ||
706 | return "isoc-first"; | ||
707 | case DWC3_TRBCTL_ISOCHRONOUS: | ||
708 | return "isoc"; | ||
709 | case DWC3_TRBCTL_LINK_TRB: | ||
710 | return "link"; | ||
711 | default: | ||
712 | return "UNKNOWN"; | ||
713 | } | ||
714 | } | ||
715 | |||
716 | static int dwc3_ep_trb_ring_show(struct seq_file *s, void *unused) | 643 | static int dwc3_ep_trb_ring_show(struct seq_file *s, void *unused) |
717 | { | 644 | { |
718 | struct dwc3_ep *dep = s->private; | 645 | struct dwc3_ep *dep = s->private; |
@@ -733,10 +660,11 @@ static int dwc3_ep_trb_ring_show(struct seq_file *s, void *unused) | |||
733 | 660 | ||
734 | for (i = 0; i < DWC3_TRB_NUM; i++) { | 661 | for (i = 0; i < DWC3_TRB_NUM; i++) { |
735 | struct dwc3_trb *trb = &dep->trb_pool[i]; | 662 | struct dwc3_trb *trb = &dep->trb_pool[i]; |
663 | unsigned int type = DWC3_TRBCTL_TYPE(trb->ctrl); | ||
736 | 664 | ||
737 | seq_printf(s, "%08x%08x,%d,%s,%d,%d,%d,%d,%d,%d\n", | 665 | seq_printf(s, "%08x%08x,%d,%s,%d,%d,%d,%d,%d,%d\n", |
738 | trb->bph, trb->bpl, trb->size, | 666 | trb->bph, trb->bpl, trb->size, |
739 | dwc3_trb_type_string(trb), | 667 | dwc3_trb_type_string(type), |
740 | !!(trb->ctrl & DWC3_TRB_CTRL_IOC), | 668 | !!(trb->ctrl & DWC3_TRB_CTRL_IOC), |
741 | !!(trb->ctrl & DWC3_TRB_CTRL_ISP_IMI), | 669 | !!(trb->ctrl & DWC3_TRB_CTRL_ISP_IMI), |
742 | !!(trb->ctrl & DWC3_TRB_CTRL_CSP), | 670 | !!(trb->ctrl & DWC3_TRB_CTRL_CSP), |
@@ -822,19 +750,8 @@ static void dwc3_debugfs_create_endpoint_dirs(struct dwc3 *dwc, | |||
822 | { | 750 | { |
823 | int i; | 751 | int i; |
824 | 752 | ||
825 | for (i = 0; i < dwc->num_in_eps; i++) { | 753 | for (i = 0; i < dwc->num_eps; i++) { |
826 | u8 epnum = (i << 1) | 1; | 754 | struct dwc3_ep *dep = dwc->eps[i]; |
827 | struct dwc3_ep *dep = dwc->eps[epnum]; | ||
828 | |||
829 | if (!dep) | ||
830 | continue; | ||
831 | |||
832 | dwc3_debugfs_create_endpoint_dir(dep, parent); | ||
833 | } | ||
834 | |||
835 | for (i = 0; i < dwc->num_out_eps; i++) { | ||
836 | u8 epnum = (i << 1); | ||
837 | struct dwc3_ep *dep = dwc->eps[epnum]; | ||
838 | 755 | ||
839 | if (!dep) | 756 | if (!dep) |
840 | continue; | 757 | continue; |
diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c new file mode 100644 index 000000000000..2765c51c7ef5 --- /dev/null +++ b/drivers/usb/dwc3/drd.c | |||
@@ -0,0 +1,85 @@ | |||
1 | /** | ||
2 | * drd.c - DesignWare USB3 DRD Controller Dual-role support | ||
3 | * | ||
4 | * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com | ||
5 | * | ||
6 | * Authors: Roger Quadros <rogerq@ti.com> | ||
7 | * | ||
8 | * This program is free software: you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 of | ||
10 | * the License as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #include <linux/extcon.h> | ||
22 | |||
23 | #include "debug.h" | ||
24 | #include "core.h" | ||
25 | #include "gadget.h" | ||
26 | |||
27 | static void dwc3_drd_update(struct dwc3 *dwc) | ||
28 | { | ||
29 | int id; | ||
30 | |||
31 | id = extcon_get_state(dwc->edev, EXTCON_USB_HOST); | ||
32 | if (id < 0) | ||
33 | id = 0; | ||
34 | |||
35 | dwc3_set_mode(dwc, id ? | ||
36 | DWC3_GCTL_PRTCAP_HOST : | ||
37 | DWC3_GCTL_PRTCAP_DEVICE); | ||
38 | } | ||
39 | |||
40 | static int dwc3_drd_notifier(struct notifier_block *nb, | ||
41 | unsigned long event, void *ptr) | ||
42 | { | ||
43 | struct dwc3 *dwc = container_of(nb, struct dwc3, edev_nb); | ||
44 | |||
45 | dwc3_set_mode(dwc, event ? | ||
46 | DWC3_GCTL_PRTCAP_HOST : | ||
47 | DWC3_GCTL_PRTCAP_DEVICE); | ||
48 | |||
49 | return NOTIFY_DONE; | ||
50 | } | ||
51 | |||
52 | int dwc3_drd_init(struct dwc3 *dwc) | ||
53 | { | ||
54 | int ret; | ||
55 | |||
56 | if (dwc->dev->of_node) { | ||
57 | if (of_property_read_bool(dwc->dev->of_node, "extcon")) | ||
58 | dwc->edev = extcon_get_edev_by_phandle(dwc->dev, 0); | ||
59 | |||
60 | if (IS_ERR(dwc->edev)) | ||
61 | return PTR_ERR(dwc->edev); | ||
62 | |||
63 | dwc->edev_nb.notifier_call = dwc3_drd_notifier; | ||
64 | ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST, | ||
65 | &dwc->edev_nb); | ||
66 | if (ret < 0) { | ||
67 | dev_err(dwc->dev, "couldn't register cable notifier\n"); | ||
68 | return ret; | ||
69 | } | ||
70 | } | ||
71 | |||
72 | dwc3_drd_update(dwc); | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | void dwc3_drd_exit(struct dwc3 *dwc) | ||
78 | { | ||
79 | extcon_unregister_notifier(dwc->edev, EXTCON_USB_HOST, | ||
80 | &dwc->edev_nb); | ||
81 | |||
82 | dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); | ||
83 | flush_work(&dwc->drd_work); | ||
84 | dwc3_gadget_exit(dwc); | ||
85 | } | ||
diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c index 1515d45ebcec..98f74ff66120 100644 --- a/drivers/usb/dwc3/dwc3-exynos.c +++ b/drivers/usb/dwc3/dwc3-exynos.c | |||
@@ -147,53 +147,53 @@ static int dwc3_exynos_probe(struct platform_device *pdev) | |||
147 | exynos->vdd33 = devm_regulator_get(dev, "vdd33"); | 147 | exynos->vdd33 = devm_regulator_get(dev, "vdd33"); |
148 | if (IS_ERR(exynos->vdd33)) { | 148 | if (IS_ERR(exynos->vdd33)) { |
149 | ret = PTR_ERR(exynos->vdd33); | 149 | ret = PTR_ERR(exynos->vdd33); |
150 | goto err2; | 150 | goto vdd33_err; |
151 | } | 151 | } |
152 | ret = regulator_enable(exynos->vdd33); | 152 | ret = regulator_enable(exynos->vdd33); |
153 | if (ret) { | 153 | if (ret) { |
154 | dev_err(dev, "Failed to enable VDD33 supply\n"); | 154 | dev_err(dev, "Failed to enable VDD33 supply\n"); |
155 | goto err2; | 155 | goto vdd33_err; |
156 | } | 156 | } |
157 | 157 | ||
158 | exynos->vdd10 = devm_regulator_get(dev, "vdd10"); | 158 | exynos->vdd10 = devm_regulator_get(dev, "vdd10"); |
159 | if (IS_ERR(exynos->vdd10)) { | 159 | if (IS_ERR(exynos->vdd10)) { |
160 | ret = PTR_ERR(exynos->vdd10); | 160 | ret = PTR_ERR(exynos->vdd10); |
161 | goto err3; | 161 | goto vdd10_err; |
162 | } | 162 | } |
163 | ret = regulator_enable(exynos->vdd10); | 163 | ret = regulator_enable(exynos->vdd10); |
164 | if (ret) { | 164 | if (ret) { |
165 | dev_err(dev, "Failed to enable VDD10 supply\n"); | 165 | dev_err(dev, "Failed to enable VDD10 supply\n"); |
166 | goto err3; | 166 | goto vdd10_err; |
167 | } | 167 | } |
168 | 168 | ||
169 | ret = dwc3_exynos_register_phys(exynos); | 169 | ret = dwc3_exynos_register_phys(exynos); |
170 | if (ret) { | 170 | if (ret) { |
171 | dev_err(dev, "couldn't register PHYs\n"); | 171 | dev_err(dev, "couldn't register PHYs\n"); |
172 | goto err4; | 172 | goto phys_err; |
173 | } | 173 | } |
174 | 174 | ||
175 | if (node) { | 175 | if (node) { |
176 | ret = of_platform_populate(node, NULL, NULL, dev); | 176 | ret = of_platform_populate(node, NULL, NULL, dev); |
177 | if (ret) { | 177 | if (ret) { |
178 | dev_err(dev, "failed to add dwc3 core\n"); | 178 | dev_err(dev, "failed to add dwc3 core\n"); |
179 | goto err5; | 179 | goto populate_err; |
180 | } | 180 | } |
181 | } else { | 181 | } else { |
182 | dev_err(dev, "no device node, failed to add dwc3 core\n"); | 182 | dev_err(dev, "no device node, failed to add dwc3 core\n"); |
183 | ret = -ENODEV; | 183 | ret = -ENODEV; |
184 | goto err5; | 184 | goto populate_err; |
185 | } | 185 | } |
186 | 186 | ||
187 | return 0; | 187 | return 0; |
188 | 188 | ||
189 | err5: | 189 | populate_err: |
190 | platform_device_unregister(exynos->usb2_phy); | 190 | platform_device_unregister(exynos->usb2_phy); |
191 | platform_device_unregister(exynos->usb3_phy); | 191 | platform_device_unregister(exynos->usb3_phy); |
192 | err4: | 192 | phys_err: |
193 | regulator_disable(exynos->vdd10); | 193 | regulator_disable(exynos->vdd10); |
194 | err3: | 194 | vdd10_err: |
195 | regulator_disable(exynos->vdd33); | 195 | regulator_disable(exynos->vdd33); |
196 | err2: | 196 | vdd33_err: |
197 | clk_disable_unprepare(exynos->axius_clk); | 197 | clk_disable_unprepare(exynos->axius_clk); |
198 | axius_clk_err: | 198 | axius_clk_err: |
199 | clk_disable_unprepare(exynos->susp_clk); | 199 | clk_disable_unprepare(exynos->susp_clk); |
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index f8d0747810e7..98926504b55b 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c | |||
@@ -79,40 +79,40 @@ | |||
79 | #define USBOTGSS_DEBUG_OFFSET 0x0600 | 79 | #define USBOTGSS_DEBUG_OFFSET 0x0600 |
80 | 80 | ||
81 | /* SYSCONFIG REGISTER */ | 81 | /* SYSCONFIG REGISTER */ |
82 | #define USBOTGSS_SYSCONFIG_DMADISABLE (1 << 16) | 82 | #define USBOTGSS_SYSCONFIG_DMADISABLE BIT(16) |
83 | 83 | ||
84 | /* IRQ_EOI REGISTER */ | 84 | /* IRQ_EOI REGISTER */ |
85 | #define USBOTGSS_IRQ_EOI_LINE_NUMBER (1 << 0) | 85 | #define USBOTGSS_IRQ_EOI_LINE_NUMBER BIT(0) |
86 | 86 | ||
87 | /* IRQS0 BITS */ | 87 | /* IRQS0 BITS */ |
88 | #define USBOTGSS_IRQO_COREIRQ_ST (1 << 0) | 88 | #define USBOTGSS_IRQO_COREIRQ_ST BIT(0) |
89 | 89 | ||
90 | /* IRQMISC BITS */ | 90 | /* IRQMISC BITS */ |
91 | #define USBOTGSS_IRQMISC_DMADISABLECLR (1 << 17) | 91 | #define USBOTGSS_IRQMISC_DMADISABLECLR BIT(17) |
92 | #define USBOTGSS_IRQMISC_OEVT (1 << 16) | 92 | #define USBOTGSS_IRQMISC_OEVT BIT(16) |
93 | #define USBOTGSS_IRQMISC_DRVVBUS_RISE (1 << 13) | 93 | #define USBOTGSS_IRQMISC_DRVVBUS_RISE BIT(13) |
94 | #define USBOTGSS_IRQMISC_CHRGVBUS_RISE (1 << 12) | 94 | #define USBOTGSS_IRQMISC_CHRGVBUS_RISE BIT(12) |
95 | #define USBOTGSS_IRQMISC_DISCHRGVBUS_RISE (1 << 11) | 95 | #define USBOTGSS_IRQMISC_DISCHRGVBUS_RISE BIT(11) |
96 | #define USBOTGSS_IRQMISC_IDPULLUP_RISE (1 << 8) | 96 | #define USBOTGSS_IRQMISC_IDPULLUP_RISE BIT(8) |
97 | #define USBOTGSS_IRQMISC_DRVVBUS_FALL (1 << 5) | 97 | #define USBOTGSS_IRQMISC_DRVVBUS_FALL BIT(5) |
98 | #define USBOTGSS_IRQMISC_CHRGVBUS_FALL (1 << 4) | 98 | #define USBOTGSS_IRQMISC_CHRGVBUS_FALL BIT(4) |
99 | #define USBOTGSS_IRQMISC_DISCHRGVBUS_FALL (1 << 3) | 99 | #define USBOTGSS_IRQMISC_DISCHRGVBUS_FALL BIT(3) |
100 | #define USBOTGSS_IRQMISC_IDPULLUP_FALL (1 << 0) | 100 | #define USBOTGSS_IRQMISC_IDPULLUP_FALL BIT(0) |
101 | 101 | ||
102 | /* UTMI_OTG_STATUS REGISTER */ | 102 | /* UTMI_OTG_STATUS REGISTER */ |
103 | #define USBOTGSS_UTMI_OTG_STATUS_DRVVBUS (1 << 5) | 103 | #define USBOTGSS_UTMI_OTG_STATUS_DRVVBUS BIT(5) |
104 | #define USBOTGSS_UTMI_OTG_STATUS_CHRGVBUS (1 << 4) | 104 | #define USBOTGSS_UTMI_OTG_STATUS_CHRGVBUS BIT(4) |
105 | #define USBOTGSS_UTMI_OTG_STATUS_DISCHRGVBUS (1 << 3) | 105 | #define USBOTGSS_UTMI_OTG_STATUS_DISCHRGVBUS BIT(3) |
106 | #define USBOTGSS_UTMI_OTG_STATUS_IDPULLUP (1 << 0) | 106 | #define USBOTGSS_UTMI_OTG_STATUS_IDPULLUP BIT(0) |
107 | 107 | ||
108 | /* UTMI_OTG_CTRL REGISTER */ | 108 | /* UTMI_OTG_CTRL REGISTER */ |
109 | #define USBOTGSS_UTMI_OTG_CTRL_SW_MODE (1 << 31) | 109 | #define USBOTGSS_UTMI_OTG_CTRL_SW_MODE BIT(31) |
110 | #define USBOTGSS_UTMI_OTG_CTRL_POWERPRESENT (1 << 9) | 110 | #define USBOTGSS_UTMI_OTG_CTRL_POWERPRESENT BIT(9) |
111 | #define USBOTGSS_UTMI_OTG_CTRL_TXBITSTUFFENABLE (1 << 8) | 111 | #define USBOTGSS_UTMI_OTG_CTRL_TXBITSTUFFENABLE BIT(8) |
112 | #define USBOTGSS_UTMI_OTG_CTRL_IDDIG (1 << 4) | 112 | #define USBOTGSS_UTMI_OTG_CTRL_IDDIG BIT(4) |
113 | #define USBOTGSS_UTMI_OTG_CTRL_SESSEND (1 << 3) | 113 | #define USBOTGSS_UTMI_OTG_CTRL_SESSEND BIT(3) |
114 | #define USBOTGSS_UTMI_OTG_CTRL_SESSVALID (1 << 2) | 114 | #define USBOTGSS_UTMI_OTG_CTRL_SESSVALID BIT(2) |
115 | #define USBOTGSS_UTMI_OTG_CTRL_VBUSVALID (1 << 1) | 115 | #define USBOTGSS_UTMI_OTG_CTRL_VBUSVALID BIT(1) |
116 | 116 | ||
117 | struct dwc3_omap { | 117 | struct dwc3_omap { |
118 | struct device *dev; | 118 | struct device *dev; |
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index e689cede9b0e..a78c78e7a8c3 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c | |||
@@ -39,14 +39,13 @@ static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep); | |||
39 | static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, | 39 | static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, |
40 | struct dwc3_ep *dep, struct dwc3_request *req); | 40 | struct dwc3_ep *dep, struct dwc3_request *req); |
41 | 41 | ||
42 | static void dwc3_ep0_prepare_one_trb(struct dwc3 *dwc, u8 epnum, | 42 | static void dwc3_ep0_prepare_one_trb(struct dwc3_ep *dep, |
43 | dma_addr_t buf_dma, u32 len, u32 type, bool chain) | 43 | dma_addr_t buf_dma, u32 len, u32 type, bool chain) |
44 | { | 44 | { |
45 | struct dwc3_trb *trb; | 45 | struct dwc3_trb *trb; |
46 | struct dwc3_ep *dep; | 46 | struct dwc3 *dwc; |
47 | |||
48 | dep = dwc->eps[epnum]; | ||
49 | 47 | ||
48 | dwc = dep->dwc; | ||
50 | trb = &dwc->ep0_trb[dep->trb_enqueue]; | 49 | trb = &dwc->ep0_trb[dep->trb_enqueue]; |
51 | 50 | ||
52 | if (chain) | 51 | if (chain) |
@@ -69,16 +68,17 @@ static void dwc3_ep0_prepare_one_trb(struct dwc3 *dwc, u8 epnum, | |||
69 | trace_dwc3_prepare_trb(dep, trb); | 68 | trace_dwc3_prepare_trb(dep, trb); |
70 | } | 69 | } |
71 | 70 | ||
72 | static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum) | 71 | static int dwc3_ep0_start_trans(struct dwc3_ep *dep) |
73 | { | 72 | { |
74 | struct dwc3_gadget_ep_cmd_params params; | 73 | struct dwc3_gadget_ep_cmd_params params; |
75 | struct dwc3_ep *dep; | 74 | struct dwc3 *dwc; |
76 | int ret; | 75 | int ret; |
77 | 76 | ||
78 | dep = dwc->eps[epnum]; | ||
79 | if (dep->flags & DWC3_EP_BUSY) | 77 | if (dep->flags & DWC3_EP_BUSY) |
80 | return 0; | 78 | return 0; |
81 | 79 | ||
80 | dwc = dep->dwc; | ||
81 | |||
82 | memset(¶ms, 0, sizeof(params)); | 82 | memset(¶ms, 0, sizeof(params)); |
83 | params.param0 = upper_32_bits(dwc->ep0_trb_addr); | 83 | params.param0 = upper_32_bits(dwc->ep0_trb_addr); |
84 | params.param1 = lower_32_bits(dwc->ep0_trb_addr); | 84 | params.param1 = lower_32_bits(dwc->ep0_trb_addr); |
@@ -279,13 +279,15 @@ int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value) | |||
279 | 279 | ||
280 | void dwc3_ep0_out_start(struct dwc3 *dwc) | 280 | void dwc3_ep0_out_start(struct dwc3 *dwc) |
281 | { | 281 | { |
282 | struct dwc3_ep *dep; | ||
282 | int ret; | 283 | int ret; |
283 | 284 | ||
284 | complete(&dwc->ep0_in_setup); | 285 | complete(&dwc->ep0_in_setup); |
285 | 286 | ||
286 | dwc3_ep0_prepare_one_trb(dwc, 0, dwc->ctrl_req_addr, 8, | 287 | dep = dwc->eps[0]; |
288 | dwc3_ep0_prepare_one_trb(dep, dwc->ep0_trb_addr, 8, | ||
287 | DWC3_TRBCTL_CONTROL_SETUP, false); | 289 | DWC3_TRBCTL_CONTROL_SETUP, false); |
288 | ret = dwc3_ep0_start_trans(dwc, 0); | 290 | ret = dwc3_ep0_start_trans(dep); |
289 | WARN_ON(ret < 0); | 291 | WARN_ON(ret < 0); |
290 | } | 292 | } |
291 | 293 | ||
@@ -794,7 +796,7 @@ static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) | |||
794 | static void dwc3_ep0_inspect_setup(struct dwc3 *dwc, | 796 | static void dwc3_ep0_inspect_setup(struct dwc3 *dwc, |
795 | const struct dwc3_event_depevt *event) | 797 | const struct dwc3_event_depevt *event) |
796 | { | 798 | { |
797 | struct usb_ctrlrequest *ctrl = dwc->ctrl_req; | 799 | struct usb_ctrlrequest *ctrl = (void *) dwc->ep0_trb; |
798 | int ret = -EINVAL; | 800 | int ret = -EINVAL; |
799 | u32 len; | 801 | u32 len; |
800 | 802 | ||
@@ -834,7 +836,6 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, | |||
834 | struct usb_request *ur; | 836 | struct usb_request *ur; |
835 | struct dwc3_trb *trb; | 837 | struct dwc3_trb *trb; |
836 | struct dwc3_ep *ep0; | 838 | struct dwc3_ep *ep0; |
837 | unsigned transfer_size = 0; | ||
838 | unsigned maxp; | 839 | unsigned maxp; |
839 | unsigned remaining_ur_length; | 840 | unsigned remaining_ur_length; |
840 | void *buf; | 841 | void *buf; |
@@ -847,9 +848,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, | |||
847 | ep0 = dwc->eps[0]; | 848 | ep0 = dwc->eps[0]; |
848 | 849 | ||
849 | dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS; | 850 | dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS; |
850 | |||
851 | trb = dwc->ep0_trb; | 851 | trb = dwc->ep0_trb; |
852 | |||
853 | trace_dwc3_complete_trb(ep0, trb); | 852 | trace_dwc3_complete_trb(ep0, trb); |
854 | 853 | ||
855 | r = next_request(&ep0->pending_list); | 854 | r = next_request(&ep0->pending_list); |
@@ -870,58 +869,23 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, | |||
870 | remaining_ur_length = ur->length; | 869 | remaining_ur_length = ur->length; |
871 | 870 | ||
872 | length = trb->size & DWC3_TRB_SIZE_MASK; | 871 | length = trb->size & DWC3_TRB_SIZE_MASK; |
873 | |||
874 | maxp = ep0->endpoint.maxpacket; | 872 | maxp = ep0->endpoint.maxpacket; |
875 | 873 | transferred = ur->length - length; | |
876 | if (dwc->ep0_bounced) { | ||
877 | /* | ||
878 | * Handle the first TRB before handling the bounce buffer if | ||
879 | * the request length is greater than the bounce buffer size | ||
880 | */ | ||
881 | if (ur->length > DWC3_EP0_BOUNCE_SIZE) { | ||
882 | transfer_size = ALIGN(ur->length - maxp, maxp); | ||
883 | transferred = transfer_size - length; | ||
884 | buf = (u8 *)buf + transferred; | ||
885 | ur->actual += transferred; | ||
886 | remaining_ur_length -= transferred; | ||
887 | |||
888 | trb++; | ||
889 | length = trb->size & DWC3_TRB_SIZE_MASK; | ||
890 | |||
891 | ep0->trb_enqueue = 0; | ||
892 | } | ||
893 | |||
894 | transfer_size = roundup((ur->length - transfer_size), | ||
895 | maxp); | ||
896 | |||
897 | transferred = min_t(u32, remaining_ur_length, | ||
898 | transfer_size - length); | ||
899 | memcpy(buf, dwc->ep0_bounce, transferred); | ||
900 | } else { | ||
901 | transferred = ur->length - length; | ||
902 | } | ||
903 | |||
904 | ur->actual += transferred; | 874 | ur->actual += transferred; |
905 | 875 | ||
906 | if ((epnum & 1) && ur->actual < ur->length) { | 876 | if ((IS_ALIGNED(ur->length, ep0->endpoint.maxpacket) && |
907 | /* for some reason we did not get everything out */ | 877 | ur->length && ur->zero) || dwc->ep0_bounced) { |
878 | trb++; | ||
879 | trb->ctrl &= ~DWC3_TRB_CTRL_HWO; | ||
880 | trace_dwc3_complete_trb(ep0, trb); | ||
881 | ep0->trb_enqueue = 0; | ||
882 | dwc->ep0_bounced = false; | ||
883 | } | ||
908 | 884 | ||
885 | if ((epnum & 1) && ur->actual < ur->length) | ||
909 | dwc3_ep0_stall_and_restart(dwc); | 886 | dwc3_ep0_stall_and_restart(dwc); |
910 | } else { | 887 | else |
911 | dwc3_gadget_giveback(ep0, r, 0); | 888 | dwc3_gadget_giveback(ep0, r, 0); |
912 | |||
913 | if (IS_ALIGNED(ur->length, ep0->endpoint.maxpacket) && | ||
914 | ur->length && ur->zero) { | ||
915 | int ret; | ||
916 | |||
917 | dwc->ep0_next_event = DWC3_EP0_COMPLETE; | ||
918 | |||
919 | dwc3_ep0_prepare_one_trb(dwc, epnum, dwc->ctrl_req_addr, | ||
920 | 0, DWC3_TRBCTL_CONTROL_DATA, false); | ||
921 | ret = dwc3_ep0_start_trans(dwc, epnum); | ||
922 | WARN_ON(ret < 0); | ||
923 | } | ||
924 | } | ||
925 | } | 889 | } |
926 | 890 | ||
927 | static void dwc3_ep0_complete_status(struct dwc3 *dwc, | 891 | static void dwc3_ep0_complete_status(struct dwc3 *dwc, |
@@ -997,14 +961,13 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, | |||
997 | req->direction = !!dep->number; | 961 | req->direction = !!dep->number; |
998 | 962 | ||
999 | if (req->request.length == 0) { | 963 | if (req->request.length == 0) { |
1000 | dwc3_ep0_prepare_one_trb(dwc, dep->number, | 964 | dwc3_ep0_prepare_one_trb(dep, dwc->ep0_trb_addr, 0, |
1001 | dwc->ctrl_req_addr, 0, | ||
1002 | DWC3_TRBCTL_CONTROL_DATA, false); | 965 | DWC3_TRBCTL_CONTROL_DATA, false); |
1003 | ret = dwc3_ep0_start_trans(dwc, dep->number); | 966 | ret = dwc3_ep0_start_trans(dep); |
1004 | } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket) | 967 | } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket) |
1005 | && (dep->number == 0)) { | 968 | && (dep->number == 0)) { |
1006 | u32 transfer_size = 0; | ||
1007 | u32 maxpacket; | 969 | u32 maxpacket; |
970 | u32 rem; | ||
1008 | 971 | ||
1009 | ret = usb_gadget_map_request_by_dev(dwc->sysdev, | 972 | ret = usb_gadget_map_request_by_dev(dwc->sysdev, |
1010 | &req->request, dep->number); | 973 | &req->request, dep->number); |
@@ -1012,36 +975,55 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, | |||
1012 | return; | 975 | return; |
1013 | 976 | ||
1014 | maxpacket = dep->endpoint.maxpacket; | 977 | maxpacket = dep->endpoint.maxpacket; |
978 | rem = req->request.length % maxpacket; | ||
979 | dwc->ep0_bounced = true; | ||
1015 | 980 | ||
1016 | if (req->request.length > DWC3_EP0_BOUNCE_SIZE) { | 981 | /* prepare normal TRB */ |
1017 | transfer_size = ALIGN(req->request.length - maxpacket, | 982 | dwc3_ep0_prepare_one_trb(dep, req->request.dma, |
1018 | maxpacket); | 983 | req->request.length, |
1019 | dwc3_ep0_prepare_one_trb(dwc, dep->number, | 984 | DWC3_TRBCTL_CONTROL_DATA, |
1020 | req->request.dma, | 985 | true); |
1021 | transfer_size, | 986 | |
1022 | DWC3_TRBCTL_CONTROL_DATA, | 987 | /* Now prepare one extra TRB to align transfer size */ |
1023 | true); | 988 | dwc3_ep0_prepare_one_trb(dep, dwc->bounce_addr, |
1024 | } | 989 | maxpacket - rem, |
1025 | 990 | DWC3_TRBCTL_CONTROL_DATA, | |
1026 | transfer_size = roundup((req->request.length - transfer_size), | 991 | false); |
1027 | maxpacket); | 992 | ret = dwc3_ep0_start_trans(dep); |
993 | } else if (IS_ALIGNED(req->request.length, dep->endpoint.maxpacket) && | ||
994 | req->request.length && req->request.zero) { | ||
995 | u32 maxpacket; | ||
996 | u32 rem; | ||
1028 | 997 | ||
1029 | dwc->ep0_bounced = true; | 998 | ret = usb_gadget_map_request_by_dev(dwc->sysdev, |
999 | &req->request, dep->number); | ||
1000 | if (ret) | ||
1001 | return; | ||
1030 | 1002 | ||
1031 | dwc3_ep0_prepare_one_trb(dwc, dep->number, | 1003 | maxpacket = dep->endpoint.maxpacket; |
1032 | dwc->ep0_bounce_addr, transfer_size, | 1004 | rem = req->request.length % maxpacket; |
1033 | DWC3_TRBCTL_CONTROL_DATA, false); | 1005 | |
1034 | ret = dwc3_ep0_start_trans(dwc, dep->number); | 1006 | /* prepare normal TRB */ |
1007 | dwc3_ep0_prepare_one_trb(dep, req->request.dma, | ||
1008 | req->request.length, | ||
1009 | DWC3_TRBCTL_CONTROL_DATA, | ||
1010 | true); | ||
1011 | |||
1012 | /* Now prepare one extra TRB to align transfer size */ | ||
1013 | dwc3_ep0_prepare_one_trb(dep, dwc->bounce_addr, | ||
1014 | 0, DWC3_TRBCTL_CONTROL_DATA, | ||
1015 | false); | ||
1016 | ret = dwc3_ep0_start_trans(dep); | ||
1035 | } else { | 1017 | } else { |
1036 | ret = usb_gadget_map_request_by_dev(dwc->sysdev, | 1018 | ret = usb_gadget_map_request_by_dev(dwc->sysdev, |
1037 | &req->request, dep->number); | 1019 | &req->request, dep->number); |
1038 | if (ret) | 1020 | if (ret) |
1039 | return; | 1021 | return; |
1040 | 1022 | ||
1041 | dwc3_ep0_prepare_one_trb(dwc, dep->number, req->request.dma, | 1023 | dwc3_ep0_prepare_one_trb(dep, req->request.dma, |
1042 | req->request.length, DWC3_TRBCTL_CONTROL_DATA, | 1024 | req->request.length, DWC3_TRBCTL_CONTROL_DATA, |
1043 | false); | 1025 | false); |
1044 | ret = dwc3_ep0_start_trans(dwc, dep->number); | 1026 | ret = dwc3_ep0_start_trans(dep); |
1045 | } | 1027 | } |
1046 | 1028 | ||
1047 | WARN_ON(ret < 0); | 1029 | WARN_ON(ret < 0); |
@@ -1055,9 +1037,8 @@ static int dwc3_ep0_start_control_status(struct dwc3_ep *dep) | |||
1055 | type = dwc->three_stage_setup ? DWC3_TRBCTL_CONTROL_STATUS3 | 1037 | type = dwc->three_stage_setup ? DWC3_TRBCTL_CONTROL_STATUS3 |
1056 | : DWC3_TRBCTL_CONTROL_STATUS2; | 1038 | : DWC3_TRBCTL_CONTROL_STATUS2; |
1057 | 1039 | ||
1058 | dwc3_ep0_prepare_one_trb(dwc, dep->number, | 1040 | dwc3_ep0_prepare_one_trb(dep, dwc->ep0_trb_addr, 0, type, false); |
1059 | dwc->ctrl_req_addr, 0, type, false); | 1041 | return dwc3_ep0_start_trans(dep); |
1060 | return dwc3_ep0_start_trans(dwc, dep->number); | ||
1061 | } | 1042 | } |
1062 | 1043 | ||
1063 | static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep) | 1044 | static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep) |
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 79e7a3480d51..6f6f0b3be3ad 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c | |||
@@ -171,7 +171,6 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, | |||
171 | int status) | 171 | int status) |
172 | { | 172 | { |
173 | struct dwc3 *dwc = dep->dwc; | 173 | struct dwc3 *dwc = dep->dwc; |
174 | unsigned int unmap_after_complete = false; | ||
175 | 174 | ||
176 | req->started = false; | 175 | req->started = false; |
177 | list_del(&req->list); | 176 | list_del(&req->list); |
@@ -181,19 +180,8 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, | |||
181 | if (req->request.status == -EINPROGRESS) | 180 | if (req->request.status == -EINPROGRESS) |
182 | req->request.status = status; | 181 | req->request.status = status; |
183 | 182 | ||
184 | /* | 183 | usb_gadget_unmap_request_by_dev(dwc->sysdev, |
185 | * NOTICE we don't want to unmap before calling ->complete() if we're | 184 | &req->request, req->direction); |
186 | * dealing with a bounced ep0 request. If we unmap it here, we would end | ||
187 | * up overwritting the contents of req->buf and this could confuse the | ||
188 | * gadget driver. | ||
189 | */ | ||
190 | if (dwc->ep0_bounced && dep->number <= 1) { | ||
191 | dwc->ep0_bounced = false; | ||
192 | unmap_after_complete = true; | ||
193 | } else { | ||
194 | usb_gadget_unmap_request_by_dev(dwc->sysdev, | ||
195 | &req->request, req->direction); | ||
196 | } | ||
197 | 185 | ||
198 | trace_dwc3_gadget_giveback(req); | 186 | trace_dwc3_gadget_giveback(req); |
199 | 187 | ||
@@ -201,10 +189,6 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, | |||
201 | usb_gadget_giveback_request(&dep->endpoint, &req->request); | 189 | usb_gadget_giveback_request(&dep->endpoint, &req->request); |
202 | spin_lock(&dwc->lock); | 190 | spin_lock(&dwc->lock); |
203 | 191 | ||
204 | if (unmap_after_complete) | ||
205 | usb_gadget_unmap_request_by_dev(dwc->sysdev, | ||
206 | &req->request, req->direction); | ||
207 | |||
208 | if (dep->number > 1) | 192 | if (dep->number > 1) |
209 | pm_runtime_put(dwc->dev); | 193 | pm_runtime_put(dwc->dev); |
210 | } | 194 | } |
@@ -1060,6 +1044,22 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, | |||
1060 | false, 0, req->request.stream_id, | 1044 | false, 0, req->request.stream_id, |
1061 | req->request.short_not_ok, | 1045 | req->request.short_not_ok, |
1062 | req->request.no_interrupt); | 1046 | req->request.no_interrupt); |
1047 | } else if (req->request.zero && req->request.length && | ||
1048 | (IS_ALIGNED(req->request.length,dep->endpoint.maxpacket))) { | ||
1049 | struct dwc3 *dwc = dep->dwc; | ||
1050 | struct dwc3_trb *trb; | ||
1051 | |||
1052 | req->zero = true; | ||
1053 | |||
1054 | /* prepare normal TRB */ | ||
1055 | dwc3_prepare_one_trb(dep, req, true, 0); | ||
1056 | |||
1057 | /* Now prepare one extra TRB to handle ZLP */ | ||
1058 | trb = &dep->trb_pool[dep->trb_enqueue]; | ||
1059 | __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0, | ||
1060 | false, 0, req->request.stream_id, | ||
1061 | req->request.short_not_ok, | ||
1062 | req->request.no_interrupt); | ||
1063 | } else { | 1063 | } else { |
1064 | dwc3_prepare_one_trb(dep, req, false, 0); | 1064 | dwc3_prepare_one_trb(dep, req, false, 0); |
1065 | } | 1065 | } |
@@ -1184,8 +1184,11 @@ static void __dwc3_gadget_start_isoc(struct dwc3 *dwc, | |||
1184 | return; | 1184 | return; |
1185 | } | 1185 | } |
1186 | 1186 | ||
1187 | /* 4 micro frames in the future */ | 1187 | /* |
1188 | uf = cur_uf + dep->interval * 4; | 1188 | * Schedule the first trb for one interval in the future or at |
1189 | * least 4 microframes. | ||
1190 | */ | ||
1191 | uf = cur_uf + max_t(u32, 4, dep->interval); | ||
1189 | 1192 | ||
1190 | __dwc3_gadget_kick_transfer(dep, uf); | 1193 | __dwc3_gadget_kick_transfer(dep, uf); |
1191 | } | 1194 | } |
@@ -1272,31 +1275,6 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) | |||
1272 | return ret; | 1275 | return ret; |
1273 | } | 1276 | } |
1274 | 1277 | ||
1275 | static void __dwc3_gadget_ep_zlp_complete(struct usb_ep *ep, | ||
1276 | struct usb_request *request) | ||
1277 | { | ||
1278 | dwc3_gadget_ep_free_request(ep, request); | ||
1279 | } | ||
1280 | |||
1281 | static int __dwc3_gadget_ep_queue_zlp(struct dwc3 *dwc, struct dwc3_ep *dep) | ||
1282 | { | ||
1283 | struct dwc3_request *req; | ||
1284 | struct usb_request *request; | ||
1285 | struct usb_ep *ep = &dep->endpoint; | ||
1286 | |||
1287 | request = dwc3_gadget_ep_alloc_request(ep, GFP_ATOMIC); | ||
1288 | if (!request) | ||
1289 | return -ENOMEM; | ||
1290 | |||
1291 | request->length = 0; | ||
1292 | request->buf = dwc->zlp_buf; | ||
1293 | request->complete = __dwc3_gadget_ep_zlp_complete; | ||
1294 | |||
1295 | req = to_dwc3_request(request); | ||
1296 | |||
1297 | return __dwc3_gadget_ep_queue(dep, req); | ||
1298 | } | ||
1299 | |||
1300 | static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, | 1278 | static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, |
1301 | gfp_t gfp_flags) | 1279 | gfp_t gfp_flags) |
1302 | { | 1280 | { |
@@ -1310,17 +1288,6 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, | |||
1310 | 1288 | ||
1311 | spin_lock_irqsave(&dwc->lock, flags); | 1289 | spin_lock_irqsave(&dwc->lock, flags); |
1312 | ret = __dwc3_gadget_ep_queue(dep, req); | 1290 | ret = __dwc3_gadget_ep_queue(dep, req); |
1313 | |||
1314 | /* | ||
1315 | * Okay, here's the thing, if gadget driver has requested for a ZLP by | ||
1316 | * setting request->zero, instead of doing magic, we will just queue an | ||
1317 | * extra usb_request ourselves so that it gets handled the same way as | ||
1318 | * any other request. | ||
1319 | */ | ||
1320 | if (ret == 0 && request->zero && request->length && | ||
1321 | (request->length % ep->maxpacket == 0)) | ||
1322 | ret = __dwc3_gadget_ep_queue_zlp(dwc, dep); | ||
1323 | |||
1324 | spin_unlock_irqrestore(&dwc->lock, flags); | 1291 | spin_unlock_irqrestore(&dwc->lock, flags); |
1325 | 1292 | ||
1326 | return ret; | 1293 | return ret; |
@@ -1400,7 +1367,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, | |||
1400 | dwc3_ep_inc_deq(dep); | 1367 | dwc3_ep_inc_deq(dep); |
1401 | } | 1368 | } |
1402 | 1369 | ||
1403 | if (r->unaligned) { | 1370 | if (r->unaligned || r->zero) { |
1404 | trb = r->trb + r->num_pending_sgs + 1; | 1371 | trb = r->trb + r->num_pending_sgs + 1; |
1405 | trb->ctrl &= ~DWC3_TRB_CTRL_HWO; | 1372 | trb->ctrl &= ~DWC3_TRB_CTRL_HWO; |
1406 | dwc3_ep_inc_deq(dep); | 1373 | dwc3_ep_inc_deq(dep); |
@@ -1411,7 +1378,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, | |||
1411 | trb->ctrl &= ~DWC3_TRB_CTRL_HWO; | 1378 | trb->ctrl &= ~DWC3_TRB_CTRL_HWO; |
1412 | dwc3_ep_inc_deq(dep); | 1379 | dwc3_ep_inc_deq(dep); |
1413 | 1380 | ||
1414 | if (r->unaligned) { | 1381 | if (r->unaligned || r->zero) { |
1415 | trb = r->trb + 1; | 1382 | trb = r->trb + 1; |
1416 | trb->ctrl &= ~DWC3_TRB_CTRL_HWO; | 1383 | trb->ctrl &= ~DWC3_TRB_CTRL_HWO; |
1417 | dwc3_ep_inc_deq(dep); | 1384 | dwc3_ep_inc_deq(dep); |
@@ -2006,14 +1973,15 @@ static const struct usb_gadget_ops dwc3_gadget_ops = { | |||
2006 | 1973 | ||
2007 | /* -------------------------------------------------------------------------- */ | 1974 | /* -------------------------------------------------------------------------- */ |
2008 | 1975 | ||
2009 | static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc, | 1976 | static int dwc3_gadget_init_endpoints(struct dwc3 *dwc, u8 num) |
2010 | u8 num, u32 direction) | ||
2011 | { | 1977 | { |
2012 | struct dwc3_ep *dep; | 1978 | struct dwc3_ep *dep; |
2013 | u8 i; | 1979 | u8 epnum; |
1980 | |||
1981 | INIT_LIST_HEAD(&dwc->gadget.ep_list); | ||
2014 | 1982 | ||
2015 | for (i = 0; i < num; i++) { | 1983 | for (epnum = 0; epnum < num; epnum++) { |
2016 | u8 epnum = (i << 1) | (direction ? 1 : 0); | 1984 | bool direction = epnum & 1; |
2017 | 1985 | ||
2018 | dep = kzalloc(sizeof(*dep), GFP_KERNEL); | 1986 | dep = kzalloc(sizeof(*dep), GFP_KERNEL); |
2019 | if (!dep) | 1987 | if (!dep) |
@@ -2021,12 +1989,12 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc, | |||
2021 | 1989 | ||
2022 | dep->dwc = dwc; | 1990 | dep->dwc = dwc; |
2023 | dep->number = epnum; | 1991 | dep->number = epnum; |
2024 | dep->direction = !!direction; | 1992 | dep->direction = direction; |
2025 | dep->regs = dwc->regs + DWC3_DEP_BASE(epnum); | 1993 | dep->regs = dwc->regs + DWC3_DEP_BASE(epnum); |
2026 | dwc->eps[epnum] = dep; | 1994 | dwc->eps[epnum] = dep; |
2027 | 1995 | ||
2028 | snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1, | 1996 | snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1, |
2029 | (epnum & 1) ? "in" : "out"); | 1997 | direction ? "in" : "out"); |
2030 | 1998 | ||
2031 | dep->endpoint.name = dep->name; | 1999 | dep->endpoint.name = dep->name; |
2032 | 2000 | ||
@@ -2053,7 +2021,7 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc, | |||
2053 | /* MDWIDTH is represented in bits, we need it in bytes */ | 2021 | /* MDWIDTH is represented in bits, we need it in bytes */ |
2054 | mdwidth /= 8; | 2022 | mdwidth /= 8; |
2055 | 2023 | ||
2056 | size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(i)); | 2024 | size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(epnum >> 1)); |
2057 | size = DWC3_GTXFIFOSIZ_TXFDEF(size); | 2025 | size = DWC3_GTXFIFOSIZ_TXFDEF(size); |
2058 | 2026 | ||
2059 | /* FIFO Depth is in MDWDITH bytes. Multiply */ | 2027 | /* FIFO Depth is in MDWDITH bytes. Multiply */ |
@@ -2103,7 +2071,7 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc, | |||
2103 | dep->endpoint.caps.type_int = true; | 2071 | dep->endpoint.caps.type_int = true; |
2104 | } | 2072 | } |
2105 | 2073 | ||
2106 | dep->endpoint.caps.dir_in = !!direction; | 2074 | dep->endpoint.caps.dir_in = direction; |
2107 | dep->endpoint.caps.dir_out = !direction; | 2075 | dep->endpoint.caps.dir_out = !direction; |
2108 | 2076 | ||
2109 | INIT_LIST_HEAD(&dep->pending_list); | 2077 | INIT_LIST_HEAD(&dep->pending_list); |
@@ -2113,27 +2081,6 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc, | |||
2113 | return 0; | 2081 | return 0; |
2114 | } | 2082 | } |
2115 | 2083 | ||
2116 | static int dwc3_gadget_init_endpoints(struct dwc3 *dwc) | ||
2117 | { | ||
2118 | int ret; | ||
2119 | |||
2120 | INIT_LIST_HEAD(&dwc->gadget.ep_list); | ||
2121 | |||
2122 | ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_out_eps, 0); | ||
2123 | if (ret < 0) { | ||
2124 | dev_err(dwc->dev, "failed to initialize OUT endpoints\n"); | ||
2125 | return ret; | ||
2126 | } | ||
2127 | |||
2128 | ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_in_eps, 1); | ||
2129 | if (ret < 0) { | ||
2130 | dev_err(dwc->dev, "failed to initialize IN endpoints\n"); | ||
2131 | return ret; | ||
2132 | } | ||
2133 | |||
2134 | return 0; | ||
2135 | } | ||
2136 | |||
2137 | static void dwc3_gadget_free_endpoints(struct dwc3 *dwc) | 2084 | static void dwc3_gadget_free_endpoints(struct dwc3 *dwc) |
2138 | { | 2085 | { |
2139 | struct dwc3_ep *dep; | 2086 | struct dwc3_ep *dep; |
@@ -2197,7 +2144,7 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep, | |||
2197 | * with one TRB pending in the ring. We need to manually clear HWO bit | 2144 | * with one TRB pending in the ring. We need to manually clear HWO bit |
2198 | * from that TRB. | 2145 | * from that TRB. |
2199 | */ | 2146 | */ |
2200 | if (req->unaligned && (trb->ctrl & DWC3_TRB_CTRL_HWO)) { | 2147 | if ((req->zero || req->unaligned) && (trb->ctrl & DWC3_TRB_CTRL_HWO)) { |
2201 | trb->ctrl &= ~DWC3_TRB_CTRL_HWO; | 2148 | trb->ctrl &= ~DWC3_TRB_CTRL_HWO; |
2202 | return 1; | 2149 | return 1; |
2203 | } | 2150 | } |
@@ -2291,11 +2238,12 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, | |||
2291 | event, status, chain); | 2238 | event, status, chain); |
2292 | } | 2239 | } |
2293 | 2240 | ||
2294 | if (req->unaligned) { | 2241 | if (req->unaligned || req->zero) { |
2295 | trb = &dep->trb_pool[dep->trb_dequeue]; | 2242 | trb = &dep->trb_pool[dep->trb_dequeue]; |
2296 | ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb, | 2243 | ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb, |
2297 | event, status, false); | 2244 | event, status, false); |
2298 | req->unaligned = false; | 2245 | req->unaligned = false; |
2246 | req->zero = false; | ||
2299 | } | 2247 | } |
2300 | 2248 | ||
2301 | req->request.actual = length - req->remaining; | 2249 | req->request.actual = length - req->remaining; |
@@ -3161,49 +3109,26 @@ int dwc3_gadget_init(struct dwc3 *dwc) | |||
3161 | 3109 | ||
3162 | dwc->irq_gadget = irq; | 3110 | dwc->irq_gadget = irq; |
3163 | 3111 | ||
3164 | dwc->ctrl_req = dma_alloc_coherent(dwc->sysdev, sizeof(*dwc->ctrl_req), | ||
3165 | &dwc->ctrl_req_addr, GFP_KERNEL); | ||
3166 | if (!dwc->ctrl_req) { | ||
3167 | dev_err(dwc->dev, "failed to allocate ctrl request\n"); | ||
3168 | ret = -ENOMEM; | ||
3169 | goto err0; | ||
3170 | } | ||
3171 | |||
3172 | dwc->ep0_trb = dma_alloc_coherent(dwc->sysdev, | 3112 | dwc->ep0_trb = dma_alloc_coherent(dwc->sysdev, |
3173 | sizeof(*dwc->ep0_trb) * 2, | 3113 | sizeof(*dwc->ep0_trb) * 2, |
3174 | &dwc->ep0_trb_addr, GFP_KERNEL); | 3114 | &dwc->ep0_trb_addr, GFP_KERNEL); |
3175 | if (!dwc->ep0_trb) { | 3115 | if (!dwc->ep0_trb) { |
3176 | dev_err(dwc->dev, "failed to allocate ep0 trb\n"); | 3116 | dev_err(dwc->dev, "failed to allocate ep0 trb\n"); |
3177 | ret = -ENOMEM; | 3117 | ret = -ENOMEM; |
3178 | goto err1; | 3118 | goto err0; |
3179 | } | 3119 | } |
3180 | 3120 | ||
3181 | dwc->setup_buf = kzalloc(DWC3_EP0_BOUNCE_SIZE, GFP_KERNEL); | 3121 | dwc->setup_buf = kzalloc(DWC3_EP0_SETUP_SIZE, GFP_KERNEL); |
3182 | if (!dwc->setup_buf) { | 3122 | if (!dwc->setup_buf) { |
3183 | ret = -ENOMEM; | 3123 | ret = -ENOMEM; |
3184 | goto err2; | 3124 | goto err1; |
3185 | } | ||
3186 | |||
3187 | dwc->ep0_bounce = dma_alloc_coherent(dwc->sysdev, | ||
3188 | DWC3_EP0_BOUNCE_SIZE, &dwc->ep0_bounce_addr, | ||
3189 | GFP_KERNEL); | ||
3190 | if (!dwc->ep0_bounce) { | ||
3191 | dev_err(dwc->dev, "failed to allocate ep0 bounce buffer\n"); | ||
3192 | ret = -ENOMEM; | ||
3193 | goto err3; | ||
3194 | } | ||
3195 | |||
3196 | dwc->zlp_buf = kzalloc(DWC3_ZLP_BUF_SIZE, GFP_KERNEL); | ||
3197 | if (!dwc->zlp_buf) { | ||
3198 | ret = -ENOMEM; | ||
3199 | goto err4; | ||
3200 | } | 3125 | } |
3201 | 3126 | ||
3202 | dwc->bounce = dma_alloc_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, | 3127 | dwc->bounce = dma_alloc_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, |
3203 | &dwc->bounce_addr, GFP_KERNEL); | 3128 | &dwc->bounce_addr, GFP_KERNEL); |
3204 | if (!dwc->bounce) { | 3129 | if (!dwc->bounce) { |
3205 | ret = -ENOMEM; | 3130 | ret = -ENOMEM; |
3206 | goto err5; | 3131 | goto err2; |
3207 | } | 3132 | } |
3208 | 3133 | ||
3209 | init_completion(&dwc->ep0_in_setup); | 3134 | init_completion(&dwc->ep0_in_setup); |
@@ -3241,39 +3166,31 @@ int dwc3_gadget_init(struct dwc3 *dwc) | |||
3241 | * sure we're starting from a well known location. | 3166 | * sure we're starting from a well known location. |
3242 | */ | 3167 | */ |
3243 | 3168 | ||
3244 | ret = dwc3_gadget_init_endpoints(dwc); | 3169 | ret = dwc3_gadget_init_endpoints(dwc, dwc->num_eps); |
3245 | if (ret) | 3170 | if (ret) |
3246 | goto err6; | 3171 | goto err3; |
3247 | 3172 | ||
3248 | ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget); | 3173 | ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget); |
3249 | if (ret) { | 3174 | if (ret) { |
3250 | dev_err(dwc->dev, "failed to register udc\n"); | 3175 | dev_err(dwc->dev, "failed to register udc\n"); |
3251 | goto err6; | 3176 | goto err4; |
3252 | } | 3177 | } |
3253 | 3178 | ||
3254 | return 0; | 3179 | return 0; |
3255 | err6: | ||
3256 | dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce, | ||
3257 | dwc->bounce_addr); | ||
3258 | |||
3259 | err5: | ||
3260 | kfree(dwc->zlp_buf); | ||
3261 | 3180 | ||
3262 | err4: | 3181 | err4: |
3263 | dwc3_gadget_free_endpoints(dwc); | 3182 | dwc3_gadget_free_endpoints(dwc); |
3264 | dma_free_coherent(dwc->sysdev, DWC3_EP0_BOUNCE_SIZE, | ||
3265 | dwc->ep0_bounce, dwc->ep0_bounce_addr); | ||
3266 | 3183 | ||
3267 | err3: | 3184 | err3: |
3268 | kfree(dwc->setup_buf); | 3185 | dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce, |
3186 | dwc->bounce_addr); | ||
3269 | 3187 | ||
3270 | err2: | 3188 | err2: |
3271 | dma_free_coherent(dwc->sysdev, sizeof(*dwc->ep0_trb) * 2, | 3189 | kfree(dwc->setup_buf); |
3272 | dwc->ep0_trb, dwc->ep0_trb_addr); | ||
3273 | 3190 | ||
3274 | err1: | 3191 | err1: |
3275 | dma_free_coherent(dwc->sysdev, sizeof(*dwc->ctrl_req), | 3192 | dma_free_coherent(dwc->sysdev, sizeof(*dwc->ep0_trb) * 2, |
3276 | dwc->ctrl_req, dwc->ctrl_req_addr); | 3193 | dwc->ep0_trb, dwc->ep0_trb_addr); |
3277 | 3194 | ||
3278 | err0: | 3195 | err0: |
3279 | return ret; | 3196 | return ret; |
@@ -3284,22 +3201,12 @@ err0: | |||
3284 | void dwc3_gadget_exit(struct dwc3 *dwc) | 3201 | void dwc3_gadget_exit(struct dwc3 *dwc) |
3285 | { | 3202 | { |
3286 | usb_del_gadget_udc(&dwc->gadget); | 3203 | usb_del_gadget_udc(&dwc->gadget); |
3287 | |||
3288 | dwc3_gadget_free_endpoints(dwc); | 3204 | dwc3_gadget_free_endpoints(dwc); |
3289 | |||
3290 | dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce, | 3205 | dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce, |
3291 | dwc->bounce_addr); | 3206 | dwc->bounce_addr); |
3292 | dma_free_coherent(dwc->sysdev, DWC3_EP0_BOUNCE_SIZE, | ||
3293 | dwc->ep0_bounce, dwc->ep0_bounce_addr); | ||
3294 | |||
3295 | kfree(dwc->setup_buf); | 3207 | kfree(dwc->setup_buf); |
3296 | kfree(dwc->zlp_buf); | ||
3297 | |||
3298 | dma_free_coherent(dwc->sysdev, sizeof(*dwc->ep0_trb) * 2, | 3208 | dma_free_coherent(dwc->sysdev, sizeof(*dwc->ep0_trb) * 2, |
3299 | dwc->ep0_trb, dwc->ep0_trb_addr); | 3209 | dwc->ep0_trb, dwc->ep0_trb_addr); |
3300 | |||
3301 | dma_free_coherent(dwc->sysdev, sizeof(*dwc->ctrl_req), | ||
3302 | dwc->ctrl_req, dwc->ctrl_req_addr); | ||
3303 | } | 3210 | } |
3304 | 3211 | ||
3305 | int dwc3_gadget_suspend(struct dwc3 *dwc) | 3212 | int dwc3_gadget_suspend(struct dwc3 *dwc) |
diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h index 265e223ab645..e4602d0e515b 100644 --- a/drivers/usb/dwc3/gadget.h +++ b/drivers/usb/dwc3/gadget.h | |||
@@ -29,16 +29,16 @@ struct dwc3; | |||
29 | 29 | ||
30 | /* DEPCFG parameter 1 */ | 30 | /* DEPCFG parameter 1 */ |
31 | #define DWC3_DEPCFG_INT_NUM(n) (((n) & 0x1f) << 0) | 31 | #define DWC3_DEPCFG_INT_NUM(n) (((n) & 0x1f) << 0) |
32 | #define DWC3_DEPCFG_XFER_COMPLETE_EN (1 << 8) | 32 | #define DWC3_DEPCFG_XFER_COMPLETE_EN BIT(8) |
33 | #define DWC3_DEPCFG_XFER_IN_PROGRESS_EN (1 << 9) | 33 | #define DWC3_DEPCFG_XFER_IN_PROGRESS_EN BIT(9) |
34 | #define DWC3_DEPCFG_XFER_NOT_READY_EN (1 << 10) | 34 | #define DWC3_DEPCFG_XFER_NOT_READY_EN BIT(10) |
35 | #define DWC3_DEPCFG_FIFO_ERROR_EN (1 << 11) | 35 | #define DWC3_DEPCFG_FIFO_ERROR_EN BIT(11) |
36 | #define DWC3_DEPCFG_STREAM_EVENT_EN (1 << 13) | 36 | #define DWC3_DEPCFG_STREAM_EVENT_EN BIT(12) |
37 | #define DWC3_DEPCFG_BINTERVAL_M1(n) (((n) & 0xff) << 16) | 37 | #define DWC3_DEPCFG_BINTERVAL_M1(n) (((n) & 0xff) << 16) |
38 | #define DWC3_DEPCFG_STREAM_CAPABLE (1 << 24) | 38 | #define DWC3_DEPCFG_STREAM_CAPABLE BIT(24) |
39 | #define DWC3_DEPCFG_EP_NUMBER(n) (((n) & 0x1f) << 25) | 39 | #define DWC3_DEPCFG_EP_NUMBER(n) (((n) & 0x1f) << 25) |
40 | #define DWC3_DEPCFG_BULK_BASED (1 << 30) | 40 | #define DWC3_DEPCFG_BULK_BASED BIT(30) |
41 | #define DWC3_DEPCFG_FIFO_BASED (1 << 31) | 41 | #define DWC3_DEPCFG_FIFO_BASED BIT(31) |
42 | 42 | ||
43 | /* DEPCFG parameter 0 */ | 43 | /* DEPCFG parameter 0 */ |
44 | #define DWC3_DEPCFG_EP_TYPE(n) (((n) & 0x3) << 1) | 44 | #define DWC3_DEPCFG_EP_TYPE(n) (((n) & 0x3) << 1) |
@@ -47,10 +47,10 @@ struct dwc3; | |||
47 | #define DWC3_DEPCFG_BURST_SIZE(n) (((n) & 0xf) << 22) | 47 | #define DWC3_DEPCFG_BURST_SIZE(n) (((n) & 0xf) << 22) |
48 | #define DWC3_DEPCFG_DATA_SEQ_NUM(n) ((n) << 26) | 48 | #define DWC3_DEPCFG_DATA_SEQ_NUM(n) ((n) << 26) |
49 | /* This applies for core versions earlier than 1.94a */ | 49 | /* This applies for core versions earlier than 1.94a */ |
50 | #define DWC3_DEPCFG_IGN_SEQ_NUM (1 << 31) | 50 | #define DWC3_DEPCFG_IGN_SEQ_NUM BIT(31) |
51 | /* These apply for core versions 1.94a and later */ | 51 | /* These apply for core versions 1.94a and later */ |
52 | #define DWC3_DEPCFG_ACTION_INIT (0 << 30) | 52 | #define DWC3_DEPCFG_ACTION_INIT (0 << 30) |
53 | #define DWC3_DEPCFG_ACTION_RESTORE (1 << 30) | 53 | #define DWC3_DEPCFG_ACTION_RESTORE BIT(30) |
54 | #define DWC3_DEPCFG_ACTION_MODIFY (2 << 30) | 54 | #define DWC3_DEPCFG_ACTION_MODIFY (2 << 30) |
55 | 55 | ||
56 | /* DEPXFERCFG parameter 0 */ | 56 | /* DEPXFERCFG parameter 0 */ |
diff --git a/drivers/usb/dwc3/trace.h b/drivers/usb/dwc3/trace.h index 2b124f94d858..f1bd444d22a3 100644 --- a/drivers/usb/dwc3/trace.h +++ b/drivers/usb/dwc3/trace.h | |||
@@ -27,31 +27,6 @@ | |||
27 | #include "core.h" | 27 | #include "core.h" |
28 | #include "debug.h" | 28 | #include "debug.h" |
29 | 29 | ||
30 | DECLARE_EVENT_CLASS(dwc3_log_msg, | ||
31 | TP_PROTO(struct va_format *vaf), | ||
32 | TP_ARGS(vaf), | ||
33 | TP_STRUCT__entry(__dynamic_array(char, msg, DWC3_MSG_MAX)), | ||
34 | TP_fast_assign( | ||
35 | vsnprintf(__get_str(msg), DWC3_MSG_MAX, vaf->fmt, *vaf->va); | ||
36 | ), | ||
37 | TP_printk("%s", __get_str(msg)) | ||
38 | ); | ||
39 | |||
40 | DEFINE_EVENT(dwc3_log_msg, dwc3_gadget, | ||
41 | TP_PROTO(struct va_format *vaf), | ||
42 | TP_ARGS(vaf) | ||
43 | ); | ||
44 | |||
45 | DEFINE_EVENT(dwc3_log_msg, dwc3_core, | ||
46 | TP_PROTO(struct va_format *vaf), | ||
47 | TP_ARGS(vaf) | ||
48 | ); | ||
49 | |||
50 | DEFINE_EVENT(dwc3_log_msg, dwc3_ep0, | ||
51 | TP_PROTO(struct va_format *vaf), | ||
52 | TP_ARGS(vaf) | ||
53 | ); | ||
54 | |||
55 | DECLARE_EVENT_CLASS(dwc3_log_io, | 30 | DECLARE_EVENT_CLASS(dwc3_log_io, |
56 | TP_PROTO(void *base, u32 offset, u32 value), | 31 | TP_PROTO(void *base, u32 offset, u32 value), |
57 | TP_ARGS(base, offset, value), | 32 | TP_ARGS(base, offset, value), |
@@ -198,7 +173,7 @@ DECLARE_EVENT_CLASS(dwc3_log_generic_cmd, | |||
198 | __entry->param = param; | 173 | __entry->param = param; |
199 | __entry->status = status; | 174 | __entry->status = status; |
200 | ), | 175 | ), |
201 | TP_printk("cmd '%s' [%d] param %08x --> status: %s", | 176 | TP_printk("cmd '%s' [%x] param %08x --> status: %s", |
202 | dwc3_gadget_generic_cmd_string(__entry->cmd), | 177 | dwc3_gadget_generic_cmd_string(__entry->cmd), |
203 | __entry->cmd, __entry->param, | 178 | __entry->cmd, __entry->param, |
204 | dwc3_gadget_generic_cmd_status_string(__entry->status) | 179 | dwc3_gadget_generic_cmd_status_string(__entry->status) |
@@ -298,36 +273,7 @@ DECLARE_EVENT_CLASS(dwc3_log_trb, | |||
298 | __entry->ctrl & DWC3_TRB_CTRL_CSP ? 'S' : 's', | 273 | __entry->ctrl & DWC3_TRB_CTRL_CSP ? 'S' : 's', |
299 | __entry->ctrl & DWC3_TRB_CTRL_ISP_IMI ? 'S' : 's', | 274 | __entry->ctrl & DWC3_TRB_CTRL_ISP_IMI ? 'S' : 's', |
300 | __entry->ctrl & DWC3_TRB_CTRL_IOC ? 'C' : 'c', | 275 | __entry->ctrl & DWC3_TRB_CTRL_IOC ? 'C' : 'c', |
301 | ({char *s; | 276 | dwc3_trb_type_string(DWC3_TRBCTL_TYPE(__entry->ctrl)) |
302 | switch (__entry->ctrl & 0x3f0) { | ||
303 | case DWC3_TRBCTL_NORMAL: | ||
304 | s = "normal"; | ||
305 | break; | ||
306 | case DWC3_TRBCTL_CONTROL_SETUP: | ||
307 | s = "setup"; | ||
308 | break; | ||
309 | case DWC3_TRBCTL_CONTROL_STATUS2: | ||
310 | s = "status2"; | ||
311 | break; | ||
312 | case DWC3_TRBCTL_CONTROL_STATUS3: | ||
313 | s = "status3"; | ||
314 | break; | ||
315 | case DWC3_TRBCTL_CONTROL_DATA: | ||
316 | s = "data"; | ||
317 | break; | ||
318 | case DWC3_TRBCTL_ISOCHRONOUS_FIRST: | ||
319 | s = "isoc-first"; | ||
320 | break; | ||
321 | case DWC3_TRBCTL_ISOCHRONOUS: | ||
322 | s = "isoc"; | ||
323 | break; | ||
324 | case DWC3_TRBCTL_LINK_TRB: | ||
325 | s = "link"; | ||
326 | break; | ||
327 | default: | ||
328 | s = "UNKNOWN"; | ||
329 | break; | ||
330 | } s; }) | ||
331 | ) | 277 | ) |
332 | ); | 278 | ); |
333 | 279 | ||
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 8ad203296079..c164d6b788c3 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig | |||
@@ -212,7 +212,7 @@ config USB_F_TCM | |||
212 | # this first set of drivers all depend on bulk-capable hardware. | 212 | # this first set of drivers all depend on bulk-capable hardware. |
213 | 213 | ||
214 | config USB_CONFIGFS | 214 | config USB_CONFIGFS |
215 | tristate "USB functions configurable through configfs" | 215 | tristate "USB Gadget functions configurable through configfs" |
216 | select USB_LIBCOMPOSITE | 216 | select USB_LIBCOMPOSITE |
217 | help | 217 | help |
218 | A Linux USB "gadget" can be set up through configfs. | 218 | A Linux USB "gadget" can be set up through configfs. |
@@ -458,8 +458,9 @@ config USB_CONFIGFS_F_TCM | |||
458 | UAS utilizes the USB 3.0 feature called streams support. | 458 | UAS utilizes the USB 3.0 feature called streams support. |
459 | 459 | ||
460 | choice | 460 | choice |
461 | tristate "USB Gadget Drivers" | 461 | tristate "USB Gadget precomposed configurations" |
462 | default USB_ETH | 462 | default USB_ETH |
463 | optional | ||
463 | help | 464 | help |
464 | A Linux "Gadget Driver" talks to the USB Peripheral Controller | 465 | A Linux "Gadget Driver" talks to the USB Peripheral Controller |
465 | driver through the abstract "gadget" API. Some other operating | 466 | driver through the abstract "gadget" API. Some other operating |
@@ -476,6 +477,12 @@ choice | |||
476 | not be able work with that controller, or might need to implement | 477 | not be able work with that controller, or might need to implement |
477 | a less common variant of a device class protocol. | 478 | a less common variant of a device class protocol. |
478 | 479 | ||
480 | The available choices each represent a single precomposed USB | ||
481 | gadget configuration. In the device model, each option contains | ||
482 | both the device instantiation as a child for a USB gadget | ||
483 | controller, and the relevant drivers for each function declared | ||
484 | by the device. | ||
485 | |||
479 | source "drivers/usb/gadget/legacy/Kconfig" | 486 | source "drivers/usb/gadget/legacy/Kconfig" |
480 | 487 | ||
481 | endchoice | 488 | endchoice |
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index a0085571824d..71dd27c0d7f2 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c | |||
@@ -246,7 +246,6 @@ EXPORT_SYMBOL_GPL(ffs_lock); | |||
246 | 246 | ||
247 | static struct ffs_dev *_ffs_find_dev(const char *name); | 247 | static struct ffs_dev *_ffs_find_dev(const char *name); |
248 | static struct ffs_dev *_ffs_alloc_dev(void); | 248 | static struct ffs_dev *_ffs_alloc_dev(void); |
249 | static int _ffs_name_dev(struct ffs_dev *dev, const char *name); | ||
250 | static void _ffs_free_dev(struct ffs_dev *dev); | 249 | static void _ffs_free_dev(struct ffs_dev *dev); |
251 | static void *ffs_acquire_dev(const char *dev_name); | 250 | static void *ffs_acquire_dev(const char *dev_name); |
252 | static void ffs_release_dev(struct ffs_data *ffs_data); | 251 | static void ffs_release_dev(struct ffs_data *ffs_data); |
@@ -1571,14 +1570,14 @@ static void ffs_data_get(struct ffs_data *ffs) | |||
1571 | { | 1570 | { |
1572 | ENTER(); | 1571 | ENTER(); |
1573 | 1572 | ||
1574 | atomic_inc(&ffs->ref); | 1573 | refcount_inc(&ffs->ref); |
1575 | } | 1574 | } |
1576 | 1575 | ||
1577 | static void ffs_data_opened(struct ffs_data *ffs) | 1576 | static void ffs_data_opened(struct ffs_data *ffs) |
1578 | { | 1577 | { |
1579 | ENTER(); | 1578 | ENTER(); |
1580 | 1579 | ||
1581 | atomic_inc(&ffs->ref); | 1580 | refcount_inc(&ffs->ref); |
1582 | if (atomic_add_return(1, &ffs->opened) == 1 && | 1581 | if (atomic_add_return(1, &ffs->opened) == 1 && |
1583 | ffs->state == FFS_DEACTIVATED) { | 1582 | ffs->state == FFS_DEACTIVATED) { |
1584 | ffs->state = FFS_CLOSING; | 1583 | ffs->state = FFS_CLOSING; |
@@ -1590,7 +1589,7 @@ static void ffs_data_put(struct ffs_data *ffs) | |||
1590 | { | 1589 | { |
1591 | ENTER(); | 1590 | ENTER(); |
1592 | 1591 | ||
1593 | if (unlikely(atomic_dec_and_test(&ffs->ref))) { | 1592 | if (unlikely(refcount_dec_and_test(&ffs->ref))) { |
1594 | pr_info("%s(): freeing\n", __func__); | 1593 | pr_info("%s(): freeing\n", __func__); |
1595 | ffs_data_clear(ffs); | 1594 | ffs_data_clear(ffs); |
1596 | BUG_ON(waitqueue_active(&ffs->ev.waitq) || | 1595 | BUG_ON(waitqueue_active(&ffs->ev.waitq) || |
@@ -1635,7 +1634,7 @@ static struct ffs_data *ffs_data_new(void) | |||
1635 | 1634 | ||
1636 | ENTER(); | 1635 | ENTER(); |
1637 | 1636 | ||
1638 | atomic_set(&ffs->ref, 1); | 1637 | refcount_set(&ffs->ref, 1); |
1639 | atomic_set(&ffs->opened, 0); | 1638 | atomic_set(&ffs->opened, 0); |
1640 | ffs->state = FFS_READ_DESCRIPTORS; | 1639 | ffs->state = FFS_READ_DESCRIPTORS; |
1641 | mutex_init(&ffs->mutex); | 1640 | mutex_init(&ffs->mutex); |
@@ -3302,9 +3301,10 @@ static struct ffs_dev *_ffs_do_find_dev(const char *name) | |||
3302 | { | 3301 | { |
3303 | struct ffs_dev *dev; | 3302 | struct ffs_dev *dev; |
3304 | 3303 | ||
3304 | if (!name) | ||
3305 | return NULL; | ||
3306 | |||
3305 | list_for_each_entry(dev, &ffs_devices, entry) { | 3307 | list_for_each_entry(dev, &ffs_devices, entry) { |
3306 | if (!dev->name || !name) | ||
3307 | continue; | ||
3308 | if (strcmp(dev->name, name) == 0) | 3308 | if (strcmp(dev->name, name) == 0) |
3309 | return dev; | 3309 | return dev; |
3310 | } | 3310 | } |
@@ -3380,42 +3380,11 @@ static void ffs_free_inst(struct usb_function_instance *f) | |||
3380 | kfree(opts); | 3380 | kfree(opts); |
3381 | } | 3381 | } |
3382 | 3382 | ||
3383 | #define MAX_INST_NAME_LEN 40 | ||
3384 | |||
3385 | static int ffs_set_inst_name(struct usb_function_instance *fi, const char *name) | 3383 | static int ffs_set_inst_name(struct usb_function_instance *fi, const char *name) |
3386 | { | 3384 | { |
3387 | struct f_fs_opts *opts; | 3385 | if (strlen(name) >= FIELD_SIZEOF(struct ffs_dev, name)) |
3388 | char *ptr; | ||
3389 | const char *tmp; | ||
3390 | int name_len, ret; | ||
3391 | |||
3392 | name_len = strlen(name) + 1; | ||
3393 | if (name_len > MAX_INST_NAME_LEN) | ||
3394 | return -ENAMETOOLONG; | 3386 | return -ENAMETOOLONG; |
3395 | 3387 | return ffs_name_dev(to_f_fs_opts(fi)->dev, name); | |
3396 | ptr = kstrndup(name, name_len, GFP_KERNEL); | ||
3397 | if (!ptr) | ||
3398 | return -ENOMEM; | ||
3399 | |||
3400 | opts = to_f_fs_opts(fi); | ||
3401 | tmp = NULL; | ||
3402 | |||
3403 | ffs_dev_lock(); | ||
3404 | |||
3405 | tmp = opts->dev->name_allocated ? opts->dev->name : NULL; | ||
3406 | ret = _ffs_name_dev(opts->dev, ptr); | ||
3407 | if (ret) { | ||
3408 | kfree(ptr); | ||
3409 | ffs_dev_unlock(); | ||
3410 | return ret; | ||
3411 | } | ||
3412 | opts->dev->name_allocated = true; | ||
3413 | |||
3414 | ffs_dev_unlock(); | ||
3415 | |||
3416 | kfree(tmp); | ||
3417 | |||
3418 | return 0; | ||
3419 | } | 3388 | } |
3420 | 3389 | ||
3421 | static struct usb_function_instance *ffs_alloc_inst(void) | 3390 | static struct usb_function_instance *ffs_alloc_inst(void) |
@@ -3545,32 +3514,19 @@ static struct ffs_dev *_ffs_alloc_dev(void) | |||
3545 | return dev; | 3514 | return dev; |
3546 | } | 3515 | } |
3547 | 3516 | ||
3548 | /* | 3517 | int ffs_name_dev(struct ffs_dev *dev, const char *name) |
3549 | * ffs_lock must be taken by the caller of this function | ||
3550 | * The caller is responsible for "name" being available whenever f_fs needs it | ||
3551 | */ | ||
3552 | static int _ffs_name_dev(struct ffs_dev *dev, const char *name) | ||
3553 | { | 3518 | { |
3554 | struct ffs_dev *existing; | 3519 | struct ffs_dev *existing; |
3520 | int ret = 0; | ||
3555 | 3521 | ||
3556 | existing = _ffs_do_find_dev(name); | 3522 | ffs_dev_lock(); |
3557 | if (existing) | ||
3558 | return -EBUSY; | ||
3559 | |||
3560 | dev->name = name; | ||
3561 | |||
3562 | return 0; | ||
3563 | } | ||
3564 | 3523 | ||
3565 | /* | 3524 | existing = _ffs_do_find_dev(name); |
3566 | * The caller is responsible for "name" being available whenever f_fs needs it | 3525 | if (!existing) |
3567 | */ | 3526 | strlcpy(dev->name, name, ARRAY_SIZE(dev->name)); |
3568 | int ffs_name_dev(struct ffs_dev *dev, const char *name) | 3527 | else if (existing != dev) |
3569 | { | 3528 | ret = -EBUSY; |
3570 | int ret; | ||
3571 | 3529 | ||
3572 | ffs_dev_lock(); | ||
3573 | ret = _ffs_name_dev(dev, name); | ||
3574 | ffs_dev_unlock(); | 3530 | ffs_dev_unlock(); |
3575 | 3531 | ||
3576 | return ret; | 3532 | return ret; |
@@ -3600,8 +3556,6 @@ EXPORT_SYMBOL_GPL(ffs_single_dev); | |||
3600 | static void _ffs_free_dev(struct ffs_dev *dev) | 3556 | static void _ffs_free_dev(struct ffs_dev *dev) |
3601 | { | 3557 | { |
3602 | list_del(&dev->entry); | 3558 | list_del(&dev->entry); |
3603 | if (dev->name_allocated) | ||
3604 | kfree(dev->name); | ||
3605 | 3559 | ||
3606 | /* Clear the private_data pointer to stop incorrect dev access */ | 3560 | /* Clear the private_data pointer to stop incorrect dev access */ |
3607 | if (dev->ffs_data) | 3561 | if (dev->ffs_data) |
diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c index c3cab77181d4..a8b40d07e927 100644 --- a/drivers/usb/gadget/function/u_ether.c +++ b/drivers/usb/gadget/function/u_ether.c | |||
@@ -178,6 +178,7 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req); | |||
178 | static int | 178 | static int |
179 | rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) | 179 | rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) |
180 | { | 180 | { |
181 | struct usb_gadget *g = dev->gadget; | ||
181 | struct sk_buff *skb; | 182 | struct sk_buff *skb; |
182 | int retval = -ENOMEM; | 183 | int retval = -ENOMEM; |
183 | size_t size = 0; | 184 | size_t size = 0; |
@@ -209,8 +210,11 @@ rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) | |||
209 | */ | 210 | */ |
210 | size += sizeof(struct ethhdr) + dev->net->mtu + RX_EXTRA; | 211 | size += sizeof(struct ethhdr) + dev->net->mtu + RX_EXTRA; |
211 | size += dev->port_usb->header_len; | 212 | size += dev->port_usb->header_len; |
212 | size += out->maxpacket - 1; | 213 | |
213 | size -= size % out->maxpacket; | 214 | if (g->quirk_ep_out_aligned_size) { |
215 | size += out->maxpacket - 1; | ||
216 | size -= size % out->maxpacket; | ||
217 | } | ||
214 | 218 | ||
215 | if (dev->port_usb->is_fixed) | 219 | if (dev->port_usb->is_fixed) |
216 | size = max_t(size_t, size, dev->port_usb->fixed_out_len); | 220 | size = max_t(size_t, size, dev->port_usb->fixed_out_len); |
@@ -401,13 +405,12 @@ done: | |||
401 | static void rx_fill(struct eth_dev *dev, gfp_t gfp_flags) | 405 | static void rx_fill(struct eth_dev *dev, gfp_t gfp_flags) |
402 | { | 406 | { |
403 | struct usb_request *req; | 407 | struct usb_request *req; |
408 | struct usb_request *tmp; | ||
404 | unsigned long flags; | 409 | unsigned long flags; |
405 | 410 | ||
406 | /* fill unused rxq slots with some skb */ | 411 | /* fill unused rxq slots with some skb */ |
407 | spin_lock_irqsave(&dev->req_lock, flags); | 412 | spin_lock_irqsave(&dev->req_lock, flags); |
408 | while (!list_empty(&dev->rx_reqs)) { | 413 | list_for_each_entry_safe(req, tmp, &dev->rx_reqs, list) { |
409 | req = container_of(dev->rx_reqs.next, | ||
410 | struct usb_request, list); | ||
411 | list_del_init(&req->list); | 414 | list_del_init(&req->list); |
412 | spin_unlock_irqrestore(&dev->req_lock, flags); | 415 | spin_unlock_irqrestore(&dev->req_lock, flags); |
413 | 416 | ||
@@ -527,7 +530,7 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb, | |||
527 | return NETDEV_TX_BUSY; | 530 | return NETDEV_TX_BUSY; |
528 | } | 531 | } |
529 | 532 | ||
530 | req = container_of(dev->tx_reqs.next, struct usb_request, list); | 533 | req = list_first_entry(&dev->tx_reqs, struct usb_request, list); |
531 | list_del(&req->list); | 534 | list_del(&req->list); |
532 | 535 | ||
533 | /* temporarily stop TX queue when the freelist empties */ | 536 | /* temporarily stop TX queue when the freelist empties */ |
@@ -1122,6 +1125,7 @@ void gether_disconnect(struct gether *link) | |||
1122 | { | 1125 | { |
1123 | struct eth_dev *dev = link->ioport; | 1126 | struct eth_dev *dev = link->ioport; |
1124 | struct usb_request *req; | 1127 | struct usb_request *req; |
1128 | struct usb_request *tmp; | ||
1125 | 1129 | ||
1126 | WARN_ON(!dev); | 1130 | WARN_ON(!dev); |
1127 | if (!dev) | 1131 | if (!dev) |
@@ -1138,9 +1142,7 @@ void gether_disconnect(struct gether *link) | |||
1138 | */ | 1142 | */ |
1139 | usb_ep_disable(link->in_ep); | 1143 | usb_ep_disable(link->in_ep); |
1140 | spin_lock(&dev->req_lock); | 1144 | spin_lock(&dev->req_lock); |
1141 | while (!list_empty(&dev->tx_reqs)) { | 1145 | list_for_each_entry_safe(req, tmp, &dev->tx_reqs, list) { |
1142 | req = container_of(dev->tx_reqs.next, | ||
1143 | struct usb_request, list); | ||
1144 | list_del(&req->list); | 1146 | list_del(&req->list); |
1145 | 1147 | ||
1146 | spin_unlock(&dev->req_lock); | 1148 | spin_unlock(&dev->req_lock); |
@@ -1152,9 +1154,7 @@ void gether_disconnect(struct gether *link) | |||
1152 | 1154 | ||
1153 | usb_ep_disable(link->out_ep); | 1155 | usb_ep_disable(link->out_ep); |
1154 | spin_lock(&dev->req_lock); | 1156 | spin_lock(&dev->req_lock); |
1155 | while (!list_empty(&dev->rx_reqs)) { | 1157 | list_for_each_entry_safe(req, tmp, &dev->rx_reqs, list) { |
1156 | req = container_of(dev->rx_reqs.next, | ||
1157 | struct usb_request, list); | ||
1158 | list_del(&req->list); | 1158 | list_del(&req->list); |
1159 | 1159 | ||
1160 | spin_unlock(&dev->req_lock); | 1160 | spin_unlock(&dev->req_lock); |
diff --git a/drivers/usb/gadget/function/u_fs.h b/drivers/usb/gadget/function/u_fs.h index 4b6969451cdc..4378cc2fcac3 100644 --- a/drivers/usb/gadget/function/u_fs.h +++ b/drivers/usb/gadget/function/u_fs.h | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/list.h> | 20 | #include <linux/list.h> |
21 | #include <linux/mutex.h> | 21 | #include <linux/mutex.h> |
22 | #include <linux/workqueue.h> | 22 | #include <linux/workqueue.h> |
23 | #include <linux/refcount.h> | ||
23 | 24 | ||
24 | #ifdef VERBOSE_DEBUG | 25 | #ifdef VERBOSE_DEBUG |
25 | #ifndef pr_vdebug | 26 | #ifndef pr_vdebug |
@@ -39,15 +40,16 @@ | |||
39 | struct f_fs_opts; | 40 | struct f_fs_opts; |
40 | 41 | ||
41 | struct ffs_dev { | 42 | struct ffs_dev { |
42 | const char *name; | ||
43 | bool name_allocated; | ||
44 | bool mounted; | ||
45 | bool desc_ready; | ||
46 | bool single; | ||
47 | struct ffs_data *ffs_data; | 43 | struct ffs_data *ffs_data; |
48 | struct f_fs_opts *opts; | 44 | struct f_fs_opts *opts; |
49 | struct list_head entry; | 45 | struct list_head entry; |
50 | 46 | ||
47 | char name[41]; | ||
48 | |||
49 | bool mounted; | ||
50 | bool desc_ready; | ||
51 | bool single; | ||
52 | |||
51 | int (*ffs_ready_callback)(struct ffs_data *ffs); | 53 | int (*ffs_ready_callback)(struct ffs_data *ffs); |
52 | void (*ffs_closed_callback)(struct ffs_data *ffs); | 54 | void (*ffs_closed_callback)(struct ffs_data *ffs); |
53 | void *(*ffs_acquire_dev_callback)(struct ffs_dev *dev); | 55 | void *(*ffs_acquire_dev_callback)(struct ffs_dev *dev); |
@@ -177,7 +179,7 @@ struct ffs_data { | |||
177 | struct completion ep0req_completion; /* P: mutex */ | 179 | struct completion ep0req_completion; /* P: mutex */ |
178 | 180 | ||
179 | /* reference counter */ | 181 | /* reference counter */ |
180 | atomic_t ref; | 182 | refcount_t ref; |
181 | /* how many files are opened (EP0 and others) */ | 183 | /* how many files are opened (EP0 and others) */ |
182 | atomic_t opened; | 184 | atomic_t opened; |
183 | 185 | ||
diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c index 4e037d2a7a60..844cb738bafd 100644 --- a/drivers/usb/gadget/function/uvc_configfs.c +++ b/drivers/usb/gadget/function/uvc_configfs.c | |||
@@ -2125,7 +2125,7 @@ static struct configfs_item_operations uvc_item_ops = { | |||
2125 | .release = uvc_attr_release, | 2125 | .release = uvc_attr_release, |
2126 | }; | 2126 | }; |
2127 | 2127 | ||
2128 | #define UVCG_OPTS_ATTR(cname, conv, str2u, uxx, vnoc, limit) \ | 2128 | #define UVCG_OPTS_ATTR(cname, aname, conv, str2u, uxx, vnoc, limit) \ |
2129 | static ssize_t f_uvc_opts_##cname##_show( \ | 2129 | static ssize_t f_uvc_opts_##cname##_show( \ |
2130 | struct config_item *item, char *page) \ | 2130 | struct config_item *item, char *page) \ |
2131 | { \ | 2131 | { \ |
@@ -2168,16 +2168,16 @@ end: \ | |||
2168 | return ret; \ | 2168 | return ret; \ |
2169 | } \ | 2169 | } \ |
2170 | \ | 2170 | \ |
2171 | UVC_ATTR(f_uvc_opts_, cname, aname) | 2171 | UVC_ATTR(f_uvc_opts_, cname, cname) |
2172 | 2172 | ||
2173 | #define identity_conv(x) (x) | 2173 | #define identity_conv(x) (x) |
2174 | 2174 | ||
2175 | UVCG_OPTS_ATTR(streaming_interval, identity_conv, kstrtou8, u8, identity_conv, | 2175 | UVCG_OPTS_ATTR(streaming_interval, streaming_interval, identity_conv, |
2176 | 16); | 2176 | kstrtou8, u8, identity_conv, 16); |
2177 | UVCG_OPTS_ATTR(streaming_maxpacket, le16_to_cpu, kstrtou16, u16, le16_to_cpu, | 2177 | UVCG_OPTS_ATTR(streaming_maxpacket, streaming_maxpacket, le16_to_cpu, |
2178 | 3072); | 2178 | kstrtou16, u16, le16_to_cpu, 3072); |
2179 | UVCG_OPTS_ATTR(streaming_maxburst, identity_conv, kstrtou8, u8, identity_conv, | 2179 | UVCG_OPTS_ATTR(streaming_maxburst, streaming_maxburst, identity_conv, |
2180 | 15); | 2180 | kstrtou8, u8, identity_conv, 15); |
2181 | 2181 | ||
2182 | #undef identity_conv | 2182 | #undef identity_conv |
2183 | 2183 | ||
diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c index a2c916869293..b9ca0a26cbd9 100644 --- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/mmu_context.h> | 27 | #include <linux/mmu_context.h> |
28 | #include <linux/aio.h> | 28 | #include <linux/aio.h> |
29 | #include <linux/uio.h> | 29 | #include <linux/uio.h> |
30 | #include <linux/refcount.h> | ||
30 | 31 | ||
31 | #include <linux/device.h> | 32 | #include <linux/device.h> |
32 | #include <linux/moduleparam.h> | 33 | #include <linux/moduleparam.h> |
@@ -114,7 +115,7 @@ enum ep0_state { | |||
114 | 115 | ||
115 | struct dev_data { | 116 | struct dev_data { |
116 | spinlock_t lock; | 117 | spinlock_t lock; |
117 | atomic_t count; | 118 | refcount_t count; |
118 | enum ep0_state state; /* P: lock */ | 119 | enum ep0_state state; /* P: lock */ |
119 | struct usb_gadgetfs_event event [N_EVENT]; | 120 | struct usb_gadgetfs_event event [N_EVENT]; |
120 | unsigned ev_next; | 121 | unsigned ev_next; |
@@ -150,12 +151,12 @@ struct dev_data { | |||
150 | 151 | ||
151 | static inline void get_dev (struct dev_data *data) | 152 | static inline void get_dev (struct dev_data *data) |
152 | { | 153 | { |
153 | atomic_inc (&data->count); | 154 | refcount_inc (&data->count); |
154 | } | 155 | } |
155 | 156 | ||
156 | static void put_dev (struct dev_data *data) | 157 | static void put_dev (struct dev_data *data) |
157 | { | 158 | { |
158 | if (likely (!atomic_dec_and_test (&data->count))) | 159 | if (likely (!refcount_dec_and_test (&data->count))) |
159 | return; | 160 | return; |
160 | /* needs no more cleanup */ | 161 | /* needs no more cleanup */ |
161 | BUG_ON (waitqueue_active (&data->wait)); | 162 | BUG_ON (waitqueue_active (&data->wait)); |
@@ -170,7 +171,7 @@ static struct dev_data *dev_new (void) | |||
170 | if (!dev) | 171 | if (!dev) |
171 | return NULL; | 172 | return NULL; |
172 | dev->state = STATE_DEV_DISABLED; | 173 | dev->state = STATE_DEV_DISABLED; |
173 | atomic_set (&dev->count, 1); | 174 | refcount_set (&dev->count, 1); |
174 | spin_lock_init (&dev->lock); | 175 | spin_lock_init (&dev->lock); |
175 | INIT_LIST_HEAD (&dev->epfiles); | 176 | INIT_LIST_HEAD (&dev->epfiles); |
176 | init_waitqueue_head (&dev->wait); | 177 | init_waitqueue_head (&dev->wait); |
@@ -190,7 +191,7 @@ enum ep_state { | |||
190 | struct ep_data { | 191 | struct ep_data { |
191 | struct mutex lock; | 192 | struct mutex lock; |
192 | enum ep_state state; | 193 | enum ep_state state; |
193 | atomic_t count; | 194 | refcount_t count; |
194 | struct dev_data *dev; | 195 | struct dev_data *dev; |
195 | /* must hold dev->lock before accessing ep or req */ | 196 | /* must hold dev->lock before accessing ep or req */ |
196 | struct usb_ep *ep; | 197 | struct usb_ep *ep; |
@@ -205,12 +206,12 @@ struct ep_data { | |||
205 | 206 | ||
206 | static inline void get_ep (struct ep_data *data) | 207 | static inline void get_ep (struct ep_data *data) |
207 | { | 208 | { |
208 | atomic_inc (&data->count); | 209 | refcount_inc (&data->count); |
209 | } | 210 | } |
210 | 211 | ||
211 | static void put_ep (struct ep_data *data) | 212 | static void put_ep (struct ep_data *data) |
212 | { | 213 | { |
213 | if (likely (!atomic_dec_and_test (&data->count))) | 214 | if (likely (!refcount_dec_and_test (&data->count))) |
214 | return; | 215 | return; |
215 | put_dev (data->dev); | 216 | put_dev (data->dev); |
216 | /* needs no more cleanup */ | 217 | /* needs no more cleanup */ |
@@ -1561,7 +1562,7 @@ static int activate_ep_files (struct dev_data *dev) | |||
1561 | init_waitqueue_head (&data->wait); | 1562 | init_waitqueue_head (&data->wait); |
1562 | 1563 | ||
1563 | strncpy (data->name, ep->name, sizeof (data->name) - 1); | 1564 | strncpy (data->name, ep->name, sizeof (data->name) - 1); |
1564 | atomic_set (&data->count, 1); | 1565 | refcount_set (&data->count, 1); |
1565 | data->dev = dev; | 1566 | data->dev = dev; |
1566 | get_dev (dev); | 1567 | get_dev (dev); |
1567 | 1568 | ||
diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig index 4b69f28a9af9..1c14c283cc47 100644 --- a/drivers/usb/gadget/udc/Kconfig +++ b/drivers/usb/gadget/udc/Kconfig | |||
@@ -62,8 +62,9 @@ config USB_ATMEL_USBA | |||
62 | 62 | ||
63 | The fifo_mode parameter is used to select endpoint allocation mode. | 63 | The fifo_mode parameter is used to select endpoint allocation mode. |
64 | fifo_mode = 0 is used to let the driver autoconfigure the endpoints. | 64 | fifo_mode = 0 is used to let the driver autoconfigure the endpoints. |
65 | In this case 2 banks are allocated for isochronous endpoints and | 65 | In this case, for ep1 2 banks are allocated if it works in isochronous |
66 | only one bank is allocated for the rest of the endpoints. | 66 | mode and only 1 bank otherwise. For the rest of the endpoints |
67 | only 1 bank is allocated. | ||
67 | 68 | ||
68 | fifo_mode = 1 is a generic maximum fifo size (1024 bytes) configuration | 69 | fifo_mode = 1 is a generic maximum fifo size (1024 bytes) configuration |
69 | allowing the usage of ep1 - ep6 | 70 | allowing the usage of ep1 - ep6 |
@@ -191,6 +192,7 @@ config USB_RENESAS_USBHS_UDC | |||
191 | config USB_RENESAS_USB3 | 192 | config USB_RENESAS_USB3 |
192 | tristate 'Renesas USB3.0 Peripheral controller' | 193 | tristate 'Renesas USB3.0 Peripheral controller' |
193 | depends on ARCH_RENESAS || COMPILE_TEST | 194 | depends on ARCH_RENESAS || COMPILE_TEST |
195 | depends on EXTCON | ||
194 | help | 196 | help |
195 | Renesas USB3.0 Peripheral controller is a USB peripheral controller | 197 | Renesas USB3.0 Peripheral controller is a USB peripheral controller |
196 | that supports super, high, and full speed USB 3.0 data transfers. | 198 | that supports super, high, and full speed USB 3.0 data transfers. |
@@ -253,6 +255,20 @@ config USB_MV_U3D | |||
253 | MARVELL PXA2128 Processor series include a super speed USB3.0 device | 255 | MARVELL PXA2128 Processor series include a super speed USB3.0 device |
254 | controller, which support super speed USB peripheral. | 256 | controller, which support super speed USB peripheral. |
255 | 257 | ||
258 | config USB_SNP_CORE | ||
259 | depends on USB_AMD5536UDC | ||
260 | tristate | ||
261 | help | ||
262 | This enables core driver support for Synopsys USB 2.0 Device | ||
263 | controller. | ||
264 | |||
265 | This will be enabled when PCI or Platform driver for this UDC is | ||
266 | selected. Currently, this will be enabled by USB_SNP_UDC_PLAT or | ||
267 | USB_AMD5536UDC options. | ||
268 | |||
269 | This IP is different to the High Speed OTG IP that can be enabled | ||
270 | by selecting USB_DWC2 or USB_DWC3 options. | ||
271 | |||
256 | # | 272 | # |
257 | # Controllers available in both integrated and discrete versions | 273 | # Controllers available in both integrated and discrete versions |
258 | # | 274 | # |
@@ -277,7 +293,8 @@ source "drivers/usb/gadget/udc/bdc/Kconfig" | |||
277 | 293 | ||
278 | config USB_AMD5536UDC | 294 | config USB_AMD5536UDC |
279 | tristate "AMD5536 UDC" | 295 | tristate "AMD5536 UDC" |
280 | depends on PCI | 296 | depends on USB_PCI |
297 | select USB_SNP_CORE | ||
281 | help | 298 | help |
282 | The AMD5536 UDC is part of the AMD Geode CS5536, an x86 southbridge. | 299 | The AMD5536 UDC is part of the AMD Geode CS5536, an x86 southbridge. |
283 | It is a USB Highspeed DMA capable USB device controller. Beside ep0 | 300 | It is a USB Highspeed DMA capable USB device controller. Beside ep0 |
@@ -285,6 +302,9 @@ config USB_AMD5536UDC | |||
285 | The UDC port supports OTG operation, and may be used as a host port | 302 | The UDC port supports OTG operation, and may be used as a host port |
286 | if it's not being used to implement peripheral or OTG roles. | 303 | if it's not being used to implement peripheral or OTG roles. |
287 | 304 | ||
305 | This UDC is based on Synopsys USB device controller IP and selects | ||
306 | CONFIG_USB_SNP_CORE option to build the core driver. | ||
307 | |||
288 | Say "y" to link the driver statically, or "m" to build a | 308 | Say "y" to link the driver statically, or "m" to build a |
289 | dynamically linked module called "amd5536udc" and force all | 309 | dynamically linked module called "amd5536udc" and force all |
290 | gadget drivers to also be dynamically linked. | 310 | gadget drivers to also be dynamically linked. |
@@ -327,7 +347,7 @@ config USB_NET2272_DMA | |||
327 | 347 | ||
328 | config USB_NET2280 | 348 | config USB_NET2280 |
329 | tristate "NetChip NET228x / PLX USB3x8x" | 349 | tristate "NetChip NET228x / PLX USB3x8x" |
330 | depends on PCI | 350 | depends on USB_PCI |
331 | help | 351 | help |
332 | NetChip 2280 / 2282 is a PCI based USB peripheral controller which | 352 | NetChip 2280 / 2282 is a PCI based USB peripheral controller which |
333 | supports both full and high speed USB 2.0 data transfers. | 353 | supports both full and high speed USB 2.0 data transfers. |
@@ -352,7 +372,7 @@ config USB_NET2280 | |||
352 | 372 | ||
353 | config USB_GOKU | 373 | config USB_GOKU |
354 | tristate "Toshiba TC86C001 'Goku-S'" | 374 | tristate "Toshiba TC86C001 'Goku-S'" |
355 | depends on PCI | 375 | depends on USB_PCI |
356 | help | 376 | help |
357 | The Toshiba TC86C001 is a PCI device which includes controllers | 377 | The Toshiba TC86C001 is a PCI device which includes controllers |
358 | for full speed USB devices, IDE, I2C, SIO, plus a USB host (OHCI). | 378 | for full speed USB devices, IDE, I2C, SIO, plus a USB host (OHCI). |
@@ -366,7 +386,7 @@ config USB_GOKU | |||
366 | 386 | ||
367 | config USB_EG20T | 387 | config USB_EG20T |
368 | tristate "Intel QUARK X1000/EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC" | 388 | tristate "Intel QUARK X1000/EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC" |
369 | depends on PCI | 389 | depends on USB_PCI |
370 | help | 390 | help |
371 | This is a USB device driver for EG20T PCH. | 391 | This is a USB device driver for EG20T PCH. |
372 | EG20T PCH is the platform controller hub that is used in Intel's | 392 | EG20T PCH is the platform controller hub that is used in Intel's |
diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile index 98e74ed9f555..626e1f1c62da 100644 --- a/drivers/usb/gadget/udc/Makefile +++ b/drivers/usb/gadget/udc/Makefile | |||
@@ -10,7 +10,8 @@ obj-$(CONFIG_USB_GADGET) += udc-core.o | |||
10 | obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o | 10 | obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o |
11 | obj-$(CONFIG_USB_NET2272) += net2272.o | 11 | obj-$(CONFIG_USB_NET2272) += net2272.o |
12 | obj-$(CONFIG_USB_NET2280) += net2280.o | 12 | obj-$(CONFIG_USB_NET2280) += net2280.o |
13 | obj-$(CONFIG_USB_AMD5536UDC) += amd5536udc.o | 13 | obj-$(CONFIG_USB_SNP_CORE) += amd5536udc.o |
14 | obj-$(CONFIG_USB_AMD5536UDC) += amd5536udc_pci.o | ||
14 | obj-$(CONFIG_USB_PXA25X) += pxa25x_udc.o | 15 | obj-$(CONFIG_USB_PXA25X) += pxa25x_udc.o |
15 | obj-$(CONFIG_USB_PXA27X) += pxa27x_udc.o | 16 | obj-$(CONFIG_USB_PXA27X) += pxa27x_udc.o |
16 | obj-$(CONFIG_USB_GOKU) += goku_udc.o | 17 | obj-$(CONFIG_USB_GOKU) += goku_udc.o |
diff --git a/drivers/usb/gadget/udc/amd5536udc.c b/drivers/usb/gadget/udc/amd5536udc.c index ea03ca7ae29a..4ecd2f20ea48 100644 --- a/drivers/usb/gadget/udc/amd5536udc.c +++ b/drivers/usb/gadget/udc/amd5536udc.c | |||
@@ -11,27 +11,15 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | /* | 13 | /* |
14 | * The AMD5536 UDC is part of the x86 southbridge AMD Geode CS5536. | 14 | * This file does the core driver implementation for the UDC that is based |
15 | * It is a USB Highspeed DMA capable USB device controller. Beside ep0 it | 15 | * on Synopsys device controller IP (different than HS OTG IP) that is either |
16 | * provides 4 IN and 4 OUT endpoints (bulk or interrupt type). | 16 | * connected through PCI bus or integrated to SoC platforms. |
17 | * | ||
18 | * Make sure that UDC is assigned to port 4 by BIOS settings (port can also | ||
19 | * be used as host port) and UOC bits PAD_EN and APU are set (should be done | ||
20 | * by BIOS init). | ||
21 | * | ||
22 | * UDC DMA requires 32-bit aligned buffers so DMA with gadget ether does not | ||
23 | * work without updating NET_IP_ALIGN. Or PIO mode (module param "use_dma=0") | ||
24 | * can be used with gadget ether. | ||
25 | */ | 17 | */ |
26 | 18 | ||
27 | /* debug control */ | ||
28 | /* #define UDC_VERBOSE */ | ||
29 | |||
30 | /* Driver strings */ | 19 | /* Driver strings */ |
31 | #define UDC_MOD_DESCRIPTION "AMD 5536 UDC - USB Device Controller" | 20 | #define UDC_MOD_DESCRIPTION "Synopsys USB Device Controller" |
32 | #define UDC_DRIVER_VERSION_STRING "01.00.0206" | 21 | #define UDC_DRIVER_VERSION_STRING "01.00.0206" |
33 | 22 | ||
34 | /* system */ | ||
35 | #include <linux/module.h> | 23 | #include <linux/module.h> |
36 | #include <linux/pci.h> | 24 | #include <linux/pci.h> |
37 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
@@ -46,23 +34,12 @@ | |||
46 | #include <linux/ioctl.h> | 34 | #include <linux/ioctl.h> |
47 | #include <linux/fs.h> | 35 | #include <linux/fs.h> |
48 | #include <linux/dmapool.h> | 36 | #include <linux/dmapool.h> |
49 | #include <linux/moduleparam.h> | ||
50 | #include <linux/device.h> | ||
51 | #include <linux/io.h> | ||
52 | #include <linux/irq.h> | ||
53 | #include <linux/prefetch.h> | 37 | #include <linux/prefetch.h> |
54 | 38 | #include <linux/moduleparam.h> | |
55 | #include <asm/byteorder.h> | 39 | #include <asm/byteorder.h> |
56 | #include <asm/unaligned.h> | 40 | #include <asm/unaligned.h> |
57 | |||
58 | /* gadget stack */ | ||
59 | #include <linux/usb/ch9.h> | ||
60 | #include <linux/usb/gadget.h> | ||
61 | |||
62 | /* udc specific */ | ||
63 | #include "amd5536udc.h" | 41 | #include "amd5536udc.h" |
64 | 42 | ||
65 | |||
66 | static void udc_tasklet_disconnect(unsigned long); | 43 | static void udc_tasklet_disconnect(unsigned long); |
67 | static void empty_req_queue(struct udc_ep *); | 44 | static void empty_req_queue(struct udc_ep *); |
68 | static void udc_setup_endpoints(struct udc *dev); | 45 | static void udc_setup_endpoints(struct udc *dev); |
@@ -72,7 +49,7 @@ static void udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq); | |||
72 | 49 | ||
73 | /* description */ | 50 | /* description */ |
74 | static const char mod_desc[] = UDC_MOD_DESCRIPTION; | 51 | static const char mod_desc[] = UDC_MOD_DESCRIPTION; |
75 | static const char name[] = "amd5536udc"; | 52 | static const char name[] = "udc"; |
76 | 53 | ||
77 | /* structure to hold endpoint function pointers */ | 54 | /* structure to hold endpoint function pointers */ |
78 | static const struct usb_ep_ops udc_ep_ops; | 55 | static const struct usb_ep_ops udc_ep_ops; |
@@ -208,30 +185,11 @@ static const struct { | |||
208 | #undef EP_INFO | 185 | #undef EP_INFO |
209 | }; | 186 | }; |
210 | 187 | ||
211 | /* DMA usage flag */ | ||
212 | static bool use_dma = 1; | ||
213 | /* packet per buffer dma */ | ||
214 | static bool use_dma_ppb = 1; | ||
215 | /* with per descr. update */ | ||
216 | static bool use_dma_ppb_du; | ||
217 | /* buffer fill mode */ | 188 | /* buffer fill mode */ |
218 | static int use_dma_bufferfill_mode; | 189 | static int use_dma_bufferfill_mode; |
219 | /* full speed only mode */ | ||
220 | static bool use_fullspeed; | ||
221 | /* tx buffer size for high speed */ | 190 | /* tx buffer size for high speed */ |
222 | static unsigned long hs_tx_buf = UDC_EPIN_BUFF_SIZE; | 191 | static unsigned long hs_tx_buf = UDC_EPIN_BUFF_SIZE; |
223 | 192 | ||
224 | /* module parameters */ | ||
225 | module_param(use_dma, bool, S_IRUGO); | ||
226 | MODULE_PARM_DESC(use_dma, "true for DMA"); | ||
227 | module_param(use_dma_ppb, bool, S_IRUGO); | ||
228 | MODULE_PARM_DESC(use_dma_ppb, "true for DMA in packet per buffer mode"); | ||
229 | module_param(use_dma_ppb_du, bool, S_IRUGO); | ||
230 | MODULE_PARM_DESC(use_dma_ppb_du, | ||
231 | "true for DMA in packet per buffer mode with descriptor update"); | ||
232 | module_param(use_fullspeed, bool, S_IRUGO); | ||
233 | MODULE_PARM_DESC(use_fullspeed, "true for fullspeed only"); | ||
234 | |||
235 | /*---------------------------------------------------------------------------*/ | 193 | /*---------------------------------------------------------------------------*/ |
236 | /* Prints UDC device registers and endpoint irq registers */ | 194 | /* Prints UDC device registers and endpoint irq registers */ |
237 | static void print_regs(struct udc *dev) | 195 | static void print_regs(struct udc *dev) |
@@ -267,7 +225,7 @@ static void print_regs(struct udc *dev) | |||
267 | } | 225 | } |
268 | 226 | ||
269 | /* Masks unused interrupts */ | 227 | /* Masks unused interrupts */ |
270 | static int udc_mask_unused_interrupts(struct udc *dev) | 228 | int udc_mask_unused_interrupts(struct udc *dev) |
271 | { | 229 | { |
272 | u32 tmp; | 230 | u32 tmp; |
273 | 231 | ||
@@ -287,6 +245,7 @@ static int udc_mask_unused_interrupts(struct udc *dev) | |||
287 | 245 | ||
288 | return 0; | 246 | return 0; |
289 | } | 247 | } |
248 | EXPORT_SYMBOL_GPL(udc_mask_unused_interrupts); | ||
290 | 249 | ||
291 | /* Enables endpoint 0 interrupts */ | 250 | /* Enables endpoint 0 interrupts */ |
292 | static int udc_enable_ep0_interrupts(struct udc *dev) | 251 | static int udc_enable_ep0_interrupts(struct udc *dev) |
@@ -306,7 +265,7 @@ static int udc_enable_ep0_interrupts(struct udc *dev) | |||
306 | } | 265 | } |
307 | 266 | ||
308 | /* Enables device interrupts for SET_INTF and SET_CONFIG */ | 267 | /* Enables device interrupts for SET_INTF and SET_CONFIG */ |
309 | static int udc_enable_dev_setup_interrupts(struct udc *dev) | 268 | int udc_enable_dev_setup_interrupts(struct udc *dev) |
310 | { | 269 | { |
311 | u32 tmp; | 270 | u32 tmp; |
312 | 271 | ||
@@ -325,6 +284,7 @@ static int udc_enable_dev_setup_interrupts(struct udc *dev) | |||
325 | 284 | ||
326 | return 0; | 285 | return 0; |
327 | } | 286 | } |
287 | EXPORT_SYMBOL_GPL(udc_enable_dev_setup_interrupts); | ||
328 | 288 | ||
329 | /* Calculates fifo start of endpoint based on preceding endpoints */ | 289 | /* Calculates fifo start of endpoint based on preceding endpoints */ |
330 | static int udc_set_txfifo_addr(struct udc_ep *ep) | 290 | static int udc_set_txfifo_addr(struct udc_ep *ep) |
@@ -583,7 +543,7 @@ udc_alloc_request(struct usb_ep *usbep, gfp_t gfp) | |||
583 | 543 | ||
584 | if (ep->dma) { | 544 | if (ep->dma) { |
585 | /* ep0 in requests are allocated from data pool here */ | 545 | /* ep0 in requests are allocated from data pool here */ |
586 | dma_desc = pci_pool_alloc(ep->dev->data_requests, gfp, | 546 | dma_desc = dma_pool_alloc(ep->dev->data_requests, gfp, |
587 | &req->td_phys); | 547 | &req->td_phys); |
588 | if (!dma_desc) { | 548 | if (!dma_desc) { |
589 | kfree(req); | 549 | kfree(req); |
@@ -608,27 +568,23 @@ udc_alloc_request(struct usb_ep *usbep, gfp_t gfp) | |||
608 | } | 568 | } |
609 | 569 | ||
610 | /* frees pci pool descriptors of a DMA chain */ | 570 | /* frees pci pool descriptors of a DMA chain */ |
611 | static int udc_free_dma_chain(struct udc *dev, struct udc_request *req) | 571 | static void udc_free_dma_chain(struct udc *dev, struct udc_request *req) |
612 | { | 572 | { |
613 | int ret_val = 0; | 573 | struct udc_data_dma *td = req->td_data; |
614 | struct udc_data_dma *td; | ||
615 | struct udc_data_dma *td_last = NULL; | ||
616 | unsigned int i; | 574 | unsigned int i; |
617 | 575 | ||
576 | dma_addr_t addr_next = 0x00; | ||
577 | dma_addr_t addr = (dma_addr_t)td->next; | ||
578 | |||
618 | DBG(dev, "free chain req = %p\n", req); | 579 | DBG(dev, "free chain req = %p\n", req); |
619 | 580 | ||
620 | /* do not free first desc., will be done by free for request */ | 581 | /* do not free first desc., will be done by free for request */ |
621 | td_last = req->td_data; | ||
622 | td = phys_to_virt(td_last->next); | ||
623 | |||
624 | for (i = 1; i < req->chain_len; i++) { | 582 | for (i = 1; i < req->chain_len; i++) { |
625 | pci_pool_free(dev->data_requests, td, | 583 | td = phys_to_virt(addr); |
626 | (dma_addr_t)td_last->next); | 584 | addr_next = (dma_addr_t)td->next; |
627 | td_last = td; | 585 | dma_pool_free(dev->data_requests, td, addr); |
628 | td = phys_to_virt(td_last->next); | 586 | addr = addr_next; |
629 | } | 587 | } |
630 | |||
631 | return ret_val; | ||
632 | } | 588 | } |
633 | 589 | ||
634 | /* Frees request packet, called by gadget driver */ | 590 | /* Frees request packet, called by gadget driver */ |
@@ -652,7 +608,7 @@ udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq) | |||
652 | if (req->chain_len > 1) | 608 | if (req->chain_len > 1) |
653 | udc_free_dma_chain(ep->dev, req); | 609 | udc_free_dma_chain(ep->dev, req); |
654 | 610 | ||
655 | pci_pool_free(ep->dev->data_requests, req->td_data, | 611 | dma_pool_free(ep->dev->data_requests, req->td_data, |
656 | req->td_phys); | 612 | req->td_phys); |
657 | } | 613 | } |
658 | kfree(req); | 614 | kfree(req); |
@@ -847,7 +803,7 @@ static int udc_create_dma_chain( | |||
847 | for (i = buf_len; i < bytes; i += buf_len) { | 803 | for (i = buf_len; i < bytes; i += buf_len) { |
848 | /* create or determine next desc. */ | 804 | /* create or determine next desc. */ |
849 | if (create_new_chain) { | 805 | if (create_new_chain) { |
850 | td = pci_pool_alloc(ep->dev->data_requests, | 806 | td = dma_pool_alloc(ep->dev->data_requests, |
851 | gfp_flags, &dma_addr); | 807 | gfp_flags, &dma_addr); |
852 | if (!td) | 808 | if (!td) |
853 | return -ENOMEM; | 809 | return -ENOMEM; |
@@ -1507,7 +1463,7 @@ static void make_ep_lists(struct udc *dev) | |||
1507 | } | 1463 | } |
1508 | 1464 | ||
1509 | /* Inits UDC context */ | 1465 | /* Inits UDC context */ |
1510 | static void udc_basic_init(struct udc *dev) | 1466 | void udc_basic_init(struct udc *dev) |
1511 | { | 1467 | { |
1512 | u32 tmp; | 1468 | u32 tmp; |
1513 | 1469 | ||
@@ -1543,6 +1499,7 @@ static void udc_basic_init(struct udc *dev) | |||
1543 | dev->data_ep_enabled = 0; | 1499 | dev->data_ep_enabled = 0; |
1544 | dev->data_ep_queued = 0; | 1500 | dev->data_ep_queued = 0; |
1545 | } | 1501 | } |
1502 | EXPORT_SYMBOL_GPL(udc_basic_init); | ||
1546 | 1503 | ||
1547 | /* init registers at driver load time */ | 1504 | /* init registers at driver load time */ |
1548 | static int startup_registers(struct udc *dev) | 1505 | static int startup_registers(struct udc *dev) |
@@ -3031,7 +2988,7 @@ __acquires(dev->lock) | |||
3031 | } | 2988 | } |
3032 | 2989 | ||
3033 | /* Interrupt Service Routine, see Linux Kernel Doc for parameters */ | 2990 | /* Interrupt Service Routine, see Linux Kernel Doc for parameters */ |
3034 | static irqreturn_t udc_irq(int irq, void *pdev) | 2991 | irqreturn_t udc_irq(int irq, void *pdev) |
3035 | { | 2992 | { |
3036 | struct udc *dev = pdev; | 2993 | struct udc *dev = pdev; |
3037 | u32 reg; | 2994 | u32 reg; |
@@ -3083,16 +3040,18 @@ static irqreturn_t udc_irq(int irq, void *pdev) | |||
3083 | spin_unlock(&dev->lock); | 3040 | spin_unlock(&dev->lock); |
3084 | return ret_val; | 3041 | return ret_val; |
3085 | } | 3042 | } |
3043 | EXPORT_SYMBOL_GPL(udc_irq); | ||
3086 | 3044 | ||
3087 | /* Tears down device */ | 3045 | /* Tears down device */ |
3088 | static void gadget_release(struct device *pdev) | 3046 | void gadget_release(struct device *pdev) |
3089 | { | 3047 | { |
3090 | struct amd5536udc *dev = dev_get_drvdata(pdev); | 3048 | struct amd5536udc *dev = dev_get_drvdata(pdev); |
3091 | kfree(dev); | 3049 | kfree(dev); |
3092 | } | 3050 | } |
3051 | EXPORT_SYMBOL_GPL(gadget_release); | ||
3093 | 3052 | ||
3094 | /* Cleanup on device remove */ | 3053 | /* Cleanup on device remove */ |
3095 | static void udc_remove(struct udc *dev) | 3054 | void udc_remove(struct udc *dev) |
3096 | { | 3055 | { |
3097 | /* remove timer */ | 3056 | /* remove timer */ |
3098 | stop_timer++; | 3057 | stop_timer++; |
@@ -3108,9 +3067,10 @@ static void udc_remove(struct udc *dev) | |||
3108 | del_timer_sync(&udc_pollstall_timer); | 3067 | del_timer_sync(&udc_pollstall_timer); |
3109 | udc = NULL; | 3068 | udc = NULL; |
3110 | } | 3069 | } |
3070 | EXPORT_SYMBOL_GPL(udc_remove); | ||
3111 | 3071 | ||
3112 | /* free all the dma pools */ | 3072 | /* free all the dma pools */ |
3113 | static void free_dma_pools(struct udc *dev) | 3073 | void free_dma_pools(struct udc *dev) |
3114 | { | 3074 | { |
3115 | dma_pool_free(dev->stp_requests, dev->ep[UDC_EP0OUT_IX].td, | 3075 | dma_pool_free(dev->stp_requests, dev->ep[UDC_EP0OUT_IX].td, |
3116 | dev->ep[UDC_EP0OUT_IX].td_phys); | 3076 | dev->ep[UDC_EP0OUT_IX].td_phys); |
@@ -3119,35 +3079,10 @@ static void free_dma_pools(struct udc *dev) | |||
3119 | dma_pool_destroy(dev->stp_requests); | 3079 | dma_pool_destroy(dev->stp_requests); |
3120 | dma_pool_destroy(dev->data_requests); | 3080 | dma_pool_destroy(dev->data_requests); |
3121 | } | 3081 | } |
3122 | 3082 | EXPORT_SYMBOL_GPL(free_dma_pools); | |
3123 | /* Reset all pci context */ | ||
3124 | static void udc_pci_remove(struct pci_dev *pdev) | ||
3125 | { | ||
3126 | struct udc *dev; | ||
3127 | |||
3128 | dev = pci_get_drvdata(pdev); | ||
3129 | |||
3130 | usb_del_gadget_udc(&udc->gadget); | ||
3131 | /* gadget driver must not be registered */ | ||
3132 | if (WARN_ON(dev->driver)) | ||
3133 | return; | ||
3134 | |||
3135 | /* dma pool cleanup */ | ||
3136 | free_dma_pools(dev); | ||
3137 | |||
3138 | /* reset controller */ | ||
3139 | writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg); | ||
3140 | free_irq(pdev->irq, dev); | ||
3141 | iounmap(dev->virt_addr); | ||
3142 | release_mem_region(pci_resource_start(pdev, 0), | ||
3143 | pci_resource_len(pdev, 0)); | ||
3144 | pci_disable_device(pdev); | ||
3145 | |||
3146 | udc_remove(dev); | ||
3147 | } | ||
3148 | 3083 | ||
3149 | /* create dma pools on init */ | 3084 | /* create dma pools on init */ |
3150 | static int init_dma_pools(struct udc *dev) | 3085 | int init_dma_pools(struct udc *dev) |
3151 | { | 3086 | { |
3152 | struct udc_stp_dma *td_stp; | 3087 | struct udc_stp_dma *td_stp; |
3153 | struct udc_data_dma *td_data; | 3088 | struct udc_data_dma *td_data; |
@@ -3210,9 +3145,10 @@ err_create_dma_pool: | |||
3210 | dev->data_requests = NULL; | 3145 | dev->data_requests = NULL; |
3211 | return retval; | 3146 | return retval; |
3212 | } | 3147 | } |
3148 | EXPORT_SYMBOL_GPL(init_dma_pools); | ||
3213 | 3149 | ||
3214 | /* general probe */ | 3150 | /* general probe */ |
3215 | static int udc_probe(struct udc *dev) | 3151 | int udc_probe(struct udc *dev) |
3216 | { | 3152 | { |
3217 | char tmp[128]; | 3153 | char tmp[128]; |
3218 | u32 reg; | 3154 | u32 reg; |
@@ -3276,137 +3212,7 @@ static int udc_probe(struct udc *dev) | |||
3276 | finished: | 3212 | finished: |
3277 | return retval; | 3213 | return retval; |
3278 | } | 3214 | } |
3279 | 3215 | EXPORT_SYMBOL_GPL(udc_probe); | |
3280 | /* Called by pci bus driver to init pci context */ | ||
3281 | static int udc_pci_probe( | ||
3282 | struct pci_dev *pdev, | ||
3283 | const struct pci_device_id *id | ||
3284 | ) | ||
3285 | { | ||
3286 | struct udc *dev; | ||
3287 | unsigned long resource; | ||
3288 | unsigned long len; | ||
3289 | int retval = 0; | ||
3290 | |||
3291 | /* one udc only */ | ||
3292 | if (udc) { | ||
3293 | dev_dbg(&pdev->dev, "already probed\n"); | ||
3294 | return -EBUSY; | ||
3295 | } | ||
3296 | |||
3297 | /* init */ | ||
3298 | dev = kzalloc(sizeof(struct udc), GFP_KERNEL); | ||
3299 | if (!dev) | ||
3300 | return -ENOMEM; | ||
3301 | |||
3302 | /* pci setup */ | ||
3303 | if (pci_enable_device(pdev) < 0) { | ||
3304 | retval = -ENODEV; | ||
3305 | goto err_pcidev; | ||
3306 | } | ||
3307 | |||
3308 | /* PCI resource allocation */ | ||
3309 | resource = pci_resource_start(pdev, 0); | ||
3310 | len = pci_resource_len(pdev, 0); | ||
3311 | |||
3312 | if (!request_mem_region(resource, len, name)) { | ||
3313 | dev_dbg(&pdev->dev, "pci device used already\n"); | ||
3314 | retval = -EBUSY; | ||
3315 | goto err_memreg; | ||
3316 | } | ||
3317 | |||
3318 | dev->virt_addr = ioremap_nocache(resource, len); | ||
3319 | if (!dev->virt_addr) { | ||
3320 | dev_dbg(&pdev->dev, "start address cannot be mapped\n"); | ||
3321 | retval = -EFAULT; | ||
3322 | goto err_ioremap; | ||
3323 | } | ||
3324 | |||
3325 | if (!pdev->irq) { | ||
3326 | dev_err(&pdev->dev, "irq not set\n"); | ||
3327 | retval = -ENODEV; | ||
3328 | goto err_irq; | ||
3329 | } | ||
3330 | |||
3331 | spin_lock_init(&dev->lock); | ||
3332 | /* udc csr registers base */ | ||
3333 | dev->csr = dev->virt_addr + UDC_CSR_ADDR; | ||
3334 | /* dev registers base */ | ||
3335 | dev->regs = dev->virt_addr + UDC_DEVCFG_ADDR; | ||
3336 | /* ep registers base */ | ||
3337 | dev->ep_regs = dev->virt_addr + UDC_EPREGS_ADDR; | ||
3338 | /* fifo's base */ | ||
3339 | dev->rxfifo = (u32 __iomem *)(dev->virt_addr + UDC_RXFIFO_ADDR); | ||
3340 | dev->txfifo = (u32 __iomem *)(dev->virt_addr + UDC_TXFIFO_ADDR); | ||
3341 | |||
3342 | if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) { | ||
3343 | dev_dbg(&pdev->dev, "request_irq(%d) fail\n", pdev->irq); | ||
3344 | retval = -EBUSY; | ||
3345 | goto err_irq; | ||
3346 | } | ||
3347 | |||
3348 | pci_set_drvdata(pdev, dev); | ||
3349 | |||
3350 | /* chip revision for Hs AMD5536 */ | ||
3351 | dev->chiprev = pdev->revision; | ||
3352 | |||
3353 | pci_set_master(pdev); | ||
3354 | pci_try_set_mwi(pdev); | ||
3355 | |||
3356 | /* init dma pools */ | ||
3357 | if (use_dma) { | ||
3358 | retval = init_dma_pools(dev); | ||
3359 | if (retval != 0) | ||
3360 | goto err_dma; | ||
3361 | } | ||
3362 | |||
3363 | dev->phys_addr = resource; | ||
3364 | dev->irq = pdev->irq; | ||
3365 | dev->pdev = pdev; | ||
3366 | |||
3367 | /* general probing */ | ||
3368 | if (udc_probe(dev)) { | ||
3369 | retval = -ENODEV; | ||
3370 | goto err_probe; | ||
3371 | } | ||
3372 | return 0; | ||
3373 | |||
3374 | err_probe: | ||
3375 | if (use_dma) | ||
3376 | free_dma_pools(dev); | ||
3377 | err_dma: | ||
3378 | free_irq(pdev->irq, dev); | ||
3379 | err_irq: | ||
3380 | iounmap(dev->virt_addr); | ||
3381 | err_ioremap: | ||
3382 | release_mem_region(resource, len); | ||
3383 | err_memreg: | ||
3384 | pci_disable_device(pdev); | ||
3385 | err_pcidev: | ||
3386 | kfree(dev); | ||
3387 | return retval; | ||
3388 | } | ||
3389 | |||
3390 | /* PCI device parameters */ | ||
3391 | static const struct pci_device_id pci_id[] = { | ||
3392 | { | ||
3393 | PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x2096), | ||
3394 | .class = PCI_CLASS_SERIAL_USB_DEVICE, | ||
3395 | .class_mask = 0xffffffff, | ||
3396 | }, | ||
3397 | {}, | ||
3398 | }; | ||
3399 | MODULE_DEVICE_TABLE(pci, pci_id); | ||
3400 | |||
3401 | /* PCI functions */ | ||
3402 | static struct pci_driver udc_pci_driver = { | ||
3403 | .name = (char *) name, | ||
3404 | .id_table = pci_id, | ||
3405 | .probe = udc_pci_probe, | ||
3406 | .remove = udc_pci_remove, | ||
3407 | }; | ||
3408 | |||
3409 | module_pci_driver(udc_pci_driver); | ||
3410 | 3216 | ||
3411 | MODULE_DESCRIPTION(UDC_MOD_DESCRIPTION); | 3217 | MODULE_DESCRIPTION(UDC_MOD_DESCRIPTION); |
3412 | MODULE_AUTHOR("Thomas Dahlmann"); | 3218 | MODULE_AUTHOR("Thomas Dahlmann"); |
diff --git a/drivers/usb/gadget/udc/amd5536udc.h b/drivers/usb/gadget/udc/amd5536udc.h index 4638d707f169..fae49bf3833e 100644 --- a/drivers/usb/gadget/udc/amd5536udc.h +++ b/drivers/usb/gadget/udc/amd5536udc.h | |||
@@ -13,6 +13,12 @@ | |||
13 | #ifndef AMD5536UDC_H | 13 | #ifndef AMD5536UDC_H |
14 | #define AMD5536UDC_H | 14 | #define AMD5536UDC_H |
15 | 15 | ||
16 | /* debug control */ | ||
17 | /* #define UDC_VERBOSE */ | ||
18 | |||
19 | #include <linux/usb/ch9.h> | ||
20 | #include <linux/usb/gadget.h> | ||
21 | |||
16 | /* various constants */ | 22 | /* various constants */ |
17 | #define UDC_RDE_TIMER_SECONDS 1 | 23 | #define UDC_RDE_TIMER_SECONDS 1 |
18 | #define UDC_RDE_TIMER_DIV 10 | 24 | #define UDC_RDE_TIMER_DIV 10 |
@@ -545,8 +551,8 @@ struct udc { | |||
545 | u32 __iomem *txfifo; | 551 | u32 __iomem *txfifo; |
546 | 552 | ||
547 | /* DMA desc pools */ | 553 | /* DMA desc pools */ |
548 | struct pci_pool *data_requests; | 554 | struct dma_pool *data_requests; |
549 | struct pci_pool *stp_requests; | 555 | struct dma_pool *stp_requests; |
550 | 556 | ||
551 | /* device data */ | 557 | /* device data */ |
552 | unsigned long phys_addr; | 558 | unsigned long phys_addr; |
@@ -567,6 +573,36 @@ union udc_setup_data { | |||
567 | struct usb_ctrlrequest request; | 573 | struct usb_ctrlrequest request; |
568 | }; | 574 | }; |
569 | 575 | ||
576 | /* Function declarations */ | ||
577 | int udc_enable_dev_setup_interrupts(struct udc *dev); | ||
578 | int udc_mask_unused_interrupts(struct udc *dev); | ||
579 | irqreturn_t udc_irq(int irq, void *pdev); | ||
580 | void gadget_release(struct device *pdev); | ||
581 | void udc_basic_init(struct udc *dev); | ||
582 | void free_dma_pools(struct udc *dev); | ||
583 | int init_dma_pools(struct udc *dev); | ||
584 | void udc_remove(struct udc *dev); | ||
585 | int udc_probe(struct udc *dev); | ||
586 | |||
587 | /* DMA usage flag */ | ||
588 | static bool use_dma = 1; | ||
589 | /* packet per buffer dma */ | ||
590 | static bool use_dma_ppb = 1; | ||
591 | /* with per descr. update */ | ||
592 | static bool use_dma_ppb_du; | ||
593 | /* full speed only mode */ | ||
594 | static bool use_fullspeed; | ||
595 | |||
596 | /* module parameters */ | ||
597 | module_param(use_dma, bool, S_IRUGO); | ||
598 | MODULE_PARM_DESC(use_dma, "true for DMA"); | ||
599 | module_param(use_dma_ppb, bool, S_IRUGO); | ||
600 | MODULE_PARM_DESC(use_dma_ppb, "true for DMA in packet per buffer mode"); | ||
601 | module_param(use_dma_ppb_du, bool, S_IRUGO); | ||
602 | MODULE_PARM_DESC(use_dma_ppb_du, | ||
603 | "true for DMA in packet per buffer mode with descriptor update"); | ||
604 | module_param(use_fullspeed, bool, S_IRUGO); | ||
605 | MODULE_PARM_DESC(use_fullspeed, "true for fullspeed only"); | ||
570 | /* | 606 | /* |
571 | *--------------------------------------------------------------------------- | 607 | *--------------------------------------------------------------------------- |
572 | * SET and GET bitfields in u32 values | 608 | * SET and GET bitfields in u32 values |
diff --git a/drivers/usb/gadget/udc/amd5536udc_pci.c b/drivers/usb/gadget/udc/amd5536udc_pci.c new file mode 100644 index 000000000000..2a2d0a96fe24 --- /dev/null +++ b/drivers/usb/gadget/udc/amd5536udc_pci.c | |||
@@ -0,0 +1,217 @@ | |||
1 | /* | ||
2 | * amd5536udc_pci.c -- AMD 5536 UDC high/full speed USB device controller | ||
3 | * | ||
4 | * Copyright (C) 2005-2007 AMD (http://www.amd.com) | ||
5 | * Author: Thomas Dahlmann | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | /* | ||
14 | * The AMD5536 UDC is part of the x86 southbridge AMD Geode CS5536. | ||
15 | * It is a USB Highspeed DMA capable USB device controller. Beside ep0 it | ||
16 | * provides 4 IN and 4 OUT endpoints (bulk or interrupt type). | ||
17 | * | ||
18 | * Make sure that UDC is assigned to port 4 by BIOS settings (port can also | ||
19 | * be used as host port) and UOC bits PAD_EN and APU are set (should be done | ||
20 | * by BIOS init). | ||
21 | * | ||
22 | * UDC DMA requires 32-bit aligned buffers so DMA with gadget ether does not | ||
23 | * work without updating NET_IP_ALIGN. Or PIO mode (module param "use_dma=0") | ||
24 | * can be used with gadget ether. | ||
25 | * | ||
26 | * This file does pci device registration, and the core driver implementation | ||
27 | * is done in amd5536udc.c | ||
28 | * | ||
29 | * The driver is split so as to use the core UDC driver which is based on | ||
30 | * Synopsys device controller IP (different than HS OTG IP) in UDCs | ||
31 | * integrated to SoC platforms. | ||
32 | * | ||
33 | */ | ||
34 | |||
35 | /* Driver strings */ | ||
36 | #define UDC_MOD_DESCRIPTION "AMD 5536 UDC - USB Device Controller" | ||
37 | |||
38 | /* system */ | ||
39 | #include <linux/device.h> | ||
40 | #include <linux/dmapool.h> | ||
41 | #include <linux/interrupt.h> | ||
42 | #include <linux/io.h> | ||
43 | #include <linux/irq.h> | ||
44 | #include <linux/module.h> | ||
45 | #include <linux/moduleparam.h> | ||
46 | #include <linux/prefetch.h> | ||
47 | #include <linux/pci.h> | ||
48 | |||
49 | /* udc specific */ | ||
50 | #include "amd5536udc.h" | ||
51 | |||
52 | /* pointer to device object */ | ||
53 | static struct udc *udc; | ||
54 | |||
55 | /* description */ | ||
56 | static const char mod_desc[] = UDC_MOD_DESCRIPTION; | ||
57 | static const char name[] = "amd5536udc-pci"; | ||
58 | |||
59 | /* Reset all pci context */ | ||
60 | static void udc_pci_remove(struct pci_dev *pdev) | ||
61 | { | ||
62 | struct udc *dev; | ||
63 | |||
64 | dev = pci_get_drvdata(pdev); | ||
65 | |||
66 | usb_del_gadget_udc(&udc->gadget); | ||
67 | /* gadget driver must not be registered */ | ||
68 | if (WARN_ON(dev->driver)) | ||
69 | return; | ||
70 | |||
71 | /* dma pool cleanup */ | ||
72 | free_dma_pools(dev); | ||
73 | |||
74 | /* reset controller */ | ||
75 | writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg); | ||
76 | free_irq(pdev->irq, dev); | ||
77 | iounmap(dev->virt_addr); | ||
78 | release_mem_region(pci_resource_start(pdev, 0), | ||
79 | pci_resource_len(pdev, 0)); | ||
80 | pci_disable_device(pdev); | ||
81 | |||
82 | udc_remove(dev); | ||
83 | } | ||
84 | |||
85 | /* Called by pci bus driver to init pci context */ | ||
86 | static int udc_pci_probe( | ||
87 | struct pci_dev *pdev, | ||
88 | const struct pci_device_id *id | ||
89 | ) | ||
90 | { | ||
91 | struct udc *dev; | ||
92 | unsigned long resource; | ||
93 | unsigned long len; | ||
94 | int retval = 0; | ||
95 | |||
96 | /* one udc only */ | ||
97 | if (udc) { | ||
98 | dev_dbg(&pdev->dev, "already probed\n"); | ||
99 | return -EBUSY; | ||
100 | } | ||
101 | |||
102 | /* init */ | ||
103 | dev = kzalloc(sizeof(struct udc), GFP_KERNEL); | ||
104 | if (!dev) | ||
105 | return -ENOMEM; | ||
106 | |||
107 | /* pci setup */ | ||
108 | if (pci_enable_device(pdev) < 0) { | ||
109 | retval = -ENODEV; | ||
110 | goto err_pcidev; | ||
111 | } | ||
112 | |||
113 | /* PCI resource allocation */ | ||
114 | resource = pci_resource_start(pdev, 0); | ||
115 | len = pci_resource_len(pdev, 0); | ||
116 | |||
117 | if (!request_mem_region(resource, len, name)) { | ||
118 | dev_dbg(&pdev->dev, "pci device used already\n"); | ||
119 | retval = -EBUSY; | ||
120 | goto err_memreg; | ||
121 | } | ||
122 | |||
123 | dev->virt_addr = ioremap_nocache(resource, len); | ||
124 | if (!dev->virt_addr) { | ||
125 | dev_dbg(&pdev->dev, "start address cannot be mapped\n"); | ||
126 | retval = -EFAULT; | ||
127 | goto err_ioremap; | ||
128 | } | ||
129 | |||
130 | if (!pdev->irq) { | ||
131 | dev_err(&pdev->dev, "irq not set\n"); | ||
132 | retval = -ENODEV; | ||
133 | goto err_irq; | ||
134 | } | ||
135 | |||
136 | spin_lock_init(&dev->lock); | ||
137 | /* udc csr registers base */ | ||
138 | dev->csr = dev->virt_addr + UDC_CSR_ADDR; | ||
139 | /* dev registers base */ | ||
140 | dev->regs = dev->virt_addr + UDC_DEVCFG_ADDR; | ||
141 | /* ep registers base */ | ||
142 | dev->ep_regs = dev->virt_addr + UDC_EPREGS_ADDR; | ||
143 | /* fifo's base */ | ||
144 | dev->rxfifo = (u32 __iomem *)(dev->virt_addr + UDC_RXFIFO_ADDR); | ||
145 | dev->txfifo = (u32 __iomem *)(dev->virt_addr + UDC_TXFIFO_ADDR); | ||
146 | |||
147 | if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) { | ||
148 | dev_dbg(&pdev->dev, "request_irq(%d) fail\n", pdev->irq); | ||
149 | retval = -EBUSY; | ||
150 | goto err_irq; | ||
151 | } | ||
152 | |||
153 | pci_set_drvdata(pdev, dev); | ||
154 | |||
155 | /* chip revision for Hs AMD5536 */ | ||
156 | dev->chiprev = pdev->revision; | ||
157 | |||
158 | pci_set_master(pdev); | ||
159 | pci_try_set_mwi(pdev); | ||
160 | |||
161 | /* init dma pools */ | ||
162 | if (use_dma) { | ||
163 | retval = init_dma_pools(dev); | ||
164 | if (retval != 0) | ||
165 | goto err_dma; | ||
166 | } | ||
167 | |||
168 | dev->phys_addr = resource; | ||
169 | dev->irq = pdev->irq; | ||
170 | dev->pdev = pdev; | ||
171 | |||
172 | /* general probing */ | ||
173 | if (udc_probe(dev)) { | ||
174 | retval = -ENODEV; | ||
175 | goto err_probe; | ||
176 | } | ||
177 | return 0; | ||
178 | |||
179 | err_probe: | ||
180 | if (use_dma) | ||
181 | free_dma_pools(dev); | ||
182 | err_dma: | ||
183 | free_irq(pdev->irq, dev); | ||
184 | err_irq: | ||
185 | iounmap(dev->virt_addr); | ||
186 | err_ioremap: | ||
187 | release_mem_region(resource, len); | ||
188 | err_memreg: | ||
189 | pci_disable_device(pdev); | ||
190 | err_pcidev: | ||
191 | kfree(dev); | ||
192 | return retval; | ||
193 | } | ||
194 | |||
195 | /* PCI device parameters */ | ||
196 | static const struct pci_device_id pci_id[] = { | ||
197 | { | ||
198 | PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x2096), | ||
199 | .class = PCI_CLASS_SERIAL_USB_DEVICE, | ||
200 | .class_mask = 0xffffffff, | ||
201 | }, | ||
202 | {}, | ||
203 | }; | ||
204 | MODULE_DEVICE_TABLE(pci, pci_id); | ||
205 | |||
206 | /* PCI functions */ | ||
207 | static struct pci_driver udc_pci_driver = { | ||
208 | .name = (char *) name, | ||
209 | .id_table = pci_id, | ||
210 | .probe = udc_pci_probe, | ||
211 | .remove = udc_pci_remove, | ||
212 | }; | ||
213 | module_pci_driver(udc_pci_driver); | ||
214 | |||
215 | MODULE_DESCRIPTION(UDC_MOD_DESCRIPTION); | ||
216 | MODULE_AUTHOR("Thomas Dahlmann"); | ||
217 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index 2035906b8ced..3ccc34176a5a 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c | |||
@@ -321,7 +321,6 @@ static inline void usba_cleanup_debugfs(struct usba_udc *udc) | |||
321 | 321 | ||
322 | static ushort fifo_mode; | 322 | static ushort fifo_mode; |
323 | 323 | ||
324 | /* "modprobe ... fifo_mode=1" etc */ | ||
325 | module_param(fifo_mode, ushort, 0x0); | 324 | module_param(fifo_mode, ushort, 0x0); |
326 | MODULE_PARM_DESC(fifo_mode, "Endpoint configuration mode"); | 325 | MODULE_PARM_DESC(fifo_mode, "Endpoint configuration mode"); |
327 | 326 | ||
@@ -371,7 +370,7 @@ static struct usba_fifo_cfg mode_4_cfg[] = { | |||
371 | }; | 370 | }; |
372 | /* Add additional configurations here */ | 371 | /* Add additional configurations here */ |
373 | 372 | ||
374 | int usba_config_fifo_table(struct usba_udc *udc) | 373 | static int usba_config_fifo_table(struct usba_udc *udc) |
375 | { | 374 | { |
376 | int n; | 375 | int n; |
377 | 376 | ||
@@ -1076,11 +1075,9 @@ static int atmel_usba_start(struct usb_gadget *gadget, | |||
1076 | struct usb_gadget_driver *driver); | 1075 | struct usb_gadget_driver *driver); |
1077 | static int atmel_usba_stop(struct usb_gadget *gadget); | 1076 | static int atmel_usba_stop(struct usb_gadget *gadget); |
1078 | 1077 | ||
1079 | static struct usb_ep *atmel_usba_match_ep( | 1078 | static struct usb_ep *atmel_usba_match_ep(struct usb_gadget *gadget, |
1080 | struct usb_gadget *gadget, | 1079 | struct usb_endpoint_descriptor *desc, |
1081 | struct usb_endpoint_descriptor *desc, | 1080 | struct usb_ss_ep_comp_descriptor *ep_comp) |
1082 | struct usb_ss_ep_comp_descriptor *ep_comp | ||
1083 | ) | ||
1084 | { | 1081 | { |
1085 | struct usb_ep *_ep; | 1082 | struct usb_ep *_ep; |
1086 | struct usba_ep *ep; | 1083 | struct usba_ep *ep; |
@@ -1100,7 +1097,6 @@ found_ep: | |||
1100 | ep = to_usba_ep(_ep); | 1097 | ep = to_usba_ep(_ep); |
1101 | 1098 | ||
1102 | switch (usb_endpoint_type(desc)) { | 1099 | switch (usb_endpoint_type(desc)) { |
1103 | |||
1104 | case USB_ENDPOINT_XFER_CONTROL: | 1100 | case USB_ENDPOINT_XFER_CONTROL: |
1105 | break; | 1101 | break; |
1106 | 1102 | ||
@@ -1141,7 +1137,7 @@ found_ep: | |||
1141 | ep->udc->configured_ep++; | 1137 | ep->udc->configured_ep++; |
1142 | } | 1138 | } |
1143 | 1139 | ||
1144 | return _ep; | 1140 | return _ep; |
1145 | } | 1141 | } |
1146 | 1142 | ||
1147 | static const struct usb_gadget_ops usba_udc_ops = { | 1143 | static const struct usb_gadget_ops usba_udc_ops = { |
@@ -1855,8 +1851,8 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) | |||
1855 | * but it's clearly harmless... | 1851 | * but it's clearly harmless... |
1856 | */ | 1852 | */ |
1857 | if (!(usba_ep_readl(ep0, CFG) & USBA_EPT_MAPPED)) | 1853 | if (!(usba_ep_readl(ep0, CFG) & USBA_EPT_MAPPED)) |
1858 | dev_dbg(&udc->pdev->dev, | 1854 | dev_err(&udc->pdev->dev, |
1859 | "ODD: EP0 configuration is invalid!\n"); | 1855 | "ODD: EP0 configuration is invalid!\n"); |
1860 | 1856 | ||
1861 | /* Preallocate other endpoints */ | 1857 | /* Preallocate other endpoints */ |
1862 | n = fifo_mode ? udc->num_ep : udc->configured_ep; | 1858 | n = fifo_mode ? udc->num_ep : udc->configured_ep; |
@@ -1864,8 +1860,8 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) | |||
1864 | ep = &udc->usba_ep[i]; | 1860 | ep = &udc->usba_ep[i]; |
1865 | usba_ep_writel(ep, CFG, ep->ept_cfg); | 1861 | usba_ep_writel(ep, CFG, ep->ept_cfg); |
1866 | if (!(usba_ep_readl(ep, CFG) & USBA_EPT_MAPPED)) | 1862 | if (!(usba_ep_readl(ep, CFG) & USBA_EPT_MAPPED)) |
1867 | dev_dbg(&udc->pdev->dev, | 1863 | dev_err(&udc->pdev->dev, |
1868 | "ODD: EP%d configuration is invalid!\n", i); | 1864 | "ODD: EP%d configuration is invalid!\n", i); |
1869 | } | 1865 | } |
1870 | } | 1866 | } |
1871 | 1867 | ||
@@ -2089,8 +2085,9 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, | |||
2089 | while ((pp = of_get_next_child(np, pp))) | 2085 | while ((pp = of_get_next_child(np, pp))) |
2090 | udc->num_ep++; | 2086 | udc->num_ep++; |
2091 | udc->configured_ep = 1; | 2087 | udc->configured_ep = 1; |
2092 | } else | 2088 | } else { |
2093 | udc->num_ep = usba_config_fifo_table(udc); | 2089 | udc->num_ep = usba_config_fifo_table(udc); |
2090 | } | ||
2094 | 2091 | ||
2095 | eps = devm_kzalloc(&pdev->dev, sizeof(struct usba_ep) * udc->num_ep, | 2092 | eps = devm_kzalloc(&pdev->dev, sizeof(struct usba_ep) * udc->num_ep, |
2096 | GFP_KERNEL); | 2093 | GFP_KERNEL); |
@@ -2118,14 +2115,34 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, | |||
2118 | dev_err(&pdev->dev, "of_probe: fifo-size error(%d)\n", ret); | 2115 | dev_err(&pdev->dev, "of_probe: fifo-size error(%d)\n", ret); |
2119 | goto err; | 2116 | goto err; |
2120 | } | 2117 | } |
2121 | ep->fifo_size = fifo_mode ? udc->fifo_cfg[i].fifo_size : val; | 2118 | if (fifo_mode) { |
2119 | if (val < udc->fifo_cfg[i].fifo_size) { | ||
2120 | dev_warn(&pdev->dev, | ||
2121 | "Using max fifo-size value from DT\n"); | ||
2122 | ep->fifo_size = val; | ||
2123 | } else { | ||
2124 | ep->fifo_size = udc->fifo_cfg[i].fifo_size; | ||
2125 | } | ||
2126 | } else { | ||
2127 | ep->fifo_size = val; | ||
2128 | } | ||
2122 | 2129 | ||
2123 | ret = of_property_read_u32(pp, "atmel,nb-banks", &val); | 2130 | ret = of_property_read_u32(pp, "atmel,nb-banks", &val); |
2124 | if (ret) { | 2131 | if (ret) { |
2125 | dev_err(&pdev->dev, "of_probe: nb-banks error(%d)\n", ret); | 2132 | dev_err(&pdev->dev, "of_probe: nb-banks error(%d)\n", ret); |
2126 | goto err; | 2133 | goto err; |
2127 | } | 2134 | } |
2128 | ep->nr_banks = fifo_mode ? udc->fifo_cfg[i].nr_banks : val; | 2135 | if (fifo_mode) { |
2136 | if (val < udc->fifo_cfg[i].nr_banks) { | ||
2137 | dev_warn(&pdev->dev, | ||
2138 | "Using max nb-banks value from DT\n"); | ||
2139 | ep->nr_banks = val; | ||
2140 | } else { | ||
2141 | ep->nr_banks = udc->fifo_cfg[i].nr_banks; | ||
2142 | } | ||
2143 | } else { | ||
2144 | ep->nr_banks = val; | ||
2145 | } | ||
2129 | 2146 | ||
2130 | ep->can_dma = of_property_read_bool(pp, "atmel,can-dma"); | 2147 | ep->can_dma = of_property_read_bool(pp, "atmel,can-dma"); |
2131 | ep->can_isoc = of_property_read_bool(pp, "atmel,can-isoc"); | 2148 | ep->can_isoc = of_property_read_bool(pp, "atmel,can-isoc"); |
diff --git a/drivers/usb/gadget/udc/bdc/Kconfig b/drivers/usb/gadget/udc/bdc/Kconfig index 0d7b8c9f72fd..eb8b55392360 100644 --- a/drivers/usb/gadget/udc/bdc/Kconfig +++ b/drivers/usb/gadget/udc/bdc/Kconfig | |||
@@ -14,7 +14,7 @@ if USB_BDC_UDC | |||
14 | comment "Platform Support" | 14 | comment "Platform Support" |
15 | config USB_BDC_PCI | 15 | config USB_BDC_PCI |
16 | tristate "BDC support for PCIe based platforms" | 16 | tristate "BDC support for PCIe based platforms" |
17 | depends on PCI | 17 | depends on USB_PCI |
18 | default USB_BDC_UDC | 18 | default USB_BDC_UDC |
19 | help | 19 | help |
20 | Enable support for platforms which have BDC connected through PCIe, such as Lego3 FPGA platform. | 20 | Enable support for platforms which have BDC connected through PCIe, such as Lego3 FPGA platform. |
diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index d685d82dcf48..efce68e9a8e0 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c | |||
@@ -1273,6 +1273,7 @@ void usb_del_gadget_udc(struct usb_gadget *gadget) | |||
1273 | flush_work(&gadget->work); | 1273 | flush_work(&gadget->work); |
1274 | device_unregister(&udc->dev); | 1274 | device_unregister(&udc->dev); |
1275 | device_unregister(&gadget->dev); | 1275 | device_unregister(&gadget->dev); |
1276 | memset(&gadget->dev, 0x00, sizeof(gadget->dev)); | ||
1276 | } | 1277 | } |
1277 | EXPORT_SYMBOL_GPL(usb_del_gadget_udc); | 1278 | EXPORT_SYMBOL_GPL(usb_del_gadget_udc); |
1278 | 1279 | ||
diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c index 8cabc5944d5f..c79081952ea0 100644 --- a/drivers/usb/gadget/udc/dummy_hcd.c +++ b/drivers/usb/gadget/udc/dummy_hcd.c | |||
@@ -2062,16 +2062,13 @@ static int dummy_hub_control( | |||
2062 | } | 2062 | } |
2063 | break; | 2063 | break; |
2064 | case USB_PORT_FEAT_POWER: | 2064 | case USB_PORT_FEAT_POWER: |
2065 | if (hcd->speed == HCD_USB3) { | 2065 | dev_dbg(dummy_dev(dum_hcd), "power-off\n"); |
2066 | if (dum_hcd->port_status & USB_PORT_STAT_POWER) | 2066 | if (hcd->speed == HCD_USB3) |
2067 | dev_dbg(dummy_dev(dum_hcd), | 2067 | dum_hcd->port_status &= ~USB_SS_PORT_STAT_POWER; |
2068 | "power-off\n"); | 2068 | else |
2069 | } else | 2069 | dum_hcd->port_status &= ~USB_PORT_STAT_POWER; |
2070 | if (dum_hcd->port_status & | 2070 | set_link_state(dum_hcd); |
2071 | USB_SS_PORT_STAT_POWER) | 2071 | break; |
2072 | dev_dbg(dummy_dev(dum_hcd), | ||
2073 | "power-off\n"); | ||
2074 | /* FALLS THROUGH */ | ||
2075 | default: | 2072 | default: |
2076 | dum_hcd->port_status &= ~(1 << wValue); | 2073 | dum_hcd->port_status &= ~(1 << wValue); |
2077 | set_link_state(dum_hcd); | 2074 | set_link_state(dum_hcd); |
@@ -2242,14 +2239,13 @@ static int dummy_hub_control( | |||
2242 | if ((dum_hcd->port_status & | 2239 | if ((dum_hcd->port_status & |
2243 | USB_SS_PORT_STAT_POWER) != 0) { | 2240 | USB_SS_PORT_STAT_POWER) != 0) { |
2244 | dum_hcd->port_status |= (1 << wValue); | 2241 | dum_hcd->port_status |= (1 << wValue); |
2245 | set_link_state(dum_hcd); | ||
2246 | } | 2242 | } |
2247 | } else | 2243 | } else |
2248 | if ((dum_hcd->port_status & | 2244 | if ((dum_hcd->port_status & |
2249 | USB_PORT_STAT_POWER) != 0) { | 2245 | USB_PORT_STAT_POWER) != 0) { |
2250 | dum_hcd->port_status |= (1 << wValue); | 2246 | dum_hcd->port_status |= (1 << wValue); |
2251 | set_link_state(dum_hcd); | ||
2252 | } | 2247 | } |
2248 | set_link_state(dum_hcd); | ||
2253 | } | 2249 | } |
2254 | break; | 2250 | break; |
2255 | case GetPortErrorCount: | 2251 | case GetPortErrorCount: |
diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c index b76fcdb763a0..6f2f71c054be 100644 --- a/drivers/usb/gadget/udc/fsl_udc_core.c +++ b/drivers/usb/gadget/udc/fsl_udc_core.c | |||
@@ -2676,6 +2676,8 @@ static const struct platform_device_id fsl_udc_devtype[] = { | |||
2676 | }, { | 2676 | }, { |
2677 | .name = "imx-udc-mx51", | 2677 | .name = "imx-udc-mx51", |
2678 | }, { | 2678 | }, { |
2679 | .name = "fsl-usb2-udc", | ||
2680 | }, { | ||
2679 | /* sentinel */ | 2681 | /* sentinel */ |
2680 | } | 2682 | } |
2681 | }; | 2683 | }; |
diff --git a/drivers/usb/gadget/udc/mv_u3d_core.c b/drivers/usb/gadget/udc/mv_u3d_core.c index d365449a295a..772049afe166 100644 --- a/drivers/usb/gadget/udc/mv_u3d_core.c +++ b/drivers/usb/gadget/udc/mv_u3d_core.c | |||
@@ -1835,13 +1835,18 @@ static int mv_u3d_probe(struct platform_device *dev) | |||
1835 | } | 1835 | } |
1836 | 1836 | ||
1837 | /* we will access controller register, so enable the u3d controller */ | 1837 | /* we will access controller register, so enable the u3d controller */ |
1838 | clk_enable(u3d->clk); | 1838 | retval = clk_enable(u3d->clk); |
1839 | if (retval) { | ||
1840 | dev_err(&dev->dev, "clk_enable error %d\n", retval); | ||
1841 | goto err_u3d_enable; | ||
1842 | } | ||
1839 | 1843 | ||
1840 | if (pdata->phy_init) { | 1844 | if (pdata->phy_init) { |
1841 | retval = pdata->phy_init(u3d->phy_regs); | 1845 | retval = pdata->phy_init(u3d->phy_regs); |
1842 | if (retval) { | 1846 | if (retval) { |
1843 | dev_err(&dev->dev, "init phy error %d\n", retval); | 1847 | dev_err(&dev->dev, "init phy error %d\n", retval); |
1844 | goto err_u3d_enable; | 1848 | clk_disable(u3d->clk); |
1849 | goto err_phy_init; | ||
1845 | } | 1850 | } |
1846 | } | 1851 | } |
1847 | 1852 | ||
@@ -1974,15 +1979,13 @@ err_alloc_trb_pool: | |||
1974 | dma_free_coherent(&dev->dev, u3d->ep_context_size, | 1979 | dma_free_coherent(&dev->dev, u3d->ep_context_size, |
1975 | u3d->ep_context, u3d->ep_context_dma); | 1980 | u3d->ep_context, u3d->ep_context_dma); |
1976 | err_alloc_ep_context: | 1981 | err_alloc_ep_context: |
1977 | if (pdata->phy_deinit) | 1982 | err_phy_init: |
1978 | pdata->phy_deinit(u3d->phy_regs); | ||
1979 | clk_disable(u3d->clk); | ||
1980 | err_u3d_enable: | 1983 | err_u3d_enable: |
1981 | iounmap(u3d->cap_regs); | 1984 | iounmap(u3d->cap_regs); |
1982 | err_map_cap_regs: | 1985 | err_map_cap_regs: |
1983 | err_get_cap_regs: | 1986 | err_get_cap_regs: |
1984 | err_get_clk: | ||
1985 | clk_put(u3d->clk); | 1987 | clk_put(u3d->clk); |
1988 | err_get_clk: | ||
1986 | kfree(u3d); | 1989 | kfree(u3d); |
1987 | err_alloc_private: | 1990 | err_alloc_private: |
1988 | err_pdata: | 1991 | err_pdata: |
diff --git a/drivers/usb/gadget/udc/mv_udc_core.c b/drivers/usb/gadget/udc/mv_udc_core.c index 27ebb0d5449d..76f56c5762f9 100644 --- a/drivers/usb/gadget/udc/mv_udc_core.c +++ b/drivers/usb/gadget/udc/mv_udc_core.c | |||
@@ -445,7 +445,8 @@ static int mv_ep_enable(struct usb_ep *_ep, | |||
445 | struct mv_dqh *dqh; | 445 | struct mv_dqh *dqh; |
446 | u16 max = 0; | 446 | u16 max = 0; |
447 | u32 bit_pos, epctrlx, direction; | 447 | u32 bit_pos, epctrlx, direction; |
448 | unsigned char zlt = 0, ios = 0, mult = 0; | 448 | const unsigned char zlt = 1; |
449 | unsigned char ios, mult; | ||
449 | unsigned long flags; | 450 | unsigned long flags; |
450 | 451 | ||
451 | ep = container_of(_ep, struct mv_ep, ep); | 452 | ep = container_of(_ep, struct mv_ep, ep); |
@@ -465,8 +466,6 @@ static int mv_ep_enable(struct usb_ep *_ep, | |||
465 | * disable HW zero length termination select | 466 | * disable HW zero length termination select |
466 | * driver handles zero length packet through req->req.zero | 467 | * driver handles zero length packet through req->req.zero |
467 | */ | 468 | */ |
468 | zlt = 1; | ||
469 | |||
470 | bit_pos = 1 << ((direction == EP_DIR_OUT ? 0 : 16) + ep->ep_num); | 469 | bit_pos = 1 << ((direction == EP_DIR_OUT ? 0 : 16) + ep->ep_num); |
471 | 470 | ||
472 | /* Check if the Endpoint is Primed */ | 471 | /* Check if the Endpoint is Primed */ |
@@ -481,16 +480,16 @@ static int mv_ep_enable(struct usb_ep *_ep, | |||
481 | (unsigned)bit_pos); | 480 | (unsigned)bit_pos); |
482 | goto en_done; | 481 | goto en_done; |
483 | } | 482 | } |
483 | |||
484 | /* Set the max packet length, interrupt on Setup and Mult fields */ | 484 | /* Set the max packet length, interrupt on Setup and Mult fields */ |
485 | ios = 0; | ||
486 | mult = 0; | ||
485 | switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { | 487 | switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { |
486 | case USB_ENDPOINT_XFER_BULK: | 488 | case USB_ENDPOINT_XFER_BULK: |
487 | zlt = 1; | 489 | case USB_ENDPOINT_XFER_INT: |
488 | mult = 0; | ||
489 | break; | 490 | break; |
490 | case USB_ENDPOINT_XFER_CONTROL: | 491 | case USB_ENDPOINT_XFER_CONTROL: |
491 | ios = 1; | 492 | ios = 1; |
492 | case USB_ENDPOINT_XFER_INT: | ||
493 | mult = 0; | ||
494 | break; | 493 | break; |
495 | case USB_ENDPOINT_XFER_ISOC: | 494 | case USB_ENDPOINT_XFER_ISOC: |
496 | /* Calculate transactions needed for high bandwidth iso */ | 495 | /* Calculate transactions needed for high bandwidth iso */ |
diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c index 7dc0102abdfe..8f85a51bd2b3 100644 --- a/drivers/usb/gadget/udc/net2272.c +++ b/drivers/usb/gadget/udc/net2272.c | |||
@@ -653,7 +653,7 @@ net2272_request_dma(struct net2272 *dev, unsigned ep, u32 buf, | |||
653 | dev->dma_busy = 1; | 653 | dev->dma_busy = 1; |
654 | 654 | ||
655 | /* initialize platform's dma */ | 655 | /* initialize platform's dma */ |
656 | #ifdef CONFIG_PCI | 656 | #ifdef CONFIG_USB_PCI |
657 | /* NET2272 addr, buffer addr, length, etc. */ | 657 | /* NET2272 addr, buffer addr, length, etc. */ |
658 | switch (dev->dev_id) { | 658 | switch (dev->dev_id) { |
659 | case PCI_DEVICE_ID_RDK1: | 659 | case PCI_DEVICE_ID_RDK1: |
@@ -701,7 +701,7 @@ static void | |||
701 | net2272_start_dma(struct net2272 *dev) | 701 | net2272_start_dma(struct net2272 *dev) |
702 | { | 702 | { |
703 | /* start platform's dma controller */ | 703 | /* start platform's dma controller */ |
704 | #ifdef CONFIG_PCI | 704 | #ifdef CONFIG_USB_PCI |
705 | switch (dev->dev_id) { | 705 | switch (dev->dev_id) { |
706 | case PCI_DEVICE_ID_RDK1: | 706 | case PCI_DEVICE_ID_RDK1: |
707 | writeb((1 << CHANNEL_ENABLE) | (1 << CHANNEL_START), | 707 | writeb((1 << CHANNEL_ENABLE) | (1 << CHANNEL_START), |
@@ -797,7 +797,7 @@ net2272_kick_dma(struct net2272_ep *ep, struct net2272_request *req) | |||
797 | 797 | ||
798 | static void net2272_cancel_dma(struct net2272 *dev) | 798 | static void net2272_cancel_dma(struct net2272 *dev) |
799 | { | 799 | { |
800 | #ifdef CONFIG_PCI | 800 | #ifdef CONFIG_USB_PCI |
801 | switch (dev->dev_id) { | 801 | switch (dev->dev_id) { |
802 | case PCI_DEVICE_ID_RDK1: | 802 | case PCI_DEVICE_ID_RDK1: |
803 | writeb(0, dev->rdk1.plx9054_base_addr + DMACSR0); | 803 | writeb(0, dev->rdk1.plx9054_base_addr + DMACSR0); |
@@ -2306,7 +2306,7 @@ err_add_udc: | |||
2306 | return ret; | 2306 | return ret; |
2307 | } | 2307 | } |
2308 | 2308 | ||
2309 | #ifdef CONFIG_PCI | 2309 | #ifdef CONFIG_USB_PCI |
2310 | 2310 | ||
2311 | /* | 2311 | /* |
2312 | * wrap this driver around the specified device, but | 2312 | * wrap this driver around the specified device, but |
diff --git a/drivers/usb/gadget/udc/net2272.h b/drivers/usb/gadget/udc/net2272.h index 127ab03fcde3..69bc9c3c6ce4 100644 --- a/drivers/usb/gadget/udc/net2272.h +++ b/drivers/usb/gadget/udc/net2272.h | |||
@@ -472,7 +472,7 @@ struct net2272 { | |||
472 | unsigned int base_shift; | 472 | unsigned int base_shift; |
473 | u16 __iomem *base_addr; | 473 | u16 __iomem *base_addr; |
474 | union { | 474 | union { |
475 | #ifdef CONFIG_PCI | 475 | #ifdef CONFIG_USB_PCI |
476 | struct { | 476 | struct { |
477 | void __iomem *plx9054_base_addr; | 477 | void __iomem *plx9054_base_addr; |
478 | void __iomem *epld_base_addr; | 478 | void __iomem *epld_base_addr; |
diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c index 3828c2ec8623..6cf07857eaca 100644 --- a/drivers/usb/gadget/udc/net2280.c +++ b/drivers/usb/gadget/udc/net2280.c | |||
@@ -569,7 +569,7 @@ static struct usb_request | |||
569 | if (ep->dma) { | 569 | if (ep->dma) { |
570 | struct net2280_dma *td; | 570 | struct net2280_dma *td; |
571 | 571 | ||
572 | td = pci_pool_alloc(ep->dev->requests, gfp_flags, | 572 | td = dma_pool_alloc(ep->dev->requests, gfp_flags, |
573 | &req->td_dma); | 573 | &req->td_dma); |
574 | if (!td) { | 574 | if (!td) { |
575 | kfree(req); | 575 | kfree(req); |
@@ -597,7 +597,7 @@ static void net2280_free_request(struct usb_ep *_ep, struct usb_request *_req) | |||
597 | req = container_of(_req, struct net2280_request, req); | 597 | req = container_of(_req, struct net2280_request, req); |
598 | WARN_ON(!list_empty(&req->queue)); | 598 | WARN_ON(!list_empty(&req->queue)); |
599 | if (req->td) | 599 | if (req->td) |
600 | pci_pool_free(ep->dev->requests, req->td, req->td_dma); | 600 | dma_pool_free(ep->dev->requests, req->td, req->td_dma); |
601 | kfree(req); | 601 | kfree(req); |
602 | } | 602 | } |
603 | 603 | ||
@@ -3579,10 +3579,10 @@ static void net2280_remove(struct pci_dev *pdev) | |||
3579 | for (i = 1; i < 5; i++) { | 3579 | for (i = 1; i < 5; i++) { |
3580 | if (!dev->ep[i].dummy) | 3580 | if (!dev->ep[i].dummy) |
3581 | continue; | 3581 | continue; |
3582 | pci_pool_free(dev->requests, dev->ep[i].dummy, | 3582 | dma_pool_free(dev->requests, dev->ep[i].dummy, |
3583 | dev->ep[i].td_dma); | 3583 | dev->ep[i].td_dma); |
3584 | } | 3584 | } |
3585 | pci_pool_destroy(dev->requests); | 3585 | dma_pool_destroy(dev->requests); |
3586 | } | 3586 | } |
3587 | if (dev->got_irq) | 3587 | if (dev->got_irq) |
3588 | free_irq(pdev->irq, dev); | 3588 | free_irq(pdev->irq, dev); |
@@ -3724,7 +3724,7 @@ static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
3724 | 3724 | ||
3725 | /* DMA setup */ | 3725 | /* DMA setup */ |
3726 | /* NOTE: we know only the 32 LSBs of dma addresses may be nonzero */ | 3726 | /* NOTE: we know only the 32 LSBs of dma addresses may be nonzero */ |
3727 | dev->requests = pci_pool_create("requests", pdev, | 3727 | dev->requests = dma_pool_create("requests", &pdev->dev, |
3728 | sizeof(struct net2280_dma), | 3728 | sizeof(struct net2280_dma), |
3729 | 0 /* no alignment requirements */, | 3729 | 0 /* no alignment requirements */, |
3730 | 0 /* or page-crossing issues */); | 3730 | 0 /* or page-crossing issues */); |
@@ -3736,7 +3736,7 @@ static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
3736 | for (i = 1; i < 5; i++) { | 3736 | for (i = 1; i < 5; i++) { |
3737 | struct net2280_dma *td; | 3737 | struct net2280_dma *td; |
3738 | 3738 | ||
3739 | td = pci_pool_alloc(dev->requests, GFP_KERNEL, | 3739 | td = dma_pool_alloc(dev->requests, GFP_KERNEL, |
3740 | &dev->ep[i].td_dma); | 3740 | &dev->ep[i].td_dma); |
3741 | if (!td) { | 3741 | if (!td) { |
3742 | ep_dbg(dev, "can't get dummy %d\n", i); | 3742 | ep_dbg(dev, "can't get dummy %d\n", i); |
diff --git a/drivers/usb/gadget/udc/net2280.h b/drivers/usb/gadget/udc/net2280.h index 2736a95751c3..1088c3745999 100644 --- a/drivers/usb/gadget/udc/net2280.h +++ b/drivers/usb/gadget/udc/net2280.h | |||
@@ -187,7 +187,7 @@ struct net2280 { | |||
187 | struct usb338x_ll_chi_regs __iomem *ll_chicken_reg; | 187 | struct usb338x_ll_chi_regs __iomem *ll_chicken_reg; |
188 | struct usb338x_pl_regs __iomem *plregs; | 188 | struct usb338x_pl_regs __iomem *plregs; |
189 | 189 | ||
190 | struct pci_pool *requests; | 190 | struct dma_pool *requests; |
191 | /* statistics...*/ | 191 | /* statistics...*/ |
192 | }; | 192 | }; |
193 | 193 | ||
diff --git a/drivers/usb/gadget/udc/pch_udc.c b/drivers/usb/gadget/udc/pch_udc.c index 8a365aad66fe..84dcbcd756f0 100644 --- a/drivers/usb/gadget/udc/pch_udc.c +++ b/drivers/usb/gadget/udc/pch_udc.c | |||
@@ -355,8 +355,8 @@ struct pch_udc_dev { | |||
355 | vbus_session:1, | 355 | vbus_session:1, |
356 | set_cfg_not_acked:1, | 356 | set_cfg_not_acked:1, |
357 | waiting_zlp_ack:1; | 357 | waiting_zlp_ack:1; |
358 | struct pci_pool *data_requests; | 358 | struct dma_pool *data_requests; |
359 | struct pci_pool *stp_requests; | 359 | struct dma_pool *stp_requests; |
360 | dma_addr_t dma_addr; | 360 | dma_addr_t dma_addr; |
361 | struct usb_ctrlrequest setup_data; | 361 | struct usb_ctrlrequest setup_data; |
362 | void __iomem *base_addr; | 362 | void __iomem *base_addr; |
@@ -1522,7 +1522,8 @@ static void pch_udc_free_dma_chain(struct pch_udc_dev *dev, | |||
1522 | /* do not free first desc., will be done by free for request */ | 1522 | /* do not free first desc., will be done by free for request */ |
1523 | td = phys_to_virt(addr); | 1523 | td = phys_to_virt(addr); |
1524 | addr2 = (dma_addr_t)td->next; | 1524 | addr2 = (dma_addr_t)td->next; |
1525 | pci_pool_free(dev->data_requests, td, addr); | 1525 | dma_pool_free(dev->data_requests, td, addr); |
1526 | td->next = 0x00; | ||
1526 | addr = addr2; | 1527 | addr = addr2; |
1527 | } | 1528 | } |
1528 | req->chain_len = 1; | 1529 | req->chain_len = 1; |
@@ -1538,7 +1539,7 @@ static void pch_udc_free_dma_chain(struct pch_udc_dev *dev, | |||
1538 | * | 1539 | * |
1539 | * Return codes: | 1540 | * Return codes: |
1540 | * 0: success, | 1541 | * 0: success, |
1541 | * -ENOMEM: pci_pool_alloc invocation fails | 1542 | * -ENOMEM: dma_pool_alloc invocation fails |
1542 | */ | 1543 | */ |
1543 | static int pch_udc_create_dma_chain(struct pch_udc_ep *ep, | 1544 | static int pch_udc_create_dma_chain(struct pch_udc_ep *ep, |
1544 | struct pch_udc_request *req, | 1545 | struct pch_udc_request *req, |
@@ -1564,7 +1565,7 @@ static int pch_udc_create_dma_chain(struct pch_udc_ep *ep, | |||
1564 | if (bytes <= buf_len) | 1565 | if (bytes <= buf_len) |
1565 | break; | 1566 | break; |
1566 | last = td; | 1567 | last = td; |
1567 | td = pci_pool_alloc(ep->dev->data_requests, gfp_flags, | 1568 | td = dma_pool_alloc(ep->dev->data_requests, gfp_flags, |
1568 | &dma_addr); | 1569 | &dma_addr); |
1569 | if (!td) | 1570 | if (!td) |
1570 | goto nomem; | 1571 | goto nomem; |
@@ -1769,7 +1770,7 @@ static struct usb_request *pch_udc_alloc_request(struct usb_ep *usbep, | |||
1769 | if (!ep->dev->dma_addr) | 1770 | if (!ep->dev->dma_addr) |
1770 | return &req->req; | 1771 | return &req->req; |
1771 | /* ep0 in requests are allocated from data pool here */ | 1772 | /* ep0 in requests are allocated from data pool here */ |
1772 | dma_desc = pci_pool_alloc(ep->dev->data_requests, gfp, | 1773 | dma_desc = dma_pool_alloc(ep->dev->data_requests, gfp, |
1773 | &req->td_data_phys); | 1774 | &req->td_data_phys); |
1774 | if (NULL == dma_desc) { | 1775 | if (NULL == dma_desc) { |
1775 | kfree(req); | 1776 | kfree(req); |
@@ -1808,7 +1809,7 @@ static void pch_udc_free_request(struct usb_ep *usbep, | |||
1808 | if (req->td_data != NULL) { | 1809 | if (req->td_data != NULL) { |
1809 | if (req->chain_len > 1) | 1810 | if (req->chain_len > 1) |
1810 | pch_udc_free_dma_chain(ep->dev, req); | 1811 | pch_udc_free_dma_chain(ep->dev, req); |
1811 | pci_pool_free(ep->dev->data_requests, req->td_data, | 1812 | dma_pool_free(ep->dev->data_requests, req->td_data, |
1812 | req->td_data_phys); | 1813 | req->td_data_phys); |
1813 | } | 1814 | } |
1814 | kfree(req); | 1815 | kfree(req); |
@@ -2913,7 +2914,7 @@ static int init_dma_pools(struct pch_udc_dev *dev) | |||
2913 | void *ep0out_buf; | 2914 | void *ep0out_buf; |
2914 | 2915 | ||
2915 | /* DMA setup */ | 2916 | /* DMA setup */ |
2916 | dev->data_requests = pci_pool_create("data_requests", dev->pdev, | 2917 | dev->data_requests = dma_pool_create("data_requests", &dev->pdev->dev, |
2917 | sizeof(struct pch_udc_data_dma_desc), 0, 0); | 2918 | sizeof(struct pch_udc_data_dma_desc), 0, 0); |
2918 | if (!dev->data_requests) { | 2919 | if (!dev->data_requests) { |
2919 | dev_err(&dev->pdev->dev, "%s: can't get request data pool\n", | 2920 | dev_err(&dev->pdev->dev, "%s: can't get request data pool\n", |
@@ -2922,7 +2923,7 @@ static int init_dma_pools(struct pch_udc_dev *dev) | |||
2922 | } | 2923 | } |
2923 | 2924 | ||
2924 | /* dma desc for setup data */ | 2925 | /* dma desc for setup data */ |
2925 | dev->stp_requests = pci_pool_create("setup requests", dev->pdev, | 2926 | dev->stp_requests = dma_pool_create("setup requests", &dev->pdev->dev, |
2926 | sizeof(struct pch_udc_stp_dma_desc), 0, 0); | 2927 | sizeof(struct pch_udc_stp_dma_desc), 0, 0); |
2927 | if (!dev->stp_requests) { | 2928 | if (!dev->stp_requests) { |
2928 | dev_err(&dev->pdev->dev, "%s: can't get setup request pool\n", | 2929 | dev_err(&dev->pdev->dev, "%s: can't get setup request pool\n", |
@@ -2930,7 +2931,7 @@ static int init_dma_pools(struct pch_udc_dev *dev) | |||
2930 | return -ENOMEM; | 2931 | return -ENOMEM; |
2931 | } | 2932 | } |
2932 | /* setup */ | 2933 | /* setup */ |
2933 | td_stp = pci_pool_alloc(dev->stp_requests, GFP_KERNEL, | 2934 | td_stp = dma_pool_alloc(dev->stp_requests, GFP_KERNEL, |
2934 | &dev->ep[UDC_EP0OUT_IDX].td_stp_phys); | 2935 | &dev->ep[UDC_EP0OUT_IDX].td_stp_phys); |
2935 | if (!td_stp) { | 2936 | if (!td_stp) { |
2936 | dev_err(&dev->pdev->dev, | 2937 | dev_err(&dev->pdev->dev, |
@@ -2940,7 +2941,7 @@ static int init_dma_pools(struct pch_udc_dev *dev) | |||
2940 | dev->ep[UDC_EP0OUT_IDX].td_stp = td_stp; | 2941 | dev->ep[UDC_EP0OUT_IDX].td_stp = td_stp; |
2941 | 2942 | ||
2942 | /* data: 0 packets !? */ | 2943 | /* data: 0 packets !? */ |
2943 | td_data = pci_pool_alloc(dev->data_requests, GFP_KERNEL, | 2944 | td_data = dma_pool_alloc(dev->data_requests, GFP_KERNEL, |
2944 | &dev->ep[UDC_EP0OUT_IDX].td_data_phys); | 2945 | &dev->ep[UDC_EP0OUT_IDX].td_data_phys); |
2945 | if (!td_data) { | 2946 | if (!td_data) { |
2946 | dev_err(&dev->pdev->dev, | 2947 | dev_err(&dev->pdev->dev, |
@@ -3020,22 +3021,21 @@ static void pch_udc_remove(struct pci_dev *pdev) | |||
3020 | dev_err(&pdev->dev, | 3021 | dev_err(&pdev->dev, |
3021 | "%s: gadget driver still bound!!!\n", __func__); | 3022 | "%s: gadget driver still bound!!!\n", __func__); |
3022 | /* dma pool cleanup */ | 3023 | /* dma pool cleanup */ |
3023 | if (dev->data_requests) | 3024 | dma_pool_destroy(dev->data_requests); |
3024 | pci_pool_destroy(dev->data_requests); | ||
3025 | 3025 | ||
3026 | if (dev->stp_requests) { | 3026 | if (dev->stp_requests) { |
3027 | /* cleanup DMA desc's for ep0in */ | 3027 | /* cleanup DMA desc's for ep0in */ |
3028 | if (dev->ep[UDC_EP0OUT_IDX].td_stp) { | 3028 | if (dev->ep[UDC_EP0OUT_IDX].td_stp) { |
3029 | pci_pool_free(dev->stp_requests, | 3029 | dma_pool_free(dev->stp_requests, |
3030 | dev->ep[UDC_EP0OUT_IDX].td_stp, | 3030 | dev->ep[UDC_EP0OUT_IDX].td_stp, |
3031 | dev->ep[UDC_EP0OUT_IDX].td_stp_phys); | 3031 | dev->ep[UDC_EP0OUT_IDX].td_stp_phys); |
3032 | } | 3032 | } |
3033 | if (dev->ep[UDC_EP0OUT_IDX].td_data) { | 3033 | if (dev->ep[UDC_EP0OUT_IDX].td_data) { |
3034 | pci_pool_free(dev->stp_requests, | 3034 | dma_pool_free(dev->stp_requests, |
3035 | dev->ep[UDC_EP0OUT_IDX].td_data, | 3035 | dev->ep[UDC_EP0OUT_IDX].td_data, |
3036 | dev->ep[UDC_EP0OUT_IDX].td_data_phys); | 3036 | dev->ep[UDC_EP0OUT_IDX].td_data_phys); |
3037 | } | 3037 | } |
3038 | pci_pool_destroy(dev->stp_requests); | 3038 | dma_pool_destroy(dev->stp_requests); |
3039 | } | 3039 | } |
3040 | 3040 | ||
3041 | if (dev->dma_addr) | 3041 | if (dev->dma_addr) |
diff --git a/drivers/usb/gadget/udc/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c index 832c4fdbe985..d48e239660c3 100644 --- a/drivers/usb/gadget/udc/pxa27x_udc.c +++ b/drivers/usb/gadget/udc/pxa27x_udc.c | |||
@@ -1608,9 +1608,6 @@ static int pxa_udc_pullup(struct usb_gadget *_gadget, int is_active) | |||
1608 | return 0; | 1608 | return 0; |
1609 | } | 1609 | } |
1610 | 1610 | ||
1611 | static void udc_enable(struct pxa_udc *udc); | ||
1612 | static void udc_disable(struct pxa_udc *udc); | ||
1613 | |||
1614 | /** | 1611 | /** |
1615 | * pxa_udc_vbus_session - Called by external transceiver to enable/disable udc | 1612 | * pxa_udc_vbus_session - Called by external transceiver to enable/disable udc |
1616 | * @_gadget: usb gadget | 1613 | * @_gadget: usb gadget |
diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index 2218f91e92a6..5a2d845fb1a6 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c | |||
@@ -10,6 +10,7 @@ | |||
10 | 10 | ||
11 | #include <linux/delay.h> | 11 | #include <linux/delay.h> |
12 | #include <linux/err.h> | 12 | #include <linux/err.h> |
13 | #include <linux/extcon.h> | ||
13 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
14 | #include <linux/io.h> | 15 | #include <linux/io.h> |
15 | #include <linux/module.h> | 16 | #include <linux/module.h> |
@@ -37,6 +38,9 @@ | |||
37 | #define USB3_USB_INT_ENA_2 0x22c | 38 | #define USB3_USB_INT_ENA_2 0x22c |
38 | #define USB3_STUP_DAT_0 0x230 | 39 | #define USB3_STUP_DAT_0 0x230 |
39 | #define USB3_STUP_DAT_1 0x234 | 40 | #define USB3_STUP_DAT_1 0x234 |
41 | #define USB3_USB_OTG_STA 0x268 | ||
42 | #define USB3_USB_OTG_INT_STA 0x26c | ||
43 | #define USB3_USB_OTG_INT_ENA 0x270 | ||
40 | #define USB3_P0_MOD 0x280 | 44 | #define USB3_P0_MOD 0x280 |
41 | #define USB3_P0_CON 0x288 | 45 | #define USB3_P0_CON 0x288 |
42 | #define USB3_P0_STA 0x28c | 46 | #define USB3_P0_STA 0x28c |
@@ -124,6 +128,9 @@ | |||
124 | /* USB_INT_ENA_2 and USB_INT_STA_2 */ | 128 | /* USB_INT_ENA_2 and USB_INT_STA_2 */ |
125 | #define USB_INT_2_PIPE(n) BIT(n) | 129 | #define USB_INT_2_PIPE(n) BIT(n) |
126 | 130 | ||
131 | /* USB_OTG_STA, USB_OTG_INT_STA and USB_OTG_INT_ENA */ | ||
132 | #define USB_OTG_IDMON BIT(4) | ||
133 | |||
127 | /* P0_MOD */ | 134 | /* P0_MOD */ |
128 | #define P0_MOD_DIR BIT(6) | 135 | #define P0_MOD_DIR BIT(6) |
129 | 136 | ||
@@ -257,6 +264,8 @@ struct renesas_usb3 { | |||
257 | 264 | ||
258 | struct usb_gadget gadget; | 265 | struct usb_gadget gadget; |
259 | struct usb_gadget_driver *driver; | 266 | struct usb_gadget_driver *driver; |
267 | struct extcon_dev *extcon; | ||
268 | struct work_struct extcon_work; | ||
260 | 269 | ||
261 | struct renesas_usb3_ep *usb3_ep; | 270 | struct renesas_usb3_ep *usb3_ep; |
262 | int num_usb3_eps; | 271 | int num_usb3_eps; |
@@ -269,6 +278,8 @@ struct renesas_usb3 { | |||
269 | u8 ep0_buf[USB3_EP0_BUF_SIZE]; | 278 | u8 ep0_buf[USB3_EP0_BUF_SIZE]; |
270 | bool softconnect; | 279 | bool softconnect; |
271 | bool workaround_for_vbus; | 280 | bool workaround_for_vbus; |
281 | bool extcon_host; /* check id and set EXTCON_USB_HOST */ | ||
282 | bool extcon_usb; /* check vbus and set EXTCON_USB */ | ||
272 | }; | 283 | }; |
273 | 284 | ||
274 | #define gadget_to_renesas_usb3(_gadget) \ | 285 | #define gadget_to_renesas_usb3(_gadget) \ |
@@ -332,6 +343,15 @@ static int usb3_wait(struct renesas_usb3 *usb3, u32 reg, u32 mask, | |||
332 | return -EBUSY; | 343 | return -EBUSY; |
333 | } | 344 | } |
334 | 345 | ||
346 | static void renesas_usb3_extcon_work(struct work_struct *work) | ||
347 | { | ||
348 | struct renesas_usb3 *usb3 = container_of(work, struct renesas_usb3, | ||
349 | extcon_work); | ||
350 | |||
351 | extcon_set_state_sync(usb3->extcon, EXTCON_USB_HOST, usb3->extcon_host); | ||
352 | extcon_set_state_sync(usb3->extcon, EXTCON_USB, usb3->extcon_usb); | ||
353 | } | ||
354 | |||
335 | static void usb3_enable_irq_1(struct renesas_usb3 *usb3, u32 bits) | 355 | static void usb3_enable_irq_1(struct renesas_usb3 *usb3, u32 bits) |
336 | { | 356 | { |
337 | usb3_set_bit(usb3, bits, USB3_USB_INT_ENA_1); | 357 | usb3_set_bit(usb3, bits, USB3_USB_INT_ENA_1); |
@@ -352,6 +372,11 @@ static void usb3_disable_pipe_irq(struct renesas_usb3 *usb3, int num) | |||
352 | usb3_clear_bit(usb3, USB_INT_2_PIPE(num), USB3_USB_INT_ENA_2); | 372 | usb3_clear_bit(usb3, USB_INT_2_PIPE(num), USB3_USB_INT_ENA_2); |
353 | } | 373 | } |
354 | 374 | ||
375 | static bool usb3_is_host(struct renesas_usb3 *usb3) | ||
376 | { | ||
377 | return !(usb3_read(usb3, USB3_DRD_CON) & DRD_CON_PERI_CON); | ||
378 | } | ||
379 | |||
355 | static void usb3_init_axi_bridge(struct renesas_usb3 *usb3) | 380 | static void usb3_init_axi_bridge(struct renesas_usb3 *usb3) |
356 | { | 381 | { |
357 | /* Set AXI_INT */ | 382 | /* Set AXI_INT */ |
@@ -362,10 +387,6 @@ static void usb3_init_axi_bridge(struct renesas_usb3 *usb3) | |||
362 | 387 | ||
363 | static void usb3_init_epc_registers(struct renesas_usb3 *usb3) | 388 | static void usb3_init_epc_registers(struct renesas_usb3 *usb3) |
364 | { | 389 | { |
365 | /* FIXME: How to change host / peripheral mode as well? */ | ||
366 | usb3_set_bit(usb3, DRD_CON_PERI_CON, USB3_DRD_CON); | ||
367 | usb3_clear_bit(usb3, DRD_CON_VBOUT, USB3_DRD_CON); | ||
368 | |||
369 | usb3_write(usb3, ~0, USB3_USB_INT_STA_1); | 390 | usb3_write(usb3, ~0, USB3_USB_INT_STA_1); |
370 | usb3_enable_irq_1(usb3, USB_INT_1_VBUS_CNG); | 391 | usb3_enable_irq_1(usb3, USB_INT_1_VBUS_CNG); |
371 | } | 392 | } |
@@ -531,18 +552,70 @@ static void usb3_check_vbus(struct renesas_usb3 *usb3) | |||
531 | if (usb3->workaround_for_vbus) { | 552 | if (usb3->workaround_for_vbus) { |
532 | usb3_connect(usb3); | 553 | usb3_connect(usb3); |
533 | } else { | 554 | } else { |
534 | if (usb3_read(usb3, USB3_USB_STA) & USB_STA_VBUS_STA) | 555 | usb3->extcon_usb = !!(usb3_read(usb3, USB3_USB_STA) & |
556 | USB_STA_VBUS_STA); | ||
557 | if (usb3->extcon_usb) | ||
535 | usb3_connect(usb3); | 558 | usb3_connect(usb3); |
536 | else | 559 | else |
537 | usb3_disconnect(usb3); | 560 | usb3_disconnect(usb3); |
561 | |||
562 | schedule_work(&usb3->extcon_work); | ||
538 | } | 563 | } |
539 | } | 564 | } |
540 | 565 | ||
566 | static void usb3_set_mode(struct renesas_usb3 *usb3, bool host) | ||
567 | { | ||
568 | if (host) | ||
569 | usb3_clear_bit(usb3, DRD_CON_PERI_CON, USB3_DRD_CON); | ||
570 | else | ||
571 | usb3_set_bit(usb3, DRD_CON_PERI_CON, USB3_DRD_CON); | ||
572 | } | ||
573 | |||
574 | static void usb3_vbus_out(struct renesas_usb3 *usb3, bool enable) | ||
575 | { | ||
576 | if (enable) | ||
577 | usb3_set_bit(usb3, DRD_CON_VBOUT, USB3_DRD_CON); | ||
578 | else | ||
579 | usb3_clear_bit(usb3, DRD_CON_VBOUT, USB3_DRD_CON); | ||
580 | } | ||
581 | |||
582 | static void usb3_mode_config(struct renesas_usb3 *usb3, bool host, bool a_dev) | ||
583 | { | ||
584 | unsigned long flags; | ||
585 | |||
586 | spin_lock_irqsave(&usb3->lock, flags); | ||
587 | usb3_set_mode(usb3, host); | ||
588 | usb3_vbus_out(usb3, a_dev); | ||
589 | if (!host && a_dev) /* for A-Peripheral */ | ||
590 | usb3_connect(usb3); | ||
591 | spin_unlock_irqrestore(&usb3->lock, flags); | ||
592 | } | ||
593 | |||
594 | static bool usb3_is_a_device(struct renesas_usb3 *usb3) | ||
595 | { | ||
596 | return !(usb3_read(usb3, USB3_USB_OTG_STA) & USB_OTG_IDMON); | ||
597 | } | ||
598 | |||
599 | static void usb3_check_id(struct renesas_usb3 *usb3) | ||
600 | { | ||
601 | usb3->extcon_host = usb3_is_a_device(usb3); | ||
602 | |||
603 | if (usb3->extcon_host) | ||
604 | usb3_mode_config(usb3, true, true); | ||
605 | else | ||
606 | usb3_mode_config(usb3, false, false); | ||
607 | |||
608 | schedule_work(&usb3->extcon_work); | ||
609 | } | ||
610 | |||
541 | static void renesas_usb3_init_controller(struct renesas_usb3 *usb3) | 611 | static void renesas_usb3_init_controller(struct renesas_usb3 *usb3) |
542 | { | 612 | { |
543 | usb3_init_axi_bridge(usb3); | 613 | usb3_init_axi_bridge(usb3); |
544 | usb3_init_epc_registers(usb3); | 614 | usb3_init_epc_registers(usb3); |
615 | usb3_write(usb3, USB_OTG_IDMON, USB3_USB_OTG_INT_STA); | ||
616 | usb3_write(usb3, USB_OTG_IDMON, USB3_USB_OTG_INT_ENA); | ||
545 | 617 | ||
618 | usb3_check_id(usb3); | ||
546 | usb3_check_vbus(usb3); | 619 | usb3_check_vbus(usb3); |
547 | } | 620 | } |
548 | 621 | ||
@@ -551,6 +624,7 @@ static void renesas_usb3_stop_controller(struct renesas_usb3 *usb3) | |||
551 | usb3_disconnect(usb3); | 624 | usb3_disconnect(usb3); |
552 | usb3_write(usb3, 0, USB3_P0_INT_ENA); | 625 | usb3_write(usb3, 0, USB3_P0_INT_ENA); |
553 | usb3_write(usb3, 0, USB3_PN_INT_ENA); | 626 | usb3_write(usb3, 0, USB3_PN_INT_ENA); |
627 | usb3_write(usb3, 0, USB3_USB_OTG_INT_ENA); | ||
554 | usb3_write(usb3, 0, USB3_USB_INT_ENA_1); | 628 | usb3_write(usb3, 0, USB3_USB_INT_ENA_1); |
555 | usb3_write(usb3, 0, USB3_USB_INT_ENA_2); | 629 | usb3_write(usb3, 0, USB3_USB_INT_ENA_2); |
556 | usb3_write(usb3, 0, USB3_AXI_INT_ENA); | 630 | usb3_write(usb3, 0, USB3_AXI_INT_ENA); |
@@ -1474,10 +1548,22 @@ static void usb3_irq_epc_int_2(struct renesas_usb3 *usb3, u32 int_sta_2) | |||
1474 | } | 1548 | } |
1475 | } | 1549 | } |
1476 | 1550 | ||
1551 | static void usb3_irq_idmon_change(struct renesas_usb3 *usb3) | ||
1552 | { | ||
1553 | usb3_check_id(usb3); | ||
1554 | } | ||
1555 | |||
1556 | static void usb3_irq_otg_int(struct renesas_usb3 *usb3, u32 otg_int_sta) | ||
1557 | { | ||
1558 | if (otg_int_sta & USB_OTG_IDMON) | ||
1559 | usb3_irq_idmon_change(usb3); | ||
1560 | } | ||
1561 | |||
1477 | static void usb3_irq_epc(struct renesas_usb3 *usb3) | 1562 | static void usb3_irq_epc(struct renesas_usb3 *usb3) |
1478 | { | 1563 | { |
1479 | u32 int_sta_1 = usb3_read(usb3, USB3_USB_INT_STA_1); | 1564 | u32 int_sta_1 = usb3_read(usb3, USB3_USB_INT_STA_1); |
1480 | u32 int_sta_2 = usb3_read(usb3, USB3_USB_INT_STA_2); | 1565 | u32 int_sta_2 = usb3_read(usb3, USB3_USB_INT_STA_2); |
1566 | u32 otg_int_sta = usb3_read(usb3, USB3_USB_OTG_INT_STA); | ||
1481 | 1567 | ||
1482 | int_sta_1 &= usb3_read(usb3, USB3_USB_INT_ENA_1); | 1568 | int_sta_1 &= usb3_read(usb3, USB3_USB_INT_ENA_1); |
1483 | if (int_sta_1) { | 1569 | if (int_sta_1) { |
@@ -1488,6 +1574,12 @@ static void usb3_irq_epc(struct renesas_usb3 *usb3) | |||
1488 | int_sta_2 &= usb3_read(usb3, USB3_USB_INT_ENA_2); | 1574 | int_sta_2 &= usb3_read(usb3, USB3_USB_INT_ENA_2); |
1489 | if (int_sta_2) | 1575 | if (int_sta_2) |
1490 | usb3_irq_epc_int_2(usb3, int_sta_2); | 1576 | usb3_irq_epc_int_2(usb3, int_sta_2); |
1577 | |||
1578 | otg_int_sta &= usb3_read(usb3, USB3_USB_OTG_INT_ENA); | ||
1579 | if (otg_int_sta) { | ||
1580 | usb3_write(usb3, otg_int_sta, USB3_USB_OTG_INT_STA); | ||
1581 | usb3_irq_otg_int(usb3, otg_int_sta); | ||
1582 | } | ||
1491 | } | 1583 | } |
1492 | 1584 | ||
1493 | static irqreturn_t renesas_usb3_irq(int irq, void *_usb3) | 1585 | static irqreturn_t renesas_usb3_irq(int irq, void *_usb3) |
@@ -1756,11 +1848,49 @@ static const struct usb_gadget_ops renesas_usb3_gadget_ops = { | |||
1756 | .set_selfpowered = renesas_usb3_set_selfpowered, | 1848 | .set_selfpowered = renesas_usb3_set_selfpowered, |
1757 | }; | 1849 | }; |
1758 | 1850 | ||
1851 | static ssize_t role_store(struct device *dev, struct device_attribute *attr, | ||
1852 | const char *buf, size_t count) | ||
1853 | { | ||
1854 | struct renesas_usb3 *usb3 = dev_get_drvdata(dev); | ||
1855 | bool new_mode_is_host; | ||
1856 | |||
1857 | if (!usb3->driver) | ||
1858 | return -ENODEV; | ||
1859 | |||
1860 | if (!strncmp(buf, "host", strlen("host"))) | ||
1861 | new_mode_is_host = true; | ||
1862 | else if (!strncmp(buf, "peripheral", strlen("peripheral"))) | ||
1863 | new_mode_is_host = false; | ||
1864 | else | ||
1865 | return -EINVAL; | ||
1866 | |||
1867 | if (new_mode_is_host == usb3_is_host(usb3)) | ||
1868 | return -EINVAL; | ||
1869 | |||
1870 | usb3_mode_config(usb3, new_mode_is_host, usb3_is_a_device(usb3)); | ||
1871 | |||
1872 | return count; | ||
1873 | } | ||
1874 | |||
1875 | static ssize_t role_show(struct device *dev, struct device_attribute *attr, | ||
1876 | char *buf) | ||
1877 | { | ||
1878 | struct renesas_usb3 *usb3 = dev_get_drvdata(dev); | ||
1879 | |||
1880 | if (!usb3->driver) | ||
1881 | return -ENODEV; | ||
1882 | |||
1883 | return sprintf(buf, "%s\n", usb3_is_host(usb3) ? "host" : "peripheral"); | ||
1884 | } | ||
1885 | static DEVICE_ATTR_RW(role); | ||
1886 | |||
1759 | /*------- platform_driver ------------------------------------------------*/ | 1887 | /*------- platform_driver ------------------------------------------------*/ |
1760 | static int renesas_usb3_remove(struct platform_device *pdev) | 1888 | static int renesas_usb3_remove(struct platform_device *pdev) |
1761 | { | 1889 | { |
1762 | struct renesas_usb3 *usb3 = platform_get_drvdata(pdev); | 1890 | struct renesas_usb3 *usb3 = platform_get_drvdata(pdev); |
1763 | 1891 | ||
1892 | device_remove_file(&pdev->dev, &dev_attr_role); | ||
1893 | |||
1764 | pm_runtime_put(&pdev->dev); | 1894 | pm_runtime_put(&pdev->dev); |
1765 | pm_runtime_disable(&pdev->dev); | 1895 | pm_runtime_disable(&pdev->dev); |
1766 | 1896 | ||
@@ -1894,6 +2024,12 @@ static const struct of_device_id usb3_of_match[] = { | |||
1894 | }; | 2024 | }; |
1895 | MODULE_DEVICE_TABLE(of, usb3_of_match); | 2025 | MODULE_DEVICE_TABLE(of, usb3_of_match); |
1896 | 2026 | ||
2027 | static const unsigned int renesas_usb3_cable[] = { | ||
2028 | EXTCON_USB, | ||
2029 | EXTCON_USB_HOST, | ||
2030 | EXTCON_NONE, | ||
2031 | }; | ||
2032 | |||
1897 | static int renesas_usb3_probe(struct platform_device *pdev) | 2033 | static int renesas_usb3_probe(struct platform_device *pdev) |
1898 | { | 2034 | { |
1899 | struct renesas_usb3 *usb3; | 2035 | struct renesas_usb3 *usb3; |
@@ -1937,6 +2073,17 @@ static int renesas_usb3_probe(struct platform_device *pdev) | |||
1937 | if (ret < 0) | 2073 | if (ret < 0) |
1938 | return ret; | 2074 | return ret; |
1939 | 2075 | ||
2076 | INIT_WORK(&usb3->extcon_work, renesas_usb3_extcon_work); | ||
2077 | usb3->extcon = devm_extcon_dev_allocate(&pdev->dev, renesas_usb3_cable); | ||
2078 | if (IS_ERR(usb3->extcon)) | ||
2079 | return PTR_ERR(usb3->extcon); | ||
2080 | |||
2081 | ret = devm_extcon_dev_register(&pdev->dev, usb3->extcon); | ||
2082 | if (ret < 0) { | ||
2083 | dev_err(&pdev->dev, "Failed to register extcon\n"); | ||
2084 | return ret; | ||
2085 | } | ||
2086 | |||
1940 | /* for ep0 handling */ | 2087 | /* for ep0 handling */ |
1941 | usb3->ep0_req = __renesas_usb3_ep_alloc_request(GFP_KERNEL); | 2088 | usb3->ep0_req = __renesas_usb3_ep_alloc_request(GFP_KERNEL); |
1942 | if (!usb3->ep0_req) | 2089 | if (!usb3->ep0_req) |
@@ -1946,6 +2093,10 @@ static int renesas_usb3_probe(struct platform_device *pdev) | |||
1946 | if (ret < 0) | 2093 | if (ret < 0) |
1947 | goto err_add_udc; | 2094 | goto err_add_udc; |
1948 | 2095 | ||
2096 | ret = device_create_file(&pdev->dev, &dev_attr_role); | ||
2097 | if (ret < 0) | ||
2098 | goto err_dev_create; | ||
2099 | |||
1949 | usb3->workaround_for_vbus = priv->workaround_for_vbus; | 2100 | usb3->workaround_for_vbus = priv->workaround_for_vbus; |
1950 | 2101 | ||
1951 | pm_runtime_enable(&pdev->dev); | 2102 | pm_runtime_enable(&pdev->dev); |
@@ -1955,6 +2106,9 @@ static int renesas_usb3_probe(struct platform_device *pdev) | |||
1955 | 2106 | ||
1956 | return 0; | 2107 | return 0; |
1957 | 2108 | ||
2109 | err_dev_create: | ||
2110 | usb_del_gadget_udc(&usb3->gadget); | ||
2111 | |||
1958 | err_add_udc: | 2112 | err_add_udc: |
1959 | __renesas_usb3_ep_free_request(usb3->ep0_req); | 2113 | __renesas_usb3_ep_free_request(usb3->ep0_req); |
1960 | 2114 | ||
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 407d947b34ea..ababb91d654a 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
@@ -30,7 +30,7 @@ if USB_XHCI_HCD | |||
30 | 30 | ||
31 | config USB_XHCI_PCI | 31 | config USB_XHCI_PCI |
32 | tristate | 32 | tristate |
33 | depends on PCI | 33 | depends on USB_PCI |
34 | default y | 34 | default y |
35 | 35 | ||
36 | config USB_XHCI_PLATFORM | 36 | config USB_XHCI_PLATFORM |
@@ -139,7 +139,7 @@ if USB_EHCI_HCD | |||
139 | 139 | ||
140 | config USB_EHCI_PCI | 140 | config USB_EHCI_PCI |
141 | tristate | 141 | tristate |
142 | depends on PCI | 142 | depends on USB_PCI |
143 | default y | 143 | default y |
144 | 144 | ||
145 | config USB_EHCI_HCD_PMC_MSP | 145 | config USB_EHCI_HCD_PMC_MSP |
@@ -188,7 +188,7 @@ config USB_EHCI_HCD_OMAP | |||
188 | 188 | ||
189 | config USB_EHCI_HCD_ORION | 189 | config USB_EHCI_HCD_ORION |
190 | tristate "Support for Marvell EBU on-chip EHCI USB controller" | 190 | tristate "Support for Marvell EBU on-chip EHCI USB controller" |
191 | depends on USB_EHCI_HCD && PLAT_ORION | 191 | depends on USB_EHCI_HCD && (PLAT_ORION || ARCH_MVEBU) |
192 | default y | 192 | default y |
193 | ---help--- | 193 | ---help--- |
194 | Enables support for the on-chip EHCI controller on Marvell's | 194 | Enables support for the on-chip EHCI controller on Marvell's |
@@ -525,7 +525,7 @@ config USB_OHCI_HCD_PPC_OF | |||
525 | 525 | ||
526 | config USB_OHCI_HCD_PCI | 526 | config USB_OHCI_HCD_PCI |
527 | tristate "OHCI support for PCI-bus USB controllers" | 527 | tristate "OHCI support for PCI-bus USB controllers" |
528 | depends on PCI | 528 | depends on USB_PCI |
529 | default y | 529 | default y |
530 | select USB_OHCI_LITTLE_ENDIAN | 530 | select USB_OHCI_LITTLE_ENDIAN |
531 | ---help--- | 531 | ---help--- |
@@ -606,7 +606,7 @@ endif # USB_OHCI_HCD | |||
606 | 606 | ||
607 | config USB_UHCI_HCD | 607 | config USB_UHCI_HCD |
608 | tristate "UHCI HCD (most Intel and VIA) support" | 608 | tristate "UHCI HCD (most Intel and VIA) support" |
609 | depends on PCI || USB_UHCI_SUPPORT_NON_PCI_HC | 609 | depends on USB_PCI || USB_UHCI_SUPPORT_NON_PCI_HC |
610 | ---help--- | 610 | ---help--- |
611 | The Universal Host Controller Interface is a standard by Intel for | 611 | The Universal Host Controller Interface is a standard by Intel for |
612 | accessing the USB hardware in the PC (which is also called the USB | 612 | accessing the USB hardware in the PC (which is also called the USB |
@@ -739,7 +739,7 @@ config USB_RENESAS_USBHS_HCD | |||
739 | 739 | ||
740 | config USB_WHCI_HCD | 740 | config USB_WHCI_HCD |
741 | tristate "Wireless USB Host Controller Interface (WHCI) driver" | 741 | tristate "Wireless USB Host Controller Interface (WHCI) driver" |
742 | depends on PCI && USB && UWB | 742 | depends on USB_PCI && USB && UWB |
743 | select USB_WUSB | 743 | select USB_WUSB |
744 | select UWB_WHCI | 744 | select UWB_WHCI |
745 | help | 745 | help |
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 2644537b7bcf..c77b0a38557b 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile | |||
@@ -27,9 +27,7 @@ endif | |||
27 | 27 | ||
28 | obj-$(CONFIG_USB_WHCI_HCD) += whci/ | 28 | obj-$(CONFIG_USB_WHCI_HCD) += whci/ |
29 | 29 | ||
30 | ifneq ($(CONFIG_USB), ) | 30 | obj-$(CONFIG_USB_PCI) += pci-quirks.o |
31 | obj-$(CONFIG_PCI) += pci-quirks.o | ||
32 | endif | ||
33 | 31 | ||
34 | obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o | 32 | obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o |
35 | obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o | 33 | obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o |
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 1a2614aae42c..cbb9b8e12c3c 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c | |||
@@ -803,7 +803,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) | |||
803 | size -= temp; | 803 | size -= temp; |
804 | next += temp; | 804 | next += temp; |
805 | 805 | ||
806 | #ifdef CONFIG_PCI | 806 | #ifdef CONFIG_USB_PCI |
807 | /* EHCI 0.96 and later may have "extended capabilities" */ | 807 | /* EHCI 0.96 and later may have "extended capabilities" */ |
808 | if (dev_is_pci(hcd->self.controller)) { | 808 | if (dev_is_pci(hcd->self.controller)) { |
809 | struct pci_dev *pdev; | 809 | struct pci_dev *pdev; |
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 3733aab46efe..4a08b70c81aa 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c | |||
@@ -96,8 +96,8 @@ static int fsl_ehci_drv_probe(struct platform_device *pdev) | |||
96 | } | 96 | } |
97 | irq = res->start; | 97 | irq = res->start; |
98 | 98 | ||
99 | hcd = usb_create_hcd(&fsl_ehci_hc_driver, &pdev->dev, | 99 | hcd = __usb_create_hcd(&fsl_ehci_hc_driver, pdev->dev.parent, |
100 | dev_name(&pdev->dev)); | 100 | &pdev->dev, dev_name(&pdev->dev), NULL); |
101 | if (!hcd) { | 101 | if (!hcd) { |
102 | retval = -ENOMEM; | 102 | retval = -ENOMEM; |
103 | goto err1; | 103 | goto err1; |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index ac2c4eab478d..6e834b83a104 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -597,7 +597,7 @@ static int ehci_run (struct usb_hcd *hcd) | |||
597 | /* | 597 | /* |
598 | * hcc_params controls whether ehci->regs->segment must (!!!) | 598 | * hcc_params controls whether ehci->regs->segment must (!!!) |
599 | * be used; it constrains QH/ITD/SITD and QTD locations. | 599 | * be used; it constrains QH/ITD/SITD and QTD locations. |
600 | * pci_pool consistent memory always uses segment zero. | 600 | * dma_pool consistent memory always uses segment zero. |
601 | * streaming mappings for I/O buffers, like pci_map_single(), | 601 | * streaming mappings for I/O buffers, like pci_map_single(), |
602 | * can return segments above 4GB, if the device allows. | 602 | * can return segments above 4GB, if the device allows. |
603 | * | 603 | * |
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c index 4de43011df23..9b7e63977215 100644 --- a/drivers/usb/host/ehci-mem.c +++ b/drivers/usb/host/ehci-mem.c | |||
@@ -138,7 +138,7 @@ static void ehci_mem_cleanup (struct ehci_hcd *ehci) | |||
138 | ehci->sitd_pool = NULL; | 138 | ehci->sitd_pool = NULL; |
139 | 139 | ||
140 | if (ehci->periodic) | 140 | if (ehci->periodic) |
141 | dma_free_coherent (ehci_to_hcd(ehci)->self.controller, | 141 | dma_free_coherent(ehci_to_hcd(ehci)->self.sysdev, |
142 | ehci->periodic_size * sizeof (u32), | 142 | ehci->periodic_size * sizeof (u32), |
143 | ehci->periodic, ehci->periodic_dma); | 143 | ehci->periodic, ehci->periodic_dma); |
144 | ehci->periodic = NULL; | 144 | ehci->periodic = NULL; |
@@ -155,7 +155,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags) | |||
155 | 155 | ||
156 | /* QTDs for control/bulk/intr transfers */ | 156 | /* QTDs for control/bulk/intr transfers */ |
157 | ehci->qtd_pool = dma_pool_create ("ehci_qtd", | 157 | ehci->qtd_pool = dma_pool_create ("ehci_qtd", |
158 | ehci_to_hcd(ehci)->self.controller, | 158 | ehci_to_hcd(ehci)->self.sysdev, |
159 | sizeof (struct ehci_qtd), | 159 | sizeof (struct ehci_qtd), |
160 | 32 /* byte alignment (for hw parts) */, | 160 | 32 /* byte alignment (for hw parts) */, |
161 | 4096 /* can't cross 4K */); | 161 | 4096 /* can't cross 4K */); |
@@ -165,7 +165,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags) | |||
165 | 165 | ||
166 | /* QHs for control/bulk/intr transfers */ | 166 | /* QHs for control/bulk/intr transfers */ |
167 | ehci->qh_pool = dma_pool_create ("ehci_qh", | 167 | ehci->qh_pool = dma_pool_create ("ehci_qh", |
168 | ehci_to_hcd(ehci)->self.controller, | 168 | ehci_to_hcd(ehci)->self.sysdev, |
169 | sizeof(struct ehci_qh_hw), | 169 | sizeof(struct ehci_qh_hw), |
170 | 32 /* byte alignment (for hw parts) */, | 170 | 32 /* byte alignment (for hw parts) */, |
171 | 4096 /* can't cross 4K */); | 171 | 4096 /* can't cross 4K */); |
@@ -179,7 +179,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags) | |||
179 | 179 | ||
180 | /* ITD for high speed ISO transfers */ | 180 | /* ITD for high speed ISO transfers */ |
181 | ehci->itd_pool = dma_pool_create ("ehci_itd", | 181 | ehci->itd_pool = dma_pool_create ("ehci_itd", |
182 | ehci_to_hcd(ehci)->self.controller, | 182 | ehci_to_hcd(ehci)->self.sysdev, |
183 | sizeof (struct ehci_itd), | 183 | sizeof (struct ehci_itd), |
184 | 32 /* byte alignment (for hw parts) */, | 184 | 32 /* byte alignment (for hw parts) */, |
185 | 4096 /* can't cross 4K */); | 185 | 4096 /* can't cross 4K */); |
@@ -189,7 +189,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags) | |||
189 | 189 | ||
190 | /* SITD for full/low speed split ISO transfers */ | 190 | /* SITD for full/low speed split ISO transfers */ |
191 | ehci->sitd_pool = dma_pool_create ("ehci_sitd", | 191 | ehci->sitd_pool = dma_pool_create ("ehci_sitd", |
192 | ehci_to_hcd(ehci)->self.controller, | 192 | ehci_to_hcd(ehci)->self.sysdev, |
193 | sizeof (struct ehci_sitd), | 193 | sizeof (struct ehci_sitd), |
194 | 32 /* byte alignment (for hw parts) */, | 194 | 32 /* byte alignment (for hw parts) */, |
195 | 4096 /* can't cross 4K */); | 195 | 4096 /* can't cross 4K */); |
@@ -199,7 +199,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags) | |||
199 | 199 | ||
200 | /* Hardware periodic table */ | 200 | /* Hardware periodic table */ |
201 | ehci->periodic = (__le32 *) | 201 | ehci->periodic = (__le32 *) |
202 | dma_alloc_coherent (ehci_to_hcd(ehci)->self.controller, | 202 | dma_alloc_coherent(ehci_to_hcd(ehci)->self.sysdev, |
203 | ehci->periodic_size * sizeof(__le32), | 203 | ehci->periodic_size * sizeof(__le32), |
204 | &ehci->periodic_dma, flags); | 204 | &ehci->periodic_dma, flags); |
205 | if (ehci->periodic == NULL) { | 205 | if (ehci->periodic == NULL) { |
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index ee8d5faa0194..1aec87ec68df 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c | |||
@@ -47,6 +47,18 @@ | |||
47 | #define USB_PHY_IVREF_CTRL 0x440 | 47 | #define USB_PHY_IVREF_CTRL 0x440 |
48 | #define USB_PHY_TST_GRP_CTRL 0x450 | 48 | #define USB_PHY_TST_GRP_CTRL 0x450 |
49 | 49 | ||
50 | #define USB_SBUSCFG 0x90 | ||
51 | |||
52 | /* BAWR = BARD = 3 : Align read/write bursts packets larger than 128 bytes */ | ||
53 | #define USB_SBUSCFG_BAWR_ALIGN_128B (0x3 << 6) | ||
54 | #define USB_SBUSCFG_BARD_ALIGN_128B (0x3 << 3) | ||
55 | /* AHBBRST = 3 : Align AHB Burst to INCR16 (64 bytes) */ | ||
56 | #define USB_SBUSCFG_AHBBRST_INCR16 (0x3 << 0) | ||
57 | |||
58 | #define USB_SBUSCFG_DEF_VAL (USB_SBUSCFG_BAWR_ALIGN_128B \ | ||
59 | | USB_SBUSCFG_BARD_ALIGN_128B \ | ||
60 | | USB_SBUSCFG_AHBBRST_INCR16) | ||
61 | |||
50 | #define DRIVER_DESC "EHCI orion driver" | 62 | #define DRIVER_DESC "EHCI orion driver" |
51 | 63 | ||
52 | #define hcd_to_orion_priv(h) ((struct orion_ehci_hcd *)hcd_to_ehci(h)->priv) | 64 | #define hcd_to_orion_priv(h) ((struct orion_ehci_hcd *)hcd_to_ehci(h)->priv) |
@@ -151,8 +163,31 @@ ehci_orion_conf_mbus_windows(struct usb_hcd *hcd, | |||
151 | } | 163 | } |
152 | } | 164 | } |
153 | 165 | ||
166 | static int ehci_orion_drv_reset(struct usb_hcd *hcd) | ||
167 | { | ||
168 | struct device *dev = hcd->self.controller; | ||
169 | int ret; | ||
170 | |||
171 | ret = ehci_setup(hcd); | ||
172 | if (ret) | ||
173 | return ret; | ||
174 | |||
175 | /* | ||
176 | * For SoC without hlock, need to program sbuscfg value to guarantee | ||
177 | * AHB master's burst would not overrun or underrun FIFO. | ||
178 | * | ||
179 | * sbuscfg reg has to be set after usb controller reset, otherwise | ||
180 | * the value would be override to 0. | ||
181 | */ | ||
182 | if (of_device_is_compatible(dev->of_node, "marvell,armada-3700-ehci")) | ||
183 | wrl(USB_SBUSCFG, USB_SBUSCFG_DEF_VAL); | ||
184 | |||
185 | return ret; | ||
186 | } | ||
187 | |||
154 | static const struct ehci_driver_overrides orion_overrides __initconst = { | 188 | static const struct ehci_driver_overrides orion_overrides __initconst = { |
155 | .extra_priv_size = sizeof(struct orion_ehci_hcd), | 189 | .extra_priv_size = sizeof(struct orion_ehci_hcd), |
190 | .reset = ehci_orion_drv_reset, | ||
156 | }; | 191 | }; |
157 | 192 | ||
158 | static int ehci_orion_drv_probe(struct platform_device *pdev) | 193 | static int ehci_orion_drv_probe(struct platform_device *pdev) |
@@ -310,6 +345,7 @@ static int ehci_orion_drv_remove(struct platform_device *pdev) | |||
310 | 345 | ||
311 | static const struct of_device_id ehci_orion_dt_ids[] = { | 346 | static const struct of_device_id ehci_orion_dt_ids[] = { |
312 | { .compatible = "marvell,orion-ehci", }, | 347 | { .compatible = "marvell,orion-ehci", }, |
348 | { .compatible = "marvell,armada-3700-ehci", }, | ||
313 | {}, | 349 | {}, |
314 | }; | 350 | }; |
315 | MODULE_DEVICE_TABLE(of, ehci_orion_dt_ids); | 351 | MODULE_DEVICE_TABLE(of, ehci_orion_dt_ids); |
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index a268d9e8d6cf..bc7b9be12f54 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/usb.h> | 34 | #include <linux/usb.h> |
35 | #include <linux/usb/hcd.h> | 35 | #include <linux/usb/hcd.h> |
36 | #include <linux/usb/ehci_pdriver.h> | 36 | #include <linux/usb/ehci_pdriver.h> |
37 | #include <linux/usb/of.h> | ||
37 | 38 | ||
38 | #include "ehci.h" | 39 | #include "ehci.h" |
39 | 40 | ||
@@ -220,6 +221,9 @@ static int ehci_platform_probe(struct platform_device *dev) | |||
220 | if (IS_ERR(priv->phys[phy_num])) { | 221 | if (IS_ERR(priv->phys[phy_num])) { |
221 | err = PTR_ERR(priv->phys[phy_num]); | 222 | err = PTR_ERR(priv->phys[phy_num]); |
222 | goto err_put_hcd; | 223 | goto err_put_hcd; |
224 | } else if (!hcd->phy) { | ||
225 | /* Avoiding phy_get() in usb_add_hcd() */ | ||
226 | hcd->phy = priv->phys[phy_num]; | ||
223 | } | 227 | } |
224 | } | 228 | } |
225 | 229 | ||
@@ -297,6 +301,7 @@ static int ehci_platform_probe(struct platform_device *dev) | |||
297 | goto err_power; | 301 | goto err_power; |
298 | 302 | ||
299 | device_wakeup_enable(hcd->self.controller); | 303 | device_wakeup_enable(hcd->self.controller); |
304 | device_enable_async_suspend(hcd->self.controller); | ||
300 | platform_set_drvdata(dev, hcd); | 305 | platform_set_drvdata(dev, hcd); |
301 | 306 | ||
302 | return err; | 307 | return err; |
@@ -370,6 +375,7 @@ static int ehci_platform_resume(struct device *dev) | |||
370 | struct usb_ehci_pdata *pdata = dev_get_platdata(dev); | 375 | struct usb_ehci_pdata *pdata = dev_get_platdata(dev); |
371 | struct platform_device *pdev = to_platform_device(dev); | 376 | struct platform_device *pdev = to_platform_device(dev); |
372 | struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd); | 377 | struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd); |
378 | struct device *companion_dev; | ||
373 | 379 | ||
374 | if (pdata->power_on) { | 380 | if (pdata->power_on) { |
375 | int err = pdata->power_on(pdev); | 381 | int err = pdata->power_on(pdev); |
@@ -377,6 +383,10 @@ static int ehci_platform_resume(struct device *dev) | |||
377 | return err; | 383 | return err; |
378 | } | 384 | } |
379 | 385 | ||
386 | companion_dev = usb_of_get_companion_dev(hcd->self.controller); | ||
387 | if (companion_dev) | ||
388 | device_pm_wait_for_dev(hcd->self.controller, companion_dev); | ||
389 | |||
380 | ehci_resume(hcd, priv->reset_on_resume); | 390 | ehci_resume(hcd, priv->reset_on_resume); |
381 | return 0; | 391 | return 0; |
382 | } | 392 | } |
diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c index 1c5b34b74860..ced08dc229ad 100644 --- a/drivers/usb/host/fotg210-hcd.c +++ b/drivers/usb/host/fotg210-hcd.c | |||
@@ -5047,7 +5047,7 @@ static int fotg210_run(struct usb_hcd *hcd) | |||
5047 | /* | 5047 | /* |
5048 | * hcc_params controls whether fotg210->regs->segment must (!!!) | 5048 | * hcc_params controls whether fotg210->regs->segment must (!!!) |
5049 | * be used; it constrains QH/ITD/SITD and QTD locations. | 5049 | * be used; it constrains QH/ITD/SITD and QTD locations. |
5050 | * pci_pool consistent memory always uses segment zero. | 5050 | * dma_pool consistent memory always uses segment zero. |
5051 | * streaming mappings for I/O buffers, like pci_map_single(), | 5051 | * streaming mappings for I/O buffers, like pci_map_single(), |
5052 | * can return segments above 4GB, if the device allows. | 5052 | * can return segments above 4GB, if the device allows. |
5053 | * | 5053 | * |
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index b6daf2e69989..44924824fa41 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
@@ -231,7 +231,8 @@ static int ohci_urb_enqueue ( | |||
231 | 231 | ||
232 | /* Start up the I/O watchdog timer, if it's not running */ | 232 | /* Start up the I/O watchdog timer, if it's not running */ |
233 | if (!timer_pending(&ohci->io_watchdog) && | 233 | if (!timer_pending(&ohci->io_watchdog) && |
234 | list_empty(&ohci->eds_in_use)) { | 234 | list_empty(&ohci->eds_in_use) && |
235 | !(ohci->flags & OHCI_QUIRK_QEMU)) { | ||
235 | ohci->prev_frame_no = ohci_frame_no(ohci); | 236 | ohci->prev_frame_no = ohci_frame_no(ohci); |
236 | mod_timer(&ohci->io_watchdog, | 237 | mod_timer(&ohci->io_watchdog, |
237 | jiffies + IO_WATCHDOG_DELAY); | 238 | jiffies + IO_WATCHDOG_DELAY); |
@@ -994,7 +995,7 @@ static void ohci_stop (struct usb_hcd *hcd) | |||
994 | 995 | ||
995 | /*-------------------------------------------------------------------------*/ | 996 | /*-------------------------------------------------------------------------*/ |
996 | 997 | ||
997 | #if defined(CONFIG_PM) || defined(CONFIG_PCI) | 998 | #if defined(CONFIG_PM) || defined(CONFIG_USB_PCI) |
998 | 999 | ||
999 | /* must not be called from interrupt context */ | 1000 | /* must not be called from interrupt context */ |
1000 | int ohci_restart(struct ohci_hcd *ohci) | 1001 | int ohci_restart(struct ohci_hcd *ohci) |
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index bb1509675727..a84aebe9b0a9 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c | |||
@@ -164,6 +164,15 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd) | |||
164 | return 0; | 164 | return 0; |
165 | } | 165 | } |
166 | 166 | ||
167 | static int ohci_quirk_qemu(struct usb_hcd *hcd) | ||
168 | { | ||
169 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | ||
170 | |||
171 | ohci->flags |= OHCI_QUIRK_QEMU; | ||
172 | ohci_dbg(ohci, "enabled qemu quirk\n"); | ||
173 | return 0; | ||
174 | } | ||
175 | |||
167 | /* List of quirks for OHCI */ | 176 | /* List of quirks for OHCI */ |
168 | static const struct pci_device_id ohci_pci_quirks[] = { | 177 | static const struct pci_device_id ohci_pci_quirks[] = { |
169 | { | 178 | { |
@@ -214,6 +223,13 @@ static const struct pci_device_id ohci_pci_quirks[] = { | |||
214 | PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399), | 223 | PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399), |
215 | .driver_data = (unsigned long)ohci_quirk_amd700, | 224 | .driver_data = (unsigned long)ohci_quirk_amd700, |
216 | }, | 225 | }, |
226 | { | ||
227 | .vendor = PCI_VENDOR_ID_APPLE, | ||
228 | .device = 0x003f, | ||
229 | .subvendor = PCI_SUBVENDOR_ID_REDHAT_QUMRANET, | ||
230 | .subdevice = PCI_SUBDEVICE_ID_QEMU, | ||
231 | .driver_data = (unsigned long)ohci_quirk_qemu, | ||
232 | }, | ||
217 | 233 | ||
218 | /* FIXME for some of the early AMD 760 southbridges, OHCI | 234 | /* FIXME for some of the early AMD 760 southbridges, OHCI |
219 | * won't work at all. blacklist them. | 235 | * won't work at all. blacklist them. |
diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c index 898b74086c12..6368fce43197 100644 --- a/drivers/usb/host/ohci-platform.c +++ b/drivers/usb/host/ohci-platform.c | |||
@@ -183,6 +183,9 @@ static int ohci_platform_probe(struct platform_device *dev) | |||
183 | if (IS_ERR(priv->phys[phy_num])) { | 183 | if (IS_ERR(priv->phys[phy_num])) { |
184 | err = PTR_ERR(priv->phys[phy_num]); | 184 | err = PTR_ERR(priv->phys[phy_num]); |
185 | goto err_put_hcd; | 185 | goto err_put_hcd; |
186 | } else if (!hcd->phy) { | ||
187 | /* Avoiding phy_get() in usb_add_hcd() */ | ||
188 | hcd->phy = priv->phys[phy_num]; | ||
186 | } | 189 | } |
187 | } | 190 | } |
188 | 191 | ||
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 37f1725e7a46..12742d002d2d 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h | |||
@@ -418,6 +418,7 @@ struct ohci_hcd { | |||
418 | #define OHCI_QUIRK_AMD_PLL 0x200 /* AMD PLL quirk*/ | 418 | #define OHCI_QUIRK_AMD_PLL 0x200 /* AMD PLL quirk*/ |
419 | #define OHCI_QUIRK_AMD_PREFETCH 0x400 /* pre-fetch for ISO transfer */ | 419 | #define OHCI_QUIRK_AMD_PREFETCH 0x400 /* pre-fetch for ISO transfer */ |
420 | #define OHCI_QUIRK_GLOBAL_SUSPEND 0x800 /* must suspend ports */ | 420 | #define OHCI_QUIRK_GLOBAL_SUSPEND 0x800 /* must suspend ports */ |
421 | #define OHCI_QUIRK_QEMU 0x1000 /* relax timing expectations */ | ||
421 | 422 | ||
422 | // there are also chip quirks/bugs in init logic | 423 | // there are also chip quirks/bugs in init logic |
423 | 424 | ||
@@ -438,7 +439,7 @@ struct ohci_hcd { | |||
438 | 439 | ||
439 | }; | 440 | }; |
440 | 441 | ||
441 | #ifdef CONFIG_PCI | 442 | #ifdef CONFIG_USB_PCI |
442 | static inline int quirk_nec(struct ohci_hcd *ohci) | 443 | static inline int quirk_nec(struct ohci_hcd *ohci) |
443 | { | 444 | { |
444 | return ohci->flags & OHCI_QUIRK_NEC; | 445 | return ohci->flags & OHCI_QUIRK_NEC; |
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index bcf531c44c70..ed20fb34c897 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c | |||
@@ -2708,7 +2708,7 @@ static int oxu_run(struct usb_hcd *hcd) | |||
2708 | 2708 | ||
2709 | /* hcc_params controls whether oxu->regs->segment must (!!!) | 2709 | /* hcc_params controls whether oxu->regs->segment must (!!!) |
2710 | * be used; it constrains QH/ITD/SITD and QTD locations. | 2710 | * be used; it constrains QH/ITD/SITD and QTD locations. |
2711 | * pci_pool consistent memory always uses segment zero. | 2711 | * dma_pool consistent memory always uses segment zero. |
2712 | * streaming mappings for I/O buffers, like pci_map_single(), | 2712 | * streaming mappings for I/O buffers, like pci_map_single(), |
2713 | * can return segments above 4GB, if the device allows. | 2713 | * can return segments above 4GB, if the device allows. |
2714 | * | 2714 | * |
diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h index c622ddf21c94..0222195bd5b0 100644 --- a/drivers/usb/host/pci-quirks.h +++ b/drivers/usb/host/pci-quirks.h | |||
@@ -1,7 +1,7 @@ | |||
1 | #ifndef __LINUX_USB_PCI_QUIRKS_H | 1 | #ifndef __LINUX_USB_PCI_QUIRKS_H |
2 | #define __LINUX_USB_PCI_QUIRKS_H | 2 | #define __LINUX_USB_PCI_QUIRKS_H |
3 | 3 | ||
4 | #ifdef CONFIG_PCI | 4 | #ifdef CONFIG_USB_PCI |
5 | void uhci_reset_hc(struct pci_dev *pdev, unsigned long base); | 5 | void uhci_reset_hc(struct pci_dev *pdev, unsigned long base); |
6 | int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base); | 6 | int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base); |
7 | int usb_amd_find_chipset_info(void); | 7 | int usb_amd_find_chipset_info(void); |
@@ -21,6 +21,6 @@ static inline void usb_amd_quirk_pll_enable(void) {} | |||
21 | static inline void usb_amd_dev_put(void) {} | 21 | static inline void usb_amd_dev_put(void) {} |
22 | static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {} | 22 | static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {} |
23 | static inline void sb800_prefetch(struct device *dev, int on) {} | 23 | static inline void sb800_prefetch(struct device *dev, int on) {} |
24 | #endif /* CONFIG_PCI */ | 24 | #endif /* CONFIG_USB_PCI */ |
25 | 25 | ||
26 | #endif /* __LINUX_USB_PCI_QUIRKS_H */ | 26 | #endif /* __LINUX_USB_PCI_QUIRKS_H */ |
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 683098afa93e..94b150196d4f 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -837,7 +837,7 @@ static int uhci_count_ports(struct usb_hcd *hcd) | |||
837 | 837 | ||
838 | static const char hcd_name[] = "uhci_hcd"; | 838 | static const char hcd_name[] = "uhci_hcd"; |
839 | 839 | ||
840 | #ifdef CONFIG_PCI | 840 | #ifdef CONFIG_USB_PCI |
841 | #include "uhci-pci.c" | 841 | #include "uhci-pci.c" |
842 | #define PCI_DRIVER uhci_pci_driver | 842 | #define PCI_DRIVER uhci_pci_driver |
843 | #endif | 843 | #endif |
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 6f986d82472d..7fa318a3091d 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h | |||
@@ -530,7 +530,7 @@ static inline void uhci_writeb(const struct uhci_hcd *uhci, u8 val, int reg) | |||
530 | 530 | ||
531 | #else | 531 | #else |
532 | /* Support non-PCI host controllers */ | 532 | /* Support non-PCI host controllers */ |
533 | #ifdef CONFIG_PCI | 533 | #ifdef CONFIG_USB_PCI |
534 | /* Support PCI and non-PCI host controllers */ | 534 | /* Support PCI and non-PCI host controllers */ |
535 | #define uhci_has_pci_registers(u) ((u)->io_addr != 0) | 535 | #define uhci_has_pci_registers(u) ((u)->io_addr != 0) |
536 | #else | 536 | #else |
diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index 2b4a00fa735d..2c83b37ae8f2 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c | |||
@@ -254,157 +254,6 @@ void xhci_print_registers(struct xhci_hcd *xhci) | |||
254 | xhci_print_ports(xhci); | 254 | xhci_print_ports(xhci); |
255 | } | 255 | } |
256 | 256 | ||
257 | void xhci_print_trb_offsets(struct xhci_hcd *xhci, union xhci_trb *trb) | ||
258 | { | ||
259 | int i; | ||
260 | for (i = 0; i < 4; i++) | ||
261 | xhci_dbg(xhci, "Offset 0x%x = 0x%x\n", | ||
262 | i*4, trb->generic.field[i]); | ||
263 | } | ||
264 | |||
265 | /** | ||
266 | * Debug a transfer request block (TRB). | ||
267 | */ | ||
268 | void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb) | ||
269 | { | ||
270 | u64 address; | ||
271 | u32 type = le32_to_cpu(trb->link.control) & TRB_TYPE_BITMASK; | ||
272 | |||
273 | switch (type) { | ||
274 | case TRB_TYPE(TRB_LINK): | ||
275 | xhci_dbg(xhci, "Link TRB:\n"); | ||
276 | xhci_print_trb_offsets(xhci, trb); | ||
277 | |||
278 | address = le64_to_cpu(trb->link.segment_ptr); | ||
279 | xhci_dbg(xhci, "Next ring segment DMA address = 0x%llx\n", address); | ||
280 | |||
281 | xhci_dbg(xhci, "Interrupter target = 0x%x\n", | ||
282 | GET_INTR_TARGET(le32_to_cpu(trb->link.intr_target))); | ||
283 | xhci_dbg(xhci, "Cycle bit = %u\n", | ||
284 | le32_to_cpu(trb->link.control) & TRB_CYCLE); | ||
285 | xhci_dbg(xhci, "Toggle cycle bit = %u\n", | ||
286 | le32_to_cpu(trb->link.control) & LINK_TOGGLE); | ||
287 | xhci_dbg(xhci, "No Snoop bit = %u\n", | ||
288 | le32_to_cpu(trb->link.control) & TRB_NO_SNOOP); | ||
289 | break; | ||
290 | case TRB_TYPE(TRB_TRANSFER): | ||
291 | address = le64_to_cpu(trb->trans_event.buffer); | ||
292 | /* | ||
293 | * FIXME: look at flags to figure out if it's an address or if | ||
294 | * the data is directly in the buffer field. | ||
295 | */ | ||
296 | xhci_dbg(xhci, "DMA address or buffer contents= %llu\n", address); | ||
297 | break; | ||
298 | case TRB_TYPE(TRB_COMPLETION): | ||
299 | address = le64_to_cpu(trb->event_cmd.cmd_trb); | ||
300 | xhci_dbg(xhci, "Command TRB pointer = %llu\n", address); | ||
301 | xhci_dbg(xhci, "Completion status = %u\n", | ||
302 | GET_COMP_CODE(le32_to_cpu(trb->event_cmd.status))); | ||
303 | xhci_dbg(xhci, "Flags = 0x%x\n", | ||
304 | le32_to_cpu(trb->event_cmd.flags)); | ||
305 | break; | ||
306 | default: | ||
307 | xhci_dbg(xhci, "Unknown TRB with TRB type ID %u\n", | ||
308 | (unsigned int) type>>10); | ||
309 | xhci_print_trb_offsets(xhci, trb); | ||
310 | break; | ||
311 | } | ||
312 | } | ||
313 | |||
314 | /** | ||
315 | * Debug a segment with an xHCI ring. | ||
316 | * | ||
317 | * @return The Link TRB of the segment, or NULL if there is no Link TRB | ||
318 | * (which is a bug, since all segments must have a Link TRB). | ||
319 | * | ||
320 | * Prints out all TRBs in the segment, even those after the Link TRB. | ||
321 | * | ||
322 | * XXX: should we print out TRBs that the HC owns? As long as we don't | ||
323 | * write, that should be fine... We shouldn't expect that the memory pointed to | ||
324 | * by the TRB is valid at all. Do we care about ones the HC owns? Probably, | ||
325 | * for HC debugging. | ||
326 | */ | ||
327 | void xhci_debug_segment(struct xhci_hcd *xhci, struct xhci_segment *seg) | ||
328 | { | ||
329 | int i; | ||
330 | u64 addr = seg->dma; | ||
331 | union xhci_trb *trb = seg->trbs; | ||
332 | |||
333 | for (i = 0; i < TRBS_PER_SEGMENT; i++) { | ||
334 | trb = &seg->trbs[i]; | ||
335 | xhci_dbg(xhci, "@%016llx %08x %08x %08x %08x\n", addr, | ||
336 | lower_32_bits(le64_to_cpu(trb->link.segment_ptr)), | ||
337 | upper_32_bits(le64_to_cpu(trb->link.segment_ptr)), | ||
338 | le32_to_cpu(trb->link.intr_target), | ||
339 | le32_to_cpu(trb->link.control)); | ||
340 | addr += sizeof(*trb); | ||
341 | } | ||
342 | } | ||
343 | |||
344 | void xhci_dbg_ring_ptrs(struct xhci_hcd *xhci, struct xhci_ring *ring) | ||
345 | { | ||
346 | xhci_dbg(xhci, "Ring deq = %p (virt), 0x%llx (dma)\n", | ||
347 | ring->dequeue, | ||
348 | (unsigned long long)xhci_trb_virt_to_dma(ring->deq_seg, | ||
349 | ring->dequeue)); | ||
350 | xhci_dbg(xhci, "Ring deq updated %u times\n", | ||
351 | ring->deq_updates); | ||
352 | xhci_dbg(xhci, "Ring enq = %p (virt), 0x%llx (dma)\n", | ||
353 | ring->enqueue, | ||
354 | (unsigned long long)xhci_trb_virt_to_dma(ring->enq_seg, | ||
355 | ring->enqueue)); | ||
356 | xhci_dbg(xhci, "Ring enq updated %u times\n", | ||
357 | ring->enq_updates); | ||
358 | } | ||
359 | |||
360 | /** | ||
361 | * Debugging for an xHCI ring, which is a queue broken into multiple segments. | ||
362 | * | ||
363 | * Print out each segment in the ring. Check that the DMA address in | ||
364 | * each link segment actually matches the segment's stored DMA address. | ||
365 | * Check that the link end bit is only set at the end of the ring. | ||
366 | * Check that the dequeue and enqueue pointers point to real data in this ring | ||
367 | * (not some other ring). | ||
368 | */ | ||
369 | void xhci_debug_ring(struct xhci_hcd *xhci, struct xhci_ring *ring) | ||
370 | { | ||
371 | /* FIXME: Throw an error if any segment doesn't have a Link TRB */ | ||
372 | struct xhci_segment *seg; | ||
373 | struct xhci_segment *first_seg = ring->first_seg; | ||
374 | xhci_debug_segment(xhci, first_seg); | ||
375 | |||
376 | if (!ring->enq_updates && !ring->deq_updates) { | ||
377 | xhci_dbg(xhci, " Ring has not been updated\n"); | ||
378 | return; | ||
379 | } | ||
380 | for (seg = first_seg->next; seg != first_seg; seg = seg->next) | ||
381 | xhci_debug_segment(xhci, seg); | ||
382 | } | ||
383 | |||
384 | void xhci_dbg_ep_rings(struct xhci_hcd *xhci, | ||
385 | unsigned int slot_id, unsigned int ep_index, | ||
386 | struct xhci_virt_ep *ep) | ||
387 | { | ||
388 | int i; | ||
389 | struct xhci_ring *ring; | ||
390 | |||
391 | if (ep->ep_state & EP_HAS_STREAMS) { | ||
392 | for (i = 1; i < ep->stream_info->num_streams; i++) { | ||
393 | ring = ep->stream_info->stream_rings[i]; | ||
394 | xhci_dbg(xhci, "Dev %d endpoint %d stream ID %d:\n", | ||
395 | slot_id, ep_index, i); | ||
396 | xhci_debug_segment(xhci, ring->deq_seg); | ||
397 | } | ||
398 | } else { | ||
399 | ring = ep->ring; | ||
400 | if (!ring) | ||
401 | return; | ||
402 | xhci_dbg(xhci, "Dev %d endpoint ring %d:\n", | ||
403 | slot_id, ep_index); | ||
404 | xhci_debug_segment(xhci, ring->deq_seg); | ||
405 | } | ||
406 | } | ||
407 | |||
408 | void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst) | 257 | void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst) |
409 | { | 258 | { |
410 | u64 addr = erst->erst_dma_addr; | 259 | u64 addr = erst->erst_dma_addr; |
@@ -434,166 +283,13 @@ void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci) | |||
434 | upper_32_bits(val)); | 283 | upper_32_bits(val)); |
435 | } | 284 | } |
436 | 285 | ||
437 | /* Print the last 32 bytes for 64-byte contexts */ | ||
438 | static void dbg_rsvd64(struct xhci_hcd *xhci, u64 *ctx, dma_addr_t dma) | ||
439 | { | ||
440 | int i; | ||
441 | for (i = 0; i < 4; i++) { | ||
442 | xhci_dbg(xhci, "@%p (virt) @%08llx " | ||
443 | "(dma) %#08llx - rsvd64[%d]\n", | ||
444 | &ctx[4 + i], (unsigned long long)dma, | ||
445 | ctx[4 + i], i); | ||
446 | dma += 8; | ||
447 | } | ||
448 | } | ||
449 | |||
450 | char *xhci_get_slot_state(struct xhci_hcd *xhci, | 286 | char *xhci_get_slot_state(struct xhci_hcd *xhci, |
451 | struct xhci_container_ctx *ctx) | 287 | struct xhci_container_ctx *ctx) |
452 | { | 288 | { |
453 | struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx); | 289 | struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx); |
290 | int state = GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state)); | ||
454 | 291 | ||
455 | switch (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state))) { | 292 | return xhci_slot_state_string(state); |
456 | case SLOT_STATE_ENABLED: | ||
457 | return "enabled/disabled"; | ||
458 | case SLOT_STATE_DEFAULT: | ||
459 | return "default"; | ||
460 | case SLOT_STATE_ADDRESSED: | ||
461 | return "addressed"; | ||
462 | case SLOT_STATE_CONFIGURED: | ||
463 | return "configured"; | ||
464 | default: | ||
465 | return "reserved"; | ||
466 | } | ||
467 | } | ||
468 | |||
469 | static void xhci_dbg_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx) | ||
470 | { | ||
471 | /* Fields are 32 bits wide, DMA addresses are in bytes */ | ||
472 | int field_size = 32 / 8; | ||
473 | int i; | ||
474 | |||
475 | struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx); | ||
476 | dma_addr_t dma = ctx->dma + | ||
477 | ((unsigned long)slot_ctx - (unsigned long)ctx->bytes); | ||
478 | int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params); | ||
479 | |||
480 | xhci_dbg(xhci, "Slot Context:\n"); | ||
481 | xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info\n", | ||
482 | &slot_ctx->dev_info, | ||
483 | (unsigned long long)dma, slot_ctx->dev_info); | ||
484 | dma += field_size; | ||
485 | xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info2\n", | ||
486 | &slot_ctx->dev_info2, | ||
487 | (unsigned long long)dma, slot_ctx->dev_info2); | ||
488 | dma += field_size; | ||
489 | xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tt_info\n", | ||
490 | &slot_ctx->tt_info, | ||
491 | (unsigned long long)dma, slot_ctx->tt_info); | ||
492 | dma += field_size; | ||
493 | xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_state\n", | ||
494 | &slot_ctx->dev_state, | ||
495 | (unsigned long long)dma, slot_ctx->dev_state); | ||
496 | dma += field_size; | ||
497 | for (i = 0; i < 4; i++) { | ||
498 | xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n", | ||
499 | &slot_ctx->reserved[i], (unsigned long long)dma, | ||
500 | slot_ctx->reserved[i], i); | ||
501 | dma += field_size; | ||
502 | } | ||
503 | |||
504 | if (csz) | ||
505 | dbg_rsvd64(xhci, (u64 *)slot_ctx, dma); | ||
506 | } | ||
507 | |||
508 | static void xhci_dbg_ep_ctx(struct xhci_hcd *xhci, | ||
509 | struct xhci_container_ctx *ctx, | ||
510 | unsigned int last_ep) | ||
511 | { | ||
512 | int i, j; | ||
513 | int last_ep_ctx = 31; | ||
514 | /* Fields are 32 bits wide, DMA addresses are in bytes */ | ||
515 | int field_size = 32 / 8; | ||
516 | int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params); | ||
517 | |||
518 | if (last_ep < 31) | ||
519 | last_ep_ctx = last_ep + 1; | ||
520 | for (i = 0; i < last_ep_ctx; i++) { | ||
521 | unsigned int epaddr = xhci_get_endpoint_address(i); | ||
522 | struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, ctx, i); | ||
523 | dma_addr_t dma = ctx->dma + | ||
524 | ((unsigned long)ep_ctx - (unsigned long)ctx->bytes); | ||
525 | |||
526 | xhci_dbg(xhci, "%s Endpoint %02d Context (ep_index %02d):\n", | ||
527 | usb_endpoint_out(epaddr) ? "OUT" : "IN", | ||
528 | epaddr & USB_ENDPOINT_NUMBER_MASK, i); | ||
529 | xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info\n", | ||
530 | &ep_ctx->ep_info, | ||
531 | (unsigned long long)dma, ep_ctx->ep_info); | ||
532 | dma += field_size; | ||
533 | xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info2\n", | ||
534 | &ep_ctx->ep_info2, | ||
535 | (unsigned long long)dma, ep_ctx->ep_info2); | ||
536 | dma += field_size; | ||
537 | xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08llx - deq\n", | ||
538 | &ep_ctx->deq, | ||
539 | (unsigned long long)dma, ep_ctx->deq); | ||
540 | dma += 2*field_size; | ||
541 | xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tx_info\n", | ||
542 | &ep_ctx->tx_info, | ||
543 | (unsigned long long)dma, ep_ctx->tx_info); | ||
544 | dma += field_size; | ||
545 | for (j = 0; j < 3; j++) { | ||
546 | xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n", | ||
547 | &ep_ctx->reserved[j], | ||
548 | (unsigned long long)dma, | ||
549 | ep_ctx->reserved[j], j); | ||
550 | dma += field_size; | ||
551 | } | ||
552 | |||
553 | if (csz) | ||
554 | dbg_rsvd64(xhci, (u64 *)ep_ctx, dma); | ||
555 | } | ||
556 | } | ||
557 | |||
558 | void xhci_dbg_ctx(struct xhci_hcd *xhci, | ||
559 | struct xhci_container_ctx *ctx, | ||
560 | unsigned int last_ep) | ||
561 | { | ||
562 | int i; | ||
563 | /* Fields are 32 bits wide, DMA addresses are in bytes */ | ||
564 | int field_size = 32 / 8; | ||
565 | dma_addr_t dma = ctx->dma; | ||
566 | int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params); | ||
567 | |||
568 | if (ctx->type == XHCI_CTX_TYPE_INPUT) { | ||
569 | struct xhci_input_control_ctx *ctrl_ctx = | ||
570 | xhci_get_input_control_ctx(ctx); | ||
571 | if (!ctrl_ctx) { | ||
572 | xhci_warn(xhci, "Could not get input context, bad type.\n"); | ||
573 | return; | ||
574 | } | ||
575 | |||
576 | xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - drop flags\n", | ||
577 | &ctrl_ctx->drop_flags, (unsigned long long)dma, | ||
578 | ctrl_ctx->drop_flags); | ||
579 | dma += field_size; | ||
580 | xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - add flags\n", | ||
581 | &ctrl_ctx->add_flags, (unsigned long long)dma, | ||
582 | ctrl_ctx->add_flags); | ||
583 | dma += field_size; | ||
584 | for (i = 0; i < 6; i++) { | ||
585 | xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd2[%d]\n", | ||
586 | &ctrl_ctx->rsvd2[i], (unsigned long long)dma, | ||
587 | ctrl_ctx->rsvd2[i], i); | ||
588 | dma += field_size; | ||
589 | } | ||
590 | |||
591 | if (csz) | ||
592 | dbg_rsvd64(xhci, (u64 *)ctrl_ctx, dma); | ||
593 | } | ||
594 | |||
595 | xhci_dbg_slot_ctx(xhci, ctx); | ||
596 | xhci_dbg_ep_ctx(xhci, ctx, last_ep); | ||
597 | } | 293 | } |
598 | 294 | ||
599 | void xhci_dbg_trace(struct xhci_hcd *xhci, void (*trace)(struct va_format *), | 295 | void xhci_dbg_trace(struct xhci_hcd *xhci, void (*trace)(struct va_format *), |
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 3bddeaa1e2d7..5e3e9d4c6956 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c | |||
@@ -392,10 +392,8 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) | |||
392 | trace_xhci_stop_device(virt_dev); | 392 | trace_xhci_stop_device(virt_dev); |
393 | 393 | ||
394 | cmd = xhci_alloc_command(xhci, false, true, GFP_NOIO); | 394 | cmd = xhci_alloc_command(xhci, false, true, GFP_NOIO); |
395 | if (!cmd) { | 395 | if (!cmd) |
396 | xhci_dbg(xhci, "Couldn't allocate command structure.\n"); | ||
397 | return -ENOMEM; | 396 | return -ENOMEM; |
398 | } | ||
399 | 397 | ||
400 | spin_lock_irqsave(&xhci->lock, flags); | 398 | spin_lock_irqsave(&xhci->lock, flags); |
401 | for (i = LAST_EP_INDEX; i > 0; i--) { | 399 | for (i = LAST_EP_INDEX; i > 0; i--) { |
@@ -540,6 +538,119 @@ static int xhci_get_ports(struct usb_hcd *hcd, __le32 __iomem ***port_array) | |||
540 | return max_ports; | 538 | return max_ports; |
541 | } | 539 | } |
542 | 540 | ||
541 | static __le32 __iomem *xhci_get_port_io_addr(struct usb_hcd *hcd, int index) | ||
542 | { | ||
543 | __le32 __iomem **port_array; | ||
544 | |||
545 | xhci_get_ports(hcd, &port_array); | ||
546 | return port_array[index]; | ||
547 | } | ||
548 | |||
549 | /* | ||
550 | * xhci_set_port_power() must be called with xhci->lock held. | ||
551 | * It will release and re-aquire the lock while calling ACPI | ||
552 | * method. | ||
553 | */ | ||
554 | static void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd, | ||
555 | u16 index, bool on, unsigned long *flags) | ||
556 | { | ||
557 | __le32 __iomem *addr; | ||
558 | u32 temp; | ||
559 | |||
560 | addr = xhci_get_port_io_addr(hcd, index); | ||
561 | temp = readl(addr); | ||
562 | temp = xhci_port_state_to_neutral(temp); | ||
563 | if (on) { | ||
564 | /* Power on */ | ||
565 | writel(temp | PORT_POWER, addr); | ||
566 | temp = readl(addr); | ||
567 | xhci_dbg(xhci, "set port power, actual port %d status = 0x%x\n", | ||
568 | index, temp); | ||
569 | } else { | ||
570 | /* Power off */ | ||
571 | writel(temp & ~PORT_POWER, addr); | ||
572 | } | ||
573 | |||
574 | spin_unlock_irqrestore(&xhci->lock, *flags); | ||
575 | temp = usb_acpi_power_manageable(hcd->self.root_hub, | ||
576 | index); | ||
577 | if (temp) | ||
578 | usb_acpi_set_power_state(hcd->self.root_hub, | ||
579 | index, on); | ||
580 | spin_lock_irqsave(&xhci->lock, *flags); | ||
581 | } | ||
582 | |||
583 | static void xhci_port_set_test_mode(struct xhci_hcd *xhci, | ||
584 | u16 test_mode, u16 wIndex) | ||
585 | { | ||
586 | u32 temp; | ||
587 | __le32 __iomem *addr; | ||
588 | |||
589 | /* xhci only supports test mode for usb2 ports, i.e. xhci->main_hcd */ | ||
590 | addr = xhci_get_port_io_addr(xhci->main_hcd, wIndex); | ||
591 | temp = readl(addr + PORTPMSC); | ||
592 | temp |= test_mode << PORT_TEST_MODE_SHIFT; | ||
593 | writel(temp, addr + PORTPMSC); | ||
594 | xhci->test_mode = test_mode; | ||
595 | if (test_mode == TEST_FORCE_EN) | ||
596 | xhci_start(xhci); | ||
597 | } | ||
598 | |||
599 | static int xhci_enter_test_mode(struct xhci_hcd *xhci, | ||
600 | u16 test_mode, u16 wIndex, unsigned long *flags) | ||
601 | { | ||
602 | int i, retval; | ||
603 | |||
604 | /* Disable all Device Slots */ | ||
605 | xhci_dbg(xhci, "Disable all slots\n"); | ||
606 | for (i = 1; i <= HCS_MAX_SLOTS(xhci->hcs_params1); i++) { | ||
607 | retval = xhci_disable_slot(xhci, NULL, i); | ||
608 | if (retval) | ||
609 | xhci_err(xhci, "Failed to disable slot %d, %d. Enter test mode anyway\n", | ||
610 | i, retval); | ||
611 | } | ||
612 | /* Put all ports to the Disable state by clear PP */ | ||
613 | xhci_dbg(xhci, "Disable all port (PP = 0)\n"); | ||
614 | /* Power off USB3 ports*/ | ||
615 | for (i = 0; i < xhci->num_usb3_ports; i++) | ||
616 | xhci_set_port_power(xhci, xhci->shared_hcd, i, false, flags); | ||
617 | /* Power off USB2 ports*/ | ||
618 | for (i = 0; i < xhci->num_usb2_ports; i++) | ||
619 | xhci_set_port_power(xhci, xhci->main_hcd, i, false, flags); | ||
620 | /* Stop the controller */ | ||
621 | xhci_dbg(xhci, "Stop controller\n"); | ||
622 | retval = xhci_halt(xhci); | ||
623 | if (retval) | ||
624 | return retval; | ||
625 | /* Disable runtime PM for test mode */ | ||
626 | pm_runtime_forbid(xhci_to_hcd(xhci)->self.controller); | ||
627 | /* Set PORTPMSC.PTC field to enter selected test mode */ | ||
628 | /* Port is selected by wIndex. port_id = wIndex + 1 */ | ||
629 | xhci_dbg(xhci, "Enter Test Mode: %d, Port_id=%d\n", | ||
630 | test_mode, wIndex + 1); | ||
631 | xhci_port_set_test_mode(xhci, test_mode, wIndex); | ||
632 | return retval; | ||
633 | } | ||
634 | |||
635 | static int xhci_exit_test_mode(struct xhci_hcd *xhci) | ||
636 | { | ||
637 | int retval; | ||
638 | |||
639 | if (!xhci->test_mode) { | ||
640 | xhci_err(xhci, "Not in test mode, do nothing.\n"); | ||
641 | return 0; | ||
642 | } | ||
643 | if (xhci->test_mode == TEST_FORCE_EN && | ||
644 | !(xhci->xhc_state & XHCI_STATE_HALTED)) { | ||
645 | retval = xhci_halt(xhci); | ||
646 | if (retval) | ||
647 | return retval; | ||
648 | } | ||
649 | pm_runtime_allow(xhci_to_hcd(xhci)->self.controller); | ||
650 | xhci->test_mode = 0; | ||
651 | return xhci_reset(xhci); | ||
652 | } | ||
653 | |||
543 | void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array, | 654 | void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array, |
544 | int port_id, u32 link_state) | 655 | int port_id, u32 link_state) |
545 | { | 656 | { |
@@ -895,6 +1006,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
895 | u16 link_state = 0; | 1006 | u16 link_state = 0; |
896 | u16 wake_mask = 0; | 1007 | u16 wake_mask = 0; |
897 | u16 timeout = 0; | 1008 | u16 timeout = 0; |
1009 | u16 test_mode = 0; | ||
898 | 1010 | ||
899 | max_ports = xhci_get_ports(hcd, &port_array); | 1011 | max_ports = xhci_get_ports(hcd, &port_array); |
900 | bus_state = &xhci->bus_state[hcd_index(hcd)]; | 1012 | bus_state = &xhci->bus_state[hcd_index(hcd)]; |
@@ -935,7 +1047,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
935 | goto error; | 1047 | goto error; |
936 | wIndex--; | 1048 | wIndex--; |
937 | temp = readl(port_array[wIndex]); | 1049 | temp = readl(port_array[wIndex]); |
938 | if (temp == 0xffffffff) { | 1050 | if (temp == ~(u32)0) { |
1051 | xhci_hc_died(xhci); | ||
939 | retval = -ENODEV; | 1052 | retval = -ENODEV; |
940 | break; | 1053 | break; |
941 | } | 1054 | } |
@@ -968,6 +1081,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
968 | link_state = (wIndex & 0xff00) >> 3; | 1081 | link_state = (wIndex & 0xff00) >> 3; |
969 | if (wValue == USB_PORT_FEAT_REMOTE_WAKE_MASK) | 1082 | if (wValue == USB_PORT_FEAT_REMOTE_WAKE_MASK) |
970 | wake_mask = wIndex & 0xff00; | 1083 | wake_mask = wIndex & 0xff00; |
1084 | if (wValue == USB_PORT_FEAT_TEST) | ||
1085 | test_mode = (wIndex & 0xff00) >> 8; | ||
971 | /* The MSB of wIndex is the U1/U2 timeout */ | 1086 | /* The MSB of wIndex is the U1/U2 timeout */ |
972 | timeout = (wIndex & 0xff00) >> 8; | 1087 | timeout = (wIndex & 0xff00) >> 8; |
973 | wIndex &= 0xff; | 1088 | wIndex &= 0xff; |
@@ -975,7 +1090,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
975 | goto error; | 1090 | goto error; |
976 | wIndex--; | 1091 | wIndex--; |
977 | temp = readl(port_array[wIndex]); | 1092 | temp = readl(port_array[wIndex]); |
978 | if (temp == 0xffffffff) { | 1093 | if (temp == ~(u32)0) { |
1094 | xhci_hc_died(xhci); | ||
979 | retval = -ENODEV; | 1095 | retval = -ENODEV; |
980 | break; | 1096 | break; |
981 | } | 1097 | } |
@@ -1092,18 +1208,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
1092 | * However, hub_wq will ignore the roothub events until | 1208 | * However, hub_wq will ignore the roothub events until |
1093 | * the roothub is registered. | 1209 | * the roothub is registered. |
1094 | */ | 1210 | */ |
1095 | writel(temp | PORT_POWER, port_array[wIndex]); | 1211 | xhci_set_port_power(xhci, hcd, wIndex, true, &flags); |
1096 | |||
1097 | temp = readl(port_array[wIndex]); | ||
1098 | xhci_dbg(xhci, "set port power, actual port %d status = 0x%x\n", wIndex, temp); | ||
1099 | |||
1100 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
1101 | temp = usb_acpi_power_manageable(hcd->self.root_hub, | ||
1102 | wIndex); | ||
1103 | if (temp) | ||
1104 | usb_acpi_set_power_state(hcd->self.root_hub, | ||
1105 | wIndex, true); | ||
1106 | spin_lock_irqsave(&xhci->lock, flags); | ||
1107 | break; | 1212 | break; |
1108 | case USB_PORT_FEAT_RESET: | 1213 | case USB_PORT_FEAT_RESET: |
1109 | temp = (temp | PORT_RESET); | 1214 | temp = (temp | PORT_RESET); |
@@ -1142,6 +1247,15 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
1142 | temp |= PORT_U2_TIMEOUT(timeout); | 1247 | temp |= PORT_U2_TIMEOUT(timeout); |
1143 | writel(temp, port_array[wIndex] + PORTPMSC); | 1248 | writel(temp, port_array[wIndex] + PORTPMSC); |
1144 | break; | 1249 | break; |
1250 | case USB_PORT_FEAT_TEST: | ||
1251 | /* 4.19.6 Port Test Modes (USB2 Test Mode) */ | ||
1252 | if (hcd->speed != HCD_USB2) | ||
1253 | goto error; | ||
1254 | if (test_mode > TEST_FORCE_EN || test_mode < TEST_J) | ||
1255 | goto error; | ||
1256 | retval = xhci_enter_test_mode(xhci, test_mode, wIndex, | ||
1257 | &flags); | ||
1258 | break; | ||
1145 | default: | 1259 | default: |
1146 | goto error; | 1260 | goto error; |
1147 | } | 1261 | } |
@@ -1153,7 +1267,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
1153 | goto error; | 1267 | goto error; |
1154 | wIndex--; | 1268 | wIndex--; |
1155 | temp = readl(port_array[wIndex]); | 1269 | temp = readl(port_array[wIndex]); |
1156 | if (temp == 0xffffffff) { | 1270 | if (temp == ~(u32)0) { |
1271 | xhci_hc_died(xhci); | ||
1157 | retval = -ENODEV; | 1272 | retval = -ENODEV; |
1158 | break; | 1273 | break; |
1159 | } | 1274 | } |
@@ -1207,15 +1322,10 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
1207 | port_array[wIndex], temp); | 1322 | port_array[wIndex], temp); |
1208 | break; | 1323 | break; |
1209 | case USB_PORT_FEAT_POWER: | 1324 | case USB_PORT_FEAT_POWER: |
1210 | writel(temp & ~PORT_POWER, port_array[wIndex]); | 1325 | xhci_set_port_power(xhci, hcd, wIndex, false, &flags); |
1211 | 1326 | break; | |
1212 | spin_unlock_irqrestore(&xhci->lock, flags); | 1327 | case USB_PORT_FEAT_TEST: |
1213 | temp = usb_acpi_power_manageable(hcd->self.root_hub, | 1328 | retval = xhci_exit_test_mode(xhci); |
1214 | wIndex); | ||
1215 | if (temp) | ||
1216 | usb_acpi_set_power_state(hcd->self.root_hub, | ||
1217 | wIndex, false); | ||
1218 | spin_lock_irqsave(&xhci->lock, flags); | ||
1219 | break; | 1329 | break; |
1220 | default: | 1330 | default: |
1221 | goto error; | 1331 | goto error; |
@@ -1269,7 +1379,8 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
1269 | /* For each port, did anything change? If so, set that bit in buf. */ | 1379 | /* For each port, did anything change? If so, set that bit in buf. */ |
1270 | for (i = 0; i < max_ports; i++) { | 1380 | for (i = 0; i < max_ports; i++) { |
1271 | temp = readl(port_array[i]); | 1381 | temp = readl(port_array[i]); |
1272 | if (temp == 0xffffffff) { | 1382 | if (temp == ~(u32)0) { |
1383 | xhci_hc_died(xhci); | ||
1273 | retval = -ENODEV; | 1384 | retval = -ENODEV; |
1274 | break; | 1385 | break; |
1275 | } | 1386 | } |
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index ba1853f4e407..bbe22bcc550a 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c | |||
@@ -288,6 +288,8 @@ void xhci_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring) | |||
288 | if (!ring) | 288 | if (!ring) |
289 | return; | 289 | return; |
290 | 290 | ||
291 | trace_xhci_ring_free(ring); | ||
292 | |||
291 | if (ring->first_seg) { | 293 | if (ring->first_seg) { |
292 | if (ring->type == TYPE_STREAM) | 294 | if (ring->type == TYPE_STREAM) |
293 | xhci_remove_stream_mapping(ring); | 295 | xhci_remove_stream_mapping(ring); |
@@ -313,9 +315,6 @@ static void xhci_initialize_ring_info(struct xhci_ring *ring, | |||
313 | * handling ring expansion, set the cycle state equal to the old ring. | 315 | * handling ring expansion, set the cycle state equal to the old ring. |
314 | */ | 316 | */ |
315 | ring->cycle_state = cycle_state; | 317 | ring->cycle_state = cycle_state; |
316 | /* Not necessary for new rings, but needed for re-initialized rings */ | ||
317 | ring->enq_updates = 0; | ||
318 | ring->deq_updates = 0; | ||
319 | 318 | ||
320 | /* | 319 | /* |
321 | * Each segment has a link TRB, and leave an extra TRB for SW | 320 | * Each segment has a link TRB, and leave an extra TRB for SW |
@@ -400,6 +399,7 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci, | |||
400 | cpu_to_le32(LINK_TOGGLE); | 399 | cpu_to_le32(LINK_TOGGLE); |
401 | } | 400 | } |
402 | xhci_initialize_ring_info(ring, cycle_state); | 401 | xhci_initialize_ring_info(ring, cycle_state); |
402 | trace_xhci_ring_alloc(ring); | ||
403 | return ring; | 403 | return ring; |
404 | 404 | ||
405 | fail: | 405 | fail: |
@@ -504,6 +504,7 @@ int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring, | |||
504 | } | 504 | } |
505 | 505 | ||
506 | xhci_link_rings(xhci, ring, first, last, num_segs); | 506 | xhci_link_rings(xhci, ring, first, last, num_segs); |
507 | trace_xhci_ring_expansion(ring); | ||
507 | xhci_dbg_trace(xhci, trace_xhci_dbg_ring_expansion, | 508 | xhci_dbg_trace(xhci, trace_xhci_dbg_ring_expansion, |
508 | "ring expansion succeed, now has %d segments", | 509 | "ring expansion succeed, now has %d segments", |
509 | ring->num_segs); | 510 | ring->num_segs); |
@@ -586,7 +587,7 @@ static void xhci_free_stream_ctx(struct xhci_hcd *xhci, | |||
586 | unsigned int num_stream_ctxs, | 587 | unsigned int num_stream_ctxs, |
587 | struct xhci_stream_ctx *stream_ctx, dma_addr_t dma) | 588 | struct xhci_stream_ctx *stream_ctx, dma_addr_t dma) |
588 | { | 589 | { |
589 | struct device *dev = xhci_to_hcd(xhci)->self.controller; | 590 | struct device *dev = xhci_to_hcd(xhci)->self.sysdev; |
590 | size_t size = sizeof(struct xhci_stream_ctx) * num_stream_ctxs; | 591 | size_t size = sizeof(struct xhci_stream_ctx) * num_stream_ctxs; |
591 | 592 | ||
592 | if (size > MEDIUM_STREAM_ARRAY_SIZE) | 593 | if (size > MEDIUM_STREAM_ARRAY_SIZE) |
@@ -614,7 +615,7 @@ static struct xhci_stream_ctx *xhci_alloc_stream_ctx(struct xhci_hcd *xhci, | |||
614 | unsigned int num_stream_ctxs, dma_addr_t *dma, | 615 | unsigned int num_stream_ctxs, dma_addr_t *dma, |
615 | gfp_t mem_flags) | 616 | gfp_t mem_flags) |
616 | { | 617 | { |
617 | struct device *dev = xhci_to_hcd(xhci)->self.controller; | 618 | struct device *dev = xhci_to_hcd(xhci)->self.sysdev; |
618 | size_t size = sizeof(struct xhci_stream_ctx) * num_stream_ctxs; | 619 | size_t size = sizeof(struct xhci_stream_ctx) * num_stream_ctxs; |
619 | 620 | ||
620 | if (size > MEDIUM_STREAM_ARRAY_SIZE) | 621 | if (size > MEDIUM_STREAM_ARRAY_SIZE) |
@@ -1502,6 +1503,17 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, | |||
1502 | */ | 1503 | */ |
1503 | max_esit_payload = xhci_get_max_esit_payload(udev, ep); | 1504 | max_esit_payload = xhci_get_max_esit_payload(udev, ep); |
1504 | interval = xhci_get_endpoint_interval(udev, ep); | 1505 | interval = xhci_get_endpoint_interval(udev, ep); |
1506 | |||
1507 | /* Periodic endpoint bInterval limit quirk */ | ||
1508 | if (usb_endpoint_xfer_int(&ep->desc) || | ||
1509 | usb_endpoint_xfer_isoc(&ep->desc)) { | ||
1510 | if ((xhci->quirks & XHCI_LIMIT_ENDPOINT_INTERVAL_7) && | ||
1511 | udev->speed >= USB_SPEED_HIGH && | ||
1512 | interval >= 7) { | ||
1513 | interval = 6; | ||
1514 | } | ||
1515 | } | ||
1516 | |||
1505 | mult = xhci_get_endpoint_mult(udev, ep); | 1517 | mult = xhci_get_endpoint_mult(udev, ep); |
1506 | max_packet = usb_endpoint_maxp(&ep->desc); | 1518 | max_packet = usb_endpoint_maxp(&ep->desc); |
1507 | max_burst = xhci_get_endpoint_max_burst(udev, ep); | 1519 | max_burst = xhci_get_endpoint_max_burst(udev, ep); |
@@ -1686,7 +1698,7 @@ void xhci_slot_copy(struct xhci_hcd *xhci, | |||
1686 | static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) | 1698 | static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) |
1687 | { | 1699 | { |
1688 | int i; | 1700 | int i; |
1689 | struct device *dev = xhci_to_hcd(xhci)->self.controller; | 1701 | struct device *dev = xhci_to_hcd(xhci)->self.sysdev; |
1690 | int num_sp = HCS_MAX_SCRATCHPAD(xhci->hcs_params2); | 1702 | int num_sp = HCS_MAX_SCRATCHPAD(xhci->hcs_params2); |
1691 | 1703 | ||
1692 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, | 1704 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, |
@@ -1709,36 +1721,27 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) | |||
1709 | if (!xhci->scratchpad->sp_buffers) | 1721 | if (!xhci->scratchpad->sp_buffers) |
1710 | goto fail_sp3; | 1722 | goto fail_sp3; |
1711 | 1723 | ||
1712 | xhci->scratchpad->sp_dma_buffers = | ||
1713 | kzalloc(sizeof(dma_addr_t) * num_sp, flags); | ||
1714 | |||
1715 | if (!xhci->scratchpad->sp_dma_buffers) | ||
1716 | goto fail_sp4; | ||
1717 | |||
1718 | xhci->dcbaa->dev_context_ptrs[0] = cpu_to_le64(xhci->scratchpad->sp_dma); | 1724 | xhci->dcbaa->dev_context_ptrs[0] = cpu_to_le64(xhci->scratchpad->sp_dma); |
1719 | for (i = 0; i < num_sp; i++) { | 1725 | for (i = 0; i < num_sp; i++) { |
1720 | dma_addr_t dma; | 1726 | dma_addr_t dma; |
1721 | void *buf = dma_alloc_coherent(dev, xhci->page_size, &dma, | 1727 | void *buf = dma_alloc_coherent(dev, xhci->page_size, &dma, |
1722 | flags); | 1728 | flags); |
1723 | if (!buf) | 1729 | if (!buf) |
1724 | goto fail_sp5; | 1730 | goto fail_sp4; |
1725 | 1731 | ||
1726 | xhci->scratchpad->sp_array[i] = dma; | 1732 | xhci->scratchpad->sp_array[i] = dma; |
1727 | xhci->scratchpad->sp_buffers[i] = buf; | 1733 | xhci->scratchpad->sp_buffers[i] = buf; |
1728 | xhci->scratchpad->sp_dma_buffers[i] = dma; | ||
1729 | } | 1734 | } |
1730 | 1735 | ||
1731 | return 0; | 1736 | return 0; |
1732 | 1737 | ||
1733 | fail_sp5: | 1738 | fail_sp4: |
1734 | for (i = i - 1; i >= 0; i--) { | 1739 | for (i = i - 1; i >= 0; i--) { |
1735 | dma_free_coherent(dev, xhci->page_size, | 1740 | dma_free_coherent(dev, xhci->page_size, |
1736 | xhci->scratchpad->sp_buffers[i], | 1741 | xhci->scratchpad->sp_buffers[i], |
1737 | xhci->scratchpad->sp_dma_buffers[i]); | 1742 | xhci->scratchpad->sp_array[i]); |
1738 | } | 1743 | } |
1739 | kfree(xhci->scratchpad->sp_dma_buffers); | ||
1740 | 1744 | ||
1741 | fail_sp4: | ||
1742 | kfree(xhci->scratchpad->sp_buffers); | 1745 | kfree(xhci->scratchpad->sp_buffers); |
1743 | 1746 | ||
1744 | fail_sp3: | 1747 | fail_sp3: |
@@ -1758,7 +1761,7 @@ static void scratchpad_free(struct xhci_hcd *xhci) | |||
1758 | { | 1761 | { |
1759 | int num_sp; | 1762 | int num_sp; |
1760 | int i; | 1763 | int i; |
1761 | struct device *dev = xhci_to_hcd(xhci)->self.controller; | 1764 | struct device *dev = xhci_to_hcd(xhci)->self.sysdev; |
1762 | 1765 | ||
1763 | if (!xhci->scratchpad) | 1766 | if (!xhci->scratchpad) |
1764 | return; | 1767 | return; |
@@ -1768,9 +1771,8 @@ static void scratchpad_free(struct xhci_hcd *xhci) | |||
1768 | for (i = 0; i < num_sp; i++) { | 1771 | for (i = 0; i < num_sp; i++) { |
1769 | dma_free_coherent(dev, xhci->page_size, | 1772 | dma_free_coherent(dev, xhci->page_size, |
1770 | xhci->scratchpad->sp_buffers[i], | 1773 | xhci->scratchpad->sp_buffers[i], |
1771 | xhci->scratchpad->sp_dma_buffers[i]); | 1774 | xhci->scratchpad->sp_array[i]); |
1772 | } | 1775 | } |
1773 | kfree(xhci->scratchpad->sp_dma_buffers); | ||
1774 | kfree(xhci->scratchpad->sp_buffers); | 1776 | kfree(xhci->scratchpad->sp_buffers); |
1775 | dma_free_coherent(dev, num_sp * sizeof(u64), | 1777 | dma_free_coherent(dev, num_sp * sizeof(u64), |
1776 | xhci->scratchpad->sp_array, | 1778 | xhci->scratchpad->sp_array, |
@@ -1831,7 +1833,7 @@ void xhci_free_command(struct xhci_hcd *xhci, | |||
1831 | 1833 | ||
1832 | void xhci_mem_cleanup(struct xhci_hcd *xhci) | 1834 | void xhci_mem_cleanup(struct xhci_hcd *xhci) |
1833 | { | 1835 | { |
1834 | struct device *dev = xhci_to_hcd(xhci)->self.controller; | 1836 | struct device *dev = xhci_to_hcd(xhci)->self.sysdev; |
1835 | int size; | 1837 | int size; |
1836 | int i, j, num_ports; | 1838 | int i, j, num_ports; |
1837 | 1839 | ||
@@ -2373,7 +2375,7 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) | |||
2373 | int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) | 2375 | int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) |
2374 | { | 2376 | { |
2375 | dma_addr_t dma; | 2377 | dma_addr_t dma; |
2376 | struct device *dev = xhci_to_hcd(xhci)->self.controller; | 2378 | struct device *dev = xhci_to_hcd(xhci)->self.sysdev; |
2377 | unsigned int val, val2; | 2379 | unsigned int val, val2; |
2378 | u64 val_64; | 2380 | u64 val_64; |
2379 | struct xhci_segment *seg; | 2381 | struct xhci_segment *seg; |
@@ -2419,7 +2421,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) | |||
2419 | writel(val, &xhci->op_regs->config_reg); | 2421 | writel(val, &xhci->op_regs->config_reg); |
2420 | 2422 | ||
2421 | /* | 2423 | /* |
2422 | * Section 5.4.8 - doorbell array must be | 2424 | * xHCI section 5.4.6 - doorbell array must be |
2423 | * "physically contiguous and 64-byte (cache line) aligned". | 2425 | * "physically contiguous and 64-byte (cache line) aligned". |
2424 | */ | 2426 | */ |
2425 | xhci->dcbaa = dma_alloc_coherent(dev, sizeof(*xhci->dcbaa), &dma, | 2427 | xhci->dcbaa = dma_alloc_coherent(dev, sizeof(*xhci->dcbaa), &dma, |
@@ -2480,7 +2482,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) | |||
2480 | (xhci->cmd_ring->first_seg->dma & (u64) ~CMD_RING_RSVD_BITS) | | 2482 | (xhci->cmd_ring->first_seg->dma & (u64) ~CMD_RING_RSVD_BITS) | |
2481 | xhci->cmd_ring->cycle_state; | 2483 | xhci->cmd_ring->cycle_state; |
2482 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, | 2484 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, |
2483 | "// Setting command ring address to 0x%x", val); | 2485 | "// Setting command ring address to 0x%016llx", val_64); |
2484 | xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring); | 2486 | xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring); |
2485 | xhci_dbg_cmd_ptrs(xhci); | 2487 | xhci_dbg_cmd_ptrs(xhci); |
2486 | 2488 | ||
@@ -2601,7 +2603,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) | |||
2601 | return 0; | 2603 | return 0; |
2602 | 2604 | ||
2603 | fail: | 2605 | fail: |
2604 | xhci_warn(xhci, "Couldn't initialize memory\n"); | ||
2605 | xhci_halt(xhci); | 2606 | xhci_halt(xhci); |
2606 | xhci_reset(xhci); | 2607 | xhci_reset(xhci); |
2607 | xhci_mem_cleanup(xhci); | 2608 | xhci_mem_cleanup(xhci); |
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index fc99f51d12e1..7b86508ac8cf 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c | |||
@@ -199,6 +199,9 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) | |||
199 | pdev->device == 0x1042) | 199 | pdev->device == 0x1042) |
200 | xhci->quirks |= XHCI_BROKEN_STREAMS; | 200 | xhci->quirks |= XHCI_BROKEN_STREAMS; |
201 | 201 | ||
202 | if (pdev->vendor == PCI_VENDOR_ID_TI && pdev->device == 0x8241) | ||
203 | xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_7; | ||
204 | |||
202 | if (xhci->quirks & XHCI_RESET_ON_RESUME) | 205 | if (xhci->quirks & XHCI_RESET_ON_RESUME) |
203 | xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, | 206 | xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, |
204 | "QUIRK: Resetting on resume"); | 207 | "QUIRK: Resetting on resume"); |
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 6ed468fa7d5e..7c2a9e7c8e0f 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/clk.h> | 14 | #include <linux/clk.h> |
15 | #include <linux/dma-mapping.h> | 15 | #include <linux/dma-mapping.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/pci.h> | ||
17 | #include <linux/of.h> | 18 | #include <linux/of.h> |
18 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
19 | #include <linux/usb/phy.h> | 20 | #include <linux/usb/phy.h> |
@@ -54,6 +55,16 @@ static int xhci_priv_init_quirk(struct usb_hcd *hcd) | |||
54 | return priv->init_quirk(hcd); | 55 | return priv->init_quirk(hcd); |
55 | } | 56 | } |
56 | 57 | ||
58 | static int xhci_priv_resume_quirk(struct usb_hcd *hcd) | ||
59 | { | ||
60 | struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); | ||
61 | |||
62 | if (!priv->resume_quirk) | ||
63 | return 0; | ||
64 | |||
65 | return priv->resume_quirk(hcd); | ||
66 | } | ||
67 | |||
57 | static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci) | 68 | static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci) |
58 | { | 69 | { |
59 | /* | 70 | /* |
@@ -92,18 +103,21 @@ static const struct xhci_plat_priv xhci_plat_renesas_rcar_gen2 = { | |||
92 | .firmware_name = XHCI_RCAR_FIRMWARE_NAME_V1, | 103 | .firmware_name = XHCI_RCAR_FIRMWARE_NAME_V1, |
93 | .init_quirk = xhci_rcar_init_quirk, | 104 | .init_quirk = xhci_rcar_init_quirk, |
94 | .plat_start = xhci_rcar_start, | 105 | .plat_start = xhci_rcar_start, |
106 | .resume_quirk = xhci_rcar_resume_quirk, | ||
95 | }; | 107 | }; |
96 | 108 | ||
97 | static const struct xhci_plat_priv xhci_plat_renesas_rcar_gen3 = { | 109 | static const struct xhci_plat_priv xhci_plat_renesas_rcar_gen3 = { |
98 | .firmware_name = XHCI_RCAR_FIRMWARE_NAME_V2, | 110 | .firmware_name = XHCI_RCAR_FIRMWARE_NAME_V2, |
99 | .init_quirk = xhci_rcar_init_quirk, | 111 | .init_quirk = xhci_rcar_init_quirk, |
100 | .plat_start = xhci_rcar_start, | 112 | .plat_start = xhci_rcar_start, |
113 | .resume_quirk = xhci_rcar_resume_quirk, | ||
101 | }; | 114 | }; |
102 | 115 | ||
103 | static const struct xhci_plat_priv xhci_plat_renesas_rcar_r8a7796 = { | 116 | static const struct xhci_plat_priv xhci_plat_renesas_rcar_r8a7796 = { |
104 | .firmware_name = XHCI_RCAR_FIRMWARE_NAME_V3, | 117 | .firmware_name = XHCI_RCAR_FIRMWARE_NAME_V3, |
105 | .init_quirk = xhci_rcar_init_quirk, | 118 | .init_quirk = xhci_rcar_init_quirk, |
106 | .plat_start = xhci_rcar_start, | 119 | .plat_start = xhci_rcar_start, |
120 | .resume_quirk = xhci_rcar_resume_quirk, | ||
107 | }; | 121 | }; |
108 | 122 | ||
109 | static const struct of_device_id usb_xhci_of_match[] = { | 123 | static const struct of_device_id usb_xhci_of_match[] = { |
@@ -148,6 +162,7 @@ static int xhci_plat_probe(struct platform_device *pdev) | |||
148 | { | 162 | { |
149 | const struct of_device_id *match; | 163 | const struct of_device_id *match; |
150 | const struct hc_driver *driver; | 164 | const struct hc_driver *driver; |
165 | struct device *sysdev; | ||
151 | struct xhci_hcd *xhci; | 166 | struct xhci_hcd *xhci; |
152 | struct resource *res; | 167 | struct resource *res; |
153 | struct usb_hcd *hcd; | 168 | struct usb_hcd *hcd; |
@@ -164,24 +179,47 @@ static int xhci_plat_probe(struct platform_device *pdev) | |||
164 | if (irq < 0) | 179 | if (irq < 0) |
165 | return -ENODEV; | 180 | return -ENODEV; |
166 | 181 | ||
182 | /* | ||
183 | * sysdev must point to a device that is known to the system firmware | ||
184 | * or PCI hardware. We handle these three cases here: | ||
185 | * 1. xhci_plat comes from firmware | ||
186 | * 2. xhci_plat is child of a device from firmware (dwc3-plat) | ||
187 | * 3. xhci_plat is grandchild of a pci device (dwc3-pci) | ||
188 | */ | ||
189 | sysdev = &pdev->dev; | ||
190 | if (sysdev->parent && !sysdev->of_node && sysdev->parent->of_node) | ||
191 | sysdev = sysdev->parent; | ||
192 | #ifdef CONFIG_PCI | ||
193 | else if (sysdev->parent && sysdev->parent->parent && | ||
194 | sysdev->parent->parent->bus == &pci_bus_type) | ||
195 | sysdev = sysdev->parent->parent; | ||
196 | #endif | ||
197 | |||
167 | /* Try to set 64-bit DMA first */ | 198 | /* Try to set 64-bit DMA first */ |
168 | if (!pdev->dev.dma_mask) | 199 | if (WARN_ON(!sysdev->dma_mask)) |
169 | /* Platform did not initialize dma_mask */ | 200 | /* Platform did not initialize dma_mask */ |
170 | ret = dma_coerce_mask_and_coherent(&pdev->dev, | 201 | ret = dma_coerce_mask_and_coherent(sysdev, |
171 | DMA_BIT_MASK(64)); | 202 | DMA_BIT_MASK(64)); |
172 | else | 203 | else |
173 | ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); | 204 | ret = dma_set_mask_and_coherent(sysdev, DMA_BIT_MASK(64)); |
174 | 205 | ||
175 | /* If seting 64-bit DMA mask fails, fall back to 32-bit DMA mask */ | 206 | /* If seting 64-bit DMA mask fails, fall back to 32-bit DMA mask */ |
176 | if (ret) { | 207 | if (ret) { |
177 | ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); | 208 | ret = dma_set_mask_and_coherent(sysdev, DMA_BIT_MASK(32)); |
178 | if (ret) | 209 | if (ret) |
179 | return ret; | 210 | return ret; |
180 | } | 211 | } |
181 | 212 | ||
182 | hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); | 213 | pm_runtime_set_active(&pdev->dev); |
183 | if (!hcd) | 214 | pm_runtime_enable(&pdev->dev); |
184 | return -ENOMEM; | 215 | pm_runtime_get_noresume(&pdev->dev); |
216 | |||
217 | hcd = __usb_create_hcd(driver, sysdev, &pdev->dev, | ||
218 | dev_name(&pdev->dev), NULL); | ||
219 | if (!hcd) { | ||
220 | ret = -ENOMEM; | ||
221 | goto disable_runtime; | ||
222 | } | ||
185 | 223 | ||
186 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 224 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
187 | hcd->regs = devm_ioremap_resource(&pdev->dev, res); | 225 | hcd->regs = devm_ioremap_resource(&pdev->dev, res); |
@@ -222,20 +260,20 @@ static int xhci_plat_probe(struct platform_device *pdev) | |||
222 | 260 | ||
223 | xhci->clk = clk; | 261 | xhci->clk = clk; |
224 | xhci->main_hcd = hcd; | 262 | xhci->main_hcd = hcd; |
225 | xhci->shared_hcd = usb_create_shared_hcd(driver, &pdev->dev, | 263 | xhci->shared_hcd = __usb_create_hcd(driver, sysdev, &pdev->dev, |
226 | dev_name(&pdev->dev), hcd); | 264 | dev_name(&pdev->dev), hcd); |
227 | if (!xhci->shared_hcd) { | 265 | if (!xhci->shared_hcd) { |
228 | ret = -ENOMEM; | 266 | ret = -ENOMEM; |
229 | goto disable_clk; | 267 | goto disable_clk; |
230 | } | 268 | } |
231 | 269 | ||
232 | if (device_property_read_bool(&pdev->dev, "usb3-lpm-capable")) | 270 | if (device_property_read_bool(sysdev, "usb3-lpm-capable")) |
233 | xhci->quirks |= XHCI_LPM_SUPPORT; | 271 | xhci->quirks |= XHCI_LPM_SUPPORT; |
234 | 272 | ||
235 | if (device_property_read_bool(&pdev->dev, "quirk-broken-port-ped")) | 273 | if (device_property_read_bool(&pdev->dev, "quirk-broken-port-ped")) |
236 | xhci->quirks |= XHCI_BROKEN_PORT_PED; | 274 | xhci->quirks |= XHCI_BROKEN_PORT_PED; |
237 | 275 | ||
238 | hcd->usb_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0); | 276 | hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev, "usb-phy", 0); |
239 | if (IS_ERR(hcd->usb_phy)) { | 277 | if (IS_ERR(hcd->usb_phy)) { |
240 | ret = PTR_ERR(hcd->usb_phy); | 278 | ret = PTR_ERR(hcd->usb_phy); |
241 | if (ret == -EPROBE_DEFER) | 279 | if (ret == -EPROBE_DEFER) |
@@ -258,6 +296,15 @@ static int xhci_plat_probe(struct platform_device *pdev) | |||
258 | if (ret) | 296 | if (ret) |
259 | goto dealloc_usb2_hcd; | 297 | goto dealloc_usb2_hcd; |
260 | 298 | ||
299 | device_enable_async_suspend(&pdev->dev); | ||
300 | pm_runtime_put_noidle(&pdev->dev); | ||
301 | |||
302 | /* | ||
303 | * Prevent runtime pm from being on as default, users should enable | ||
304 | * runtime pm using power/control in sysfs. | ||
305 | */ | ||
306 | pm_runtime_forbid(&pdev->dev); | ||
307 | |||
261 | return 0; | 308 | return 0; |
262 | 309 | ||
263 | 310 | ||
@@ -277,6 +324,10 @@ disable_clk: | |||
277 | put_hcd: | 324 | put_hcd: |
278 | usb_put_hcd(hcd); | 325 | usb_put_hcd(hcd); |
279 | 326 | ||
327 | disable_runtime: | ||
328 | pm_runtime_put_noidle(&pdev->dev); | ||
329 | pm_runtime_disable(&pdev->dev); | ||
330 | |||
280 | return ret; | 331 | return ret; |
281 | } | 332 | } |
282 | 333 | ||
@@ -298,14 +349,17 @@ static int xhci_plat_remove(struct platform_device *dev) | |||
298 | clk_disable_unprepare(clk); | 349 | clk_disable_unprepare(clk); |
299 | usb_put_hcd(hcd); | 350 | usb_put_hcd(hcd); |
300 | 351 | ||
352 | pm_runtime_set_suspended(&dev->dev); | ||
353 | pm_runtime_disable(&dev->dev); | ||
354 | |||
301 | return 0; | 355 | return 0; |
302 | } | 356 | } |
303 | 357 | ||
304 | #ifdef CONFIG_PM_SLEEP | 358 | static int __maybe_unused xhci_plat_suspend(struct device *dev) |
305 | static int xhci_plat_suspend(struct device *dev) | ||
306 | { | 359 | { |
307 | struct usb_hcd *hcd = dev_get_drvdata(dev); | 360 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
308 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 361 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
362 | int ret; | ||
309 | 363 | ||
310 | /* | 364 | /* |
311 | * xhci_suspend() needs `do_wakeup` to know whether host is allowed | 365 | * xhci_suspend() needs `do_wakeup` to know whether host is allowed |
@@ -315,24 +369,53 @@ static int xhci_plat_suspend(struct device *dev) | |||
315 | * reconsider this when xhci_plat_suspend enlarges its scope, e.g., | 369 | * reconsider this when xhci_plat_suspend enlarges its scope, e.g., |
316 | * also applies to runtime suspend. | 370 | * also applies to runtime suspend. |
317 | */ | 371 | */ |
318 | return xhci_suspend(xhci, device_may_wakeup(dev)); | 372 | ret = xhci_suspend(xhci, device_may_wakeup(dev)); |
373 | |||
374 | if (!device_may_wakeup(dev) && !IS_ERR(xhci->clk)) | ||
375 | clk_disable_unprepare(xhci->clk); | ||
376 | |||
377 | return ret; | ||
319 | } | 378 | } |
320 | 379 | ||
321 | static int xhci_plat_resume(struct device *dev) | 380 | static int __maybe_unused xhci_plat_resume(struct device *dev) |
322 | { | 381 | { |
323 | struct usb_hcd *hcd = dev_get_drvdata(dev); | 382 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
324 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 383 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
384 | int ret; | ||
385 | |||
386 | if (!device_may_wakeup(dev) && !IS_ERR(xhci->clk)) | ||
387 | clk_prepare_enable(xhci->clk); | ||
388 | |||
389 | ret = xhci_priv_resume_quirk(hcd); | ||
390 | if (ret) | ||
391 | return ret; | ||
392 | |||
393 | return xhci_resume(xhci, 0); | ||
394 | } | ||
395 | |||
396 | static int __maybe_unused xhci_plat_runtime_suspend(struct device *dev) | ||
397 | { | ||
398 | struct usb_hcd *hcd = dev_get_drvdata(dev); | ||
399 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | ||
400 | |||
401 | return xhci_suspend(xhci, true); | ||
402 | } | ||
403 | |||
404 | static int __maybe_unused xhci_plat_runtime_resume(struct device *dev) | ||
405 | { | ||
406 | struct usb_hcd *hcd = dev_get_drvdata(dev); | ||
407 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | ||
325 | 408 | ||
326 | return xhci_resume(xhci, 0); | 409 | return xhci_resume(xhci, 0); |
327 | } | 410 | } |
328 | 411 | ||
329 | static const struct dev_pm_ops xhci_plat_pm_ops = { | 412 | static const struct dev_pm_ops xhci_plat_pm_ops = { |
330 | SET_SYSTEM_SLEEP_PM_OPS(xhci_plat_suspend, xhci_plat_resume) | 413 | SET_SYSTEM_SLEEP_PM_OPS(xhci_plat_suspend, xhci_plat_resume) |
414 | |||
415 | SET_RUNTIME_PM_OPS(xhci_plat_runtime_suspend, | ||
416 | xhci_plat_runtime_resume, | ||
417 | NULL) | ||
331 | }; | 418 | }; |
332 | #define DEV_PM_OPS (&xhci_plat_pm_ops) | ||
333 | #else | ||
334 | #define DEV_PM_OPS NULL | ||
335 | #endif /* CONFIG_PM */ | ||
336 | 419 | ||
337 | static const struct acpi_device_id usb_xhci_acpi_match[] = { | 420 | static const struct acpi_device_id usb_xhci_acpi_match[] = { |
338 | /* XHCI-compliant USB Controller */ | 421 | /* XHCI-compliant USB Controller */ |
@@ -347,7 +430,7 @@ static struct platform_driver usb_xhci_driver = { | |||
347 | .shutdown = usb_hcd_platform_shutdown, | 430 | .shutdown = usb_hcd_platform_shutdown, |
348 | .driver = { | 431 | .driver = { |
349 | .name = "xhci-hcd", | 432 | .name = "xhci-hcd", |
350 | .pm = DEV_PM_OPS, | 433 | .pm = &xhci_plat_pm_ops, |
351 | .of_match_table = of_match_ptr(usb_xhci_of_match), | 434 | .of_match_table = of_match_ptr(usb_xhci_of_match), |
352 | .acpi_match_table = ACPI_PTR(usb_xhci_acpi_match), | 435 | .acpi_match_table = ACPI_PTR(usb_xhci_acpi_match), |
353 | }, | 436 | }, |
diff --git a/drivers/usb/host/xhci-plat.h b/drivers/usb/host/xhci-plat.h index 9af0cb48053f..29b227895b07 100644 --- a/drivers/usb/host/xhci-plat.h +++ b/drivers/usb/host/xhci-plat.h | |||
@@ -17,6 +17,7 @@ struct xhci_plat_priv { | |||
17 | const char *firmware_name; | 17 | const char *firmware_name; |
18 | void (*plat_start)(struct usb_hcd *); | 18 | void (*plat_start)(struct usb_hcd *); |
19 | int (*init_quirk)(struct usb_hcd *); | 19 | int (*init_quirk)(struct usb_hcd *); |
20 | int (*resume_quirk)(struct usb_hcd *); | ||
20 | }; | 21 | }; |
21 | 22 | ||
22 | #define hcd_to_xhci_priv(h) ((struct xhci_plat_priv *)hcd_to_xhci(h)->priv) | 23 | #define hcd_to_xhci_priv(h) ((struct xhci_plat_priv *)hcd_to_xhci(h)->priv) |
diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c index d28df386e780..07278228214b 100644 --- a/drivers/usb/host/xhci-rcar.c +++ b/drivers/usb/host/xhci-rcar.c | |||
@@ -198,3 +198,14 @@ int xhci_rcar_init_quirk(struct usb_hcd *hcd) | |||
198 | 198 | ||
199 | return xhci_rcar_download_firmware(hcd); | 199 | return xhci_rcar_download_firmware(hcd); |
200 | } | 200 | } |
201 | |||
202 | int xhci_rcar_resume_quirk(struct usb_hcd *hcd) | ||
203 | { | ||
204 | int ret; | ||
205 | |||
206 | ret = xhci_rcar_download_firmware(hcd); | ||
207 | if (!ret) | ||
208 | xhci_rcar_start(hcd); | ||
209 | |||
210 | return ret; | ||
211 | } | ||
diff --git a/drivers/usb/host/xhci-rcar.h b/drivers/usb/host/xhci-rcar.h index d2ffe20401cf..d247951147a1 100644 --- a/drivers/usb/host/xhci-rcar.h +++ b/drivers/usb/host/xhci-rcar.h | |||
@@ -18,6 +18,7 @@ | |||
18 | #if IS_ENABLED(CONFIG_USB_XHCI_RCAR) | 18 | #if IS_ENABLED(CONFIG_USB_XHCI_RCAR) |
19 | void xhci_rcar_start(struct usb_hcd *hcd); | 19 | void xhci_rcar_start(struct usb_hcd *hcd); |
20 | int xhci_rcar_init_quirk(struct usb_hcd *hcd); | 20 | int xhci_rcar_init_quirk(struct usb_hcd *hcd); |
21 | int xhci_rcar_resume_quirk(struct usb_hcd *hcd); | ||
21 | #else | 22 | #else |
22 | static inline void xhci_rcar_start(struct usb_hcd *hcd) | 23 | static inline void xhci_rcar_start(struct usb_hcd *hcd) |
23 | { | 24 | { |
@@ -27,5 +28,10 @@ static inline int xhci_rcar_init_quirk(struct usb_hcd *hcd) | |||
27 | { | 28 | { |
28 | return 0; | 29 | return 0; |
29 | } | 30 | } |
31 | |||
32 | static inline int xhci_rcar_resume_quirk(struct usb_hcd *hcd) | ||
33 | { | ||
34 | return 0; | ||
35 | } | ||
30 | #endif | 36 | #endif |
31 | #endif /* _XHCI_RCAR_H */ | 37 | #endif /* _XHCI_RCAR_H */ |
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index a3309aa02993..74bf5c60a260 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
@@ -167,8 +167,6 @@ static void next_trb(struct xhci_hcd *xhci, | |||
167 | */ | 167 | */ |
168 | static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring) | 168 | static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring) |
169 | { | 169 | { |
170 | ring->deq_updates++; | ||
171 | |||
172 | /* event ring doesn't have link trbs, check for last trb */ | 170 | /* event ring doesn't have link trbs, check for last trb */ |
173 | if (ring->type == TYPE_EVENT) { | 171 | if (ring->type == TYPE_EVENT) { |
174 | if (!last_trb_on_seg(ring->deq_seg, ring->dequeue)) { | 172 | if (!last_trb_on_seg(ring->deq_seg, ring->dequeue)) { |
@@ -191,6 +189,9 @@ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring) | |||
191 | ring->deq_seg = ring->deq_seg->next; | 189 | ring->deq_seg = ring->deq_seg->next; |
192 | ring->dequeue = ring->deq_seg->trbs; | 190 | ring->dequeue = ring->deq_seg->trbs; |
193 | } | 191 | } |
192 | |||
193 | trace_xhci_inc_deq(ring); | ||
194 | |||
194 | return; | 195 | return; |
195 | } | 196 | } |
196 | 197 | ||
@@ -223,7 +224,6 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, | |||
223 | ring->num_trbs_free--; | 224 | ring->num_trbs_free--; |
224 | next = ++(ring->enqueue); | 225 | next = ++(ring->enqueue); |
225 | 226 | ||
226 | ring->enq_updates++; | ||
227 | /* Update the dequeue pointer further if that was a link TRB */ | 227 | /* Update the dequeue pointer further if that was a link TRB */ |
228 | while (trb_is_link(next)) { | 228 | while (trb_is_link(next)) { |
229 | 229 | ||
@@ -259,6 +259,8 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, | |||
259 | ring->enqueue = ring->enq_seg->trbs; | 259 | ring->enqueue = ring->enq_seg->trbs; |
260 | next = ring->enqueue; | 260 | next = ring->enqueue; |
261 | } | 261 | } |
262 | |||
263 | trace_xhci_inc_enq(ring); | ||
262 | } | 264 | } |
263 | 265 | ||
264 | /* | 266 | /* |
@@ -359,21 +361,19 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags) | |||
359 | xhci_write_64(xhci, temp_64 | CMD_RING_ABORT, | 361 | xhci_write_64(xhci, temp_64 | CMD_RING_ABORT, |
360 | &xhci->op_regs->cmd_ring); | 362 | &xhci->op_regs->cmd_ring); |
361 | 363 | ||
362 | /* Section 4.6.1.2 of xHCI 1.0 spec says software should | 364 | /* Section 4.6.1.2 of xHCI 1.0 spec says software should also time the |
363 | * time the completion od all xHCI commands, including | 365 | * completion of the Command Abort operation. If CRR is not negated in 5 |
364 | * the Command Abort operation. If software doesn't see | 366 | * seconds then driver handles it as if host died (-ENODEV). |
365 | * CRR negated in a timely manner (e.g. longer than 5 | 367 | * In the future we should distinguish between -ENODEV and -ETIMEDOUT |
366 | * seconds), then it should assume that the there are | 368 | * and try to recover a -ETIMEDOUT with a host controller reset. |
367 | * larger problems with the xHC and assert HCRST. | ||
368 | */ | 369 | */ |
369 | ret = xhci_handshake(&xhci->op_regs->cmd_ring, | 370 | ret = xhci_handshake(&xhci->op_regs->cmd_ring, |
370 | CMD_RING_RUNNING, 0, 5 * 1000 * 1000); | 371 | CMD_RING_RUNNING, 0, 5 * 1000 * 1000); |
371 | if (ret < 0) { | 372 | if (ret < 0) { |
372 | xhci_err(xhci, | 373 | xhci_err(xhci, "Abort failed to stop command ring: %d\n", ret); |
373 | "Stop command ring failed, maybe the host is dead\n"); | ||
374 | xhci->xhc_state |= XHCI_STATE_DYING; | ||
375 | xhci_halt(xhci); | 374 | xhci_halt(xhci); |
376 | return -ESHUTDOWN; | 375 | xhci_hc_died(xhci); |
376 | return ret; | ||
377 | } | 377 | } |
378 | /* | 378 | /* |
379 | * Writing the CMD_RING_ABORT bit should cause a cmd completion event, | 379 | * Writing the CMD_RING_ABORT bit should cause a cmd completion event, |
@@ -689,6 +689,8 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id, | |||
689 | struct xhci_virt_ep *ep; | 689 | struct xhci_virt_ep *ep; |
690 | struct xhci_td *cur_td = NULL; | 690 | struct xhci_td *cur_td = NULL; |
691 | struct xhci_td *last_unlinked_td; | 691 | struct xhci_td *last_unlinked_td; |
692 | struct xhci_ep_ctx *ep_ctx; | ||
693 | struct xhci_virt_device *vdev; | ||
692 | 694 | ||
693 | struct xhci_dequeue_state deq_state; | 695 | struct xhci_dequeue_state deq_state; |
694 | 696 | ||
@@ -702,6 +704,11 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id, | |||
702 | 704 | ||
703 | memset(&deq_state, 0, sizeof(deq_state)); | 705 | memset(&deq_state, 0, sizeof(deq_state)); |
704 | ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3])); | 706 | ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3])); |
707 | |||
708 | vdev = xhci->devs[slot_id]; | ||
709 | ep_ctx = xhci_get_ep_ctx(xhci, vdev->out_ctx, ep_index); | ||
710 | trace_xhci_handle_cmd_stop_ep(ep_ctx); | ||
711 | |||
705 | ep = &xhci->devs[slot_id]->eps[ep_index]; | 712 | ep = &xhci->devs[slot_id]->eps[ep_index]; |
706 | last_unlinked_td = list_last_entry(&ep->cancelled_td_list, | 713 | last_unlinked_td = list_last_entry(&ep->cancelled_td_list, |
707 | struct xhci_td, cancelled_td_list); | 714 | struct xhci_td, cancelled_td_list); |
@@ -866,6 +873,40 @@ static void xhci_kill_endpoint_urbs(struct xhci_hcd *xhci, | |||
866 | } | 873 | } |
867 | } | 874 | } |
868 | 875 | ||
876 | /* | ||
877 | * host controller died, register read returns 0xffffffff | ||
878 | * Complete pending commands, mark them ABORTED. | ||
879 | * URBs need to be given back as usb core might be waiting with device locks | ||
880 | * held for the URBs to finish during device disconnect, blocking host remove. | ||
881 | * | ||
882 | * Call with xhci->lock held. | ||
883 | * lock is relased and re-acquired while giving back urb. | ||
884 | */ | ||
885 | void xhci_hc_died(struct xhci_hcd *xhci) | ||
886 | { | ||
887 | int i, j; | ||
888 | |||
889 | if (xhci->xhc_state & XHCI_STATE_DYING) | ||
890 | return; | ||
891 | |||
892 | xhci_err(xhci, "xHCI host controller not responding, assume dead\n"); | ||
893 | xhci->xhc_state |= XHCI_STATE_DYING; | ||
894 | |||
895 | xhci_cleanup_command_queue(xhci); | ||
896 | |||
897 | /* return any pending urbs, remove may be waiting for them */ | ||
898 | for (i = 0; i <= HCS_MAX_SLOTS(xhci->hcs_params1); i++) { | ||
899 | if (!xhci->devs[i]) | ||
900 | continue; | ||
901 | for (j = 0; j < 31; j++) | ||
902 | xhci_kill_endpoint_urbs(xhci, i, j); | ||
903 | } | ||
904 | |||
905 | /* inform usb core hc died if PCI remove isn't already handling it */ | ||
906 | if (!(xhci->xhc_state & XHCI_STATE_REMOVING)) | ||
907 | usb_hc_died(xhci_to_hcd(xhci)); | ||
908 | } | ||
909 | |||
869 | /* Watchdog timer function for when a stop endpoint command fails to complete. | 910 | /* Watchdog timer function for when a stop endpoint command fails to complete. |
870 | * In this case, we assume the host controller is broken or dying or dead. The | 911 | * In this case, we assume the host controller is broken or dying or dead. The |
871 | * host may still be completing some other events, so we have to be careful to | 912 | * host may still be completing some other events, so we have to be careful to |
@@ -887,7 +928,6 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg) | |||
887 | { | 928 | { |
888 | struct xhci_hcd *xhci; | 929 | struct xhci_hcd *xhci; |
889 | struct xhci_virt_ep *ep; | 930 | struct xhci_virt_ep *ep; |
890 | int ret, i, j; | ||
891 | unsigned long flags; | 931 | unsigned long flags; |
892 | 932 | ||
893 | ep = (struct xhci_virt_ep *) arg; | 933 | ep = (struct xhci_virt_ep *) arg; |
@@ -904,52 +944,22 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg) | |||
904 | } | 944 | } |
905 | 945 | ||
906 | xhci_warn(xhci, "xHCI host not responding to stop endpoint command.\n"); | 946 | xhci_warn(xhci, "xHCI host not responding to stop endpoint command.\n"); |
907 | xhci_warn(xhci, "Assuming host is dying, halting host.\n"); | ||
908 | /* Oops, HC is dead or dying or at least not responding to the stop | ||
909 | * endpoint command. | ||
910 | */ | ||
911 | |||
912 | xhci->xhc_state |= XHCI_STATE_DYING; | ||
913 | ep->ep_state &= ~EP_STOP_CMD_PENDING; | 947 | ep->ep_state &= ~EP_STOP_CMD_PENDING; |
914 | 948 | ||
915 | /* Disable interrupts from the host controller and start halting it */ | 949 | xhci_halt(xhci); |
916 | xhci_quiesce(xhci); | ||
917 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
918 | 950 | ||
919 | ret = xhci_halt(xhci); | 951 | /* |
952 | * handle a stop endpoint cmd timeout as if host died (-ENODEV). | ||
953 | * In the future we could distinguish between -ENODEV and -ETIMEDOUT | ||
954 | * and try to recover a -ETIMEDOUT with a host controller reset | ||
955 | */ | ||
956 | xhci_hc_died(xhci); | ||
920 | 957 | ||
921 | spin_lock_irqsave(&xhci->lock, flags); | ||
922 | if (ret < 0) { | ||
923 | /* This is bad; the host is not responding to commands and it's | ||
924 | * not allowing itself to be halted. At least interrupts are | ||
925 | * disabled. If we call usb_hc_died(), it will attempt to | ||
926 | * disconnect all device drivers under this host. Those | ||
927 | * disconnect() methods will wait for all URBs to be unlinked, | ||
928 | * so we must complete them. | ||
929 | */ | ||
930 | xhci_warn(xhci, "Non-responsive xHCI host is not halting.\n"); | ||
931 | xhci_warn(xhci, "Completing active URBs anyway.\n"); | ||
932 | /* We could turn all TDs on the rings to no-ops. This won't | ||
933 | * help if the host has cached part of the ring, and is slow if | ||
934 | * we want to preserve the cycle bit. Skip it and hope the host | ||
935 | * doesn't touch the memory. | ||
936 | */ | ||
937 | } | ||
938 | for (i = 0; i < MAX_HC_SLOTS; i++) { | ||
939 | if (!xhci->devs[i]) | ||
940 | continue; | ||
941 | for (j = 0; j < 31; j++) | ||
942 | xhci_kill_endpoint_urbs(xhci, i, j); | ||
943 | } | ||
944 | spin_unlock_irqrestore(&xhci->lock, flags); | 958 | spin_unlock_irqrestore(&xhci->lock, flags); |
945 | xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, | 959 | xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, |
946 | "Calling usb_hc_died()"); | ||
947 | usb_hc_died(xhci_to_hcd(xhci)); | ||
948 | xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, | ||
949 | "xHCI host controller is dead."); | 960 | "xHCI host controller is dead."); |
950 | } | 961 | } |
951 | 962 | ||
952 | |||
953 | static void update_ring_for_set_deq_completion(struct xhci_hcd *xhci, | 963 | static void update_ring_for_set_deq_completion(struct xhci_hcd *xhci, |
954 | struct xhci_virt_device *dev, | 964 | struct xhci_virt_device *dev, |
955 | struct xhci_ring *ep_ring, | 965 | struct xhci_ring *ep_ring, |
@@ -1029,6 +1039,8 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id, | |||
1029 | 1039 | ||
1030 | ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index); | 1040 | ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index); |
1031 | slot_ctx = xhci_get_slot_ctx(xhci, dev->out_ctx); | 1041 | slot_ctx = xhci_get_slot_ctx(xhci, dev->out_ctx); |
1042 | trace_xhci_handle_cmd_set_deq(slot_ctx); | ||
1043 | trace_xhci_handle_cmd_set_deq_ep(ep_ctx); | ||
1032 | 1044 | ||
1033 | if (cmd_comp_code != COMP_SUCCESS) { | 1045 | if (cmd_comp_code != COMP_SUCCESS) { |
1034 | unsigned int ep_state; | 1046 | unsigned int ep_state; |
@@ -1099,9 +1111,15 @@ cleanup: | |||
1099 | static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id, | 1111 | static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id, |
1100 | union xhci_trb *trb, u32 cmd_comp_code) | 1112 | union xhci_trb *trb, u32 cmd_comp_code) |
1101 | { | 1113 | { |
1114 | struct xhci_virt_device *vdev; | ||
1115 | struct xhci_ep_ctx *ep_ctx; | ||
1102 | unsigned int ep_index; | 1116 | unsigned int ep_index; |
1103 | 1117 | ||
1104 | ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3])); | 1118 | ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3])); |
1119 | vdev = xhci->devs[slot_id]; | ||
1120 | ep_ctx = xhci_get_ep_ctx(xhci, vdev->out_ctx, ep_index); | ||
1121 | trace_xhci_handle_cmd_reset_ep(ep_ctx); | ||
1122 | |||
1105 | /* This command will only fail if the endpoint wasn't halted, | 1123 | /* This command will only fail if the endpoint wasn't halted, |
1106 | * but we don't care. | 1124 | * but we don't care. |
1107 | */ | 1125 | */ |
@@ -1114,11 +1132,11 @@ static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id, | |||
1114 | */ | 1132 | */ |
1115 | if (xhci->quirks & XHCI_RESET_EP_QUIRK) { | 1133 | if (xhci->quirks & XHCI_RESET_EP_QUIRK) { |
1116 | struct xhci_command *command; | 1134 | struct xhci_command *command; |
1135 | |||
1117 | command = xhci_alloc_command(xhci, false, false, GFP_ATOMIC); | 1136 | command = xhci_alloc_command(xhci, false, false, GFP_ATOMIC); |
1118 | if (!command) { | 1137 | if (!command) |
1119 | xhci_warn(xhci, "WARN Cannot submit cfg ep: ENOMEM\n"); | ||
1120 | return; | 1138 | return; |
1121 | } | 1139 | |
1122 | xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, | 1140 | xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, |
1123 | "Queueing configure endpoint command"); | 1141 | "Queueing configure endpoint command"); |
1124 | xhci_queue_configure_endpoint(xhci, command, | 1142 | xhci_queue_configure_endpoint(xhci, command, |
@@ -1143,10 +1161,15 @@ static void xhci_handle_cmd_enable_slot(struct xhci_hcd *xhci, int slot_id, | |||
1143 | static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id) | 1161 | static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id) |
1144 | { | 1162 | { |
1145 | struct xhci_virt_device *virt_dev; | 1163 | struct xhci_virt_device *virt_dev; |
1164 | struct xhci_slot_ctx *slot_ctx; | ||
1146 | 1165 | ||
1147 | virt_dev = xhci->devs[slot_id]; | 1166 | virt_dev = xhci->devs[slot_id]; |
1148 | if (!virt_dev) | 1167 | if (!virt_dev) |
1149 | return; | 1168 | return; |
1169 | |||
1170 | slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx); | ||
1171 | trace_xhci_handle_cmd_disable_slot(slot_ctx); | ||
1172 | |||
1150 | if (xhci->quirks & XHCI_EP_LIMIT_QUIRK) | 1173 | if (xhci->quirks & XHCI_EP_LIMIT_QUIRK) |
1151 | /* Delete default control endpoint resources */ | 1174 | /* Delete default control endpoint resources */ |
1152 | xhci_free_device_endpoint_resources(xhci, virt_dev, true); | 1175 | xhci_free_device_endpoint_resources(xhci, virt_dev, true); |
@@ -1158,6 +1181,7 @@ static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id, | |||
1158 | { | 1181 | { |
1159 | struct xhci_virt_device *virt_dev; | 1182 | struct xhci_virt_device *virt_dev; |
1160 | struct xhci_input_control_ctx *ctrl_ctx; | 1183 | struct xhci_input_control_ctx *ctrl_ctx; |
1184 | struct xhci_ep_ctx *ep_ctx; | ||
1161 | unsigned int ep_index; | 1185 | unsigned int ep_index; |
1162 | unsigned int ep_state; | 1186 | unsigned int ep_state; |
1163 | u32 add_flags, drop_flags; | 1187 | u32 add_flags, drop_flags; |
@@ -1182,6 +1206,9 @@ static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id, | |||
1182 | /* Input ctx add_flags are the endpoint index plus one */ | 1206 | /* Input ctx add_flags are the endpoint index plus one */ |
1183 | ep_index = xhci_last_valid_endpoint(add_flags) - 1; | 1207 | ep_index = xhci_last_valid_endpoint(add_flags) - 1; |
1184 | 1208 | ||
1209 | ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->out_ctx, ep_index); | ||
1210 | trace_xhci_handle_cmd_config_ep(ep_ctx); | ||
1211 | |||
1185 | /* A usb_set_interface() call directly after clearing a halted | 1212 | /* A usb_set_interface() call directly after clearing a halted |
1186 | * condition may race on this quirky hardware. Not worth | 1213 | * condition may race on this quirky hardware. Not worth |
1187 | * worrying about, since this is prototype hardware. Not sure | 1214 | * worrying about, since this is prototype hardware. Not sure |
@@ -1206,9 +1233,26 @@ static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id, | |||
1206 | return; | 1233 | return; |
1207 | } | 1234 | } |
1208 | 1235 | ||
1236 | static void xhci_handle_cmd_addr_dev(struct xhci_hcd *xhci, int slot_id) | ||
1237 | { | ||
1238 | struct xhci_virt_device *vdev; | ||
1239 | struct xhci_slot_ctx *slot_ctx; | ||
1240 | |||
1241 | vdev = xhci->devs[slot_id]; | ||
1242 | slot_ctx = xhci_get_slot_ctx(xhci, vdev->out_ctx); | ||
1243 | trace_xhci_handle_cmd_addr_dev(slot_ctx); | ||
1244 | } | ||
1245 | |||
1209 | static void xhci_handle_cmd_reset_dev(struct xhci_hcd *xhci, int slot_id, | 1246 | static void xhci_handle_cmd_reset_dev(struct xhci_hcd *xhci, int slot_id, |
1210 | struct xhci_event_cmd *event) | 1247 | struct xhci_event_cmd *event) |
1211 | { | 1248 | { |
1249 | struct xhci_virt_device *vdev; | ||
1250 | struct xhci_slot_ctx *slot_ctx; | ||
1251 | |||
1252 | vdev = xhci->devs[slot_id]; | ||
1253 | slot_ctx = xhci_get_slot_ctx(xhci, vdev->out_ctx); | ||
1254 | trace_xhci_handle_cmd_reset_dev(slot_ctx); | ||
1255 | |||
1212 | xhci_dbg(xhci, "Completed reset device command.\n"); | 1256 | xhci_dbg(xhci, "Completed reset device command.\n"); |
1213 | if (!xhci->devs[slot_id]) | 1257 | if (!xhci->devs[slot_id]) |
1214 | xhci_warn(xhci, "Reset device command completion " | 1258 | xhci_warn(xhci, "Reset device command completion " |
@@ -1250,7 +1294,6 @@ void xhci_cleanup_command_queue(struct xhci_hcd *xhci) | |||
1250 | void xhci_handle_command_timeout(struct work_struct *work) | 1294 | void xhci_handle_command_timeout(struct work_struct *work) |
1251 | { | 1295 | { |
1252 | struct xhci_hcd *xhci; | 1296 | struct xhci_hcd *xhci; |
1253 | int ret; | ||
1254 | unsigned long flags; | 1297 | unsigned long flags; |
1255 | u64 hw_ring_state; | 1298 | u64 hw_ring_state; |
1256 | 1299 | ||
@@ -1271,22 +1314,17 @@ void xhci_handle_command_timeout(struct work_struct *work) | |||
1271 | 1314 | ||
1272 | /* Make sure command ring is running before aborting it */ | 1315 | /* Make sure command ring is running before aborting it */ |
1273 | hw_ring_state = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); | 1316 | hw_ring_state = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); |
1317 | if (hw_ring_state == ~(u64)0) { | ||
1318 | xhci_hc_died(xhci); | ||
1319 | goto time_out_completed; | ||
1320 | } | ||
1321 | |||
1274 | if ((xhci->cmd_ring_state & CMD_RING_STATE_RUNNING) && | 1322 | if ((xhci->cmd_ring_state & CMD_RING_STATE_RUNNING) && |
1275 | (hw_ring_state & CMD_RING_RUNNING)) { | 1323 | (hw_ring_state & CMD_RING_RUNNING)) { |
1276 | /* Prevent new doorbell, and start command abort */ | 1324 | /* Prevent new doorbell, and start command abort */ |
1277 | xhci->cmd_ring_state = CMD_RING_STATE_ABORTED; | 1325 | xhci->cmd_ring_state = CMD_RING_STATE_ABORTED; |
1278 | xhci_dbg(xhci, "Command timeout\n"); | 1326 | xhci_dbg(xhci, "Command timeout\n"); |
1279 | ret = xhci_abort_cmd_ring(xhci, flags); | 1327 | xhci_abort_cmd_ring(xhci, flags); |
1280 | if (unlikely(ret == -ESHUTDOWN)) { | ||
1281 | xhci_err(xhci, "Abort command ring failed\n"); | ||
1282 | xhci_cleanup_command_queue(xhci); | ||
1283 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
1284 | usb_hc_died(xhci_to_hcd(xhci)->primary_hcd); | ||
1285 | xhci_dbg(xhci, "xHCI host controller is dead.\n"); | ||
1286 | |||
1287 | return; | ||
1288 | } | ||
1289 | |||
1290 | goto time_out_completed; | 1328 | goto time_out_completed; |
1291 | } | 1329 | } |
1292 | 1330 | ||
@@ -1384,6 +1422,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, | |||
1384 | case TRB_EVAL_CONTEXT: | 1422 | case TRB_EVAL_CONTEXT: |
1385 | break; | 1423 | break; |
1386 | case TRB_ADDR_DEV: | 1424 | case TRB_ADDR_DEV: |
1425 | xhci_handle_cmd_addr_dev(xhci, slot_id); | ||
1387 | break; | 1426 | break; |
1388 | case TRB_STOP_RING: | 1427 | case TRB_STOP_RING: |
1389 | WARN_ON(slot_id != TRB_TO_SLOT_ID( | 1428 | WARN_ON(slot_id != TRB_TO_SLOT_ID( |
@@ -2243,7 +2282,8 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
2243 | slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags)); | 2282 | slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags)); |
2244 | xdev = xhci->devs[slot_id]; | 2283 | xdev = xhci->devs[slot_id]; |
2245 | if (!xdev) { | 2284 | if (!xdev) { |
2246 | xhci_err(xhci, "ERROR Transfer event pointed to bad slot\n"); | 2285 | xhci_err(xhci, "ERROR Transfer event pointed to bad slot %u\n", |
2286 | slot_id); | ||
2247 | xhci_err(xhci, "@%016llx %08x %08x %08x %08x\n", | 2287 | xhci_err(xhci, "@%016llx %08x %08x %08x %08x\n", |
2248 | (unsigned long long) xhci_trb_virt_to_dma( | 2288 | (unsigned long long) xhci_trb_virt_to_dma( |
2249 | xhci->event_ring->deq_seg, | 2289 | xhci->event_ring->deq_seg, |
@@ -2252,8 +2292,6 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
2252 | upper_32_bits(le64_to_cpu(event->buffer)), | 2292 | upper_32_bits(le64_to_cpu(event->buffer)), |
2253 | le32_to_cpu(event->transfer_len), | 2293 | le32_to_cpu(event->transfer_len), |
2254 | le32_to_cpu(event->flags)); | 2294 | le32_to_cpu(event->flags)); |
2255 | xhci_dbg(xhci, "Event ring:\n"); | ||
2256 | xhci_debug_segment(xhci, xhci->event_ring->deq_seg); | ||
2257 | return -ENODEV; | 2295 | return -ENODEV; |
2258 | } | 2296 | } |
2259 | 2297 | ||
@@ -2263,8 +2301,9 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
2263 | ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer)); | 2301 | ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer)); |
2264 | ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); | 2302 | ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); |
2265 | if (!ep_ring || GET_EP_CTX_STATE(ep_ctx) == EP_STATE_DISABLED) { | 2303 | if (!ep_ring || GET_EP_CTX_STATE(ep_ctx) == EP_STATE_DISABLED) { |
2266 | xhci_err(xhci, "ERROR Transfer event for disabled endpoint " | 2304 | xhci_err(xhci, |
2267 | "or incorrect stream ring\n"); | 2305 | "ERROR Transfer event for disabled endpoint slot %u ep %u or incorrect stream ring\n", |
2306 | slot_id, ep_index); | ||
2268 | xhci_err(xhci, "@%016llx %08x %08x %08x %08x\n", | 2307 | xhci_err(xhci, "@%016llx %08x %08x %08x %08x\n", |
2269 | (unsigned long long) xhci_trb_virt_to_dma( | 2308 | (unsigned long long) xhci_trb_virt_to_dma( |
2270 | xhci->event_ring->deq_seg, | 2309 | xhci->event_ring->deq_seg, |
@@ -2273,8 +2312,6 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
2273 | upper_32_bits(le64_to_cpu(event->buffer)), | 2312 | upper_32_bits(le64_to_cpu(event->buffer)), |
2274 | le32_to_cpu(event->transfer_len), | 2313 | le32_to_cpu(event->transfer_len), |
2275 | le32_to_cpu(event->flags)); | 2314 | le32_to_cpu(event->flags)); |
2276 | xhci_dbg(xhci, "Event ring:\n"); | ||
2277 | xhci_debug_segment(xhci, xhci->event_ring->deq_seg); | ||
2278 | return -ENODEV; | 2315 | return -ENODEV; |
2279 | } | 2316 | } |
2280 | 2317 | ||
@@ -2298,45 +2335,62 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
2298 | trb_comp_code = COMP_SHORT_PACKET; | 2335 | trb_comp_code = COMP_SHORT_PACKET; |
2299 | else | 2336 | else |
2300 | xhci_warn_ratelimited(xhci, | 2337 | xhci_warn_ratelimited(xhci, |
2301 | "WARN Successful completion on short TX: needs XHCI_TRUST_TX_LENGTH quirk?\n"); | 2338 | "WARN Successful completion on short TX for slot %u ep %u: needs XHCI_TRUST_TX_LENGTH quirk?\n", |
2339 | slot_id, ep_index); | ||
2302 | case COMP_SHORT_PACKET: | 2340 | case COMP_SHORT_PACKET: |
2303 | break; | 2341 | break; |
2304 | case COMP_STOPPED: | 2342 | case COMP_STOPPED: |
2305 | xhci_dbg(xhci, "Stopped on Transfer TRB\n"); | 2343 | xhci_dbg(xhci, "Stopped on Transfer TRB for slot %u ep %u\n", |
2344 | slot_id, ep_index); | ||
2306 | break; | 2345 | break; |
2307 | case COMP_STOPPED_LENGTH_INVALID: | 2346 | case COMP_STOPPED_LENGTH_INVALID: |
2308 | xhci_dbg(xhci, "Stopped on No-op or Link TRB\n"); | 2347 | xhci_dbg(xhci, |
2348 | "Stopped on No-op or Link TRB for slot %u ep %u\n", | ||
2349 | slot_id, ep_index); | ||
2309 | break; | 2350 | break; |
2310 | case COMP_STOPPED_SHORT_PACKET: | 2351 | case COMP_STOPPED_SHORT_PACKET: |
2311 | xhci_dbg(xhci, "Stopped with short packet transfer detected\n"); | 2352 | xhci_dbg(xhci, |
2353 | "Stopped with short packet transfer detected for slot %u ep %u\n", | ||
2354 | slot_id, ep_index); | ||
2312 | break; | 2355 | break; |
2313 | case COMP_STALL_ERROR: | 2356 | case COMP_STALL_ERROR: |
2314 | xhci_dbg(xhci, "Stalled endpoint\n"); | 2357 | xhci_dbg(xhci, "Stalled endpoint for slot %u ep %u\n", slot_id, |
2358 | ep_index); | ||
2315 | ep->ep_state |= EP_HALTED; | 2359 | ep->ep_state |= EP_HALTED; |
2316 | status = -EPIPE; | 2360 | status = -EPIPE; |
2317 | break; | 2361 | break; |
2318 | case COMP_TRB_ERROR: | 2362 | case COMP_TRB_ERROR: |
2319 | xhci_warn(xhci, "WARN: TRB error on endpoint\n"); | 2363 | xhci_warn(xhci, |
2364 | "WARN: TRB error for slot %u ep %u on endpoint\n", | ||
2365 | slot_id, ep_index); | ||
2320 | status = -EILSEQ; | 2366 | status = -EILSEQ; |
2321 | break; | 2367 | break; |
2322 | case COMP_SPLIT_TRANSACTION_ERROR: | 2368 | case COMP_SPLIT_TRANSACTION_ERROR: |
2323 | case COMP_USB_TRANSACTION_ERROR: | 2369 | case COMP_USB_TRANSACTION_ERROR: |
2324 | xhci_dbg(xhci, "Transfer error on endpoint\n"); | 2370 | xhci_dbg(xhci, "Transfer error for slot %u ep %u on endpoint\n", |
2371 | slot_id, ep_index); | ||
2325 | status = -EPROTO; | 2372 | status = -EPROTO; |
2326 | break; | 2373 | break; |
2327 | case COMP_BABBLE_DETECTED_ERROR: | 2374 | case COMP_BABBLE_DETECTED_ERROR: |
2328 | xhci_dbg(xhci, "Babble error on endpoint\n"); | 2375 | xhci_dbg(xhci, "Babble error for slot %u ep %u on endpoint\n", |
2376 | slot_id, ep_index); | ||
2329 | status = -EOVERFLOW; | 2377 | status = -EOVERFLOW; |
2330 | break; | 2378 | break; |
2331 | case COMP_DATA_BUFFER_ERROR: | 2379 | case COMP_DATA_BUFFER_ERROR: |
2332 | xhci_warn(xhci, "WARN: HC couldn't access mem fast enough\n"); | 2380 | xhci_warn(xhci, |
2381 | "WARN: HC couldn't access mem fast enough for slot %u ep %u\n", | ||
2382 | slot_id, ep_index); | ||
2333 | status = -ENOSR; | 2383 | status = -ENOSR; |
2334 | break; | 2384 | break; |
2335 | case COMP_BANDWIDTH_OVERRUN_ERROR: | 2385 | case COMP_BANDWIDTH_OVERRUN_ERROR: |
2336 | xhci_warn(xhci, "WARN: bandwidth overrun event on endpoint\n"); | 2386 | xhci_warn(xhci, |
2387 | "WARN: bandwidth overrun event for slot %u ep %u on endpoint\n", | ||
2388 | slot_id, ep_index); | ||
2337 | break; | 2389 | break; |
2338 | case COMP_ISOCH_BUFFER_OVERRUN: | 2390 | case COMP_ISOCH_BUFFER_OVERRUN: |
2339 | xhci_warn(xhci, "WARN: buffer overrun event on endpoint\n"); | 2391 | xhci_warn(xhci, |
2392 | "WARN: buffer overrun event for slot %u ep %u on endpoint", | ||
2393 | slot_id, ep_index); | ||
2340 | break; | 2394 | break; |
2341 | case COMP_RING_UNDERRUN: | 2395 | case COMP_RING_UNDERRUN: |
2342 | /* | 2396 | /* |
@@ -2360,7 +2414,9 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
2360 | ep_index); | 2414 | ep_index); |
2361 | goto cleanup; | 2415 | goto cleanup; |
2362 | case COMP_INCOMPATIBLE_DEVICE_ERROR: | 2416 | case COMP_INCOMPATIBLE_DEVICE_ERROR: |
2363 | xhci_warn(xhci, "WARN: detect an incompatible device"); | 2417 | xhci_warn(xhci, |
2418 | "WARN: detect an incompatible device for slot %u ep %u", | ||
2419 | slot_id, ep_index); | ||
2364 | status = -EPROTO; | 2420 | status = -EPROTO; |
2365 | break; | 2421 | break; |
2366 | case COMP_MISSED_SERVICE_ERROR: | 2422 | case COMP_MISSED_SERVICE_ERROR: |
@@ -2371,19 +2427,24 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
2371 | * short transfer when process the ep_ring next time. | 2427 | * short transfer when process the ep_ring next time. |
2372 | */ | 2428 | */ |
2373 | ep->skip = true; | 2429 | ep->skip = true; |
2374 | xhci_dbg(xhci, "Miss service interval error, set skip flag\n"); | 2430 | xhci_dbg(xhci, |
2431 | "Miss service interval error for slot %u ep %u, set skip flag\n", | ||
2432 | slot_id, ep_index); | ||
2375 | goto cleanup; | 2433 | goto cleanup; |
2376 | case COMP_NO_PING_RESPONSE_ERROR: | 2434 | case COMP_NO_PING_RESPONSE_ERROR: |
2377 | ep->skip = true; | 2435 | ep->skip = true; |
2378 | xhci_dbg(xhci, "No Ping response error, Skip one Isoc TD\n"); | 2436 | xhci_dbg(xhci, |
2437 | "No Ping response error for slot %u ep %u, Skip one Isoc TD\n", | ||
2438 | slot_id, ep_index); | ||
2379 | goto cleanup; | 2439 | goto cleanup; |
2380 | default: | 2440 | default: |
2381 | if (xhci_is_vendor_info_code(xhci, trb_comp_code)) { | 2441 | if (xhci_is_vendor_info_code(xhci, trb_comp_code)) { |
2382 | status = 0; | 2442 | status = 0; |
2383 | break; | 2443 | break; |
2384 | } | 2444 | } |
2385 | xhci_warn(xhci, "ERROR Unknown event condition %u, HC probably busted\n", | 2445 | xhci_warn(xhci, |
2386 | trb_comp_code); | 2446 | "ERROR Unknown event condition %u for slot %u ep %u , HC probably busted\n", |
2447 | trb_comp_code, slot_id, ep_index); | ||
2387 | goto cleanup; | 2448 | goto cleanup; |
2388 | } | 2449 | } |
2389 | 2450 | ||
@@ -2402,15 +2463,11 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
2402 | xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n", | 2463 | xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n", |
2403 | TRB_TO_SLOT_ID(le32_to_cpu(event->flags)), | 2464 | TRB_TO_SLOT_ID(le32_to_cpu(event->flags)), |
2404 | ep_index); | 2465 | ep_index); |
2405 | xhci_dbg(xhci, "Event TRB with TRB type ID %u\n", | ||
2406 | (le32_to_cpu(event->flags) & | ||
2407 | TRB_TYPE_BITMASK)>>10); | ||
2408 | xhci_print_trb_offsets(xhci, (union xhci_trb *) event); | ||
2409 | } | 2466 | } |
2410 | if (ep->skip) { | 2467 | if (ep->skip) { |
2411 | ep->skip = false; | 2468 | ep->skip = false; |
2412 | xhci_dbg(xhci, "td_list is empty while skip " | 2469 | xhci_dbg(xhci, "td_list is empty while skip flag set. Clear skip flag for slot %u ep %u.\n", |
2413 | "flag set. Clear skip flag.\n"); | 2470 | slot_id, ep_index); |
2414 | } | 2471 | } |
2415 | goto cleanup; | 2472 | goto cleanup; |
2416 | } | 2473 | } |
@@ -2418,8 +2475,8 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
2418 | /* We've skipped all the TDs on the ep ring when ep->skip set */ | 2475 | /* We've skipped all the TDs on the ep ring when ep->skip set */ |
2419 | if (ep->skip && td_num == 0) { | 2476 | if (ep->skip && td_num == 0) { |
2420 | ep->skip = false; | 2477 | ep->skip = false; |
2421 | xhci_dbg(xhci, "All tds on the ep_ring skipped. " | 2478 | xhci_dbg(xhci, "All tds on the ep_ring skipped. Clear skip flag for slot %u ep %u.\n", |
2422 | "Clear skip flag.\n"); | 2479 | slot_id, ep_index); |
2423 | goto cleanup; | 2480 | goto cleanup; |
2424 | } | 2481 | } |
2425 | 2482 | ||
@@ -2478,7 +2535,9 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
2478 | ep_ring->last_td_was_short = false; | 2535 | ep_ring->last_td_was_short = false; |
2479 | 2536 | ||
2480 | if (ep->skip) { | 2537 | if (ep->skip) { |
2481 | xhci_dbg(xhci, "Found td. Clear skip flag.\n"); | 2538 | xhci_dbg(xhci, |
2539 | "Found td. Clear skip flag for slot %u ep %u.\n", | ||
2540 | slot_id, ep_index); | ||
2482 | ep->skip = false; | 2541 | ep->skip = false; |
2483 | } | 2542 | } |
2484 | 2543 | ||
@@ -2495,7 +2554,9 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
2495 | * the TD. | 2554 | * the TD. |
2496 | */ | 2555 | */ |
2497 | if (trb_is_noop(ep_trb)) { | 2556 | if (trb_is_noop(ep_trb)) { |
2498 | xhci_dbg(xhci, "ep_trb is a no-op TRB. Skip it\n"); | 2557 | xhci_dbg(xhci, |
2558 | "ep_trb is a no-op TRB. Skip it for slot %u ep %u\n", | ||
2559 | slot_id, ep_index); | ||
2499 | goto cleanup; | 2560 | goto cleanup; |
2500 | } | 2561 | } |
2501 | 2562 | ||
@@ -2623,7 +2684,8 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) | |||
2623 | spin_lock(&xhci->lock); | 2684 | spin_lock(&xhci->lock); |
2624 | /* Check if the xHC generated the interrupt, or the irq is shared */ | 2685 | /* Check if the xHC generated the interrupt, or the irq is shared */ |
2625 | status = readl(&xhci->op_regs->status); | 2686 | status = readl(&xhci->op_regs->status); |
2626 | if (status == 0xffffffff) { | 2687 | if (status == ~(u32)0) { |
2688 | xhci_hc_died(xhci); | ||
2627 | ret = IRQ_HANDLED; | 2689 | ret = IRQ_HANDLED; |
2628 | goto out; | 2690 | goto out; |
2629 | } | 2691 | } |
@@ -3942,10 +4004,8 @@ void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci, | |||
3942 | 4004 | ||
3943 | /* This function gets called from contexts where it cannot sleep */ | 4005 | /* This function gets called from contexts where it cannot sleep */ |
3944 | cmd = xhci_alloc_command(xhci, false, false, GFP_ATOMIC); | 4006 | cmd = xhci_alloc_command(xhci, false, false, GFP_ATOMIC); |
3945 | if (!cmd) { | 4007 | if (!cmd) |
3946 | xhci_warn(xhci, "WARN Cannot submit Set TR Deq Ptr: ENOMEM\n"); | ||
3947 | return; | 4008 | return; |
3948 | } | ||
3949 | 4009 | ||
3950 | ep->queued_deq_seg = deq_state->new_deq_seg; | 4010 | ep->queued_deq_seg = deq_state->new_deq_seg; |
3951 | ep->queued_deq_ptr = deq_state->new_deq_ptr; | 4011 | ep->queued_deq_ptr = deq_state->new_deq_ptr; |
diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h index 1ac2cdf8eece..8ce96de10e8a 100644 --- a/drivers/usb/host/xhci-trace.h +++ b/drivers/usb/host/xhci-trace.h | |||
@@ -231,6 +231,7 @@ DECLARE_EVENT_CLASS(xhci_log_urb, | |||
231 | __field(int, epnum) | 231 | __field(int, epnum) |
232 | __field(int, dir_in) | 232 | __field(int, dir_in) |
233 | __field(int, type) | 233 | __field(int, type) |
234 | __field(int, slot_id) | ||
234 | ), | 235 | ), |
235 | TP_fast_assign( | 236 | TP_fast_assign( |
236 | __entry->urb = urb; | 237 | __entry->urb = urb; |
@@ -245,8 +246,9 @@ DECLARE_EVENT_CLASS(xhci_log_urb, | |||
245 | __entry->epnum = usb_endpoint_num(&urb->ep->desc); | 246 | __entry->epnum = usb_endpoint_num(&urb->ep->desc); |
246 | __entry->dir_in = usb_endpoint_dir_in(&urb->ep->desc); | 247 | __entry->dir_in = usb_endpoint_dir_in(&urb->ep->desc); |
247 | __entry->type = usb_endpoint_type(&urb->ep->desc); | 248 | __entry->type = usb_endpoint_type(&urb->ep->desc); |
249 | __entry->slot_id = urb->dev->slot_id; | ||
248 | ), | 250 | ), |
249 | TP_printk("ep%d%s-%s: urb %p pipe %u length %d/%d sgs %d/%d stream %d flags %08x", | 251 | TP_printk("ep%d%s-%s: urb %p pipe %u slot %d length %d/%d sgs %d/%d stream %d flags %08x", |
250 | __entry->epnum, __entry->dir_in ? "in" : "out", | 252 | __entry->epnum, __entry->dir_in ? "in" : "out", |
251 | ({ char *s; | 253 | ({ char *s; |
252 | switch (__entry->type) { | 254 | switch (__entry->type) { |
@@ -264,8 +266,8 @@ DECLARE_EVENT_CLASS(xhci_log_urb, | |||
264 | break; | 266 | break; |
265 | default: | 267 | default: |
266 | s = "UNKNOWN"; | 268 | s = "UNKNOWN"; |
267 | } s; }), __entry->urb, __entry->pipe, __entry->actual, | 269 | } s; }), __entry->urb, __entry->pipe, __entry->slot_id, |
268 | __entry->length, __entry->num_mapped_sgs, | 270 | __entry->actual, __entry->length, __entry->num_mapped_sgs, |
269 | __entry->num_sgs, __entry->stream, __entry->flags | 271 | __entry->num_sgs, __entry->stream, __entry->flags |
270 | ) | 272 | ) |
271 | ); | 273 | ); |
@@ -285,6 +287,172 @@ DEFINE_EVENT(xhci_log_urb, xhci_urb_dequeue, | |||
285 | TP_ARGS(urb) | 287 | TP_ARGS(urb) |
286 | ); | 288 | ); |
287 | 289 | ||
290 | DECLARE_EVENT_CLASS(xhci_log_ep_ctx, | ||
291 | TP_PROTO(struct xhci_ep_ctx *ctx), | ||
292 | TP_ARGS(ctx), | ||
293 | TP_STRUCT__entry( | ||
294 | __field(u32, info) | ||
295 | __field(u32, info2) | ||
296 | __field(u64, deq) | ||
297 | __field(u32, tx_info) | ||
298 | ), | ||
299 | TP_fast_assign( | ||
300 | __entry->info = le32_to_cpu(ctx->ep_info); | ||
301 | __entry->info2 = le32_to_cpu(ctx->ep_info2); | ||
302 | __entry->deq = le64_to_cpu(ctx->deq); | ||
303 | __entry->tx_info = le32_to_cpu(ctx->tx_info); | ||
304 | ), | ||
305 | TP_printk("%s", xhci_decode_ep_context(__entry->info, | ||
306 | __entry->info2, __entry->deq, __entry->tx_info) | ||
307 | ) | ||
308 | ); | ||
309 | |||
310 | DEFINE_EVENT(xhci_log_ep_ctx, xhci_handle_cmd_stop_ep, | ||
311 | TP_PROTO(struct xhci_ep_ctx *ctx), | ||
312 | TP_ARGS(ctx) | ||
313 | ); | ||
314 | |||
315 | DEFINE_EVENT(xhci_log_ep_ctx, xhci_handle_cmd_set_deq_ep, | ||
316 | TP_PROTO(struct xhci_ep_ctx *ctx), | ||
317 | TP_ARGS(ctx) | ||
318 | ); | ||
319 | |||
320 | DEFINE_EVENT(xhci_log_ep_ctx, xhci_handle_cmd_reset_ep, | ||
321 | TP_PROTO(struct xhci_ep_ctx *ctx), | ||
322 | TP_ARGS(ctx) | ||
323 | ); | ||
324 | |||
325 | DEFINE_EVENT(xhci_log_ep_ctx, xhci_handle_cmd_config_ep, | ||
326 | TP_PROTO(struct xhci_ep_ctx *ctx), | ||
327 | TP_ARGS(ctx) | ||
328 | ); | ||
329 | |||
330 | DECLARE_EVENT_CLASS(xhci_log_slot_ctx, | ||
331 | TP_PROTO(struct xhci_slot_ctx *ctx), | ||
332 | TP_ARGS(ctx), | ||
333 | TP_STRUCT__entry( | ||
334 | __field(u32, info) | ||
335 | __field(u32, info2) | ||
336 | __field(u32, tt_info) | ||
337 | __field(u32, state) | ||
338 | ), | ||
339 | TP_fast_assign( | ||
340 | __entry->info = le32_to_cpu(ctx->dev_info); | ||
341 | __entry->info2 = le32_to_cpu(ctx->dev_info2); | ||
342 | __entry->tt_info = le64_to_cpu(ctx->tt_info); | ||
343 | __entry->state = le32_to_cpu(ctx->dev_state); | ||
344 | ), | ||
345 | TP_printk("%s", xhci_decode_slot_context(__entry->info, | ||
346 | __entry->info2, __entry->tt_info, | ||
347 | __entry->state) | ||
348 | ) | ||
349 | ); | ||
350 | |||
351 | DEFINE_EVENT(xhci_log_slot_ctx, xhci_alloc_dev, | ||
352 | TP_PROTO(struct xhci_slot_ctx *ctx), | ||
353 | TP_ARGS(ctx) | ||
354 | ); | ||
355 | |||
356 | DEFINE_EVENT(xhci_log_slot_ctx, xhci_free_dev, | ||
357 | TP_PROTO(struct xhci_slot_ctx *ctx), | ||
358 | TP_ARGS(ctx) | ||
359 | ); | ||
360 | |||
361 | DEFINE_EVENT(xhci_log_slot_ctx, xhci_handle_cmd_disable_slot, | ||
362 | TP_PROTO(struct xhci_slot_ctx *ctx), | ||
363 | TP_ARGS(ctx) | ||
364 | ); | ||
365 | |||
366 | DEFINE_EVENT(xhci_log_slot_ctx, xhci_discover_or_reset_device, | ||
367 | TP_PROTO(struct xhci_slot_ctx *ctx), | ||
368 | TP_ARGS(ctx) | ||
369 | ); | ||
370 | |||
371 | DEFINE_EVENT(xhci_log_slot_ctx, xhci_setup_device_slot, | ||
372 | TP_PROTO(struct xhci_slot_ctx *ctx), | ||
373 | TP_ARGS(ctx) | ||
374 | ); | ||
375 | |||
376 | DEFINE_EVENT(xhci_log_slot_ctx, xhci_handle_cmd_addr_dev, | ||
377 | TP_PROTO(struct xhci_slot_ctx *ctx), | ||
378 | TP_ARGS(ctx) | ||
379 | ); | ||
380 | |||
381 | DEFINE_EVENT(xhci_log_slot_ctx, xhci_handle_cmd_reset_dev, | ||
382 | TP_PROTO(struct xhci_slot_ctx *ctx), | ||
383 | TP_ARGS(ctx) | ||
384 | ); | ||
385 | |||
386 | DEFINE_EVENT(xhci_log_slot_ctx, xhci_handle_cmd_set_deq, | ||
387 | TP_PROTO(struct xhci_slot_ctx *ctx), | ||
388 | TP_ARGS(ctx) | ||
389 | ); | ||
390 | |||
391 | DECLARE_EVENT_CLASS(xhci_log_ring, | ||
392 | TP_PROTO(struct xhci_ring *ring), | ||
393 | TP_ARGS(ring), | ||
394 | TP_STRUCT__entry( | ||
395 | __field(u32, type) | ||
396 | __field(void *, ring) | ||
397 | __field(dma_addr_t, enq) | ||
398 | __field(dma_addr_t, deq) | ||
399 | __field(dma_addr_t, enq_seg) | ||
400 | __field(dma_addr_t, deq_seg) | ||
401 | __field(unsigned int, num_segs) | ||
402 | __field(unsigned int, stream_id) | ||
403 | __field(unsigned int, cycle_state) | ||
404 | __field(unsigned int, num_trbs_free) | ||
405 | __field(unsigned int, bounce_buf_len) | ||
406 | ), | ||
407 | TP_fast_assign( | ||
408 | __entry->ring = ring; | ||
409 | __entry->type = ring->type; | ||
410 | __entry->num_segs = ring->num_segs; | ||
411 | __entry->stream_id = ring->stream_id; | ||
412 | __entry->enq_seg = ring->enq_seg->dma; | ||
413 | __entry->deq_seg = ring->deq_seg->dma; | ||
414 | __entry->cycle_state = ring->cycle_state; | ||
415 | __entry->num_trbs_free = ring->num_trbs_free; | ||
416 | __entry->bounce_buf_len = ring->bounce_buf_len; | ||
417 | __entry->enq = xhci_trb_virt_to_dma(ring->enq_seg, ring->enqueue); | ||
418 | __entry->deq = xhci_trb_virt_to_dma(ring->deq_seg, ring->dequeue); | ||
419 | ), | ||
420 | TP_printk("%s %p: enq %pad(%pad) deq %pad(%pad) segs %d stream %d free_trbs %d bounce %d cycle %d", | ||
421 | xhci_ring_type_string(__entry->type), __entry->ring, | ||
422 | &__entry->enq, &__entry->enq_seg, | ||
423 | &__entry->deq, &__entry->deq_seg, | ||
424 | __entry->num_segs, | ||
425 | __entry->stream_id, | ||
426 | __entry->num_trbs_free, | ||
427 | __entry->bounce_buf_len, | ||
428 | __entry->cycle_state | ||
429 | ) | ||
430 | ); | ||
431 | |||
432 | DEFINE_EVENT(xhci_log_ring, xhci_ring_alloc, | ||
433 | TP_PROTO(struct xhci_ring *ring), | ||
434 | TP_ARGS(ring) | ||
435 | ); | ||
436 | |||
437 | DEFINE_EVENT(xhci_log_ring, xhci_ring_free, | ||
438 | TP_PROTO(struct xhci_ring *ring), | ||
439 | TP_ARGS(ring) | ||
440 | ); | ||
441 | |||
442 | DEFINE_EVENT(xhci_log_ring, xhci_ring_expansion, | ||
443 | TP_PROTO(struct xhci_ring *ring), | ||
444 | TP_ARGS(ring) | ||
445 | ); | ||
446 | |||
447 | DEFINE_EVENT(xhci_log_ring, xhci_inc_enq, | ||
448 | TP_PROTO(struct xhci_ring *ring), | ||
449 | TP_ARGS(ring) | ||
450 | ); | ||
451 | |||
452 | DEFINE_EVENT(xhci_log_ring, xhci_inc_deq, | ||
453 | TP_PROTO(struct xhci_ring *ring), | ||
454 | TP_ARGS(ring) | ||
455 | ); | ||
288 | #endif /* __XHCI_TRACE_H */ | 456 | #endif /* __XHCI_TRACE_H */ |
289 | 457 | ||
290 | /* this part must be outside header guard */ | 458 | /* this part must be outside header guard */ |
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 953fd8f62df0..2d1310220832 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c | |||
@@ -125,7 +125,7 @@ int xhci_halt(struct xhci_hcd *xhci) | |||
125 | /* | 125 | /* |
126 | * Set the run bit and wait for the host to be running. | 126 | * Set the run bit and wait for the host to be running. |
127 | */ | 127 | */ |
128 | static int xhci_start(struct xhci_hcd *xhci) | 128 | int xhci_start(struct xhci_hcd *xhci) |
129 | { | 129 | { |
130 | u32 temp; | 130 | u32 temp; |
131 | int ret; | 131 | int ret; |
@@ -216,31 +216,21 @@ int xhci_reset(struct xhci_hcd *xhci) | |||
216 | return ret; | 216 | return ret; |
217 | } | 217 | } |
218 | 218 | ||
219 | #ifdef CONFIG_PCI | ||
220 | static int xhci_free_msi(struct xhci_hcd *xhci) | ||
221 | { | ||
222 | int i; | ||
223 | |||
224 | if (!xhci->msix_entries) | ||
225 | return -EINVAL; | ||
226 | |||
227 | for (i = 0; i < xhci->msix_count; i++) | ||
228 | if (xhci->msix_entries[i].vector) | ||
229 | free_irq(xhci->msix_entries[i].vector, | ||
230 | xhci_to_hcd(xhci)); | ||
231 | return 0; | ||
232 | } | ||
233 | 219 | ||
220 | #ifdef CONFIG_USB_PCI | ||
234 | /* | 221 | /* |
235 | * Set up MSI | 222 | * Set up MSI |
236 | */ | 223 | */ |
237 | static int xhci_setup_msi(struct xhci_hcd *xhci) | 224 | static int xhci_setup_msi(struct xhci_hcd *xhci) |
238 | { | 225 | { |
239 | int ret; | 226 | int ret; |
227 | /* | ||
228 | * TODO:Check with MSI Soc for sysdev | ||
229 | */ | ||
240 | struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); | 230 | struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); |
241 | 231 | ||
242 | ret = pci_enable_msi(pdev); | 232 | ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI); |
243 | if (ret) { | 233 | if (ret < 0) { |
244 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, | 234 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, |
245 | "failed to allocate MSI entry"); | 235 | "failed to allocate MSI entry"); |
246 | return ret; | 236 | return ret; |
@@ -251,35 +241,13 @@ static int xhci_setup_msi(struct xhci_hcd *xhci) | |||
251 | if (ret) { | 241 | if (ret) { |
252 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, | 242 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, |
253 | "disable MSI interrupt"); | 243 | "disable MSI interrupt"); |
254 | pci_disable_msi(pdev); | 244 | pci_free_irq_vectors(pdev); |
255 | } | 245 | } |
256 | 246 | ||
257 | return ret; | 247 | return ret; |
258 | } | 248 | } |
259 | 249 | ||
260 | /* | 250 | /* |
261 | * Free IRQs | ||
262 | * free all IRQs request | ||
263 | */ | ||
264 | static void xhci_free_irq(struct xhci_hcd *xhci) | ||
265 | { | ||
266 | struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); | ||
267 | int ret; | ||
268 | |||
269 | /* return if using legacy interrupt */ | ||
270 | if (xhci_to_hcd(xhci)->irq > 0) | ||
271 | return; | ||
272 | |||
273 | ret = xhci_free_msi(xhci); | ||
274 | if (!ret) | ||
275 | return; | ||
276 | if (pdev->irq > 0) | ||
277 | free_irq(pdev->irq, xhci_to_hcd(xhci)); | ||
278 | |||
279 | return; | ||
280 | } | ||
281 | |||
282 | /* | ||
283 | * Set up MSI-X | 251 | * Set up MSI-X |
284 | */ | 252 | */ |
285 | static int xhci_setup_msix(struct xhci_hcd *xhci) | 253 | static int xhci_setup_msix(struct xhci_hcd *xhci) |
@@ -298,28 +266,17 @@ static int xhci_setup_msix(struct xhci_hcd *xhci) | |||
298 | xhci->msix_count = min(num_online_cpus() + 1, | 266 | xhci->msix_count = min(num_online_cpus() + 1, |
299 | HCS_MAX_INTRS(xhci->hcs_params1)); | 267 | HCS_MAX_INTRS(xhci->hcs_params1)); |
300 | 268 | ||
301 | xhci->msix_entries = | 269 | ret = pci_alloc_irq_vectors(pdev, xhci->msix_count, xhci->msix_count, |
302 | kmalloc((sizeof(struct msix_entry))*xhci->msix_count, | 270 | PCI_IRQ_MSIX); |
303 | GFP_KERNEL); | 271 | if (ret < 0) { |
304 | if (!xhci->msix_entries) | ||
305 | return -ENOMEM; | ||
306 | |||
307 | for (i = 0; i < xhci->msix_count; i++) { | ||
308 | xhci->msix_entries[i].entry = i; | ||
309 | xhci->msix_entries[i].vector = 0; | ||
310 | } | ||
311 | |||
312 | ret = pci_enable_msix_exact(pdev, xhci->msix_entries, xhci->msix_count); | ||
313 | if (ret) { | ||
314 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, | 272 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, |
315 | "Failed to enable MSI-X"); | 273 | "Failed to enable MSI-X"); |
316 | goto free_entries; | 274 | return ret; |
317 | } | 275 | } |
318 | 276 | ||
319 | for (i = 0; i < xhci->msix_count; i++) { | 277 | for (i = 0; i < xhci->msix_count; i++) { |
320 | ret = request_irq(xhci->msix_entries[i].vector, | 278 | ret = request_irq(pci_irq_vector(pdev, i), xhci_msi_irq, 0, |
321 | xhci_msi_irq, | 279 | "xhci_hcd", xhci_to_hcd(xhci)); |
322 | 0, "xhci_hcd", xhci_to_hcd(xhci)); | ||
323 | if (ret) | 280 | if (ret) |
324 | goto disable_msix; | 281 | goto disable_msix; |
325 | } | 282 | } |
@@ -329,11 +286,9 @@ static int xhci_setup_msix(struct xhci_hcd *xhci) | |||
329 | 286 | ||
330 | disable_msix: | 287 | disable_msix: |
331 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, "disable MSI-X interrupt"); | 288 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, "disable MSI-X interrupt"); |
332 | xhci_free_irq(xhci); | 289 | while (--i >= 0) |
333 | pci_disable_msix(pdev); | 290 | free_irq(pci_irq_vector(pdev, i), xhci_to_hcd(xhci)); |
334 | free_entries: | 291 | pci_free_irq_vectors(pdev); |
335 | kfree(xhci->msix_entries); | ||
336 | xhci->msix_entries = NULL; | ||
337 | return ret; | 292 | return ret; |
338 | } | 293 | } |
339 | 294 | ||
@@ -346,27 +301,33 @@ static void xhci_cleanup_msix(struct xhci_hcd *xhci) | |||
346 | if (xhci->quirks & XHCI_PLAT) | 301 | if (xhci->quirks & XHCI_PLAT) |
347 | return; | 302 | return; |
348 | 303 | ||
349 | xhci_free_irq(xhci); | 304 | /* return if using legacy interrupt */ |
305 | if (hcd->irq > 0) | ||
306 | return; | ||
307 | |||
308 | if (hcd->msix_enabled) { | ||
309 | int i; | ||
350 | 310 | ||
351 | if (xhci->msix_entries) { | 311 | for (i = 0; i < xhci->msix_count; i++) |
352 | pci_disable_msix(pdev); | 312 | free_irq(pci_irq_vector(pdev, i), xhci_to_hcd(xhci)); |
353 | kfree(xhci->msix_entries); | ||
354 | xhci->msix_entries = NULL; | ||
355 | } else { | 313 | } else { |
356 | pci_disable_msi(pdev); | 314 | free_irq(pci_irq_vector(pdev, 0), xhci_to_hcd(xhci)); |
357 | } | 315 | } |
358 | 316 | ||
317 | pci_free_irq_vectors(pdev); | ||
359 | hcd->msix_enabled = 0; | 318 | hcd->msix_enabled = 0; |
360 | return; | ||
361 | } | 319 | } |
362 | 320 | ||
363 | static void __maybe_unused xhci_msix_sync_irqs(struct xhci_hcd *xhci) | 321 | static void __maybe_unused xhci_msix_sync_irqs(struct xhci_hcd *xhci) |
364 | { | 322 | { |
365 | int i; | 323 | struct usb_hcd *hcd = xhci_to_hcd(xhci); |
324 | |||
325 | if (hcd->msix_enabled) { | ||
326 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); | ||
327 | int i; | ||
366 | 328 | ||
367 | if (xhci->msix_entries) { | ||
368 | for (i = 0; i < xhci->msix_count; i++) | 329 | for (i = 0; i < xhci->msix_count; i++) |
369 | synchronize_irq(xhci->msix_entries[i].vector); | 330 | synchronize_irq(pci_irq_vector(pdev, i)); |
370 | } | 331 | } |
371 | } | 332 | } |
372 | 333 | ||
@@ -539,7 +500,7 @@ static int xhci_all_ports_seen_u0(struct xhci_hcd *xhci) | |||
539 | * device contexts (?), set up a command ring segment (or two?), create event | 500 | * device contexts (?), set up a command ring segment (or two?), create event |
540 | * ring (one for now). | 501 | * ring (one for now). |
541 | */ | 502 | */ |
542 | int xhci_init(struct usb_hcd *hcd) | 503 | static int xhci_init(struct usb_hcd *hcd) |
543 | { | 504 | { |
544 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 505 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
545 | int retval = 0; | 506 | int retval = 0; |
@@ -619,16 +580,10 @@ int xhci_run(struct usb_hcd *hcd) | |||
619 | if (ret) | 580 | if (ret) |
620 | return ret; | 581 | return ret; |
621 | 582 | ||
622 | xhci_dbg(xhci, "Command ring memory map follows:\n"); | ||
623 | xhci_debug_ring(xhci, xhci->cmd_ring); | ||
624 | xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring); | ||
625 | xhci_dbg_cmd_ptrs(xhci); | 583 | xhci_dbg_cmd_ptrs(xhci); |
626 | 584 | ||
627 | xhci_dbg(xhci, "ERST memory map follows:\n"); | 585 | xhci_dbg(xhci, "ERST memory map follows:\n"); |
628 | xhci_dbg_erst(xhci, &xhci->erst); | 586 | xhci_dbg_erst(xhci, &xhci->erst); |
629 | xhci_dbg(xhci, "Event ring:\n"); | ||
630 | xhci_debug_ring(xhci, xhci->event_ring); | ||
631 | xhci_dbg_ring_ptrs(xhci, xhci->event_ring); | ||
632 | temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); | 587 | temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); |
633 | temp_64 &= ~ERST_PTR_MASK; | 588 | temp_64 &= ~ERST_PTR_MASK; |
634 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, | 589 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, |
@@ -661,9 +616,11 @@ int xhci_run(struct usb_hcd *hcd) | |||
661 | 616 | ||
662 | if (xhci->quirks & XHCI_NEC_HOST) { | 617 | if (xhci->quirks & XHCI_NEC_HOST) { |
663 | struct xhci_command *command; | 618 | struct xhci_command *command; |
619 | |||
664 | command = xhci_alloc_command(xhci, false, false, GFP_KERNEL); | 620 | command = xhci_alloc_command(xhci, false, false, GFP_KERNEL); |
665 | if (!command) | 621 | if (!command) |
666 | return -ENOMEM; | 622 | return -ENOMEM; |
623 | |||
667 | xhci_queue_vendor_command(xhci, command, 0, 0, 0, | 624 | xhci_queue_vendor_command(xhci, command, 0, 0, 0, |
668 | TRB_TYPE(TRB_NEC_GET_FW)); | 625 | TRB_TYPE(TRB_NEC_GET_FW)); |
669 | } | 626 | } |
@@ -682,28 +639,28 @@ EXPORT_SYMBOL_GPL(xhci_run); | |||
682 | * Disable device contexts, disable IRQs, and quiesce the HC. | 639 | * Disable device contexts, disable IRQs, and quiesce the HC. |
683 | * Reset the HC, finish any completed transactions, and cleanup memory. | 640 | * Reset the HC, finish any completed transactions, and cleanup memory. |
684 | */ | 641 | */ |
685 | void xhci_stop(struct usb_hcd *hcd) | 642 | static void xhci_stop(struct usb_hcd *hcd) |
686 | { | 643 | { |
687 | u32 temp; | 644 | u32 temp; |
688 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 645 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
689 | 646 | ||
690 | mutex_lock(&xhci->mutex); | 647 | mutex_lock(&xhci->mutex); |
691 | 648 | ||
692 | if (!(xhci->xhc_state & XHCI_STATE_HALTED)) { | 649 | /* Only halt host and free memory after both hcds are removed */ |
693 | spin_lock_irq(&xhci->lock); | ||
694 | |||
695 | xhci->xhc_state |= XHCI_STATE_HALTED; | ||
696 | xhci->cmd_ring_state = CMD_RING_STATE_STOPPED; | ||
697 | xhci_halt(xhci); | ||
698 | xhci_reset(xhci); | ||
699 | spin_unlock_irq(&xhci->lock); | ||
700 | } | ||
701 | |||
702 | if (!usb_hcd_is_primary_hcd(hcd)) { | 650 | if (!usb_hcd_is_primary_hcd(hcd)) { |
651 | /* usb core will free this hcd shortly, unset pointer */ | ||
652 | xhci->shared_hcd = NULL; | ||
703 | mutex_unlock(&xhci->mutex); | 653 | mutex_unlock(&xhci->mutex); |
704 | return; | 654 | return; |
705 | } | 655 | } |
706 | 656 | ||
657 | spin_lock_irq(&xhci->lock); | ||
658 | xhci->xhc_state |= XHCI_STATE_HALTED; | ||
659 | xhci->cmd_ring_state = CMD_RING_STATE_STOPPED; | ||
660 | xhci_halt(xhci); | ||
661 | xhci_reset(xhci); | ||
662 | spin_unlock_irq(&xhci->lock); | ||
663 | |||
707 | xhci_cleanup_msix(xhci); | 664 | xhci_cleanup_msix(xhci); |
708 | 665 | ||
709 | /* Deleting Compliance Mode Recovery Timer */ | 666 | /* Deleting Compliance Mode Recovery Timer */ |
@@ -721,7 +678,7 @@ void xhci_stop(struct usb_hcd *hcd) | |||
721 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, | 678 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, |
722 | "// Disabling event ring interrupts"); | 679 | "// Disabling event ring interrupts"); |
723 | temp = readl(&xhci->op_regs->status); | 680 | temp = readl(&xhci->op_regs->status); |
724 | writel(temp & ~STS_EINT, &xhci->op_regs->status); | 681 | writel((temp & ~0x1fff) | STS_EINT, &xhci->op_regs->status); |
725 | temp = readl(&xhci->ir_set->irq_pending); | 682 | temp = readl(&xhci->ir_set->irq_pending); |
726 | writel(ER_IRQ_DISABLE(temp), &xhci->ir_set->irq_pending); | 683 | writel(ER_IRQ_DISABLE(temp), &xhci->ir_set->irq_pending); |
727 | xhci_print_ir_set(xhci, 0); | 684 | xhci_print_ir_set(xhci, 0); |
@@ -743,12 +700,12 @@ void xhci_stop(struct usb_hcd *hcd) | |||
743 | * | 700 | * |
744 | * This will only ever be called with the main usb_hcd (the USB3 roothub). | 701 | * This will only ever be called with the main usb_hcd (the USB3 roothub). |
745 | */ | 702 | */ |
746 | void xhci_shutdown(struct usb_hcd *hcd) | 703 | static void xhci_shutdown(struct usb_hcd *hcd) |
747 | { | 704 | { |
748 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 705 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
749 | 706 | ||
750 | if (xhci->quirks & XHCI_SPURIOUS_REBOOT) | 707 | if (xhci->quirks & XHCI_SPURIOUS_REBOOT) |
751 | usb_disable_xhci_ports(to_pci_dev(hcd->self.controller)); | 708 | usb_disable_xhci_ports(to_pci_dev(hcd->self.sysdev)); |
752 | 709 | ||
753 | spin_lock_irq(&xhci->lock); | 710 | spin_lock_irq(&xhci->lock); |
754 | xhci_halt(xhci); | 711 | xhci_halt(xhci); |
@@ -765,7 +722,7 @@ void xhci_shutdown(struct usb_hcd *hcd) | |||
765 | 722 | ||
766 | /* Yet another workaround for spurious wakeups at shutdown with HSW */ | 723 | /* Yet another workaround for spurious wakeups at shutdown with HSW */ |
767 | if (xhci->quirks & XHCI_SPURIOUS_WAKEUP) | 724 | if (xhci->quirks & XHCI_SPURIOUS_WAKEUP) |
768 | pci_set_power_state(to_pci_dev(hcd->self.controller), PCI_D3hot); | 725 | pci_set_power_state(to_pci_dev(hcd->self.sysdev), PCI_D3hot); |
769 | } | 726 | } |
770 | 727 | ||
771 | #ifdef CONFIG_PM | 728 | #ifdef CONFIG_PM |
@@ -1054,7 +1011,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) | |||
1054 | 1011 | ||
1055 | xhci_dbg(xhci, "// Disabling event ring interrupts\n"); | 1012 | xhci_dbg(xhci, "// Disabling event ring interrupts\n"); |
1056 | temp = readl(&xhci->op_regs->status); | 1013 | temp = readl(&xhci->op_regs->status); |
1057 | writel(temp & ~STS_EINT, &xhci->op_regs->status); | 1014 | writel((temp & ~0x1fff) | STS_EINT, &xhci->op_regs->status); |
1058 | temp = readl(&xhci->ir_set->irq_pending); | 1015 | temp = readl(&xhci->ir_set->irq_pending); |
1059 | writel(ER_IRQ_DISABLE(temp), &xhci->ir_set->irq_pending); | 1016 | writel(ER_IRQ_DISABLE(temp), &xhci->ir_set->irq_pending); |
1060 | xhci_print_ir_set(xhci, 0); | 1017 | xhci_print_ir_set(xhci, 0); |
@@ -1176,7 +1133,7 @@ unsigned int xhci_get_endpoint_address(unsigned int ep_index) | |||
1176 | * endpoint index to create a bitmask. The slot context is bit 0, endpoint 0 is | 1133 | * endpoint index to create a bitmask. The slot context is bit 0, endpoint 0 is |
1177 | * bit 1, etc. | 1134 | * bit 1, etc. |
1178 | */ | 1135 | */ |
1179 | unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc) | 1136 | static unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc) |
1180 | { | 1137 | { |
1181 | return 1 << (xhci_get_endpoint_index(desc) + 1); | 1138 | return 1 << (xhci_get_endpoint_index(desc) + 1); |
1182 | } | 1139 | } |
@@ -1185,7 +1142,7 @@ unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc) | |||
1185 | * endpoint index to create a bitmask. The slot context is bit 0, endpoint 0 is | 1142 | * endpoint index to create a bitmask. The slot context is bit 0, endpoint 0 is |
1186 | * bit 1, etc. | 1143 | * bit 1, etc. |
1187 | */ | 1144 | */ |
1188 | unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index) | 1145 | static unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index) |
1189 | { | 1146 | { |
1190 | return 1 << (ep_index + 1); | 1147 | return 1 << (ep_index + 1); |
1191 | } | 1148 | } |
@@ -1306,11 +1263,6 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id, | |||
1306 | ctrl_ctx->add_flags = cpu_to_le32(EP0_FLAG); | 1263 | ctrl_ctx->add_flags = cpu_to_le32(EP0_FLAG); |
1307 | ctrl_ctx->drop_flags = 0; | 1264 | ctrl_ctx->drop_flags = 0; |
1308 | 1265 | ||
1309 | xhci_dbg(xhci, "Slot %d input context\n", slot_id); | ||
1310 | xhci_dbg_ctx(xhci, command->in_ctx, ep_index); | ||
1311 | xhci_dbg(xhci, "Slot %d output context\n", slot_id); | ||
1312 | xhci_dbg_ctx(xhci, out_ctx, ep_index); | ||
1313 | |||
1314 | ret = xhci_configure_endpoint(xhci, urb->dev, command, | 1266 | ret = xhci_configure_endpoint(xhci, urb->dev, command, |
1315 | true, false); | 1267 | true, false); |
1316 | 1268 | ||
@@ -1329,7 +1281,7 @@ command_cleanup: | |||
1329 | * non-error returns are a promise to giveback() the urb later | 1281 | * non-error returns are a promise to giveback() the urb later |
1330 | * we drop ownership so next owner (or urb unlink) can get it | 1282 | * we drop ownership so next owner (or urb unlink) can get it |
1331 | */ | 1283 | */ |
1332 | int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) | 1284 | static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) |
1333 | { | 1285 | { |
1334 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 1286 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
1335 | unsigned long flags; | 1287 | unsigned long flags; |
@@ -1465,7 +1417,7 @@ free_priv: | |||
1465 | * Note that this function can be called in any context, or so says | 1417 | * Note that this function can be called in any context, or so says |
1466 | * usb_hcd_unlink_urb() | 1418 | * usb_hcd_unlink_urb() |
1467 | */ | 1419 | */ |
1468 | int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | 1420 | static int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) |
1469 | { | 1421 | { |
1470 | unsigned long flags; | 1422 | unsigned long flags; |
1471 | int ret, i; | 1423 | int ret, i; |
@@ -1501,10 +1453,16 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | |||
1501 | if (!ep || !ep_ring) | 1453 | if (!ep || !ep_ring) |
1502 | goto err_giveback; | 1454 | goto err_giveback; |
1503 | 1455 | ||
1456 | /* If xHC is dead take it down and return ALL URBs in xhci_hc_died() */ | ||
1504 | temp = readl(&xhci->op_regs->status); | 1457 | temp = readl(&xhci->op_regs->status); |
1505 | if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_HALTED)) { | 1458 | if (temp == ~(u32)0 || xhci->xhc_state & XHCI_STATE_DYING) { |
1459 | xhci_hc_died(xhci); | ||
1460 | goto done; | ||
1461 | } | ||
1462 | |||
1463 | if (xhci->xhc_state & XHCI_STATE_HALTED) { | ||
1506 | xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, | 1464 | xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb, |
1507 | "HW died, freeing TD."); | 1465 | "HC halted, freeing TD manually."); |
1508 | for (i = urb_priv->num_tds_done; | 1466 | for (i = urb_priv->num_tds_done; |
1509 | i < urb_priv->num_tds; | 1467 | i < urb_priv->num_tds; |
1510 | i++) { | 1468 | i++) { |
@@ -1576,7 +1534,7 @@ err_giveback: | |||
1576 | * disabled, so there's no need for mutual exclusion to protect | 1534 | * disabled, so there's no need for mutual exclusion to protect |
1577 | * the xhci->devs[slot_id] structure. | 1535 | * the xhci->devs[slot_id] structure. |
1578 | */ | 1536 | */ |
1579 | int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, | 1537 | static int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, |
1580 | struct usb_host_endpoint *ep) | 1538 | struct usb_host_endpoint *ep) |
1581 | { | 1539 | { |
1582 | struct xhci_hcd *xhci; | 1540 | struct xhci_hcd *xhci; |
@@ -1659,7 +1617,7 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, | |||
1659 | * configuration or alt setting is installed in the device, so there's no need | 1617 | * configuration or alt setting is installed in the device, so there's no need |
1660 | * for mutual exclusion to protect the xhci->devs[slot_id] structure. | 1618 | * for mutual exclusion to protect the xhci->devs[slot_id] structure. |
1661 | */ | 1619 | */ |
1662 | int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, | 1620 | static int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, |
1663 | struct usb_host_endpoint *ep) | 1621 | struct usb_host_endpoint *ep) |
1664 | { | 1622 | { |
1665 | struct xhci_hcd *xhci; | 1623 | struct xhci_hcd *xhci; |
@@ -1852,7 +1810,6 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci, | |||
1852 | struct usb_device *udev, u32 *cmd_status) | 1810 | struct usb_device *udev, u32 *cmd_status) |
1853 | { | 1811 | { |
1854 | int ret; | 1812 | int ret; |
1855 | struct xhci_virt_device *virt_dev = xhci->devs[udev->slot_id]; | ||
1856 | 1813 | ||
1857 | switch (*cmd_status) { | 1814 | switch (*cmd_status) { |
1858 | case COMP_COMMAND_ABORTED: | 1815 | case COMP_COMMAND_ABORTED: |
@@ -1873,7 +1830,6 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci, | |||
1873 | case COMP_CONTEXT_STATE_ERROR: | 1830 | case COMP_CONTEXT_STATE_ERROR: |
1874 | dev_warn(&udev->dev, | 1831 | dev_warn(&udev->dev, |
1875 | "WARN: invalid context state for evaluate context command.\n"); | 1832 | "WARN: invalid context state for evaluate context command.\n"); |
1876 | xhci_dbg_ctx(xhci, virt_dev->out_ctx, 1); | ||
1877 | ret = -EINVAL; | 1833 | ret = -EINVAL; |
1878 | break; | 1834 | break; |
1879 | case COMP_INCOMPATIBLE_DEVICE_ERROR: | 1835 | case COMP_INCOMPATIBLE_DEVICE_ERROR: |
@@ -2330,7 +2286,7 @@ static unsigned int xhci_get_ss_bw_consumed(struct xhci_bw_info *ep_bw) | |||
2330 | 2286 | ||
2331 | } | 2287 | } |
2332 | 2288 | ||
2333 | void xhci_drop_ep_from_interval_table(struct xhci_hcd *xhci, | 2289 | static void xhci_drop_ep_from_interval_table(struct xhci_hcd *xhci, |
2334 | struct xhci_bw_info *ep_bw, | 2290 | struct xhci_bw_info *ep_bw, |
2335 | struct xhci_interval_bw_table *bw_table, | 2291 | struct xhci_interval_bw_table *bw_table, |
2336 | struct usb_device *udev, | 2292 | struct usb_device *udev, |
@@ -2595,6 +2551,12 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, | |||
2595 | return -EINVAL; | 2551 | return -EINVAL; |
2596 | 2552 | ||
2597 | spin_lock_irqsave(&xhci->lock, flags); | 2553 | spin_lock_irqsave(&xhci->lock, flags); |
2554 | |||
2555 | if (xhci->xhc_state & XHCI_STATE_DYING) { | ||
2556 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
2557 | return -ESHUTDOWN; | ||
2558 | } | ||
2559 | |||
2598 | virt_dev = xhci->devs[udev->slot_id]; | 2560 | virt_dev = xhci->devs[udev->slot_id]; |
2599 | 2561 | ||
2600 | ctrl_ctx = xhci_get_input_control_ctx(command->in_ctx); | 2562 | ctrl_ctx = xhci_get_input_control_ctx(command->in_ctx); |
@@ -2689,7 +2651,7 @@ static void xhci_check_bw_drop_ep_streams(struct xhci_hcd *xhci, | |||
2689 | * else should be touching the xhci->devs[slot_id] structure, so we | 2651 | * else should be touching the xhci->devs[slot_id] structure, so we |
2690 | * don't need to take the xhci->lock for manipulating that. | 2652 | * don't need to take the xhci->lock for manipulating that. |
2691 | */ | 2653 | */ |
2692 | int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) | 2654 | static int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) |
2693 | { | 2655 | { |
2694 | int i; | 2656 | int i; |
2695 | int ret = 0; | 2657 | int ret = 0; |
@@ -2746,9 +2708,6 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) | |||
2746 | break; | 2708 | break; |
2747 | } | 2709 | } |
2748 | } | 2710 | } |
2749 | xhci_dbg(xhci, "New Input Control Context:\n"); | ||
2750 | xhci_dbg_ctx(xhci, virt_dev->in_ctx, | ||
2751 | LAST_CTX_TO_EP_NUM(le32_to_cpu(slot_ctx->dev_info))); | ||
2752 | 2711 | ||
2753 | ret = xhci_configure_endpoint(xhci, udev, command, | 2712 | ret = xhci_configure_endpoint(xhci, udev, command, |
2754 | false, false); | 2713 | false, false); |
@@ -2756,10 +2715,6 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) | |||
2756 | /* Callee should call reset_bandwidth() */ | 2715 | /* Callee should call reset_bandwidth() */ |
2757 | goto command_cleanup; | 2716 | goto command_cleanup; |
2758 | 2717 | ||
2759 | xhci_dbg(xhci, "Output context after successful config ep cmd:\n"); | ||
2760 | xhci_dbg_ctx(xhci, virt_dev->out_ctx, | ||
2761 | LAST_CTX_TO_EP_NUM(le32_to_cpu(slot_ctx->dev_info))); | ||
2762 | |||
2763 | /* Free any rings that were dropped, but not changed. */ | 2718 | /* Free any rings that were dropped, but not changed. */ |
2764 | for (i = 1; i < 31; i++) { | 2719 | for (i = 1; i < 31; i++) { |
2765 | if ((le32_to_cpu(ctrl_ctx->drop_flags) & (1 << (i + 1))) && | 2720 | if ((le32_to_cpu(ctrl_ctx->drop_flags) & (1 << (i + 1))) && |
@@ -2793,7 +2748,7 @@ command_cleanup: | |||
2793 | return ret; | 2748 | return ret; |
2794 | } | 2749 | } |
2795 | 2750 | ||
2796 | void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) | 2751 | static void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) |
2797 | { | 2752 | { |
2798 | struct xhci_hcd *xhci; | 2753 | struct xhci_hcd *xhci; |
2799 | struct xhci_virt_device *virt_dev; | 2754 | struct xhci_virt_device *virt_dev; |
@@ -2826,9 +2781,6 @@ static void xhci_setup_input_ctx_for_config_ep(struct xhci_hcd *xhci, | |||
2826 | ctrl_ctx->drop_flags = cpu_to_le32(drop_flags); | 2781 | ctrl_ctx->drop_flags = cpu_to_le32(drop_flags); |
2827 | xhci_slot_copy(xhci, in_ctx, out_ctx); | 2782 | xhci_slot_copy(xhci, in_ctx, out_ctx); |
2828 | ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG); | 2783 | ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG); |
2829 | |||
2830 | xhci_dbg(xhci, "Input Context:\n"); | ||
2831 | xhci_dbg_ctx(xhci, in_ctx, xhci_last_valid_endpoint(add_flags)); | ||
2832 | } | 2784 | } |
2833 | 2785 | ||
2834 | static void xhci_setup_input_ctx_for_quirk(struct xhci_hcd *xhci, | 2786 | static void xhci_setup_input_ctx_for_quirk(struct xhci_hcd *xhci, |
@@ -2919,7 +2871,7 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, | |||
2919 | * Context: in_interrupt | 2871 | * Context: in_interrupt |
2920 | */ | 2872 | */ |
2921 | 2873 | ||
2922 | void xhci_endpoint_reset(struct usb_hcd *hcd, | 2874 | static void xhci_endpoint_reset(struct usb_hcd *hcd, |
2923 | struct usb_host_endpoint *ep) | 2875 | struct usb_host_endpoint *ep) |
2924 | { | 2876 | { |
2925 | struct xhci_hcd *xhci; | 2877 | struct xhci_hcd *xhci; |
@@ -3095,7 +3047,7 @@ static u32 xhci_calculate_no_streams_bitmask(struct xhci_hcd *xhci, | |||
3095 | * hardware or endpoints claim they can't support the number of requested | 3047 | * hardware or endpoints claim they can't support the number of requested |
3096 | * stream IDs. | 3048 | * stream IDs. |
3097 | */ | 3049 | */ |
3098 | int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev, | 3050 | static int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev, |
3099 | struct usb_host_endpoint **eps, unsigned int num_eps, | 3051 | struct usb_host_endpoint **eps, unsigned int num_eps, |
3100 | unsigned int num_streams, gfp_t mem_flags) | 3052 | unsigned int num_streams, gfp_t mem_flags) |
3101 | { | 3053 | { |
@@ -3129,10 +3081,9 @@ int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev, | |||
3129 | } | 3081 | } |
3130 | 3082 | ||
3131 | config_cmd = xhci_alloc_command(xhci, true, true, mem_flags); | 3083 | config_cmd = xhci_alloc_command(xhci, true, true, mem_flags); |
3132 | if (!config_cmd) { | 3084 | if (!config_cmd) |
3133 | xhci_dbg(xhci, "Could not allocate xHCI command structure.\n"); | ||
3134 | return -ENOMEM; | 3085 | return -ENOMEM; |
3135 | } | 3086 | |
3136 | ctrl_ctx = xhci_get_input_control_ctx(config_cmd->in_ctx); | 3087 | ctrl_ctx = xhci_get_input_control_ctx(config_cmd->in_ctx); |
3137 | if (!ctrl_ctx) { | 3088 | if (!ctrl_ctx) { |
3138 | xhci_warn(xhci, "%s: Could not get input context, bad type.\n", | 3089 | xhci_warn(xhci, "%s: Could not get input context, bad type.\n", |
@@ -3259,7 +3210,7 @@ cleanup: | |||
3259 | * Modify the endpoint context state, submit a configure endpoint command, | 3210 | * Modify the endpoint context state, submit a configure endpoint command, |
3260 | * and free all endpoint rings for streams if that completes successfully. | 3211 | * and free all endpoint rings for streams if that completes successfully. |
3261 | */ | 3212 | */ |
3262 | int xhci_free_streams(struct usb_hcd *hcd, struct usb_device *udev, | 3213 | static int xhci_free_streams(struct usb_hcd *hcd, struct usb_device *udev, |
3263 | struct usb_host_endpoint **eps, unsigned int num_eps, | 3214 | struct usb_host_endpoint **eps, unsigned int num_eps, |
3264 | gfp_t mem_flags) | 3215 | gfp_t mem_flags) |
3265 | { | 3216 | { |
@@ -3391,7 +3342,8 @@ void xhci_free_device_endpoint_resources(struct xhci_hcd *xhci, | |||
3391 | * re-initialization during S3/S4. In this case, call xhci_alloc_dev() to | 3342 | * re-initialization during S3/S4. In this case, call xhci_alloc_dev() to |
3392 | * re-allocate the device. | 3343 | * re-allocate the device. |
3393 | */ | 3344 | */ |
3394 | int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev) | 3345 | static int xhci_discover_or_reset_device(struct usb_hcd *hcd, |
3346 | struct usb_device *udev) | ||
3395 | { | 3347 | { |
3396 | int ret, i; | 3348 | int ret, i; |
3397 | unsigned long flags; | 3349 | unsigned long flags; |
@@ -3443,6 +3395,8 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev) | |||
3443 | SLOT_STATE_DISABLED) | 3395 | SLOT_STATE_DISABLED) |
3444 | return 0; | 3396 | return 0; |
3445 | 3397 | ||
3398 | trace_xhci_discover_or_reset_device(slot_ctx); | ||
3399 | |||
3446 | xhci_dbg(xhci, "Resetting device with slot ID %u\n", slot_id); | 3400 | xhci_dbg(xhci, "Resetting device with slot ID %u\n", slot_id); |
3447 | /* Allocate the command structure that holds the struct completion. | 3401 | /* Allocate the command structure that holds the struct completion. |
3448 | * Assume we're in process context, since the normal device reset | 3402 | * Assume we're in process context, since the normal device reset |
@@ -3539,9 +3493,6 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev) | |||
3539 | } | 3493 | } |
3540 | /* If necessary, update the number of active TTs on this root port */ | 3494 | /* If necessary, update the number of active TTs on this root port */ |
3541 | xhci_update_tt_active_eps(xhci, virt_dev, old_active_eps); | 3495 | xhci_update_tt_active_eps(xhci, virt_dev, old_active_eps); |
3542 | |||
3543 | xhci_dbg(xhci, "Output context after successful reset device cmd:\n"); | ||
3544 | xhci_dbg_ctx(xhci, virt_dev->out_ctx, last_freed_endpoint); | ||
3545 | ret = 0; | 3496 | ret = 0; |
3546 | 3497 | ||
3547 | command_cleanup: | 3498 | command_cleanup: |
@@ -3554,12 +3505,11 @@ command_cleanup: | |||
3554 | * disconnected, and all traffic has been stopped and the endpoints have been | 3505 | * disconnected, and all traffic has been stopped and the endpoints have been |
3555 | * disabled. Free any HC data structures associated with that device. | 3506 | * disabled. Free any HC data structures associated with that device. |
3556 | */ | 3507 | */ |
3557 | void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) | 3508 | static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) |
3558 | { | 3509 | { |
3559 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 3510 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
3560 | struct xhci_virt_device *virt_dev; | 3511 | struct xhci_virt_device *virt_dev; |
3561 | unsigned long flags; | 3512 | struct xhci_slot_ctx *slot_ctx; |
3562 | u32 state; | ||
3563 | int i, ret; | 3513 | int i, ret; |
3564 | struct xhci_command *command; | 3514 | struct xhci_command *command; |
3565 | 3515 | ||
@@ -3587,6 +3537,8 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) | |||
3587 | } | 3537 | } |
3588 | 3538 | ||
3589 | virt_dev = xhci->devs[udev->slot_id]; | 3539 | virt_dev = xhci->devs[udev->slot_id]; |
3540 | slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx); | ||
3541 | trace_xhci_free_dev(slot_ctx); | ||
3590 | 3542 | ||
3591 | /* Stop any wayward timer functions (which may grab the lock) */ | 3543 | /* Stop any wayward timer functions (which may grab the lock) */ |
3592 | for (i = 0; i < 31; i++) { | 3544 | for (i = 0; i < 31; i++) { |
@@ -3594,30 +3546,50 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) | |||
3594 | del_timer_sync(&virt_dev->eps[i].stop_cmd_timer); | 3546 | del_timer_sync(&virt_dev->eps[i].stop_cmd_timer); |
3595 | } | 3547 | } |
3596 | 3548 | ||
3549 | xhci_disable_slot(xhci, command, udev->slot_id); | ||
3550 | /* | ||
3551 | * Event command completion handler will free any data structures | ||
3552 | * associated with the slot. XXX Can free sleep? | ||
3553 | */ | ||
3554 | } | ||
3555 | |||
3556 | int xhci_disable_slot(struct xhci_hcd *xhci, struct xhci_command *command, | ||
3557 | u32 slot_id) | ||
3558 | { | ||
3559 | unsigned long flags; | ||
3560 | u32 state; | ||
3561 | int ret = 0; | ||
3562 | struct xhci_virt_device *virt_dev; | ||
3563 | |||
3564 | virt_dev = xhci->devs[slot_id]; | ||
3565 | if (!virt_dev) | ||
3566 | return -EINVAL; | ||
3567 | if (!command) | ||
3568 | command = xhci_alloc_command(xhci, false, false, GFP_KERNEL); | ||
3569 | if (!command) | ||
3570 | return -ENOMEM; | ||
3571 | |||
3597 | spin_lock_irqsave(&xhci->lock, flags); | 3572 | spin_lock_irqsave(&xhci->lock, flags); |
3598 | /* Don't disable the slot if the host controller is dead. */ | 3573 | /* Don't disable the slot if the host controller is dead. */ |
3599 | state = readl(&xhci->op_regs->status); | 3574 | state = readl(&xhci->op_regs->status); |
3600 | if (state == 0xffffffff || (xhci->xhc_state & XHCI_STATE_DYING) || | 3575 | if (state == 0xffffffff || (xhci->xhc_state & XHCI_STATE_DYING) || |
3601 | (xhci->xhc_state & XHCI_STATE_HALTED)) { | 3576 | (xhci->xhc_state & XHCI_STATE_HALTED)) { |
3602 | xhci_free_virt_device(xhci, udev->slot_id); | 3577 | xhci_free_virt_device(xhci, slot_id); |
3603 | spin_unlock_irqrestore(&xhci->lock, flags); | 3578 | spin_unlock_irqrestore(&xhci->lock, flags); |
3604 | kfree(command); | 3579 | kfree(command); |
3605 | return; | 3580 | return ret; |
3606 | } | 3581 | } |
3607 | 3582 | ||
3608 | if (xhci_queue_slot_control(xhci, command, TRB_DISABLE_SLOT, | 3583 | ret = xhci_queue_slot_control(xhci, command, TRB_DISABLE_SLOT, |
3609 | udev->slot_id)) { | 3584 | slot_id); |
3585 | if (ret) { | ||
3610 | spin_unlock_irqrestore(&xhci->lock, flags); | 3586 | spin_unlock_irqrestore(&xhci->lock, flags); |
3611 | xhci_dbg(xhci, "FIXME: allocate a command ring segment\n"); | 3587 | xhci_dbg(xhci, "FIXME: allocate a command ring segment\n"); |
3612 | return; | 3588 | return ret; |
3613 | } | 3589 | } |
3614 | xhci_ring_cmd_db(xhci); | 3590 | xhci_ring_cmd_db(xhci); |
3615 | spin_unlock_irqrestore(&xhci->lock, flags); | 3591 | spin_unlock_irqrestore(&xhci->lock, flags); |
3616 | 3592 | return ret; | |
3617 | /* | ||
3618 | * Event command completion handler will free any data structures | ||
3619 | * associated with the slot. XXX Can free sleep? | ||
3620 | */ | ||
3621 | } | 3593 | } |
3622 | 3594 | ||
3623 | /* | 3595 | /* |
@@ -3650,6 +3622,8 @@ static int xhci_reserve_host_control_ep_resources(struct xhci_hcd *xhci) | |||
3650 | int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) | 3622 | int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) |
3651 | { | 3623 | { |
3652 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 3624 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
3625 | struct xhci_virt_device *vdev; | ||
3626 | struct xhci_slot_ctx *slot_ctx; | ||
3653 | unsigned long flags; | 3627 | unsigned long flags; |
3654 | int ret, slot_id; | 3628 | int ret, slot_id; |
3655 | struct xhci_command *command; | 3629 | struct xhci_command *command; |
@@ -3705,6 +3679,10 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) | |||
3705 | xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n"); | 3679 | xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n"); |
3706 | goto disable_slot; | 3680 | goto disable_slot; |
3707 | } | 3681 | } |
3682 | vdev = xhci->devs[slot_id]; | ||
3683 | slot_ctx = xhci_get_slot_ctx(xhci, vdev->out_ctx); | ||
3684 | trace_xhci_alloc_dev(slot_ctx); | ||
3685 | |||
3708 | udev->slot_id = slot_id; | 3686 | udev->slot_id = slot_id; |
3709 | 3687 | ||
3710 | #ifndef CONFIG_USB_DEFAULT_PERSIST | 3688 | #ifndef CONFIG_USB_DEFAULT_PERSIST |
@@ -3724,15 +3702,10 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) | |||
3724 | 3702 | ||
3725 | disable_slot: | 3703 | disable_slot: |
3726 | /* Disable slot, if we can do it without mem alloc */ | 3704 | /* Disable slot, if we can do it without mem alloc */ |
3727 | spin_lock_irqsave(&xhci->lock, flags); | ||
3728 | kfree(command->completion); | 3705 | kfree(command->completion); |
3729 | command->completion = NULL; | 3706 | command->completion = NULL; |
3730 | command->status = 0; | 3707 | command->status = 0; |
3731 | if (!xhci_queue_slot_control(xhci, command, TRB_DISABLE_SLOT, | 3708 | return xhci_disable_slot(xhci, command, udev->slot_id); |
3732 | udev->slot_id)) | ||
3733 | xhci_ring_cmd_db(xhci); | ||
3734 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
3735 | return 0; | ||
3736 | } | 3709 | } |
3737 | 3710 | ||
3738 | /* | 3711 | /* |
@@ -3779,9 +3752,10 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, | |||
3779 | ret = -EINVAL; | 3752 | ret = -EINVAL; |
3780 | goto out; | 3753 | goto out; |
3781 | } | 3754 | } |
3755 | slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx); | ||
3756 | trace_xhci_setup_device_slot(slot_ctx); | ||
3782 | 3757 | ||
3783 | if (setup == SETUP_CONTEXT_ONLY) { | 3758 | if (setup == SETUP_CONTEXT_ONLY) { |
3784 | slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx); | ||
3785 | if (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state)) == | 3759 | if (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state)) == |
3786 | SLOT_STATE_DEFAULT) { | 3760 | SLOT_STATE_DEFAULT) { |
3787 | xhci_dbg(xhci, "Slot already in default state\n"); | 3761 | xhci_dbg(xhci, "Slot already in default state\n"); |
@@ -3818,8 +3792,6 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, | |||
3818 | ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG); | 3792 | ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG); |
3819 | ctrl_ctx->drop_flags = 0; | 3793 | ctrl_ctx->drop_flags = 0; |
3820 | 3794 | ||
3821 | xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id); | ||
3822 | xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2); | ||
3823 | trace_xhci_address_ctx(xhci, virt_dev->in_ctx, | 3795 | trace_xhci_address_ctx(xhci, virt_dev->in_ctx, |
3824 | le32_to_cpu(slot_ctx->dev_info) >> 27); | 3796 | le32_to_cpu(slot_ctx->dev_info) >> 27); |
3825 | 3797 | ||
@@ -3872,8 +3844,6 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, | |||
3872 | xhci_err(xhci, | 3844 | xhci_err(xhci, |
3873 | "ERROR: unexpected setup %s command completion code 0x%x.\n", | 3845 | "ERROR: unexpected setup %s command completion code 0x%x.\n", |
3874 | act, command->status); | 3846 | act, command->status); |
3875 | xhci_dbg(xhci, "Slot ID %d Output Context:\n", udev->slot_id); | ||
3876 | xhci_dbg_ctx(xhci, virt_dev->out_ctx, 2); | ||
3877 | trace_xhci_address_ctx(xhci, virt_dev->out_ctx, 1); | 3847 | trace_xhci_address_ctx(xhci, virt_dev->out_ctx, 1); |
3878 | ret = -EINVAL; | 3848 | ret = -EINVAL; |
3879 | break; | 3849 | break; |
@@ -3892,17 +3862,12 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, | |||
3892 | xhci_dbg_trace(xhci, trace_xhci_dbg_address, | 3862 | xhci_dbg_trace(xhci, trace_xhci_dbg_address, |
3893 | "Output Context DMA address = %#08llx", | 3863 | "Output Context DMA address = %#08llx", |
3894 | (unsigned long long)virt_dev->out_ctx->dma); | 3864 | (unsigned long long)virt_dev->out_ctx->dma); |
3895 | xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id); | ||
3896 | xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2); | ||
3897 | trace_xhci_address_ctx(xhci, virt_dev->in_ctx, | 3865 | trace_xhci_address_ctx(xhci, virt_dev->in_ctx, |
3898 | le32_to_cpu(slot_ctx->dev_info) >> 27); | 3866 | le32_to_cpu(slot_ctx->dev_info) >> 27); |
3899 | xhci_dbg(xhci, "Slot ID %d Output Context:\n", udev->slot_id); | ||
3900 | xhci_dbg_ctx(xhci, virt_dev->out_ctx, 2); | ||
3901 | /* | 3867 | /* |
3902 | * USB core uses address 1 for the roothubs, so we add one to the | 3868 | * USB core uses address 1 for the roothubs, so we add one to the |
3903 | * address given back to us by the HC. | 3869 | * address given back to us by the HC. |
3904 | */ | 3870 | */ |
3905 | slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx); | ||
3906 | trace_xhci_address_ctx(xhci, virt_dev->out_ctx, | 3871 | trace_xhci_address_ctx(xhci, virt_dev->out_ctx, |
3907 | le32_to_cpu(slot_ctx->dev_info) >> 27); | 3872 | le32_to_cpu(slot_ctx->dev_info) >> 27); |
3908 | /* Zero the input context control for later use */ | 3873 | /* Zero the input context control for later use */ |
@@ -3921,12 +3886,12 @@ out: | |||
3921 | return ret; | 3886 | return ret; |
3922 | } | 3887 | } |
3923 | 3888 | ||
3924 | int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) | 3889 | static int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) |
3925 | { | 3890 | { |
3926 | return xhci_setup_device(hcd, udev, SETUP_CONTEXT_ADDRESS); | 3891 | return xhci_setup_device(hcd, udev, SETUP_CONTEXT_ADDRESS); |
3927 | } | 3892 | } |
3928 | 3893 | ||
3929 | int xhci_enable_device(struct usb_hcd *hcd, struct usb_device *udev) | 3894 | static int xhci_enable_device(struct usb_hcd *hcd, struct usb_device *udev) |
3930 | { | 3895 | { |
3931 | return xhci_setup_device(hcd, udev, SETUP_CONTEXT_ONLY); | 3896 | return xhci_setup_device(hcd, udev, SETUP_CONTEXT_ONLY); |
3932 | } | 3897 | } |
@@ -4003,14 +3968,10 @@ static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci, | |||
4003 | 3968 | ||
4004 | xhci_dbg_trace(xhci, trace_xhci_dbg_context_change, | 3969 | xhci_dbg_trace(xhci, trace_xhci_dbg_context_change, |
4005 | "Set up evaluate context for LPM MEL change."); | 3970 | "Set up evaluate context for LPM MEL change."); |
4006 | xhci_dbg(xhci, "Slot %u Input Context:\n", udev->slot_id); | ||
4007 | xhci_dbg_ctx(xhci, command->in_ctx, 0); | ||
4008 | 3971 | ||
4009 | /* Issue and wait for the evaluate context command. */ | 3972 | /* Issue and wait for the evaluate context command. */ |
4010 | ret = xhci_configure_endpoint(xhci, udev, command, | 3973 | ret = xhci_configure_endpoint(xhci, udev, command, |
4011 | true, true); | 3974 | true, true); |
4012 | xhci_dbg(xhci, "Slot %u Output Context:\n", udev->slot_id); | ||
4013 | xhci_dbg_ctx(xhci, virt_dev->out_ctx, 0); | ||
4014 | 3975 | ||
4015 | if (!ret) { | 3976 | if (!ret) { |
4016 | spin_lock_irqsave(&xhci->lock, flags); | 3977 | spin_lock_irqsave(&xhci->lock, flags); |
@@ -4083,7 +4044,7 @@ static int xhci_calculate_usb2_hw_lpm_params(struct usb_device *udev) | |||
4083 | return PORT_BESLD(besld) | PORT_L1_TIMEOUT(l1) | PORT_HIRDM(hirdm); | 4044 | return PORT_BESLD(besld) | PORT_L1_TIMEOUT(l1) | PORT_HIRDM(hirdm); |
4084 | } | 4045 | } |
4085 | 4046 | ||
4086 | int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, | 4047 | static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, |
4087 | struct usb_device *udev, int enable) | 4048 | struct usb_device *udev, int enable) |
4088 | { | 4049 | { |
4089 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 4050 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
@@ -4207,7 +4168,7 @@ static int xhci_check_usb2_port_capability(struct xhci_hcd *xhci, int port, | |||
4207 | return 0; | 4168 | return 0; |
4208 | } | 4169 | } |
4209 | 4170 | ||
4210 | int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev) | 4171 | static int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev) |
4211 | { | 4172 | { |
4212 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 4173 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
4213 | int portnum = udev->portnum - 1; | 4174 | int portnum = udev->portnum - 1; |
@@ -4616,7 +4577,7 @@ static int calculate_max_exit_latency(struct usb_device *udev, | |||
4616 | } | 4577 | } |
4617 | 4578 | ||
4618 | /* Returns the USB3 hub-encoded value for the U1/U2 timeout. */ | 4579 | /* Returns the USB3 hub-encoded value for the U1/U2 timeout. */ |
4619 | int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd, | 4580 | static int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd, |
4620 | struct usb_device *udev, enum usb3_link_state state) | 4581 | struct usb_device *udev, enum usb3_link_state state) |
4621 | { | 4582 | { |
4622 | struct xhci_hcd *xhci; | 4583 | struct xhci_hcd *xhci; |
@@ -4647,7 +4608,7 @@ int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd, | |||
4647 | return hub_encoded_timeout; | 4608 | return hub_encoded_timeout; |
4648 | } | 4609 | } |
4649 | 4610 | ||
4650 | int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd, | 4611 | static int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd, |
4651 | struct usb_device *udev, enum usb3_link_state state) | 4612 | struct usb_device *udev, enum usb3_link_state state) |
4652 | { | 4613 | { |
4653 | struct xhci_hcd *xhci; | 4614 | struct xhci_hcd *xhci; |
@@ -4663,24 +4624,24 @@ int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd, | |||
4663 | } | 4624 | } |
4664 | #else /* CONFIG_PM */ | 4625 | #else /* CONFIG_PM */ |
4665 | 4626 | ||
4666 | int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, | 4627 | static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, |
4667 | struct usb_device *udev, int enable) | 4628 | struct usb_device *udev, int enable) |
4668 | { | 4629 | { |
4669 | return 0; | 4630 | return 0; |
4670 | } | 4631 | } |
4671 | 4632 | ||
4672 | int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev) | 4633 | static int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev) |
4673 | { | 4634 | { |
4674 | return 0; | 4635 | return 0; |
4675 | } | 4636 | } |
4676 | 4637 | ||
4677 | int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd, | 4638 | static int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd, |
4678 | struct usb_device *udev, enum usb3_link_state state) | 4639 | struct usb_device *udev, enum usb3_link_state state) |
4679 | { | 4640 | { |
4680 | return USB3_LPM_DISABLED; | 4641 | return USB3_LPM_DISABLED; |
4681 | } | 4642 | } |
4682 | 4643 | ||
4683 | int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd, | 4644 | static int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd, |
4684 | struct usb_device *udev, enum usb3_link_state state) | 4645 | struct usb_device *udev, enum usb3_link_state state) |
4685 | { | 4646 | { |
4686 | return 0; | 4647 | return 0; |
@@ -4692,7 +4653,7 @@ int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd, | |||
4692 | /* Once a hub descriptor is fetched for a device, we need to update the xHC's | 4653 | /* Once a hub descriptor is fetched for a device, we need to update the xHC's |
4693 | * internal data structures for the device. | 4654 | * internal data structures for the device. |
4694 | */ | 4655 | */ |
4695 | int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, | 4656 | static int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, |
4696 | struct usb_tt *tt, gfp_t mem_flags) | 4657 | struct usb_tt *tt, gfp_t mem_flags) |
4697 | { | 4658 | { |
4698 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 4659 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
@@ -4713,11 +4674,11 @@ int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, | |||
4713 | xhci_warn(xhci, "Cannot update hub desc for unknown device.\n"); | 4674 | xhci_warn(xhci, "Cannot update hub desc for unknown device.\n"); |
4714 | return -EINVAL; | 4675 | return -EINVAL; |
4715 | } | 4676 | } |
4677 | |||
4716 | config_cmd = xhci_alloc_command(xhci, true, true, mem_flags); | 4678 | config_cmd = xhci_alloc_command(xhci, true, true, mem_flags); |
4717 | if (!config_cmd) { | 4679 | if (!config_cmd) |
4718 | xhci_dbg(xhci, "Could not allocate xHCI command structure.\n"); | ||
4719 | return -ENOMEM; | 4680 | return -ENOMEM; |
4720 | } | 4681 | |
4721 | ctrl_ctx = xhci_get_input_control_ctx(config_cmd->in_ctx); | 4682 | ctrl_ctx = xhci_get_input_control_ctx(config_cmd->in_ctx); |
4722 | if (!ctrl_ctx) { | 4683 | if (!ctrl_ctx) { |
4723 | xhci_warn(xhci, "%s: Could not get input context, bad type.\n", | 4684 | xhci_warn(xhci, "%s: Could not get input context, bad type.\n", |
@@ -4778,8 +4739,6 @@ int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, | |||
4778 | xhci_dbg(xhci, "Set up %s for hub device.\n", | 4739 | xhci_dbg(xhci, "Set up %s for hub device.\n", |
4779 | (xhci->hci_version > 0x95) ? | 4740 | (xhci->hci_version > 0x95) ? |
4780 | "configure endpoint" : "evaluate context"); | 4741 | "configure endpoint" : "evaluate context"); |
4781 | xhci_dbg(xhci, "Slot %u Input Context:\n", hdev->slot_id); | ||
4782 | xhci_dbg_ctx(xhci, config_cmd->in_ctx, 0); | ||
4783 | 4742 | ||
4784 | /* Issue and wait for the configure endpoint or | 4743 | /* Issue and wait for the configure endpoint or |
4785 | * evaluate context command. | 4744 | * evaluate context command. |
@@ -4791,14 +4750,11 @@ int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, | |||
4791 | ret = xhci_configure_endpoint(xhci, hdev, config_cmd, | 4750 | ret = xhci_configure_endpoint(xhci, hdev, config_cmd, |
4792 | true, false); | 4751 | true, false); |
4793 | 4752 | ||
4794 | xhci_dbg(xhci, "Slot %u Output Context:\n", hdev->slot_id); | ||
4795 | xhci_dbg_ctx(xhci, vdev->out_ctx, 0); | ||
4796 | |||
4797 | xhci_free_command(xhci, config_cmd); | 4753 | xhci_free_command(xhci, config_cmd); |
4798 | return ret; | 4754 | return ret; |
4799 | } | 4755 | } |
4800 | 4756 | ||
4801 | int xhci_get_frame(struct usb_hcd *hcd) | 4757 | static int xhci_get_frame(struct usb_hcd *hcd) |
4802 | { | 4758 | { |
4803 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 4759 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
4804 | /* EHCI mods by the periodic size. Why? */ | 4760 | /* EHCI mods by the periodic size. Why? */ |
@@ -4808,7 +4764,11 @@ int xhci_get_frame(struct usb_hcd *hcd) | |||
4808 | int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) | 4764 | int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) |
4809 | { | 4765 | { |
4810 | struct xhci_hcd *xhci; | 4766 | struct xhci_hcd *xhci; |
4811 | struct device *dev = hcd->self.controller; | 4767 | /* |
4768 | * TODO: Check with DWC3 clients for sysdev according to | ||
4769 | * quirks | ||
4770 | */ | ||
4771 | struct device *dev = hcd->self.sysdev; | ||
4812 | int retval; | 4772 | int retval; |
4813 | 4773 | ||
4814 | /* Accept arbitrarily long scatter-gather lists */ | 4774 | /* Accept arbitrarily long scatter-gather lists */ |
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index da3eb695fe54..73a28a986d5e 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h | |||
@@ -425,6 +425,7 @@ struct xhci_op_regs { | |||
425 | #define PORT_L1DS_MASK (0xff << 8) | 425 | #define PORT_L1DS_MASK (0xff << 8) |
426 | #define PORT_L1DS(p) (((p) & 0xff) << 8) | 426 | #define PORT_L1DS(p) (((p) & 0xff) << 8) |
427 | #define PORT_HLE (1 << 16) | 427 | #define PORT_HLE (1 << 16) |
428 | #define PORT_TEST_MODE_SHIFT 28 | ||
428 | 429 | ||
429 | /* USB3 Protocol PORTLI Port Link Information */ | 430 | /* USB3 Protocol PORTLI Port Link Information */ |
430 | #define PORT_RX_LANES(p) (((p) >> 16) & 0xf) | 431 | #define PORT_RX_LANES(p) (((p) >> 16) & 0xf) |
@@ -617,6 +618,7 @@ struct xhci_slot_ctx { | |||
617 | #define ROUTE_STRING_MASK (0xfffff) | 618 | #define ROUTE_STRING_MASK (0xfffff) |
618 | /* Device speed - values defined by PORTSC Device Speed field - 20:23 */ | 619 | /* Device speed - values defined by PORTSC Device Speed field - 20:23 */ |
619 | #define DEV_SPEED (0xf << 20) | 620 | #define DEV_SPEED (0xf << 20) |
621 | #define GET_DEV_SPEED(n) (((n) & DEV_SPEED) >> 20) | ||
620 | /* bit 24 reserved */ | 622 | /* bit 24 reserved */ |
621 | /* Is this LS/FS device connected through a HS hub? - bit 25 */ | 623 | /* Is this LS/FS device connected through a HS hub? - bit 25 */ |
622 | #define DEV_MTT (0x1 << 25) | 624 | #define DEV_MTT (0x1 << 25) |
@@ -637,6 +639,7 @@ struct xhci_slot_ctx { | |||
637 | #define DEVINFO_TO_ROOT_HUB_PORT(p) (((p) >> 16) & 0xff) | 639 | #define DEVINFO_TO_ROOT_HUB_PORT(p) (((p) >> 16) & 0xff) |
638 | /* Maximum number of ports under a hub device */ | 640 | /* Maximum number of ports under a hub device */ |
639 | #define XHCI_MAX_PORTS(p) (((p) & 0xff) << 24) | 641 | #define XHCI_MAX_PORTS(p) (((p) & 0xff) << 24) |
642 | #define DEVINFO_TO_MAX_PORTS(p) (((p) & (0xff << 24)) >> 24) | ||
640 | 643 | ||
641 | /* tt_info bitmasks */ | 644 | /* tt_info bitmasks */ |
642 | /* | 645 | /* |
@@ -651,6 +654,7 @@ struct xhci_slot_ctx { | |||
651 | */ | 654 | */ |
652 | #define TT_PORT (0xff << 8) | 655 | #define TT_PORT (0xff << 8) |
653 | #define TT_THINK_TIME(p) (((p) & 0x3) << 16) | 656 | #define TT_THINK_TIME(p) (((p) & 0x3) << 16) |
657 | #define GET_TT_THINK_TIME(p) (((p) & (0x3 << 16)) >> 16) | ||
654 | 658 | ||
655 | /* dev_state bitmasks */ | 659 | /* dev_state bitmasks */ |
656 | /* USB device address - assigned by the HC */ | 660 | /* USB device address - assigned by the HC */ |
@@ -1562,10 +1566,8 @@ struct xhci_ring { | |||
1562 | struct xhci_segment *last_seg; | 1566 | struct xhci_segment *last_seg; |
1563 | union xhci_trb *enqueue; | 1567 | union xhci_trb *enqueue; |
1564 | struct xhci_segment *enq_seg; | 1568 | struct xhci_segment *enq_seg; |
1565 | unsigned int enq_updates; | ||
1566 | union xhci_trb *dequeue; | 1569 | union xhci_trb *dequeue; |
1567 | struct xhci_segment *deq_seg; | 1570 | struct xhci_segment *deq_seg; |
1568 | unsigned int deq_updates; | ||
1569 | struct list_head td_list; | 1571 | struct list_head td_list; |
1570 | /* | 1572 | /* |
1571 | * Write the cycle state into the TRB cycle field to give ownership of | 1573 | * Write the cycle state into the TRB cycle field to give ownership of |
@@ -1604,7 +1606,6 @@ struct xhci_scratchpad { | |||
1604 | u64 *sp_array; | 1606 | u64 *sp_array; |
1605 | dma_addr_t sp_dma; | 1607 | dma_addr_t sp_dma; |
1606 | void **sp_buffers; | 1608 | void **sp_buffers; |
1607 | dma_addr_t *sp_dma_buffers; | ||
1608 | }; | 1609 | }; |
1609 | 1610 | ||
1610 | struct urb_priv { | 1611 | struct urb_priv { |
@@ -1722,7 +1723,6 @@ struct xhci_hcd { | |||
1722 | int page_shift; | 1723 | int page_shift; |
1723 | /* msi-x vectors */ | 1724 | /* msi-x vectors */ |
1724 | int msix_count; | 1725 | int msix_count; |
1725 | struct msix_entry *msix_entries; | ||
1726 | /* optional clock */ | 1726 | /* optional clock */ |
1727 | struct clk *clk; | 1727 | struct clk *clk; |
1728 | /* data structures */ | 1728 | /* data structures */ |
@@ -1818,6 +1818,7 @@ struct xhci_hcd { | |||
1818 | #define XHCI_MISSING_CAS (1 << 24) | 1818 | #define XHCI_MISSING_CAS (1 << 24) |
1819 | /* For controller with a broken Port Disable implementation */ | 1819 | /* For controller with a broken Port Disable implementation */ |
1820 | #define XHCI_BROKEN_PORT_PED (1 << 25) | 1820 | #define XHCI_BROKEN_PORT_PED (1 << 25) |
1821 | #define XHCI_LIMIT_ENDPOINT_INTERVAL_7 (1 << 26) | ||
1821 | 1822 | ||
1822 | unsigned int num_active_eps; | 1823 | unsigned int num_active_eps; |
1823 | unsigned int limit_active_eps; | 1824 | unsigned int limit_active_eps; |
@@ -1843,6 +1844,7 @@ struct xhci_hcd { | |||
1843 | /* Compliance Mode Recovery Data */ | 1844 | /* Compliance Mode Recovery Data */ |
1844 | struct timer_list comp_mode_recovery_timer; | 1845 | struct timer_list comp_mode_recovery_timer; |
1845 | u32 port_status_u0; | 1846 | u32 port_status_u0; |
1847 | u16 test_mode; | ||
1846 | /* Compliance Mode Timer Triggered every 2 seconds */ | 1848 | /* Compliance Mode Timer Triggered every 2 seconds */ |
1847 | #define COMP_MODE_RCVRY_MSECS 2000 | 1849 | #define COMP_MODE_RCVRY_MSECS 2000 |
1848 | 1850 | ||
@@ -1918,19 +1920,10 @@ void xhci_print_ir_set(struct xhci_hcd *xhci, int set_num); | |||
1918 | void xhci_print_registers(struct xhci_hcd *xhci); | 1920 | void xhci_print_registers(struct xhci_hcd *xhci); |
1919 | void xhci_dbg_regs(struct xhci_hcd *xhci); | 1921 | void xhci_dbg_regs(struct xhci_hcd *xhci); |
1920 | void xhci_print_run_regs(struct xhci_hcd *xhci); | 1922 | void xhci_print_run_regs(struct xhci_hcd *xhci); |
1921 | void xhci_print_trb_offsets(struct xhci_hcd *xhci, union xhci_trb *trb); | ||
1922 | void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb); | ||
1923 | void xhci_debug_segment(struct xhci_hcd *xhci, struct xhci_segment *seg); | ||
1924 | void xhci_debug_ring(struct xhci_hcd *xhci, struct xhci_ring *ring); | ||
1925 | void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst); | 1923 | void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst); |
1926 | void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci); | 1924 | void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci); |
1927 | void xhci_dbg_ring_ptrs(struct xhci_hcd *xhci, struct xhci_ring *ring); | ||
1928 | void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int last_ep); | ||
1929 | char *xhci_get_slot_state(struct xhci_hcd *xhci, | 1925 | char *xhci_get_slot_state(struct xhci_hcd *xhci, |
1930 | struct xhci_container_ctx *ctx); | 1926 | struct xhci_container_ctx *ctx); |
1931 | void xhci_dbg_ep_rings(struct xhci_hcd *xhci, | ||
1932 | unsigned int slot_id, unsigned int ep_index, | ||
1933 | struct xhci_virt_ep *ep); | ||
1934 | void xhci_dbg_trace(struct xhci_hcd *xhci, void (*trace)(struct va_format *), | 1927 | void xhci_dbg_trace(struct xhci_hcd *xhci, void (*trace)(struct va_format *), |
1935 | const char *fmt, ...); | 1928 | const char *fmt, ...); |
1936 | 1929 | ||
@@ -1944,16 +1937,8 @@ void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci, | |||
1944 | struct usb_device *udev); | 1937 | struct usb_device *udev); |
1945 | unsigned int xhci_get_endpoint_index(struct usb_endpoint_descriptor *desc); | 1938 | unsigned int xhci_get_endpoint_index(struct usb_endpoint_descriptor *desc); |
1946 | unsigned int xhci_get_endpoint_address(unsigned int ep_index); | 1939 | unsigned int xhci_get_endpoint_address(unsigned int ep_index); |
1947 | unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc); | ||
1948 | unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index); | ||
1949 | unsigned int xhci_last_valid_endpoint(u32 added_ctxs); | 1940 | unsigned int xhci_last_valid_endpoint(u32 added_ctxs); |
1950 | void xhci_endpoint_zero(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, struct usb_host_endpoint *ep); | 1941 | void xhci_endpoint_zero(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, struct usb_host_endpoint *ep); |
1951 | void xhci_drop_ep_from_interval_table(struct xhci_hcd *xhci, | ||
1952 | struct xhci_bw_info *ep_bw, | ||
1953 | struct xhci_interval_bw_table *bw_table, | ||
1954 | struct usb_device *udev, | ||
1955 | struct xhci_virt_ep *virt_ep, | ||
1956 | struct xhci_tt_bw_info *tt_info); | ||
1957 | void xhci_update_tt_active_eps(struct xhci_hcd *xhci, | 1942 | void xhci_update_tt_active_eps(struct xhci_hcd *xhci, |
1958 | struct xhci_virt_device *virt_dev, | 1943 | struct xhci_virt_device *virt_dev, |
1959 | int old_active_eps); | 1944 | int old_active_eps); |
@@ -2010,53 +1995,25 @@ typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *); | |||
2010 | int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec); | 1995 | int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec); |
2011 | void xhci_quiesce(struct xhci_hcd *xhci); | 1996 | void xhci_quiesce(struct xhci_hcd *xhci); |
2012 | int xhci_halt(struct xhci_hcd *xhci); | 1997 | int xhci_halt(struct xhci_hcd *xhci); |
1998 | int xhci_start(struct xhci_hcd *xhci); | ||
2013 | int xhci_reset(struct xhci_hcd *xhci); | 1999 | int xhci_reset(struct xhci_hcd *xhci); |
2014 | int xhci_init(struct usb_hcd *hcd); | ||
2015 | int xhci_run(struct usb_hcd *hcd); | 2000 | int xhci_run(struct usb_hcd *hcd); |
2016 | void xhci_stop(struct usb_hcd *hcd); | ||
2017 | void xhci_shutdown(struct usb_hcd *hcd); | ||
2018 | int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks); | 2001 | int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks); |
2019 | void xhci_init_driver(struct hc_driver *drv, | 2002 | void xhci_init_driver(struct hc_driver *drv, |
2020 | const struct xhci_driver_overrides *over); | 2003 | const struct xhci_driver_overrides *over); |
2004 | int xhci_disable_slot(struct xhci_hcd *xhci, | ||
2005 | struct xhci_command *command, u32 slot_id); | ||
2021 | 2006 | ||
2022 | #ifdef CONFIG_PM | ||
2023 | int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup); | 2007 | int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup); |
2024 | int xhci_resume(struct xhci_hcd *xhci, bool hibernated); | 2008 | int xhci_resume(struct xhci_hcd *xhci, bool hibernated); |
2025 | #else | ||
2026 | #define xhci_suspend NULL | ||
2027 | #define xhci_resume NULL | ||
2028 | #endif | ||
2029 | 2009 | ||
2030 | int xhci_get_frame(struct usb_hcd *hcd); | ||
2031 | irqreturn_t xhci_irq(struct usb_hcd *hcd); | 2010 | irqreturn_t xhci_irq(struct usb_hcd *hcd); |
2032 | irqreturn_t xhci_msi_irq(int irq, void *hcd); | 2011 | irqreturn_t xhci_msi_irq(int irq, void *hcd); |
2033 | int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev); | 2012 | int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev); |
2034 | void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev); | ||
2035 | int xhci_alloc_tt_info(struct xhci_hcd *xhci, | 2013 | int xhci_alloc_tt_info(struct xhci_hcd *xhci, |
2036 | struct xhci_virt_device *virt_dev, | 2014 | struct xhci_virt_device *virt_dev, |
2037 | struct usb_device *hdev, | 2015 | struct usb_device *hdev, |
2038 | struct usb_tt *tt, gfp_t mem_flags); | 2016 | struct usb_tt *tt, gfp_t mem_flags); |
2039 | int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev, | ||
2040 | struct usb_host_endpoint **eps, unsigned int num_eps, | ||
2041 | unsigned int num_streams, gfp_t mem_flags); | ||
2042 | int xhci_free_streams(struct usb_hcd *hcd, struct usb_device *udev, | ||
2043 | struct usb_host_endpoint **eps, unsigned int num_eps, | ||
2044 | gfp_t mem_flags); | ||
2045 | int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev); | ||
2046 | int xhci_enable_device(struct usb_hcd *hcd, struct usb_device *udev); | ||
2047 | int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev); | ||
2048 | int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, | ||
2049 | struct usb_device *udev, int enable); | ||
2050 | int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, | ||
2051 | struct usb_tt *tt, gfp_t mem_flags); | ||
2052 | int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags); | ||
2053 | int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status); | ||
2054 | int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep); | ||
2055 | int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep); | ||
2056 | void xhci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep); | ||
2057 | int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev); | ||
2058 | int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev); | ||
2059 | void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev); | ||
2060 | 2017 | ||
2061 | /* xHCI ring, segment, TRB, and TD functions */ | 2018 | /* xHCI ring, segment, TRB, and TD functions */ |
2062 | dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, union xhci_trb *trb); | 2019 | dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, union xhci_trb *trb); |
@@ -2100,9 +2057,6 @@ void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci, | |||
2100 | struct xhci_dequeue_state *deq_state); | 2057 | struct xhci_dequeue_state *deq_state); |
2101 | void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, | 2058 | void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, |
2102 | unsigned int ep_index, struct xhci_td *td); | 2059 | unsigned int ep_index, struct xhci_td *td); |
2103 | void xhci_queue_config_ep_quirk(struct xhci_hcd *xhci, | ||
2104 | unsigned int slot_id, unsigned int ep_index, | ||
2105 | struct xhci_dequeue_state *deq_state); | ||
2106 | void xhci_stop_endpoint_command_watchdog(unsigned long arg); | 2060 | void xhci_stop_endpoint_command_watchdog(unsigned long arg); |
2107 | void xhci_handle_command_timeout(struct work_struct *work); | 2061 | void xhci_handle_command_timeout(struct work_struct *work); |
2108 | 2062 | ||
@@ -2113,16 +2067,13 @@ void xhci_cleanup_command_queue(struct xhci_hcd *xhci); | |||
2113 | /* xHCI roothub code */ | 2067 | /* xHCI roothub code */ |
2114 | void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array, | 2068 | void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array, |
2115 | int port_id, u32 link_state); | 2069 | int port_id, u32 link_state); |
2116 | int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd, | ||
2117 | struct usb_device *udev, enum usb3_link_state state); | ||
2118 | int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd, | ||
2119 | struct usb_device *udev, enum usb3_link_state state); | ||
2120 | void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array, | 2070 | void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array, |
2121 | int port_id, u32 port_bit); | 2071 | int port_id, u32 port_bit); |
2122 | int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, | 2072 | int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, |
2123 | char *buf, u16 wLength); | 2073 | char *buf, u16 wLength); |
2124 | int xhci_hub_status_data(struct usb_hcd *hcd, char *buf); | 2074 | int xhci_hub_status_data(struct usb_hcd *hcd, char *buf); |
2125 | int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1); | 2075 | int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1); |
2076 | void xhci_hc_died(struct xhci_hcd *xhci); | ||
2126 | 2077 | ||
2127 | #ifdef CONFIG_PM | 2078 | #ifdef CONFIG_PM |
2128 | int xhci_bus_suspend(struct usb_hcd *hcd); | 2079 | int xhci_bus_suspend(struct usb_hcd *hcd); |
@@ -2153,6 +2104,22 @@ static inline struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, | |||
2153 | urb->stream_id); | 2104 | urb->stream_id); |
2154 | } | 2105 | } |
2155 | 2106 | ||
2107 | static inline char *xhci_slot_state_string(u32 state) | ||
2108 | { | ||
2109 | switch (state) { | ||
2110 | case SLOT_STATE_ENABLED: | ||
2111 | return "enabled/disabled"; | ||
2112 | case SLOT_STATE_DEFAULT: | ||
2113 | return "default"; | ||
2114 | case SLOT_STATE_ADDRESSED: | ||
2115 | return "addressed"; | ||
2116 | case SLOT_STATE_CONFIGURED: | ||
2117 | return "configured"; | ||
2118 | default: | ||
2119 | return "reserved"; | ||
2120 | } | ||
2121 | } | ||
2122 | |||
2156 | static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2, | 2123 | static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2, |
2157 | u32 field3) | 2124 | u32 field3) |
2158 | { | 2125 | { |
@@ -2162,14 +2129,12 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2, | |||
2162 | switch (type) { | 2129 | switch (type) { |
2163 | case TRB_LINK: | 2130 | case TRB_LINK: |
2164 | sprintf(str, | 2131 | sprintf(str, |
2165 | "TRB %08x%08x status '%s' len %d slot %d ep %d type '%s' flags %c:%c", | 2132 | "LINK %08x%08x intr %d type '%s' flags %c:%c:%c:%c", |
2166 | field1, field0, | 2133 | field1, field0, GET_INTR_TARGET(field2), |
2167 | xhci_trb_comp_code_string(GET_COMP_CODE(field2)), | 2134 | xhci_trb_type_string(type), |
2168 | EVENT_TRB_LEN(field2), TRB_TO_SLOT_ID(field3), | 2135 | field3 & TRB_IOC ? 'I' : 'i', |
2169 | /* Macro decrements 1, maybe it shouldn't?!? */ | 2136 | field3 & TRB_CHAIN ? 'C' : 'c', |
2170 | TRB_TO_EP_INDEX(field3) + 1, | 2137 | field3 & TRB_TC ? 'T' : 't', |
2171 | xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)), | ||
2172 | field3 & EVENT_DATA ? 'E' : 'e', | ||
2173 | field3 & TRB_CYCLE ? 'C' : 'c'); | 2138 | field3 & TRB_CYCLE ? 'C' : 'c'); |
2174 | break; | 2139 | break; |
2175 | case TRB_TRANSFER: | 2140 | case TRB_TRANSFER: |
@@ -2187,37 +2152,52 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2, | |||
2187 | EVENT_TRB_LEN(field2), TRB_TO_SLOT_ID(field3), | 2152 | EVENT_TRB_LEN(field2), TRB_TO_SLOT_ID(field3), |
2188 | /* Macro decrements 1, maybe it shouldn't?!? */ | 2153 | /* Macro decrements 1, maybe it shouldn't?!? */ |
2189 | TRB_TO_EP_INDEX(field3) + 1, | 2154 | TRB_TO_EP_INDEX(field3) + 1, |
2190 | xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)), | 2155 | xhci_trb_type_string(type), |
2191 | field3 & EVENT_DATA ? 'E' : 'e', | 2156 | field3 & EVENT_DATA ? 'E' : 'e', |
2192 | field3 & TRB_CYCLE ? 'C' : 'c'); | 2157 | field3 & TRB_CYCLE ? 'C' : 'c'); |
2193 | 2158 | ||
2194 | break; | 2159 | break; |
2195 | case TRB_SETUP: | 2160 | case TRB_SETUP: |
2196 | sprintf(str, | 2161 | sprintf(str, "bRequestType %02x bRequest %02x wValue %02x%02x wIndex %02x%02x wLength %d length %d TD size %d intr %d type '%s' flags %c:%c:%c", |
2197 | "bRequestType %02x bRequest %02x wValue %02x%02x wIndex %02x%02x wLength %d length %d TD size %d intr %d type '%s' flags %c:%c:%c:%c:%c:%c:%c:%c", | 2162 | field0 & 0xff, |
2198 | field0 & 0xff, | 2163 | (field0 & 0xff00) >> 8, |
2199 | (field0 & 0xff00) >> 8, | 2164 | (field0 & 0xff000000) >> 24, |
2200 | (field0 & 0xff000000) >> 24, | 2165 | (field0 & 0xff0000) >> 16, |
2201 | (field0 & 0xff0000) >> 16, | 2166 | (field1 & 0xff00) >> 8, |
2202 | (field1 & 0xff00) >> 8, | 2167 | field1 & 0xff, |
2203 | field1 & 0xff, | 2168 | (field1 & 0xff000000) >> 16 | |
2204 | (field1 & 0xff000000) >> 16 | | 2169 | (field1 & 0xff0000) >> 16, |
2205 | (field1 & 0xff0000) >> 16, | 2170 | TRB_LEN(field2), GET_TD_SIZE(field2), |
2206 | TRB_LEN(field2), GET_TD_SIZE(field2), | 2171 | GET_INTR_TARGET(field2), |
2207 | GET_INTR_TARGET(field2), | 2172 | xhci_trb_type_string(type), |
2208 | xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)), | 2173 | field3 & TRB_IDT ? 'I' : 'i', |
2209 | field3 & TRB_BEI ? 'B' : 'b', | 2174 | field3 & TRB_IOC ? 'I' : 'i', |
2210 | field3 & TRB_IDT ? 'I' : 'i', | 2175 | field3 & TRB_CYCLE ? 'C' : 'c'); |
2211 | field3 & TRB_IOC ? 'I' : 'i', | ||
2212 | field3 & TRB_CHAIN ? 'C' : 'c', | ||
2213 | field3 & TRB_NO_SNOOP ? 'S' : 's', | ||
2214 | field3 & TRB_ISP ? 'I' : 'i', | ||
2215 | field3 & TRB_ENT ? 'E' : 'e', | ||
2216 | field3 & TRB_CYCLE ? 'C' : 'c'); | ||
2217 | break; | 2176 | break; |
2218 | case TRB_NORMAL: | ||
2219 | case TRB_DATA: | 2177 | case TRB_DATA: |
2178 | sprintf(str, "Buffer %08x%08x length %d TD size %d intr %d type '%s' flags %c:%c:%c:%c:%c:%c:%c", | ||
2179 | field1, field0, TRB_LEN(field2), GET_TD_SIZE(field2), | ||
2180 | GET_INTR_TARGET(field2), | ||
2181 | xhci_trb_type_string(type), | ||
2182 | field3 & TRB_IDT ? 'I' : 'i', | ||
2183 | field3 & TRB_IOC ? 'I' : 'i', | ||
2184 | field3 & TRB_CHAIN ? 'C' : 'c', | ||
2185 | field3 & TRB_NO_SNOOP ? 'S' : 's', | ||
2186 | field3 & TRB_ISP ? 'I' : 'i', | ||
2187 | field3 & TRB_ENT ? 'E' : 'e', | ||
2188 | field3 & TRB_CYCLE ? 'C' : 'c'); | ||
2189 | break; | ||
2220 | case TRB_STATUS: | 2190 | case TRB_STATUS: |
2191 | sprintf(str, "Buffer %08x%08x length %d TD size %d intr %d type '%s' flags %c:%c:%c:%c", | ||
2192 | field1, field0, TRB_LEN(field2), GET_TD_SIZE(field2), | ||
2193 | GET_INTR_TARGET(field2), | ||
2194 | xhci_trb_type_string(type), | ||
2195 | field3 & TRB_IOC ? 'I' : 'i', | ||
2196 | field3 & TRB_CHAIN ? 'C' : 'c', | ||
2197 | field3 & TRB_ENT ? 'E' : 'e', | ||
2198 | field3 & TRB_CYCLE ? 'C' : 'c'); | ||
2199 | break; | ||
2200 | case TRB_NORMAL: | ||
2221 | case TRB_ISOC: | 2201 | case TRB_ISOC: |
2222 | case TRB_EVENT_DATA: | 2202 | case TRB_EVENT_DATA: |
2223 | case TRB_TR_NOOP: | 2203 | case TRB_TR_NOOP: |
@@ -2225,7 +2205,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2, | |||
2225 | "Buffer %08x%08x length %d TD size %d intr %d type '%s' flags %c:%c:%c:%c:%c:%c:%c:%c", | 2205 | "Buffer %08x%08x length %d TD size %d intr %d type '%s' flags %c:%c:%c:%c:%c:%c:%c:%c", |
2226 | field1, field0, TRB_LEN(field2), GET_TD_SIZE(field2), | 2206 | field1, field0, TRB_LEN(field2), GET_TD_SIZE(field2), |
2227 | GET_INTR_TARGET(field2), | 2207 | GET_INTR_TARGET(field2), |
2228 | xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)), | 2208 | xhci_trb_type_string(type), |
2229 | field3 & TRB_BEI ? 'B' : 'b', | 2209 | field3 & TRB_BEI ? 'B' : 'b', |
2230 | field3 & TRB_IDT ? 'I' : 'i', | 2210 | field3 & TRB_IDT ? 'I' : 'i', |
2231 | field3 & TRB_IOC ? 'I' : 'i', | 2211 | field3 & TRB_IOC ? 'I' : 'i', |
@@ -2240,21 +2220,21 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2, | |||
2240 | case TRB_ENABLE_SLOT: | 2220 | case TRB_ENABLE_SLOT: |
2241 | sprintf(str, | 2221 | sprintf(str, |
2242 | "%s: flags %c", | 2222 | "%s: flags %c", |
2243 | xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)), | 2223 | xhci_trb_type_string(type), |
2244 | field3 & TRB_CYCLE ? 'C' : 'c'); | 2224 | field3 & TRB_CYCLE ? 'C' : 'c'); |
2245 | break; | 2225 | break; |
2246 | case TRB_DISABLE_SLOT: | 2226 | case TRB_DISABLE_SLOT: |
2247 | case TRB_NEG_BANDWIDTH: | 2227 | case TRB_NEG_BANDWIDTH: |
2248 | sprintf(str, | 2228 | sprintf(str, |
2249 | "%s: slot %d flags %c", | 2229 | "%s: slot %d flags %c", |
2250 | xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)), | 2230 | xhci_trb_type_string(type), |
2251 | TRB_TO_SLOT_ID(field3), | 2231 | TRB_TO_SLOT_ID(field3), |
2252 | field3 & TRB_CYCLE ? 'C' : 'c'); | 2232 | field3 & TRB_CYCLE ? 'C' : 'c'); |
2253 | break; | 2233 | break; |
2254 | case TRB_ADDR_DEV: | 2234 | case TRB_ADDR_DEV: |
2255 | sprintf(str, | 2235 | sprintf(str, |
2256 | "%s: ctx %08x%08x slot %d flags %c:%c", | 2236 | "%s: ctx %08x%08x slot %d flags %c:%c", |
2257 | xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)), | 2237 | xhci_trb_type_string(type), |
2258 | field1, field0, | 2238 | field1, field0, |
2259 | TRB_TO_SLOT_ID(field3), | 2239 | TRB_TO_SLOT_ID(field3), |
2260 | field3 & TRB_BSR ? 'B' : 'b', | 2240 | field3 & TRB_BSR ? 'B' : 'b', |
@@ -2263,7 +2243,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2, | |||
2263 | case TRB_CONFIG_EP: | 2243 | case TRB_CONFIG_EP: |
2264 | sprintf(str, | 2244 | sprintf(str, |
2265 | "%s: ctx %08x%08x slot %d flags %c:%c", | 2245 | "%s: ctx %08x%08x slot %d flags %c:%c", |
2266 | xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)), | 2246 | xhci_trb_type_string(type), |
2267 | field1, field0, | 2247 | field1, field0, |
2268 | TRB_TO_SLOT_ID(field3), | 2248 | TRB_TO_SLOT_ID(field3), |
2269 | field3 & TRB_DC ? 'D' : 'd', | 2249 | field3 & TRB_DC ? 'D' : 'd', |
@@ -2272,7 +2252,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2, | |||
2272 | case TRB_EVAL_CONTEXT: | 2252 | case TRB_EVAL_CONTEXT: |
2273 | sprintf(str, | 2253 | sprintf(str, |
2274 | "%s: ctx %08x%08x slot %d flags %c", | 2254 | "%s: ctx %08x%08x slot %d flags %c", |
2275 | xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)), | 2255 | xhci_trb_type_string(type), |
2276 | field1, field0, | 2256 | field1, field0, |
2277 | TRB_TO_SLOT_ID(field3), | 2257 | TRB_TO_SLOT_ID(field3), |
2278 | field3 & TRB_CYCLE ? 'C' : 'c'); | 2258 | field3 & TRB_CYCLE ? 'C' : 'c'); |
@@ -2280,7 +2260,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2, | |||
2280 | case TRB_RESET_EP: | 2260 | case TRB_RESET_EP: |
2281 | sprintf(str, | 2261 | sprintf(str, |
2282 | "%s: ctx %08x%08x slot %d ep %d flags %c", | 2262 | "%s: ctx %08x%08x slot %d ep %d flags %c", |
2283 | xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)), | 2263 | xhci_trb_type_string(type), |
2284 | field1, field0, | 2264 | field1, field0, |
2285 | TRB_TO_SLOT_ID(field3), | 2265 | TRB_TO_SLOT_ID(field3), |
2286 | /* Macro decrements 1, maybe it shouldn't?!? */ | 2266 | /* Macro decrements 1, maybe it shouldn't?!? */ |
@@ -2290,7 +2270,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2, | |||
2290 | case TRB_STOP_RING: | 2270 | case TRB_STOP_RING: |
2291 | sprintf(str, | 2271 | sprintf(str, |
2292 | "%s: slot %d sp %d ep %d flags %c", | 2272 | "%s: slot %d sp %d ep %d flags %c", |
2293 | xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)), | 2273 | xhci_trb_type_string(type), |
2294 | TRB_TO_SLOT_ID(field3), | 2274 | TRB_TO_SLOT_ID(field3), |
2295 | TRB_TO_SUSPEND_PORT(field3), | 2275 | TRB_TO_SUSPEND_PORT(field3), |
2296 | /* Macro decrements 1, maybe it shouldn't?!? */ | 2276 | /* Macro decrements 1, maybe it shouldn't?!? */ |
@@ -2300,7 +2280,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2, | |||
2300 | case TRB_SET_DEQ: | 2280 | case TRB_SET_DEQ: |
2301 | sprintf(str, | 2281 | sprintf(str, |
2302 | "%s: deq %08x%08x stream %d slot %d ep %d flags %c", | 2282 | "%s: deq %08x%08x stream %d slot %d ep %d flags %c", |
2303 | xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)), | 2283 | xhci_trb_type_string(type), |
2304 | field1, field0, | 2284 | field1, field0, |
2305 | TRB_TO_STREAM_ID(field2), | 2285 | TRB_TO_STREAM_ID(field2), |
2306 | TRB_TO_SLOT_ID(field3), | 2286 | TRB_TO_SLOT_ID(field3), |
@@ -2311,14 +2291,14 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2, | |||
2311 | case TRB_RESET_DEV: | 2291 | case TRB_RESET_DEV: |
2312 | sprintf(str, | 2292 | sprintf(str, |
2313 | "%s: slot %d flags %c", | 2293 | "%s: slot %d flags %c", |
2314 | xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)), | 2294 | xhci_trb_type_string(type), |
2315 | TRB_TO_SLOT_ID(field3), | 2295 | TRB_TO_SLOT_ID(field3), |
2316 | field3 & TRB_CYCLE ? 'C' : 'c'); | 2296 | field3 & TRB_CYCLE ? 'C' : 'c'); |
2317 | break; | 2297 | break; |
2318 | case TRB_FORCE_EVENT: | 2298 | case TRB_FORCE_EVENT: |
2319 | sprintf(str, | 2299 | sprintf(str, |
2320 | "%s: event %08x%08x vf intr %d vf id %d flags %c", | 2300 | "%s: event %08x%08x vf intr %d vf id %d flags %c", |
2321 | xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)), | 2301 | xhci_trb_type_string(type), |
2322 | field1, field0, | 2302 | field1, field0, |
2323 | TRB_TO_VF_INTR_TARGET(field2), | 2303 | TRB_TO_VF_INTR_TARGET(field2), |
2324 | TRB_TO_VF_ID(field3), | 2304 | TRB_TO_VF_ID(field3), |
@@ -2327,14 +2307,14 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2, | |||
2327 | case TRB_SET_LT: | 2307 | case TRB_SET_LT: |
2328 | sprintf(str, | 2308 | sprintf(str, |
2329 | "%s: belt %d flags %c", | 2309 | "%s: belt %d flags %c", |
2330 | xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)), | 2310 | xhci_trb_type_string(type), |
2331 | TRB_TO_BELT(field3), | 2311 | TRB_TO_BELT(field3), |
2332 | field3 & TRB_CYCLE ? 'C' : 'c'); | 2312 | field3 & TRB_CYCLE ? 'C' : 'c'); |
2333 | break; | 2313 | break; |
2334 | case TRB_GET_BW: | 2314 | case TRB_GET_BW: |
2335 | sprintf(str, | 2315 | sprintf(str, |
2336 | "%s: ctx %08x%08x slot %d speed %d flags %c", | 2316 | "%s: ctx %08x%08x slot %d speed %d flags %c", |
2337 | xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)), | 2317 | xhci_trb_type_string(type), |
2338 | field1, field0, | 2318 | field1, field0, |
2339 | TRB_TO_SLOT_ID(field3), | 2319 | TRB_TO_SLOT_ID(field3), |
2340 | TRB_TO_DEV_SPEED(field3), | 2320 | TRB_TO_DEV_SPEED(field3), |
@@ -2343,7 +2323,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2, | |||
2343 | case TRB_FORCE_HEADER: | 2323 | case TRB_FORCE_HEADER: |
2344 | sprintf(str, | 2324 | sprintf(str, |
2345 | "%s: info %08x%08x%08x pkt type %d roothub port %d flags %c", | 2325 | "%s: info %08x%08x%08x pkt type %d roothub port %d flags %c", |
2346 | xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)), | 2326 | xhci_trb_type_string(type), |
2347 | field2, field1, field0 & 0xffffffe0, | 2327 | field2, field1, field0 & 0xffffffe0, |
2348 | TRB_TO_PACKET_TYPE(field0), | 2328 | TRB_TO_PACKET_TYPE(field0), |
2349 | TRB_TO_ROOTHUB_PORT(field3), | 2329 | TRB_TO_ROOTHUB_PORT(field3), |
@@ -2352,12 +2332,155 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2, | |||
2352 | default: | 2332 | default: |
2353 | sprintf(str, | 2333 | sprintf(str, |
2354 | "type '%s' -> raw %08x %08x %08x %08x", | 2334 | "type '%s' -> raw %08x %08x %08x %08x", |
2355 | xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)), | 2335 | xhci_trb_type_string(type), |
2356 | field0, field1, field2, field3); | 2336 | field0, field1, field2, field3); |
2357 | } | 2337 | } |
2358 | 2338 | ||
2359 | return str; | 2339 | return str; |
2360 | } | 2340 | } |
2361 | 2341 | ||
2342 | static inline const char *xhci_decode_slot_context(u32 info, u32 info2, | ||
2343 | u32 tt_info, u32 state) | ||
2344 | { | ||
2345 | static char str[1024]; | ||
2346 | u32 speed; | ||
2347 | u32 hub; | ||
2348 | u32 mtt; | ||
2349 | int ret = 0; | ||
2350 | |||
2351 | speed = info & DEV_SPEED; | ||
2352 | hub = info & DEV_HUB; | ||
2353 | mtt = info & DEV_MTT; | ||
2354 | |||
2355 | ret = sprintf(str, "RS %05x %s%s%s Ctx Entries %d MEL %d us Port# %d/%d", | ||
2356 | info & ROUTE_STRING_MASK, | ||
2357 | ({ char *s; | ||
2358 | switch (speed) { | ||
2359 | case SLOT_SPEED_FS: | ||
2360 | s = "full-speed"; | ||
2361 | break; | ||
2362 | case SLOT_SPEED_LS: | ||
2363 | s = "low-speed"; | ||
2364 | break; | ||
2365 | case SLOT_SPEED_HS: | ||
2366 | s = "high-speed"; | ||
2367 | break; | ||
2368 | case SLOT_SPEED_SS: | ||
2369 | s = "super-speed"; | ||
2370 | break; | ||
2371 | case SLOT_SPEED_SSP: | ||
2372 | s = "super-speed plus"; | ||
2373 | break; | ||
2374 | default: | ||
2375 | s = "UNKNOWN speed"; | ||
2376 | } s; }), | ||
2377 | mtt ? " multi-TT" : "", | ||
2378 | hub ? " Hub" : "", | ||
2379 | (info & LAST_CTX_MASK) >> 27, | ||
2380 | info2 & MAX_EXIT, | ||
2381 | DEVINFO_TO_ROOT_HUB_PORT(info2), | ||
2382 | DEVINFO_TO_MAX_PORTS(info2)); | ||
2383 | |||
2384 | ret += sprintf(str + ret, " [TT Slot %d Port# %d TTT %d Intr %d] Addr %d State %s", | ||
2385 | tt_info & TT_SLOT, (tt_info & TT_PORT) >> 8, | ||
2386 | GET_TT_THINK_TIME(tt_info), GET_INTR_TARGET(tt_info), | ||
2387 | state & DEV_ADDR_MASK, | ||
2388 | xhci_slot_state_string(GET_SLOT_STATE(state))); | ||
2389 | |||
2390 | return str; | ||
2391 | } | ||
2392 | |||
2393 | static inline const char *xhci_ep_state_string(u8 state) | ||
2394 | { | ||
2395 | switch (state) { | ||
2396 | case EP_STATE_DISABLED: | ||
2397 | return "disabled"; | ||
2398 | case EP_STATE_RUNNING: | ||
2399 | return "running"; | ||
2400 | case EP_STATE_HALTED: | ||
2401 | return "halted"; | ||
2402 | case EP_STATE_STOPPED: | ||
2403 | return "stopped"; | ||
2404 | case EP_STATE_ERROR: | ||
2405 | return "error"; | ||
2406 | default: | ||
2407 | return "INVALID"; | ||
2408 | } | ||
2409 | } | ||
2410 | |||
2411 | static inline const char *xhci_ep_type_string(u8 type) | ||
2412 | { | ||
2413 | switch (type) { | ||
2414 | case ISOC_OUT_EP: | ||
2415 | return "Isoc OUT"; | ||
2416 | case BULK_OUT_EP: | ||
2417 | return "Bulk OUT"; | ||
2418 | case INT_OUT_EP: | ||
2419 | return "Int OUT"; | ||
2420 | case CTRL_EP: | ||
2421 | return "Ctrl"; | ||
2422 | case ISOC_IN_EP: | ||
2423 | return "Isoc IN"; | ||
2424 | case BULK_IN_EP: | ||
2425 | return "Bulk IN"; | ||
2426 | case INT_IN_EP: | ||
2427 | return "Int IN"; | ||
2428 | default: | ||
2429 | return "INVALID"; | ||
2430 | } | ||
2431 | } | ||
2432 | |||
2433 | static inline const char *xhci_decode_ep_context(u32 info, u32 info2, u64 deq, | ||
2434 | u32 tx_info) | ||
2435 | { | ||
2436 | static char str[1024]; | ||
2437 | int ret; | ||
2438 | |||
2439 | u32 esit; | ||
2440 | u16 maxp; | ||
2441 | u16 avg; | ||
2442 | |||
2443 | u8 max_pstr; | ||
2444 | u8 ep_state; | ||
2445 | u8 interval; | ||
2446 | u8 ep_type; | ||
2447 | u8 burst; | ||
2448 | u8 cerr; | ||
2449 | u8 mult; | ||
2450 | u8 lsa; | ||
2451 | u8 hid; | ||
2452 | |||
2453 | esit = EP_MAX_ESIT_PAYLOAD_HI(info) << 16 | | ||
2454 | EP_MAX_ESIT_PAYLOAD_LO(tx_info); | ||
2455 | |||
2456 | ep_state = info & EP_STATE_MASK; | ||
2457 | max_pstr = info & EP_MAXPSTREAMS_MASK; | ||
2458 | interval = CTX_TO_EP_INTERVAL(info); | ||
2459 | mult = CTX_TO_EP_MULT(info) + 1; | ||
2460 | lsa = info & EP_HAS_LSA; | ||
2461 | |||
2462 | cerr = (info2 & (3 << 1)) >> 1; | ||
2463 | ep_type = CTX_TO_EP_TYPE(info2); | ||
2464 | hid = info2 & (1 << 7); | ||
2465 | burst = CTX_TO_MAX_BURST(info2); | ||
2466 | maxp = MAX_PACKET_DECODED(info2); | ||
2467 | |||
2468 | avg = EP_AVG_TRB_LENGTH(tx_info); | ||
2469 | |||
2470 | ret = sprintf(str, "State %s mult %d max P. Streams %d %s", | ||
2471 | xhci_ep_state_string(ep_state), mult, | ||
2472 | max_pstr, lsa ? "LSA " : ""); | ||
2473 | |||
2474 | ret += sprintf(str + ret, "interval %d us max ESIT payload %d CErr %d ", | ||
2475 | (1 << interval) * 125, esit, cerr); | ||
2476 | |||
2477 | ret += sprintf(str + ret, "Type %s %sburst %d maxp %d deq %016llx ", | ||
2478 | xhci_ep_type_string(ep_type), hid ? "HID" : "", | ||
2479 | burst, maxp, deq); | ||
2480 | |||
2481 | ret += sprintf(str + ret, "avg trb len %d", avg); | ||
2482 | |||
2483 | return str; | ||
2484 | } | ||
2362 | 2485 | ||
2363 | #endif /* __LINUX_XHCI_HCD_H */ | 2486 | #endif /* __LINUX_XHCI_HCD_H */ |
diff --git a/drivers/usb/isp1760/isp1760-if.c b/drivers/usb/isp1760/isp1760-if.c index 79205b31e4a9..bc68bbab7fa1 100644 --- a/drivers/usb/isp1760/isp1760-if.c +++ b/drivers/usb/isp1760/isp1760-if.c | |||
@@ -21,11 +21,11 @@ | |||
21 | #include "isp1760-core.h" | 21 | #include "isp1760-core.h" |
22 | #include "isp1760-regs.h" | 22 | #include "isp1760-regs.h" |
23 | 23 | ||
24 | #ifdef CONFIG_PCI | 24 | #ifdef CONFIG_USB_PCI |
25 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
26 | #endif | 26 | #endif |
27 | 27 | ||
28 | #ifdef CONFIG_PCI | 28 | #ifdef CONFIG_USB_PCI |
29 | static int isp1761_pci_init(struct pci_dev *dev) | 29 | static int isp1761_pci_init(struct pci_dev *dev) |
30 | { | 30 | { |
31 | resource_size_t mem_start; | 31 | resource_size_t mem_start; |
@@ -286,7 +286,7 @@ static int __init isp1760_init(void) | |||
286 | ret = platform_driver_register(&isp1760_plat_driver); | 286 | ret = platform_driver_register(&isp1760_plat_driver); |
287 | if (!ret) | 287 | if (!ret) |
288 | any_ret = 0; | 288 | any_ret = 0; |
289 | #ifdef CONFIG_PCI | 289 | #ifdef CONFIG_USB_PCI |
290 | ret = pci_register_driver(&isp1761_pci_driver); | 290 | ret = pci_register_driver(&isp1761_pci_driver); |
291 | if (!ret) | 291 | if (!ret) |
292 | any_ret = 0; | 292 | any_ret = 0; |
@@ -301,7 +301,7 @@ module_init(isp1760_init); | |||
301 | static void __exit isp1760_exit(void) | 301 | static void __exit isp1760_exit(void) |
302 | { | 302 | { |
303 | platform_driver_unregister(&isp1760_plat_driver); | 303 | platform_driver_unregister(&isp1760_plat_driver); |
304 | #ifdef CONFIG_PCI | 304 | #ifdef CONFIG_USB_PCI |
305 | pci_unregister_driver(&isp1761_pci_driver); | 305 | pci_unregister_driver(&isp1761_pci_driver); |
306 | #endif | 306 | #endif |
307 | isp1760_deinit_kmem_cache(); | 307 | isp1760_deinit_kmem_cache(); |
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index db9a9e6ff6be..dfd54ea4808f 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c | |||
@@ -655,24 +655,15 @@ static int adu_probe(struct usb_interface *interface, | |||
655 | { | 655 | { |
656 | struct usb_device *udev = interface_to_usbdev(interface); | 656 | struct usb_device *udev = interface_to_usbdev(interface); |
657 | struct adu_device *dev = NULL; | 657 | struct adu_device *dev = NULL; |
658 | struct usb_host_interface *iface_desc; | 658 | int retval = -ENOMEM; |
659 | struct usb_endpoint_descriptor *endpoint; | ||
660 | int retval = -ENODEV; | ||
661 | int in_end_size; | 659 | int in_end_size; |
662 | int out_end_size; | 660 | int out_end_size; |
663 | int i; | 661 | int res; |
664 | |||
665 | if (udev == NULL) { | ||
666 | dev_err(&interface->dev, "udev is NULL.\n"); | ||
667 | goto exit; | ||
668 | } | ||
669 | 662 | ||
670 | /* allocate memory for our device state and initialize it */ | 663 | /* allocate memory for our device state and initialize it */ |
671 | dev = kzalloc(sizeof(struct adu_device), GFP_KERNEL); | 664 | dev = kzalloc(sizeof(struct adu_device), GFP_KERNEL); |
672 | if (!dev) { | 665 | if (!dev) |
673 | retval = -ENOMEM; | 666 | return -ENOMEM; |
674 | goto exit; | ||
675 | } | ||
676 | 667 | ||
677 | mutex_init(&dev->mtx); | 668 | mutex_init(&dev->mtx); |
678 | spin_lock_init(&dev->buflock); | 669 | spin_lock_init(&dev->buflock); |
@@ -680,24 +671,13 @@ static int adu_probe(struct usb_interface *interface, | |||
680 | init_waitqueue_head(&dev->read_wait); | 671 | init_waitqueue_head(&dev->read_wait); |
681 | init_waitqueue_head(&dev->write_wait); | 672 | init_waitqueue_head(&dev->write_wait); |
682 | 673 | ||
683 | iface_desc = &interface->altsetting[0]; | 674 | res = usb_find_common_endpoints_reverse(&interface->altsetting[0], |
684 | 675 | NULL, NULL, | |
685 | /* set up the endpoint information */ | 676 | &dev->interrupt_in_endpoint, |
686 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | 677 | &dev->interrupt_out_endpoint); |
687 | endpoint = &iface_desc->endpoint[i].desc; | 678 | if (res) { |
688 | 679 | dev_err(&interface->dev, "interrupt endpoints not found\n"); | |
689 | if (usb_endpoint_is_int_in(endpoint)) | 680 | retval = res; |
690 | dev->interrupt_in_endpoint = endpoint; | ||
691 | |||
692 | if (usb_endpoint_is_int_out(endpoint)) | ||
693 | dev->interrupt_out_endpoint = endpoint; | ||
694 | } | ||
695 | if (dev->interrupt_in_endpoint == NULL) { | ||
696 | dev_err(&interface->dev, "interrupt in endpoint not found\n"); | ||
697 | goto error; | ||
698 | } | ||
699 | if (dev->interrupt_out_endpoint == NULL) { | ||
700 | dev_err(&interface->dev, "interrupt out endpoint not found\n"); | ||
701 | goto error; | 681 | goto error; |
702 | } | 682 | } |
703 | 683 | ||
@@ -705,10 +685,8 @@ static int adu_probe(struct usb_interface *interface, | |||
705 | out_end_size = usb_endpoint_maxp(dev->interrupt_out_endpoint); | 685 | out_end_size = usb_endpoint_maxp(dev->interrupt_out_endpoint); |
706 | 686 | ||
707 | dev->read_buffer_primary = kmalloc((4 * in_end_size), GFP_KERNEL); | 687 | dev->read_buffer_primary = kmalloc((4 * in_end_size), GFP_KERNEL); |
708 | if (!dev->read_buffer_primary) { | 688 | if (!dev->read_buffer_primary) |
709 | retval = -ENOMEM; | ||
710 | goto error; | 689 | goto error; |
711 | } | ||
712 | 690 | ||
713 | /* debug code prime the buffer */ | 691 | /* debug code prime the buffer */ |
714 | memset(dev->read_buffer_primary, 'a', in_end_size); | 692 | memset(dev->read_buffer_primary, 'a', in_end_size); |
@@ -717,10 +695,8 @@ static int adu_probe(struct usb_interface *interface, | |||
717 | memset(dev->read_buffer_primary + (3 * in_end_size), 'd', in_end_size); | 695 | memset(dev->read_buffer_primary + (3 * in_end_size), 'd', in_end_size); |
718 | 696 | ||
719 | dev->read_buffer_secondary = kmalloc((4 * in_end_size), GFP_KERNEL); | 697 | dev->read_buffer_secondary = kmalloc((4 * in_end_size), GFP_KERNEL); |
720 | if (!dev->read_buffer_secondary) { | 698 | if (!dev->read_buffer_secondary) |
721 | retval = -ENOMEM; | ||
722 | goto error; | 699 | goto error; |
723 | } | ||
724 | 700 | ||
725 | /* debug code prime the buffer */ | 701 | /* debug code prime the buffer */ |
726 | memset(dev->read_buffer_secondary, 'e', in_end_size); | 702 | memset(dev->read_buffer_secondary, 'e', in_end_size); |
@@ -748,6 +724,7 @@ static int adu_probe(struct usb_interface *interface, | |||
748 | if (!usb_string(udev, udev->descriptor.iSerialNumber, dev->serial_number, | 724 | if (!usb_string(udev, udev->descriptor.iSerialNumber, dev->serial_number, |
749 | sizeof(dev->serial_number))) { | 725 | sizeof(dev->serial_number))) { |
750 | dev_err(&interface->dev, "Could not retrieve serial number\n"); | 726 | dev_err(&interface->dev, "Could not retrieve serial number\n"); |
727 | retval = -EIO; | ||
751 | goto error; | 728 | goto error; |
752 | } | 729 | } |
753 | dev_dbg(&interface->dev,"serial_number=%s", dev->serial_number); | 730 | dev_dbg(&interface->dev,"serial_number=%s", dev->serial_number); |
@@ -770,8 +747,8 @@ static int adu_probe(struct usb_interface *interface, | |||
770 | dev_info(&interface->dev, "ADU%d %s now attached to /dev/usb/adutux%d\n", | 747 | dev_info(&interface->dev, "ADU%d %s now attached to /dev/usb/adutux%d\n", |
771 | le16_to_cpu(udev->descriptor.idProduct), dev->serial_number, | 748 | le16_to_cpu(udev->descriptor.idProduct), dev->serial_number, |
772 | (dev->minor - ADU_MINOR_BASE)); | 749 | (dev->minor - ADU_MINOR_BASE)); |
773 | exit: | 750 | |
774 | return retval; | 751 | return 0; |
775 | 752 | ||
776 | error: | 753 | error: |
777 | adu_delete(dev); | 754 | adu_delete(dev); |
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index da5ff401a354..8efdc500e790 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c | |||
@@ -212,28 +212,21 @@ static int appledisplay_probe(struct usb_interface *iface, | |||
212 | struct backlight_properties props; | 212 | struct backlight_properties props; |
213 | struct appledisplay *pdata; | 213 | struct appledisplay *pdata; |
214 | struct usb_device *udev = interface_to_usbdev(iface); | 214 | struct usb_device *udev = interface_to_usbdev(iface); |
215 | struct usb_host_interface *iface_desc; | ||
216 | struct usb_endpoint_descriptor *endpoint; | 215 | struct usb_endpoint_descriptor *endpoint; |
217 | int int_in_endpointAddr = 0; | 216 | int int_in_endpointAddr = 0; |
218 | int i, retval = -ENOMEM, brightness; | 217 | int retval, brightness; |
219 | char bl_name[20]; | 218 | char bl_name[20]; |
220 | 219 | ||
221 | /* set up the endpoint information */ | 220 | /* set up the endpoint information */ |
222 | /* use only the first interrupt-in endpoint */ | 221 | /* use only the first interrupt-in endpoint */ |
223 | iface_desc = iface->cur_altsetting; | 222 | retval = usb_find_int_in_endpoint(iface->cur_altsetting, &endpoint); |
224 | for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { | 223 | if (retval) { |
225 | endpoint = &iface_desc->endpoint[i].desc; | ||
226 | if (!int_in_endpointAddr && usb_endpoint_is_int_in(endpoint)) { | ||
227 | /* we found an interrupt in endpoint */ | ||
228 | int_in_endpointAddr = endpoint->bEndpointAddress; | ||
229 | break; | ||
230 | } | ||
231 | } | ||
232 | if (!int_in_endpointAddr) { | ||
233 | dev_err(&iface->dev, "Could not find int-in endpoint\n"); | 224 | dev_err(&iface->dev, "Could not find int-in endpoint\n"); |
234 | return -EIO; | 225 | return retval; |
235 | } | 226 | } |
236 | 227 | ||
228 | int_in_endpointAddr = endpoint->bEndpointAddress; | ||
229 | |||
237 | /* allocate memory for our device state and initialize it */ | 230 | /* allocate memory for our device state and initialize it */ |
238 | pdata = kzalloc(sizeof(struct appledisplay), GFP_KERNEL); | 231 | pdata = kzalloc(sizeof(struct appledisplay), GFP_KERNEL); |
239 | if (!pdata) { | 232 | if (!pdata) { |
diff --git a/drivers/usb/misc/chaoskey.c b/drivers/usb/misc/chaoskey.c index aa350dc9eb25..e9cae4d82af2 100644 --- a/drivers/usb/misc/chaoskey.c +++ b/drivers/usb/misc/chaoskey.c | |||
@@ -117,28 +117,26 @@ static int chaoskey_probe(struct usb_interface *interface, | |||
117 | { | 117 | { |
118 | struct usb_device *udev = interface_to_usbdev(interface); | 118 | struct usb_device *udev = interface_to_usbdev(interface); |
119 | struct usb_host_interface *altsetting = interface->cur_altsetting; | 119 | struct usb_host_interface *altsetting = interface->cur_altsetting; |
120 | int i; | 120 | struct usb_endpoint_descriptor *epd; |
121 | int in_ep = -1; | 121 | int in_ep; |
122 | struct chaoskey *dev; | 122 | struct chaoskey *dev; |
123 | int result = -ENOMEM; | 123 | int result = -ENOMEM; |
124 | int size; | 124 | int size; |
125 | int res; | ||
125 | 126 | ||
126 | usb_dbg(interface, "probe %s-%s", udev->product, udev->serial); | 127 | usb_dbg(interface, "probe %s-%s", udev->product, udev->serial); |
127 | 128 | ||
128 | /* Find the first bulk IN endpoint and its packet size */ | 129 | /* Find the first bulk IN endpoint and its packet size */ |
129 | for (i = 0; i < altsetting->desc.bNumEndpoints; i++) { | 130 | res = usb_find_bulk_in_endpoint(altsetting, &epd); |
130 | if (usb_endpoint_is_bulk_in(&altsetting->endpoint[i].desc)) { | 131 | if (res) { |
131 | in_ep = usb_endpoint_num(&altsetting->endpoint[i].desc); | 132 | usb_dbg(interface, "no IN endpoint found"); |
132 | size = usb_endpoint_maxp(&altsetting->endpoint[i].desc); | 133 | return res; |
133 | break; | ||
134 | } | ||
135 | } | 134 | } |
136 | 135 | ||
136 | in_ep = usb_endpoint_num(epd); | ||
137 | size = usb_endpoint_maxp(epd); | ||
138 | |||
137 | /* Validate endpoint and size */ | 139 | /* Validate endpoint and size */ |
138 | if (in_ep == -1) { | ||
139 | usb_dbg(interface, "no IN endpoint found"); | ||
140 | return -ENODEV; | ||
141 | } | ||
142 | if (size <= 0) { | 140 | if (size <= 0) { |
143 | usb_dbg(interface, "invalid size (%d)", size); | 141 | usb_dbg(interface, "invalid size (%d)", size); |
144 | return -ENODEV; | 142 | return -ENODEV; |
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 01a9373b7e18..8291499d0581 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c | |||
@@ -2700,10 +2700,8 @@ static int ftdi_elan_probe(struct usb_interface *interface, | |||
2700 | const struct usb_device_id *id) | 2700 | const struct usb_device_id *id) |
2701 | { | 2701 | { |
2702 | struct usb_host_interface *iface_desc; | 2702 | struct usb_host_interface *iface_desc; |
2703 | struct usb_endpoint_descriptor *endpoint; | 2703 | struct usb_endpoint_descriptor *bulk_in, *bulk_out; |
2704 | size_t buffer_size; | 2704 | int retval; |
2705 | int i; | ||
2706 | int retval = -ENOMEM; | ||
2707 | struct usb_ftdi *ftdi; | 2705 | struct usb_ftdi *ftdi; |
2708 | 2706 | ||
2709 | ftdi = kzalloc(sizeof(struct usb_ftdi), GFP_KERNEL); | 2707 | ftdi = kzalloc(sizeof(struct usb_ftdi), GFP_KERNEL); |
@@ -2720,31 +2718,25 @@ static int ftdi_elan_probe(struct usb_interface *interface, | |||
2720 | ftdi->interface = interface; | 2718 | ftdi->interface = interface; |
2721 | mutex_init(&ftdi->u132_lock); | 2719 | mutex_init(&ftdi->u132_lock); |
2722 | ftdi->expected = 4; | 2720 | ftdi->expected = 4; |
2721 | |||
2723 | iface_desc = interface->cur_altsetting; | 2722 | iface_desc = interface->cur_altsetting; |
2724 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | 2723 | retval = usb_find_common_endpoints(iface_desc, |
2725 | endpoint = &iface_desc->endpoint[i].desc; | 2724 | &bulk_in, &bulk_out, NULL, NULL); |
2726 | if (!ftdi->bulk_in_endpointAddr && | 2725 | if (retval) { |
2727 | usb_endpoint_is_bulk_in(endpoint)) { | ||
2728 | buffer_size = usb_endpoint_maxp(endpoint); | ||
2729 | ftdi->bulk_in_size = buffer_size; | ||
2730 | ftdi->bulk_in_endpointAddr = endpoint->bEndpointAddress; | ||
2731 | ftdi->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); | ||
2732 | if (!ftdi->bulk_in_buffer) { | ||
2733 | retval = -ENOMEM; | ||
2734 | goto error; | ||
2735 | } | ||
2736 | } | ||
2737 | if (!ftdi->bulk_out_endpointAddr && | ||
2738 | usb_endpoint_is_bulk_out(endpoint)) { | ||
2739 | ftdi->bulk_out_endpointAddr = | ||
2740 | endpoint->bEndpointAddress; | ||
2741 | } | ||
2742 | } | ||
2743 | if (!(ftdi->bulk_in_endpointAddr && ftdi->bulk_out_endpointAddr)) { | ||
2744 | dev_err(&ftdi->udev->dev, "Could not find both bulk-in and bulk-out endpoints\n"); | 2726 | dev_err(&ftdi->udev->dev, "Could not find both bulk-in and bulk-out endpoints\n"); |
2745 | retval = -ENODEV; | ||
2746 | goto error; | 2727 | goto error; |
2747 | } | 2728 | } |
2729 | |||
2730 | ftdi->bulk_in_size = usb_endpoint_maxp(bulk_in); | ||
2731 | ftdi->bulk_in_endpointAddr = bulk_in->bEndpointAddress; | ||
2732 | ftdi->bulk_in_buffer = kmalloc(ftdi->bulk_in_size, GFP_KERNEL); | ||
2733 | if (!ftdi->bulk_in_buffer) { | ||
2734 | retval = -ENOMEM; | ||
2735 | goto error; | ||
2736 | } | ||
2737 | |||
2738 | ftdi->bulk_out_endpointAddr = bulk_out->bEndpointAddress; | ||
2739 | |||
2748 | dev_info(&ftdi->udev->dev, "interface %d has I=%02X O=%02X\n", | 2740 | dev_info(&ftdi->udev->dev, "interface %d has I=%02X O=%02X\n", |
2749 | iface_desc->desc.bInterfaceNumber, ftdi->bulk_in_endpointAddr, | 2741 | iface_desc->desc.bInterfaceNumber, ftdi->bulk_in_endpointAddr, |
2750 | ftdi->bulk_out_endpointAddr); | 2742 | ftdi->bulk_out_endpointAddr); |
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c index 502bfe30a077..81fcbf024c65 100644 --- a/drivers/usb/misc/idmouse.c +++ b/drivers/usb/misc/idmouse.c | |||
@@ -360,26 +360,22 @@ static int idmouse_probe(struct usb_interface *interface, | |||
360 | dev->interface = interface; | 360 | dev->interface = interface; |
361 | 361 | ||
362 | /* set up the endpoint information - use only the first bulk-in endpoint */ | 362 | /* set up the endpoint information - use only the first bulk-in endpoint */ |
363 | endpoint = &iface_desc->endpoint[0].desc; | 363 | result = usb_find_bulk_in_endpoint(iface_desc, &endpoint); |
364 | if (!dev->bulk_in_endpointAddr && usb_endpoint_is_bulk_in(endpoint)) { | 364 | if (result) { |
365 | /* we found a bulk in endpoint */ | 365 | dev_err(&interface->dev, "Unable to find bulk-in endpoint.\n"); |
366 | dev->orig_bi_size = usb_endpoint_maxp(endpoint); | 366 | idmouse_delete(dev); |
367 | dev->bulk_in_size = 0x200; /* works _much_ faster */ | 367 | return result; |
368 | dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; | ||
369 | dev->bulk_in_buffer = | ||
370 | kmalloc(IMGSIZE + dev->bulk_in_size, GFP_KERNEL); | ||
371 | |||
372 | if (!dev->bulk_in_buffer) { | ||
373 | idmouse_delete(dev); | ||
374 | return -ENOMEM; | ||
375 | } | ||
376 | } | 368 | } |
377 | 369 | ||
378 | if (!(dev->bulk_in_endpointAddr)) { | 370 | dev->orig_bi_size = usb_endpoint_maxp(endpoint); |
379 | dev_err(&interface->dev, "Unable to find bulk-in endpoint.\n"); | 371 | dev->bulk_in_size = 0x200; /* works _much_ faster */ |
372 | dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; | ||
373 | dev->bulk_in_buffer = kmalloc(IMGSIZE + dev->bulk_in_size, GFP_KERNEL); | ||
374 | if (!dev->bulk_in_buffer) { | ||
380 | idmouse_delete(dev); | 375 | idmouse_delete(dev); |
381 | return -ENODEV; | 376 | return -ENOMEM; |
382 | } | 377 | } |
378 | |||
383 | /* allow device read, write and ioctl */ | 379 | /* allow device read, write and ioctl */ |
384 | dev->present = 1; | 380 | dev->present = 1; |
385 | 381 | ||
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index 37c63cb39714..77569531b78a 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c | |||
@@ -756,9 +756,8 @@ static int iowarrior_probe(struct usb_interface *interface, | |||
756 | struct usb_device *udev = interface_to_usbdev(interface); | 756 | struct usb_device *udev = interface_to_usbdev(interface); |
757 | struct iowarrior *dev = NULL; | 757 | struct iowarrior *dev = NULL; |
758 | struct usb_host_interface *iface_desc; | 758 | struct usb_host_interface *iface_desc; |
759 | struct usb_endpoint_descriptor *endpoint; | ||
760 | int i; | ||
761 | int retval = -ENOMEM; | 759 | int retval = -ENOMEM; |
760 | int res; | ||
762 | 761 | ||
763 | /* allocate memory for our device state and initialize it */ | 762 | /* allocate memory for our device state and initialize it */ |
764 | dev = kzalloc(sizeof(struct iowarrior), GFP_KERNEL); | 763 | dev = kzalloc(sizeof(struct iowarrior), GFP_KERNEL); |
@@ -781,27 +780,19 @@ static int iowarrior_probe(struct usb_interface *interface, | |||
781 | iface_desc = interface->cur_altsetting; | 780 | iface_desc = interface->cur_altsetting; |
782 | dev->product_id = le16_to_cpu(udev->descriptor.idProduct); | 781 | dev->product_id = le16_to_cpu(udev->descriptor.idProduct); |
783 | 782 | ||
784 | /* set up the endpoint information */ | 783 | res = usb_find_last_int_in_endpoint(iface_desc, &dev->int_in_endpoint); |
785 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | 784 | if (res) { |
786 | endpoint = &iface_desc->endpoint[i].desc; | ||
787 | |||
788 | if (usb_endpoint_is_int_in(endpoint)) | ||
789 | dev->int_in_endpoint = endpoint; | ||
790 | if (usb_endpoint_is_int_out(endpoint)) | ||
791 | /* this one will match for the IOWarrior56 only */ | ||
792 | dev->int_out_endpoint = endpoint; | ||
793 | } | ||
794 | |||
795 | if (!dev->int_in_endpoint) { | ||
796 | dev_err(&interface->dev, "no interrupt-in endpoint found\n"); | 785 | dev_err(&interface->dev, "no interrupt-in endpoint found\n"); |
797 | retval = -ENODEV; | 786 | retval = res; |
798 | goto error; | 787 | goto error; |
799 | } | 788 | } |
800 | 789 | ||
801 | if (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56) { | 790 | if (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56) { |
802 | if (!dev->int_out_endpoint) { | 791 | res = usb_find_last_int_out_endpoint(iface_desc, |
792 | &dev->int_out_endpoint); | ||
793 | if (res) { | ||
803 | dev_err(&interface->dev, "no interrupt-out endpoint found\n"); | 794 | dev_err(&interface->dev, "no interrupt-out endpoint found\n"); |
804 | retval = -ENODEV; | 795 | retval = res; |
805 | goto error; | 796 | goto error; |
806 | } | 797 | } |
807 | } | 798 | } |
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index 3bc5356832db..9d9487c66f87 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c | |||
@@ -122,13 +122,13 @@ MODULE_SUPPORTED_DEVICE("LD USB Devices"); | |||
122 | * avoid racing conditions and get better performance of the driver. | 122 | * avoid racing conditions and get better performance of the driver. |
123 | */ | 123 | */ |
124 | static int ring_buffer_size = 128; | 124 | static int ring_buffer_size = 128; |
125 | module_param(ring_buffer_size, int, 0); | 125 | module_param(ring_buffer_size, int, 0000); |
126 | MODULE_PARM_DESC(ring_buffer_size, "Read ring buffer size in reports"); | 126 | MODULE_PARM_DESC(ring_buffer_size, "Read ring buffer size in reports"); |
127 | 127 | ||
128 | /* The write_buffer can contain more than one interrupt out transfer. | 128 | /* The write_buffer can contain more than one interrupt out transfer. |
129 | */ | 129 | */ |
130 | static int write_buffer_size = 10; | 130 | static int write_buffer_size = 10; |
131 | module_param(write_buffer_size, int, 0); | 131 | module_param(write_buffer_size, int, 0000); |
132 | MODULE_PARM_DESC(write_buffer_size, "Write buffer size in reports"); | 132 | MODULE_PARM_DESC(write_buffer_size, "Write buffer size in reports"); |
133 | 133 | ||
134 | /* As of kernel version 2.6.4 ehci-hcd uses an | 134 | /* As of kernel version 2.6.4 ehci-hcd uses an |
@@ -141,30 +141,30 @@ MODULE_PARM_DESC(write_buffer_size, "Write buffer size in reports"); | |||
141 | * or set to 1 to use the standard interval from the endpoint descriptors. | 141 | * or set to 1 to use the standard interval from the endpoint descriptors. |
142 | */ | 142 | */ |
143 | static int min_interrupt_in_interval = 2; | 143 | static int min_interrupt_in_interval = 2; |
144 | module_param(min_interrupt_in_interval, int, 0); | 144 | module_param(min_interrupt_in_interval, int, 0000); |
145 | MODULE_PARM_DESC(min_interrupt_in_interval, "Minimum interrupt in interval in ms"); | 145 | MODULE_PARM_DESC(min_interrupt_in_interval, "Minimum interrupt in interval in ms"); |
146 | 146 | ||
147 | static int min_interrupt_out_interval = 2; | 147 | static int min_interrupt_out_interval = 2; |
148 | module_param(min_interrupt_out_interval, int, 0); | 148 | module_param(min_interrupt_out_interval, int, 0000); |
149 | MODULE_PARM_DESC(min_interrupt_out_interval, "Minimum interrupt out interval in ms"); | 149 | MODULE_PARM_DESC(min_interrupt_out_interval, "Minimum interrupt out interval in ms"); |
150 | 150 | ||
151 | /* Structure to hold all of our device specific stuff */ | 151 | /* Structure to hold all of our device specific stuff */ |
152 | struct ld_usb { | 152 | struct ld_usb { |
153 | struct mutex mutex; /* locks this structure */ | 153 | struct mutex mutex; /* locks this structure */ |
154 | struct usb_interface* intf; /* save off the usb interface pointer */ | 154 | struct usb_interface *intf; /* save off the usb interface pointer */ |
155 | 155 | ||
156 | int open_count; /* number of times this port has been opened */ | 156 | int open_count; /* number of times this port has been opened */ |
157 | 157 | ||
158 | char* ring_buffer; | 158 | char *ring_buffer; |
159 | unsigned int ring_head; | 159 | unsigned int ring_head; |
160 | unsigned int ring_tail; | 160 | unsigned int ring_tail; |
161 | 161 | ||
162 | wait_queue_head_t read_wait; | 162 | wait_queue_head_t read_wait; |
163 | wait_queue_head_t write_wait; | 163 | wait_queue_head_t write_wait; |
164 | 164 | ||
165 | char* interrupt_in_buffer; | 165 | char *interrupt_in_buffer; |
166 | struct usb_endpoint_descriptor* interrupt_in_endpoint; | 166 | struct usb_endpoint_descriptor *interrupt_in_endpoint; |
167 | struct urb* interrupt_in_urb; | 167 | struct urb *interrupt_in_urb; |
168 | int interrupt_in_interval; | 168 | int interrupt_in_interval; |
169 | size_t interrupt_in_endpoint_size; | 169 | size_t interrupt_in_endpoint_size; |
170 | int interrupt_in_running; | 170 | int interrupt_in_running; |
@@ -172,9 +172,9 @@ struct ld_usb { | |||
172 | int buffer_overflow; | 172 | int buffer_overflow; |
173 | spinlock_t rbsl; | 173 | spinlock_t rbsl; |
174 | 174 | ||
175 | char* interrupt_out_buffer; | 175 | char *interrupt_out_buffer; |
176 | struct usb_endpoint_descriptor* interrupt_out_endpoint; | 176 | struct usb_endpoint_descriptor *interrupt_out_endpoint; |
177 | struct urb* interrupt_out_urb; | 177 | struct urb *interrupt_out_urb; |
178 | int interrupt_out_interval; | 178 | int interrupt_out_interval; |
179 | size_t interrupt_out_endpoint_size; | 179 | size_t interrupt_out_endpoint_size; |
180 | int interrupt_out_busy; | 180 | int interrupt_out_busy; |
@@ -244,7 +244,7 @@ static void ld_usb_interrupt_in_callback(struct urb *urb) | |||
244 | if (urb->actual_length > 0) { | 244 | if (urb->actual_length > 0) { |
245 | next_ring_head = (dev->ring_head+1) % ring_buffer_size; | 245 | next_ring_head = (dev->ring_head+1) % ring_buffer_size; |
246 | if (next_ring_head != dev->ring_tail) { | 246 | if (next_ring_head != dev->ring_tail) { |
247 | actual_buffer = (size_t*)(dev->ring_buffer + dev->ring_head*(sizeof(size_t)+dev->interrupt_in_endpoint_size)); | 247 | actual_buffer = (size_t *)(dev->ring_buffer + dev->ring_head * (sizeof(size_t)+dev->interrupt_in_endpoint_size)); |
248 | /* actual_buffer gets urb->actual_length + interrupt_in_buffer */ | 248 | /* actual_buffer gets urb->actual_length + interrupt_in_buffer */ |
249 | *actual_buffer = urb->actual_length; | 249 | *actual_buffer = urb->actual_length; |
250 | memcpy(actual_buffer+1, dev->interrupt_in_buffer, urb->actual_length); | 250 | memcpy(actual_buffer+1, dev->interrupt_in_buffer, urb->actual_length); |
@@ -483,7 +483,7 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count, | |||
483 | } | 483 | } |
484 | 484 | ||
485 | /* actual_buffer contains actual_length + interrupt_in_buffer */ | 485 | /* actual_buffer contains actual_length + interrupt_in_buffer */ |
486 | actual_buffer = (size_t*)(dev->ring_buffer + dev->ring_tail*(sizeof(size_t)+dev->interrupt_in_endpoint_size)); | 486 | actual_buffer = (size_t *)(dev->ring_buffer + dev->ring_tail * (sizeof(size_t)+dev->interrupt_in_endpoint_size)); |
487 | bytes_to_read = min(count, *actual_buffer); | 487 | bytes_to_read = min(count, *actual_buffer); |
488 | if (bytes_to_read < *actual_buffer) | 488 | if (bytes_to_read < *actual_buffer) |
489 | dev_warn(&dev->intf->dev, "Read buffer overflow, %zd bytes dropped\n", | 489 | dev_warn(&dev->intf->dev, "Read buffer overflow, %zd bytes dropped\n", |
@@ -561,7 +561,7 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer, | |||
561 | /* write the data into interrupt_out_buffer from userspace */ | 561 | /* write the data into interrupt_out_buffer from userspace */ |
562 | bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size); | 562 | bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size); |
563 | if (bytes_to_write < count) | 563 | if (bytes_to_write < count) |
564 | dev_warn(&dev->intf->dev, "Write buffer overflow, %zd bytes dropped\n",count-bytes_to_write); | 564 | dev_warn(&dev->intf->dev, "Write buffer overflow, %zd bytes dropped\n", count-bytes_to_write); |
565 | dev_dbg(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", | 565 | dev_dbg(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", |
566 | __func__, count, bytes_to_write); | 566 | __func__, count, bytes_to_write); |
567 | 567 | ||
@@ -650,10 +650,9 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id * | |||
650 | struct usb_device *udev = interface_to_usbdev(intf); | 650 | struct usb_device *udev = interface_to_usbdev(intf); |
651 | struct ld_usb *dev = NULL; | 651 | struct ld_usb *dev = NULL; |
652 | struct usb_host_interface *iface_desc; | 652 | struct usb_host_interface *iface_desc; |
653 | struct usb_endpoint_descriptor *endpoint; | ||
654 | char *buffer; | 653 | char *buffer; |
655 | int i; | ||
656 | int retval = -ENOMEM; | 654 | int retval = -ENOMEM; |
655 | int res; | ||
657 | 656 | ||
658 | /* allocate memory for our device state and initialize it */ | 657 | /* allocate memory for our device state and initialize it */ |
659 | 658 | ||
@@ -681,21 +680,17 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id * | |||
681 | 680 | ||
682 | iface_desc = intf->cur_altsetting; | 681 | iface_desc = intf->cur_altsetting; |
683 | 682 | ||
684 | /* set up the endpoint information */ | 683 | res = usb_find_last_int_in_endpoint(iface_desc, |
685 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | 684 | &dev->interrupt_in_endpoint); |
686 | endpoint = &iface_desc->endpoint[i].desc; | 685 | if (res) { |
687 | |||
688 | if (usb_endpoint_is_int_in(endpoint)) | ||
689 | dev->interrupt_in_endpoint = endpoint; | ||
690 | |||
691 | if (usb_endpoint_is_int_out(endpoint)) | ||
692 | dev->interrupt_out_endpoint = endpoint; | ||
693 | } | ||
694 | if (dev->interrupt_in_endpoint == NULL) { | ||
695 | dev_err(&intf->dev, "Interrupt in endpoint not found\n"); | 686 | dev_err(&intf->dev, "Interrupt in endpoint not found\n"); |
687 | retval = res; | ||
696 | goto error; | 688 | goto error; |
697 | } | 689 | } |
698 | if (dev->interrupt_out_endpoint == NULL) | 690 | |
691 | res = usb_find_last_int_out_endpoint(iface_desc, | ||
692 | &dev->interrupt_out_endpoint); | ||
693 | if (res) | ||
699 | dev_warn(&intf->dev, "Interrupt out endpoint not found (using control endpoint instead)\n"); | 694 | dev_warn(&intf->dev, "Interrupt out endpoint not found (using control endpoint instead)\n"); |
700 | 695 | ||
701 | dev->interrupt_in_endpoint_size = usb_endpoint_maxp(dev->interrupt_in_endpoint); | 696 | dev->interrupt_in_endpoint_size = usb_endpoint_maxp(dev->interrupt_in_endpoint); |
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 322a042d6e59..aa3c280fdf8d 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c | |||
@@ -317,9 +317,16 @@ static int tower_open (struct inode *inode, struct file *file) | |||
317 | int subminor; | 317 | int subminor; |
318 | int retval = 0; | 318 | int retval = 0; |
319 | struct usb_interface *interface; | 319 | struct usb_interface *interface; |
320 | struct tower_reset_reply reset_reply; | 320 | struct tower_reset_reply *reset_reply; |
321 | int result; | 321 | int result; |
322 | 322 | ||
323 | reset_reply = kmalloc(sizeof(*reset_reply), GFP_KERNEL); | ||
324 | |||
325 | if (!reset_reply) { | ||
326 | retval = -ENOMEM; | ||
327 | goto exit; | ||
328 | } | ||
329 | |||
323 | nonseekable_open(inode, file); | 330 | nonseekable_open(inode, file); |
324 | subminor = iminor(inode); | 331 | subminor = iminor(inode); |
325 | 332 | ||
@@ -364,8 +371,8 @@ static int tower_open (struct inode *inode, struct file *file) | |||
364 | USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, | 371 | USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, |
365 | 0, | 372 | 0, |
366 | 0, | 373 | 0, |
367 | &reset_reply, | 374 | reset_reply, |
368 | sizeof(reset_reply), | 375 | sizeof(*reset_reply), |
369 | 1000); | 376 | 1000); |
370 | if (result < 0) { | 377 | if (result < 0) { |
371 | dev_err(&dev->udev->dev, | 378 | dev_err(&dev->udev->dev, |
@@ -406,6 +413,7 @@ unlock_exit: | |||
406 | mutex_unlock(&dev->lock); | 413 | mutex_unlock(&dev->lock); |
407 | 414 | ||
408 | exit: | 415 | exit: |
416 | kfree(reset_reply); | ||
409 | return retval; | 417 | return retval; |
410 | } | 418 | } |
411 | 419 | ||
@@ -806,10 +814,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device | |||
806 | struct device *idev = &interface->dev; | 814 | struct device *idev = &interface->dev; |
807 | struct usb_device *udev = interface_to_usbdev(interface); | 815 | struct usb_device *udev = interface_to_usbdev(interface); |
808 | struct lego_usb_tower *dev = NULL; | 816 | struct lego_usb_tower *dev = NULL; |
809 | struct usb_host_interface *iface_desc; | 817 | struct tower_get_version_reply *get_version_reply = NULL; |
810 | struct usb_endpoint_descriptor* endpoint; | ||
811 | struct tower_get_version_reply get_version_reply; | ||
812 | int i; | ||
813 | int retval = -ENOMEM; | 818 | int retval = -ENOMEM; |
814 | int result; | 819 | int result; |
815 | 820 | ||
@@ -846,25 +851,13 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device | |||
846 | dev->interrupt_out_urb = NULL; | 851 | dev->interrupt_out_urb = NULL; |
847 | dev->interrupt_out_busy = 0; | 852 | dev->interrupt_out_busy = 0; |
848 | 853 | ||
849 | iface_desc = interface->cur_altsetting; | 854 | result = usb_find_common_endpoints_reverse(interface->cur_altsetting, |
850 | 855 | NULL, NULL, | |
851 | /* set up the endpoint information */ | 856 | &dev->interrupt_in_endpoint, |
852 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | 857 | &dev->interrupt_out_endpoint); |
853 | endpoint = &iface_desc->endpoint[i].desc; | 858 | if (result) { |
854 | 859 | dev_err(idev, "interrupt endpoints not found\n"); | |
855 | if (usb_endpoint_xfer_int(endpoint)) { | 860 | retval = result; |
856 | if (usb_endpoint_dir_in(endpoint)) | ||
857 | dev->interrupt_in_endpoint = endpoint; | ||
858 | else | ||
859 | dev->interrupt_out_endpoint = endpoint; | ||
860 | } | ||
861 | } | ||
862 | if(dev->interrupt_in_endpoint == NULL) { | ||
863 | dev_err(idev, "interrupt in endpoint not found\n"); | ||
864 | goto error; | ||
865 | } | ||
866 | if (dev->interrupt_out_endpoint == NULL) { | ||
867 | dev_err(idev, "interrupt out endpoint not found\n"); | ||
868 | goto error; | 861 | goto error; |
869 | } | 862 | } |
870 | 863 | ||
@@ -886,6 +879,13 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device | |||
886 | dev->interrupt_in_interval = interrupt_in_interval ? interrupt_in_interval : dev->interrupt_in_endpoint->bInterval; | 879 | dev->interrupt_in_interval = interrupt_in_interval ? interrupt_in_interval : dev->interrupt_in_endpoint->bInterval; |
887 | dev->interrupt_out_interval = interrupt_out_interval ? interrupt_out_interval : dev->interrupt_out_endpoint->bInterval; | 880 | dev->interrupt_out_interval = interrupt_out_interval ? interrupt_out_interval : dev->interrupt_out_endpoint->bInterval; |
888 | 881 | ||
882 | get_version_reply = kmalloc(sizeof(*get_version_reply), GFP_KERNEL); | ||
883 | |||
884 | if (!get_version_reply) { | ||
885 | retval = -ENOMEM; | ||
886 | goto error; | ||
887 | } | ||
888 | |||
889 | /* get the firmware version and log it */ | 889 | /* get the firmware version and log it */ |
890 | result = usb_control_msg (udev, | 890 | result = usb_control_msg (udev, |
891 | usb_rcvctrlpipe(udev, 0), | 891 | usb_rcvctrlpipe(udev, 0), |
@@ -893,18 +893,19 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device | |||
893 | USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, | 893 | USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, |
894 | 0, | 894 | 0, |
895 | 0, | 895 | 0, |
896 | &get_version_reply, | 896 | get_version_reply, |
897 | sizeof(get_version_reply), | 897 | sizeof(*get_version_reply), |
898 | 1000); | 898 | 1000); |
899 | if (result < 0) { | 899 | if (result < 0) { |
900 | dev_err(idev, "LEGO USB Tower get version control request failed\n"); | 900 | dev_err(idev, "LEGO USB Tower get version control request failed\n"); |
901 | retval = result; | 901 | retval = result; |
902 | goto error; | 902 | goto error; |
903 | } | 903 | } |
904 | dev_info(&interface->dev, "LEGO USB Tower firmware version is %d.%d " | 904 | dev_info(&interface->dev, |
905 | "build %d\n", get_version_reply.major, | 905 | "LEGO USB Tower firmware version is %d.%d build %d\n", |
906 | get_version_reply.minor, | 906 | get_version_reply->major, |
907 | le16_to_cpu(get_version_reply.build_no)); | 907 | get_version_reply->minor, |
908 | le16_to_cpu(get_version_reply->build_no)); | ||
908 | 909 | ||
909 | /* we can register the device now, as it is ready */ | 910 | /* we can register the device now, as it is ready */ |
910 | usb_set_intfdata (interface, dev); | 911 | usb_set_intfdata (interface, dev); |
@@ -928,6 +929,7 @@ exit: | |||
928 | return retval; | 929 | return retval; |
929 | 930 | ||
930 | error: | 931 | error: |
932 | kfree(get_version_reply); | ||
931 | tower_delete(dev); | 933 | tower_delete(dev); |
932 | return retval; | 934 | return retval; |
933 | } | 935 | } |
diff --git a/drivers/usb/misc/lvstest.c b/drivers/usb/misc/lvstest.c index d3d124753266..2142132a1f82 100644 --- a/drivers/usb/misc/lvstest.c +++ b/drivers/usb/misc/lvstest.c | |||
@@ -193,7 +193,7 @@ static ssize_t u2_timeout_store(struct device *dev, | |||
193 | return ret; | 193 | return ret; |
194 | } | 194 | } |
195 | 195 | ||
196 | if (val < 0 || val > 127) | 196 | if (val > 127) |
197 | return -EINVAL; | 197 | return -EINVAL; |
198 | 198 | ||
199 | ret = lvs_rh_set_port_feature(hdev, lvs->portnum | (val << 8), | 199 | ret = lvs_rh_set_port_feature(hdev, lvs->portnum | (val << 8), |
@@ -222,7 +222,7 @@ static ssize_t u1_timeout_store(struct device *dev, | |||
222 | return ret; | 222 | return ret; |
223 | } | 223 | } |
224 | 224 | ||
225 | if (val < 0 || val > 127) | 225 | if (val > 127) |
226 | return -EINVAL; | 226 | return -EINVAL; |
227 | 227 | ||
228 | ret = lvs_rh_set_port_feature(hdev, lvs->portnum | (val << 8), | 228 | ret = lvs_rh_set_port_feature(hdev, lvs->portnum | (val << 8), |
@@ -367,10 +367,9 @@ static int lvs_rh_probe(struct usb_interface *intf, | |||
367 | hdev = interface_to_usbdev(intf); | 367 | hdev = interface_to_usbdev(intf); |
368 | desc = intf->cur_altsetting; | 368 | desc = intf->cur_altsetting; |
369 | 369 | ||
370 | if (desc->desc.bNumEndpoints < 1) | 370 | ret = usb_find_int_in_endpoint(desc, &endpoint); |
371 | return -ENODEV; | 371 | if (ret) |
372 | 372 | return ret; | |
373 | endpoint = &desc->endpoint[0].desc; | ||
374 | 373 | ||
375 | /* valid only for SS root hub */ | 374 | /* valid only for SS root hub */ |
376 | if (hdev->descriptor.bDeviceProtocol != USB_HUB_PR_SS || hdev->parent) { | 375 | if (hdev->descriptor.bDeviceProtocol != USB_HUB_PR_SS || hdev->parent) { |
@@ -433,6 +432,7 @@ static void lvs_rh_disconnect(struct usb_interface *intf) | |||
433 | struct lvs_rh *lvs = usb_get_intfdata(intf); | 432 | struct lvs_rh *lvs = usb_get_intfdata(intf); |
434 | 433 | ||
435 | sysfs_remove_group(&intf->dev.kobj, &lvs_attr_group); | 434 | sysfs_remove_group(&intf->dev.kobj, &lvs_attr_group); |
435 | usb_poison_urb(lvs->urb); /* used in scheduled work */ | ||
436 | flush_work(&lvs->rh_work); | 436 | flush_work(&lvs->rh_work); |
437 | usb_free_urb(lvs->urb); | 437 | usb_free_urb(lvs->urb); |
438 | } | 438 | } |
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c index 4b5777ec1501..3c6948af726a 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_con.c +++ b/drivers/usb/misc/sisusbvga/sisusb_con.c | |||
@@ -816,7 +816,7 @@ sisusbcon_scroll_area(struct vc_data *c, struct sisusb_usb_data *sisusb, | |||
816 | 816 | ||
817 | mutex_unlock(&sisusb->lock); | 817 | mutex_unlock(&sisusb->lock); |
818 | 818 | ||
819 | return 1; | 819 | return true; |
820 | } | 820 | } |
821 | 821 | ||
822 | /* Interface routine */ | 822 | /* Interface routine */ |
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c index 9f48419abc46..0f5ad896c7e3 100644 --- a/drivers/usb/misc/usblcd.c +++ b/drivers/usb/misc/usblcd.c | |||
@@ -313,16 +313,15 @@ static int lcd_probe(struct usb_interface *interface, | |||
313 | const struct usb_device_id *id) | 313 | const struct usb_device_id *id) |
314 | { | 314 | { |
315 | struct usb_lcd *dev = NULL; | 315 | struct usb_lcd *dev = NULL; |
316 | struct usb_host_interface *iface_desc; | 316 | struct usb_endpoint_descriptor *bulk_in, *bulk_out; |
317 | struct usb_endpoint_descriptor *endpoint; | ||
318 | size_t buffer_size; | ||
319 | int i; | 317 | int i; |
320 | int retval = -ENOMEM; | 318 | int retval; |
321 | 319 | ||
322 | /* allocate memory for our device state and initialize it */ | 320 | /* allocate memory for our device state and initialize it */ |
323 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 321 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
324 | if (!dev) | 322 | if (!dev) |
325 | goto error; | 323 | return -ENOMEM; |
324 | |||
326 | kref_init(&dev->kref); | 325 | kref_init(&dev->kref); |
327 | sema_init(&dev->limit_sem, USB_LCD_CONCURRENT_WRITES); | 326 | sema_init(&dev->limit_sem, USB_LCD_CONCURRENT_WRITES); |
328 | init_usb_anchor(&dev->submitted); | 327 | init_usb_anchor(&dev->submitted); |
@@ -338,33 +337,24 @@ static int lcd_probe(struct usb_interface *interface, | |||
338 | 337 | ||
339 | /* set up the endpoint information */ | 338 | /* set up the endpoint information */ |
340 | /* use only the first bulk-in and bulk-out endpoints */ | 339 | /* use only the first bulk-in and bulk-out endpoints */ |
341 | iface_desc = interface->cur_altsetting; | 340 | retval = usb_find_common_endpoints(interface->cur_altsetting, |
342 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | 341 | &bulk_in, &bulk_out, NULL, NULL); |
343 | endpoint = &iface_desc->endpoint[i].desc; | 342 | if (retval) { |
344 | |||
345 | if (!dev->bulk_in_endpointAddr && | ||
346 | usb_endpoint_is_bulk_in(endpoint)) { | ||
347 | /* we found a bulk in endpoint */ | ||
348 | buffer_size = usb_endpoint_maxp(endpoint); | ||
349 | dev->bulk_in_size = buffer_size; | ||
350 | dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; | ||
351 | dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); | ||
352 | if (!dev->bulk_in_buffer) | ||
353 | goto error; | ||
354 | } | ||
355 | |||
356 | if (!dev->bulk_out_endpointAddr && | ||
357 | usb_endpoint_is_bulk_out(endpoint)) { | ||
358 | /* we found a bulk out endpoint */ | ||
359 | dev->bulk_out_endpointAddr = endpoint->bEndpointAddress; | ||
360 | } | ||
361 | } | ||
362 | if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) { | ||
363 | dev_err(&interface->dev, | 343 | dev_err(&interface->dev, |
364 | "Could not find both bulk-in and bulk-out endpoints\n"); | 344 | "Could not find both bulk-in and bulk-out endpoints\n"); |
365 | goto error; | 345 | goto error; |
366 | } | 346 | } |
367 | 347 | ||
348 | dev->bulk_in_size = usb_endpoint_maxp(bulk_in); | ||
349 | dev->bulk_in_endpointAddr = bulk_in->bEndpointAddress; | ||
350 | dev->bulk_in_buffer = kmalloc(dev->bulk_in_size, GFP_KERNEL); | ||
351 | if (!dev->bulk_in_buffer) { | ||
352 | retval = -ENOMEM; | ||
353 | goto error; | ||
354 | } | ||
355 | |||
356 | dev->bulk_out_endpointAddr = bulk_out->bEndpointAddress; | ||
357 | |||
368 | /* save our data pointer in this interface device */ | 358 | /* save our data pointer in this interface device */ |
369 | usb_set_intfdata(interface, dev); | 359 | usb_set_intfdata(interface, dev); |
370 | 360 | ||
@@ -390,8 +380,7 @@ static int lcd_probe(struct usb_interface *interface, | |||
390 | return 0; | 380 | return 0; |
391 | 381 | ||
392 | error: | 382 | error: |
393 | if (dev) | 383 | kref_put(&dev->kref, lcd_delete); |
394 | kref_put(&dev->kref, lcd_delete); | ||
395 | return retval; | 384 | return retval; |
396 | } | 385 | } |
397 | 386 | ||
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 17c081068257..eee82ca55b7b 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c | |||
@@ -124,6 +124,20 @@ static struct usb_device *testdev_to_usbdev(struct usbtest_dev *test) | |||
124 | 124 | ||
125 | /*-------------------------------------------------------------------------*/ | 125 | /*-------------------------------------------------------------------------*/ |
126 | 126 | ||
127 | static inline void endpoint_update(int edi, | ||
128 | struct usb_host_endpoint **in, | ||
129 | struct usb_host_endpoint **out, | ||
130 | struct usb_host_endpoint *e) | ||
131 | { | ||
132 | if (edi) { | ||
133 | if (!*in) | ||
134 | *in = e; | ||
135 | } else { | ||
136 | if (!*out) | ||
137 | *out = e; | ||
138 | } | ||
139 | } | ||
140 | |||
127 | static int | 141 | static int |
128 | get_endpoints(struct usbtest_dev *dev, struct usb_interface *intf) | 142 | get_endpoints(struct usbtest_dev *dev, struct usb_interface *intf) |
129 | { | 143 | { |
@@ -151,46 +165,26 @@ get_endpoints(struct usbtest_dev *dev, struct usb_interface *intf) | |||
151 | */ | 165 | */ |
152 | for (ep = 0; ep < alt->desc.bNumEndpoints; ep++) { | 166 | for (ep = 0; ep < alt->desc.bNumEndpoints; ep++) { |
153 | struct usb_host_endpoint *e; | 167 | struct usb_host_endpoint *e; |
168 | int edi; | ||
154 | 169 | ||
155 | e = alt->endpoint + ep; | 170 | e = alt->endpoint + ep; |
171 | edi = usb_endpoint_dir_in(&e->desc); | ||
172 | |||
156 | switch (usb_endpoint_type(&e->desc)) { | 173 | switch (usb_endpoint_type(&e->desc)) { |
157 | case USB_ENDPOINT_XFER_BULK: | 174 | case USB_ENDPOINT_XFER_BULK: |
158 | break; | 175 | endpoint_update(edi, &in, &out, e); |
176 | continue; | ||
159 | case USB_ENDPOINT_XFER_INT: | 177 | case USB_ENDPOINT_XFER_INT: |
160 | if (dev->info->intr) | 178 | if (dev->info->intr) |
161 | goto try_intr; | 179 | endpoint_update(edi, &int_in, &int_out, e); |
180 | continue; | ||
162 | case USB_ENDPOINT_XFER_ISOC: | 181 | case USB_ENDPOINT_XFER_ISOC: |
163 | if (dev->info->iso) | 182 | if (dev->info->iso) |
164 | goto try_iso; | 183 | endpoint_update(edi, &iso_in, &iso_out, e); |
165 | /* FALLTHROUGH */ | 184 | /* FALLTHROUGH */ |
166 | default: | 185 | default: |
167 | continue; | 186 | continue; |
168 | } | 187 | } |
169 | if (usb_endpoint_dir_in(&e->desc)) { | ||
170 | if (!in) | ||
171 | in = e; | ||
172 | } else { | ||
173 | if (!out) | ||
174 | out = e; | ||
175 | } | ||
176 | continue; | ||
177 | try_intr: | ||
178 | if (usb_endpoint_dir_in(&e->desc)) { | ||
179 | if (!int_in) | ||
180 | int_in = e; | ||
181 | } else { | ||
182 | if (!int_out) | ||
183 | int_out = e; | ||
184 | } | ||
185 | continue; | ||
186 | try_iso: | ||
187 | if (usb_endpoint_dir_in(&e->desc)) { | ||
188 | if (!iso_in) | ||
189 | iso_in = e; | ||
190 | } else { | ||
191 | if (!iso_out) | ||
192 | iso_out = e; | ||
193 | } | ||
194 | } | 188 | } |
195 | if ((in && out) || iso_in || iso_out || int_in || int_out) | 189 | if ((in && out) || iso_in || iso_out || int_in || int_out) |
196 | goto found; | 190 | goto found; |
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c index 07014cad6dbe..5947373700a1 100644 --- a/drivers/usb/misc/uss720.c +++ b/drivers/usb/misc/uss720.c | |||
@@ -689,7 +689,7 @@ static int uss720_probe(struct usb_interface *intf, | |||
689 | { | 689 | { |
690 | struct usb_device *usbdev = usb_get_dev(interface_to_usbdev(intf)); | 690 | struct usb_device *usbdev = usb_get_dev(interface_to_usbdev(intf)); |
691 | struct usb_host_interface *interface; | 691 | struct usb_host_interface *interface; |
692 | struct usb_host_endpoint *endpoint; | 692 | struct usb_endpoint_descriptor *epd; |
693 | struct parport_uss720_private *priv; | 693 | struct parport_uss720_private *priv; |
694 | struct parport *pp; | 694 | struct parport *pp; |
695 | unsigned char reg; | 695 | unsigned char reg; |
@@ -745,9 +745,11 @@ static int uss720_probe(struct usb_interface *intf, | |||
745 | get_1284_register(pp, 0, ®, GFP_KERNEL); | 745 | get_1284_register(pp, 0, ®, GFP_KERNEL); |
746 | dev_dbg(&intf->dev, "reg: %7ph\n", priv->reg); | 746 | dev_dbg(&intf->dev, "reg: %7ph\n", priv->reg); |
747 | 747 | ||
748 | endpoint = &interface->endpoint[2]; | 748 | i = usb_find_last_int_in_endpoint(interface, &epd); |
749 | dev_dbg(&intf->dev, "epaddr %d interval %d\n", | 749 | if (!i) { |
750 | endpoint->desc.bEndpointAddress, endpoint->desc.bInterval); | 750 | dev_dbg(&intf->dev, "epaddr %d interval %d\n", |
751 | epd->bEndpointAddress, epd->bInterval); | ||
752 | } | ||
751 | parport_announce_port(pp); | 753 | parport_announce_port(pp); |
752 | 754 | ||
753 | usb_set_intfdata(intf, pp); | 755 | usb_set_intfdata(intf, pp); |
diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c index 54e53ac4c08f..58abdf28620a 100644 --- a/drivers/usb/misc/yurex.c +++ b/drivers/usb/misc/yurex.c | |||
@@ -195,8 +195,8 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_ | |||
195 | struct usb_host_interface *iface_desc; | 195 | struct usb_host_interface *iface_desc; |
196 | struct usb_endpoint_descriptor *endpoint; | 196 | struct usb_endpoint_descriptor *endpoint; |
197 | int retval = -ENOMEM; | 197 | int retval = -ENOMEM; |
198 | int i; | ||
199 | DEFINE_WAIT(wait); | 198 | DEFINE_WAIT(wait); |
199 | int res; | ||
200 | 200 | ||
201 | /* allocate memory for our device state and initialize it */ | 201 | /* allocate memory for our device state and initialize it */ |
202 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 202 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
@@ -212,20 +212,14 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_ | |||
212 | 212 | ||
213 | /* set up the endpoint information */ | 213 | /* set up the endpoint information */ |
214 | iface_desc = interface->cur_altsetting; | 214 | iface_desc = interface->cur_altsetting; |
215 | for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { | 215 | res = usb_find_int_in_endpoint(iface_desc, &endpoint); |
216 | endpoint = &iface_desc->endpoint[i].desc; | 216 | if (res) { |
217 | |||
218 | if (usb_endpoint_is_int_in(endpoint)) { | ||
219 | dev->int_in_endpointAddr = endpoint->bEndpointAddress; | ||
220 | break; | ||
221 | } | ||
222 | } | ||
223 | if (!dev->int_in_endpointAddr) { | ||
224 | retval = -ENODEV; | ||
225 | dev_err(&interface->dev, "Could not find endpoints\n"); | 217 | dev_err(&interface->dev, "Could not find endpoints\n"); |
218 | retval = res; | ||
226 | goto error; | 219 | goto error; |
227 | } | 220 | } |
228 | 221 | ||
222 | dev->int_in_endpointAddr = endpoint->bEndpointAddress; | ||
229 | 223 | ||
230 | /* allocate control URB */ | 224 | /* allocate control URB */ |
231 | dev->cntl_urb = usb_alloc_urb(0, GFP_KERNEL); | 225 | dev->cntl_urb = usb_alloc_urb(0, GFP_KERNEL); |
diff --git a/drivers/usb/mtu3/mtu3_dr.c b/drivers/usb/mtu3/mtu3_dr.c index 1a8987e7c5b0..11a0d3b84c5e 100644 --- a/drivers/usb/mtu3/mtu3_dr.c +++ b/drivers/usb/mtu3/mtu3_dr.c | |||
@@ -223,25 +223,25 @@ static int ssusb_extcon_register(struct otg_switch_mtk *otg_sx) | |||
223 | return 0; | 223 | return 0; |
224 | 224 | ||
225 | otg_sx->vbus_nb.notifier_call = ssusb_vbus_notifier; | 225 | otg_sx->vbus_nb.notifier_call = ssusb_vbus_notifier; |
226 | ret = extcon_register_notifier(edev, EXTCON_USB, | 226 | ret = devm_extcon_register_notifier(ssusb->dev, edev, EXTCON_USB, |
227 | &otg_sx->vbus_nb); | 227 | &otg_sx->vbus_nb); |
228 | if (ret < 0) | 228 | if (ret < 0) |
229 | dev_err(ssusb->dev, "failed to register notifier for USB\n"); | 229 | dev_err(ssusb->dev, "failed to register notifier for USB\n"); |
230 | 230 | ||
231 | otg_sx->id_nb.notifier_call = ssusb_id_notifier; | 231 | otg_sx->id_nb.notifier_call = ssusb_id_notifier; |
232 | ret = extcon_register_notifier(edev, EXTCON_USB_HOST, | 232 | ret = devm_extcon_register_notifier(ssusb->dev, edev, EXTCON_USB_HOST, |
233 | &otg_sx->id_nb); | 233 | &otg_sx->id_nb); |
234 | if (ret < 0) | 234 | if (ret < 0) |
235 | dev_err(ssusb->dev, "failed to register notifier for USB-HOST\n"); | 235 | dev_err(ssusb->dev, "failed to register notifier for USB-HOST\n"); |
236 | 236 | ||
237 | dev_dbg(ssusb->dev, "EXTCON_USB: %d, EXTCON_USB_HOST: %d\n", | 237 | dev_dbg(ssusb->dev, "EXTCON_USB: %d, EXTCON_USB_HOST: %d\n", |
238 | extcon_get_cable_state_(edev, EXTCON_USB), | 238 | extcon_get_state(edev, EXTCON_USB), |
239 | extcon_get_cable_state_(edev, EXTCON_USB_HOST)); | 239 | extcon_get_state(edev, EXTCON_USB_HOST)); |
240 | 240 | ||
241 | /* default as host, switch to device mode if needed */ | 241 | /* default as host, switch to device mode if needed */ |
242 | if (extcon_get_cable_state_(edev, EXTCON_USB_HOST) == false) | 242 | if (extcon_get_state(edev, EXTCON_USB_HOST) == false) |
243 | ssusb_set_mailbox(otg_sx, MTU3_ID_FLOAT); | 243 | ssusb_set_mailbox(otg_sx, MTU3_ID_FLOAT); |
244 | if (extcon_get_cable_state_(edev, EXTCON_USB) == true) | 244 | if (extcon_get_state(edev, EXTCON_USB) == true) |
245 | ssusb_set_mailbox(otg_sx, MTU3_VBUS_VALID); | 245 | ssusb_set_mailbox(otg_sx, MTU3_VBUS_VALID); |
246 | 246 | ||
247 | return 0; | 247 | return 0; |
@@ -367,13 +367,6 @@ void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb) | |||
367 | 367 | ||
368 | cancel_delayed_work(&otg_sx->extcon_reg_dwork); | 368 | cancel_delayed_work(&otg_sx->extcon_reg_dwork); |
369 | 369 | ||
370 | if (otg_sx->edev) { | ||
371 | extcon_unregister_notifier(otg_sx->edev, | ||
372 | EXTCON_USB, &otg_sx->vbus_nb); | ||
373 | extcon_unregister_notifier(otg_sx->edev, | ||
374 | EXTCON_USB_HOST, &otg_sx->id_nb); | ||
375 | } | ||
376 | |||
377 | if (otg_sx->manual_drd_enabled) | 370 | if (otg_sx->manual_drd_enabled) |
378 | ssusb_debugfs_exit(ssusb); | 371 | ssusb_debugfs_exit(ssusb); |
379 | } | 372 | } |
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 72a2a5040848..5506a9c03c1f 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig | |||
@@ -160,8 +160,8 @@ config USB_TI_CPPI_DMA | |||
160 | Enable DMA transfers when TI CPPI DMA is available. | 160 | Enable DMA transfers when TI CPPI DMA is available. |
161 | 161 | ||
162 | config USB_TI_CPPI41_DMA | 162 | config USB_TI_CPPI41_DMA |
163 | bool 'TI CPPI 4.1 (AM335x)' | 163 | bool 'TI CPPI 4.1' |
164 | depends on ARCH_OMAP && DMADEVICES | 164 | depends on (ARCH_OMAP || ARCH_DAVINCI_DA8XX) && DMADEVICES |
165 | select TI_CPPI41 | 165 | select TI_CPPI41 |
166 | 166 | ||
167 | config USB_TUSB_OMAP_DMA | 167 | config USB_TUSB_OMAP_DMA |
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index c4fabe952ca6..a13bd3625043 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c | |||
@@ -582,9 +582,10 @@ cppi_next_tx_segment(struct musb *musb, struct cppi_channel *tx) | |||
582 | maxpacket = length; | 582 | maxpacket = length; |
583 | n_bds = 1; | 583 | n_bds = 1; |
584 | } else { | 584 | } else { |
585 | n_bds = length / maxpacket; | 585 | if (length) |
586 | if (!length || (length % maxpacket)) | 586 | n_bds = DIV_ROUND_UP(length, maxpacket); |
587 | n_bds++; | 587 | else |
588 | n_bds = 1; | ||
588 | n_bds = min(n_bds, (unsigned) NUM_TXCHAN_BD); | 589 | n_bds = min(n_bds, (unsigned) NUM_TXCHAN_BD); |
589 | length = min(n_bds * maxpacket, length); | 590 | length = min(n_bds * maxpacket, length); |
590 | } | 591 | } |
@@ -790,9 +791,7 @@ cppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket) | |||
790 | n_bds = 0xffff / maxpacket; | 791 | n_bds = 0xffff / maxpacket; |
791 | length = n_bds * maxpacket; | 792 | length = n_bds * maxpacket; |
792 | } else { | 793 | } else { |
793 | n_bds = length / maxpacket; | 794 | n_bds = DIV_ROUND_UP(length, maxpacket); |
794 | if (length % maxpacket) | ||
795 | n_bds++; | ||
796 | } | 795 | } |
797 | if (n_bds == 1) | 796 | if (n_bds == 1) |
798 | onepacket = 1; | 797 | onepacket = 1; |
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c index d79c288ccbf2..df88123274ca 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/clk.h> | 33 | #include <linux/clk.h> |
34 | #include <linux/err.h> | 34 | #include <linux/err.h> |
35 | #include <linux/io.h> | 35 | #include <linux/io.h> |
36 | #include <linux/of_platform.h> | ||
36 | #include <linux/phy/phy.h> | 37 | #include <linux/phy/phy.h> |
37 | #include <linux/platform_device.h> | 38 | #include <linux/platform_device.h> |
38 | #include <linux/dma-mapping.h> | 39 | #include <linux/dma-mapping.h> |
@@ -456,12 +457,41 @@ static inline u8 get_vbus_power(struct device *dev) | |||
456 | return current_uA / 1000 / 2; | 457 | return current_uA / 1000 / 2; |
457 | } | 458 | } |
458 | 459 | ||
460 | #ifdef CONFIG_USB_TI_CPPI41_DMA | ||
461 | static void da8xx_dma_controller_callback(struct dma_controller *c) | ||
462 | { | ||
463 | struct musb *musb = c->musb; | ||
464 | void __iomem *reg_base = musb->ctrl_base; | ||
465 | |||
466 | musb_writel(reg_base, DA8XX_USB_END_OF_INTR_REG, 0); | ||
467 | } | ||
468 | |||
469 | static struct dma_controller * | ||
470 | da8xx_dma_controller_create(struct musb *musb, void __iomem *base) | ||
471 | { | ||
472 | struct dma_controller *controller; | ||
473 | |||
474 | controller = cppi41_dma_controller_create(musb, base); | ||
475 | if (IS_ERR_OR_NULL(controller)) | ||
476 | return controller; | ||
477 | |||
478 | controller->dma_callback = da8xx_dma_controller_callback; | ||
479 | |||
480 | return controller; | ||
481 | } | ||
482 | #endif | ||
483 | |||
459 | static const struct musb_platform_ops da8xx_ops = { | 484 | static const struct musb_platform_ops da8xx_ops = { |
460 | .quirks = MUSB_INDEXED_EP | MUSB_PRESERVE_SESSION, | 485 | .quirks = MUSB_INDEXED_EP | MUSB_PRESERVE_SESSION | |
486 | MUSB_DMA_CPPI41 | MUSB_DA8XX, | ||
461 | .init = da8xx_musb_init, | 487 | .init = da8xx_musb_init, |
462 | .exit = da8xx_musb_exit, | 488 | .exit = da8xx_musb_exit, |
463 | 489 | ||
464 | .fifo_mode = 2, | 490 | .fifo_mode = 2, |
491 | #ifdef CONFIG_USB_TI_CPPI41_DMA | ||
492 | .dma_init = da8xx_dma_controller_create, | ||
493 | .dma_exit = cppi41_dma_controller_destroy, | ||
494 | #endif | ||
465 | .enable = da8xx_musb_enable, | 495 | .enable = da8xx_musb_enable, |
466 | .disable = da8xx_musb_disable, | 496 | .disable = da8xx_musb_disable, |
467 | 497 | ||
@@ -483,6 +513,12 @@ static const struct musb_hdrc_config da8xx_config = { | |||
483 | .multipoint = 1, | 513 | .multipoint = 1, |
484 | }; | 514 | }; |
485 | 515 | ||
516 | static struct of_dev_auxdata da8xx_auxdata_lookup[] = { | ||
517 | OF_DEV_AUXDATA("ti,da830-cppi41", 0x01e01000, "cppi41-dmaengine", | ||
518 | NULL), | ||
519 | {} | ||
520 | }; | ||
521 | |||
486 | static int da8xx_probe(struct platform_device *pdev) | 522 | static int da8xx_probe(struct platform_device *pdev) |
487 | { | 523 | { |
488 | struct resource musb_resources[2]; | 524 | struct resource musb_resources[2]; |
@@ -533,6 +569,11 @@ static int da8xx_probe(struct platform_device *pdev) | |||
533 | } | 569 | } |
534 | platform_set_drvdata(pdev, glue); | 570 | platform_set_drvdata(pdev, glue); |
535 | 571 | ||
572 | ret = of_platform_populate(pdev->dev.of_node, NULL, | ||
573 | da8xx_auxdata_lookup, &pdev->dev); | ||
574 | if (ret) | ||
575 | return ret; | ||
576 | |||
536 | memset(musb_resources, 0x00, sizeof(*musb_resources) * | 577 | memset(musb_resources, 0x00, sizeof(*musb_resources) * |
537 | ARRAY_SIZE(musb_resources)); | 578 | ARRAY_SIZE(musb_resources)); |
538 | 579 | ||
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 0c3664ab705e..870da18f5077 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c | |||
@@ -2332,7 +2332,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) | |||
2332 | setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb); | 2332 | setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb); |
2333 | 2333 | ||
2334 | /* attach to the IRQ */ | 2334 | /* attach to the IRQ */ |
2335 | if (request_irq(nIrq, musb->isr, 0, dev_name(dev), musb)) { | 2335 | if (request_irq(nIrq, musb->isr, IRQF_SHARED, dev_name(dev), musb)) { |
2336 | dev_err(dev, "request_irq %d failed!\n", nIrq); | 2336 | dev_err(dev, "request_irq %d failed!\n", nIrq); |
2337 | status = -ENODEV; | 2337 | status = -ENODEV; |
2338 | goto fail3; | 2338 | goto fail3; |
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 5b708be6d1d1..3e98d4268a64 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h | |||
@@ -172,6 +172,7 @@ struct musb_io; | |||
172 | */ | 172 | */ |
173 | struct musb_platform_ops { | 173 | struct musb_platform_ops { |
174 | 174 | ||
175 | #define MUSB_DA8XX BIT(8) | ||
175 | #define MUSB_PRESERVE_SESSION BIT(7) | 176 | #define MUSB_PRESERVE_SESSION BIT(7) |
176 | #define MUSB_DMA_UX500 BIT(6) | 177 | #define MUSB_DMA_UX500 BIT(6) |
177 | #define MUSB_DMA_CPPI41 BIT(5) | 178 | #define MUSB_DMA_CPPI41 BIT(5) |
diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c index 355655f8a3fb..e7c8b1b8bf22 100644 --- a/drivers/usb/musb/musb_cppi41.c +++ b/drivers/usb/musb/musb_cppi41.c | |||
@@ -571,6 +571,10 @@ static int cppi41_dma_channel_abort(struct dma_channel *channel) | |||
571 | } | 571 | } |
572 | } | 572 | } |
573 | 573 | ||
574 | /* DA8xx Advisory 2.3.27: wait 250 ms before to start the teardown */ | ||
575 | if (musb->io.quirks & MUSB_DA8XX) | ||
576 | mdelay(250); | ||
577 | |||
574 | tdbit = 1 << cppi41_channel->port_num; | 578 | tdbit = 1 << cppi41_channel->port_num; |
575 | if (is_tx) | 579 | if (is_tx) |
576 | tdbit <<= 16; | 580 | tdbit <<= 16; |
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 61cef7511a50..3006f569c068 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig | |||
@@ -74,13 +74,6 @@ config AM335X_PHY_USB | |||
74 | This driver provides PHY support for that phy which part for the | 74 | This driver provides PHY support for that phy which part for the |
75 | AM335x SoC. | 75 | AM335x SoC. |
76 | 76 | ||
77 | config SAMSUNG_USBPHY | ||
78 | tristate | ||
79 | help | ||
80 | Enable this to support Samsung USB phy helper driver for Samsung SoCs. | ||
81 | This driver provides common interface to interact, for Samsung USB 2.0 PHY | ||
82 | driver and later for Samsung USB 3.0 PHY driver. | ||
83 | |||
84 | config TWL6030_USB | 77 | config TWL6030_USB |
85 | tristate "TWL6030 USB Transceiver Driver" | 78 | tristate "TWL6030 USB Transceiver Driver" |
86 | depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS | 79 | depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS |
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index b433e5d89be4..e7c9ca8cafb0 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile | |||
@@ -14,7 +14,6 @@ obj-$(CONFIG_TAHVO_USB) += phy-tahvo.o | |||
14 | obj-$(CONFIG_AM335X_CONTROL_USB) += phy-am335x-control.o | 14 | obj-$(CONFIG_AM335X_CONTROL_USB) += phy-am335x-control.o |
15 | obj-$(CONFIG_AM335X_PHY_USB) += phy-am335x.o | 15 | obj-$(CONFIG_AM335X_PHY_USB) += phy-am335x.o |
16 | obj-$(CONFIG_OMAP_OTG) += phy-omap-otg.o | 16 | obj-$(CONFIG_OMAP_OTG) += phy-omap-otg.o |
17 | obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o | ||
18 | obj-$(CONFIG_TWL6030_USB) += phy-twl6030-usb.o | 17 | obj-$(CONFIG_TWL6030_USB) += phy-twl6030-usb.o |
19 | obj-$(CONFIG_USB_EHCI_TEGRA) += phy-tegra-usb.o | 18 | obj-$(CONFIG_USB_EHCI_TEGRA) += phy-tegra-usb.o |
20 | obj-$(CONFIG_USB_GPIO_VBUS) += phy-gpio-vbus-usb.o | 19 | obj-$(CONFIG_USB_GPIO_VBUS) += phy-gpio-vbus-usb.o |
diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c index 392ab422163c..cf8f40ae6e01 100644 --- a/drivers/usb/phy/phy-fsl-usb.c +++ b/drivers/usb/phy/phy-fsl-usb.c | |||
@@ -44,6 +44,13 @@ | |||
44 | 44 | ||
45 | #include "phy-fsl-usb.h" | 45 | #include "phy-fsl-usb.h" |
46 | 46 | ||
47 | #ifdef VERBOSE | ||
48 | #define VDBG(fmt, args...) pr_debug("[%s] " fmt, \ | ||
49 | __func__, ## args) | ||
50 | #else | ||
51 | #define VDBG(stuff...) do {} while (0) | ||
52 | #endif | ||
53 | |||
47 | #define DRIVER_VERSION "Rev. 1.55" | 54 | #define DRIVER_VERSION "Rev. 1.55" |
48 | #define DRIVER_AUTHOR "Jerry Huang/Li Yang" | 55 | #define DRIVER_AUTHOR "Jerry Huang/Li Yang" |
49 | #define DRIVER_DESC "Freescale USB OTG Transceiver Driver" | 56 | #define DRIVER_DESC "Freescale USB OTG Transceiver Driver" |
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c index 80a9845cd93f..569c2200ba42 100644 --- a/drivers/usb/serial/aircable.c +++ b/drivers/usb/serial/aircable.c | |||
@@ -29,12 +29,6 @@ | |||
29 | * is any other control code, I will simply check for the first | 29 | * is any other control code, I will simply check for the first |
30 | * one. | 30 | * one. |
31 | * | 31 | * |
32 | * The driver registers himself with the USB-serial core and the USB Core. I had | ||
33 | * to implement a probe function against USB-serial, because other way, the | ||
34 | * driver was attaching himself to both interfaces. I have tried with different | ||
35 | * configurations of usb_serial_driver with out exit, only the probe function | ||
36 | * could handle this correctly. | ||
37 | * | ||
38 | * I have taken some info from a Greg Kroah-Hartman article: | 32 | * I have taken some info from a Greg Kroah-Hartman article: |
39 | * http://www.linuxjournal.com/article/6573 | 33 | * http://www.linuxjournal.com/article/6573 |
40 | * And from Linux Device Driver Kit CD, which is a great work, the authors taken | 34 | * And from Linux Device Driver Kit CD, which is a great work, the authors taken |
@@ -93,30 +87,17 @@ static int aircable_prepare_write_buffer(struct usb_serial_port *port, | |||
93 | return count + HCI_HEADER_LENGTH; | 87 | return count + HCI_HEADER_LENGTH; |
94 | } | 88 | } |
95 | 89 | ||
96 | static int aircable_probe(struct usb_serial *serial, | 90 | static int aircable_calc_num_ports(struct usb_serial *serial, |
97 | const struct usb_device_id *id) | 91 | struct usb_serial_endpoints *epds) |
98 | { | 92 | { |
99 | struct usb_host_interface *iface_desc = serial->interface-> | 93 | /* Ignore the first interface, which has no bulk endpoints. */ |
100 | cur_altsetting; | 94 | if (epds->num_bulk_out == 0) { |
101 | struct usb_endpoint_descriptor *endpoint; | 95 | dev_dbg(&serial->interface->dev, |
102 | int num_bulk_out = 0; | 96 | "ignoring interface with no bulk-out endpoints\n"); |
103 | int i; | ||
104 | |||
105 | for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { | ||
106 | endpoint = &iface_desc->endpoint[i].desc; | ||
107 | if (usb_endpoint_is_bulk_out(endpoint)) { | ||
108 | dev_dbg(&serial->dev->dev, | ||
109 | "found bulk out on endpoint %d\n", i); | ||
110 | ++num_bulk_out; | ||
111 | } | ||
112 | } | ||
113 | |||
114 | if (num_bulk_out == 0) { | ||
115 | dev_dbg(&serial->dev->dev, "Invalid interface, discarding\n"); | ||
116 | return -ENODEV; | 97 | return -ENODEV; |
117 | } | 98 | } |
118 | 99 | ||
119 | return 0; | 100 | return 1; |
120 | } | 101 | } |
121 | 102 | ||
122 | static int aircable_process_packet(struct usb_serial_port *port, | 103 | static int aircable_process_packet(struct usb_serial_port *port, |
@@ -164,9 +145,8 @@ static struct usb_serial_driver aircable_device = { | |||
164 | .name = "aircable", | 145 | .name = "aircable", |
165 | }, | 146 | }, |
166 | .id_table = id_table, | 147 | .id_table = id_table, |
167 | .num_ports = 1, | ||
168 | .bulk_out_size = HCI_COMPLETE_FRAME, | 148 | .bulk_out_size = HCI_COMPLETE_FRAME, |
169 | .probe = aircable_probe, | 149 | .calc_num_ports = aircable_calc_num_ports, |
170 | .process_read_urb = aircable_process_read_urb, | 150 | .process_read_urb = aircable_process_read_urb, |
171 | .prepare_write_buffer = aircable_prepare_write_buffer, | 151 | .prepare_write_buffer = aircable_prepare_write_buffer, |
172 | .throttle = usb_serial_generic_throttle, | 152 | .throttle = usb_serial_generic_throttle, |
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index 2779e59c30f1..0adbd38b4eea 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c | |||
@@ -122,19 +122,6 @@ static inline int calc_divisor(int bps) | |||
122 | return (12000000 + 2*bps) / (4*bps); | 122 | return (12000000 + 2*bps) / (4*bps); |
123 | } | 123 | } |
124 | 124 | ||
125 | static int ark3116_attach(struct usb_serial *serial) | ||
126 | { | ||
127 | /* make sure we have our end-points */ | ||
128 | if (serial->num_bulk_in == 0 || | ||
129 | serial->num_bulk_out == 0 || | ||
130 | serial->num_interrupt_in == 0) { | ||
131 | dev_err(&serial->interface->dev, "missing endpoint\n"); | ||
132 | return -ENODEV; | ||
133 | } | ||
134 | |||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static int ark3116_port_probe(struct usb_serial_port *port) | 125 | static int ark3116_port_probe(struct usb_serial_port *port) |
139 | { | 126 | { |
140 | struct usb_serial *serial = port->serial; | 127 | struct usb_serial *serial = port->serial; |
@@ -671,7 +658,9 @@ static struct usb_serial_driver ark3116_device = { | |||
671 | }, | 658 | }, |
672 | .id_table = id_table, | 659 | .id_table = id_table, |
673 | .num_ports = 1, | 660 | .num_ports = 1, |
674 | .attach = ark3116_attach, | 661 | .num_bulk_in = 1, |
662 | .num_bulk_out = 1, | ||
663 | .num_interrupt_in = 1, | ||
675 | .port_probe = ark3116_port_probe, | 664 | .port_probe = ark3116_port_probe, |
676 | .port_remove = ark3116_port_remove, | 665 | .port_remove = ark3116_port_remove, |
677 | .set_termios = ark3116_set_termios, | 666 | .set_termios = ark3116_set_termios, |
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 80260b08398b..47fbd9f0c0c7 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c | |||
@@ -50,7 +50,6 @@ | |||
50 | #define CYBERJACK_PRODUCT_ID 0x0100 | 50 | #define CYBERJACK_PRODUCT_ID 0x0100 |
51 | 51 | ||
52 | /* Function prototypes */ | 52 | /* Function prototypes */ |
53 | static int cyberjack_attach(struct usb_serial *serial); | ||
54 | static int cyberjack_port_probe(struct usb_serial_port *port); | 53 | static int cyberjack_port_probe(struct usb_serial_port *port); |
55 | static int cyberjack_port_remove(struct usb_serial_port *port); | 54 | static int cyberjack_port_remove(struct usb_serial_port *port); |
56 | static int cyberjack_open(struct tty_struct *tty, | 55 | static int cyberjack_open(struct tty_struct *tty, |
@@ -78,7 +77,7 @@ static struct usb_serial_driver cyberjack_device = { | |||
78 | .description = "Reiner SCT Cyberjack USB card reader", | 77 | .description = "Reiner SCT Cyberjack USB card reader", |
79 | .id_table = id_table, | 78 | .id_table = id_table, |
80 | .num_ports = 1, | 79 | .num_ports = 1, |
81 | .attach = cyberjack_attach, | 80 | .num_bulk_out = 1, |
82 | .port_probe = cyberjack_port_probe, | 81 | .port_probe = cyberjack_port_probe, |
83 | .port_remove = cyberjack_port_remove, | 82 | .port_remove = cyberjack_port_remove, |
84 | .open = cyberjack_open, | 83 | .open = cyberjack_open, |
@@ -102,14 +101,6 @@ struct cyberjack_private { | |||
102 | short wrsent; /* Data already sent */ | 101 | short wrsent; /* Data already sent */ |
103 | }; | 102 | }; |
104 | 103 | ||
105 | static int cyberjack_attach(struct usb_serial *serial) | ||
106 | { | ||
107 | if (serial->num_bulk_out < serial->num_ports) | ||
108 | return -ENODEV; | ||
109 | |||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | static int cyberjack_port_probe(struct usb_serial_port *port) | 104 | static int cyberjack_port_probe(struct usb_serial_port *port) |
114 | { | 105 | { |
115 | struct cyberjack_private *priv; | 106 | struct cyberjack_private *priv; |
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 6537d3ca2797..2ce39af32cfa 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c | |||
@@ -273,6 +273,8 @@ static struct usb_serial_driver digi_acceleport_2_device = { | |||
273 | .description = "Digi 2 port USB adapter", | 273 | .description = "Digi 2 port USB adapter", |
274 | .id_table = id_table_2, | 274 | .id_table = id_table_2, |
275 | .num_ports = 3, | 275 | .num_ports = 3, |
276 | .num_bulk_in = 4, | ||
277 | .num_bulk_out = 4, | ||
276 | .open = digi_open, | 278 | .open = digi_open, |
277 | .close = digi_close, | 279 | .close = digi_close, |
278 | .dtr_rts = digi_dtr_rts, | 280 | .dtr_rts = digi_dtr_rts, |
@@ -302,6 +304,8 @@ static struct usb_serial_driver digi_acceleport_4_device = { | |||
302 | .description = "Digi 4 port USB adapter", | 304 | .description = "Digi 4 port USB adapter", |
303 | .id_table = id_table_4, | 305 | .id_table = id_table_4, |
304 | .num_ports = 4, | 306 | .num_ports = 4, |
307 | .num_bulk_in = 5, | ||
308 | .num_bulk_out = 5, | ||
305 | .open = digi_open, | 309 | .open = digi_open, |
306 | .close = digi_close, | 310 | .close = digi_close, |
307 | .write = digi_write, | 311 | .write = digi_write, |
@@ -1251,27 +1255,8 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num) | |||
1251 | 1255 | ||
1252 | static int digi_startup(struct usb_serial *serial) | 1256 | static int digi_startup(struct usb_serial *serial) |
1253 | { | 1257 | { |
1254 | struct device *dev = &serial->interface->dev; | ||
1255 | struct digi_serial *serial_priv; | 1258 | struct digi_serial *serial_priv; |
1256 | int ret; | 1259 | int ret; |
1257 | int i; | ||
1258 | |||
1259 | /* check whether the device has the expected number of endpoints */ | ||
1260 | if (serial->num_port_pointers < serial->type->num_ports + 1) { | ||
1261 | dev_err(dev, "OOB endpoints missing\n"); | ||
1262 | return -ENODEV; | ||
1263 | } | ||
1264 | |||
1265 | for (i = 0; i < serial->type->num_ports + 1 ; i++) { | ||
1266 | if (!serial->port[i]->read_urb) { | ||
1267 | dev_err(dev, "bulk-in endpoint missing\n"); | ||
1268 | return -ENODEV; | ||
1269 | } | ||
1270 | if (!serial->port[i]->write_urb) { | ||
1271 | dev_err(dev, "bulk-out endpoint missing\n"); | ||
1272 | return -ENODEV; | ||
1273 | } | ||
1274 | } | ||
1275 | 1260 | ||
1276 | serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL); | 1261 | serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL); |
1277 | if (!serial_priv) | 1262 | if (!serial_priv) |
diff --git a/drivers/usb/serial/f81534.c b/drivers/usb/serial/f81534.c index 22f23a429a95..3d616a2a9f96 100644 --- a/drivers/usb/serial/f81534.c +++ b/drivers/usb/serial/f81534.c | |||
@@ -611,20 +611,30 @@ static int f81534_find_config_idx(struct usb_serial *serial, u8 *index) | |||
611 | * The f81534_calc_num_ports() will run to "new style" with checking | 611 | * The f81534_calc_num_ports() will run to "new style" with checking |
612 | * F81534_PORT_UNAVAILABLE section. | 612 | * F81534_PORT_UNAVAILABLE section. |
613 | */ | 613 | */ |
614 | static int f81534_calc_num_ports(struct usb_serial *serial) | 614 | static int f81534_calc_num_ports(struct usb_serial *serial, |
615 | struct usb_serial_endpoints *epds) | ||
615 | { | 616 | { |
617 | struct device *dev = &serial->interface->dev; | ||
618 | int size_bulk_in = usb_endpoint_maxp(epds->bulk_in[0]); | ||
619 | int size_bulk_out = usb_endpoint_maxp(epds->bulk_out[0]); | ||
616 | u8 setting[F81534_CUSTOM_DATA_SIZE]; | 620 | u8 setting[F81534_CUSTOM_DATA_SIZE]; |
617 | u8 setting_idx; | 621 | u8 setting_idx; |
618 | u8 num_port = 0; | 622 | u8 num_port = 0; |
619 | int status; | 623 | int status; |
620 | size_t i; | 624 | size_t i; |
621 | 625 | ||
626 | if (size_bulk_out != F81534_WRITE_BUFFER_SIZE || | ||
627 | size_bulk_in != F81534_MAX_RECEIVE_BLOCK_SIZE) { | ||
628 | dev_err(dev, "unsupported endpoint max packet size\n"); | ||
629 | return -ENODEV; | ||
630 | } | ||
631 | |||
622 | /* Check had custom setting */ | 632 | /* Check had custom setting */ |
623 | status = f81534_find_config_idx(serial, &setting_idx); | 633 | status = f81534_find_config_idx(serial, &setting_idx); |
624 | if (status) { | 634 | if (status) { |
625 | dev_err(&serial->interface->dev, "%s: find idx failed: %d\n", | 635 | dev_err(&serial->interface->dev, "%s: find idx failed: %d\n", |
626 | __func__, status); | 636 | __func__, status); |
627 | return 0; | 637 | return status; |
628 | } | 638 | } |
629 | 639 | ||
630 | /* | 640 | /* |
@@ -640,7 +650,7 @@ static int f81534_calc_num_ports(struct usb_serial *serial) | |||
640 | dev_err(&serial->interface->dev, | 650 | dev_err(&serial->interface->dev, |
641 | "%s: get custom data failed: %d\n", | 651 | "%s: get custom data failed: %d\n", |
642 | __func__, status); | 652 | __func__, status); |
643 | return 0; | 653 | return status; |
644 | } | 654 | } |
645 | 655 | ||
646 | dev_dbg(&serial->interface->dev, | 656 | dev_dbg(&serial->interface->dev, |
@@ -656,7 +666,7 @@ static int f81534_calc_num_ports(struct usb_serial *serial) | |||
656 | dev_err(&serial->interface->dev, | 666 | dev_err(&serial->interface->dev, |
657 | "%s: read failed: %d\n", __func__, | 667 | "%s: read failed: %d\n", __func__, |
658 | status); | 668 | status); |
659 | return 0; | 669 | return status; |
660 | } | 670 | } |
661 | 671 | ||
662 | dev_dbg(&serial->interface->dev, "%s: read default config\n", | 672 | dev_dbg(&serial->interface->dev, "%s: read default config\n", |
@@ -671,12 +681,24 @@ static int f81534_calc_num_ports(struct usb_serial *serial) | |||
671 | ++num_port; | 681 | ++num_port; |
672 | } | 682 | } |
673 | 683 | ||
674 | if (num_port) | 684 | if (!num_port) { |
675 | return num_port; | 685 | dev_warn(&serial->interface->dev, |
686 | "no config found, assuming 4 ports\n"); | ||
687 | num_port = 4; /* Nothing found, oldest version IC */ | ||
688 | } | ||
689 | |||
690 | /* | ||
691 | * Setup bulk-out endpoint multiplexing. All ports share the same | ||
692 | * bulk-out endpoint. | ||
693 | */ | ||
694 | BUILD_BUG_ON(ARRAY_SIZE(epds->bulk_out) < F81534_NUM_PORT); | ||
695 | |||
696 | for (i = 1; i < num_port; ++i) | ||
697 | epds->bulk_out[i] = epds->bulk_out[0]; | ||
676 | 698 | ||
677 | dev_warn(&serial->interface->dev, "%s: Read Failed. default 4 ports\n", | 699 | epds->num_bulk_out = num_port; |
678 | __func__); | 700 | |
679 | return 4; /* Nothing found, oldest version IC */ | 701 | return num_port; |
680 | } | 702 | } |
681 | 703 | ||
682 | static void f81534_set_termios(struct tty_struct *tty, | 704 | static void f81534_set_termios(struct tty_struct *tty, |
@@ -1067,96 +1089,6 @@ static void f81534_write_usb_callback(struct urb *urb) | |||
1067 | } | 1089 | } |
1068 | } | 1090 | } |
1069 | 1091 | ||
1070 | static int f81534_setup_ports(struct usb_serial *serial) | ||
1071 | { | ||
1072 | struct usb_serial_port *port; | ||
1073 | u8 port0_out_address; | ||
1074 | int buffer_size; | ||
1075 | size_t i; | ||
1076 | |||
1077 | /* | ||
1078 | * In our system architecture, we had 2 or 4 serial ports, | ||
1079 | * but only get 1 set of bulk in/out endpoints. | ||
1080 | * | ||
1081 | * The usb-serial subsystem will generate port 0 data, | ||
1082 | * but port 1/2/3 will not. It's will generate write URB and buffer | ||
1083 | * by following code and use the port0 read URB for read operation. | ||
1084 | */ | ||
1085 | for (i = 1; i < serial->num_ports; ++i) { | ||
1086 | port0_out_address = serial->port[0]->bulk_out_endpointAddress; | ||
1087 | buffer_size = serial->port[0]->bulk_out_size; | ||
1088 | port = serial->port[i]; | ||
1089 | |||
1090 | if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL)) | ||
1091 | return -ENOMEM; | ||
1092 | |||
1093 | port->bulk_out_size = buffer_size; | ||
1094 | port->bulk_out_endpointAddress = port0_out_address; | ||
1095 | |||
1096 | port->write_urbs[0] = usb_alloc_urb(0, GFP_KERNEL); | ||
1097 | if (!port->write_urbs[0]) | ||
1098 | return -ENOMEM; | ||
1099 | |||
1100 | port->bulk_out_buffers[0] = kzalloc(buffer_size, GFP_KERNEL); | ||
1101 | if (!port->bulk_out_buffers[0]) | ||
1102 | return -ENOMEM; | ||
1103 | |||
1104 | usb_fill_bulk_urb(port->write_urbs[0], serial->dev, | ||
1105 | usb_sndbulkpipe(serial->dev, | ||
1106 | port0_out_address), | ||
1107 | port->bulk_out_buffers[0], buffer_size, | ||
1108 | serial->type->write_bulk_callback, port); | ||
1109 | |||
1110 | port->write_urb = port->write_urbs[0]; | ||
1111 | port->bulk_out_buffer = port->bulk_out_buffers[0]; | ||
1112 | } | ||
1113 | |||
1114 | return 0; | ||
1115 | } | ||
1116 | |||
1117 | static int f81534_probe(struct usb_serial *serial, | ||
1118 | const struct usb_device_id *id) | ||
1119 | { | ||
1120 | struct usb_endpoint_descriptor *endpoint; | ||
1121 | struct usb_host_interface *iface_desc; | ||
1122 | struct device *dev; | ||
1123 | int num_bulk_in = 0; | ||
1124 | int num_bulk_out = 0; | ||
1125 | int size_bulk_in = 0; | ||
1126 | int size_bulk_out = 0; | ||
1127 | int i; | ||
1128 | |||
1129 | dev = &serial->interface->dev; | ||
1130 | iface_desc = serial->interface->cur_altsetting; | ||
1131 | |||
1132 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | ||
1133 | endpoint = &iface_desc->endpoint[i].desc; | ||
1134 | |||
1135 | if (usb_endpoint_is_bulk_in(endpoint)) { | ||
1136 | ++num_bulk_in; | ||
1137 | size_bulk_in = usb_endpoint_maxp(endpoint); | ||
1138 | } | ||
1139 | |||
1140 | if (usb_endpoint_is_bulk_out(endpoint)) { | ||
1141 | ++num_bulk_out; | ||
1142 | size_bulk_out = usb_endpoint_maxp(endpoint); | ||
1143 | } | ||
1144 | } | ||
1145 | |||
1146 | if (num_bulk_in != 1 || num_bulk_out != 1) { | ||
1147 | dev_err(dev, "expected endpoints not found\n"); | ||
1148 | return -ENODEV; | ||
1149 | } | ||
1150 | |||
1151 | if (size_bulk_out != F81534_WRITE_BUFFER_SIZE || | ||
1152 | size_bulk_in != F81534_MAX_RECEIVE_BLOCK_SIZE) { | ||
1153 | dev_err(dev, "unsupported endpoint max packet size\n"); | ||
1154 | return -ENODEV; | ||
1155 | } | ||
1156 | |||
1157 | return 0; | ||
1158 | } | ||
1159 | |||
1160 | static int f81534_attach(struct usb_serial *serial) | 1092 | static int f81534_attach(struct usb_serial *serial) |
1161 | { | 1093 | { |
1162 | struct f81534_serial_private *serial_priv; | 1094 | struct f81534_serial_private *serial_priv; |
@@ -1173,10 +1105,6 @@ static int f81534_attach(struct usb_serial *serial) | |||
1173 | 1105 | ||
1174 | mutex_init(&serial_priv->urb_mutex); | 1106 | mutex_init(&serial_priv->urb_mutex); |
1175 | 1107 | ||
1176 | status = f81534_setup_ports(serial); | ||
1177 | if (status) | ||
1178 | return status; | ||
1179 | |||
1180 | /* Check had custom setting */ | 1108 | /* Check had custom setting */ |
1181 | status = f81534_find_config_idx(serial, &serial_priv->setting_idx); | 1109 | status = f81534_find_config_idx(serial, &serial_priv->setting_idx); |
1182 | if (status) { | 1110 | if (status) { |
@@ -1380,12 +1308,13 @@ static struct usb_serial_driver f81534_device = { | |||
1380 | }, | 1308 | }, |
1381 | .description = DRIVER_DESC, | 1309 | .description = DRIVER_DESC, |
1382 | .id_table = f81534_id_table, | 1310 | .id_table = f81534_id_table, |
1311 | .num_bulk_in = 1, | ||
1312 | .num_bulk_out = 1, | ||
1383 | .open = f81534_open, | 1313 | .open = f81534_open, |
1384 | .close = f81534_close, | 1314 | .close = f81534_close, |
1385 | .write = f81534_write, | 1315 | .write = f81534_write, |
1386 | .tx_empty = f81534_tx_empty, | 1316 | .tx_empty = f81534_tx_empty, |
1387 | .calc_num_ports = f81534_calc_num_ports, | 1317 | .calc_num_ports = f81534_calc_num_ports, |
1388 | .probe = f81534_probe, | ||
1389 | .attach = f81534_attach, | 1318 | .attach = f81534_attach, |
1390 | .port_probe = f81534_port_probe, | 1319 | .port_probe = f81534_port_probe, |
1391 | .dtr_rts = f81534_dtr_rts, | 1320 | .dtr_rts = f81534_dtr_rts, |
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index c540de15aad2..d38780fa8788 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -873,6 +873,7 @@ static const struct usb_device_id id_table_combined[] = { | |||
873 | { USB_DEVICE_AND_INTERFACE_INFO(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID, | 873 | { USB_DEVICE_AND_INTERFACE_INFO(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID, |
874 | USB_CLASS_VENDOR_SPEC, | 874 | USB_CLASS_VENDOR_SPEC, |
875 | USB_SUBCLASS_VENDOR_SPEC, 0x00) }, | 875 | USB_SUBCLASS_VENDOR_SPEC, 0x00) }, |
876 | { USB_DEVICE_INTERFACE_NUMBER(ACTEL_VID, MICROSEMI_ARROW_SF2PLUS_BOARD_PID, 2) }, | ||
876 | { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) }, | 877 | { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) }, |
877 | { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID), | 878 | { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID), |
878 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | 879 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, |
@@ -1406,6 +1407,9 @@ static int write_latency_timer(struct usb_serial_port *port) | |||
1406 | int rv; | 1407 | int rv; |
1407 | int l = priv->latency; | 1408 | int l = priv->latency; |
1408 | 1409 | ||
1410 | if (priv->chip_type == SIO || priv->chip_type == FT8U232AM) | ||
1411 | return -EINVAL; | ||
1412 | |||
1409 | if (priv->flags & ASYNC_LOW_LATENCY) | 1413 | if (priv->flags & ASYNC_LOW_LATENCY) |
1410 | l = 1; | 1414 | l = 1; |
1411 | 1415 | ||
@@ -1422,7 +1426,7 @@ static int write_latency_timer(struct usb_serial_port *port) | |||
1422 | return rv; | 1426 | return rv; |
1423 | } | 1427 | } |
1424 | 1428 | ||
1425 | static int read_latency_timer(struct usb_serial_port *port) | 1429 | static int _read_latency_timer(struct usb_serial_port *port) |
1426 | { | 1430 | { |
1427 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1431 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1428 | struct usb_device *udev = port->serial->dev; | 1432 | struct usb_device *udev = port->serial->dev; |
@@ -1440,11 +1444,10 @@ static int read_latency_timer(struct usb_serial_port *port) | |||
1440 | 0, priv->interface, | 1444 | 0, priv->interface, |
1441 | buf, 1, WDR_TIMEOUT); | 1445 | buf, 1, WDR_TIMEOUT); |
1442 | if (rv < 1) { | 1446 | if (rv < 1) { |
1443 | dev_err(&port->dev, "Unable to read latency timer: %i\n", rv); | ||
1444 | if (rv >= 0) | 1447 | if (rv >= 0) |
1445 | rv = -EIO; | 1448 | rv = -EIO; |
1446 | } else { | 1449 | } else { |
1447 | priv->latency = buf[0]; | 1450 | rv = buf[0]; |
1448 | } | 1451 | } |
1449 | 1452 | ||
1450 | kfree(buf); | 1453 | kfree(buf); |
@@ -1452,6 +1455,25 @@ static int read_latency_timer(struct usb_serial_port *port) | |||
1452 | return rv; | 1455 | return rv; |
1453 | } | 1456 | } |
1454 | 1457 | ||
1458 | static int read_latency_timer(struct usb_serial_port *port) | ||
1459 | { | ||
1460 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
1461 | int rv; | ||
1462 | |||
1463 | if (priv->chip_type == SIO || priv->chip_type == FT8U232AM) | ||
1464 | return -EINVAL; | ||
1465 | |||
1466 | rv = _read_latency_timer(port); | ||
1467 | if (rv < 0) { | ||
1468 | dev_err(&port->dev, "Unable to read latency timer: %i\n", rv); | ||
1469 | return rv; | ||
1470 | } | ||
1471 | |||
1472 | priv->latency = rv; | ||
1473 | |||
1474 | return 0; | ||
1475 | } | ||
1476 | |||
1455 | static int get_serial_info(struct usb_serial_port *port, | 1477 | static int get_serial_info(struct usb_serial_port *port, |
1456 | struct serial_struct __user *retinfo) | 1478 | struct serial_struct __user *retinfo) |
1457 | { | 1479 | { |
@@ -1603,9 +1625,19 @@ static void ftdi_determine_type(struct usb_serial_port *port) | |||
1603 | priv->baud_base = 12000000 / 16; | 1625 | priv->baud_base = 12000000 / 16; |
1604 | } else if (version < 0x400) { | 1626 | } else if (version < 0x400) { |
1605 | /* Assume it's an FT8U232AM (or FT8U245AM) */ | 1627 | /* Assume it's an FT8U232AM (or FT8U245AM) */ |
1606 | /* (It might be a BM because of the iSerialNumber bug, | ||
1607 | * but it will still work as an AM device.) */ | ||
1608 | priv->chip_type = FT8U232AM; | 1628 | priv->chip_type = FT8U232AM; |
1629 | /* | ||
1630 | * It might be a BM type because of the iSerialNumber bug. | ||
1631 | * If iSerialNumber==0 and the latency timer is readable, | ||
1632 | * assume it is BM type. | ||
1633 | */ | ||
1634 | if (udev->descriptor.iSerialNumber == 0 && | ||
1635 | _read_latency_timer(port) >= 0) { | ||
1636 | dev_dbg(&port->dev, | ||
1637 | "%s: has latency timer so not an AM type\n", | ||
1638 | __func__); | ||
1639 | priv->chip_type = FT232BM; | ||
1640 | } | ||
1609 | } else if (version < 0x600) { | 1641 | } else if (version < 0x600) { |
1610 | /* Assume it's an FT232BM (or FT245BM) */ | 1642 | /* Assume it's an FT232BM (or FT245BM) */ |
1611 | priv->chip_type = FT232BM; | 1643 | priv->chip_type = FT232BM; |
@@ -1685,9 +1717,12 @@ static ssize_t latency_timer_store(struct device *dev, | |||
1685 | { | 1717 | { |
1686 | struct usb_serial_port *port = to_usb_serial_port(dev); | 1718 | struct usb_serial_port *port = to_usb_serial_port(dev); |
1687 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1719 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1688 | int v = simple_strtoul(valbuf, NULL, 10); | 1720 | u8 v; |
1689 | int rv; | 1721 | int rv; |
1690 | 1722 | ||
1723 | if (kstrtou8(valbuf, 10, &v)) | ||
1724 | return -EINVAL; | ||
1725 | |||
1691 | priv->latency = v; | 1726 | priv->latency = v; |
1692 | rv = write_latency_timer(port); | 1727 | rv = write_latency_timer(port); |
1693 | if (rv < 0) | 1728 | if (rv < 0) |
@@ -1704,10 +1739,13 @@ static ssize_t store_event_char(struct device *dev, | |||
1704 | struct usb_serial_port *port = to_usb_serial_port(dev); | 1739 | struct usb_serial_port *port = to_usb_serial_port(dev); |
1705 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1740 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1706 | struct usb_device *udev = port->serial->dev; | 1741 | struct usb_device *udev = port->serial->dev; |
1707 | int v = simple_strtoul(valbuf, NULL, 10); | 1742 | unsigned int v; |
1708 | int rv; | 1743 | int rv; |
1709 | 1744 | ||
1710 | dev_dbg(&port->dev, "%s: setting event char = %i\n", __func__, v); | 1745 | if (kstrtouint(valbuf, 0, &v) || v >= 0x200) |
1746 | return -EINVAL; | ||
1747 | |||
1748 | dev_dbg(&port->dev, "%s: setting event char = 0x%03x\n", __func__, v); | ||
1711 | 1749 | ||
1712 | rv = usb_control_msg(udev, | 1750 | rv = usb_control_msg(udev, |
1713 | usb_sndctrlpipe(udev, 0), | 1751 | usb_sndctrlpipe(udev, 0), |
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 48ee04c94a75..71fb9e59db71 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h | |||
@@ -873,6 +873,12 @@ | |||
873 | #define FIC_VID 0x1457 | 873 | #define FIC_VID 0x1457 |
874 | #define FIC_NEO1973_DEBUG_PID 0x5118 | 874 | #define FIC_NEO1973_DEBUG_PID 0x5118 |
875 | 875 | ||
876 | /* | ||
877 | * Actel / Microsemi | ||
878 | */ | ||
879 | #define ACTEL_VID 0x1514 | ||
880 | #define MICROSEMI_ARROW_SF2PLUS_BOARD_PID 0x2008 | ||
881 | |||
876 | /* Olimex */ | 882 | /* Olimex */ |
877 | #define OLIMEX_VID 0x15BA | 883 | #define OLIMEX_VID 0x15BA |
878 | #define OLIMEX_ARM_USB_OCD_PID 0x0003 | 884 | #define OLIMEX_ARM_USB_OCD_PID 0x0003 |
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 49ce2be90fa0..35cb8c0e584f 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
@@ -37,13 +37,41 @@ MODULE_PARM_DESC(product, "User specified USB idProduct"); | |||
37 | 37 | ||
38 | static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */ | 38 | static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */ |
39 | 39 | ||
40 | struct usb_serial_driver usb_serial_generic_device = { | 40 | static int usb_serial_generic_probe(struct usb_serial *serial, |
41 | const struct usb_device_id *id) | ||
42 | { | ||
43 | struct device *dev = &serial->interface->dev; | ||
44 | |||
45 | dev_info(dev, "The \"generic\" usb-serial driver is only for testing and one-off prototypes.\n"); | ||
46 | dev_info(dev, "Tell linux-usb@vger.kernel.org to add your device to a proper driver.\n"); | ||
47 | |||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | static int usb_serial_generic_calc_num_ports(struct usb_serial *serial, | ||
52 | struct usb_serial_endpoints *epds) | ||
53 | { | ||
54 | struct device *dev = &serial->interface->dev; | ||
55 | int num_ports; | ||
56 | |||
57 | num_ports = max(epds->num_bulk_in, epds->num_bulk_out); | ||
58 | |||
59 | if (num_ports == 0) { | ||
60 | dev_err(dev, "device has no bulk endpoints\n"); | ||
61 | return -ENODEV; | ||
62 | } | ||
63 | |||
64 | return num_ports; | ||
65 | } | ||
66 | |||
67 | static struct usb_serial_driver usb_serial_generic_device = { | ||
41 | .driver = { | 68 | .driver = { |
42 | .owner = THIS_MODULE, | 69 | .owner = THIS_MODULE, |
43 | .name = "generic", | 70 | .name = "generic", |
44 | }, | 71 | }, |
45 | .id_table = generic_device_ids, | 72 | .id_table = generic_device_ids, |
46 | .num_ports = 1, | 73 | .probe = usb_serial_generic_probe, |
74 | .calc_num_ports = usb_serial_generic_calc_num_ports, | ||
47 | .throttle = usb_serial_generic_throttle, | 75 | .throttle = usb_serial_generic_throttle, |
48 | .unthrottle = usb_serial_generic_unthrottle, | 76 | .unthrottle = usb_serial_generic_unthrottle, |
49 | .resume = usb_serial_generic_resume, | 77 | .resume = usb_serial_generic_resume, |
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index bb7673e80a57..bdf8bd814a9a 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c | |||
@@ -1544,11 +1544,6 @@ static void edge_set_termios(struct tty_struct *tty, | |||
1544 | struct usb_serial_port *port, struct ktermios *old_termios) | 1544 | struct usb_serial_port *port, struct ktermios *old_termios) |
1545 | { | 1545 | { |
1546 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | 1546 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); |
1547 | unsigned int cflag; | ||
1548 | |||
1549 | cflag = tty->termios.c_cflag; | ||
1550 | dev_dbg(&port->dev, "%s - clfag %08x iflag %08x\n", __func__, tty->termios.c_cflag, tty->termios.c_iflag); | ||
1551 | dev_dbg(&port->dev, "%s - old clfag %08x old iflag %08x\n", __func__, old_termios->c_cflag, old_termios->c_iflag); | ||
1552 | 1547 | ||
1553 | if (edge_port == NULL) | 1548 | if (edge_port == NULL) |
1554 | return; | 1549 | return; |
@@ -2844,14 +2839,9 @@ static int edge_startup(struct usb_serial *serial) | |||
2844 | bool interrupt_in_found; | 2839 | bool interrupt_in_found; |
2845 | bool bulk_in_found; | 2840 | bool bulk_in_found; |
2846 | bool bulk_out_found; | 2841 | bool bulk_out_found; |
2847 | static __u32 descriptor[3] = { EDGE_COMPATIBILITY_MASK0, | 2842 | static const __u32 descriptor[3] = { EDGE_COMPATIBILITY_MASK0, |
2848 | EDGE_COMPATIBILITY_MASK1, | 2843 | EDGE_COMPATIBILITY_MASK1, |
2849 | EDGE_COMPATIBILITY_MASK2 }; | 2844 | EDGE_COMPATIBILITY_MASK2 }; |
2850 | |||
2851 | if (serial->num_bulk_in < 1 || serial->num_interrupt_in < 1) { | ||
2852 | dev_err(&serial->interface->dev, "missing endpoints\n"); | ||
2853 | return -ENODEV; | ||
2854 | } | ||
2855 | 2845 | ||
2856 | dev = serial->dev; | 2846 | dev = serial->dev; |
2857 | 2847 | ||
@@ -3120,6 +3110,9 @@ static struct usb_serial_driver edgeport_2port_device = { | |||
3120 | .description = "Edgeport 2 port adapter", | 3110 | .description = "Edgeport 2 port adapter", |
3121 | .id_table = edgeport_2port_id_table, | 3111 | .id_table = edgeport_2port_id_table, |
3122 | .num_ports = 2, | 3112 | .num_ports = 2, |
3113 | .num_bulk_in = 1, | ||
3114 | .num_bulk_out = 1, | ||
3115 | .num_interrupt_in = 1, | ||
3123 | .open = edge_open, | 3116 | .open = edge_open, |
3124 | .close = edge_close, | 3117 | .close = edge_close, |
3125 | .throttle = edge_throttle, | 3118 | .throttle = edge_throttle, |
@@ -3152,6 +3145,9 @@ static struct usb_serial_driver edgeport_4port_device = { | |||
3152 | .description = "Edgeport 4 port adapter", | 3145 | .description = "Edgeport 4 port adapter", |
3153 | .id_table = edgeport_4port_id_table, | 3146 | .id_table = edgeport_4port_id_table, |
3154 | .num_ports = 4, | 3147 | .num_ports = 4, |
3148 | .num_bulk_in = 1, | ||
3149 | .num_bulk_out = 1, | ||
3150 | .num_interrupt_in = 1, | ||
3155 | .open = edge_open, | 3151 | .open = edge_open, |
3156 | .close = edge_close, | 3152 | .close = edge_close, |
3157 | .throttle = edge_throttle, | 3153 | .throttle = edge_throttle, |
@@ -3184,6 +3180,9 @@ static struct usb_serial_driver edgeport_8port_device = { | |||
3184 | .description = "Edgeport 8 port adapter", | 3180 | .description = "Edgeport 8 port adapter", |
3185 | .id_table = edgeport_8port_id_table, | 3181 | .id_table = edgeport_8port_id_table, |
3186 | .num_ports = 8, | 3182 | .num_ports = 8, |
3183 | .num_bulk_in = 1, | ||
3184 | .num_bulk_out = 1, | ||
3185 | .num_interrupt_in = 1, | ||
3187 | .open = edge_open, | 3186 | .open = edge_open, |
3188 | .close = edge_close, | 3187 | .close = edge_close, |
3189 | .throttle = edge_throttle, | 3188 | .throttle = edge_throttle, |
@@ -3216,6 +3215,9 @@ static struct usb_serial_driver epic_device = { | |||
3216 | .description = "EPiC device", | 3215 | .description = "EPiC device", |
3217 | .id_table = Epic_port_id_table, | 3216 | .id_table = Epic_port_id_table, |
3218 | .num_ports = 1, | 3217 | .num_ports = 1, |
3218 | .num_bulk_in = 1, | ||
3219 | .num_bulk_out = 1, | ||
3220 | .num_interrupt_in = 1, | ||
3219 | .open = edge_open, | 3221 | .open = edge_open, |
3220 | .close = edge_close, | 3222 | .close = edge_close, |
3221 | .throttle = edge_throttle, | 3223 | .throttle = edge_throttle, |
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index a76b95d32157..87798e625d6c 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c | |||
@@ -1933,13 +1933,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
1933 | if (edge_serial->num_ports_open == 0) { | 1933 | if (edge_serial->num_ports_open == 0) { |
1934 | /* we are the first port to open, post the interrupt urb */ | 1934 | /* we are the first port to open, post the interrupt urb */ |
1935 | urb = edge_serial->serial->port[0]->interrupt_in_urb; | 1935 | urb = edge_serial->serial->port[0]->interrupt_in_urb; |
1936 | if (!urb) { | ||
1937 | dev_err(&port->dev, | ||
1938 | "%s - no interrupt urb present, exiting\n", | ||
1939 | __func__); | ||
1940 | status = -EINVAL; | ||
1941 | goto release_es_lock; | ||
1942 | } | ||
1943 | urb->context = edge_serial; | 1936 | urb->context = edge_serial; |
1944 | status = usb_submit_urb(urb, GFP_KERNEL); | 1937 | status = usb_submit_urb(urb, GFP_KERNEL); |
1945 | if (status) { | 1938 | if (status) { |
@@ -1959,12 +1952,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
1959 | 1952 | ||
1960 | /* start up our bulk read urb */ | 1953 | /* start up our bulk read urb */ |
1961 | urb = port->read_urb; | 1954 | urb = port->read_urb; |
1962 | if (!urb) { | ||
1963 | dev_err(&port->dev, "%s - no read urb present, exiting\n", | ||
1964 | __func__); | ||
1965 | status = -EINVAL; | ||
1966 | goto unlink_int_urb; | ||
1967 | } | ||
1968 | edge_port->ep_read_urb_state = EDGE_READ_URB_RUNNING; | 1955 | edge_port->ep_read_urb_state = EDGE_READ_URB_RUNNING; |
1969 | urb->context = edge_port; | 1956 | urb->context = edge_port; |
1970 | status = usb_submit_urb(urb, GFP_KERNEL); | 1957 | status = usb_submit_urb(urb, GFP_KERNEL); |
@@ -2385,14 +2372,6 @@ static void edge_set_termios(struct tty_struct *tty, | |||
2385 | struct usb_serial_port *port, struct ktermios *old_termios) | 2372 | struct usb_serial_port *port, struct ktermios *old_termios) |
2386 | { | 2373 | { |
2387 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | 2374 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); |
2388 | unsigned int cflag; | ||
2389 | |||
2390 | cflag = tty->termios.c_cflag; | ||
2391 | |||
2392 | dev_dbg(&port->dev, "%s - clfag %08x iflag %08x\n", __func__, | ||
2393 | tty->termios.c_cflag, tty->termios.c_iflag); | ||
2394 | dev_dbg(&port->dev, "%s - old clfag %08x old iflag %08x\n", __func__, | ||
2395 | old_termios->c_cflag, old_termios->c_iflag); | ||
2396 | 2375 | ||
2397 | if (edge_port == NULL) | 2376 | if (edge_port == NULL) |
2398 | return; | 2377 | return; |
@@ -2544,19 +2523,31 @@ static void edge_heartbeat_work(struct work_struct *work) | |||
2544 | edge_heartbeat_schedule(serial); | 2523 | edge_heartbeat_schedule(serial); |
2545 | } | 2524 | } |
2546 | 2525 | ||
2547 | static int edge_startup(struct usb_serial *serial) | 2526 | static int edge_calc_num_ports(struct usb_serial *serial, |
2527 | struct usb_serial_endpoints *epds) | ||
2548 | { | 2528 | { |
2549 | struct edgeport_serial *edge_serial; | 2529 | struct device *dev = &serial->interface->dev; |
2550 | int status; | 2530 | unsigned char num_ports = serial->type->num_ports; |
2551 | u16 product_id; | ||
2552 | 2531 | ||
2553 | /* Make sure we have the required endpoints when in download mode. */ | 2532 | /* Make sure we have the required endpoints when in download mode. */ |
2554 | if (serial->interface->cur_altsetting->desc.bNumEndpoints > 1) { | 2533 | if (serial->interface->cur_altsetting->desc.bNumEndpoints > 1) { |
2555 | if (serial->num_bulk_in < serial->num_ports || | 2534 | if (epds->num_bulk_in < num_ports || |
2556 | serial->num_bulk_out < serial->num_ports) | 2535 | epds->num_bulk_out < num_ports || |
2536 | epds->num_interrupt_in < 1) { | ||
2537 | dev_err(dev, "required endpoints missing\n"); | ||
2557 | return -ENODEV; | 2538 | return -ENODEV; |
2539 | } | ||
2558 | } | 2540 | } |
2559 | 2541 | ||
2542 | return num_ports; | ||
2543 | } | ||
2544 | |||
2545 | static int edge_startup(struct usb_serial *serial) | ||
2546 | { | ||
2547 | struct edgeport_serial *edge_serial; | ||
2548 | int status; | ||
2549 | u16 product_id; | ||
2550 | |||
2560 | /* create our private serial structure */ | 2551 | /* create our private serial structure */ |
2561 | edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL); | 2552 | edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL); |
2562 | if (!edge_serial) | 2553 | if (!edge_serial) |
@@ -2736,11 +2727,13 @@ static struct usb_serial_driver edgeport_1port_device = { | |||
2736 | .description = "Edgeport TI 1 port adapter", | 2727 | .description = "Edgeport TI 1 port adapter", |
2737 | .id_table = edgeport_1port_id_table, | 2728 | .id_table = edgeport_1port_id_table, |
2738 | .num_ports = 1, | 2729 | .num_ports = 1, |
2730 | .num_bulk_out = 1, | ||
2739 | .open = edge_open, | 2731 | .open = edge_open, |
2740 | .close = edge_close, | 2732 | .close = edge_close, |
2741 | .throttle = edge_throttle, | 2733 | .throttle = edge_throttle, |
2742 | .unthrottle = edge_unthrottle, | 2734 | .unthrottle = edge_unthrottle, |
2743 | .attach = edge_startup, | 2735 | .attach = edge_startup, |
2736 | .calc_num_ports = edge_calc_num_ports, | ||
2744 | .disconnect = edge_disconnect, | 2737 | .disconnect = edge_disconnect, |
2745 | .release = edge_release, | 2738 | .release = edge_release, |
2746 | .port_probe = edge_port_probe, | 2739 | .port_probe = edge_port_probe, |
@@ -2773,11 +2766,13 @@ static struct usb_serial_driver edgeport_2port_device = { | |||
2773 | .description = "Edgeport TI 2 port adapter", | 2766 | .description = "Edgeport TI 2 port adapter", |
2774 | .id_table = edgeport_2port_id_table, | 2767 | .id_table = edgeport_2port_id_table, |
2775 | .num_ports = 2, | 2768 | .num_ports = 2, |
2769 | .num_bulk_out = 1, | ||
2776 | .open = edge_open, | 2770 | .open = edge_open, |
2777 | .close = edge_close, | 2771 | .close = edge_close, |
2778 | .throttle = edge_throttle, | 2772 | .throttle = edge_throttle, |
2779 | .unthrottle = edge_unthrottle, | 2773 | .unthrottle = edge_unthrottle, |
2780 | .attach = edge_startup, | 2774 | .attach = edge_startup, |
2775 | .calc_num_ports = edge_calc_num_ports, | ||
2781 | .disconnect = edge_disconnect, | 2776 | .disconnect = edge_disconnect, |
2782 | .release = edge_release, | 2777 | .release = edge_release, |
2783 | .port_probe = edge_port_probe, | 2778 | .port_probe = edge_port_probe, |
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index ec1b8f2c1183..cde0dcdce9c4 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c | |||
@@ -33,7 +33,8 @@ static int initial_wait; | |||
33 | /* Function prototypes for an ipaq */ | 33 | /* Function prototypes for an ipaq */ |
34 | static int ipaq_open(struct tty_struct *tty, | 34 | static int ipaq_open(struct tty_struct *tty, |
35 | struct usb_serial_port *port); | 35 | struct usb_serial_port *port); |
36 | static int ipaq_calc_num_ports(struct usb_serial *serial); | 36 | static int ipaq_calc_num_ports(struct usb_serial *serial, |
37 | struct usb_serial_endpoints *epds); | ||
37 | static int ipaq_startup(struct usb_serial *serial); | 38 | static int ipaq_startup(struct usb_serial *serial); |
38 | 39 | ||
39 | static const struct usb_device_id ipaq_id_table[] = { | 40 | static const struct usb_device_id ipaq_id_table[] = { |
@@ -550,42 +551,38 @@ static int ipaq_open(struct tty_struct *tty, | |||
550 | return usb_serial_generic_open(tty, port); | 551 | return usb_serial_generic_open(tty, port); |
551 | } | 552 | } |
552 | 553 | ||
553 | static int ipaq_calc_num_ports(struct usb_serial *serial) | 554 | static int ipaq_calc_num_ports(struct usb_serial *serial, |
555 | struct usb_serial_endpoints *epds) | ||
554 | { | 556 | { |
555 | /* | 557 | /* |
556 | * some devices have 3 endpoints, the 3rd of which | 558 | * Some of the devices in ipaq_id_table[] are composite, and we |
557 | * must be ignored as it would make the core | 559 | * shouldn't bind to all the interfaces. This test will rule out |
558 | * create a second port which oopses when used | 560 | * some obviously invalid possibilities. |
559 | */ | 561 | */ |
560 | int ipaq_num_ports = 1; | 562 | if (epds->num_bulk_in == 0 || epds->num_bulk_out == 0) |
561 | 563 | return -ENODEV; | |
562 | dev_dbg(&serial->dev->dev, "%s - numberofendpoints: %d\n", __func__, | ||
563 | (int)serial->interface->cur_altsetting->desc.bNumEndpoints); | ||
564 | 564 | ||
565 | /* | 565 | /* |
566 | * a few devices have 4 endpoints, seemingly Yakuma devices, | 566 | * A few devices have four endpoints, seemingly Yakuma devices, and |
567 | * and we need the second pair, so let them have 2 ports | 567 | * we need the second pair. |
568 | * | ||
569 | * TODO: can we drop port 1 ? | ||
570 | */ | 568 | */ |
571 | if (serial->interface->cur_altsetting->desc.bNumEndpoints > 3) { | 569 | if (epds->num_bulk_in > 1 && epds->num_bulk_out > 1) { |
572 | ipaq_num_ports = 2; | 570 | epds->bulk_in[0] = epds->bulk_in[1]; |
571 | epds->bulk_out[0] = epds->bulk_out[1]; | ||
573 | } | 572 | } |
574 | 573 | ||
575 | return ipaq_num_ports; | 574 | /* |
576 | } | 575 | * Other devices have 3 endpoints, but we only use the first bulk in |
576 | * and out endpoints. | ||
577 | */ | ||
578 | epds->num_bulk_in = 1; | ||
579 | epds->num_bulk_out = 1; | ||
577 | 580 | ||
581 | return 1; | ||
582 | } | ||
578 | 583 | ||
579 | static int ipaq_startup(struct usb_serial *serial) | 584 | static int ipaq_startup(struct usb_serial *serial) |
580 | { | 585 | { |
581 | /* Some of the devices in ipaq_id_table[] are composite, and we | ||
582 | * shouldn't bind to all the interfaces. This test will rule out | ||
583 | * some obviously invalid possibilities. | ||
584 | */ | ||
585 | if (serial->num_bulk_in < serial->num_ports || | ||
586 | serial->num_bulk_out < serial->num_ports) | ||
587 | return -ENODEV; | ||
588 | |||
589 | if (serial->dev->actconfig->desc.bConfigurationValue != 1) { | 586 | if (serial->dev->actconfig->desc.bConfigurationValue != 1) { |
590 | /* | 587 | /* |
591 | * FIXME: HP iPaq rx3715, possibly others, have 1 config that | 588 | * FIXME: HP iPaq rx3715, possibly others, have 1 config that |
@@ -597,10 +594,6 @@ static int ipaq_startup(struct usb_serial *serial) | |||
597 | return -ENODEV; | 594 | return -ENODEV; |
598 | } | 595 | } |
599 | 596 | ||
600 | dev_dbg(&serial->dev->dev, | ||
601 | "%s - iPAQ module configured for %d ports\n", __func__, | ||
602 | serial->num_ports); | ||
603 | |||
604 | return usb_reset_configuration(serial->dev); | 597 | return usb_reset_configuration(serial->dev); |
605 | } | 598 | } |
606 | 599 | ||
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 030390f37b0a..18fc992a245f 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c | |||
@@ -68,16 +68,6 @@ struct iuu_private { | |||
68 | u32 clk; | 68 | u32 clk; |
69 | }; | 69 | }; |
70 | 70 | ||
71 | static int iuu_attach(struct usb_serial *serial) | ||
72 | { | ||
73 | unsigned char num_ports = serial->num_ports; | ||
74 | |||
75 | if (serial->num_bulk_in < num_ports || serial->num_bulk_out < num_ports) | ||
76 | return -ENODEV; | ||
77 | |||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | static int iuu_port_probe(struct usb_serial_port *port) | 71 | static int iuu_port_probe(struct usb_serial_port *port) |
82 | { | 72 | { |
83 | struct iuu_private *priv; | 73 | struct iuu_private *priv; |
@@ -598,9 +588,8 @@ static void read_buf_callback(struct urb *urb) | |||
598 | } | 588 | } |
599 | 589 | ||
600 | dev_dbg(&port->dev, "%s - %i chars to write\n", __func__, urb->actual_length); | 590 | dev_dbg(&port->dev, "%s - %i chars to write\n", __func__, urb->actual_length); |
601 | if (data == NULL) | 591 | |
602 | dev_dbg(&port->dev, "%s - data is NULL !!!\n", __func__); | 592 | if (urb->actual_length) { |
603 | if (urb->actual_length && data) { | ||
604 | tty_insert_flip_string(&port->port, data, urb->actual_length); | 593 | tty_insert_flip_string(&port->port, data, urb->actual_length); |
605 | tty_flip_buffer_push(&port->port); | 594 | tty_flip_buffer_push(&port->port); |
606 | } | 595 | } |
@@ -665,10 +654,8 @@ static void iuu_uart_read_callback(struct urb *urb) | |||
665 | /* error stop all */ | 654 | /* error stop all */ |
666 | return; | 655 | return; |
667 | } | 656 | } |
668 | if (data == NULL) | ||
669 | dev_dbg(&port->dev, "%s - data is NULL !!!\n", __func__); | ||
670 | 657 | ||
671 | if (urb->actual_length == 1 && data != NULL) | 658 | if (urb->actual_length == 1) |
672 | len = (int) data[0]; | 659 | len = (int) data[0]; |
673 | 660 | ||
674 | if (urb->actual_length > 1) { | 661 | if (urb->actual_length > 1) { |
@@ -1183,6 +1170,8 @@ static struct usb_serial_driver iuu_device = { | |||
1183 | }, | 1170 | }, |
1184 | .id_table = id_table, | 1171 | .id_table = id_table, |
1185 | .num_ports = 1, | 1172 | .num_ports = 1, |
1173 | .num_bulk_in = 1, | ||
1174 | .num_bulk_out = 1, | ||
1186 | .bulk_in_size = 512, | 1175 | .bulk_in_size = 512, |
1187 | .bulk_out_size = 512, | 1176 | .bulk_out_size = 512, |
1188 | .open = iuu_open, | 1177 | .open = iuu_open, |
@@ -1193,7 +1182,6 @@ static struct usb_serial_driver iuu_device = { | |||
1193 | .tiocmset = iuu_tiocmset, | 1182 | .tiocmset = iuu_tiocmset, |
1194 | .set_termios = iuu_set_termios, | 1183 | .set_termios = iuu_set_termios, |
1195 | .init_termios = iuu_init_termios, | 1184 | .init_termios = iuu_init_termios, |
1196 | .attach = iuu_attach, | ||
1197 | .port_probe = iuu_port_probe, | 1185 | .port_probe = iuu_port_probe, |
1198 | .port_remove = iuu_port_remove, | 1186 | .port_remove = iuu_port_remove, |
1199 | }; | 1187 | }; |
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index d2dab2a341b8..196908dd25a1 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c | |||
@@ -708,19 +708,6 @@ MODULE_FIRMWARE("keyspan_pda/keyspan_pda.fw"); | |||
708 | MODULE_FIRMWARE("keyspan_pda/xircom_pgs.fw"); | 708 | MODULE_FIRMWARE("keyspan_pda/xircom_pgs.fw"); |
709 | #endif | 709 | #endif |
710 | 710 | ||
711 | static int keyspan_pda_attach(struct usb_serial *serial) | ||
712 | { | ||
713 | unsigned char num_ports = serial->num_ports; | ||
714 | |||
715 | if (serial->num_bulk_out < num_ports || | ||
716 | serial->num_interrupt_in < num_ports) { | ||
717 | dev_err(&serial->interface->dev, "missing endpoints\n"); | ||
718 | return -ENODEV; | ||
719 | } | ||
720 | |||
721 | return 0; | ||
722 | } | ||
723 | |||
724 | static int keyspan_pda_port_probe(struct usb_serial_port *port) | 711 | static int keyspan_pda_port_probe(struct usb_serial_port *port) |
725 | { | 712 | { |
726 | 713 | ||
@@ -784,6 +771,8 @@ static struct usb_serial_driver keyspan_pda_device = { | |||
784 | .description = "Keyspan PDA", | 771 | .description = "Keyspan PDA", |
785 | .id_table = id_table_std, | 772 | .id_table = id_table_std, |
786 | .num_ports = 1, | 773 | .num_ports = 1, |
774 | .num_bulk_out = 1, | ||
775 | .num_interrupt_in = 1, | ||
787 | .dtr_rts = keyspan_pda_dtr_rts, | 776 | .dtr_rts = keyspan_pda_dtr_rts, |
788 | .open = keyspan_pda_open, | 777 | .open = keyspan_pda_open, |
789 | .close = keyspan_pda_close, | 778 | .close = keyspan_pda_close, |
@@ -798,7 +787,6 @@ static struct usb_serial_driver keyspan_pda_device = { | |||
798 | .break_ctl = keyspan_pda_break_ctl, | 787 | .break_ctl = keyspan_pda_break_ctl, |
799 | .tiocmget = keyspan_pda_tiocmget, | 788 | .tiocmget = keyspan_pda_tiocmget, |
800 | .tiocmset = keyspan_pda_tiocmset, | 789 | .tiocmset = keyspan_pda_tiocmset, |
801 | .attach = keyspan_pda_attach, | ||
802 | .port_probe = keyspan_pda_port_probe, | 790 | .port_probe = keyspan_pda_port_probe, |
803 | .port_remove = keyspan_pda_port_remove, | 791 | .port_remove = keyspan_pda_port_remove, |
804 | }; | 792 | }; |
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 813035f51fe7..3024b9b25360 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c | |||
@@ -51,7 +51,6 @@ | |||
51 | 51 | ||
52 | 52 | ||
53 | /* Function prototypes */ | 53 | /* Function prototypes */ |
54 | static int kobil_attach(struct usb_serial *serial); | ||
55 | static int kobil_port_probe(struct usb_serial_port *probe); | 54 | static int kobil_port_probe(struct usb_serial_port *probe); |
56 | static int kobil_port_remove(struct usb_serial_port *probe); | 55 | static int kobil_port_remove(struct usb_serial_port *probe); |
57 | static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port); | 56 | static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port); |
@@ -87,7 +86,7 @@ static struct usb_serial_driver kobil_device = { | |||
87 | .description = "KOBIL USB smart card terminal", | 86 | .description = "KOBIL USB smart card terminal", |
88 | .id_table = id_table, | 87 | .id_table = id_table, |
89 | .num_ports = 1, | 88 | .num_ports = 1, |
90 | .attach = kobil_attach, | 89 | .num_interrupt_out = 1, |
91 | .port_probe = kobil_port_probe, | 90 | .port_probe = kobil_port_probe, |
92 | .port_remove = kobil_port_remove, | 91 | .port_remove = kobil_port_remove, |
93 | .ioctl = kobil_ioctl, | 92 | .ioctl = kobil_ioctl, |
@@ -115,16 +114,6 @@ struct kobil_private { | |||
115 | }; | 114 | }; |
116 | 115 | ||
117 | 116 | ||
118 | static int kobil_attach(struct usb_serial *serial) | ||
119 | { | ||
120 | if (serial->num_interrupt_out < serial->num_ports) { | ||
121 | dev_err(&serial->interface->dev, "missing interrupt-out endpoint\n"); | ||
122 | return -ENODEV; | ||
123 | } | ||
124 | |||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | static int kobil_port_probe(struct usb_serial_port *port) | 117 | static int kobil_port_probe(struct usb_serial_port *port) |
129 | { | 118 | { |
130 | struct usb_serial *serial = port->serial; | 119 | struct usb_serial *serial = port->serial; |
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index f075121c6e32..a453965f9e9a 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c | |||
@@ -973,11 +973,24 @@ static void mos7720_bulk_out_data_callback(struct urb *urb) | |||
973 | tty_port_tty_wakeup(&mos7720_port->port->port); | 973 | tty_port_tty_wakeup(&mos7720_port->port->port); |
974 | } | 974 | } |
975 | 975 | ||
976 | static int mos77xx_calc_num_ports(struct usb_serial *serial) | 976 | static int mos77xx_calc_num_ports(struct usb_serial *serial, |
977 | struct usb_serial_endpoints *epds) | ||
977 | { | 978 | { |
978 | u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); | 979 | u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); |
979 | if (product == MOSCHIP_DEVICE_ID_7715) | 980 | |
981 | if (product == MOSCHIP_DEVICE_ID_7715) { | ||
982 | /* | ||
983 | * The 7715 uses the first bulk in/out endpoint pair for the | ||
984 | * parallel port, and the second for the serial port. We swap | ||
985 | * the endpoint descriptors here so that the the first and | ||
986 | * only registered port structure uses the serial-port | ||
987 | * endpoints. | ||
988 | */ | ||
989 | swap(epds->bulk_in[0], epds->bulk_in[1]); | ||
990 | swap(epds->bulk_out[0], epds->bulk_out[1]); | ||
991 | |||
980 | return 1; | 992 | return 1; |
993 | } | ||
981 | 994 | ||
982 | return 2; | 995 | return 2; |
983 | } | 996 | } |
@@ -1395,7 +1408,7 @@ struct divisor_table_entry { | |||
1395 | /* Define table of divisors for moschip 7720 hardware * | 1408 | /* Define table of divisors for moschip 7720 hardware * |
1396 | * These assume a 3.6864MHz crystal, the standard /16, and * | 1409 | * These assume a 3.6864MHz crystal, the standard /16, and * |
1397 | * MCR.7 = 0. */ | 1410 | * MCR.7 = 0. */ |
1398 | static struct divisor_table_entry divisor_table[] = { | 1411 | static const struct divisor_table_entry divisor_table[] = { |
1399 | { 50, 2304}, | 1412 | { 50, 2304}, |
1400 | { 110, 1047}, /* 2094.545455 => 230450 => .0217 % over */ | 1413 | { 110, 1047}, /* 2094.545455 => 230450 => .0217 % over */ |
1401 | { 134, 857}, /* 1713.011152 => 230398.5 => .00065% under */ | 1414 | { 134, 857}, /* 1713.011152 => 230398.5 => .00065% under */ |
@@ -1675,7 +1688,6 @@ static void mos7720_set_termios(struct tty_struct *tty, | |||
1675 | struct usb_serial_port *port, struct ktermios *old_termios) | 1688 | struct usb_serial_port *port, struct ktermios *old_termios) |
1676 | { | 1689 | { |
1677 | int status; | 1690 | int status; |
1678 | unsigned int cflag; | ||
1679 | struct usb_serial *serial; | 1691 | struct usb_serial *serial; |
1680 | struct moschip_port *mos7720_port; | 1692 | struct moschip_port *mos7720_port; |
1681 | 1693 | ||
@@ -1691,16 +1703,6 @@ static void mos7720_set_termios(struct tty_struct *tty, | |||
1691 | return; | 1703 | return; |
1692 | } | 1704 | } |
1693 | 1705 | ||
1694 | dev_dbg(&port->dev, "setting termios - ASPIRE\n"); | ||
1695 | |||
1696 | cflag = tty->termios.c_cflag; | ||
1697 | |||
1698 | dev_dbg(&port->dev, "%s - cflag %08x iflag %08x\n", __func__, | ||
1699 | tty->termios.c_cflag, RELEVANT_IFLAG(tty->termios.c_iflag)); | ||
1700 | |||
1701 | dev_dbg(&port->dev, "%s - old cflag %08x old iflag %08x\n", __func__, | ||
1702 | old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag)); | ||
1703 | |||
1704 | /* change the port settings to the new ones specified */ | 1706 | /* change the port settings to the new ones specified */ |
1705 | change_port_settings(tty, mos7720_port, old_termios); | 1707 | change_port_settings(tty, mos7720_port, old_termios); |
1706 | 1708 | ||
@@ -1900,54 +1902,24 @@ static int mos7720_startup(struct usb_serial *serial) | |||
1900 | u16 product; | 1902 | u16 product; |
1901 | int ret_val; | 1903 | int ret_val; |
1902 | 1904 | ||
1903 | if (serial->num_bulk_in < 2 || serial->num_bulk_out < 2) { | ||
1904 | dev_err(&serial->interface->dev, "missing bulk endpoints\n"); | ||
1905 | return -ENODEV; | ||
1906 | } | ||
1907 | |||
1908 | product = le16_to_cpu(serial->dev->descriptor.idProduct); | 1905 | product = le16_to_cpu(serial->dev->descriptor.idProduct); |
1909 | dev = serial->dev; | 1906 | dev = serial->dev; |
1910 | 1907 | ||
1911 | /* | ||
1912 | * The 7715 uses the first bulk in/out endpoint pair for the parallel | ||
1913 | * port, and the second for the serial port. Because the usbserial core | ||
1914 | * assumes both pairs are serial ports, we must engage in a bit of | ||
1915 | * subterfuge and swap the pointers for ports 0 and 1 in order to make | ||
1916 | * port 0 point to the serial port. However, both moschip devices use a | ||
1917 | * single interrupt-in endpoint for both ports (as mentioned a little | ||
1918 | * further down), and this endpoint was assigned to port 0. So after | ||
1919 | * the swap, we must copy the interrupt endpoint elements from port 1 | ||
1920 | * (as newly assigned) to port 0, and null out port 1 pointers. | ||
1921 | */ | ||
1922 | if (product == MOSCHIP_DEVICE_ID_7715) { | ||
1923 | struct usb_serial_port *tmp = serial->port[0]; | ||
1924 | serial->port[0] = serial->port[1]; | ||
1925 | serial->port[1] = tmp; | ||
1926 | serial->port[0]->interrupt_in_urb = tmp->interrupt_in_urb; | ||
1927 | serial->port[0]->interrupt_in_buffer = tmp->interrupt_in_buffer; | ||
1928 | serial->port[0]->interrupt_in_endpointAddress = | ||
1929 | tmp->interrupt_in_endpointAddress; | ||
1930 | serial->port[1]->interrupt_in_urb = NULL; | ||
1931 | serial->port[1]->interrupt_in_buffer = NULL; | ||
1932 | |||
1933 | if (serial->port[0]->interrupt_in_urb) { | ||
1934 | struct urb *urb = serial->port[0]->interrupt_in_urb; | ||
1935 | |||
1936 | urb->complete = mos7715_interrupt_callback; | ||
1937 | } | ||
1938 | } | ||
1939 | |||
1940 | /* setting configuration feature to one */ | 1908 | /* setting configuration feature to one */ |
1941 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | 1909 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), |
1942 | (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5000); | 1910 | (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5000); |
1943 | 1911 | ||
1944 | #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT | ||
1945 | if (product == MOSCHIP_DEVICE_ID_7715) { | 1912 | if (product == MOSCHIP_DEVICE_ID_7715) { |
1913 | struct urb *urb = serial->port[0]->interrupt_in_urb; | ||
1914 | |||
1915 | urb->complete = mos7715_interrupt_callback; | ||
1916 | |||
1917 | #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT | ||
1946 | ret_val = mos7715_parport_init(serial); | 1918 | ret_val = mos7715_parport_init(serial); |
1947 | if (ret_val < 0) | 1919 | if (ret_val < 0) |
1948 | return ret_val; | 1920 | return ret_val; |
1949 | } | ||
1950 | #endif | 1921 | #endif |
1922 | } | ||
1951 | /* start the interrupt urb */ | 1923 | /* start the interrupt urb */ |
1952 | ret_val = usb_submit_urb(serial->port[0]->interrupt_in_urb, GFP_KERNEL); | 1924 | ret_val = usb_submit_urb(serial->port[0]->interrupt_in_urb, GFP_KERNEL); |
1953 | if (ret_val) { | 1925 | if (ret_val) { |
@@ -2039,6 +2011,9 @@ static struct usb_serial_driver moschip7720_2port_driver = { | |||
2039 | }, | 2011 | }, |
2040 | .description = "Moschip 2 port adapter", | 2012 | .description = "Moschip 2 port adapter", |
2041 | .id_table = id_table, | 2013 | .id_table = id_table, |
2014 | .num_bulk_in = 2, | ||
2015 | .num_bulk_out = 2, | ||
2016 | .num_interrupt_in = 1, | ||
2042 | .calc_num_ports = mos77xx_calc_num_ports, | 2017 | .calc_num_ports = mos77xx_calc_num_ports, |
2043 | .open = mos7720_open, | 2018 | .open = mos7720_open, |
2044 | .close = mos7720_close, | 2019 | .close = mos7720_close, |
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 3821c53fcee9..e8669aae14b3 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c | |||
@@ -1868,7 +1868,6 @@ static void mos7840_set_termios(struct tty_struct *tty, | |||
1868 | struct ktermios *old_termios) | 1868 | struct ktermios *old_termios) |
1869 | { | 1869 | { |
1870 | int status; | 1870 | int status; |
1871 | unsigned int cflag; | ||
1872 | struct usb_serial *serial; | 1871 | struct usb_serial *serial; |
1873 | struct moschip_port *mos7840_port; | 1872 | struct moschip_port *mos7840_port; |
1874 | 1873 | ||
@@ -1890,15 +1889,6 @@ static void mos7840_set_termios(struct tty_struct *tty, | |||
1890 | return; | 1889 | return; |
1891 | } | 1890 | } |
1892 | 1891 | ||
1893 | dev_dbg(&port->dev, "%s", "setting termios - \n"); | ||
1894 | |||
1895 | cflag = tty->termios.c_cflag; | ||
1896 | |||
1897 | dev_dbg(&port->dev, "%s - clfag %08x iflag %08x\n", __func__, | ||
1898 | tty->termios.c_cflag, RELEVANT_IFLAG(tty->termios.c_iflag)); | ||
1899 | dev_dbg(&port->dev, "%s - old clfag %08x old iflag %08x\n", __func__, | ||
1900 | old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag)); | ||
1901 | |||
1902 | /* change the port settings to the new ones specified */ | 1892 | /* change the port settings to the new ones specified */ |
1903 | 1893 | ||
1904 | mos7840_change_port_settings(tty, mos7840_port, old_termios); | 1894 | mos7840_change_port_settings(tty, mos7840_port, old_termios); |
@@ -2104,26 +2094,27 @@ out: | |||
2104 | return 0; | 2094 | return 0; |
2105 | } | 2095 | } |
2106 | 2096 | ||
2107 | static int mos7840_calc_num_ports(struct usb_serial *serial) | 2097 | static int mos7840_calc_num_ports(struct usb_serial *serial, |
2098 | struct usb_serial_endpoints *epds) | ||
2108 | { | 2099 | { |
2109 | int device_type = (unsigned long)usb_get_serial_data(serial); | 2100 | int device_type = (unsigned long)usb_get_serial_data(serial); |
2110 | int mos7840_num_ports; | 2101 | int num_ports; |
2111 | 2102 | ||
2112 | mos7840_num_ports = (device_type >> 4) & 0x000F; | 2103 | num_ports = (device_type >> 4) & 0x000F; |
2113 | 2104 | ||
2114 | return mos7840_num_ports; | 2105 | /* |
2115 | } | 2106 | * num_ports is currently never zero as device_type is one of |
2107 | * MOSCHIP_DEVICE_ID_78{1,2,4}0. | ||
2108 | */ | ||
2109 | if (num_ports == 0) | ||
2110 | return -ENODEV; | ||
2116 | 2111 | ||
2117 | static int mos7840_attach(struct usb_serial *serial) | 2112 | if (epds->num_bulk_in < num_ports || epds->num_bulk_out < num_ports) { |
2118 | { | ||
2119 | if (serial->num_bulk_in < serial->num_ports || | ||
2120 | serial->num_bulk_out < serial->num_ports || | ||
2121 | serial->num_interrupt_in < 1) { | ||
2122 | dev_err(&serial->interface->dev, "missing endpoints\n"); | 2113 | dev_err(&serial->interface->dev, "missing endpoints\n"); |
2123 | return -ENODEV; | 2114 | return -ENODEV; |
2124 | } | 2115 | } |
2125 | 2116 | ||
2126 | return 0; | 2117 | return num_ports; |
2127 | } | 2118 | } |
2128 | 2119 | ||
2129 | static int mos7840_port_probe(struct usb_serial_port *port) | 2120 | static int mos7840_port_probe(struct usb_serial_port *port) |
@@ -2384,7 +2375,7 @@ static struct usb_serial_driver moschip7840_4port_device = { | |||
2384 | }, | 2375 | }, |
2385 | .description = DRIVER_DESC, | 2376 | .description = DRIVER_DESC, |
2386 | .id_table = id_table, | 2377 | .id_table = id_table, |
2387 | .num_ports = 4, | 2378 | .num_interrupt_in = 1, |
2388 | .open = mos7840_open, | 2379 | .open = mos7840_open, |
2389 | .close = mos7840_close, | 2380 | .close = mos7840_close, |
2390 | .write = mos7840_write, | 2381 | .write = mos7840_write, |
@@ -2401,7 +2392,6 @@ static struct usb_serial_driver moschip7840_4port_device = { | |||
2401 | .tiocmset = mos7840_tiocmset, | 2392 | .tiocmset = mos7840_tiocmset, |
2402 | .tiocmiwait = usb_serial_generic_tiocmiwait, | 2393 | .tiocmiwait = usb_serial_generic_tiocmiwait, |
2403 | .get_icount = usb_serial_generic_get_icount, | 2394 | .get_icount = usb_serial_generic_get_icount, |
2404 | .attach = mos7840_attach, | ||
2405 | .port_probe = mos7840_port_probe, | 2395 | .port_probe = mos7840_port_probe, |
2406 | .port_remove = mos7840_port_remove, | 2396 | .port_remove = mos7840_port_remove, |
2407 | .read_bulk_callback = mos7840_bulk_in_callback, | 2397 | .read_bulk_callback = mos7840_bulk_in_callback, |
diff --git a/drivers/usb/serial/mxuport.c b/drivers/usb/serial/mxuport.c index c88215a0fa3d..3aef091fe88b 100644 --- a/drivers/usb/serial/mxuport.c +++ b/drivers/usb/serial/mxuport.c | |||
@@ -946,20 +946,39 @@ out: | |||
946 | * Determine how many ports this device has dynamically. It will be | 946 | * Determine how many ports this device has dynamically. It will be |
947 | * called after the probe() callback is called, but before attach(). | 947 | * called after the probe() callback is called, but before attach(). |
948 | */ | 948 | */ |
949 | static int mxuport_calc_num_ports(struct usb_serial *serial) | 949 | static int mxuport_calc_num_ports(struct usb_serial *serial, |
950 | struct usb_serial_endpoints *epds) | ||
950 | { | 951 | { |
951 | unsigned long features = (unsigned long)usb_get_serial_data(serial); | 952 | unsigned long features = (unsigned long)usb_get_serial_data(serial); |
953 | int num_ports; | ||
954 | int i; | ||
952 | 955 | ||
953 | if (features & MX_UPORT_2_PORT) | 956 | if (features & MX_UPORT_2_PORT) { |
954 | return 2; | 957 | num_ports = 2; |
955 | if (features & MX_UPORT_4_PORT) | 958 | } else if (features & MX_UPORT_4_PORT) { |
956 | return 4; | 959 | num_ports = 4; |
957 | if (features & MX_UPORT_8_PORT) | 960 | } else if (features & MX_UPORT_8_PORT) { |
958 | return 8; | 961 | num_ports = 8; |
959 | if (features & MX_UPORT_16_PORT) | 962 | } else if (features & MX_UPORT_16_PORT) { |
960 | return 16; | 963 | num_ports = 16; |
964 | } else { | ||
965 | dev_warn(&serial->interface->dev, | ||
966 | "unknown device, assuming two ports\n"); | ||
967 | num_ports = 2; | ||
968 | } | ||
961 | 969 | ||
962 | return 0; | 970 | /* |
971 | * Setup bulk-out endpoint multiplexing. All ports share the same | ||
972 | * bulk-out endpoint. | ||
973 | */ | ||
974 | BUILD_BUG_ON(ARRAY_SIZE(epds->bulk_out) < 16); | ||
975 | |||
976 | for (i = 1; i < num_ports; ++i) | ||
977 | epds->bulk_out[i] = epds->bulk_out[0]; | ||
978 | |||
979 | epds->num_bulk_out = num_ports; | ||
980 | |||
981 | return num_ports; | ||
963 | } | 982 | } |
964 | 983 | ||
965 | /* Get the version of the firmware currently running. */ | 984 | /* Get the version of the firmware currently running. */ |
@@ -1142,102 +1161,11 @@ static int mxuport_port_probe(struct usb_serial_port *port) | |||
1142 | port->port_number); | 1161 | port->port_number); |
1143 | } | 1162 | } |
1144 | 1163 | ||
1145 | static int mxuport_alloc_write_urb(struct usb_serial *serial, | ||
1146 | struct usb_serial_port *port, | ||
1147 | struct usb_serial_port *port0, | ||
1148 | int j) | ||
1149 | { | ||
1150 | struct usb_device *dev = interface_to_usbdev(serial->interface); | ||
1151 | |||
1152 | set_bit(j, &port->write_urbs_free); | ||
1153 | port->write_urbs[j] = usb_alloc_urb(0, GFP_KERNEL); | ||
1154 | if (!port->write_urbs[j]) | ||
1155 | return -ENOMEM; | ||
1156 | |||
1157 | port->bulk_out_buffers[j] = kmalloc(port0->bulk_out_size, GFP_KERNEL); | ||
1158 | if (!port->bulk_out_buffers[j]) | ||
1159 | return -ENOMEM; | ||
1160 | |||
1161 | usb_fill_bulk_urb(port->write_urbs[j], dev, | ||
1162 | usb_sndbulkpipe(dev, port->bulk_out_endpointAddress), | ||
1163 | port->bulk_out_buffers[j], | ||
1164 | port->bulk_out_size, | ||
1165 | serial->type->write_bulk_callback, | ||
1166 | port); | ||
1167 | return 0; | ||
1168 | } | ||
1169 | |||
1170 | |||
1171 | static int mxuport_alloc_write_urbs(struct usb_serial *serial, | ||
1172 | struct usb_serial_port *port, | ||
1173 | struct usb_serial_port *port0) | ||
1174 | { | ||
1175 | int j; | ||
1176 | int ret; | ||
1177 | |||
1178 | for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) { | ||
1179 | ret = mxuport_alloc_write_urb(serial, port, port0, j); | ||
1180 | if (ret) | ||
1181 | return ret; | ||
1182 | } | ||
1183 | return 0; | ||
1184 | } | ||
1185 | |||
1186 | |||
1187 | static int mxuport_attach(struct usb_serial *serial) | 1164 | static int mxuport_attach(struct usb_serial *serial) |
1188 | { | 1165 | { |
1189 | struct usb_serial_port *port0 = serial->port[0]; | 1166 | struct usb_serial_port *port0 = serial->port[0]; |
1190 | struct usb_serial_port *port1 = serial->port[1]; | 1167 | struct usb_serial_port *port1 = serial->port[1]; |
1191 | struct usb_serial_port *port; | ||
1192 | int err; | 1168 | int err; |
1193 | int i; | ||
1194 | int j; | ||
1195 | |||
1196 | /* | ||
1197 | * Throw away all but the first allocated write URBs so we can | ||
1198 | * set them up again to fit the multiplexing scheme. | ||
1199 | */ | ||
1200 | for (i = 1; i < serial->num_bulk_out; ++i) { | ||
1201 | port = serial->port[i]; | ||
1202 | for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) { | ||
1203 | usb_free_urb(port->write_urbs[j]); | ||
1204 | kfree(port->bulk_out_buffers[j]); | ||
1205 | port->write_urbs[j] = NULL; | ||
1206 | port->bulk_out_buffers[j] = NULL; | ||
1207 | } | ||
1208 | port->write_urbs_free = 0; | ||
1209 | } | ||
1210 | |||
1211 | /* | ||
1212 | * All write data is sent over the first bulk out endpoint, | ||
1213 | * with an added header to indicate the port. Allocate URBs | ||
1214 | * for each port to the first bulk out endpoint. | ||
1215 | */ | ||
1216 | for (i = 1; i < serial->num_ports; ++i) { | ||
1217 | port = serial->port[i]; | ||
1218 | port->bulk_out_size = port0->bulk_out_size; | ||
1219 | port->bulk_out_endpointAddress = | ||
1220 | port0->bulk_out_endpointAddress; | ||
1221 | |||
1222 | err = mxuport_alloc_write_urbs(serial, port, port0); | ||
1223 | if (err) | ||
1224 | return err; | ||
1225 | |||
1226 | port->write_urb = port->write_urbs[0]; | ||
1227 | port->bulk_out_buffer = port->bulk_out_buffers[0]; | ||
1228 | |||
1229 | /* | ||
1230 | * Ensure each port has a fifo. The framework only | ||
1231 | * allocates a fifo to ports with a bulk out endpoint, | ||
1232 | * where as we need one for every port. | ||
1233 | */ | ||
1234 | if (!kfifo_initialized(&port->write_fifo)) { | ||
1235 | err = kfifo_alloc(&port->write_fifo, PAGE_SIZE, | ||
1236 | GFP_KERNEL); | ||
1237 | if (err) | ||
1238 | return err; | ||
1239 | } | ||
1240 | } | ||
1241 | 1169 | ||
1242 | /* | 1170 | /* |
1243 | * All data from the ports is received on the first bulk in | 1171 | * All data from the ports is received on the first bulk in |
@@ -1366,7 +1294,8 @@ static struct usb_serial_driver mxuport_device = { | |||
1366 | }, | 1294 | }, |
1367 | .description = "MOXA UPort", | 1295 | .description = "MOXA UPort", |
1368 | .id_table = mxuport_idtable, | 1296 | .id_table = mxuport_idtable, |
1369 | .num_ports = 0, | 1297 | .num_bulk_in = 2, |
1298 | .num_bulk_out = 1, | ||
1370 | .probe = mxuport_probe, | 1299 | .probe = mxuport_probe, |
1371 | .port_probe = mxuport_port_probe, | 1300 | .port_probe = mxuport_port_probe, |
1372 | .attach = mxuport_attach, | 1301 | .attach = mxuport_attach, |
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index dd706953b466..efcd7feed6f4 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c | |||
@@ -1,6 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * USB ZyXEL omni.net LCD PLUS driver | 2 | * USB ZyXEL omni.net LCD PLUS driver |
3 | * | 3 | * |
4 | * Copyright (C) 2013,2017 Johan Hovold <johan@kernel.org> | ||
5 | * | ||
4 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU General Public License version | 7 | * modify it under the terms of the GNU General Public License version |
6 | * 2 as published by the Free Software Foundation. | 8 | * 2 as published by the Free Software Foundation. |
@@ -32,12 +34,10 @@ | |||
32 | 34 | ||
33 | /* function prototypes */ | 35 | /* function prototypes */ |
34 | static void omninet_process_read_urb(struct urb *urb); | 36 | static void omninet_process_read_urb(struct urb *urb); |
35 | static void omninet_write_bulk_callback(struct urb *urb); | 37 | static int omninet_prepare_write_buffer(struct usb_serial_port *port, |
36 | static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, | 38 | void *buf, size_t count); |
37 | const unsigned char *buf, int count); | 39 | static int omninet_calc_num_ports(struct usb_serial *serial, |
38 | static int omninet_write_room(struct tty_struct *tty); | 40 | struct usb_serial_endpoints *epds); |
39 | static void omninet_disconnect(struct usb_serial *serial); | ||
40 | static int omninet_attach(struct usb_serial *serial); | ||
41 | static int omninet_port_probe(struct usb_serial_port *port); | 41 | static int omninet_port_probe(struct usb_serial_port *port); |
42 | static int omninet_port_remove(struct usb_serial_port *port); | 42 | static int omninet_port_remove(struct usb_serial_port *port); |
43 | 43 | ||
@@ -55,15 +55,12 @@ static struct usb_serial_driver zyxel_omninet_device = { | |||
55 | }, | 55 | }, |
56 | .description = "ZyXEL - omni.net lcd plus usb", | 56 | .description = "ZyXEL - omni.net lcd plus usb", |
57 | .id_table = id_table, | 57 | .id_table = id_table, |
58 | .num_ports = 1, | 58 | .num_bulk_out = 2, |
59 | .attach = omninet_attach, | 59 | .calc_num_ports = omninet_calc_num_ports, |
60 | .port_probe = omninet_port_probe, | 60 | .port_probe = omninet_port_probe, |
61 | .port_remove = omninet_port_remove, | 61 | .port_remove = omninet_port_remove, |
62 | .write = omninet_write, | ||
63 | .write_room = omninet_write_room, | ||
64 | .write_bulk_callback = omninet_write_bulk_callback, | ||
65 | .process_read_urb = omninet_process_read_urb, | 62 | .process_read_urb = omninet_process_read_urb, |
66 | .disconnect = omninet_disconnect, | 63 | .prepare_write_buffer = omninet_prepare_write_buffer, |
67 | }; | 64 | }; |
68 | 65 | ||
69 | static struct usb_serial_driver * const serial_drivers[] = { | 66 | static struct usb_serial_driver * const serial_drivers[] = { |
@@ -104,15 +101,14 @@ struct omninet_data { | |||
104 | __u8 od_outseq; /* Sequence number for bulk_out URBs */ | 101 | __u8 od_outseq; /* Sequence number for bulk_out URBs */ |
105 | }; | 102 | }; |
106 | 103 | ||
107 | static int omninet_attach(struct usb_serial *serial) | 104 | static int omninet_calc_num_ports(struct usb_serial *serial, |
105 | struct usb_serial_endpoints *epds) | ||
108 | { | 106 | { |
109 | /* The second bulk-out endpoint is used for writing. */ | 107 | /* We need only the second bulk-out for our single-port device. */ |
110 | if (serial->num_bulk_out < 2) { | 108 | epds->bulk_out[0] = epds->bulk_out[1]; |
111 | dev_err(&serial->interface->dev, "missing endpoints\n"); | 109 | epds->num_bulk_out = 1; |
112 | return -ENODEV; | ||
113 | } | ||
114 | 110 | ||
115 | return 0; | 111 | return 1; |
116 | } | 112 | } |
117 | 113 | ||
118 | static int omninet_port_probe(struct usb_serial_port *port) | 114 | static int omninet_port_probe(struct usb_serial_port *port) |
@@ -159,96 +155,24 @@ static void omninet_process_read_urb(struct urb *urb) | |||
159 | tty_flip_buffer_push(&port->port); | 155 | tty_flip_buffer_push(&port->port); |
160 | } | 156 | } |
161 | 157 | ||
162 | static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, | 158 | static int omninet_prepare_write_buffer(struct usb_serial_port *port, |
163 | const unsigned char *buf, int count) | 159 | void *buf, size_t count) |
164 | { | 160 | { |
165 | struct usb_serial *serial = port->serial; | ||
166 | struct usb_serial_port *wport = serial->port[1]; | ||
167 | |||
168 | struct omninet_data *od = usb_get_serial_port_data(port); | 161 | struct omninet_data *od = usb_get_serial_port_data(port); |
169 | struct omninet_header *header = (struct omninet_header *) | 162 | struct omninet_header *header = buf; |
170 | wport->write_urb->transfer_buffer; | ||
171 | |||
172 | int result; | ||
173 | |||
174 | if (count == 0) { | ||
175 | dev_dbg(&port->dev, "%s - write request of 0 bytes\n", __func__); | ||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | if (!test_and_clear_bit(0, &port->write_urbs_free)) { | ||
180 | dev_dbg(&port->dev, "%s - already writing\n", __func__); | ||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | count = (count > OMNINET_PAYLOADSIZE) ? OMNINET_PAYLOADSIZE : count; | ||
185 | |||
186 | memcpy(wport->write_urb->transfer_buffer + OMNINET_HEADERLEN, | ||
187 | buf, count); | ||
188 | |||
189 | usb_serial_debug_data(&port->dev, __func__, count, | ||
190 | wport->write_urb->transfer_buffer); | ||
191 | |||
192 | header->oh_seq = od->od_outseq++; | ||
193 | header->oh_len = count; | ||
194 | header->oh_xxx = 0x03; | ||
195 | header->oh_pad = 0x00; | ||
196 | |||
197 | /* send the data out the bulk port, always 64 bytes */ | ||
198 | wport->write_urb->transfer_buffer_length = OMNINET_BULKOUTSIZE; | ||
199 | |||
200 | result = usb_submit_urb(wport->write_urb, GFP_ATOMIC); | ||
201 | if (result) { | ||
202 | set_bit(0, &wport->write_urbs_free); | ||
203 | dev_err_console(port, | ||
204 | "%s - failed submitting write urb, error %d\n", | ||
205 | __func__, result); | ||
206 | } else | ||
207 | result = count; | ||
208 | |||
209 | return result; | ||
210 | } | ||
211 | 163 | ||
164 | count = min_t(size_t, count, OMNINET_PAYLOADSIZE); | ||
212 | 165 | ||
213 | static int omninet_write_room(struct tty_struct *tty) | 166 | count = kfifo_out_locked(&port->write_fifo, buf + OMNINET_HEADERLEN, |
214 | { | 167 | count, &port->lock); |
215 | struct usb_serial_port *port = tty->driver_data; | ||
216 | struct usb_serial *serial = port->serial; | ||
217 | struct usb_serial_port *wport = serial->port[1]; | ||
218 | |||
219 | int room = 0; /* Default: no room */ | ||
220 | |||
221 | if (test_bit(0, &wport->write_urbs_free)) | ||
222 | room = wport->bulk_out_size - OMNINET_HEADERLEN; | ||
223 | |||
224 | dev_dbg(&port->dev, "%s - returns %d\n", __func__, room); | ||
225 | |||
226 | return room; | ||
227 | } | ||
228 | |||
229 | static void omninet_write_bulk_callback(struct urb *urb) | ||
230 | { | ||
231 | /* struct omninet_header *header = (struct omninet_header *) | ||
232 | urb->transfer_buffer; */ | ||
233 | struct usb_serial_port *port = urb->context; | ||
234 | int status = urb->status; | ||
235 | |||
236 | set_bit(0, &port->write_urbs_free); | ||
237 | if (status) { | ||
238 | dev_dbg(&port->dev, "%s - nonzero write bulk status received: %d\n", | ||
239 | __func__, status); | ||
240 | return; | ||
241 | } | ||
242 | 168 | ||
243 | usb_serial_port_softint(port); | 169 | header->oh_seq = od->od_outseq++; |
244 | } | 170 | header->oh_len = count; |
245 | 171 | header->oh_xxx = 0x03; | |
246 | 172 | header->oh_pad = 0x00; | |
247 | static void omninet_disconnect(struct usb_serial *serial) | ||
248 | { | ||
249 | struct usb_serial_port *wport = serial->port[1]; | ||
250 | 173 | ||
251 | usb_kill_urb(wport->write_urb); | 174 | /* always 64 bytes */ |
175 | return OMNINET_BULKOUTSIZE; | ||
252 | } | 176 | } |
253 | 177 | ||
254 | module_usb_serial_driver(serial_drivers, id_table); | 178 | module_usb_serial_driver(serial_drivers, id_table); |
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 3937b9c3cc69..58657d64678b 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c | |||
@@ -367,16 +367,6 @@ static int opticon_ioctl(struct tty_struct *tty, | |||
367 | return -ENOIOCTLCMD; | 367 | return -ENOIOCTLCMD; |
368 | } | 368 | } |
369 | 369 | ||
370 | static int opticon_startup(struct usb_serial *serial) | ||
371 | { | ||
372 | if (!serial->num_bulk_in) { | ||
373 | dev_err(&serial->dev->dev, "no bulk in endpoint\n"); | ||
374 | return -ENODEV; | ||
375 | } | ||
376 | |||
377 | return 0; | ||
378 | } | ||
379 | |||
380 | static int opticon_port_probe(struct usb_serial_port *port) | 370 | static int opticon_port_probe(struct usb_serial_port *port) |
381 | { | 371 | { |
382 | struct opticon_private *priv; | 372 | struct opticon_private *priv; |
@@ -408,8 +398,8 @@ static struct usb_serial_driver opticon_device = { | |||
408 | }, | 398 | }, |
409 | .id_table = id_table, | 399 | .id_table = id_table, |
410 | .num_ports = 1, | 400 | .num_ports = 1, |
401 | .num_bulk_in = 1, | ||
411 | .bulk_in_size = 256, | 402 | .bulk_in_size = 256, |
412 | .attach = opticon_startup, | ||
413 | .port_probe = opticon_port_probe, | 403 | .port_probe = opticon_port_probe, |
414 | .port_remove = opticon_port_remove, | 404 | .port_remove = opticon_port_remove, |
415 | .open = opticon_open, | 405 | .open = opticon_open, |
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index b8bf52bf7a94..b11eead469ee 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c | |||
@@ -134,7 +134,6 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty); | |||
134 | static int oti6858_tiocmget(struct tty_struct *tty); | 134 | static int oti6858_tiocmget(struct tty_struct *tty); |
135 | static int oti6858_tiocmset(struct tty_struct *tty, | 135 | static int oti6858_tiocmset(struct tty_struct *tty, |
136 | unsigned int set, unsigned int clear); | 136 | unsigned int set, unsigned int clear); |
137 | static int oti6858_attach(struct usb_serial *serial); | ||
138 | static int oti6858_port_probe(struct usb_serial_port *port); | 137 | static int oti6858_port_probe(struct usb_serial_port *port); |
139 | static int oti6858_port_remove(struct usb_serial_port *port); | 138 | static int oti6858_port_remove(struct usb_serial_port *port); |
140 | 139 | ||
@@ -146,6 +145,9 @@ static struct usb_serial_driver oti6858_device = { | |||
146 | }, | 145 | }, |
147 | .id_table = id_table, | 146 | .id_table = id_table, |
148 | .num_ports = 1, | 147 | .num_ports = 1, |
148 | .num_bulk_in = 1, | ||
149 | .num_bulk_out = 1, | ||
150 | .num_interrupt_in = 1, | ||
149 | .open = oti6858_open, | 151 | .open = oti6858_open, |
150 | .close = oti6858_close, | 152 | .close = oti6858_close, |
151 | .write = oti6858_write, | 153 | .write = oti6858_write, |
@@ -159,7 +161,6 @@ static struct usb_serial_driver oti6858_device = { | |||
159 | .write_bulk_callback = oti6858_write_bulk_callback, | 161 | .write_bulk_callback = oti6858_write_bulk_callback, |
160 | .write_room = oti6858_write_room, | 162 | .write_room = oti6858_write_room, |
161 | .chars_in_buffer = oti6858_chars_in_buffer, | 163 | .chars_in_buffer = oti6858_chars_in_buffer, |
162 | .attach = oti6858_attach, | ||
163 | .port_probe = oti6858_port_probe, | 164 | .port_probe = oti6858_port_probe, |
164 | .port_remove = oti6858_port_remove, | 165 | .port_remove = oti6858_port_remove, |
165 | }; | 166 | }; |
@@ -326,20 +327,6 @@ static void send_data(struct work_struct *work) | |||
326 | usb_serial_port_softint(port); | 327 | usb_serial_port_softint(port); |
327 | } | 328 | } |
328 | 329 | ||
329 | static int oti6858_attach(struct usb_serial *serial) | ||
330 | { | ||
331 | unsigned char num_ports = serial->num_ports; | ||
332 | |||
333 | if (serial->num_bulk_in < num_ports || | ||
334 | serial->num_bulk_out < num_ports || | ||
335 | serial->num_interrupt_in < num_ports) { | ||
336 | dev_err(&serial->interface->dev, "missing endpoints\n"); | ||
337 | return -ENODEV; | ||
338 | } | ||
339 | |||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | static int oti6858_port_probe(struct usb_serial_port *port) | 330 | static int oti6858_port_probe(struct usb_serial_port *port) |
344 | { | 331 | { |
345 | struct oti6858_private *priv; | 332 | struct oti6858_private *priv; |
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index ca69eb42071b..c9ebefd8f35f 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -33,9 +33,11 @@ | |||
33 | 33 | ||
34 | #define PL2303_QUIRK_UART_STATE_IDX0 BIT(0) | 34 | #define PL2303_QUIRK_UART_STATE_IDX0 BIT(0) |
35 | #define PL2303_QUIRK_LEGACY BIT(1) | 35 | #define PL2303_QUIRK_LEGACY BIT(1) |
36 | #define PL2303_QUIRK_ENDPOINT_HACK BIT(2) | ||
36 | 37 | ||
37 | static const struct usb_device_id id_table[] = { | 38 | static const struct usb_device_id id_table[] = { |
38 | { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) }, | 39 | { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID), |
40 | .driver_info = PL2303_QUIRK_ENDPOINT_HACK }, | ||
39 | { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) }, | 41 | { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) }, |
40 | { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_DCU11) }, | 42 | { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_DCU11) }, |
41 | { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) }, | 43 | { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) }, |
@@ -48,7 +50,8 @@ static const struct usb_device_id id_table[] = { | |||
48 | { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ZTEK) }, | 50 | { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ZTEK) }, |
49 | { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, | 51 | { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, |
50 | { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) }, | 52 | { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) }, |
51 | { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) }, | 53 | { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID), |
54 | .driver_info = PL2303_QUIRK_ENDPOINT_HACK }, | ||
52 | { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID2) }, | 55 | { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID2) }, |
53 | { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) }, | 56 | { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) }, |
54 | { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) }, | 57 | { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) }, |
@@ -68,7 +71,8 @@ static const struct usb_device_id id_table[] = { | |||
68 | .driver_info = PL2303_QUIRK_UART_STATE_IDX0 }, | 71 | .driver_info = PL2303_QUIRK_UART_STATE_IDX0 }, |
69 | { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75), | 72 | { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75), |
70 | .driver_info = PL2303_QUIRK_UART_STATE_IDX0 }, | 73 | .driver_info = PL2303_QUIRK_UART_STATE_IDX0 }, |
71 | { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_EF81) }, | 74 | { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_EF81), |
75 | .driver_info = PL2303_QUIRK_ENDPOINT_HACK }, | ||
72 | { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_ID_S81) }, /* Benq/Siemens S81 */ | 76 | { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_ID_S81) }, /* Benq/Siemens S81 */ |
73 | { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) }, | 77 | { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) }, |
74 | { USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID) }, | 78 | { USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID) }, |
@@ -78,7 +82,8 @@ static const struct usb_device_id id_table[] = { | |||
78 | { USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) }, | 82 | { USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) }, |
79 | { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) }, | 83 | { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) }, |
80 | { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) }, | 84 | { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) }, |
81 | { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) }, | 85 | { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID), |
86 | .driver_info = PL2303_QUIRK_ENDPOINT_HACK }, | ||
82 | { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) }, | 87 | { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) }, |
83 | { USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) }, | 88 | { USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) }, |
84 | { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) }, | 89 | { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) }, |
@@ -218,20 +223,68 @@ static int pl2303_probe(struct usb_serial *serial, | |||
218 | return 0; | 223 | return 0; |
219 | } | 224 | } |
220 | 225 | ||
226 | /* | ||
227 | * Use interrupt endpoint from first interface if available. | ||
228 | * | ||
229 | * This is needed due to the looney way its endpoints are set up. | ||
230 | */ | ||
231 | static int pl2303_endpoint_hack(struct usb_serial *serial, | ||
232 | struct usb_serial_endpoints *epds) | ||
233 | { | ||
234 | struct usb_interface *interface = serial->interface; | ||
235 | struct usb_device *dev = serial->dev; | ||
236 | struct device *ddev = &interface->dev; | ||
237 | struct usb_host_interface *iface_desc; | ||
238 | struct usb_endpoint_descriptor *endpoint; | ||
239 | unsigned int i; | ||
240 | |||
241 | if (interface == dev->actconfig->interface[0]) | ||
242 | return 0; | ||
243 | |||
244 | /* check out the endpoints of the other interface */ | ||
245 | iface_desc = dev->actconfig->interface[0]->cur_altsetting; | ||
246 | |||
247 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | ||
248 | endpoint = &iface_desc->endpoint[i].desc; | ||
249 | |||
250 | if (!usb_endpoint_is_int_in(endpoint)) | ||
251 | continue; | ||
252 | |||
253 | dev_dbg(ddev, "found interrupt in on separate interface\n"); | ||
254 | if (epds->num_interrupt_in < ARRAY_SIZE(epds->interrupt_in)) | ||
255 | epds->interrupt_in[epds->num_interrupt_in++] = endpoint; | ||
256 | } | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | static int pl2303_calc_num_ports(struct usb_serial *serial, | ||
262 | struct usb_serial_endpoints *epds) | ||
263 | { | ||
264 | unsigned long quirks = (unsigned long)usb_get_serial_data(serial); | ||
265 | struct device *dev = &serial->interface->dev; | ||
266 | int ret; | ||
267 | |||
268 | if (quirks & PL2303_QUIRK_ENDPOINT_HACK) { | ||
269 | ret = pl2303_endpoint_hack(serial, epds); | ||
270 | if (ret) | ||
271 | return ret; | ||
272 | } | ||
273 | |||
274 | if (epds->num_interrupt_in < 1) { | ||
275 | dev_err(dev, "required interrupt-in endpoint missing\n"); | ||
276 | return -ENODEV; | ||
277 | } | ||
278 | |||
279 | return 1; | ||
280 | } | ||
281 | |||
221 | static int pl2303_startup(struct usb_serial *serial) | 282 | static int pl2303_startup(struct usb_serial *serial) |
222 | { | 283 | { |
223 | struct pl2303_serial_private *spriv; | 284 | struct pl2303_serial_private *spriv; |
224 | unsigned char num_ports = serial->num_ports; | ||
225 | enum pl2303_type type = TYPE_01; | 285 | enum pl2303_type type = TYPE_01; |
226 | unsigned char *buf; | 286 | unsigned char *buf; |
227 | 287 | ||
228 | if (serial->num_bulk_in < num_ports || | ||
229 | serial->num_bulk_out < num_ports || | ||
230 | serial->num_interrupt_in < num_ports) { | ||
231 | dev_err(&serial->interface->dev, "missing endpoints\n"); | ||
232 | return -ENODEV; | ||
233 | } | ||
234 | |||
235 | spriv = kzalloc(sizeof(*spriv), GFP_KERNEL); | 288 | spriv = kzalloc(sizeof(*spriv), GFP_KERNEL); |
236 | if (!spriv) | 289 | if (!spriv) |
237 | return -ENOMEM; | 290 | return -ENOMEM; |
@@ -938,7 +991,9 @@ static struct usb_serial_driver pl2303_device = { | |||
938 | .name = "pl2303", | 991 | .name = "pl2303", |
939 | }, | 992 | }, |
940 | .id_table = id_table, | 993 | .id_table = id_table, |
941 | .num_ports = 1, | 994 | .num_bulk_in = 1, |
995 | .num_bulk_out = 1, | ||
996 | .num_interrupt_in = 0, /* see pl2303_calc_num_ports */ | ||
942 | .bulk_in_size = 256, | 997 | .bulk_in_size = 256, |
943 | .bulk_out_size = 256, | 998 | .bulk_out_size = 256, |
944 | .open = pl2303_open, | 999 | .open = pl2303_open, |
@@ -954,6 +1009,7 @@ static struct usb_serial_driver pl2303_device = { | |||
954 | .process_read_urb = pl2303_process_read_urb, | 1009 | .process_read_urb = pl2303_process_read_urb, |
955 | .read_int_callback = pl2303_read_int_callback, | 1010 | .read_int_callback = pl2303_read_int_callback, |
956 | .probe = pl2303_probe, | 1011 | .probe = pl2303_probe, |
1012 | .calc_num_ports = pl2303_calc_num_ports, | ||
957 | .attach = pl2303_startup, | 1013 | .attach = pl2303_startup, |
958 | .release = pl2303_release, | 1014 | .release = pl2303_release, |
959 | .port_probe = pl2303_port_probe, | 1015 | .port_probe = pl2303_port_probe, |
diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index fdbb904d153f..60e17d1444c3 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c | |||
@@ -246,7 +246,8 @@ static inline int update_mctrl(struct qt2_port_private *port_priv, | |||
246 | return status; | 246 | return status; |
247 | } | 247 | } |
248 | 248 | ||
249 | static int qt2_calc_num_ports(struct usb_serial *serial) | 249 | static int qt2_calc_num_ports(struct usb_serial *serial, |
250 | struct usb_serial_endpoints *epds) | ||
250 | { | 251 | { |
251 | struct qt2_device_detail d; | 252 | struct qt2_device_detail d; |
252 | int i; | 253 | int i; |
@@ -600,7 +601,6 @@ static void qt2_process_read_urb(struct urb *urb) | |||
600 | escapeflag = true; | 601 | escapeflag = true; |
601 | break; | 602 | break; |
602 | case QT2_CONTROL_ESCAPE: | 603 | case QT2_CONTROL_ESCAPE: |
603 | tty_buffer_request_room(&port->port, 2); | ||
604 | tty_insert_flip_string(&port->port, ch, 2); | 604 | tty_insert_flip_string(&port->port, ch, 2); |
605 | i += 2; | 605 | i += 2; |
606 | escapeflag = true; | 606 | escapeflag = true; |
@@ -615,8 +615,7 @@ static void qt2_process_read_urb(struct urb *urb) | |||
615 | continue; | 615 | continue; |
616 | } | 616 | } |
617 | 617 | ||
618 | tty_buffer_request_room(&port->port, 1); | 618 | tty_insert_flip_char(&port->port, *ch, TTY_NORMAL); |
619 | tty_insert_flip_string(&port->port, ch, 1); | ||
620 | } | 619 | } |
621 | 620 | ||
622 | tty_flip_buffer_push(&port->port); | 621 | tty_flip_buffer_push(&port->port); |
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 465e851b2815..4c4ac4705ac0 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c | |||
@@ -85,7 +85,8 @@ static int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable) | |||
85 | USB_CTRL_SET_TIMEOUT); /* int timeout */ | 85 | USB_CTRL_SET_TIMEOUT); /* int timeout */ |
86 | } | 86 | } |
87 | 87 | ||
88 | static int sierra_calc_num_ports(struct usb_serial *serial) | 88 | static int sierra_calc_num_ports(struct usb_serial *serial, |
89 | struct usb_serial_endpoints *epds) | ||
89 | { | 90 | { |
90 | int num_ports = 0; | 91 | int num_ports = 0; |
91 | u8 ifnum, numendpoints; | 92 | u8 ifnum, numendpoints; |
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index ddfd787c461c..5167b6564c8b 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c | |||
@@ -154,19 +154,6 @@ static int spcp8x5_probe(struct usb_serial *serial, | |||
154 | return 0; | 154 | return 0; |
155 | } | 155 | } |
156 | 156 | ||
157 | static int spcp8x5_attach(struct usb_serial *serial) | ||
158 | { | ||
159 | unsigned char num_ports = serial->num_ports; | ||
160 | |||
161 | if (serial->num_bulk_in < num_ports || | ||
162 | serial->num_bulk_out < num_ports) { | ||
163 | dev_err(&serial->interface->dev, "missing endpoints\n"); | ||
164 | return -ENODEV; | ||
165 | } | ||
166 | |||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | static int spcp8x5_port_probe(struct usb_serial_port *port) | 157 | static int spcp8x5_port_probe(struct usb_serial_port *port) |
171 | { | 158 | { |
172 | const struct usb_device_id *id = usb_get_serial_data(port->serial); | 159 | const struct usb_device_id *id = usb_get_serial_data(port->serial); |
@@ -488,6 +475,8 @@ static struct usb_serial_driver spcp8x5_device = { | |||
488 | }, | 475 | }, |
489 | .id_table = id_table, | 476 | .id_table = id_table, |
490 | .num_ports = 1, | 477 | .num_ports = 1, |
478 | .num_bulk_in = 1, | ||
479 | .num_bulk_out = 1, | ||
491 | .open = spcp8x5_open, | 480 | .open = spcp8x5_open, |
492 | .dtr_rts = spcp8x5_dtr_rts, | 481 | .dtr_rts = spcp8x5_dtr_rts, |
493 | .carrier_raised = spcp8x5_carrier_raised, | 482 | .carrier_raised = spcp8x5_carrier_raised, |
@@ -496,7 +485,6 @@ static struct usb_serial_driver spcp8x5_device = { | |||
496 | .tiocmget = spcp8x5_tiocmget, | 485 | .tiocmget = spcp8x5_tiocmget, |
497 | .tiocmset = spcp8x5_tiocmset, | 486 | .tiocmset = spcp8x5_tiocmset, |
498 | .probe = spcp8x5_probe, | 487 | .probe = spcp8x5_probe, |
499 | .attach = spcp8x5_attach, | ||
500 | .port_probe = spcp8x5_port_probe, | 488 | .port_probe = spcp8x5_port_probe, |
501 | .port_remove = spcp8x5_port_remove, | 489 | .port_remove = spcp8x5_port_remove, |
502 | }; | 490 | }; |
diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index 37f3ad15ed06..0d1727232d0c 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c | |||
@@ -147,16 +147,6 @@ static void symbol_unthrottle(struct tty_struct *tty) | |||
147 | } | 147 | } |
148 | } | 148 | } |
149 | 149 | ||
150 | static int symbol_startup(struct usb_serial *serial) | ||
151 | { | ||
152 | if (!serial->num_interrupt_in) { | ||
153 | dev_err(&serial->dev->dev, "no interrupt-in endpoint\n"); | ||
154 | return -ENODEV; | ||
155 | } | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static int symbol_port_probe(struct usb_serial_port *port) | 150 | static int symbol_port_probe(struct usb_serial_port *port) |
161 | { | 151 | { |
162 | struct symbol_private *priv; | 152 | struct symbol_private *priv; |
@@ -188,7 +178,7 @@ static struct usb_serial_driver symbol_device = { | |||
188 | }, | 178 | }, |
189 | .id_table = id_table, | 179 | .id_table = id_table, |
190 | .num_ports = 1, | 180 | .num_ports = 1, |
191 | .attach = symbol_startup, | 181 | .num_interrupt_in = 1, |
192 | .port_probe = symbol_port_probe, | 182 | .port_probe = symbol_port_probe, |
193 | .port_remove = symbol_port_remove, | 183 | .port_remove = symbol_port_remove, |
194 | .open = symbol_open, | 184 | .open = symbol_open, |
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 3107bf5d1c96..8fc3854e5e69 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c | |||
@@ -427,6 +427,7 @@ static struct usb_serial_driver ti_1port_device = { | |||
427 | .description = "TI USB 3410 1 port adapter", | 427 | .description = "TI USB 3410 1 port adapter", |
428 | .id_table = ti_id_table_3410, | 428 | .id_table = ti_id_table_3410, |
429 | .num_ports = 1, | 429 | .num_ports = 1, |
430 | .num_bulk_out = 1, | ||
430 | .attach = ti_startup, | 431 | .attach = ti_startup, |
431 | .release = ti_release, | 432 | .release = ti_release, |
432 | .port_probe = ti_port_probe, | 433 | .port_probe = ti_port_probe, |
@@ -459,6 +460,7 @@ static struct usb_serial_driver ti_2port_device = { | |||
459 | .description = "TI USB 5052 2 port adapter", | 460 | .description = "TI USB 5052 2 port adapter", |
460 | .id_table = ti_id_table_5052, | 461 | .id_table = ti_id_table_5052, |
461 | .num_ports = 2, | 462 | .num_ports = 2, |
463 | .num_bulk_out = 1, | ||
462 | .attach = ti_startup, | 464 | .attach = ti_startup, |
463 | .release = ti_release, | 465 | .release = ti_release, |
464 | .port_probe = ti_port_probe, | 466 | .port_probe = ti_port_probe, |
@@ -927,7 +929,6 @@ static void ti_set_termios(struct tty_struct *tty, | |||
927 | { | 929 | { |
928 | struct ti_port *tport = usb_get_serial_port_data(port); | 930 | struct ti_port *tport = usb_get_serial_port_data(port); |
929 | struct ti_uart_config *config; | 931 | struct ti_uart_config *config; |
930 | tcflag_t cflag, iflag; | ||
931 | int baud; | 932 | int baud; |
932 | int status; | 933 | int status; |
933 | int port_number = port->port_number; | 934 | int port_number = port->port_number; |
@@ -935,13 +936,6 @@ static void ti_set_termios(struct tty_struct *tty, | |||
935 | u16 wbaudrate; | 936 | u16 wbaudrate; |
936 | u16 wflags = 0; | 937 | u16 wflags = 0; |
937 | 938 | ||
938 | cflag = tty->termios.c_cflag; | ||
939 | iflag = tty->termios.c_iflag; | ||
940 | |||
941 | dev_dbg(&port->dev, "%s - cflag %08x, iflag %08x\n", __func__, cflag, iflag); | ||
942 | dev_dbg(&port->dev, "%s - old clfag %08x, old iflag %08x\n", __func__, | ||
943 | old_termios->c_cflag, old_termios->c_iflag); | ||
944 | |||
945 | config = kmalloc(sizeof(*config), GFP_KERNEL); | 939 | config = kmalloc(sizeof(*config), GFP_KERNEL); |
946 | if (!config) | 940 | if (!config) |
947 | return; | 941 | return; |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 4a037b4a79cf..c7ca95f64edc 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -38,7 +38,6 @@ | |||
38 | #include <linux/usb/serial.h> | 38 | #include <linux/usb/serial.h> |
39 | #include <linux/kfifo.h> | 39 | #include <linux/kfifo.h> |
40 | #include <linux/idr.h> | 40 | #include <linux/idr.h> |
41 | #include "pl2303.h" | ||
42 | 41 | ||
43 | #define DRIVER_AUTHOR "Greg Kroah-Hartman <gregkh@linuxfoundation.org>" | 42 | #define DRIVER_AUTHOR "Greg Kroah-Hartman <gregkh@linuxfoundation.org>" |
44 | #define DRIVER_DESC "USB Serial Driver core" | 43 | #define DRIVER_DESC "USB Serial Driver core" |
@@ -710,6 +709,39 @@ static const struct tty_port_operations serial_port_ops = { | |||
710 | .shutdown = serial_port_shutdown, | 709 | .shutdown = serial_port_shutdown, |
711 | }; | 710 | }; |
712 | 711 | ||
712 | static void find_endpoints(struct usb_serial *serial, | ||
713 | struct usb_serial_endpoints *epds) | ||
714 | { | ||
715 | struct device *dev = &serial->interface->dev; | ||
716 | struct usb_host_interface *iface_desc; | ||
717 | struct usb_endpoint_descriptor *epd; | ||
718 | unsigned int i; | ||
719 | |||
720 | BUILD_BUG_ON(ARRAY_SIZE(epds->bulk_in) < USB_MAXENDPOINTS / 2); | ||
721 | BUILD_BUG_ON(ARRAY_SIZE(epds->bulk_out) < USB_MAXENDPOINTS / 2); | ||
722 | BUILD_BUG_ON(ARRAY_SIZE(epds->interrupt_in) < USB_MAXENDPOINTS / 2); | ||
723 | BUILD_BUG_ON(ARRAY_SIZE(epds->interrupt_out) < USB_MAXENDPOINTS / 2); | ||
724 | |||
725 | iface_desc = serial->interface->cur_altsetting; | ||
726 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | ||
727 | epd = &iface_desc->endpoint[i].desc; | ||
728 | |||
729 | if (usb_endpoint_is_bulk_in(epd)) { | ||
730 | dev_dbg(dev, "found bulk in on endpoint %u\n", i); | ||
731 | epds->bulk_in[epds->num_bulk_in++] = epd; | ||
732 | } else if (usb_endpoint_is_bulk_out(epd)) { | ||
733 | dev_dbg(dev, "found bulk out on endpoint %u\n", i); | ||
734 | epds->bulk_out[epds->num_bulk_out++] = epd; | ||
735 | } else if (usb_endpoint_is_int_in(epd)) { | ||
736 | dev_dbg(dev, "found interrupt in on endpoint %u\n", i); | ||
737 | epds->interrupt_in[epds->num_interrupt_in++] = epd; | ||
738 | } else if (usb_endpoint_is_int_out(epd)) { | ||
739 | dev_dbg(dev, "found interrupt out on endpoint %u\n", i); | ||
740 | epds->interrupt_out[epds->num_interrupt_out++] = epd; | ||
741 | } | ||
742 | } | ||
743 | } | ||
744 | |||
713 | static int usb_serial_probe(struct usb_interface *interface, | 745 | static int usb_serial_probe(struct usb_interface *interface, |
714 | const struct usb_device_id *id) | 746 | const struct usb_device_id *id) |
715 | { | 747 | { |
@@ -717,23 +749,15 @@ static int usb_serial_probe(struct usb_interface *interface, | |||
717 | struct usb_device *dev = interface_to_usbdev(interface); | 749 | struct usb_device *dev = interface_to_usbdev(interface); |
718 | struct usb_serial *serial = NULL; | 750 | struct usb_serial *serial = NULL; |
719 | struct usb_serial_port *port; | 751 | struct usb_serial_port *port; |
720 | struct usb_host_interface *iface_desc; | ||
721 | struct usb_endpoint_descriptor *endpoint; | 752 | struct usb_endpoint_descriptor *endpoint; |
722 | struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS]; | 753 | struct usb_serial_endpoints *epds; |
723 | struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS]; | ||
724 | struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS]; | ||
725 | struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS]; | ||
726 | struct usb_serial_driver *type = NULL; | 754 | struct usb_serial_driver *type = NULL; |
727 | int retval; | 755 | int retval; |
728 | int buffer_size; | 756 | int buffer_size; |
729 | int i; | 757 | int i; |
730 | int j; | 758 | int j; |
731 | int num_interrupt_in = 0; | ||
732 | int num_interrupt_out = 0; | ||
733 | int num_bulk_in = 0; | ||
734 | int num_bulk_out = 0; | ||
735 | int num_ports = 0; | 759 | int num_ports = 0; |
736 | int max_endpoints; | 760 | unsigned char max_endpoints; |
737 | 761 | ||
738 | mutex_lock(&table_lock); | 762 | mutex_lock(&table_lock); |
739 | type = search_serial_device(interface); | 763 | type = search_serial_device(interface); |
@@ -752,8 +776,8 @@ static int usb_serial_probe(struct usb_interface *interface, | |||
752 | 776 | ||
753 | serial = create_serial(dev, interface, type); | 777 | serial = create_serial(dev, interface, type); |
754 | if (!serial) { | 778 | if (!serial) { |
755 | module_put(type->driver.owner); | 779 | retval = -ENOMEM; |
756 | return -ENOMEM; | 780 | goto err_put_module; |
757 | } | 781 | } |
758 | 782 | ||
759 | /* if this device type has a probe function, call it */ | 783 | /* if this device type has a probe function, call it */ |
@@ -765,129 +789,48 @@ static int usb_serial_probe(struct usb_interface *interface, | |||
765 | 789 | ||
766 | if (retval) { | 790 | if (retval) { |
767 | dev_dbg(ddev, "sub driver rejected device\n"); | 791 | dev_dbg(ddev, "sub driver rejected device\n"); |
768 | usb_serial_put(serial); | 792 | goto err_put_serial; |
769 | module_put(type->driver.owner); | ||
770 | return retval; | ||
771 | } | 793 | } |
772 | } | 794 | } |
773 | 795 | ||
774 | /* descriptor matches, let's find the endpoints needed */ | 796 | /* descriptor matches, let's find the endpoints needed */ |
775 | /* check out the endpoints */ | 797 | epds = kzalloc(sizeof(*epds), GFP_KERNEL); |
776 | iface_desc = interface->cur_altsetting; | 798 | if (!epds) { |
777 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | 799 | retval = -ENOMEM; |
778 | endpoint = &iface_desc->endpoint[i].desc; | 800 | goto err_put_serial; |
779 | |||
780 | if (usb_endpoint_is_bulk_in(endpoint)) { | ||
781 | /* we found a bulk in endpoint */ | ||
782 | dev_dbg(ddev, "found bulk in on endpoint %d\n", i); | ||
783 | if (num_bulk_in < MAX_NUM_PORTS) { | ||
784 | bulk_in_endpoint[num_bulk_in] = endpoint; | ||
785 | ++num_bulk_in; | ||
786 | } | ||
787 | } | ||
788 | |||
789 | if (usb_endpoint_is_bulk_out(endpoint)) { | ||
790 | /* we found a bulk out endpoint */ | ||
791 | dev_dbg(ddev, "found bulk out on endpoint %d\n", i); | ||
792 | if (num_bulk_out < MAX_NUM_PORTS) { | ||
793 | bulk_out_endpoint[num_bulk_out] = endpoint; | ||
794 | ++num_bulk_out; | ||
795 | } | ||
796 | } | ||
797 | |||
798 | if (usb_endpoint_is_int_in(endpoint)) { | ||
799 | /* we found a interrupt in endpoint */ | ||
800 | dev_dbg(ddev, "found interrupt in on endpoint %d\n", i); | ||
801 | if (num_interrupt_in < MAX_NUM_PORTS) { | ||
802 | interrupt_in_endpoint[num_interrupt_in] = | ||
803 | endpoint; | ||
804 | ++num_interrupt_in; | ||
805 | } | ||
806 | } | ||
807 | |||
808 | if (usb_endpoint_is_int_out(endpoint)) { | ||
809 | /* we found an interrupt out endpoint */ | ||
810 | dev_dbg(ddev, "found interrupt out on endpoint %d\n", i); | ||
811 | if (num_interrupt_out < MAX_NUM_PORTS) { | ||
812 | interrupt_out_endpoint[num_interrupt_out] = | ||
813 | endpoint; | ||
814 | ++num_interrupt_out; | ||
815 | } | ||
816 | } | ||
817 | } | 801 | } |
818 | 802 | ||
819 | #if IS_ENABLED(CONFIG_USB_SERIAL_PL2303) | 803 | find_endpoints(serial, epds); |
820 | /* BEGIN HORRIBLE HACK FOR PL2303 */ | ||
821 | /* this is needed due to the looney way its endpoints are set up */ | ||
822 | if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) && | ||
823 | (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) || | ||
824 | ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) && | ||
825 | (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) || | ||
826 | ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) && | ||
827 | (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID)) || | ||
828 | ((le16_to_cpu(dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) && | ||
829 | (le16_to_cpu(dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_EF81))) { | ||
830 | if (interface != dev->actconfig->interface[0]) { | ||
831 | /* check out the endpoints of the other interface*/ | ||
832 | iface_desc = dev->actconfig->interface[0]->cur_altsetting; | ||
833 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | ||
834 | endpoint = &iface_desc->endpoint[i].desc; | ||
835 | if (usb_endpoint_is_int_in(endpoint)) { | ||
836 | /* we found a interrupt in endpoint */ | ||
837 | dev_dbg(ddev, "found interrupt in for Prolific device on separate interface\n"); | ||
838 | if (num_interrupt_in < MAX_NUM_PORTS) { | ||
839 | interrupt_in_endpoint[num_interrupt_in] = endpoint; | ||
840 | ++num_interrupt_in; | ||
841 | } | ||
842 | } | ||
843 | } | ||
844 | } | ||
845 | 804 | ||
846 | /* Now make sure the PL-2303 is configured correctly. | 805 | if (epds->num_bulk_in < type->num_bulk_in || |
847 | * If not, give up now and hope this hack will work | 806 | epds->num_bulk_out < type->num_bulk_out || |
848 | * properly during a later invocation of usb_serial_probe | 807 | epds->num_interrupt_in < type->num_interrupt_in || |
849 | */ | 808 | epds->num_interrupt_out < type->num_interrupt_out) { |
850 | if (num_bulk_in == 0 || num_bulk_out == 0) { | 809 | dev_err(ddev, "required endpoints missing\n"); |
851 | dev_info(ddev, "PL-2303 hack: descriptors matched but endpoints did not\n"); | 810 | retval = -ENODEV; |
852 | usb_serial_put(serial); | 811 | goto err_free_epds; |
853 | module_put(type->driver.owner); | ||
854 | return -ENODEV; | ||
855 | } | ||
856 | } | ||
857 | /* END HORRIBLE HACK FOR PL2303 */ | ||
858 | #endif | ||
859 | |||
860 | #ifdef CONFIG_USB_SERIAL_GENERIC | ||
861 | if (type == &usb_serial_generic_device) { | ||
862 | num_ports = num_bulk_out; | ||
863 | if (num_ports == 0) { | ||
864 | dev_err(ddev, "Generic device with no bulk out, not allowed.\n"); | ||
865 | usb_serial_put(serial); | ||
866 | module_put(type->driver.owner); | ||
867 | return -EIO; | ||
868 | } | ||
869 | dev_info(ddev, "The \"generic\" usb-serial driver is only for testing and one-off prototypes.\n"); | ||
870 | dev_info(ddev, "Tell linux-usb@vger.kernel.org to add your device to a proper driver.\n"); | ||
871 | } | 812 | } |
872 | #endif | 813 | |
873 | if (!num_ports) { | 814 | if (type->calc_num_ports) { |
874 | /* if this device type has a calc_num_ports function, call it */ | 815 | retval = type->calc_num_ports(serial, epds); |
875 | if (type->calc_num_ports) | 816 | if (retval < 0) |
876 | num_ports = type->calc_num_ports(serial); | 817 | goto err_free_epds; |
877 | if (!num_ports) | 818 | num_ports = retval; |
878 | num_ports = type->num_ports; | ||
879 | } | 819 | } |
880 | 820 | ||
821 | if (!num_ports) | ||
822 | num_ports = type->num_ports; | ||
823 | |||
881 | if (num_ports > MAX_NUM_PORTS) { | 824 | if (num_ports > MAX_NUM_PORTS) { |
882 | dev_warn(ddev, "too many ports requested: %d\n", num_ports); | 825 | dev_warn(ddev, "too many ports requested: %d\n", num_ports); |
883 | num_ports = MAX_NUM_PORTS; | 826 | num_ports = MAX_NUM_PORTS; |
884 | } | 827 | } |
885 | 828 | ||
886 | serial->num_ports = num_ports; | 829 | serial->num_ports = (unsigned char)num_ports; |
887 | serial->num_bulk_in = num_bulk_in; | 830 | serial->num_bulk_in = epds->num_bulk_in; |
888 | serial->num_bulk_out = num_bulk_out; | 831 | serial->num_bulk_out = epds->num_bulk_out; |
889 | serial->num_interrupt_in = num_interrupt_in; | 832 | serial->num_interrupt_in = epds->num_interrupt_in; |
890 | serial->num_interrupt_out = num_interrupt_out; | 833 | serial->num_interrupt_out = epds->num_interrupt_out; |
891 | 834 | ||
892 | /* found all that we need */ | 835 | /* found all that we need */ |
893 | dev_info(ddev, "%s converter detected\n", type->description); | 836 | dev_info(ddev, "%s converter detected\n", type->description); |
@@ -895,10 +838,10 @@ static int usb_serial_probe(struct usb_interface *interface, | |||
895 | /* create our ports, we need as many as the max endpoints */ | 838 | /* create our ports, we need as many as the max endpoints */ |
896 | /* we don't use num_ports here because some devices have more | 839 | /* we don't use num_ports here because some devices have more |
897 | endpoint pairs than ports */ | 840 | endpoint pairs than ports */ |
898 | max_endpoints = max(num_bulk_in, num_bulk_out); | 841 | max_endpoints = max(epds->num_bulk_in, epds->num_bulk_out); |
899 | max_endpoints = max(max_endpoints, num_interrupt_in); | 842 | max_endpoints = max(max_endpoints, epds->num_interrupt_in); |
900 | max_endpoints = max(max_endpoints, num_interrupt_out); | 843 | max_endpoints = max(max_endpoints, epds->num_interrupt_out); |
901 | max_endpoints = max(max_endpoints, (int)serial->num_ports); | 844 | max_endpoints = max(max_endpoints, serial->num_ports); |
902 | serial->num_port_pointers = max_endpoints; | 845 | serial->num_port_pointers = max_endpoints; |
903 | 846 | ||
904 | dev_dbg(ddev, "setting up %d port structure(s)\n", max_endpoints); | 847 | dev_dbg(ddev, "setting up %d port structure(s)\n", max_endpoints); |
@@ -923,8 +866,8 @@ static int usb_serial_probe(struct usb_interface *interface, | |||
923 | } | 866 | } |
924 | 867 | ||
925 | /* set up the endpoint information */ | 868 | /* set up the endpoint information */ |
926 | for (i = 0; i < num_bulk_in; ++i) { | 869 | for (i = 0; i < epds->num_bulk_in; ++i) { |
927 | endpoint = bulk_in_endpoint[i]; | 870 | endpoint = epds->bulk_in[i]; |
928 | port = serial->port[i]; | 871 | port = serial->port[i]; |
929 | buffer_size = max_t(int, serial->type->bulk_in_size, | 872 | buffer_size = max_t(int, serial->type->bulk_in_size, |
930 | usb_endpoint_maxp(endpoint)); | 873 | usb_endpoint_maxp(endpoint)); |
@@ -952,8 +895,8 @@ static int usb_serial_probe(struct usb_interface *interface, | |||
952 | port->bulk_in_buffer = port->bulk_in_buffers[0]; | 895 | port->bulk_in_buffer = port->bulk_in_buffers[0]; |
953 | } | 896 | } |
954 | 897 | ||
955 | for (i = 0; i < num_bulk_out; ++i) { | 898 | for (i = 0; i < epds->num_bulk_out; ++i) { |
956 | endpoint = bulk_out_endpoint[i]; | 899 | endpoint = epds->bulk_out[i]; |
957 | port = serial->port[i]; | 900 | port = serial->port[i]; |
958 | if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL)) | 901 | if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL)) |
959 | goto probe_error; | 902 | goto probe_error; |
@@ -985,8 +928,8 @@ static int usb_serial_probe(struct usb_interface *interface, | |||
985 | } | 928 | } |
986 | 929 | ||
987 | if (serial->type->read_int_callback) { | 930 | if (serial->type->read_int_callback) { |
988 | for (i = 0; i < num_interrupt_in; ++i) { | 931 | for (i = 0; i < epds->num_interrupt_in; ++i) { |
989 | endpoint = interrupt_in_endpoint[i]; | 932 | endpoint = epds->interrupt_in[i]; |
990 | port = serial->port[i]; | 933 | port = serial->port[i]; |
991 | port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); | 934 | port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); |
992 | if (!port->interrupt_in_urb) | 935 | if (!port->interrupt_in_urb) |
@@ -1005,13 +948,13 @@ static int usb_serial_probe(struct usb_interface *interface, | |||
1005 | serial->type->read_int_callback, port, | 948 | serial->type->read_int_callback, port, |
1006 | endpoint->bInterval); | 949 | endpoint->bInterval); |
1007 | } | 950 | } |
1008 | } else if (num_interrupt_in) { | 951 | } else if (epds->num_interrupt_in) { |
1009 | dev_dbg(ddev, "The device claims to support interrupt in transfers, but read_int_callback is not defined\n"); | 952 | dev_dbg(ddev, "The device claims to support interrupt in transfers, but read_int_callback is not defined\n"); |
1010 | } | 953 | } |
1011 | 954 | ||
1012 | if (serial->type->write_int_callback) { | 955 | if (serial->type->write_int_callback) { |
1013 | for (i = 0; i < num_interrupt_out; ++i) { | 956 | for (i = 0; i < epds->num_interrupt_out; ++i) { |
1014 | endpoint = interrupt_out_endpoint[i]; | 957 | endpoint = epds->interrupt_out[i]; |
1015 | port = serial->port[i]; | 958 | port = serial->port[i]; |
1016 | port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL); | 959 | port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL); |
1017 | if (!port->interrupt_out_urb) | 960 | if (!port->interrupt_out_urb) |
@@ -1031,7 +974,7 @@ static int usb_serial_probe(struct usb_interface *interface, | |||
1031 | serial->type->write_int_callback, port, | 974 | serial->type->write_int_callback, port, |
1032 | endpoint->bInterval); | 975 | endpoint->bInterval); |
1033 | } | 976 | } |
1034 | } else if (num_interrupt_out) { | 977 | } else if (epds->num_interrupt_out) { |
1035 | dev_dbg(ddev, "The device claims to support interrupt out transfers, but write_int_callback is not defined\n"); | 978 | dev_dbg(ddev, "The device claims to support interrupt out transfers, but write_int_callback is not defined\n"); |
1036 | } | 979 | } |
1037 | 980 | ||
@@ -1053,12 +996,6 @@ static int usb_serial_probe(struct usb_interface *interface, | |||
1053 | serial->attached = 1; | 996 | serial->attached = 1; |
1054 | } | 997 | } |
1055 | 998 | ||
1056 | /* Avoid race with tty_open and serial_install by setting the | ||
1057 | * disconnected flag and not clearing it until all ports have been | ||
1058 | * registered. | ||
1059 | */ | ||
1060 | serial->disconnected = 1; | ||
1061 | |||
1062 | if (allocate_minors(serial, num_ports)) { | 999 | if (allocate_minors(serial, num_ports)) { |
1063 | dev_err(ddev, "No more free serial minor numbers\n"); | 1000 | dev_err(ddev, "No more free serial minor numbers\n"); |
1064 | goto probe_error; | 1001 | goto probe_error; |
@@ -1076,18 +1013,23 @@ static int usb_serial_probe(struct usb_interface *interface, | |||
1076 | dev_err(ddev, "Error registering port device, continuing\n"); | 1013 | dev_err(ddev, "Error registering port device, continuing\n"); |
1077 | } | 1014 | } |
1078 | 1015 | ||
1079 | serial->disconnected = 0; | ||
1080 | |||
1081 | if (num_ports > 0) | 1016 | if (num_ports > 0) |
1082 | usb_serial_console_init(serial->port[0]->minor); | 1017 | usb_serial_console_init(serial->port[0]->minor); |
1083 | exit: | 1018 | exit: |
1019 | kfree(epds); | ||
1084 | module_put(type->driver.owner); | 1020 | module_put(type->driver.owner); |
1085 | return 0; | 1021 | return 0; |
1086 | 1022 | ||
1087 | probe_error: | 1023 | probe_error: |
1024 | retval = -EIO; | ||
1025 | err_free_epds: | ||
1026 | kfree(epds); | ||
1027 | err_put_serial: | ||
1088 | usb_serial_put(serial); | 1028 | usb_serial_put(serial); |
1029 | err_put_module: | ||
1089 | module_put(type->driver.owner); | 1030 | module_put(type->driver.owner); |
1090 | return -EIO; | 1031 | |
1032 | return retval; | ||
1091 | } | 1033 | } |
1092 | 1034 | ||
1093 | static void usb_serial_disconnect(struct usb_interface *interface) | 1035 | static void usb_serial_disconnect(struct usb_interface *interface) |
diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c index 92f7e5c21162..12f4c5a91e62 100644 --- a/drivers/usb/serial/usb_debug.c +++ b/drivers/usb/serial/usb_debug.c | |||
@@ -17,7 +17,7 @@ | |||
17 | 17 | ||
18 | #define USB_DEBUG_MAX_PACKET_SIZE 8 | 18 | #define USB_DEBUG_MAX_PACKET_SIZE 8 |
19 | #define USB_DEBUG_BRK_SIZE 8 | 19 | #define USB_DEBUG_BRK_SIZE 8 |
20 | static char USB_DEBUG_BRK[USB_DEBUG_BRK_SIZE] = { | 20 | static const char USB_DEBUG_BRK[USB_DEBUG_BRK_SIZE] = { |
21 | 0x00, | 21 | 0x00, |
22 | 0xff, | 22 | 0xff, |
23 | 0x01, | 23 | 0x01, |
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 337a0be89fcf..9f3317a940ef 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c | |||
@@ -40,11 +40,12 @@ static int visor_open(struct tty_struct *tty, struct usb_serial_port *port); | |||
40 | static void visor_close(struct usb_serial_port *port); | 40 | static void visor_close(struct usb_serial_port *port); |
41 | static int visor_probe(struct usb_serial *serial, | 41 | static int visor_probe(struct usb_serial *serial, |
42 | const struct usb_device_id *id); | 42 | const struct usb_device_id *id); |
43 | static int visor_calc_num_ports(struct usb_serial *serial); | 43 | static int visor_calc_num_ports(struct usb_serial *serial, |
44 | struct usb_serial_endpoints *epds); | ||
45 | static int clie_5_calc_num_ports(struct usb_serial *serial, | ||
46 | struct usb_serial_endpoints *epds); | ||
44 | static void visor_read_int_callback(struct urb *urb); | 47 | static void visor_read_int_callback(struct urb *urb); |
45 | static int clie_3_5_startup(struct usb_serial *serial); | 48 | static int clie_3_5_startup(struct usb_serial *serial); |
46 | static int treo_attach(struct usb_serial *serial); | ||
47 | static int clie_5_attach(struct usb_serial *serial); | ||
48 | static int palm_os_3_probe(struct usb_serial *serial, | 49 | static int palm_os_3_probe(struct usb_serial *serial, |
49 | const struct usb_device_id *id); | 50 | const struct usb_device_id *id); |
50 | static int palm_os_4_probe(struct usb_serial *serial, | 51 | static int palm_os_4_probe(struct usb_serial *serial, |
@@ -174,7 +175,6 @@ static struct usb_serial_driver handspring_device = { | |||
174 | .close = visor_close, | 175 | .close = visor_close, |
175 | .throttle = usb_serial_generic_throttle, | 176 | .throttle = usb_serial_generic_throttle, |
176 | .unthrottle = usb_serial_generic_unthrottle, | 177 | .unthrottle = usb_serial_generic_unthrottle, |
177 | .attach = treo_attach, | ||
178 | .probe = visor_probe, | 178 | .probe = visor_probe, |
179 | .calc_num_ports = visor_calc_num_ports, | 179 | .calc_num_ports = visor_calc_num_ports, |
180 | .read_int_callback = visor_read_int_callback, | 180 | .read_int_callback = visor_read_int_callback, |
@@ -189,14 +189,14 @@ static struct usb_serial_driver clie_5_device = { | |||
189 | .description = "Sony Clie 5.0", | 189 | .description = "Sony Clie 5.0", |
190 | .id_table = clie_id_5_table, | 190 | .id_table = clie_id_5_table, |
191 | .num_ports = 2, | 191 | .num_ports = 2, |
192 | .num_bulk_out = 2, | ||
192 | .bulk_out_size = 256, | 193 | .bulk_out_size = 256, |
193 | .open = visor_open, | 194 | .open = visor_open, |
194 | .close = visor_close, | 195 | .close = visor_close, |
195 | .throttle = usb_serial_generic_throttle, | 196 | .throttle = usb_serial_generic_throttle, |
196 | .unthrottle = usb_serial_generic_unthrottle, | 197 | .unthrottle = usb_serial_generic_unthrottle, |
197 | .attach = clie_5_attach, | ||
198 | .probe = visor_probe, | 198 | .probe = visor_probe, |
199 | .calc_num_ports = visor_calc_num_ports, | 199 | .calc_num_ports = clie_5_calc_num_ports, |
200 | .read_int_callback = visor_read_int_callback, | 200 | .read_int_callback = visor_read_int_callback, |
201 | }; | 201 | }; |
202 | 202 | ||
@@ -466,16 +466,60 @@ static int visor_probe(struct usb_serial *serial, | |||
466 | return retval; | 466 | return retval; |
467 | } | 467 | } |
468 | 468 | ||
469 | static int visor_calc_num_ports(struct usb_serial *serial) | 469 | static int visor_calc_num_ports(struct usb_serial *serial, |
470 | struct usb_serial_endpoints *epds) | ||
470 | { | 471 | { |
472 | unsigned int vid = le16_to_cpu(serial->dev->descriptor.idVendor); | ||
471 | int num_ports = (int)(long)(usb_get_serial_data(serial)); | 473 | int num_ports = (int)(long)(usb_get_serial_data(serial)); |
472 | 474 | ||
473 | if (num_ports) | 475 | if (num_ports) |
474 | usb_set_serial_data(serial, NULL); | 476 | usb_set_serial_data(serial, NULL); |
475 | 477 | ||
478 | /* | ||
479 | * Only swap the bulk endpoints for the Handspring devices with | ||
480 | * interrupt in endpoints, which for now are the Treo devices. | ||
481 | */ | ||
482 | if (!(vid == HANDSPRING_VENDOR_ID || vid == KYOCERA_VENDOR_ID) || | ||
483 | epds->num_interrupt_in == 0) | ||
484 | goto out; | ||
485 | |||
486 | if (epds->num_bulk_in < 2 || epds->num_interrupt_in < 2) { | ||
487 | dev_err(&serial->interface->dev, "missing endpoints\n"); | ||
488 | return -ENODEV; | ||
489 | } | ||
490 | |||
491 | /* | ||
492 | * It appears that Treos and Kyoceras want to use the | ||
493 | * 1st bulk in endpoint to communicate with the 2nd bulk out endpoint, | ||
494 | * so let's swap the 1st and 2nd bulk in and interrupt endpoints. | ||
495 | * Note that swapping the bulk out endpoints would break lots of | ||
496 | * apps that want to communicate on the second port. | ||
497 | */ | ||
498 | swap(epds->bulk_in[0], epds->bulk_in[1]); | ||
499 | swap(epds->interrupt_in[0], epds->interrupt_in[1]); | ||
500 | out: | ||
476 | return num_ports; | 501 | return num_ports; |
477 | } | 502 | } |
478 | 503 | ||
504 | static int clie_5_calc_num_ports(struct usb_serial *serial, | ||
505 | struct usb_serial_endpoints *epds) | ||
506 | { | ||
507 | /* | ||
508 | * TH55 registers 2 ports. | ||
509 | * Communication in from the UX50/TH55 uses the first bulk-in | ||
510 | * endpoint, while communication out to the UX50/TH55 uses the second | ||
511 | * bulk-out endpoint. | ||
512 | */ | ||
513 | |||
514 | /* | ||
515 | * FIXME: Should we swap the descriptors instead of using the same | ||
516 | * bulk-out endpoint for both ports? | ||
517 | */ | ||
518 | epds->bulk_out[0] = epds->bulk_out[1]; | ||
519 | |||
520 | return serial->type->num_ports; | ||
521 | } | ||
522 | |||
479 | static int clie_3_5_startup(struct usb_serial *serial) | 523 | static int clie_3_5_startup(struct usb_serial *serial) |
480 | { | 524 | { |
481 | struct device *dev = &serial->dev->dev; | 525 | struct device *dev = &serial->dev->dev; |
@@ -531,94 +575,6 @@ out: | |||
531 | return result; | 575 | return result; |
532 | } | 576 | } |
533 | 577 | ||
534 | static int treo_attach(struct usb_serial *serial) | ||
535 | { | ||
536 | struct usb_serial_port *swap_port; | ||
537 | |||
538 | /* Only do this endpoint hack for the Handspring devices with | ||
539 | * interrupt in endpoints, which for now are the Treo devices. */ | ||
540 | if (!((le16_to_cpu(serial->dev->descriptor.idVendor) | ||
541 | == HANDSPRING_VENDOR_ID) || | ||
542 | (le16_to_cpu(serial->dev->descriptor.idVendor) | ||
543 | == KYOCERA_VENDOR_ID)) || | ||
544 | (serial->num_interrupt_in == 0)) | ||
545 | return 0; | ||
546 | |||
547 | if (serial->num_bulk_in < 2 || serial->num_interrupt_in < 2) { | ||
548 | dev_err(&serial->interface->dev, "missing endpoints\n"); | ||
549 | return -ENODEV; | ||
550 | } | ||
551 | |||
552 | /* | ||
553 | * It appears that Treos and Kyoceras want to use the | ||
554 | * 1st bulk in endpoint to communicate with the 2nd bulk out endpoint, | ||
555 | * so let's swap the 1st and 2nd bulk in and interrupt endpoints. | ||
556 | * Note that swapping the bulk out endpoints would break lots of | ||
557 | * apps that want to communicate on the second port. | ||
558 | */ | ||
559 | #define COPY_PORT(dest, src) \ | ||
560 | do { \ | ||
561 | int i; \ | ||
562 | \ | ||
563 | for (i = 0; i < ARRAY_SIZE(src->read_urbs); ++i) { \ | ||
564 | dest->read_urbs[i] = src->read_urbs[i]; \ | ||
565 | dest->read_urbs[i]->context = dest; \ | ||
566 | dest->bulk_in_buffers[i] = src->bulk_in_buffers[i]; \ | ||
567 | } \ | ||
568 | dest->read_urb = src->read_urb; \ | ||
569 | dest->bulk_in_endpointAddress = src->bulk_in_endpointAddress;\ | ||
570 | dest->bulk_in_buffer = src->bulk_in_buffer; \ | ||
571 | dest->bulk_in_size = src->bulk_in_size; \ | ||
572 | dest->interrupt_in_urb = src->interrupt_in_urb; \ | ||
573 | dest->interrupt_in_urb->context = dest; \ | ||
574 | dest->interrupt_in_endpointAddress = \ | ||
575 | src->interrupt_in_endpointAddress;\ | ||
576 | dest->interrupt_in_buffer = src->interrupt_in_buffer; \ | ||
577 | } while (0); | ||
578 | |||
579 | swap_port = kmalloc(sizeof(*swap_port), GFP_KERNEL); | ||
580 | if (!swap_port) | ||
581 | return -ENOMEM; | ||
582 | COPY_PORT(swap_port, serial->port[0]); | ||
583 | COPY_PORT(serial->port[0], serial->port[1]); | ||
584 | COPY_PORT(serial->port[1], swap_port); | ||
585 | kfree(swap_port); | ||
586 | |||
587 | return 0; | ||
588 | } | ||
589 | |||
590 | static int clie_5_attach(struct usb_serial *serial) | ||
591 | { | ||
592 | struct usb_serial_port *port; | ||
593 | unsigned int pipe; | ||
594 | int j; | ||
595 | |||
596 | /* TH55 registers 2 ports. | ||
597 | Communication in from the UX50/TH55 uses bulk_in_endpointAddress | ||
598 | from port 0. Communication out to the UX50/TH55 uses | ||
599 | bulk_out_endpointAddress from port 1 | ||
600 | |||
601 | Lets do a quick and dirty mapping | ||
602 | */ | ||
603 | |||
604 | /* some sanity check */ | ||
605 | if (serial->num_bulk_out < 2) { | ||
606 | dev_err(&serial->interface->dev, "missing bulk out endpoints\n"); | ||
607 | return -ENODEV; | ||
608 | } | ||
609 | |||
610 | /* port 0 now uses the modified endpoint Address */ | ||
611 | port = serial->port[0]; | ||
612 | port->bulk_out_endpointAddress = | ||
613 | serial->port[1]->bulk_out_endpointAddress; | ||
614 | |||
615 | pipe = usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress); | ||
616 | for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) | ||
617 | port->write_urbs[j]->pipe = pipe; | ||
618 | |||
619 | return 0; | ||
620 | } | ||
621 | |||
622 | module_usb_serial_driver(serial_drivers, id_table_combined); | 578 | module_usb_serial_driver(serial_drivers, id_table_combined); |
623 | 579 | ||
624 | MODULE_AUTHOR(DRIVER_AUTHOR); | 580 | MODULE_AUTHOR(DRIVER_AUTHOR); |
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 5ab65eb1dacc..55cebc1e6fec 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c | |||
@@ -80,8 +80,6 @@ static int whiteheat_firmware_download(struct usb_serial *serial, | |||
80 | static int whiteheat_firmware_attach(struct usb_serial *serial); | 80 | static int whiteheat_firmware_attach(struct usb_serial *serial); |
81 | 81 | ||
82 | /* function prototypes for the Connect Tech WhiteHEAT serial converter */ | 82 | /* function prototypes for the Connect Tech WhiteHEAT serial converter */ |
83 | static int whiteheat_probe(struct usb_serial *serial, | ||
84 | const struct usb_device_id *id); | ||
85 | static int whiteheat_attach(struct usb_serial *serial); | 83 | static int whiteheat_attach(struct usb_serial *serial); |
86 | static void whiteheat_release(struct usb_serial *serial); | 84 | static void whiteheat_release(struct usb_serial *serial); |
87 | static int whiteheat_port_probe(struct usb_serial_port *port); | 85 | static int whiteheat_port_probe(struct usb_serial_port *port); |
@@ -118,7 +116,8 @@ static struct usb_serial_driver whiteheat_device = { | |||
118 | .description = "Connect Tech - WhiteHEAT", | 116 | .description = "Connect Tech - WhiteHEAT", |
119 | .id_table = id_table_std, | 117 | .id_table = id_table_std, |
120 | .num_ports = 4, | 118 | .num_ports = 4, |
121 | .probe = whiteheat_probe, | 119 | .num_bulk_in = 5, |
120 | .num_bulk_out = 5, | ||
122 | .attach = whiteheat_attach, | 121 | .attach = whiteheat_attach, |
123 | .release = whiteheat_release, | 122 | .release = whiteheat_release, |
124 | .port_probe = whiteheat_port_probe, | 123 | .port_probe = whiteheat_port_probe, |
@@ -221,33 +220,6 @@ static int whiteheat_firmware_attach(struct usb_serial *serial) | |||
221 | * Connect Tech's White Heat serial driver functions | 220 | * Connect Tech's White Heat serial driver functions |
222 | *****************************************************************************/ | 221 | *****************************************************************************/ |
223 | 222 | ||
224 | static int whiteheat_probe(struct usb_serial *serial, | ||
225 | const struct usb_device_id *id) | ||
226 | { | ||
227 | struct usb_host_interface *iface_desc; | ||
228 | struct usb_endpoint_descriptor *endpoint; | ||
229 | size_t num_bulk_in = 0; | ||
230 | size_t num_bulk_out = 0; | ||
231 | size_t min_num_bulk; | ||
232 | unsigned int i; | ||
233 | |||
234 | iface_desc = serial->interface->cur_altsetting; | ||
235 | |||
236 | for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { | ||
237 | endpoint = &iface_desc->endpoint[i].desc; | ||
238 | if (usb_endpoint_is_bulk_in(endpoint)) | ||
239 | ++num_bulk_in; | ||
240 | if (usb_endpoint_is_bulk_out(endpoint)) | ||
241 | ++num_bulk_out; | ||
242 | } | ||
243 | |||
244 | min_num_bulk = COMMAND_PORT + 1; | ||
245 | if (num_bulk_in < min_num_bulk || num_bulk_out < min_num_bulk) | ||
246 | return -ENODEV; | ||
247 | |||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | static int whiteheat_attach(struct usb_serial *serial) | 223 | static int whiteheat_attach(struct usb_serial *serial) |
252 | { | 224 | { |
253 | struct usb_serial_port *command_port; | 225 | struct usb_serial_port *command_port; |
diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c index f9d407f0b508..b05ba4929f00 100644 --- a/drivers/usb/storage/karma.c +++ b/drivers/usb/storage/karma.c | |||
@@ -105,7 +105,7 @@ static struct us_unusual_dev karma_unusual_dev_list[] = { | |||
105 | */ | 105 | */ |
106 | static int rio_karma_send_command(char cmd, struct us_data *us) | 106 | static int rio_karma_send_command(char cmd, struct us_data *us) |
107 | { | 107 | { |
108 | int result, partial; | 108 | int result; |
109 | unsigned long timeout; | 109 | unsigned long timeout; |
110 | static unsigned char seq = 1; | 110 | static unsigned char seq = 1; |
111 | struct karma_data *data = (struct karma_data *) us->extra; | 111 | struct karma_data *data = (struct karma_data *) us->extra; |
@@ -119,12 +119,12 @@ static int rio_karma_send_command(char cmd, struct us_data *us) | |||
119 | timeout = jiffies + msecs_to_jiffies(6000); | 119 | timeout = jiffies + msecs_to_jiffies(6000); |
120 | for (;;) { | 120 | for (;;) { |
121 | result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, | 121 | result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, |
122 | us->iobuf, RIO_SEND_LEN, &partial); | 122 | us->iobuf, RIO_SEND_LEN, NULL); |
123 | if (result != USB_STOR_XFER_GOOD) | 123 | if (result != USB_STOR_XFER_GOOD) |
124 | goto err; | 124 | goto err; |
125 | 125 | ||
126 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, | 126 | result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, |
127 | data->recv, RIO_RECV_LEN, &partial); | 127 | data->recv, RIO_RECV_LEN, NULL); |
128 | if (result != USB_STOR_XFER_GOOD) | 128 | if (result != USB_STOR_XFER_GOOD) |
129 | goto err; | 129 | goto err; |
130 | 130 | ||
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 9129f6cb8230..5a70c33ef0e0 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h | |||
@@ -42,7 +42,7 @@ | |||
42 | * - a patch that adds the entry for your device, including your | 42 | * - a patch that adds the entry for your device, including your |
43 | * email address right above the entry (plus maybe a brief | 43 | * email address right above the entry (plus maybe a brief |
44 | * explanation of the reason for the entry), | 44 | * explanation of the reason for the entry), |
45 | * - a copy of /proc/bus/usb/devices with your device plugged in | 45 | * - a copy of /sys/kernel/debug/usb/devices with your device plugged in |
46 | * running with this patch. | 46 | * running with this patch. |
47 | * Send your submission to either Phil Dibowitz <phil@ipom.com> or | 47 | * Send your submission to either Phil Dibowitz <phil@ipom.com> or |
48 | * Alan Stern <stern@rowland.harvard.edu>, and don't forget to CC: the | 48 | * Alan Stern <stern@rowland.harvard.edu>, and don't forget to CC: the |
@@ -176,7 +176,7 @@ UNUSUAL_DEV( 0x0420, 0x0001, 0x0100, 0x0100, | |||
176 | 176 | ||
177 | /* | 177 | /* |
178 | * Reported by Andrew Nayenko <relan@bk.ru> | 178 | * Reported by Andrew Nayenko <relan@bk.ru> |
179 | * Updated for new firmware by Phillip Potter <phillipinda@hotmail.com> | 179 | * Updated for new firmware by Phillip Potter <phil@philpotter.co.uk> |
180 | */ | 180 | */ |
181 | UNUSUAL_DEV( 0x0421, 0x0019, 0x0592, 0x0610, | 181 | UNUSUAL_DEV( 0x0421, 0x0019, 0x0592, 0x0610, |
182 | "Nokia", | 182 | "Nokia", |
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 615bea08ec0a..06615934fed1 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c | |||
@@ -737,13 +737,11 @@ static void get_protocol(struct us_data *us) | |||
737 | /* Get the pipe settings */ | 737 | /* Get the pipe settings */ |
738 | static int get_pipes(struct us_data *us) | 738 | static int get_pipes(struct us_data *us) |
739 | { | 739 | { |
740 | struct usb_host_interface *altsetting = | 740 | struct usb_host_interface *alt = us->pusb_intf->cur_altsetting; |
741 | us->pusb_intf->cur_altsetting; | 741 | struct usb_endpoint_descriptor *ep_in; |
742 | int i; | 742 | struct usb_endpoint_descriptor *ep_out; |
743 | struct usb_endpoint_descriptor *ep; | 743 | struct usb_endpoint_descriptor *ep_int; |
744 | struct usb_endpoint_descriptor *ep_in = NULL; | 744 | int res; |
745 | struct usb_endpoint_descriptor *ep_out = NULL; | ||
746 | struct usb_endpoint_descriptor *ep_int = NULL; | ||
747 | 745 | ||
748 | /* | 746 | /* |
749 | * Find the first endpoint of each type we need. | 747 | * Find the first endpoint of each type we need. |
@@ -751,28 +749,16 @@ static int get_pipes(struct us_data *us) | |||
751 | * An optional interrupt-in is OK (necessary for CBI protocol). | 749 | * An optional interrupt-in is OK (necessary for CBI protocol). |
752 | * We will ignore any others. | 750 | * We will ignore any others. |
753 | */ | 751 | */ |
754 | for (i = 0; i < altsetting->desc.bNumEndpoints; i++) { | 752 | res = usb_find_common_endpoints(alt, &ep_in, &ep_out, NULL, NULL); |
755 | ep = &altsetting->endpoint[i].desc; | 753 | if (res) { |
756 | 754 | usb_stor_dbg(us, "bulk endpoints not found\n"); | |
757 | if (usb_endpoint_xfer_bulk(ep)) { | 755 | return res; |
758 | if (usb_endpoint_dir_in(ep)) { | ||
759 | if (!ep_in) | ||
760 | ep_in = ep; | ||
761 | } else { | ||
762 | if (!ep_out) | ||
763 | ep_out = ep; | ||
764 | } | ||
765 | } | ||
766 | |||
767 | else if (usb_endpoint_is_int_in(ep)) { | ||
768 | if (!ep_int) | ||
769 | ep_int = ep; | ||
770 | } | ||
771 | } | 756 | } |
772 | 757 | ||
773 | if (!ep_in || !ep_out || (us->protocol == USB_PR_CBI && !ep_int)) { | 758 | res = usb_find_int_in_endpoint(alt, &ep_int); |
774 | usb_stor_dbg(us, "Endpoint sanity check failed! Rejecting dev.\n"); | 759 | if (res && us->protocol == USB_PR_CBI) { |
775 | return -EIO; | 760 | usb_stor_dbg(us, "interrupt endpoint not found\n"); |
761 | return res; | ||
776 | } | 762 | } |
777 | 763 | ||
778 | /* Calculate and store the pipe values */ | 764 | /* Calculate and store the pipe values */ |
diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig new file mode 100644 index 000000000000..dfcfe459b7cf --- /dev/null +++ b/drivers/usb/typec/Kconfig | |||
@@ -0,0 +1,22 @@ | |||
1 | |||
2 | menu "USB Power Delivery and Type-C drivers" | ||
3 | |||
4 | config TYPEC | ||
5 | tristate | ||
6 | |||
7 | config TYPEC_WCOVE | ||
8 | tristate "Intel WhiskeyCove PMIC USB Type-C PHY driver" | ||
9 | depends on ACPI | ||
10 | depends on INTEL_SOC_PMIC | ||
11 | depends on INTEL_PMC_IPC | ||
12 | depends on BXT_WC_PMIC_OPREGION | ||
13 | select TYPEC | ||
14 | help | ||
15 | This driver adds support for USB Type-C detection on Intel Broxton | ||
16 | platforms that have Intel Whiskey Cove PMIC. The driver can detect the | ||
17 | role and cable orientation. | ||
18 | |||
19 | To compile this driver as module, choose M here: the module will be | ||
20 | called typec_wcove | ||
21 | |||
22 | endmenu | ||
diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile new file mode 100644 index 000000000000..b9cb862221af --- /dev/null +++ b/drivers/usb/typec/Makefile | |||
@@ -0,0 +1,2 @@ | |||
1 | obj-$(CONFIG_TYPEC) += typec.o | ||
2 | obj-$(CONFIG_TYPEC_WCOVE) += typec_wcove.o | ||
diff --git a/drivers/usb/typec/typec.c b/drivers/usb/typec/typec.c new file mode 100644 index 000000000000..89e540bb7ff3 --- /dev/null +++ b/drivers/usb/typec/typec.c | |||
@@ -0,0 +1,1262 @@ | |||
1 | /* | ||
2 | * USB Type-C Connector Class | ||
3 | * | ||
4 | * Copyright (C) 2017, Intel Corporation | ||
5 | * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/device.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/usb/typec.h> | ||
16 | |||
17 | struct typec_mode { | ||
18 | int index; | ||
19 | u32 vdo; | ||
20 | char *desc; | ||
21 | enum typec_port_type roles; | ||
22 | |||
23 | struct typec_altmode *alt_mode; | ||
24 | |||
25 | unsigned int active:1; | ||
26 | |||
27 | char group_name[6]; | ||
28 | struct attribute_group group; | ||
29 | struct attribute *attrs[5]; | ||
30 | struct device_attribute vdo_attr; | ||
31 | struct device_attribute desc_attr; | ||
32 | struct device_attribute active_attr; | ||
33 | struct device_attribute roles_attr; | ||
34 | }; | ||
35 | |||
36 | struct typec_altmode { | ||
37 | struct device dev; | ||
38 | u16 svid; | ||
39 | int n_modes; | ||
40 | struct typec_mode modes[ALTMODE_MAX_MODES]; | ||
41 | const struct attribute_group *mode_groups[ALTMODE_MAX_MODES]; | ||
42 | }; | ||
43 | |||
44 | struct typec_plug { | ||
45 | struct device dev; | ||
46 | enum typec_plug_index index; | ||
47 | }; | ||
48 | |||
49 | struct typec_cable { | ||
50 | struct device dev; | ||
51 | enum typec_plug_type type; | ||
52 | struct usb_pd_identity *identity; | ||
53 | unsigned int active:1; | ||
54 | }; | ||
55 | |||
56 | struct typec_partner { | ||
57 | struct device dev; | ||
58 | unsigned int usb_pd:1; | ||
59 | struct usb_pd_identity *identity; | ||
60 | enum typec_accessory accessory; | ||
61 | }; | ||
62 | |||
63 | struct typec_port { | ||
64 | unsigned int id; | ||
65 | struct device dev; | ||
66 | |||
67 | int prefer_role; | ||
68 | enum typec_data_role data_role; | ||
69 | enum typec_role pwr_role; | ||
70 | enum typec_role vconn_role; | ||
71 | enum typec_pwr_opmode pwr_opmode; | ||
72 | |||
73 | const struct typec_capability *cap; | ||
74 | }; | ||
75 | |||
76 | #define to_typec_port(_dev_) container_of(_dev_, struct typec_port, dev) | ||
77 | #define to_typec_plug(_dev_) container_of(_dev_, struct typec_plug, dev) | ||
78 | #define to_typec_cable(_dev_) container_of(_dev_, struct typec_cable, dev) | ||
79 | #define to_typec_partner(_dev_) container_of(_dev_, struct typec_partner, dev) | ||
80 | #define to_altmode(_dev_) container_of(_dev_, struct typec_altmode, dev) | ||
81 | |||
82 | static const struct device_type typec_partner_dev_type; | ||
83 | static const struct device_type typec_cable_dev_type; | ||
84 | static const struct device_type typec_plug_dev_type; | ||
85 | static const struct device_type typec_port_dev_type; | ||
86 | |||
87 | #define is_typec_partner(_dev_) (_dev_->type == &typec_partner_dev_type) | ||
88 | #define is_typec_cable(_dev_) (_dev_->type == &typec_cable_dev_type) | ||
89 | #define is_typec_plug(_dev_) (_dev_->type == &typec_plug_dev_type) | ||
90 | #define is_typec_port(_dev_) (_dev_->type == &typec_port_dev_type) | ||
91 | |||
92 | static DEFINE_IDA(typec_index_ida); | ||
93 | static struct class *typec_class; | ||
94 | |||
95 | /* Common attributes */ | ||
96 | |||
97 | static const char * const typec_accessory_modes[] = { | ||
98 | [TYPEC_ACCESSORY_NONE] = "none", | ||
99 | [TYPEC_ACCESSORY_AUDIO] = "analog_audio", | ||
100 | [TYPEC_ACCESSORY_DEBUG] = "debug", | ||
101 | }; | ||
102 | |||
103 | static struct usb_pd_identity *get_pd_identity(struct device *dev) | ||
104 | { | ||
105 | if (is_typec_partner(dev)) { | ||
106 | struct typec_partner *partner = to_typec_partner(dev); | ||
107 | |||
108 | return partner->identity; | ||
109 | } else if (is_typec_cable(dev)) { | ||
110 | struct typec_cable *cable = to_typec_cable(dev); | ||
111 | |||
112 | return cable->identity; | ||
113 | } | ||
114 | return NULL; | ||
115 | } | ||
116 | |||
117 | static ssize_t id_header_show(struct device *dev, struct device_attribute *attr, | ||
118 | char *buf) | ||
119 | { | ||
120 | struct usb_pd_identity *id = get_pd_identity(dev); | ||
121 | |||
122 | return sprintf(buf, "0x%08x\n", id->id_header); | ||
123 | } | ||
124 | static DEVICE_ATTR_RO(id_header); | ||
125 | |||
126 | static ssize_t cert_stat_show(struct device *dev, struct device_attribute *attr, | ||
127 | char *buf) | ||
128 | { | ||
129 | struct usb_pd_identity *id = get_pd_identity(dev); | ||
130 | |||
131 | return sprintf(buf, "0x%08x\n", id->cert_stat); | ||
132 | } | ||
133 | static DEVICE_ATTR_RO(cert_stat); | ||
134 | |||
135 | static ssize_t product_show(struct device *dev, struct device_attribute *attr, | ||
136 | char *buf) | ||
137 | { | ||
138 | struct usb_pd_identity *id = get_pd_identity(dev); | ||
139 | |||
140 | return sprintf(buf, "0x%08x\n", id->product); | ||
141 | } | ||
142 | static DEVICE_ATTR_RO(product); | ||
143 | |||
144 | static struct attribute *usb_pd_id_attrs[] = { | ||
145 | &dev_attr_id_header.attr, | ||
146 | &dev_attr_cert_stat.attr, | ||
147 | &dev_attr_product.attr, | ||
148 | NULL | ||
149 | }; | ||
150 | |||
151 | static const struct attribute_group usb_pd_id_group = { | ||
152 | .name = "identity", | ||
153 | .attrs = usb_pd_id_attrs, | ||
154 | }; | ||
155 | |||
156 | static const struct attribute_group *usb_pd_id_groups[] = { | ||
157 | &usb_pd_id_group, | ||
158 | NULL, | ||
159 | }; | ||
160 | |||
161 | static void typec_report_identity(struct device *dev) | ||
162 | { | ||
163 | sysfs_notify(&dev->kobj, "identity", "id_header"); | ||
164 | sysfs_notify(&dev->kobj, "identity", "cert_stat"); | ||
165 | sysfs_notify(&dev->kobj, "identity", "product"); | ||
166 | } | ||
167 | |||
168 | /* ------------------------------------------------------------------------- */ | ||
169 | /* Alternate Modes */ | ||
170 | |||
171 | /** | ||
172 | * typec_altmode_update_active - Report Enter/Exit mode | ||
173 | * @alt: Handle to the alternate mode | ||
174 | * @mode: Mode index | ||
175 | * @active: True when the mode has been entered | ||
176 | * | ||
177 | * If a partner or cable plug executes Enter/Exit Mode command successfully, the | ||
178 | * drivers use this routine to report the updated state of the mode. | ||
179 | */ | ||
180 | void typec_altmode_update_active(struct typec_altmode *alt, int mode, | ||
181 | bool active) | ||
182 | { | ||
183 | struct typec_mode *m = &alt->modes[mode]; | ||
184 | char dir[6]; | ||
185 | |||
186 | if (m->active == active) | ||
187 | return; | ||
188 | |||
189 | m->active = active; | ||
190 | snprintf(dir, sizeof(dir), "mode%d", mode); | ||
191 | sysfs_notify(&alt->dev.kobj, dir, "active"); | ||
192 | kobject_uevent(&alt->dev.kobj, KOBJ_CHANGE); | ||
193 | } | ||
194 | EXPORT_SYMBOL_GPL(typec_altmode_update_active); | ||
195 | |||
196 | /** | ||
197 | * typec_altmode2port - Alternate Mode to USB Type-C port | ||
198 | * @alt: The Alternate Mode | ||
199 | * | ||
200 | * Returns handle to the port that a cable plug or partner with @alt is | ||
201 | * connected to. | ||
202 | */ | ||
203 | struct typec_port *typec_altmode2port(struct typec_altmode *alt) | ||
204 | { | ||
205 | if (is_typec_plug(alt->dev.parent)) | ||
206 | return to_typec_port(alt->dev.parent->parent->parent); | ||
207 | if (is_typec_partner(alt->dev.parent)) | ||
208 | return to_typec_port(alt->dev.parent->parent); | ||
209 | if (is_typec_port(alt->dev.parent)) | ||
210 | return to_typec_port(alt->dev.parent); | ||
211 | |||
212 | return NULL; | ||
213 | } | ||
214 | EXPORT_SYMBOL_GPL(typec_altmode2port); | ||
215 | |||
216 | static ssize_t | ||
217 | typec_altmode_vdo_show(struct device *dev, struct device_attribute *attr, | ||
218 | char *buf) | ||
219 | { | ||
220 | struct typec_mode *mode = container_of(attr, struct typec_mode, | ||
221 | vdo_attr); | ||
222 | |||
223 | return sprintf(buf, "0x%08x\n", mode->vdo); | ||
224 | } | ||
225 | |||
226 | static ssize_t | ||
227 | typec_altmode_desc_show(struct device *dev, struct device_attribute *attr, | ||
228 | char *buf) | ||
229 | { | ||
230 | struct typec_mode *mode = container_of(attr, struct typec_mode, | ||
231 | desc_attr); | ||
232 | |||
233 | return sprintf(buf, "%s\n", mode->desc ? mode->desc : ""); | ||
234 | } | ||
235 | |||
236 | static ssize_t | ||
237 | typec_altmode_active_show(struct device *dev, struct device_attribute *attr, | ||
238 | char *buf) | ||
239 | { | ||
240 | struct typec_mode *mode = container_of(attr, struct typec_mode, | ||
241 | active_attr); | ||
242 | |||
243 | return sprintf(buf, "%s\n", mode->active ? "yes" : "no"); | ||
244 | } | ||
245 | |||
246 | static ssize_t | ||
247 | typec_altmode_active_store(struct device *dev, struct device_attribute *attr, | ||
248 | const char *buf, size_t size) | ||
249 | { | ||
250 | struct typec_mode *mode = container_of(attr, struct typec_mode, | ||
251 | active_attr); | ||
252 | struct typec_port *port = typec_altmode2port(mode->alt_mode); | ||
253 | bool activate; | ||
254 | int ret; | ||
255 | |||
256 | if (!port->cap->activate_mode) | ||
257 | return -EOPNOTSUPP; | ||
258 | |||
259 | ret = kstrtobool(buf, &activate); | ||
260 | if (ret) | ||
261 | return ret; | ||
262 | |||
263 | ret = port->cap->activate_mode(port->cap, mode->index, activate); | ||
264 | if (ret) | ||
265 | return ret; | ||
266 | |||
267 | return size; | ||
268 | } | ||
269 | |||
270 | static ssize_t | ||
271 | typec_altmode_roles_show(struct device *dev, struct device_attribute *attr, | ||
272 | char *buf) | ||
273 | { | ||
274 | struct typec_mode *mode = container_of(attr, struct typec_mode, | ||
275 | roles_attr); | ||
276 | ssize_t ret; | ||
277 | |||
278 | switch (mode->roles) { | ||
279 | case TYPEC_PORT_DFP: | ||
280 | ret = sprintf(buf, "source\n"); | ||
281 | break; | ||
282 | case TYPEC_PORT_UFP: | ||
283 | ret = sprintf(buf, "sink\n"); | ||
284 | break; | ||
285 | case TYPEC_PORT_DRP: | ||
286 | default: | ||
287 | ret = sprintf(buf, "source sink\n"); | ||
288 | break; | ||
289 | } | ||
290 | return ret; | ||
291 | } | ||
292 | |||
293 | static void typec_init_modes(struct typec_altmode *alt, | ||
294 | struct typec_mode_desc *desc, bool is_port) | ||
295 | { | ||
296 | int i; | ||
297 | |||
298 | for (i = 0; i < alt->n_modes; i++, desc++) { | ||
299 | struct typec_mode *mode = &alt->modes[i]; | ||
300 | |||
301 | /* Not considering the human readable description critical */ | ||
302 | mode->desc = kstrdup(desc->desc, GFP_KERNEL); | ||
303 | if (desc->desc && !mode->desc) | ||
304 | dev_err(&alt->dev, "failed to copy mode%d desc\n", i); | ||
305 | |||
306 | mode->alt_mode = alt; | ||
307 | mode->vdo = desc->vdo; | ||
308 | mode->roles = desc->roles; | ||
309 | mode->index = desc->index; | ||
310 | sprintf(mode->group_name, "mode%d", desc->index); | ||
311 | |||
312 | sysfs_attr_init(&mode->vdo_attr.attr); | ||
313 | mode->vdo_attr.attr.name = "vdo"; | ||
314 | mode->vdo_attr.attr.mode = 0444; | ||
315 | mode->vdo_attr.show = typec_altmode_vdo_show; | ||
316 | |||
317 | sysfs_attr_init(&mode->desc_attr.attr); | ||
318 | mode->desc_attr.attr.name = "description"; | ||
319 | mode->desc_attr.attr.mode = 0444; | ||
320 | mode->desc_attr.show = typec_altmode_desc_show; | ||
321 | |||
322 | sysfs_attr_init(&mode->active_attr.attr); | ||
323 | mode->active_attr.attr.name = "active"; | ||
324 | mode->active_attr.attr.mode = 0644; | ||
325 | mode->active_attr.show = typec_altmode_active_show; | ||
326 | mode->active_attr.store = typec_altmode_active_store; | ||
327 | |||
328 | mode->attrs[0] = &mode->vdo_attr.attr; | ||
329 | mode->attrs[1] = &mode->desc_attr.attr; | ||
330 | mode->attrs[2] = &mode->active_attr.attr; | ||
331 | |||
332 | /* With ports, list the roles that the mode is supported with */ | ||
333 | if (is_port) { | ||
334 | sysfs_attr_init(&mode->roles_attr.attr); | ||
335 | mode->roles_attr.attr.name = "supported_roles"; | ||
336 | mode->roles_attr.attr.mode = 0444; | ||
337 | mode->roles_attr.show = typec_altmode_roles_show; | ||
338 | |||
339 | mode->attrs[3] = &mode->roles_attr.attr; | ||
340 | } | ||
341 | |||
342 | mode->group.attrs = mode->attrs; | ||
343 | mode->group.name = mode->group_name; | ||
344 | |||
345 | alt->mode_groups[i] = &mode->group; | ||
346 | } | ||
347 | } | ||
348 | |||
349 | static ssize_t svid_show(struct device *dev, struct device_attribute *attr, | ||
350 | char *buf) | ||
351 | { | ||
352 | struct typec_altmode *alt = to_altmode(dev); | ||
353 | |||
354 | return sprintf(buf, "%04x\n", alt->svid); | ||
355 | } | ||
356 | static DEVICE_ATTR_RO(svid); | ||
357 | |||
358 | static struct attribute *typec_altmode_attrs[] = { | ||
359 | &dev_attr_svid.attr, | ||
360 | NULL | ||
361 | }; | ||
362 | ATTRIBUTE_GROUPS(typec_altmode); | ||
363 | |||
364 | static void typec_altmode_release(struct device *dev) | ||
365 | { | ||
366 | struct typec_altmode *alt = to_altmode(dev); | ||
367 | int i; | ||
368 | |||
369 | for (i = 0; i < alt->n_modes; i++) | ||
370 | kfree(alt->modes[i].desc); | ||
371 | kfree(alt); | ||
372 | } | ||
373 | |||
374 | static const struct device_type typec_altmode_dev_type = { | ||
375 | .name = "typec_alternate_mode", | ||
376 | .groups = typec_altmode_groups, | ||
377 | .release = typec_altmode_release, | ||
378 | }; | ||
379 | |||
380 | static struct typec_altmode * | ||
381 | typec_register_altmode(struct device *parent, struct typec_altmode_desc *desc) | ||
382 | { | ||
383 | struct typec_altmode *alt; | ||
384 | int ret; | ||
385 | |||
386 | alt = kzalloc(sizeof(*alt), GFP_KERNEL); | ||
387 | if (!alt) | ||
388 | return NULL; | ||
389 | |||
390 | alt->svid = desc->svid; | ||
391 | alt->n_modes = desc->n_modes; | ||
392 | typec_init_modes(alt, desc->modes, is_typec_port(parent)); | ||
393 | |||
394 | alt->dev.parent = parent; | ||
395 | alt->dev.groups = alt->mode_groups; | ||
396 | alt->dev.type = &typec_altmode_dev_type; | ||
397 | dev_set_name(&alt->dev, "svid-%04x", alt->svid); | ||
398 | |||
399 | ret = device_register(&alt->dev); | ||
400 | if (ret) { | ||
401 | dev_err(parent, "failed to register alternate mode (%d)\n", | ||
402 | ret); | ||
403 | put_device(&alt->dev); | ||
404 | return NULL; | ||
405 | } | ||
406 | |||
407 | return alt; | ||
408 | } | ||
409 | |||
410 | /** | ||
411 | * typec_unregister_altmode - Unregister Alternate Mode | ||
412 | * @alt: The alternate mode to be unregistered | ||
413 | * | ||
414 | * Unregister device created with typec_partner_register_altmode(), | ||
415 | * typec_plug_register_altmode() or typec_port_register_altmode(). | ||
416 | */ | ||
417 | void typec_unregister_altmode(struct typec_altmode *alt) | ||
418 | { | ||
419 | if (alt) | ||
420 | device_unregister(&alt->dev); | ||
421 | } | ||
422 | EXPORT_SYMBOL_GPL(typec_unregister_altmode); | ||
423 | |||
424 | /* ------------------------------------------------------------------------- */ | ||
425 | /* Type-C Partners */ | ||
426 | |||
427 | static ssize_t accessory_mode_show(struct device *dev, | ||
428 | struct device_attribute *attr, | ||
429 | char *buf) | ||
430 | { | ||
431 | struct typec_partner *p = to_typec_partner(dev); | ||
432 | |||
433 | return sprintf(buf, "%s\n", typec_accessory_modes[p->accessory]); | ||
434 | } | ||
435 | static DEVICE_ATTR_RO(accessory_mode); | ||
436 | |||
437 | static ssize_t supports_usb_power_delivery_show(struct device *dev, | ||
438 | struct device_attribute *attr, | ||
439 | char *buf) | ||
440 | { | ||
441 | struct typec_partner *p = to_typec_partner(dev); | ||
442 | |||
443 | return sprintf(buf, "%s\n", p->usb_pd ? "yes" : "no"); | ||
444 | } | ||
445 | static DEVICE_ATTR_RO(supports_usb_power_delivery); | ||
446 | |||
447 | static struct attribute *typec_partner_attrs[] = { | ||
448 | &dev_attr_accessory_mode.attr, | ||
449 | &dev_attr_supports_usb_power_delivery.attr, | ||
450 | NULL | ||
451 | }; | ||
452 | ATTRIBUTE_GROUPS(typec_partner); | ||
453 | |||
454 | static void typec_partner_release(struct device *dev) | ||
455 | { | ||
456 | struct typec_partner *partner = to_typec_partner(dev); | ||
457 | |||
458 | kfree(partner); | ||
459 | } | ||
460 | |||
461 | static const struct device_type typec_partner_dev_type = { | ||
462 | .name = "typec_partner", | ||
463 | .groups = typec_partner_groups, | ||
464 | .release = typec_partner_release, | ||
465 | }; | ||
466 | |||
467 | /** | ||
468 | * typec_partner_set_identity - Report result from Discover Identity command | ||
469 | * @partner: The partner updated identity values | ||
470 | * | ||
471 | * This routine is used to report that the result of Discover Identity USB power | ||
472 | * delivery command has become available. | ||
473 | */ | ||
474 | int typec_partner_set_identity(struct typec_partner *partner) | ||
475 | { | ||
476 | if (!partner->identity) | ||
477 | return -EINVAL; | ||
478 | |||
479 | typec_report_identity(&partner->dev); | ||
480 | return 0; | ||
481 | } | ||
482 | EXPORT_SYMBOL_GPL(typec_partner_set_identity); | ||
483 | |||
484 | /** | ||
485 | * typec_partner_register_altmode - Register USB Type-C Partner Alternate Mode | ||
486 | * @partner: USB Type-C Partner that supports the alternate mode | ||
487 | * @desc: Description of the alternate mode | ||
488 | * | ||
489 | * This routine is used to register each alternate mode individually that | ||
490 | * @partner has listed in response to Discover SVIDs command. The modes for a | ||
491 | * SVID listed in response to Discover Modes command need to be listed in an | ||
492 | * array in @desc. | ||
493 | * | ||
494 | * Returns handle to the alternate mode on success or NULL on failure. | ||
495 | */ | ||
496 | struct typec_altmode * | ||
497 | typec_partner_register_altmode(struct typec_partner *partner, | ||
498 | struct typec_altmode_desc *desc) | ||
499 | { | ||
500 | return typec_register_altmode(&partner->dev, desc); | ||
501 | } | ||
502 | EXPORT_SYMBOL_GPL(typec_partner_register_altmode); | ||
503 | |||
504 | /** | ||
505 | * typec_register_partner - Register a USB Type-C Partner | ||
506 | * @port: The USB Type-C Port the partner is connected to | ||
507 | * @desc: Description of the partner | ||
508 | * | ||
509 | * Registers a device for USB Type-C Partner described in @desc. | ||
510 | * | ||
511 | * Returns handle to the partner on success or NULL on failure. | ||
512 | */ | ||
513 | struct typec_partner *typec_register_partner(struct typec_port *port, | ||
514 | struct typec_partner_desc *desc) | ||
515 | { | ||
516 | struct typec_partner *partner; | ||
517 | int ret; | ||
518 | |||
519 | partner = kzalloc(sizeof(*partner), GFP_KERNEL); | ||
520 | if (!partner) | ||
521 | return NULL; | ||
522 | |||
523 | partner->usb_pd = desc->usb_pd; | ||
524 | partner->accessory = desc->accessory; | ||
525 | |||
526 | if (desc->identity) { | ||
527 | /* | ||
528 | * Creating directory for the identity only if the driver is | ||
529 | * able to provide data to it. | ||
530 | */ | ||
531 | partner->dev.groups = usb_pd_id_groups; | ||
532 | partner->identity = desc->identity; | ||
533 | } | ||
534 | |||
535 | partner->dev.class = typec_class; | ||
536 | partner->dev.parent = &port->dev; | ||
537 | partner->dev.type = &typec_partner_dev_type; | ||
538 | dev_set_name(&partner->dev, "%s-partner", dev_name(&port->dev)); | ||
539 | |||
540 | ret = device_register(&partner->dev); | ||
541 | if (ret) { | ||
542 | dev_err(&port->dev, "failed to register partner (%d)\n", ret); | ||
543 | put_device(&partner->dev); | ||
544 | return NULL; | ||
545 | } | ||
546 | |||
547 | return partner; | ||
548 | } | ||
549 | EXPORT_SYMBOL_GPL(typec_register_partner); | ||
550 | |||
551 | /** | ||
552 | * typec_unregister_partner - Unregister a USB Type-C Partner | ||
553 | * @partner: The partner to be unregistered | ||
554 | * | ||
555 | * Unregister device created with typec_register_partner(). | ||
556 | */ | ||
557 | void typec_unregister_partner(struct typec_partner *partner) | ||
558 | { | ||
559 | if (partner) | ||
560 | device_unregister(&partner->dev); | ||
561 | } | ||
562 | EXPORT_SYMBOL_GPL(typec_unregister_partner); | ||
563 | |||
564 | /* ------------------------------------------------------------------------- */ | ||
565 | /* Type-C Cable Plugs */ | ||
566 | |||
567 | static void typec_plug_release(struct device *dev) | ||
568 | { | ||
569 | struct typec_plug *plug = to_typec_plug(dev); | ||
570 | |||
571 | kfree(plug); | ||
572 | } | ||
573 | |||
574 | static const struct device_type typec_plug_dev_type = { | ||
575 | .name = "typec_plug", | ||
576 | .release = typec_plug_release, | ||
577 | }; | ||
578 | |||
579 | /** | ||
580 | * typec_plug_register_altmode - Register USB Type-C Cable Plug Alternate Mode | ||
581 | * @plug: USB Type-C Cable Plug that supports the alternate mode | ||
582 | * @desc: Description of the alternate mode | ||
583 | * | ||
584 | * This routine is used to register each alternate mode individually that @plug | ||
585 | * has listed in response to Discover SVIDs command. The modes for a SVID that | ||
586 | * the plug lists in response to Discover Modes command need to be listed in an | ||
587 | * array in @desc. | ||
588 | * | ||
589 | * Returns handle to the alternate mode on success or NULL on failure. | ||
590 | */ | ||
591 | struct typec_altmode * | ||
592 | typec_plug_register_altmode(struct typec_plug *plug, | ||
593 | struct typec_altmode_desc *desc) | ||
594 | { | ||
595 | return typec_register_altmode(&plug->dev, desc); | ||
596 | } | ||
597 | EXPORT_SYMBOL_GPL(typec_plug_register_altmode); | ||
598 | |||
599 | /** | ||
600 | * typec_register_plug - Register a USB Type-C Cable Plug | ||
601 | * @cable: USB Type-C Cable with the plug | ||
602 | * @desc: Description of the cable plug | ||
603 | * | ||
604 | * Registers a device for USB Type-C Cable Plug described in @desc. A USB Type-C | ||
605 | * Cable Plug represents a plug with electronics in it that can response to USB | ||
606 | * Power Delivery SOP Prime or SOP Double Prime packages. | ||
607 | * | ||
608 | * Returns handle to the cable plug on success or NULL on failure. | ||
609 | */ | ||
610 | struct typec_plug *typec_register_plug(struct typec_cable *cable, | ||
611 | struct typec_plug_desc *desc) | ||
612 | { | ||
613 | struct typec_plug *plug; | ||
614 | char name[8]; | ||
615 | int ret; | ||
616 | |||
617 | plug = kzalloc(sizeof(*plug), GFP_KERNEL); | ||
618 | if (!plug) | ||
619 | return NULL; | ||
620 | |||
621 | sprintf(name, "plug%d", desc->index); | ||
622 | |||
623 | plug->index = desc->index; | ||
624 | plug->dev.class = typec_class; | ||
625 | plug->dev.parent = &cable->dev; | ||
626 | plug->dev.type = &typec_plug_dev_type; | ||
627 | dev_set_name(&plug->dev, "%s-%s", dev_name(cable->dev.parent), name); | ||
628 | |||
629 | ret = device_register(&plug->dev); | ||
630 | if (ret) { | ||
631 | dev_err(&cable->dev, "failed to register plug (%d)\n", ret); | ||
632 | put_device(&plug->dev); | ||
633 | return NULL; | ||
634 | } | ||
635 | |||
636 | return plug; | ||
637 | } | ||
638 | EXPORT_SYMBOL_GPL(typec_register_plug); | ||
639 | |||
640 | /** | ||
641 | * typec_unregister_plug - Unregister a USB Type-C Cable Plug | ||
642 | * @plug: The cable plug to be unregistered | ||
643 | * | ||
644 | * Unregister device created with typec_register_plug(). | ||
645 | */ | ||
646 | void typec_unregister_plug(struct typec_plug *plug) | ||
647 | { | ||
648 | if (plug) | ||
649 | device_unregister(&plug->dev); | ||
650 | } | ||
651 | EXPORT_SYMBOL_GPL(typec_unregister_plug); | ||
652 | |||
653 | /* Type-C Cables */ | ||
654 | |||
655 | static ssize_t | ||
656 | type_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
657 | { | ||
658 | struct typec_cable *cable = to_typec_cable(dev); | ||
659 | |||
660 | return sprintf(buf, "%s\n", cable->active ? "active" : "passive"); | ||
661 | } | ||
662 | static DEVICE_ATTR_RO(type); | ||
663 | |||
664 | static const char * const typec_plug_types[] = { | ||
665 | [USB_PLUG_NONE] = "unknown", | ||
666 | [USB_PLUG_TYPE_A] = "type-a", | ||
667 | [USB_PLUG_TYPE_B] = "type-b", | ||
668 | [USB_PLUG_TYPE_C] = "type-c", | ||
669 | [USB_PLUG_CAPTIVE] = "captive", | ||
670 | }; | ||
671 | |||
672 | static ssize_t plug_type_show(struct device *dev, | ||
673 | struct device_attribute *attr, char *buf) | ||
674 | { | ||
675 | struct typec_cable *cable = to_typec_cable(dev); | ||
676 | |||
677 | return sprintf(buf, "%s\n", typec_plug_types[cable->type]); | ||
678 | } | ||
679 | static DEVICE_ATTR_RO(plug_type); | ||
680 | |||
681 | static struct attribute *typec_cable_attrs[] = { | ||
682 | &dev_attr_type.attr, | ||
683 | &dev_attr_plug_type.attr, | ||
684 | NULL | ||
685 | }; | ||
686 | ATTRIBUTE_GROUPS(typec_cable); | ||
687 | |||
688 | static void typec_cable_release(struct device *dev) | ||
689 | { | ||
690 | struct typec_cable *cable = to_typec_cable(dev); | ||
691 | |||
692 | kfree(cable); | ||
693 | } | ||
694 | |||
695 | static const struct device_type typec_cable_dev_type = { | ||
696 | .name = "typec_cable", | ||
697 | .groups = typec_cable_groups, | ||
698 | .release = typec_cable_release, | ||
699 | }; | ||
700 | |||
701 | /** | ||
702 | * typec_cable_set_identity - Report result from Discover Identity command | ||
703 | * @cable: The cable updated identity values | ||
704 | * | ||
705 | * This routine is used to report that the result of Discover Identity USB power | ||
706 | * delivery command has become available. | ||
707 | */ | ||
708 | int typec_cable_set_identity(struct typec_cable *cable) | ||
709 | { | ||
710 | if (!cable->identity) | ||
711 | return -EINVAL; | ||
712 | |||
713 | typec_report_identity(&cable->dev); | ||
714 | return 0; | ||
715 | } | ||
716 | EXPORT_SYMBOL_GPL(typec_cable_set_identity); | ||
717 | |||
718 | /** | ||
719 | * typec_register_cable - Register a USB Type-C Cable | ||
720 | * @port: The USB Type-C Port the cable is connected to | ||
721 | * @desc: Description of the cable | ||
722 | * | ||
723 | * Registers a device for USB Type-C Cable described in @desc. The cable will be | ||
724 | * parent for the optional cable plug devises. | ||
725 | * | ||
726 | * Returns handle to the cable on success or NULL on failure. | ||
727 | */ | ||
728 | struct typec_cable *typec_register_cable(struct typec_port *port, | ||
729 | struct typec_cable_desc *desc) | ||
730 | { | ||
731 | struct typec_cable *cable; | ||
732 | int ret; | ||
733 | |||
734 | cable = kzalloc(sizeof(*cable), GFP_KERNEL); | ||
735 | if (!cable) | ||
736 | return NULL; | ||
737 | |||
738 | cable->type = desc->type; | ||
739 | cable->active = desc->active; | ||
740 | |||
741 | if (desc->identity) { | ||
742 | /* | ||
743 | * Creating directory for the identity only if the driver is | ||
744 | * able to provide data to it. | ||
745 | */ | ||
746 | cable->dev.groups = usb_pd_id_groups; | ||
747 | cable->identity = desc->identity; | ||
748 | } | ||
749 | |||
750 | cable->dev.class = typec_class; | ||
751 | cable->dev.parent = &port->dev; | ||
752 | cable->dev.type = &typec_cable_dev_type; | ||
753 | dev_set_name(&cable->dev, "%s-cable", dev_name(&port->dev)); | ||
754 | |||
755 | ret = device_register(&cable->dev); | ||
756 | if (ret) { | ||
757 | dev_err(&port->dev, "failed to register cable (%d)\n", ret); | ||
758 | put_device(&cable->dev); | ||
759 | return NULL; | ||
760 | } | ||
761 | |||
762 | return cable; | ||
763 | } | ||
764 | EXPORT_SYMBOL_GPL(typec_register_cable); | ||
765 | |||
766 | /** | ||
767 | * typec_unregister_cable - Unregister a USB Type-C Cable | ||
768 | * @cable: The cable to be unregistered | ||
769 | * | ||
770 | * Unregister device created with typec_register_cable(). | ||
771 | */ | ||
772 | void typec_unregister_cable(struct typec_cable *cable) | ||
773 | { | ||
774 | if (cable) | ||
775 | device_unregister(&cable->dev); | ||
776 | } | ||
777 | EXPORT_SYMBOL_GPL(typec_unregister_cable); | ||
778 | |||
779 | /* ------------------------------------------------------------------------- */ | ||
780 | /* USB Type-C ports */ | ||
781 | |||
782 | static const char * const typec_roles[] = { | ||
783 | [TYPEC_SINK] = "sink", | ||
784 | [TYPEC_SOURCE] = "source", | ||
785 | }; | ||
786 | |||
787 | static const char * const typec_data_roles[] = { | ||
788 | [TYPEC_DEVICE] = "device", | ||
789 | [TYPEC_HOST] = "host", | ||
790 | }; | ||
791 | |||
792 | static ssize_t | ||
793 | preferred_role_store(struct device *dev, struct device_attribute *attr, | ||
794 | const char *buf, size_t size) | ||
795 | { | ||
796 | struct typec_port *port = to_typec_port(dev); | ||
797 | int role; | ||
798 | int ret; | ||
799 | |||
800 | if (port->cap->type != TYPEC_PORT_DRP) { | ||
801 | dev_dbg(dev, "Preferred role only supported with DRP ports\n"); | ||
802 | return -EOPNOTSUPP; | ||
803 | } | ||
804 | |||
805 | if (!port->cap->try_role) { | ||
806 | dev_dbg(dev, "Setting preferred role not supported\n"); | ||
807 | return -EOPNOTSUPP; | ||
808 | } | ||
809 | |||
810 | role = sysfs_match_string(typec_roles, buf); | ||
811 | if (role < 0) { | ||
812 | if (sysfs_streq(buf, "none")) | ||
813 | role = TYPEC_NO_PREFERRED_ROLE; | ||
814 | else | ||
815 | return -EINVAL; | ||
816 | } | ||
817 | |||
818 | ret = port->cap->try_role(port->cap, role); | ||
819 | if (ret) | ||
820 | return ret; | ||
821 | |||
822 | port->prefer_role = role; | ||
823 | return size; | ||
824 | } | ||
825 | |||
826 | static ssize_t | ||
827 | preferred_role_show(struct device *dev, struct device_attribute *attr, | ||
828 | char *buf) | ||
829 | { | ||
830 | struct typec_port *port = to_typec_port(dev); | ||
831 | |||
832 | if (port->cap->type != TYPEC_PORT_DRP) | ||
833 | return 0; | ||
834 | |||
835 | if (port->prefer_role < 0) | ||
836 | return 0; | ||
837 | |||
838 | return sprintf(buf, "%s\n", typec_roles[port->prefer_role]); | ||
839 | } | ||
840 | static DEVICE_ATTR_RW(preferred_role); | ||
841 | |||
842 | static ssize_t data_role_store(struct device *dev, | ||
843 | struct device_attribute *attr, | ||
844 | const char *buf, size_t size) | ||
845 | { | ||
846 | struct typec_port *port = to_typec_port(dev); | ||
847 | int ret; | ||
848 | |||
849 | if (port->cap->type != TYPEC_PORT_DRP) { | ||
850 | dev_dbg(dev, "data role swap only supported with DRP ports\n"); | ||
851 | return -EOPNOTSUPP; | ||
852 | } | ||
853 | |||
854 | if (!port->cap->dr_set) { | ||
855 | dev_dbg(dev, "data role swapping not supported\n"); | ||
856 | return -EOPNOTSUPP; | ||
857 | } | ||
858 | |||
859 | ret = sysfs_match_string(typec_data_roles, buf); | ||
860 | if (ret < 0) | ||
861 | return ret; | ||
862 | |||
863 | ret = port->cap->dr_set(port->cap, ret); | ||
864 | if (ret) | ||
865 | return ret; | ||
866 | |||
867 | return size; | ||
868 | } | ||
869 | |||
870 | static ssize_t data_role_show(struct device *dev, | ||
871 | struct device_attribute *attr, char *buf) | ||
872 | { | ||
873 | struct typec_port *port = to_typec_port(dev); | ||
874 | |||
875 | if (port->cap->type == TYPEC_PORT_DRP) | ||
876 | return sprintf(buf, "%s\n", port->data_role == TYPEC_HOST ? | ||
877 | "[host] device" : "host [device]"); | ||
878 | |||
879 | return sprintf(buf, "[%s]\n", typec_data_roles[port->data_role]); | ||
880 | } | ||
881 | static DEVICE_ATTR_RW(data_role); | ||
882 | |||
883 | static ssize_t power_role_store(struct device *dev, | ||
884 | struct device_attribute *attr, | ||
885 | const char *buf, size_t size) | ||
886 | { | ||
887 | struct typec_port *port = to_typec_port(dev); | ||
888 | int ret = size; | ||
889 | |||
890 | if (!port->cap->pd_revision) { | ||
891 | dev_dbg(dev, "USB Power Delivery not supported\n"); | ||
892 | return -EOPNOTSUPP; | ||
893 | } | ||
894 | |||
895 | if (!port->cap->pr_set) { | ||
896 | dev_dbg(dev, "power role swapping not supported\n"); | ||
897 | return -EOPNOTSUPP; | ||
898 | } | ||
899 | |||
900 | if (port->pwr_opmode != TYPEC_PWR_MODE_PD) { | ||
901 | dev_dbg(dev, "partner unable to swap power role\n"); | ||
902 | return -EIO; | ||
903 | } | ||
904 | |||
905 | ret = sysfs_match_string(typec_roles, buf); | ||
906 | if (ret < 0) | ||
907 | return ret; | ||
908 | |||
909 | ret = port->cap->pr_set(port->cap, ret); | ||
910 | if (ret) | ||
911 | return ret; | ||
912 | |||
913 | return size; | ||
914 | } | ||
915 | |||
916 | static ssize_t power_role_show(struct device *dev, | ||
917 | struct device_attribute *attr, char *buf) | ||
918 | { | ||
919 | struct typec_port *port = to_typec_port(dev); | ||
920 | |||
921 | if (port->cap->type == TYPEC_PORT_DRP) | ||
922 | return sprintf(buf, "%s\n", port->pwr_role == TYPEC_SOURCE ? | ||
923 | "[source] sink" : "source [sink]"); | ||
924 | |||
925 | return sprintf(buf, "[%s]\n", typec_roles[port->pwr_role]); | ||
926 | } | ||
927 | static DEVICE_ATTR_RW(power_role); | ||
928 | |||
929 | static const char * const typec_pwr_opmodes[] = { | ||
930 | [TYPEC_PWR_MODE_USB] = "default", | ||
931 | [TYPEC_PWR_MODE_1_5A] = "1.5A", | ||
932 | [TYPEC_PWR_MODE_3_0A] = "3.0A", | ||
933 | [TYPEC_PWR_MODE_PD] = "usb_power_delivery", | ||
934 | }; | ||
935 | |||
936 | static ssize_t power_operation_mode_show(struct device *dev, | ||
937 | struct device_attribute *attr, | ||
938 | char *buf) | ||
939 | { | ||
940 | struct typec_port *port = to_typec_port(dev); | ||
941 | |||
942 | return sprintf(buf, "%s\n", typec_pwr_opmodes[port->pwr_opmode]); | ||
943 | } | ||
944 | static DEVICE_ATTR_RO(power_operation_mode); | ||
945 | |||
946 | static ssize_t vconn_source_store(struct device *dev, | ||
947 | struct device_attribute *attr, | ||
948 | const char *buf, size_t size) | ||
949 | { | ||
950 | struct typec_port *port = to_typec_port(dev); | ||
951 | bool source; | ||
952 | int ret; | ||
953 | |||
954 | if (!port->cap->pd_revision) { | ||
955 | dev_dbg(dev, "VCONN swap depends on USB Power Delivery\n"); | ||
956 | return -EOPNOTSUPP; | ||
957 | } | ||
958 | |||
959 | if (!port->cap->vconn_set) { | ||
960 | dev_dbg(dev, "VCONN swapping not supported\n"); | ||
961 | return -EOPNOTSUPP; | ||
962 | } | ||
963 | |||
964 | ret = kstrtobool(buf, &source); | ||
965 | if (ret) | ||
966 | return ret; | ||
967 | |||
968 | ret = port->cap->vconn_set(port->cap, (enum typec_role)source); | ||
969 | if (ret) | ||
970 | return ret; | ||
971 | |||
972 | return size; | ||
973 | } | ||
974 | |||
975 | static ssize_t vconn_source_show(struct device *dev, | ||
976 | struct device_attribute *attr, char *buf) | ||
977 | { | ||
978 | struct typec_port *port = to_typec_port(dev); | ||
979 | |||
980 | return sprintf(buf, "%s\n", | ||
981 | port->vconn_role == TYPEC_SOURCE ? "yes" : "no"); | ||
982 | } | ||
983 | static DEVICE_ATTR_RW(vconn_source); | ||
984 | |||
985 | static ssize_t supported_accessory_modes_show(struct device *dev, | ||
986 | struct device_attribute *attr, | ||
987 | char *buf) | ||
988 | { | ||
989 | struct typec_port *port = to_typec_port(dev); | ||
990 | ssize_t ret = 0; | ||
991 | int i; | ||
992 | |||
993 | for (i = 0; i < ARRAY_SIZE(port->cap->accessory); i++) { | ||
994 | if (port->cap->accessory[i]) | ||
995 | ret += sprintf(buf + ret, "%s ", | ||
996 | typec_accessory_modes[port->cap->accessory[i]]); | ||
997 | } | ||
998 | |||
999 | if (!ret) | ||
1000 | return sprintf(buf, "none\n"); | ||
1001 | |||
1002 | buf[ret - 1] = '\n'; | ||
1003 | |||
1004 | return ret; | ||
1005 | } | ||
1006 | static DEVICE_ATTR_RO(supported_accessory_modes); | ||
1007 | |||
1008 | static ssize_t usb_typec_revision_show(struct device *dev, | ||
1009 | struct device_attribute *attr, | ||
1010 | char *buf) | ||
1011 | { | ||
1012 | struct typec_port *port = to_typec_port(dev); | ||
1013 | u16 rev = port->cap->revision; | ||
1014 | |||
1015 | return sprintf(buf, "%d.%d\n", (rev >> 8) & 0xff, (rev >> 4) & 0xf); | ||
1016 | } | ||
1017 | static DEVICE_ATTR_RO(usb_typec_revision); | ||
1018 | |||
1019 | static ssize_t usb_power_delivery_revision_show(struct device *dev, | ||
1020 | struct device_attribute *attr, | ||
1021 | char *buf) | ||
1022 | { | ||
1023 | struct typec_port *p = to_typec_port(dev); | ||
1024 | |||
1025 | return sprintf(buf, "%d\n", (p->cap->pd_revision >> 8) & 0xff); | ||
1026 | } | ||
1027 | static DEVICE_ATTR_RO(usb_power_delivery_revision); | ||
1028 | |||
1029 | static struct attribute *typec_attrs[] = { | ||
1030 | &dev_attr_data_role.attr, | ||
1031 | &dev_attr_power_operation_mode.attr, | ||
1032 | &dev_attr_power_role.attr, | ||
1033 | &dev_attr_preferred_role.attr, | ||
1034 | &dev_attr_supported_accessory_modes.attr, | ||
1035 | &dev_attr_usb_power_delivery_revision.attr, | ||
1036 | &dev_attr_usb_typec_revision.attr, | ||
1037 | &dev_attr_vconn_source.attr, | ||
1038 | NULL, | ||
1039 | }; | ||
1040 | ATTRIBUTE_GROUPS(typec); | ||
1041 | |||
1042 | static int typec_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
1043 | { | ||
1044 | int ret; | ||
1045 | |||
1046 | ret = add_uevent_var(env, "TYPEC_PORT=%s", dev_name(dev)); | ||
1047 | if (ret) | ||
1048 | dev_err(dev, "failed to add uevent TYPEC_PORT\n"); | ||
1049 | |||
1050 | return ret; | ||
1051 | } | ||
1052 | |||
1053 | static void typec_release(struct device *dev) | ||
1054 | { | ||
1055 | struct typec_port *port = to_typec_port(dev); | ||
1056 | |||
1057 | ida_simple_remove(&typec_index_ida, port->id); | ||
1058 | kfree(port); | ||
1059 | } | ||
1060 | |||
1061 | static const struct device_type typec_port_dev_type = { | ||
1062 | .name = "typec_port", | ||
1063 | .groups = typec_groups, | ||
1064 | .uevent = typec_uevent, | ||
1065 | .release = typec_release, | ||
1066 | }; | ||
1067 | |||
1068 | /* --------------------------------------- */ | ||
1069 | /* Driver callbacks to report role updates */ | ||
1070 | |||
1071 | /** | ||
1072 | * typec_set_data_role - Report data role change | ||
1073 | * @port: The USB Type-C Port where the role was changed | ||
1074 | * @role: The new data role | ||
1075 | * | ||
1076 | * This routine is used by the port drivers to report data role changes. | ||
1077 | */ | ||
1078 | void typec_set_data_role(struct typec_port *port, enum typec_data_role role) | ||
1079 | { | ||
1080 | if (port->data_role == role) | ||
1081 | return; | ||
1082 | |||
1083 | port->data_role = role; | ||
1084 | sysfs_notify(&port->dev.kobj, NULL, "data_role"); | ||
1085 | kobject_uevent(&port->dev.kobj, KOBJ_CHANGE); | ||
1086 | } | ||
1087 | EXPORT_SYMBOL_GPL(typec_set_data_role); | ||
1088 | |||
1089 | /** | ||
1090 | * typec_set_pwr_role - Report power role change | ||
1091 | * @port: The USB Type-C Port where the role was changed | ||
1092 | * @role: The new data role | ||
1093 | * | ||
1094 | * This routine is used by the port drivers to report power role changes. | ||
1095 | */ | ||
1096 | void typec_set_pwr_role(struct typec_port *port, enum typec_role role) | ||
1097 | { | ||
1098 | if (port->pwr_role == role) | ||
1099 | return; | ||
1100 | |||
1101 | port->pwr_role = role; | ||
1102 | sysfs_notify(&port->dev.kobj, NULL, "power_role"); | ||
1103 | kobject_uevent(&port->dev.kobj, KOBJ_CHANGE); | ||
1104 | } | ||
1105 | EXPORT_SYMBOL_GPL(typec_set_pwr_role); | ||
1106 | |||
1107 | /** | ||
1108 | * typec_set_pwr_role - Report VCONN source change | ||
1109 | * @port: The USB Type-C Port which VCONN role changed | ||
1110 | * @role: Source when @port is sourcing VCONN, or Sink when it's not | ||
1111 | * | ||
1112 | * This routine is used by the port drivers to report if the VCONN source is | ||
1113 | * changes. | ||
1114 | */ | ||
1115 | void typec_set_vconn_role(struct typec_port *port, enum typec_role role) | ||
1116 | { | ||
1117 | if (port->vconn_role == role) | ||
1118 | return; | ||
1119 | |||
1120 | port->vconn_role = role; | ||
1121 | sysfs_notify(&port->dev.kobj, NULL, "vconn_source"); | ||
1122 | kobject_uevent(&port->dev.kobj, KOBJ_CHANGE); | ||
1123 | } | ||
1124 | EXPORT_SYMBOL_GPL(typec_set_vconn_role); | ||
1125 | |||
1126 | /** | ||
1127 | * typec_set_pwr_opmode - Report changed power operation mode | ||
1128 | * @port: The USB Type-C Port where the mode was changed | ||
1129 | * @opmode: New power operation mode | ||
1130 | * | ||
1131 | * This routine is used by the port drivers to report changed power operation | ||
1132 | * mode in @port. The modes are USB (default), 1.5A, 3.0A as defined in USB | ||
1133 | * Type-C specification, and "USB Power Delivery" when the power levels are | ||
1134 | * negotiated with methods defined in USB Power Delivery specification. | ||
1135 | */ | ||
1136 | void typec_set_pwr_opmode(struct typec_port *port, | ||
1137 | enum typec_pwr_opmode opmode) | ||
1138 | { | ||
1139 | if (port->pwr_opmode == opmode) | ||
1140 | return; | ||
1141 | |||
1142 | port->pwr_opmode = opmode; | ||
1143 | sysfs_notify(&port->dev.kobj, NULL, "power_operation_mode"); | ||
1144 | kobject_uevent(&port->dev.kobj, KOBJ_CHANGE); | ||
1145 | } | ||
1146 | EXPORT_SYMBOL_GPL(typec_set_pwr_opmode); | ||
1147 | |||
1148 | /* --------------------------------------- */ | ||
1149 | |||
1150 | /** | ||
1151 | * typec_port_register_altmode - Register USB Type-C Port Alternate Mode | ||
1152 | * @port: USB Type-C Port that supports the alternate mode | ||
1153 | * @desc: Description of the alternate mode | ||
1154 | * | ||
1155 | * This routine is used to register an alternate mode that @port is capable of | ||
1156 | * supporting. | ||
1157 | * | ||
1158 | * Returns handle to the alternate mode on success or NULL on failure. | ||
1159 | */ | ||
1160 | struct typec_altmode * | ||
1161 | typec_port_register_altmode(struct typec_port *port, | ||
1162 | struct typec_altmode_desc *desc) | ||
1163 | { | ||
1164 | return typec_register_altmode(&port->dev, desc); | ||
1165 | } | ||
1166 | EXPORT_SYMBOL_GPL(typec_port_register_altmode); | ||
1167 | |||
1168 | /** | ||
1169 | * typec_register_port - Register a USB Type-C Port | ||
1170 | * @parent: Parent device | ||
1171 | * @cap: Description of the port | ||
1172 | * | ||
1173 | * Registers a device for USB Type-C Port described in @cap. | ||
1174 | * | ||
1175 | * Returns handle to the port on success or NULL on failure. | ||
1176 | */ | ||
1177 | struct typec_port *typec_register_port(struct device *parent, | ||
1178 | const struct typec_capability *cap) | ||
1179 | { | ||
1180 | struct typec_port *port; | ||
1181 | int role; | ||
1182 | int ret; | ||
1183 | int id; | ||
1184 | |||
1185 | port = kzalloc(sizeof(*port), GFP_KERNEL); | ||
1186 | if (!port) | ||
1187 | return NULL; | ||
1188 | |||
1189 | id = ida_simple_get(&typec_index_ida, 0, 0, GFP_KERNEL); | ||
1190 | if (id < 0) { | ||
1191 | kfree(port); | ||
1192 | return NULL; | ||
1193 | } | ||
1194 | |||
1195 | if (cap->type == TYPEC_PORT_DFP) | ||
1196 | role = TYPEC_SOURCE; | ||
1197 | else if (cap->type == TYPEC_PORT_UFP) | ||
1198 | role = TYPEC_SINK; | ||
1199 | else | ||
1200 | role = cap->prefer_role; | ||
1201 | |||
1202 | if (role == TYPEC_SOURCE) { | ||
1203 | port->data_role = TYPEC_HOST; | ||
1204 | port->pwr_role = TYPEC_SOURCE; | ||
1205 | port->vconn_role = TYPEC_SOURCE; | ||
1206 | } else { | ||
1207 | port->data_role = TYPEC_DEVICE; | ||
1208 | port->pwr_role = TYPEC_SINK; | ||
1209 | port->vconn_role = TYPEC_SINK; | ||
1210 | } | ||
1211 | |||
1212 | port->id = id; | ||
1213 | port->cap = cap; | ||
1214 | port->prefer_role = cap->prefer_role; | ||
1215 | |||
1216 | port->dev.class = typec_class; | ||
1217 | port->dev.parent = parent; | ||
1218 | port->dev.fwnode = cap->fwnode; | ||
1219 | port->dev.type = &typec_port_dev_type; | ||
1220 | dev_set_name(&port->dev, "port%d", id); | ||
1221 | |||
1222 | ret = device_register(&port->dev); | ||
1223 | if (ret) { | ||
1224 | dev_err(parent, "failed to register port (%d)\n", ret); | ||
1225 | put_device(&port->dev); | ||
1226 | return NULL; | ||
1227 | } | ||
1228 | |||
1229 | return port; | ||
1230 | } | ||
1231 | EXPORT_SYMBOL_GPL(typec_register_port); | ||
1232 | |||
1233 | /** | ||
1234 | * typec_unregister_port - Unregister a USB Type-C Port | ||
1235 | * @port: The port to be unregistered | ||
1236 | * | ||
1237 | * Unregister device created with typec_register_port(). | ||
1238 | */ | ||
1239 | void typec_unregister_port(struct typec_port *port) | ||
1240 | { | ||
1241 | if (port) | ||
1242 | device_unregister(&port->dev); | ||
1243 | } | ||
1244 | EXPORT_SYMBOL_GPL(typec_unregister_port); | ||
1245 | |||
1246 | static int __init typec_init(void) | ||
1247 | { | ||
1248 | typec_class = class_create(THIS_MODULE, "typec"); | ||
1249 | return PTR_ERR_OR_ZERO(typec_class); | ||
1250 | } | ||
1251 | subsys_initcall(typec_init); | ||
1252 | |||
1253 | static void __exit typec_exit(void) | ||
1254 | { | ||
1255 | class_destroy(typec_class); | ||
1256 | ida_destroy(&typec_index_ida); | ||
1257 | } | ||
1258 | module_exit(typec_exit); | ||
1259 | |||
1260 | MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>"); | ||
1261 | MODULE_LICENSE("GPL v2"); | ||
1262 | MODULE_DESCRIPTION("USB Type-C Connector Class"); | ||
diff --git a/drivers/usb/typec/typec_wcove.c b/drivers/usb/typec/typec_wcove.c new file mode 100644 index 000000000000..d5a7b21fa3f1 --- /dev/null +++ b/drivers/usb/typec/typec_wcove.c | |||
@@ -0,0 +1,377 @@ | |||
1 | /** | ||
2 | * typec_wcove.c - WhiskeyCove PMIC USB Type-C PHY driver | ||
3 | * | ||
4 | * Copyright (C) 2017 Intel Corporation | ||
5 | * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/acpi.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/usb/typec.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/mfd/intel_soc_pmic.h> | ||
18 | |||
19 | /* Register offsets */ | ||
20 | #define WCOVE_CHGRIRQ0 0x4e09 | ||
21 | #define WCOVE_PHYCTRL 0x5e07 | ||
22 | |||
23 | #define USBC_CONTROL1 0x7001 | ||
24 | #define USBC_CONTROL2 0x7002 | ||
25 | #define USBC_CONTROL3 0x7003 | ||
26 | #define USBC_CC1_CTRL 0x7004 | ||
27 | #define USBC_CC2_CTRL 0x7005 | ||
28 | #define USBC_STATUS1 0x7007 | ||
29 | #define USBC_STATUS2 0x7008 | ||
30 | #define USBC_STATUS3 0x7009 | ||
31 | #define USBC_IRQ1 0x7015 | ||
32 | #define USBC_IRQ2 0x7016 | ||
33 | #define USBC_IRQMASK1 0x7017 | ||
34 | #define USBC_IRQMASK2 0x7018 | ||
35 | |||
36 | /* Register bits */ | ||
37 | |||
38 | #define USBC_CONTROL1_MODE_DRP(r) (((r) & ~0x7) | 4) | ||
39 | |||
40 | #define USBC_CONTROL2_UNATT_SNK BIT(0) | ||
41 | #define USBC_CONTROL2_UNATT_SRC BIT(1) | ||
42 | #define USBC_CONTROL2_DIS_ST BIT(2) | ||
43 | |||
44 | #define USBC_CONTROL3_PD_DIS BIT(1) | ||
45 | |||
46 | #define USBC_CC_CTRL_VCONN_EN BIT(1) | ||
47 | |||
48 | #define USBC_STATUS1_DET_ONGOING BIT(6) | ||
49 | #define USBC_STATUS1_RSLT(r) ((r) & 0xf) | ||
50 | #define USBC_RSLT_NOTHING 0 | ||
51 | #define USBC_RSLT_SRC_DEFAULT 1 | ||
52 | #define USBC_RSLT_SRC_1_5A 2 | ||
53 | #define USBC_RSLT_SRC_3_0A 3 | ||
54 | #define USBC_RSLT_SNK 4 | ||
55 | #define USBC_RSLT_DEBUG_ACC 5 | ||
56 | #define USBC_RSLT_AUDIO_ACC 6 | ||
57 | #define USBC_RSLT_UNDEF 15 | ||
58 | #define USBC_STATUS1_ORIENT(r) (((r) >> 4) & 0x3) | ||
59 | #define USBC_ORIENT_NORMAL 1 | ||
60 | #define USBC_ORIENT_REVERSE 2 | ||
61 | |||
62 | #define USBC_STATUS2_VBUS_REQ BIT(5) | ||
63 | |||
64 | #define USBC_IRQ1_ADCDONE1 BIT(2) | ||
65 | #define USBC_IRQ1_OVERTEMP BIT(1) | ||
66 | #define USBC_IRQ1_SHORT BIT(0) | ||
67 | |||
68 | #define USBC_IRQ2_CC_CHANGE BIT(7) | ||
69 | #define USBC_IRQ2_RX_PD BIT(6) | ||
70 | #define USBC_IRQ2_RX_HR BIT(5) | ||
71 | #define USBC_IRQ2_RX_CR BIT(4) | ||
72 | #define USBC_IRQ2_TX_SUCCESS BIT(3) | ||
73 | #define USBC_IRQ2_TX_FAIL BIT(2) | ||
74 | |||
75 | #define USBC_IRQMASK1_ALL (USBC_IRQ1_ADCDONE1 | USBC_IRQ1_OVERTEMP | \ | ||
76 | USBC_IRQ1_SHORT) | ||
77 | |||
78 | #define USBC_IRQMASK2_ALL (USBC_IRQ2_CC_CHANGE | USBC_IRQ2_RX_PD | \ | ||
79 | USBC_IRQ2_RX_HR | USBC_IRQ2_RX_CR | \ | ||
80 | USBC_IRQ2_TX_SUCCESS | USBC_IRQ2_TX_FAIL) | ||
81 | |||
82 | struct wcove_typec { | ||
83 | struct mutex lock; /* device lock */ | ||
84 | struct device *dev; | ||
85 | struct regmap *regmap; | ||
86 | struct typec_port *port; | ||
87 | struct typec_capability cap; | ||
88 | struct typec_partner *partner; | ||
89 | }; | ||
90 | |||
91 | enum wcove_typec_func { | ||
92 | WCOVE_FUNC_DRIVE_VBUS = 1, | ||
93 | WCOVE_FUNC_ORIENTATION, | ||
94 | WCOVE_FUNC_ROLE, | ||
95 | WCOVE_FUNC_DRIVE_VCONN, | ||
96 | }; | ||
97 | |||
98 | enum wcove_typec_orientation { | ||
99 | WCOVE_ORIENTATION_NORMAL, | ||
100 | WCOVE_ORIENTATION_REVERSE, | ||
101 | }; | ||
102 | |||
103 | enum wcove_typec_role { | ||
104 | WCOVE_ROLE_HOST, | ||
105 | WCOVE_ROLE_DEVICE, | ||
106 | }; | ||
107 | |||
108 | static uuid_le uuid = UUID_LE(0x482383f0, 0x2876, 0x4e49, | ||
109 | 0x86, 0x85, 0xdb, 0x66, 0x21, 0x1a, 0xf0, 0x37); | ||
110 | |||
111 | static int wcove_typec_func(struct wcove_typec *wcove, | ||
112 | enum wcove_typec_func func, int param) | ||
113 | { | ||
114 | union acpi_object *obj; | ||
115 | union acpi_object tmp; | ||
116 | union acpi_object argv4 = ACPI_INIT_DSM_ARGV4(1, &tmp); | ||
117 | |||
118 | tmp.type = ACPI_TYPE_INTEGER; | ||
119 | tmp.integer.value = param; | ||
120 | |||
121 | obj = acpi_evaluate_dsm(ACPI_HANDLE(wcove->dev), uuid.b, 1, func, | ||
122 | &argv4); | ||
123 | if (!obj) { | ||
124 | dev_err(wcove->dev, "%s: failed to evaluate _DSM\n", __func__); | ||
125 | return -EIO; | ||
126 | } | ||
127 | |||
128 | ACPI_FREE(obj); | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static irqreturn_t wcove_typec_irq(int irq, void *data) | ||
133 | { | ||
134 | enum typec_role role = TYPEC_SINK; | ||
135 | struct typec_partner_desc partner; | ||
136 | struct wcove_typec *wcove = data; | ||
137 | unsigned int cc1_ctrl; | ||
138 | unsigned int cc2_ctrl; | ||
139 | unsigned int cc_irq1; | ||
140 | unsigned int cc_irq2; | ||
141 | unsigned int status1; | ||
142 | unsigned int status2; | ||
143 | int ret; | ||
144 | |||
145 | mutex_lock(&wcove->lock); | ||
146 | |||
147 | ret = regmap_read(wcove->regmap, USBC_IRQ1, &cc_irq1); | ||
148 | if (ret) | ||
149 | goto err; | ||
150 | |||
151 | ret = regmap_read(wcove->regmap, USBC_IRQ2, &cc_irq2); | ||
152 | if (ret) | ||
153 | goto err; | ||
154 | |||
155 | ret = regmap_read(wcove->regmap, USBC_STATUS1, &status1); | ||
156 | if (ret) | ||
157 | goto err; | ||
158 | |||
159 | ret = regmap_read(wcove->regmap, USBC_STATUS2, &status2); | ||
160 | if (ret) | ||
161 | goto err; | ||
162 | |||
163 | ret = regmap_read(wcove->regmap, USBC_CC1_CTRL, &cc1_ctrl); | ||
164 | if (ret) | ||
165 | goto err; | ||
166 | |||
167 | ret = regmap_read(wcove->regmap, USBC_CC2_CTRL, &cc2_ctrl); | ||
168 | if (ret) | ||
169 | goto err; | ||
170 | |||
171 | if (cc_irq1) { | ||
172 | if (cc_irq1 & USBC_IRQ1_OVERTEMP) | ||
173 | dev_err(wcove->dev, "VCONN Switch Over Temperature!\n"); | ||
174 | if (cc_irq1 & USBC_IRQ1_SHORT) | ||
175 | dev_err(wcove->dev, "VCONN Switch Short Circuit!\n"); | ||
176 | ret = regmap_write(wcove->regmap, USBC_IRQ1, cc_irq1); | ||
177 | if (ret) | ||
178 | goto err; | ||
179 | } | ||
180 | |||
181 | if (cc_irq2) { | ||
182 | ret = regmap_write(wcove->regmap, USBC_IRQ2, cc_irq2); | ||
183 | if (ret) | ||
184 | goto err; | ||
185 | /* | ||
186 | * Ignoring any PD communication interrupts until the PD support | ||
187 | * is available | ||
188 | */ | ||
189 | if (cc_irq2 & ~USBC_IRQ2_CC_CHANGE) { | ||
190 | dev_WARN(wcove->dev, "USB PD handling missing\n"); | ||
191 | goto err; | ||
192 | } | ||
193 | } | ||
194 | |||
195 | if (status1 & USBC_STATUS1_DET_ONGOING) | ||
196 | goto out; | ||
197 | |||
198 | if (USBC_STATUS1_RSLT(status1) == USBC_RSLT_NOTHING) { | ||
199 | if (wcove->partner) { | ||
200 | typec_unregister_partner(wcove->partner); | ||
201 | wcove->partner = NULL; | ||
202 | } | ||
203 | |||
204 | wcove_typec_func(wcove, WCOVE_FUNC_ORIENTATION, | ||
205 | WCOVE_ORIENTATION_NORMAL); | ||
206 | |||
207 | /* This makes sure the device controller is disconnected */ | ||
208 | wcove_typec_func(wcove, WCOVE_FUNC_ROLE, WCOVE_ROLE_HOST); | ||
209 | |||
210 | /* Port to default role */ | ||
211 | typec_set_data_role(wcove->port, TYPEC_DEVICE); | ||
212 | typec_set_pwr_role(wcove->port, TYPEC_SINK); | ||
213 | typec_set_pwr_opmode(wcove->port, TYPEC_PWR_MODE_USB); | ||
214 | |||
215 | goto out; | ||
216 | } | ||
217 | |||
218 | if (wcove->partner) | ||
219 | goto out; | ||
220 | |||
221 | switch (USBC_STATUS1_ORIENT(status1)) { | ||
222 | case USBC_ORIENT_NORMAL: | ||
223 | wcove_typec_func(wcove, WCOVE_FUNC_ORIENTATION, | ||
224 | WCOVE_ORIENTATION_NORMAL); | ||
225 | break; | ||
226 | case USBC_ORIENT_REVERSE: | ||
227 | wcove_typec_func(wcove, WCOVE_FUNC_ORIENTATION, | ||
228 | WCOVE_ORIENTATION_REVERSE); | ||
229 | default: | ||
230 | break; | ||
231 | } | ||
232 | |||
233 | memset(&partner, 0, sizeof(partner)); | ||
234 | |||
235 | switch (USBC_STATUS1_RSLT(status1)) { | ||
236 | case USBC_RSLT_SRC_DEFAULT: | ||
237 | typec_set_pwr_opmode(wcove->port, TYPEC_PWR_MODE_USB); | ||
238 | break; | ||
239 | case USBC_RSLT_SRC_1_5A: | ||
240 | typec_set_pwr_opmode(wcove->port, TYPEC_PWR_MODE_1_5A); | ||
241 | break; | ||
242 | case USBC_RSLT_SRC_3_0A: | ||
243 | typec_set_pwr_opmode(wcove->port, TYPEC_PWR_MODE_3_0A); | ||
244 | break; | ||
245 | case USBC_RSLT_SNK: | ||
246 | role = TYPEC_SOURCE; | ||
247 | break; | ||
248 | case USBC_RSLT_DEBUG_ACC: | ||
249 | partner.accessory = TYPEC_ACCESSORY_DEBUG; | ||
250 | break; | ||
251 | case USBC_RSLT_AUDIO_ACC: | ||
252 | partner.accessory = TYPEC_ACCESSORY_AUDIO; | ||
253 | break; | ||
254 | default: | ||
255 | dev_WARN(wcove->dev, "%s Undefined result\n", __func__); | ||
256 | goto err; | ||
257 | } | ||
258 | |||
259 | if (role == TYPEC_SINK) { | ||
260 | wcove_typec_func(wcove, WCOVE_FUNC_ROLE, WCOVE_ROLE_DEVICE); | ||
261 | typec_set_data_role(wcove->port, TYPEC_DEVICE); | ||
262 | typec_set_pwr_role(wcove->port, TYPEC_SINK); | ||
263 | } else { | ||
264 | wcove_typec_func(wcove, WCOVE_FUNC_ROLE, WCOVE_ROLE_HOST); | ||
265 | typec_set_pwr_role(wcove->port, TYPEC_SOURCE); | ||
266 | typec_set_data_role(wcove->port, TYPEC_HOST); | ||
267 | } | ||
268 | |||
269 | wcove->partner = typec_register_partner(wcove->port, &partner); | ||
270 | if (!wcove->partner) | ||
271 | dev_err(wcove->dev, "failed register partner\n"); | ||
272 | out: | ||
273 | /* If either CC pins is requesting VCONN, we turn it on */ | ||
274 | if ((cc1_ctrl & USBC_CC_CTRL_VCONN_EN) || | ||
275 | (cc2_ctrl & USBC_CC_CTRL_VCONN_EN)) | ||
276 | wcove_typec_func(wcove, WCOVE_FUNC_DRIVE_VCONN, true); | ||
277 | else | ||
278 | wcove_typec_func(wcove, WCOVE_FUNC_DRIVE_VCONN, false); | ||
279 | |||
280 | /* Relying on the FSM to know when we need to drive VBUS. */ | ||
281 | wcove_typec_func(wcove, WCOVE_FUNC_DRIVE_VBUS, | ||
282 | !!(status2 & USBC_STATUS2_VBUS_REQ)); | ||
283 | err: | ||
284 | /* REVISIT: Clear WhiskeyCove CHGR Type-C interrupt */ | ||
285 | regmap_write(wcove->regmap, WCOVE_CHGRIRQ0, BIT(5)); | ||
286 | |||
287 | mutex_unlock(&wcove->lock); | ||
288 | return IRQ_HANDLED; | ||
289 | } | ||
290 | |||
291 | static int wcove_typec_probe(struct platform_device *pdev) | ||
292 | { | ||
293 | struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent); | ||
294 | struct wcove_typec *wcove; | ||
295 | unsigned int val; | ||
296 | int ret; | ||
297 | |||
298 | wcove = devm_kzalloc(&pdev->dev, sizeof(*wcove), GFP_KERNEL); | ||
299 | if (!wcove) | ||
300 | return -ENOMEM; | ||
301 | |||
302 | mutex_init(&wcove->lock); | ||
303 | wcove->dev = &pdev->dev; | ||
304 | wcove->regmap = pmic->regmap; | ||
305 | |||
306 | ret = regmap_irq_get_virq(pmic->irq_chip_data_level2, | ||
307 | platform_get_irq(pdev, 0)); | ||
308 | if (ret < 0) | ||
309 | return ret; | ||
310 | |||
311 | ret = devm_request_threaded_irq(&pdev->dev, ret, NULL, | ||
312 | wcove_typec_irq, IRQF_ONESHOT, | ||
313 | "wcove_typec", wcove); | ||
314 | if (ret) | ||
315 | return ret; | ||
316 | |||
317 | if (!acpi_check_dsm(ACPI_HANDLE(&pdev->dev), uuid.b, 0, 0x1f)) { | ||
318 | dev_err(&pdev->dev, "Missing _DSM functions\n"); | ||
319 | return -ENODEV; | ||
320 | } | ||
321 | |||
322 | wcove->cap.type = TYPEC_PORT_DRP; | ||
323 | wcove->cap.revision = USB_TYPEC_REV_1_1; | ||
324 | wcove->cap.prefer_role = TYPEC_NO_PREFERRED_ROLE; | ||
325 | |||
326 | /* Make sure the PD PHY is disabled until USB PD is available */ | ||
327 | regmap_read(wcove->regmap, USBC_CONTROL3, &val); | ||
328 | regmap_write(wcove->regmap, USBC_CONTROL3, val | USBC_CONTROL3_PD_DIS); | ||
329 | |||
330 | /* DRP mode without accessory support */ | ||
331 | regmap_read(wcove->regmap, USBC_CONTROL1, &val); | ||
332 | regmap_write(wcove->regmap, USBC_CONTROL1, USBC_CONTROL1_MODE_DRP(val)); | ||
333 | |||
334 | wcove->port = typec_register_port(&pdev->dev, &wcove->cap); | ||
335 | if (!wcove->port) | ||
336 | return -ENODEV; | ||
337 | |||
338 | /* Unmask everything */ | ||
339 | regmap_read(wcove->regmap, USBC_IRQMASK1, &val); | ||
340 | regmap_write(wcove->regmap, USBC_IRQMASK1, val & ~USBC_IRQMASK1_ALL); | ||
341 | regmap_read(wcove->regmap, USBC_IRQMASK2, &val); | ||
342 | regmap_write(wcove->regmap, USBC_IRQMASK2, val & ~USBC_IRQMASK2_ALL); | ||
343 | |||
344 | platform_set_drvdata(pdev, wcove); | ||
345 | return 0; | ||
346 | } | ||
347 | |||
348 | static int wcove_typec_remove(struct platform_device *pdev) | ||
349 | { | ||
350 | struct wcove_typec *wcove = platform_get_drvdata(pdev); | ||
351 | unsigned int val; | ||
352 | |||
353 | /* Mask everything */ | ||
354 | regmap_read(wcove->regmap, USBC_IRQMASK1, &val); | ||
355 | regmap_write(wcove->regmap, USBC_IRQMASK1, val | USBC_IRQMASK1_ALL); | ||
356 | regmap_read(wcove->regmap, USBC_IRQMASK2, &val); | ||
357 | regmap_write(wcove->regmap, USBC_IRQMASK2, val | USBC_IRQMASK2_ALL); | ||
358 | |||
359 | typec_unregister_partner(wcove->partner); | ||
360 | typec_unregister_port(wcove->port); | ||
361 | return 0; | ||
362 | } | ||
363 | |||
364 | static struct platform_driver wcove_typec_driver = { | ||
365 | .driver = { | ||
366 | .name = "bxt_wcove_usbc", | ||
367 | }, | ||
368 | .probe = wcove_typec_probe, | ||
369 | .remove = wcove_typec_remove, | ||
370 | }; | ||
371 | |||
372 | module_platform_driver(wcove_typec_driver); | ||
373 | |||
374 | MODULE_AUTHOR("Intel Corporation"); | ||
375 | MODULE_LICENSE("GPL v2"); | ||
376 | MODULE_DESCRIPTION("WhiskeyCove PMIC USB Type-C PHY driver"); | ||
377 | MODULE_ALIAS("platform:bxt_wcove_usbc"); | ||
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index 5133a0792eb0..bb0bd732e29a 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c | |||
@@ -491,16 +491,14 @@ static int skel_probe(struct usb_interface *interface, | |||
491 | const struct usb_device_id *id) | 491 | const struct usb_device_id *id) |
492 | { | 492 | { |
493 | struct usb_skel *dev; | 493 | struct usb_skel *dev; |
494 | struct usb_host_interface *iface_desc; | 494 | struct usb_endpoint_descriptor *bulk_in, *bulk_out; |
495 | struct usb_endpoint_descriptor *endpoint; | 495 | int retval; |
496 | size_t buffer_size; | ||
497 | int i; | ||
498 | int retval = -ENOMEM; | ||
499 | 496 | ||
500 | /* allocate memory for our device state and initialize it */ | 497 | /* allocate memory for our device state and initialize it */ |
501 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 498 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
502 | if (!dev) | 499 | if (!dev) |
503 | goto error; | 500 | return -ENOMEM; |
501 | |||
504 | kref_init(&dev->kref); | 502 | kref_init(&dev->kref); |
505 | sema_init(&dev->limit_sem, WRITES_IN_FLIGHT); | 503 | sema_init(&dev->limit_sem, WRITES_IN_FLIGHT); |
506 | mutex_init(&dev->io_mutex); | 504 | mutex_init(&dev->io_mutex); |
@@ -513,36 +511,29 @@ static int skel_probe(struct usb_interface *interface, | |||
513 | 511 | ||
514 | /* set up the endpoint information */ | 512 | /* set up the endpoint information */ |
515 | /* use only the first bulk-in and bulk-out endpoints */ | 513 | /* use only the first bulk-in and bulk-out endpoints */ |
516 | iface_desc = interface->cur_altsetting; | 514 | retval = usb_find_common_endpoints(interface->cur_altsetting, |
517 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | 515 | &bulk_in, &bulk_out, NULL, NULL); |
518 | endpoint = &iface_desc->endpoint[i].desc; | 516 | if (retval) { |
519 | |||
520 | if (!dev->bulk_in_endpointAddr && | ||
521 | usb_endpoint_is_bulk_in(endpoint)) { | ||
522 | /* we found a bulk in endpoint */ | ||
523 | buffer_size = usb_endpoint_maxp(endpoint); | ||
524 | dev->bulk_in_size = buffer_size; | ||
525 | dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; | ||
526 | dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); | ||
527 | if (!dev->bulk_in_buffer) | ||
528 | goto error; | ||
529 | dev->bulk_in_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
530 | if (!dev->bulk_in_urb) | ||
531 | goto error; | ||
532 | } | ||
533 | |||
534 | if (!dev->bulk_out_endpointAddr && | ||
535 | usb_endpoint_is_bulk_out(endpoint)) { | ||
536 | /* we found a bulk out endpoint */ | ||
537 | dev->bulk_out_endpointAddr = endpoint->bEndpointAddress; | ||
538 | } | ||
539 | } | ||
540 | if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) { | ||
541 | dev_err(&interface->dev, | 517 | dev_err(&interface->dev, |
542 | "Could not find both bulk-in and bulk-out endpoints\n"); | 518 | "Could not find both bulk-in and bulk-out endpoints\n"); |
543 | goto error; | 519 | goto error; |
544 | } | 520 | } |
545 | 521 | ||
522 | dev->bulk_in_size = usb_endpoint_maxp(bulk_in); | ||
523 | dev->bulk_in_endpointAddr = bulk_in->bEndpointAddress; | ||
524 | dev->bulk_in_buffer = kmalloc(dev->bulk_in_size, GFP_KERNEL); | ||
525 | if (!dev->bulk_in_buffer) { | ||
526 | retval = -ENOMEM; | ||
527 | goto error; | ||
528 | } | ||
529 | dev->bulk_in_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
530 | if (!dev->bulk_in_urb) { | ||
531 | retval = -ENOMEM; | ||
532 | goto error; | ||
533 | } | ||
534 | |||
535 | dev->bulk_out_endpointAddr = bulk_out->bEndpointAddress; | ||
536 | |||
546 | /* save our data pointer in this interface device */ | 537 | /* save our data pointer in this interface device */ |
547 | usb_set_intfdata(interface, dev); | 538 | usb_set_intfdata(interface, dev); |
548 | 539 | ||
@@ -563,9 +554,9 @@ static int skel_probe(struct usb_interface *interface, | |||
563 | return 0; | 554 | return 0; |
564 | 555 | ||
565 | error: | 556 | error: |
566 | if (dev) | 557 | /* this frees allocated memory */ |
567 | /* this frees allocated memory */ | 558 | kref_put(&dev->kref, skel_delete); |
568 | kref_put(&dev->kref, skel_delete); | 559 | |
569 | return retval; | 560 | return retval; |
570 | } | 561 | } |
571 | 562 | ||
diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c index e4cb9f0625e8..5d8b2c261940 100644 --- a/drivers/usb/usbip/vhci_hcd.c +++ b/drivers/usb/usbip/vhci_hcd.c | |||
@@ -430,36 +430,8 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
430 | return retval; | 430 | return retval; |
431 | } | 431 | } |
432 | 432 | ||
433 | static struct vhci_device *get_vdev(struct usb_device *udev) | 433 | static void vhci_tx_urb(struct urb *urb, struct vhci_device *vdev) |
434 | { | 434 | { |
435 | struct platform_device *pdev; | ||
436 | struct usb_hcd *hcd; | ||
437 | struct vhci_hcd *vhci; | ||
438 | int pdev_nr, rhport; | ||
439 | |||
440 | if (!udev) | ||
441 | return NULL; | ||
442 | |||
443 | for (pdev_nr = 0; pdev_nr < vhci_num_controllers; pdev_nr++) { | ||
444 | pdev = *(vhci_pdevs + pdev_nr); | ||
445 | if (pdev == NULL) | ||
446 | continue; | ||
447 | hcd = platform_get_drvdata(pdev); | ||
448 | if (hcd == NULL) | ||
449 | continue; | ||
450 | vhci = hcd_to_vhci(hcd); | ||
451 | for (rhport = 0; rhport < VHCI_HC_PORTS; rhport++) { | ||
452 | if (vhci->vdev[rhport].udev == udev) | ||
453 | return &vhci->vdev[rhport]; | ||
454 | } | ||
455 | } | ||
456 | |||
457 | return NULL; | ||
458 | } | ||
459 | |||
460 | static void vhci_tx_urb(struct urb *urb) | ||
461 | { | ||
462 | struct vhci_device *vdev = get_vdev(urb->dev); | ||
463 | struct vhci_priv *priv; | 435 | struct vhci_priv *priv; |
464 | struct vhci_hcd *vhci; | 436 | struct vhci_hcd *vhci; |
465 | unsigned long flags; | 437 | unsigned long flags; |
@@ -601,7 +573,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, | |||
601 | } | 573 | } |
602 | 574 | ||
603 | out: | 575 | out: |
604 | vhci_tx_urb(urb); | 576 | vhci_tx_urb(urb, vdev); |
605 | spin_unlock_irqrestore(&vhci->lock, flags); | 577 | spin_unlock_irqrestore(&vhci->lock, flags); |
606 | 578 | ||
607 | return 0; | 579 | return 0; |
diff --git a/include/linux/mfd/syscon/exynos5-pmu.h b/include/linux/mfd/syscon/exynos5-pmu.h index 0622ae86f9db..b4942a32b81d 100644 --- a/include/linux/mfd/syscon/exynos5-pmu.h +++ b/include/linux/mfd/syscon/exynos5-pmu.h | |||
@@ -12,36 +12,6 @@ | |||
12 | #ifndef _LINUX_MFD_SYSCON_PMU_EXYNOS5_H_ | 12 | #ifndef _LINUX_MFD_SYSCON_PMU_EXYNOS5_H_ |
13 | #define _LINUX_MFD_SYSCON_PMU_EXYNOS5_H_ | 13 | #define _LINUX_MFD_SYSCON_PMU_EXYNOS5_H_ |
14 | 14 | ||
15 | /* Exynos5 PMU register definitions */ | ||
16 | #define EXYNOS5_HDMI_PHY_CONTROL (0x700) | ||
17 | #define EXYNOS5_USBDRD_PHY_CONTROL (0x704) | ||
18 | |||
19 | /* Exynos5250 specific register definitions */ | ||
20 | #define EXYNOS5_USBHOST_PHY_CONTROL (0x708) | ||
21 | #define EXYNOS5_EFNAND_PHY_CONTROL (0x70c) | ||
22 | #define EXYNOS5_MIPI_PHY0_CONTROL (0x710) | ||
23 | #define EXYNOS5_MIPI_PHY1_CONTROL (0x714) | ||
24 | #define EXYNOS5_ADC_PHY_CONTROL (0x718) | ||
25 | #define EXYNOS5_MTCADC_PHY_CONTROL (0x71c) | ||
26 | #define EXYNOS5_DPTX_PHY_CONTROL (0x720) | ||
27 | #define EXYNOS5_SATA_PHY_CONTROL (0x724) | ||
28 | |||
29 | /* Exynos5420 specific register definitions */ | ||
30 | #define EXYNOS5420_USBDRD1_PHY_CONTROL (0x708) | ||
31 | #define EXYNOS5420_USBHOST_PHY_CONTROL (0x70c) | ||
32 | #define EXYNOS5420_MIPI_PHY0_CONTROL (0x714) | ||
33 | #define EXYNOS5420_MIPI_PHY1_CONTROL (0x718) | ||
34 | #define EXYNOS5420_MIPI_PHY2_CONTROL (0x71c) | ||
35 | #define EXYNOS5420_ADC_PHY_CONTROL (0x720) | ||
36 | #define EXYNOS5420_MTCADC_PHY_CONTROL (0x724) | ||
37 | #define EXYNOS5420_DPTX_PHY_CONTROL (0x728) | ||
38 | |||
39 | /* Exynos5433 specific register definitions */ | ||
40 | #define EXYNOS5433_USBHOST30_PHY_CONTROL (0x728) | ||
41 | #define EXYNOS5433_MIPI_PHY0_CONTROL (0x710) | ||
42 | #define EXYNOS5433_MIPI_PHY1_CONTROL (0x714) | ||
43 | #define EXYNOS5433_MIPI_PHY2_CONTROL (0x718) | ||
44 | |||
45 | #define EXYNOS5_PHY_ENABLE BIT(0) | 15 | #define EXYNOS5_PHY_ENABLE BIT(0) |
46 | #define EXYNOS5_MIPI_PHY_S_RESETN BIT(1) | 16 | #define EXYNOS5_MIPI_PHY_S_RESETN BIT(1) |
47 | #define EXYNOS5_MIPI_PHY_M_RESETN BIT(2) | 17 | #define EXYNOS5_MIPI_PHY_M_RESETN BIT(2) |
diff --git a/include/linux/soc/samsung/exynos-regs-pmu.h b/include/linux/soc/samsung/exynos-regs-pmu.h index 49df0a01a2cc..bebdde5dccd6 100644 --- a/include/linux/soc/samsung/exynos-regs-pmu.h +++ b/include/linux/soc/samsung/exynos-regs-pmu.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd. | 2 | * Copyright (c) 2010-2015 Samsung Electronics Co., Ltd. |
3 | * http://www.samsung.com | 3 | * http://www.samsung.com |
4 | * | 4 | * |
5 | * EXYNOS - Power management unit definition | 5 | * EXYNOS - Power management unit definition |
@@ -50,6 +50,14 @@ | |||
50 | #define S5P_WAKEUP_MASK 0x0608 | 50 | #define S5P_WAKEUP_MASK 0x0608 |
51 | #define S5P_WAKEUP_MASK2 0x0614 | 51 | #define S5P_WAKEUP_MASK2 0x0614 |
52 | 52 | ||
53 | /* MIPI_PHYn_CONTROL, valid for Exynos3250, Exynos4, Exynos5250 and Exynos5433 */ | ||
54 | #define EXYNOS4_MIPI_PHY_CONTROL(n) (0x0710 + (n) * 4) | ||
55 | /* Phy enable bit, common for all phy registers, not only MIPI */ | ||
56 | #define EXYNOS4_PHY_ENABLE (1 << 0) | ||
57 | #define EXYNOS4_MIPI_PHY_SRESETN (1 << 1) | ||
58 | #define EXYNOS4_MIPI_PHY_MRESETN (1 << 2) | ||
59 | #define EXYNOS4_MIPI_PHY_RESET_MASK (3 << 1) | ||
60 | |||
53 | #define S5P_INFORM0 0x0800 | 61 | #define S5P_INFORM0 0x0800 |
54 | #define S5P_INFORM1 0x0804 | 62 | #define S5P_INFORM1 0x0804 |
55 | #define S5P_INFORM5 0x0814 | 63 | #define S5P_INFORM5 0x0814 |
@@ -342,6 +350,8 @@ | |||
342 | 350 | ||
343 | #define EXYNOS5_AUTO_WDTRESET_DISABLE 0x0408 | 351 | #define EXYNOS5_AUTO_WDTRESET_DISABLE 0x0408 |
344 | #define EXYNOS5_MASK_WDTRESET_REQUEST 0x040C | 352 | #define EXYNOS5_MASK_WDTRESET_REQUEST 0x040C |
353 | #define EXYNOS5_USBDRD_PHY_CONTROL 0x0704 | ||
354 | #define EXYNOS5_DPTX_PHY_CONTROL 0x0720 | ||
345 | 355 | ||
346 | #define EXYNOS5_USE_RETENTION BIT(4) | 356 | #define EXYNOS5_USE_RETENTION BIT(4) |
347 | #define EXYNOS5_SYS_WDTRESET (1 << 20) | 357 | #define EXYNOS5_SYS_WDTRESET (1 << 20) |
@@ -495,6 +505,9 @@ | |||
495 | #define EXYNOS5420_KFC_CORE_RESET(_nr) \ | 505 | #define EXYNOS5420_KFC_CORE_RESET(_nr) \ |
496 | ((EXYNOS5420_KFC_CORE_RESET0 | EXYNOS5420_KFC_ETM_RESET0) << (_nr)) | 506 | ((EXYNOS5420_KFC_CORE_RESET0 | EXYNOS5420_KFC_ETM_RESET0) << (_nr)) |
497 | 507 | ||
508 | #define EXYNOS5420_USBDRD1_PHY_CONTROL 0x0708 | ||
509 | #define EXYNOS5420_MIPI_PHY_CONTROL(n) (0x0714 + (n) * 4) | ||
510 | #define EXYNOS5420_DPTX_PHY_CONTROL 0x0728 | ||
498 | #define EXYNOS5420_ARM_CORE2_SYS_PWR_REG 0x1020 | 511 | #define EXYNOS5420_ARM_CORE2_SYS_PWR_REG 0x1020 |
499 | #define EXYNOS5420_DIS_IRQ_ARM_CORE2_LOCAL_SYS_PWR_REG 0x1024 | 512 | #define EXYNOS5420_DIS_IRQ_ARM_CORE2_LOCAL_SYS_PWR_REG 0x1024 |
500 | #define EXYNOS5420_DIS_IRQ_ARM_CORE2_CENTRAL_SYS_PWR_REG 0x1028 | 513 | #define EXYNOS5420_DIS_IRQ_ARM_CORE2_CENTRAL_SYS_PWR_REG 0x1028 |
@@ -632,6 +645,7 @@ | |||
632 | | EXYNOS5420_KFC_USE_STANDBY_WFI3) | 645 | | EXYNOS5420_KFC_USE_STANDBY_WFI3) |
633 | 646 | ||
634 | /* For EXYNOS5433 */ | 647 | /* For EXYNOS5433 */ |
648 | #define EXYNOS5433_USBHOST30_PHY_CONTROL (0x0728) | ||
635 | #define EXYNOS5433_PAD_RETENTION_AUD_OPTION (0x3028) | 649 | #define EXYNOS5433_PAD_RETENTION_AUD_OPTION (0x3028) |
636 | #define EXYNOS5433_PAD_RETENTION_MMC2_OPTION (0x30C8) | 650 | #define EXYNOS5433_PAD_RETENTION_MMC2_OPTION (0x30C8) |
637 | #define EXYNOS5433_PAD_RETENTION_TOP_OPTION (0x3108) | 651 | #define EXYNOS5433_PAD_RETENTION_TOP_OPTION (0x3108) |
diff --git a/include/linux/string.h b/include/linux/string.h index 26b6f6a66f83..c4011b28f3d8 100644 --- a/include/linux/string.h +++ b/include/linux/string.h | |||
@@ -135,6 +135,16 @@ static inline int strtobool(const char *s, bool *res) | |||
135 | } | 135 | } |
136 | 136 | ||
137 | int match_string(const char * const *array, size_t n, const char *string); | 137 | int match_string(const char * const *array, size_t n, const char *string); |
138 | int __sysfs_match_string(const char * const *array, size_t n, const char *s); | ||
139 | |||
140 | /** | ||
141 | * sysfs_match_string - matches given string in an array | ||
142 | * @_a: array of strings | ||
143 | * @_s: string to match with | ||
144 | * | ||
145 | * Helper for __sysfs_match_string(). Calculates the size of @a automatically. | ||
146 | */ | ||
147 | #define sysfs_match_string(_a, _s) __sysfs_match_string(_a, ARRAY_SIZE(_a), _s) | ||
138 | 148 | ||
139 | #ifdef CONFIG_BINARY_PRINTF | 149 | #ifdef CONFIG_BINARY_PRINTF |
140 | int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args); | 150 | int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args); |
diff --git a/include/linux/usb.h b/include/linux/usb.h index 7e68259360de..cb9fbd54386e 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h | |||
@@ -99,6 +99,76 @@ enum usb_interface_condition { | |||
99 | USB_INTERFACE_UNBINDING, | 99 | USB_INTERFACE_UNBINDING, |
100 | }; | 100 | }; |
101 | 101 | ||
102 | int __must_check | ||
103 | usb_find_common_endpoints(struct usb_host_interface *alt, | ||
104 | struct usb_endpoint_descriptor **bulk_in, | ||
105 | struct usb_endpoint_descriptor **bulk_out, | ||
106 | struct usb_endpoint_descriptor **int_in, | ||
107 | struct usb_endpoint_descriptor **int_out); | ||
108 | |||
109 | int __must_check | ||
110 | usb_find_common_endpoints_reverse(struct usb_host_interface *alt, | ||
111 | struct usb_endpoint_descriptor **bulk_in, | ||
112 | struct usb_endpoint_descriptor **bulk_out, | ||
113 | struct usb_endpoint_descriptor **int_in, | ||
114 | struct usb_endpoint_descriptor **int_out); | ||
115 | |||
116 | static inline int __must_check | ||
117 | usb_find_bulk_in_endpoint(struct usb_host_interface *alt, | ||
118 | struct usb_endpoint_descriptor **bulk_in) | ||
119 | { | ||
120 | return usb_find_common_endpoints(alt, bulk_in, NULL, NULL, NULL); | ||
121 | } | ||
122 | |||
123 | static inline int __must_check | ||
124 | usb_find_bulk_out_endpoint(struct usb_host_interface *alt, | ||
125 | struct usb_endpoint_descriptor **bulk_out) | ||
126 | { | ||
127 | return usb_find_common_endpoints(alt, NULL, bulk_out, NULL, NULL); | ||
128 | } | ||
129 | |||
130 | static inline int __must_check | ||
131 | usb_find_int_in_endpoint(struct usb_host_interface *alt, | ||
132 | struct usb_endpoint_descriptor **int_in) | ||
133 | { | ||
134 | return usb_find_common_endpoints(alt, NULL, NULL, int_in, NULL); | ||
135 | } | ||
136 | |||
137 | static inline int __must_check | ||
138 | usb_find_int_out_endpoint(struct usb_host_interface *alt, | ||
139 | struct usb_endpoint_descriptor **int_out) | ||
140 | { | ||
141 | return usb_find_common_endpoints(alt, NULL, NULL, NULL, int_out); | ||
142 | } | ||
143 | |||
144 | static inline int __must_check | ||
145 | usb_find_last_bulk_in_endpoint(struct usb_host_interface *alt, | ||
146 | struct usb_endpoint_descriptor **bulk_in) | ||
147 | { | ||
148 | return usb_find_common_endpoints_reverse(alt, bulk_in, NULL, NULL, NULL); | ||
149 | } | ||
150 | |||
151 | static inline int __must_check | ||
152 | usb_find_last_bulk_out_endpoint(struct usb_host_interface *alt, | ||
153 | struct usb_endpoint_descriptor **bulk_out) | ||
154 | { | ||
155 | return usb_find_common_endpoints_reverse(alt, NULL, bulk_out, NULL, NULL); | ||
156 | } | ||
157 | |||
158 | static inline int __must_check | ||
159 | usb_find_last_int_in_endpoint(struct usb_host_interface *alt, | ||
160 | struct usb_endpoint_descriptor **int_in) | ||
161 | { | ||
162 | return usb_find_common_endpoints_reverse(alt, NULL, NULL, int_in, NULL); | ||
163 | } | ||
164 | |||
165 | static inline int __must_check | ||
166 | usb_find_last_int_out_endpoint(struct usb_host_interface *alt, | ||
167 | struct usb_endpoint_descriptor **int_out) | ||
168 | { | ||
169 | return usb_find_common_endpoints_reverse(alt, NULL, NULL, NULL, int_out); | ||
170 | } | ||
171 | |||
102 | /** | 172 | /** |
103 | * struct usb_interface - what usb device drivers talk to | 173 | * struct usb_interface - what usb device drivers talk to |
104 | * @altsetting: array of interface structures, one for each alternate | 174 | * @altsetting: array of interface structures, one for each alternate |
@@ -248,7 +318,7 @@ void usb_put_intf(struct usb_interface *intf); | |||
248 | * struct usb_interface (which persists only as long as its configuration | 318 | * struct usb_interface (which persists only as long as its configuration |
249 | * is installed). The altsetting arrays can be accessed through these | 319 | * is installed). The altsetting arrays can be accessed through these |
250 | * structures at any time, permitting comparison of configurations and | 320 | * structures at any time, permitting comparison of configurations and |
251 | * providing support for the /proc/bus/usb/devices pseudo-file. | 321 | * providing support for the /sys/kernel/debug/usb/devices pseudo-file. |
252 | */ | 322 | */ |
253 | struct usb_interface_cache { | 323 | struct usb_interface_cache { |
254 | unsigned num_altsetting; /* number of alternate settings */ | 324 | unsigned num_altsetting; /* number of alternate settings */ |
@@ -354,6 +424,7 @@ struct usb_devmap { | |||
354 | */ | 424 | */ |
355 | struct usb_bus { | 425 | struct usb_bus { |
356 | struct device *controller; /* host/master side hardware */ | 426 | struct device *controller; /* host/master side hardware */ |
427 | struct device *sysdev; /* as seen from firmware or bus */ | ||
357 | int busnum; /* Bus number (in order of reg) */ | 428 | int busnum; /* Bus number (in order of reg) */ |
358 | const char *bus_name; /* stable id (PCI slot_name etc) */ | 429 | const char *bus_name; /* stable id (PCI slot_name etc) */ |
359 | u8 uses_dma; /* Does the host controller use DMA? */ | 430 | u8 uses_dma; /* Does the host controller use DMA? */ |
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index 40edf6a8533e..a469999a106d 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h | |||
@@ -437,6 +437,9 @@ extern int usb_hcd_alloc_bandwidth(struct usb_device *udev, | |||
437 | struct usb_host_interface *new_alt); | 437 | struct usb_host_interface *new_alt); |
438 | extern int usb_hcd_get_frame_number(struct usb_device *udev); | 438 | extern int usb_hcd_get_frame_number(struct usb_device *udev); |
439 | 439 | ||
440 | struct usb_hcd *__usb_create_hcd(const struct hc_driver *driver, | ||
441 | struct device *sysdev, struct device *dev, const char *bus_name, | ||
442 | struct usb_hcd *primary_hcd); | ||
440 | extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver, | 443 | extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver, |
441 | struct device *dev, const char *bus_name); | 444 | struct device *dev, const char *bus_name); |
442 | extern struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver, | 445 | extern struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver, |
@@ -453,7 +456,7 @@ extern int usb_hcd_find_raw_port_number(struct usb_hcd *hcd, int port1); | |||
453 | struct platform_device; | 456 | struct platform_device; |
454 | extern void usb_hcd_platform_shutdown(struct platform_device *dev); | 457 | extern void usb_hcd_platform_shutdown(struct platform_device *dev); |
455 | 458 | ||
456 | #ifdef CONFIG_PCI | 459 | #ifdef CONFIG_USB_PCI |
457 | struct pci_dev; | 460 | struct pci_dev; |
458 | struct pci_device_id; | 461 | struct pci_device_id; |
459 | extern int usb_hcd_pci_probe(struct pci_dev *dev, | 462 | extern int usb_hcd_pci_probe(struct pci_dev *dev, |
@@ -466,7 +469,7 @@ extern int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *dev); | |||
466 | #ifdef CONFIG_PM | 469 | #ifdef CONFIG_PM |
467 | extern const struct dev_pm_ops usb_hcd_pci_pm_ops; | 470 | extern const struct dev_pm_ops usb_hcd_pci_pm_ops; |
468 | #endif | 471 | #endif |
469 | #endif /* CONFIG_PCI */ | 472 | #endif /* CONFIG_USB_PCI */ |
470 | 473 | ||
471 | /* pci-ish (pdev null is ok) buffer alloc/mapping support */ | 474 | /* pci-ish (pdev null is ok) buffer alloc/mapping support */ |
472 | void usb_init_pool_max(void); | 475 | void usb_init_pool_max(void); |
diff --git a/include/linux/usb/of.h b/include/linux/usb/of.h index 5ff9032ee1b4..4031f47629ec 100644 --- a/include/linux/usb/of.h +++ b/include/linux/usb/of.h | |||
@@ -18,6 +18,7 @@ int of_usb_update_otg_caps(struct device_node *np, | |||
18 | struct usb_otg_caps *otg_caps); | 18 | struct usb_otg_caps *otg_caps); |
19 | struct device_node *usb_of_get_child_node(struct device_node *parent, | 19 | struct device_node *usb_of_get_child_node(struct device_node *parent, |
20 | int portnum); | 20 | int portnum); |
21 | struct device *usb_of_get_companion_dev(struct device *dev); | ||
21 | #else | 22 | #else |
22 | static inline enum usb_dr_mode | 23 | static inline enum usb_dr_mode |
23 | of_usb_get_dr_mode_by_phy(struct device_node *np, int arg0) | 24 | of_usb_get_dr_mode_by_phy(struct device_node *np, int arg0) |
@@ -38,6 +39,10 @@ static inline struct device_node *usb_of_get_child_node | |||
38 | { | 39 | { |
39 | return NULL; | 40 | return NULL; |
40 | } | 41 | } |
42 | static inline struct device *usb_of_get_companion_dev(struct device *dev) | ||
43 | { | ||
44 | return NULL; | ||
45 | } | ||
41 | #endif | 46 | #endif |
42 | 47 | ||
43 | #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_USB_SUPPORT) | 48 | #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_USB_SUPPORT) |
diff --git a/include/linux/usb/otg-fsm.h b/include/linux/usb/otg-fsm.h index 7a0350535cb1..a0a8f878503c 100644 --- a/include/linux/usb/otg-fsm.h +++ b/include/linux/usb/otg-fsm.h | |||
@@ -21,21 +21,6 @@ | |||
21 | #include <linux/mutex.h> | 21 | #include <linux/mutex.h> |
22 | #include <linux/errno.h> | 22 | #include <linux/errno.h> |
23 | 23 | ||
24 | #undef VERBOSE | ||
25 | |||
26 | #ifdef VERBOSE | ||
27 | #define VDBG(fmt, args...) pr_debug("[%s] " fmt , \ | ||
28 | __func__, ## args) | ||
29 | #else | ||
30 | #define VDBG(stuff...) do {} while (0) | ||
31 | #endif | ||
32 | |||
33 | #ifdef VERBOSE | ||
34 | #define MPC_LOC printk("Current Location [%s]:[%d]\n", __FILE__, __LINE__) | ||
35 | #else | ||
36 | #define MPC_LOC do {} while (0) | ||
37 | #endif | ||
38 | |||
39 | #define PROTO_UNDEF (0) | 24 | #define PROTO_UNDEF (0) |
40 | #define PROTO_HOST (1) | 25 | #define PROTO_HOST (1) |
41 | #define PROTO_GADGET (2) | 26 | #define PROTO_GADGET (2) |
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 704a1ab8240c..e2f0ab07eea5 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <linux/kfifo.h> | 20 | #include <linux/kfifo.h> |
21 | 21 | ||
22 | /* The maximum number of ports one device can grab at once */ | 22 | /* The maximum number of ports one device can grab at once */ |
23 | #define MAX_NUM_PORTS 8 | 23 | #define MAX_NUM_PORTS 16 |
24 | 24 | ||
25 | /* parity check flag */ | 25 | /* parity check flag */ |
26 | #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) | 26 | #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) |
@@ -159,10 +159,10 @@ struct usb_serial { | |||
159 | unsigned char minors_reserved:1; | 159 | unsigned char minors_reserved:1; |
160 | unsigned char num_ports; | 160 | unsigned char num_ports; |
161 | unsigned char num_port_pointers; | 161 | unsigned char num_port_pointers; |
162 | char num_interrupt_in; | 162 | unsigned char num_interrupt_in; |
163 | char num_interrupt_out; | 163 | unsigned char num_interrupt_out; |
164 | char num_bulk_in; | 164 | unsigned char num_bulk_in; |
165 | char num_bulk_out; | 165 | unsigned char num_bulk_out; |
166 | struct usb_serial_port *port[MAX_NUM_PORTS]; | 166 | struct usb_serial_port *port[MAX_NUM_PORTS]; |
167 | struct kref kref; | 167 | struct kref kref; |
168 | struct mutex disc_mutex; | 168 | struct mutex disc_mutex; |
@@ -181,6 +181,17 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data) | |||
181 | serial->private = data; | 181 | serial->private = data; |
182 | } | 182 | } |
183 | 183 | ||
184 | struct usb_serial_endpoints { | ||
185 | unsigned char num_bulk_in; | ||
186 | unsigned char num_bulk_out; | ||
187 | unsigned char num_interrupt_in; | ||
188 | unsigned char num_interrupt_out; | ||
189 | struct usb_endpoint_descriptor *bulk_in[MAX_NUM_PORTS]; | ||
190 | struct usb_endpoint_descriptor *bulk_out[MAX_NUM_PORTS]; | ||
191 | struct usb_endpoint_descriptor *interrupt_in[MAX_NUM_PORTS]; | ||
192 | struct usb_endpoint_descriptor *interrupt_out[MAX_NUM_PORTS]; | ||
193 | }; | ||
194 | |||
184 | /** | 195 | /** |
185 | * usb_serial_driver - describes a usb serial driver | 196 | * usb_serial_driver - describes a usb serial driver |
186 | * @description: pointer to a string that describes this driver. This string | 197 | * @description: pointer to a string that describes this driver. This string |
@@ -188,12 +199,17 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data) | |||
188 | * @id_table: pointer to a list of usb_device_id structures that define all | 199 | * @id_table: pointer to a list of usb_device_id structures that define all |
189 | * of the devices this structure can support. | 200 | * of the devices this structure can support. |
190 | * @num_ports: the number of different ports this device will have. | 201 | * @num_ports: the number of different ports this device will have. |
202 | * @num_bulk_in: minimum number of bulk-in endpoints | ||
203 | * @num_bulk_out: minimum number of bulk-out endpoints | ||
204 | * @num_interrupt_in: minimum number of interrupt-in endpoints | ||
205 | * @num_interrupt_out: minimum number of interrupt-out endpoints | ||
191 | * @bulk_in_size: minimum number of bytes to allocate for bulk-in buffer | 206 | * @bulk_in_size: minimum number of bytes to allocate for bulk-in buffer |
192 | * (0 = end-point size) | 207 | * (0 = end-point size) |
193 | * @bulk_out_size: bytes to allocate for bulk-out buffer (0 = end-point size) | 208 | * @bulk_out_size: bytes to allocate for bulk-out buffer (0 = end-point size) |
194 | * @calc_num_ports: pointer to a function to determine how many ports this | 209 | * @calc_num_ports: pointer to a function to determine how many ports this |
195 | * device has dynamically. It will be called after the probe() | 210 | * device has dynamically. It can also be used to verify the number of |
196 | * callback is called, but before attach() | 211 | * endpoints or to modify the port-endpoint mapping. It will be called |
212 | * after the probe() callback is called, but before attach(). | ||
197 | * @probe: pointer to the driver's probe function. | 213 | * @probe: pointer to the driver's probe function. |
198 | * This will be called when the device is inserted into the system, | 214 | * This will be called when the device is inserted into the system, |
199 | * but before the device has been fully initialized by the usb_serial | 215 | * but before the device has been fully initialized by the usb_serial |
@@ -227,19 +243,26 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data) | |||
227 | struct usb_serial_driver { | 243 | struct usb_serial_driver { |
228 | const char *description; | 244 | const char *description; |
229 | const struct usb_device_id *id_table; | 245 | const struct usb_device_id *id_table; |
230 | char num_ports; | ||
231 | 246 | ||
232 | struct list_head driver_list; | 247 | struct list_head driver_list; |
233 | struct device_driver driver; | 248 | struct device_driver driver; |
234 | struct usb_driver *usb_driver; | 249 | struct usb_driver *usb_driver; |
235 | struct usb_dynids dynids; | 250 | struct usb_dynids dynids; |
236 | 251 | ||
252 | unsigned char num_ports; | ||
253 | |||
254 | unsigned char num_bulk_in; | ||
255 | unsigned char num_bulk_out; | ||
256 | unsigned char num_interrupt_in; | ||
257 | unsigned char num_interrupt_out; | ||
258 | |||
237 | size_t bulk_in_size; | 259 | size_t bulk_in_size; |
238 | size_t bulk_out_size; | 260 | size_t bulk_out_size; |
239 | 261 | ||
240 | int (*probe)(struct usb_serial *serial, const struct usb_device_id *id); | 262 | int (*probe)(struct usb_serial *serial, const struct usb_device_id *id); |
241 | int (*attach)(struct usb_serial *serial); | 263 | int (*attach)(struct usb_serial *serial); |
242 | int (*calc_num_ports) (struct usb_serial *serial); | 264 | int (*calc_num_ports)(struct usb_serial *serial, |
265 | struct usb_serial_endpoints *epds); | ||
243 | 266 | ||
244 | void (*disconnect)(struct usb_serial *serial); | 267 | void (*disconnect)(struct usb_serial *serial); |
245 | void (*release)(struct usb_serial *serial); | 268 | void (*release)(struct usb_serial *serial); |
@@ -356,7 +379,6 @@ extern void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port, | |||
356 | extern int usb_serial_bus_register(struct usb_serial_driver *device); | 379 | extern int usb_serial_bus_register(struct usb_serial_driver *device); |
357 | extern void usb_serial_bus_deregister(struct usb_serial_driver *device); | 380 | extern void usb_serial_bus_deregister(struct usb_serial_driver *device); |
358 | 381 | ||
359 | extern struct usb_serial_driver usb_serial_generic_device; | ||
360 | extern struct bus_type usb_serial_bus_type; | 382 | extern struct bus_type usb_serial_bus_type; |
361 | extern struct tty_driver *usb_serial_tty_driver; | 383 | extern struct tty_driver *usb_serial_tty_driver; |
362 | 384 | ||
diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h new file mode 100644 index 000000000000..ec78204964ab --- /dev/null +++ b/include/linux/usb/typec.h | |||
@@ -0,0 +1,243 @@ | |||
1 | |||
2 | #ifndef __LINUX_USB_TYPEC_H | ||
3 | #define __LINUX_USB_TYPEC_H | ||
4 | |||
5 | #include <linux/types.h> | ||
6 | |||
7 | /* XXX: Once we have a header for USB Power Delivery, this belongs there */ | ||
8 | #define ALTMODE_MAX_MODES 6 | ||
9 | |||
10 | /* USB Type-C Specification releases */ | ||
11 | #define USB_TYPEC_REV_1_0 0x100 /* 1.0 */ | ||
12 | #define USB_TYPEC_REV_1_1 0x110 /* 1.1 */ | ||
13 | #define USB_TYPEC_REV_1_2 0x120 /* 1.2 */ | ||
14 | |||
15 | struct typec_altmode; | ||
16 | struct typec_partner; | ||
17 | struct typec_cable; | ||
18 | struct typec_plug; | ||
19 | struct typec_port; | ||
20 | |||
21 | struct fwnode_handle; | ||
22 | |||
23 | enum typec_port_type { | ||
24 | TYPEC_PORT_DFP, | ||
25 | TYPEC_PORT_UFP, | ||
26 | TYPEC_PORT_DRP, | ||
27 | }; | ||
28 | |||
29 | enum typec_plug_type { | ||
30 | USB_PLUG_NONE, | ||
31 | USB_PLUG_TYPE_A, | ||
32 | USB_PLUG_TYPE_B, | ||
33 | USB_PLUG_TYPE_C, | ||
34 | USB_PLUG_CAPTIVE, | ||
35 | }; | ||
36 | |||
37 | enum typec_data_role { | ||
38 | TYPEC_DEVICE, | ||
39 | TYPEC_HOST, | ||
40 | }; | ||
41 | |||
42 | enum typec_role { | ||
43 | TYPEC_SINK, | ||
44 | TYPEC_SOURCE, | ||
45 | }; | ||
46 | |||
47 | enum typec_pwr_opmode { | ||
48 | TYPEC_PWR_MODE_USB, | ||
49 | TYPEC_PWR_MODE_1_5A, | ||
50 | TYPEC_PWR_MODE_3_0A, | ||
51 | TYPEC_PWR_MODE_PD, | ||
52 | }; | ||
53 | |||
54 | enum typec_accessory { | ||
55 | TYPEC_ACCESSORY_NONE, | ||
56 | TYPEC_ACCESSORY_AUDIO, | ||
57 | TYPEC_ACCESSORY_DEBUG, | ||
58 | }; | ||
59 | |||
60 | #define TYPEC_MAX_ACCESSORY 3 | ||
61 | |||
62 | /* | ||
63 | * struct usb_pd_identity - USB Power Delivery identity data | ||
64 | * @id_header: ID Header VDO | ||
65 | * @cert_stat: Cert Stat VDO | ||
66 | * @product: Product VDO | ||
67 | * | ||
68 | * USB power delivery Discover Identity command response data. | ||
69 | * | ||
70 | * REVISIT: This is USB Power Delivery specific information, so this structure | ||
71 | * probable belongs to USB Power Delivery header file once we have them. | ||
72 | */ | ||
73 | struct usb_pd_identity { | ||
74 | u32 id_header; | ||
75 | u32 cert_stat; | ||
76 | u32 product; | ||
77 | }; | ||
78 | |||
79 | int typec_partner_set_identity(struct typec_partner *partner); | ||
80 | int typec_cable_set_identity(struct typec_cable *cable); | ||
81 | |||
82 | /* | ||
83 | * struct typec_mode_desc - Individual Mode of an Alternate Mode | ||
84 | * @index: Index of the Mode within the SVID | ||
85 | * @vdo: VDO returned by Discover Modes USB PD command | ||
86 | * @desc: Optional human readable description of the mode | ||
87 | * @roles: Only for ports. DRP if the mode is available in both roles | ||
88 | * | ||
89 | * Description of a mode of an Alternate Mode which a connector, cable plug or | ||
90 | * partner supports. Every mode will have it's own sysfs group. The details are | ||
91 | * the VDO returned by discover modes command, description for the mode and | ||
92 | * active flag telling has the mode being entered or not. | ||
93 | */ | ||
94 | struct typec_mode_desc { | ||
95 | int index; | ||
96 | u32 vdo; | ||
97 | char *desc; | ||
98 | /* Only used with ports */ | ||
99 | enum typec_port_type roles; | ||
100 | }; | ||
101 | |||
102 | /* | ||
103 | * struct typec_altmode_desc - USB Type-C Alternate Mode Descriptor | ||
104 | * @svid: Standard or Vendor ID | ||
105 | * @n_modes: Number of modes | ||
106 | * @modes: Array of modes supported by the Alternate Mode | ||
107 | * | ||
108 | * Representation of an Alternate Mode that has SVID assigned by USB-IF. The | ||
109 | * array of modes will list the modes of a particular SVID that are supported by | ||
110 | * a connector, partner of a cable plug. | ||
111 | */ | ||
112 | struct typec_altmode_desc { | ||
113 | u16 svid; | ||
114 | int n_modes; | ||
115 | struct typec_mode_desc modes[ALTMODE_MAX_MODES]; | ||
116 | }; | ||
117 | |||
118 | struct typec_altmode | ||
119 | *typec_partner_register_altmode(struct typec_partner *partner, | ||
120 | struct typec_altmode_desc *desc); | ||
121 | struct typec_altmode | ||
122 | *typec_plug_register_altmode(struct typec_plug *plug, | ||
123 | struct typec_altmode_desc *desc); | ||
124 | struct typec_altmode | ||
125 | *typec_port_register_altmode(struct typec_port *port, | ||
126 | struct typec_altmode_desc *desc); | ||
127 | void typec_unregister_altmode(struct typec_altmode *altmode); | ||
128 | |||
129 | struct typec_port *typec_altmode2port(struct typec_altmode *alt); | ||
130 | |||
131 | void typec_altmode_update_active(struct typec_altmode *alt, int mode, | ||
132 | bool active); | ||
133 | |||
134 | enum typec_plug_index { | ||
135 | TYPEC_PLUG_SOP_P, | ||
136 | TYPEC_PLUG_SOP_PP, | ||
137 | }; | ||
138 | |||
139 | /* | ||
140 | * struct typec_plug_desc - USB Type-C Cable Plug Descriptor | ||
141 | * @index: SOP Prime for the plug connected to DFP and SOP Double Prime for the | ||
142 | * plug connected to UFP | ||
143 | * | ||
144 | * Represents USB Type-C Cable Plug. | ||
145 | */ | ||
146 | struct typec_plug_desc { | ||
147 | enum typec_plug_index index; | ||
148 | }; | ||
149 | |||
150 | /* | ||
151 | * struct typec_cable_desc - USB Type-C Cable Descriptor | ||
152 | * @type: The plug type from USB PD Cable VDO | ||
153 | * @active: Is the cable active or passive | ||
154 | * @identity: Result of Discover Identity command | ||
155 | * | ||
156 | * Represents USB Type-C Cable attached to USB Type-C port. | ||
157 | */ | ||
158 | struct typec_cable_desc { | ||
159 | enum typec_plug_type type; | ||
160 | unsigned int active:1; | ||
161 | struct usb_pd_identity *identity; | ||
162 | }; | ||
163 | |||
164 | /* | ||
165 | * struct typec_partner_desc - USB Type-C Partner Descriptor | ||
166 | * @usb_pd: USB Power Delivery support | ||
167 | * @accessory: Audio, Debug or none. | ||
168 | * @identity: Discover Identity command data | ||
169 | * | ||
170 | * Details about a partner that is attached to USB Type-C port. If @identity | ||
171 | * member exists when partner is registered, a directory named "identity" is | ||
172 | * created to sysfs for the partner device. | ||
173 | */ | ||
174 | struct typec_partner_desc { | ||
175 | unsigned int usb_pd:1; | ||
176 | enum typec_accessory accessory; | ||
177 | struct usb_pd_identity *identity; | ||
178 | }; | ||
179 | |||
180 | /* | ||
181 | * struct typec_capability - USB Type-C Port Capabilities | ||
182 | * @role: DFP (Host-only), UFP (Device-only) or DRP (Dual Role) | ||
183 | * @revision: USB Type-C Specification release. Binary coded decimal | ||
184 | * @pd_revision: USB Power Delivery Specification revision if supported | ||
185 | * @prefer_role: Initial role preference | ||
186 | * @accessory: Supported Accessory Modes | ||
187 | * @fwnode: Optional fwnode of the port | ||
188 | * @try_role: Set data role preference for DRP port | ||
189 | * @dr_set: Set Data Role | ||
190 | * @pr_set: Set Power Role | ||
191 | * @vconn_set: Set VCONN Role | ||
192 | * @activate_mode: Enter/exit given Alternate Mode | ||
193 | * | ||
194 | * Static capabilities of a single USB Type-C port. | ||
195 | */ | ||
196 | struct typec_capability { | ||
197 | enum typec_port_type type; | ||
198 | u16 revision; /* 0120H = "1.2" */ | ||
199 | u16 pd_revision; /* 0300H = "3.0" */ | ||
200 | int prefer_role; | ||
201 | enum typec_accessory accessory[TYPEC_MAX_ACCESSORY]; | ||
202 | |||
203 | struct fwnode_handle *fwnode; | ||
204 | |||
205 | int (*try_role)(const struct typec_capability *, | ||
206 | int role); | ||
207 | |||
208 | int (*dr_set)(const struct typec_capability *, | ||
209 | enum typec_data_role); | ||
210 | int (*pr_set)(const struct typec_capability *, | ||
211 | enum typec_role); | ||
212 | int (*vconn_set)(const struct typec_capability *, | ||
213 | enum typec_role); | ||
214 | |||
215 | int (*activate_mode)(const struct typec_capability *, | ||
216 | int mode, int activate); | ||
217 | }; | ||
218 | |||
219 | /* Specific to try_role(). Indicates the user want's to clear the preference. */ | ||
220 | #define TYPEC_NO_PREFERRED_ROLE (-1) | ||
221 | |||
222 | struct typec_port *typec_register_port(struct device *parent, | ||
223 | const struct typec_capability *cap); | ||
224 | void typec_unregister_port(struct typec_port *port); | ||
225 | |||
226 | struct typec_partner *typec_register_partner(struct typec_port *port, | ||
227 | struct typec_partner_desc *desc); | ||
228 | void typec_unregister_partner(struct typec_partner *partner); | ||
229 | |||
230 | struct typec_cable *typec_register_cable(struct typec_port *port, | ||
231 | struct typec_cable_desc *desc); | ||
232 | void typec_unregister_cable(struct typec_cable *cable); | ||
233 | |||
234 | struct typec_plug *typec_register_plug(struct typec_cable *cable, | ||
235 | struct typec_plug_desc *desc); | ||
236 | void typec_unregister_plug(struct typec_plug *plug); | ||
237 | |||
238 | void typec_set_data_role(struct typec_port *port, enum typec_data_role role); | ||
239 | void typec_set_pwr_role(struct typec_port *port, enum typec_role role); | ||
240 | void typec_set_vconn_role(struct typec_port *port, enum typec_role role); | ||
241 | void typec_set_pwr_opmode(struct typec_port *port, enum typec_pwr_opmode mode); | ||
242 | |||
243 | #endif /* __LINUX_USB_TYPEC_H */ | ||
diff --git a/include/uapi/linux/capability.h b/include/uapi/linux/capability.h index 49bc06295398..6fe14d001f68 100644 --- a/include/uapi/linux/capability.h +++ b/include/uapi/linux/capability.h | |||
@@ -205,7 +205,7 @@ struct vfs_cap_data { | |||
205 | #define CAP_SYS_MODULE 16 | 205 | #define CAP_SYS_MODULE 16 |
206 | 206 | ||
207 | /* Allow ioperm/iopl access */ | 207 | /* Allow ioperm/iopl access */ |
208 | /* Allow sending USB messages to any device via /proc/bus/usb */ | 208 | /* Allow sending USB messages to any device via /dev/bus/usb */ |
209 | 209 | ||
210 | #define CAP_SYS_RAWIO 17 | 210 | #define CAP_SYS_RAWIO 17 |
211 | 211 | ||
diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h index 2c5d7c4a69e3..ce1169af39d7 100644 --- a/include/uapi/linux/usb/ch9.h +++ b/include/uapi/linux/usb/ch9.h | |||
@@ -224,7 +224,8 @@ struct usb_ctrlrequest { | |||
224 | * through the Linux-USB APIs, they are not converted to cpu byte | 224 | * through the Linux-USB APIs, they are not converted to cpu byte |
225 | * order; it is the responsibility of the client code to do this. | 225 | * order; it is the responsibility of the client code to do this. |
226 | * The single exception is when device and configuration descriptors (but | 226 | * The single exception is when device and configuration descriptors (but |
227 | * not other descriptors) are read from usbfs (i.e. /proc/bus/usb/BBB/DDD); | 227 | * not other descriptors) are read from character devices |
228 | * (i.e. /dev/bus/usb/BBB/DDD); | ||
228 | * in this case the fields are converted to host endianness by the kernel. | 229 | * in this case the fields are converted to host endianness by the kernel. |
229 | */ | 230 | */ |
230 | 231 | ||
diff --git a/include/uapi/linux/usb/functionfs.h b/include/uapi/linux/usb/functionfs.h index b2a31a55a612..062606f02309 100644 --- a/include/uapi/linux/usb/functionfs.h +++ b/include/uapi/linux/usb/functionfs.h | |||
@@ -158,7 +158,7 @@ struct usb_ext_prop_desc { | |||
158 | * |-----+-----------------------+------+-------------------------------------| | 158 | * |-----+-----------------------+------+-------------------------------------| |
159 | * | 0 | bFirstInterfaceNumber | U8 | index of the interface or of the 1st| | 159 | * | 0 | bFirstInterfaceNumber | U8 | index of the interface or of the 1st| |
160 | * | | | | interface in an IAD group | | 160 | * | | | | interface in an IAD group | |
161 | * | 1 | Reserved | U8 | 0 | | 161 | * | 1 | Reserved | U8 | 1 | |
162 | * | 2 | CompatibleID | U8[8]| compatible ID string | | 162 | * | 2 | CompatibleID | U8[8]| compatible ID string | |
163 | * | 10 | SubCompatibleID | U8[8]| subcompatible ID string | | 163 | * | 10 | SubCompatibleID | U8[8]| subcompatible ID string | |
164 | * | 18 | Reserved | U8[6]| 0 | | 164 | * | 18 | Reserved | U8[6]| 0 | |
diff --git a/lib/string.c b/lib/string.c index b5c9a1168d3a..1c1fc9187b05 100644 --- a/lib/string.c +++ b/lib/string.c | |||
@@ -656,6 +656,32 @@ int match_string(const char * const *array, size_t n, const char *string) | |||
656 | } | 656 | } |
657 | EXPORT_SYMBOL(match_string); | 657 | EXPORT_SYMBOL(match_string); |
658 | 658 | ||
659 | /** | ||
660 | * __sysfs_match_string - matches given string in an array | ||
661 | * @array: array of strings | ||
662 | * @n: number of strings in the array or -1 for NULL terminated arrays | ||
663 | * @str: string to match with | ||
664 | * | ||
665 | * Returns index of @str in the @array or -EINVAL, just like match_string(). | ||
666 | * Uses sysfs_streq instead of strcmp for matching. | ||
667 | */ | ||
668 | int __sysfs_match_string(const char * const *array, size_t n, const char *str) | ||
669 | { | ||
670 | const char *item; | ||
671 | int index; | ||
672 | |||
673 | for (index = 0; index < n; index++) { | ||
674 | item = array[index]; | ||
675 | if (!item) | ||
676 | break; | ||
677 | if (sysfs_streq(item, str)) | ||
678 | return index; | ||
679 | } | ||
680 | |||
681 | return -EINVAL; | ||
682 | } | ||
683 | EXPORT_SYMBOL(__sysfs_match_string); | ||
684 | |||
659 | #ifndef __HAVE_ARCH_MEMSET | 685 | #ifndef __HAVE_ARCH_MEMSET |
660 | /** | 686 | /** |
661 | * memset - Fill a region of memory with the given value | 687 | * memset - Fill a region of memory with the given value |
diff --git a/tools/usb/.gitignore b/tools/usb/.gitignore new file mode 100644 index 000000000000..1b7448981435 --- /dev/null +++ b/tools/usb/.gitignore | |||
@@ -0,0 +1,2 @@ | |||
1 | ffs-test | ||
2 | testusb | ||
diff --git a/tools/usb/usbip/README b/tools/usb/usbip/README index 5eb2b6c7722b..7844490fc603 100644 --- a/tools/usb/usbip/README +++ b/tools/usb/usbip/README | |||
@@ -244,7 +244,7 @@ Detach the imported device: | |||
244 | - See 'Debug Tips' on the project wiki. | 244 | - See 'Debug Tips' on the project wiki. |
245 | - http://usbip.wiki.sourceforge.net/how-to-debug-usbip | 245 | - http://usbip.wiki.sourceforge.net/how-to-debug-usbip |
246 | - usbip-host.ko must be bound to the target device. | 246 | - usbip-host.ko must be bound to the target device. |
247 | - See /proc/bus/usb/devices and find "Driver=..." lines of the device. | 247 | - See /sys/kernel/debug/usb/devices and find "Driver=..." lines of the device. |
248 | - Target USB gadget must be bound to vudc | 248 | - Target USB gadget must be bound to vudc |
249 | (using USB gadget susbsys, not usbip bind command) | 249 | (using USB gadget susbsys, not usbip bind command) |
250 | - Shutdown firewall. | 250 | - Shutdown firewall. |
diff --git a/tools/usb/usbip/libsrc/usbip_common.c b/tools/usb/usbip/libsrc/usbip_common.c index ac73710473de..1517a232ab18 100644 --- a/tools/usb/usbip/libsrc/usbip_common.c +++ b/tools/usb/usbip/libsrc/usbip_common.c | |||
@@ -215,9 +215,16 @@ int read_usb_interface(struct usbip_usb_device *udev, int i, | |||
215 | struct usbip_usb_interface *uinf) | 215 | struct usbip_usb_interface *uinf) |
216 | { | 216 | { |
217 | char busid[SYSFS_BUS_ID_SIZE]; | 217 | char busid[SYSFS_BUS_ID_SIZE]; |
218 | int size; | ||
218 | struct udev_device *sif; | 219 | struct udev_device *sif; |
219 | 220 | ||
220 | sprintf(busid, "%s:%d.%d", udev->busid, udev->bConfigurationValue, i); | 221 | size = snprintf(busid, sizeof(busid), "%s:%d.%d", |
222 | udev->busid, udev->bConfigurationValue, i); | ||
223 | if (size < 0 || (unsigned int)size >= sizeof(busid)) { | ||
224 | err("busid length %i >= %lu or < 0", size, | ||
225 | (long unsigned)sizeof(busid)); | ||
226 | return -1; | ||
227 | } | ||
221 | 228 | ||
222 | sif = udev_device_new_from_subsystem_sysname(udev_context, "usb", busid); | 229 | sif = udev_device_new_from_subsystem_sysname(udev_context, "usb", busid); |
223 | if (!sif) { | 230 | if (!sif) { |
diff --git a/tools/usb/usbip/libsrc/usbip_host_common.c b/tools/usb/usbip/libsrc/usbip_host_common.c index 9d415228883d..6ff7b601f854 100644 --- a/tools/usb/usbip/libsrc/usbip_host_common.c +++ b/tools/usb/usbip/libsrc/usbip_host_common.c | |||
@@ -40,13 +40,20 @@ struct udev *udev_context; | |||
40 | static int32_t read_attr_usbip_status(struct usbip_usb_device *udev) | 40 | static int32_t read_attr_usbip_status(struct usbip_usb_device *udev) |
41 | { | 41 | { |
42 | char status_attr_path[SYSFS_PATH_MAX]; | 42 | char status_attr_path[SYSFS_PATH_MAX]; |
43 | int size; | ||
43 | int fd; | 44 | int fd; |
44 | int length; | 45 | int length; |
45 | char status; | 46 | char status; |
46 | int value = 0; | 47 | int value = 0; |
47 | 48 | ||
48 | snprintf(status_attr_path, SYSFS_PATH_MAX, "%s/usbip_status", | 49 | size = snprintf(status_attr_path, sizeof(status_attr_path), |
49 | udev->path); | 50 | "%s/usbip_status", udev->path); |
51 | if (size < 0 || (unsigned int)size >= sizeof(status_attr_path)) { | ||
52 | err("usbip_status path length %i >= %lu or < 0", size, | ||
53 | (long unsigned)sizeof(status_attr_path)); | ||
54 | return -1; | ||
55 | } | ||
56 | |||
50 | 57 | ||
51 | fd = open(status_attr_path, O_RDONLY); | 58 | fd = open(status_attr_path, O_RDONLY); |
52 | if (fd < 0) { | 59 | if (fd < 0) { |
@@ -218,6 +225,7 @@ int usbip_export_device(struct usbip_exported_device *edev, int sockfd) | |||
218 | { | 225 | { |
219 | char attr_name[] = "usbip_sockfd"; | 226 | char attr_name[] = "usbip_sockfd"; |
220 | char sockfd_attr_path[SYSFS_PATH_MAX]; | 227 | char sockfd_attr_path[SYSFS_PATH_MAX]; |
228 | int size; | ||
221 | char sockfd_buff[30]; | 229 | char sockfd_buff[30]; |
222 | int ret; | 230 | int ret; |
223 | 231 | ||
@@ -237,10 +245,20 @@ int usbip_export_device(struct usbip_exported_device *edev, int sockfd) | |||
237 | } | 245 | } |
238 | 246 | ||
239 | /* only the first interface is true */ | 247 | /* only the first interface is true */ |
240 | snprintf(sockfd_attr_path, sizeof(sockfd_attr_path), "%s/%s", | 248 | size = snprintf(sockfd_attr_path, sizeof(sockfd_attr_path), "%s/%s", |
241 | edev->udev.path, attr_name); | 249 | edev->udev.path, attr_name); |
250 | if (size < 0 || (unsigned int)size >= sizeof(sockfd_attr_path)) { | ||
251 | err("exported device path length %i >= %lu or < 0", size, | ||
252 | (long unsigned)sizeof(sockfd_attr_path)); | ||
253 | return -1; | ||
254 | } | ||
242 | 255 | ||
243 | snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd); | 256 | size = snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd); |
257 | if (size < 0 || (unsigned int)size >= sizeof(sockfd_buff)) { | ||
258 | err("socket length %i >= %lu or < 0", size, | ||
259 | (long unsigned)sizeof(sockfd_buff)); | ||
260 | return -1; | ||
261 | } | ||
244 | 262 | ||
245 | ret = write_sysfs_attribute(sockfd_attr_path, sockfd_buff, | 263 | ret = write_sysfs_attribute(sockfd_attr_path, sockfd_buff, |
246 | strlen(sockfd_buff)); | 264 | strlen(sockfd_buff)); |
diff --git a/tools/usb/usbip/libsrc/vhci_driver.c b/tools/usb/usbip/libsrc/vhci_driver.c index ad9204773533..f659c146cdc8 100644 --- a/tools/usb/usbip/libsrc/vhci_driver.c +++ b/tools/usb/usbip/libsrc/vhci_driver.c | |||
@@ -123,33 +123,15 @@ static int refresh_imported_device_list(void) | |||
123 | 123 | ||
124 | static int get_nports(void) | 124 | static int get_nports(void) |
125 | { | 125 | { |
126 | char *c; | 126 | const char *attr_nports; |
127 | int nports = 0; | ||
128 | const char *attr_status; | ||
129 | 127 | ||
130 | attr_status = udev_device_get_sysattr_value(vhci_driver->hc_device, | 128 | attr_nports = udev_device_get_sysattr_value(vhci_driver->hc_device, "nports"); |
131 | "status"); | 129 | if (!attr_nports) { |
132 | if (!attr_status) { | 130 | err("udev_device_get_sysattr_value nports failed"); |
133 | err("udev_device_get_sysattr_value failed"); | ||
134 | return -1; | 131 | return -1; |
135 | } | 132 | } |
136 | 133 | ||
137 | /* skip a header line */ | 134 | return (int)strtoul(attr_nports, NULL, 10); |
138 | c = strchr(attr_status, '\n'); | ||
139 | if (!c) | ||
140 | return 0; | ||
141 | c++; | ||
142 | |||
143 | while (*c != '\0') { | ||
144 | /* go to the next line */ | ||
145 | c = strchr(c, '\n'); | ||
146 | if (!c) | ||
147 | return nports; | ||
148 | c++; | ||
149 | nports += 1; | ||
150 | } | ||
151 | |||
152 | return nports; | ||
153 | } | 135 | } |
154 | 136 | ||
155 | /* | 137 | /* |
diff --git a/tools/usb/usbip/src/usbip.c b/tools/usb/usbip/src/usbip.c index d7599d943529..73d8eee8130b 100644 --- a/tools/usb/usbip/src/usbip.c +++ b/tools/usb/usbip/src/usbip.c | |||
@@ -176,6 +176,8 @@ int main(int argc, char *argv[]) | |||
176 | break; | 176 | break; |
177 | case '?': | 177 | case '?': |
178 | printf("usbip: invalid option\n"); | 178 | printf("usbip: invalid option\n"); |
179 | /* Terminate after printing error */ | ||
180 | /* FALLTHRU */ | ||
179 | default: | 181 | default: |
180 | usbip_usage(); | 182 | usbip_usage(); |
181 | goto out; | 183 | goto out; |