diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-05 19:14:12 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-05 19:14:12 -0400 |
commit | 07c4dd3435aa387d3b58f4e941dc516513f14507 (patch) | |
tree | 26ebc60562ba573ec499f850c53ffd48f2bfdf72 | |
parent | f60342fac9fae20ada2cd5faadbc2a1337cae03f (diff) | |
parent | c2ef60fea2dc7f903450926aee1f9c282ea529ca (diff) |
Merge tag 'usb-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB and PHY updates from Greg KH:
"Here is the big USB pull request for 4.18-rc1.
Lots of stuff here, the highlights are:
- phy driver updates and new additions
- usual set of xhci driver updates
- normal set of musb updates
- gadget driver updates and new controllers
- typec work, it's getting closer to getting fully out of the staging
portion of the tree.
- lots of minor cleanups and bugfixes.
All of these have been in linux-next for a while with no reported
issues"
* tag 'usb-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (263 commits)
Revert "xhci: Reset Renesas uPD72020x USB controller for 32-bit DMA issue"
xhci: Add quirk to zero 64bit registers on Renesas PCIe controllers
xhci: Allow more than 32 quirks
usb: xhci: force all memory allocations to node
selftests: add test for USB over IP driver
USB: typec: fsusb302: no need to check return value of debugfs_create_dir()
USB: gadget: udc: s3c2410_udc: no need to check return value of debugfs_create functions
USB: gadget: udc: renesas_usb3: no need to check return value of debugfs_create functions
USB: gadget: udc: pxa27x_udc: no need to check return value of debugfs_create functions
USB: gadget: udc: gr_udc: no need to check return value of debugfs_create functions
USB: gadget: udc: bcm63xx_udc: no need to check return value of debugfs_create functions
USB: udc: atmel_usba_udc: no need to check return value of debugfs_create functions
USB: dwc3: no need to check return value of debugfs_create functions
USB: dwc2: no need to check return value of debugfs_create functions
USB: core: no need to check return value of debugfs_create functions
USB: chipidea: no need to check return value of debugfs_create functions
USB: ehci-hcd: no need to check return value of debugfs_create functions
USB: fhci-hcd: no need to check return value of debugfs_create functions
USB: fotg210-hcd: no need to check return value of debugfs_create functions
USB: imx21-hcd: no need to check return value of debugfs_create functions
...
211 files changed, 11404 insertions, 3486 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb index c702c78f24d8..08d456e07b53 100644 --- a/Documentation/ABI/testing/sysfs-bus-usb +++ b/Documentation/ABI/testing/sysfs-bus-usb | |||
@@ -189,6 +189,28 @@ Description: | |||
189 | The file will read "hotplug", "wired" and "not used" if the | 189 | The file will read "hotplug", "wired" and "not used" if the |
190 | information is available, and "unknown" otherwise. | 190 | information is available, and "unknown" otherwise. |
191 | 191 | ||
192 | What: /sys/bus/usb/devices/.../(hub interface)/portX/quirks | ||
193 | Date: May 2018 | ||
194 | Contact: Nicolas Boichat <drinkcat@chromium.org> | ||
195 | Description: | ||
196 | In some cases, we care about time-to-active for devices | ||
197 | connected on a specific port (e.g. non-standard USB port like | ||
198 | pogo pins), where the device to be connected is known in | ||
199 | advance, and behaves well according to the specification. | ||
200 | This attribute is a bit-field that controls the behavior of | ||
201 | a specific port: | ||
202 | - Bit 0 of this field selects the "old" enumeration scheme, | ||
203 | as it is considerably faster (it only causes one USB reset | ||
204 | instead of 2). | ||
205 | The old enumeration scheme can also be selected globally | ||
206 | using /sys/module/usbcore/parameters/old_scheme_first, but | ||
207 | it is often not desirable as the new scheme was introduced to | ||
208 | increase compatibility with more devices. | ||
209 | - Bit 1 reduces TRSTRCY to the 10 ms that are required by the | ||
210 | USB 2.0 specification, instead of the 50 ms that are normally | ||
211 | used to help make enumeration work better on some high speed | ||
212 | devices. | ||
213 | |||
192 | What: /sys/bus/usb/devices/.../(hub interface)/portX/over_current_count | 214 | What: /sys/bus/usb/devices/.../(hub interface)/portX/over_current_count |
193 | Date: February 2018 | 215 | Date: February 2018 |
194 | Contact: Richard Leitner <richard.leitner@skidata.com> | 216 | Contact: Richard Leitner <richard.leitner@skidata.com> |
@@ -236,3 +258,21 @@ Description: | |||
236 | Supported values are 0 - 15. | 258 | Supported values are 0 - 15. |
237 | More information on how besl values map to microseconds can be found in | 259 | More information on how besl values map to microseconds can be found in |
238 | USB 2.0 ECN Errata for Link Power Management, section 4.10) | 260 | USB 2.0 ECN Errata for Link Power Management, section 4.10) |
261 | |||
262 | What: /sys/bus/usb/devices/.../rx_lanes | ||
263 | Date: March 2018 | ||
264 | Contact: Mathias Nyman <mathias.nyman@linux.intel.com> | ||
265 | Description: | ||
266 | Number of rx lanes the device is using. | ||
267 | USB 3.2 adds Dual-lane support, 2 rx and 2 tx lanes over Type-C. | ||
268 | Inter-Chip SSIC devices support asymmetric lanes up to 4 lanes per | ||
269 | direction. Devices before USB 3.2 are single lane (rx_lanes = 1) | ||
270 | |||
271 | What: /sys/bus/usb/devices/.../tx_lanes | ||
272 | Date: March 2018 | ||
273 | Contact: Mathias Nyman <mathias.nyman@linux.intel.com> | ||
274 | Description: | ||
275 | Number of tx lanes the device is using. | ||
276 | USB 3.2 adds Dual-lane support, 2 rx and 2 tx -lanes over Type-C. | ||
277 | Inter-Chip SSIC devices support asymmetric lanes up to 4 lanes per | ||
278 | direction. Devices before USB 3.2 are single lane (tx_lanes = 1) | ||
diff --git a/Documentation/ABI/testing/sysfs-class-power b/Documentation/ABI/testing/sysfs-class-power index f85ce9e327b9..5e23e22dce1b 100644 --- a/Documentation/ABI/testing/sysfs-class-power +++ b/Documentation/ABI/testing/sysfs-class-power | |||
@@ -1,3 +1,458 @@ | |||
1 | ===== General Properties ===== | ||
2 | |||
3 | What: /sys/class/power_supply/<supply_name>/manufacturer | ||
4 | Date: May 2007 | ||
5 | Contact: linux-pm@vger.kernel.org | ||
6 | Description: | ||
7 | Reports the name of the device manufacturer. | ||
8 | |||
9 | Access: Read | ||
10 | Valid values: Represented as string | ||
11 | |||
12 | What: /sys/class/power_supply/<supply_name>/model_name | ||
13 | Date: May 2007 | ||
14 | Contact: linux-pm@vger.kernel.org | ||
15 | Description: | ||
16 | Reports the name of the device model. | ||
17 | |||
18 | Access: Read | ||
19 | Valid values: Represented as string | ||
20 | |||
21 | What: /sys/class/power_supply/<supply_name>/serial_number | ||
22 | Date: January 2008 | ||
23 | Contact: linux-pm@vger.kernel.org | ||
24 | Description: | ||
25 | Reports the serial number of the device. | ||
26 | |||
27 | Access: Read | ||
28 | Valid values: Represented as string | ||
29 | |||
30 | What: /sys/class/power_supply/<supply_name>/type | ||
31 | Date: May 2010 | ||
32 | Contact: linux-pm@vger.kernel.org | ||
33 | Description: | ||
34 | Describes the main type of the supply. | ||
35 | |||
36 | Access: Read | ||
37 | Valid values: "Battery", "UPS", "Mains", "USB" | ||
38 | |||
39 | ===== Battery Properties ===== | ||
40 | |||
41 | What: /sys/class/power_supply/<supply_name>/capacity | ||
42 | Date: May 2007 | ||
43 | Contact: linux-pm@vger.kernel.org | ||
44 | Description: | ||
45 | Fine grain representation of battery capacity. | ||
46 | Access: Read | ||
47 | Valid values: 0 - 100 (percent) | ||
48 | |||
49 | What: /sys/class/power_supply/<supply_name>/capacity_alert_max | ||
50 | Date: July 2012 | ||
51 | Contact: linux-pm@vger.kernel.org | ||
52 | Description: | ||
53 | Maximum battery capacity trip-wire value where the supply will | ||
54 | notify user-space of the event. This is normally used for the | ||
55 | battery discharging scenario where user-space needs to know the | ||
56 | battery has dropped to an upper level so it can take | ||
57 | appropriate action (e.g. warning user that battery level is | ||
58 | low). | ||
59 | |||
60 | Access: Read, Write | ||
61 | Valid values: 0 - 100 (percent) | ||
62 | |||
63 | What: /sys/class/power_supply/<supply_name>/capacity_alert_min | ||
64 | Date: July 2012 | ||
65 | Contact: linux-pm@vger.kernel.org | ||
66 | Description: | ||
67 | Minimum battery capacity trip-wire value where the supply will | ||
68 | notify user-space of the event. This is normally used for the | ||
69 | battery discharging scenario where user-space needs to know the | ||
70 | battery has dropped to a lower level so it can take | ||
71 | appropriate action (e.g. warning user that battery level is | ||
72 | critically low). | ||
73 | |||
74 | Access: Read, Write | ||
75 | Valid values: 0 - 100 (percent) | ||
76 | |||
77 | What: /sys/class/power_supply/<supply_name>/capacity_level | ||
78 | Date: June 2009 | ||
79 | Contact: linux-pm@vger.kernel.org | ||
80 | Description: | ||
81 | Coarse representation of battery capacity. | ||
82 | |||
83 | Access: Read | ||
84 | Valid values: "Unknown", "Critical", "Low", "Normal", "High", | ||
85 | "Full" | ||
86 | |||
87 | What: /sys/class/power_supply/<supply_name>/current_avg | ||
88 | Date: May 2007 | ||
89 | Contact: linux-pm@vger.kernel.org | ||
90 | Description: | ||
91 | Reports an average IBAT current reading for the battery, over a | ||
92 | fixed period. Normally devices will provide a fixed interval in | ||
93 | which they average readings to smooth out the reported value. | ||
94 | |||
95 | Access: Read | ||
96 | Valid values: Represented in microamps | ||
97 | |||
98 | What: /sys/class/power_supply/<supply_name>/current_max | ||
99 | Date: October 2010 | ||
100 | Contact: linux-pm@vger.kernel.org | ||
101 | Description: | ||
102 | Reports the maximum IBAT current allowed into the battery. | ||
103 | |||
104 | Access: Read | ||
105 | Valid values: Represented in microamps | ||
106 | |||
107 | What: /sys/class/power_supply/<supply_name>/current_now | ||
108 | Date: May 2007 | ||
109 | Contact: linux-pm@vger.kernel.org | ||
110 | Description: | ||
111 | Reports an instant, single IBAT current reading for the battery. | ||
112 | This value is not averaged/smoothed. | ||
113 | |||
114 | Access: Read | ||
115 | Valid values: Represented in microamps | ||
116 | |||
117 | What: /sys/class/power_supply/<supply_name>/charge_type | ||
118 | Date: July 2009 | ||
119 | Contact: linux-pm@vger.kernel.org | ||
120 | Description: | ||
121 | Represents the type of charging currently being applied to the | ||
122 | battery. | ||
123 | |||
124 | Access: Read | ||
125 | Valid values: "Unknown", "N/A", "Trickle", "Fast" | ||
126 | |||
127 | What: /sys/class/power_supply/<supply_name>/charge_term_current | ||
128 | Date: July 2014 | ||
129 | Contact: linux-pm@vger.kernel.org | ||
130 | Description: | ||
131 | Reports the charging current value which is used to determine | ||
132 | when the battery is considered full and charging should end. | ||
133 | |||
134 | Access: Read | ||
135 | Valid values: Represented in microamps | ||
136 | |||
137 | What: /sys/class/power_supply/<supply_name>/health | ||
138 | Date: May 2007 | ||
139 | Contact: linux-pm@vger.kernel.org | ||
140 | Description: | ||
141 | Reports the health of the battery or battery side of charger | ||
142 | functionality. | ||
143 | |||
144 | Access: Read | ||
145 | Valid values: "Unknown", "Good", "Overheat", "Dead", | ||
146 | "Over voltage", "Unspecified failure", "Cold", | ||
147 | "Watchdog timer expire", "Safety timer expire" | ||
148 | |||
149 | What: /sys/class/power_supply/<supply_name>/precharge_current | ||
150 | Date: June 2017 | ||
151 | Contact: linux-pm@vger.kernel.org | ||
152 | Description: | ||
153 | Reports the charging current applied during pre-charging phase | ||
154 | for a battery charge cycle. | ||
155 | |||
156 | Access: Read | ||
157 | Valid values: Represented in microamps | ||
158 | |||
159 | What: /sys/class/power_supply/<supply_name>/present | ||
160 | Date: May 2007 | ||
161 | Contact: linux-pm@vger.kernel.org | ||
162 | Description: | ||
163 | Reports whether a battery is present or not in the system. | ||
164 | |||
165 | Access: Read | ||
166 | Valid values: | ||
167 | 0: Absent | ||
168 | 1: Present | ||
169 | |||
170 | What: /sys/class/power_supply/<supply_name>/status | ||
171 | Date: May 2007 | ||
172 | Contact: linux-pm@vger.kernel.org | ||
173 | Description: | ||
174 | Represents the charging status of the battery. Normally this | ||
175 | is read-only reporting although for some supplies this can be | ||
176 | used to enable/disable charging to the battery. | ||
177 | |||
178 | Access: Read, Write | ||
179 | Valid values: "Unknown", "Charging", "Discharging", | ||
180 | "Not charging", "Full" | ||
181 | |||
182 | What: /sys/class/power_supply/<supply_name>/technology | ||
183 | Date: May 2007 | ||
184 | Contact: linux-pm@vger.kernel.org | ||
185 | Description: | ||
186 | Describes the battery technology supported by the supply. | ||
187 | |||
188 | Access: Read | ||
189 | Valid values: "Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe", | ||
190 | "NiCd", "LiMn" | ||
191 | |||
192 | What: /sys/class/power_supply/<supply_name>/temp | ||
193 | Date: May 2007 | ||
194 | Contact: linux-pm@vger.kernel.org | ||
195 | Description: | ||
196 | Reports the current TBAT battery temperature reading. | ||
197 | |||
198 | Access: Read | ||
199 | Valid values: Represented in 1/10 Degrees Celsius | ||
200 | |||
201 | What: /sys/class/power_supply/<supply_name>/temp_alert_max | ||
202 | Date: July 2012 | ||
203 | Contact: linux-pm@vger.kernel.org | ||
204 | Description: | ||
205 | Maximum TBAT temperature trip-wire value where the supply will | ||
206 | notify user-space of the event. This is normally used for the | ||
207 | battery charging scenario where user-space needs to know the | ||
208 | battery temperature has crossed an upper threshold so it can | ||
209 | take appropriate action (e.g. warning user that battery level is | ||
210 | critically high, and charging has stopped). | ||
211 | |||
212 | Access: Read | ||
213 | Valid values: Represented in 1/10 Degrees Celsius | ||
214 | |||
215 | What: /sys/class/power_supply/<supply_name>/temp_alert_min | ||
216 | Date: July 2012 | ||
217 | Contact: linux-pm@vger.kernel.org | ||
218 | Description: | ||
219 | Minimum TBAT temperature trip-wire value where the supply will | ||
220 | notify user-space of the event. This is normally used for the | ||
221 | battery charging scenario where user-space needs to know the | ||
222 | battery temperature has crossed a lower threshold so it can take | ||
223 | appropriate action (e.g. warning user that battery level is | ||
224 | high, and charging current has been reduced accordingly to | ||
225 | remedy the situation). | ||
226 | |||
227 | Access: Read | ||
228 | Valid values: Represented in 1/10 Degrees Celsius | ||
229 | |||
230 | What: /sys/class/power_supply/<supply_name>/temp_max | ||
231 | Date: July 2014 | ||
232 | Contact: linux-pm@vger.kernel.org | ||
233 | Description: | ||
234 | Reports the maximum allowed TBAT battery temperature for | ||
235 | charging. | ||
236 | |||
237 | Access: Read | ||
238 | Valid values: Represented in 1/10 Degrees Celsius | ||
239 | |||
240 | What: /sys/class/power_supply/<supply_name>/temp_min | ||
241 | Date: July 2014 | ||
242 | Contact: linux-pm@vger.kernel.org | ||
243 | Description: | ||
244 | Reports the minimum allowed TBAT battery temperature for | ||
245 | charging. | ||
246 | |||
247 | Access: Read | ||
248 | Valid values: Represented in 1/10 Degrees Celsius | ||
249 | |||
250 | What: /sys/class/power_supply/<supply_name>/voltage_avg, | ||
251 | Date: May 2007 | ||
252 | Contact: linux-pm@vger.kernel.org | ||
253 | Description: | ||
254 | Reports an average VBAT voltage reading for the battery, over a | ||
255 | fixed period. Normally devices will provide a fixed interval in | ||
256 | which they average readings to smooth out the reported value. | ||
257 | |||
258 | Access: Read | ||
259 | Valid values: Represented in microvolts | ||
260 | |||
261 | What: /sys/class/power_supply/<supply_name>/voltage_max, | ||
262 | Date: January 2008 | ||
263 | Contact: linux-pm@vger.kernel.org | ||
264 | Description: | ||
265 | Reports the maximum safe VBAT voltage permitted for the battery, | ||
266 | during charging. | ||
267 | |||
268 | Access: Read | ||
269 | Valid values: Represented in microvolts | ||
270 | |||
271 | What: /sys/class/power_supply/<supply_name>/voltage_min, | ||
272 | Date: January 2008 | ||
273 | Contact: linux-pm@vger.kernel.org | ||
274 | Description: | ||
275 | Reports the minimum safe VBAT voltage permitted for the battery, | ||
276 | during discharging. | ||
277 | |||
278 | Access: Read | ||
279 | Valid values: Represented in microvolts | ||
280 | |||
281 | What: /sys/class/power_supply/<supply_name>/voltage_now, | ||
282 | Date: May 2007 | ||
283 | Contact: linux-pm@vger.kernel.org | ||
284 | Description: | ||
285 | Reports an instant, single VBAT voltage reading for the battery. | ||
286 | This value is not averaged/smoothed. | ||
287 | |||
288 | Access: Read | ||
289 | Valid values: Represented in microvolts | ||
290 | |||
291 | ===== USB Properties ===== | ||
292 | |||
293 | What: /sys/class/power_supply/<supply_name>/current_avg | ||
294 | Date: May 2007 | ||
295 | Contact: linux-pm@vger.kernel.org | ||
296 | Description: | ||
297 | Reports an average IBUS current reading over a fixed period. | ||
298 | Normally devices will provide a fixed interval in which they | ||
299 | average readings to smooth out the reported value. | ||
300 | |||
301 | Access: Read | ||
302 | Valid values: Represented in microamps | ||
303 | |||
304 | |||
305 | What: /sys/class/power_supply/<supply_name>/current_max | ||
306 | Date: October 2010 | ||
307 | Contact: linux-pm@vger.kernel.org | ||
308 | Description: | ||
309 | Reports the maximum IBUS current the supply can support. | ||
310 | |||
311 | Access: Read | ||
312 | Valid values: Represented in microamps | ||
313 | |||
314 | What: /sys/class/power_supply/<supply_name>/current_now | ||
315 | Date: May 2007 | ||
316 | Contact: linux-pm@vger.kernel.org | ||
317 | Description: | ||
318 | Reports the IBUS current supplied now. This value is generally | ||
319 | read-only reporting, unless the 'online' state of the supply | ||
320 | is set to be programmable, in which case this value can be set | ||
321 | within the reported min/max range. | ||
322 | |||
323 | Access: Read, Write | ||
324 | Valid values: Represented in microamps | ||
325 | |||
326 | What: /sys/class/power_supply/<supply_name>/input_current_limit | ||
327 | Date: July 2014 | ||
328 | Contact: linux-pm@vger.kernel.org | ||
329 | Description: | ||
330 | Details the incoming IBUS current limit currently set in the | ||
331 | supply. Normally this is configured based on the type of | ||
332 | connection made (e.g. A configured SDP should output a maximum | ||
333 | of 500mA so the input current limit is set to the same value). | ||
334 | |||
335 | Access: Read, Write | ||
336 | Valid values: Represented in microamps | ||
337 | |||
338 | What: /sys/class/power_supply/<supply_name>/online, | ||
339 | Date: May 2007 | ||
340 | Contact: linux-pm@vger.kernel.org | ||
341 | Description: | ||
342 | Indicates if VBUS is present for the supply. When the supply is | ||
343 | online, and the supply allows it, then it's possible to switch | ||
344 | between online states (e.g. Fixed -> Programmable for a PD_PPS | ||
345 | USB supply so voltage and current can be controlled). | ||
346 | |||
347 | Access: Read, Write | ||
348 | Valid values: | ||
349 | 0: Offline | ||
350 | 1: Online Fixed - Fixed Voltage Supply | ||
351 | 2: Online Programmable - Programmable Voltage Supply | ||
352 | |||
353 | What: /sys/class/power_supply/<supply_name>/temp | ||
354 | Date: May 2007 | ||
355 | Contact: linux-pm@vger.kernel.org | ||
356 | Description: | ||
357 | Reports the current supply temperature reading. This would | ||
358 | normally be the internal temperature of the device itself (e.g | ||
359 | TJUNC temperature of an IC) | ||
360 | |||
361 | Access: Read | ||
362 | Valid values: Represented in 1/10 Degrees Celsius | ||
363 | |||
364 | What: /sys/class/power_supply/<supply_name>/temp_alert_max | ||
365 | Date: July 2012 | ||
366 | Contact: linux-pm@vger.kernel.org | ||
367 | Description: | ||
368 | Maximum supply temperature trip-wire value where the supply will | ||
369 | notify user-space of the event. This is normally used for the | ||
370 | charging scenario where user-space needs to know the supply | ||
371 | temperature has crossed an upper threshold so it can take | ||
372 | appropriate action (e.g. warning user that the supply | ||
373 | temperature is critically high, and charging has stopped to | ||
374 | remedy the situation). | ||
375 | |||
376 | Access: Read | ||
377 | Valid values: Represented in 1/10 Degrees Celsius | ||
378 | |||
379 | What: /sys/class/power_supply/<supply_name>/temp_alert_min | ||
380 | Date: July 2012 | ||
381 | Contact: linux-pm@vger.kernel.org | ||
382 | Description: | ||
383 | Minimum supply temperature trip-wire value where the supply will | ||
384 | notify user-space of the event. This is normally used for the | ||
385 | charging scenario where user-space needs to know the supply | ||
386 | temperature has crossed a lower threshold so it can take | ||
387 | appropriate action (e.g. warning user that the supply | ||
388 | temperature is high, and charging current has been reduced | ||
389 | accordingly to remedy the situation). | ||
390 | |||
391 | Access: Read | ||
392 | Valid values: Represented in 1/10 Degrees Celsius | ||
393 | |||
394 | What: /sys/class/power_supply/<supply_name>/temp_max | ||
395 | Date: July 2014 | ||
396 | Contact: linux-pm@vger.kernel.org | ||
397 | Description: | ||
398 | Reports the maximum allowed supply temperature for operation. | ||
399 | |||
400 | Access: Read | ||
401 | Valid values: Represented in 1/10 Degrees Celsius | ||
402 | |||
403 | What: /sys/class/power_supply/<supply_name>/temp_min | ||
404 | Date: July 2014 | ||
405 | Contact: linux-pm@vger.kernel.org | ||
406 | Description: | ||
407 | Reports the mainimum allowed supply temperature for operation. | ||
408 | |||
409 | Access: Read | ||
410 | Valid values: Represented in 1/10 Degrees Celsius | ||
411 | |||
412 | What: /sys/class/power_supply/<supply_name>/usb_type | ||
413 | Date: March 2018 | ||
414 | Contact: linux-pm@vger.kernel.org | ||
415 | Description: | ||
416 | Reports what type of USB connection is currently active for | ||
417 | the supply, for example it can show if USB-PD capable source | ||
418 | is attached. | ||
419 | |||
420 | Access: Read-Only | ||
421 | Valid values: "Unknown", "SDP", "DCP", "CDP", "ACA", "C", "PD", | ||
422 | "PD_DRP", "PD_PPS", "BrickID" | ||
423 | |||
424 | What: /sys/class/power_supply/<supply_name>/voltage_max | ||
425 | Date: January 2008 | ||
426 | Contact: linux-pm@vger.kernel.org | ||
427 | Description: | ||
428 | Reports the maximum VBUS voltage the supply can support. | ||
429 | |||
430 | Access: Read | ||
431 | Valid values: Represented in microvolts | ||
432 | |||
433 | What: /sys/class/power_supply/<supply_name>/voltage_min | ||
434 | Date: January 2008 | ||
435 | Contact: linux-pm@vger.kernel.org | ||
436 | Description: | ||
437 | Reports the minimum VBUS voltage the supply can support. | ||
438 | |||
439 | Access: Read | ||
440 | Valid values: Represented in microvolts | ||
441 | |||
442 | What: /sys/class/power_supply/<supply_name>/voltage_now | ||
443 | Date: May 2007 | ||
444 | Contact: linux-pm@vger.kernel.org | ||
445 | Description: | ||
446 | Reports the VBUS voltage supplied now. This value is generally | ||
447 | read-only reporting, unless the 'online' state of the supply | ||
448 | is set to be programmable, in which case this value can be set | ||
449 | within the reported min/max range. | ||
450 | |||
451 | Access: Read, Write | ||
452 | Valid values: Represented in microvolts | ||
453 | |||
454 | ===== Device Specific Properties ===== | ||
455 | |||
1 | What: /sys/class/power/ds2760-battery.*/charge_now | 456 | What: /sys/class/power/ds2760-battery.*/charge_now |
2 | Date: May 2010 | 457 | Date: May 2010 |
3 | KernelVersion: 2.6.35 | 458 | KernelVersion: 2.6.35 |
diff --git a/Documentation/devicetree/bindings/phy/phy-mtk-xsphy.txt b/Documentation/devicetree/bindings/phy/phy-mtk-xsphy.txt new file mode 100644 index 000000000000..e7caefa0b9c2 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/phy-mtk-xsphy.txt | |||
@@ -0,0 +1,109 @@ | |||
1 | MediaTek XS-PHY binding | ||
2 | -------------------------- | ||
3 | |||
4 | The XS-PHY controller supports physical layer functionality for USB3.1 | ||
5 | GEN2 controller on MediaTek SoCs. | ||
6 | |||
7 | Required properties (controller (parent) node): | ||
8 | - compatible : should be "mediatek,<soc-model>-xsphy", "mediatek,xsphy", | ||
9 | soc-model is the name of SoC, such as mt3611 etc; | ||
10 | when using "mediatek,xsphy" compatible string, you need SoC specific | ||
11 | ones in addition, one of: | ||
12 | - "mediatek,mt3611-xsphy" | ||
13 | |||
14 | - #address-cells, #size-cells : should use the same values as the root node | ||
15 | - ranges: must be present | ||
16 | |||
17 | Optional properties (controller (parent) node): | ||
18 | - reg : offset and length of register shared by multiple U3 ports, | ||
19 | exclude port's private register, if only U2 ports provided, | ||
20 | shouldn't use the property. | ||
21 | - mediatek,src-ref-clk-mhz : u32, frequency of reference clock for slew rate | ||
22 | calibrate | ||
23 | - mediatek,src-coef : u32, coefficient for slew rate calibrate, depends on | ||
24 | SoC process | ||
25 | |||
26 | Required nodes : a sub-node is required for each port the controller | ||
27 | provides. Address range information including the usual | ||
28 | 'reg' property is used inside these nodes to describe | ||
29 | the controller's topology. | ||
30 | |||
31 | Required properties (port (child) node): | ||
32 | - reg : address and length of the register set for the port. | ||
33 | - clocks : a list of phandle + clock-specifier pairs, one for each | ||
34 | entry in clock-names | ||
35 | - clock-names : must contain | ||
36 | "ref": 48M reference clock for HighSpeed analog phy; and 26M | ||
37 | reference clock for SuperSpeedPlus analog phy, sometimes is | ||
38 | 24M, 25M or 27M, depended on platform. | ||
39 | - #phy-cells : should be 1 | ||
40 | cell after port phandle is phy type from: | ||
41 | - PHY_TYPE_USB2 | ||
42 | - PHY_TYPE_USB3 | ||
43 | |||
44 | The following optional properties are only for debug or HQA test | ||
45 | Optional properties (PHY_TYPE_USB2 port (child) node): | ||
46 | - mediatek,eye-src : u32, the value of slew rate calibrate | ||
47 | - mediatek,eye-vrt : u32, the selection of VRT reference voltage | ||
48 | - mediatek,eye-term : u32, the selection of HS_TX TERM reference voltage | ||
49 | - mediatek,efuse-intr : u32, the selection of Internal Resistor | ||
50 | |||
51 | Optional properties (PHY_TYPE_USB3 port (child) node): | ||
52 | - mediatek,efuse-intr : u32, the selection of Internal Resistor | ||
53 | - mediatek,efuse-tx-imp : u32, the selection of TX Impedance | ||
54 | - mediatek,efuse-rx-imp : u32, the selection of RX Impedance | ||
55 | |||
56 | Banks layout of xsphy | ||
57 | ------------------------------------------------------------- | ||
58 | port offset bank | ||
59 | u2 port0 0x0000 MISC | ||
60 | 0x0100 FMREG | ||
61 | 0x0300 U2PHY_COM | ||
62 | u2 port1 0x1000 MISC | ||
63 | 0x1100 FMREG | ||
64 | 0x1300 U2PHY_COM | ||
65 | u2 port2 0x2000 MISC | ||
66 | ... | ||
67 | u31 common 0x3000 DIG_GLB | ||
68 | 0x3100 PHYA_GLB | ||
69 | u31 port0 0x3400 DIG_LN_TOP | ||
70 | 0x3500 DIG_LN_TX0 | ||
71 | 0x3600 DIG_LN_RX0 | ||
72 | 0x3700 DIG_LN_DAIF | ||
73 | 0x3800 PHYA_LN | ||
74 | u31 port1 0x3a00 DIG_LN_TOP | ||
75 | 0x3b00 DIG_LN_TX0 | ||
76 | 0x3c00 DIG_LN_RX0 | ||
77 | 0x3d00 DIG_LN_DAIF | ||
78 | 0x3e00 PHYA_LN | ||
79 | ... | ||
80 | |||
81 | DIG_GLB & PHYA_GLB are shared by U31 ports. | ||
82 | |||
83 | Example: | ||
84 | |||
85 | u3phy: usb-phy@11c40000 { | ||
86 | compatible = "mediatek,mt3611-xsphy", "mediatek,xsphy"; | ||
87 | reg = <0 0x11c43000 0 0x0200>; | ||
88 | mediatek,src-ref-clk-mhz = <26>; | ||
89 | mediatek,src-coef = <17>; | ||
90 | #address-cells = <2>; | ||
91 | #size-cells = <2>; | ||
92 | ranges; | ||
93 | |||
94 | u2port0: usb-phy@11c40000 { | ||
95 | reg = <0 0x11c40000 0 0x0400>; | ||
96 | clocks = <&clk48m>; | ||
97 | clock-names = "ref"; | ||
98 | mediatek,eye-src = <4>; | ||
99 | #phy-cells = <1>; | ||
100 | }; | ||
101 | |||
102 | u3port0: usb-phy@11c43000 { | ||
103 | reg = <0 0x11c43400 0 0x0500>; | ||
104 | clocks = <&clk26m>; | ||
105 | clock-names = "ref"; | ||
106 | mediatek,efuse-intr = <28>; | ||
107 | #phy-cells = <1>; | ||
108 | }; | ||
109 | }; | ||
diff --git a/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt b/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt index dcf1b8f691d5..266a1bb8bb6e 100644 --- a/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt +++ b/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt | |||
@@ -9,7 +9,8 @@ Required properties: | |||
9 | "qcom,ipq8074-qmp-pcie-phy" for PCIe phy on IPQ8074 | 9 | "qcom,ipq8074-qmp-pcie-phy" for PCIe phy on IPQ8074 |
10 | "qcom,msm8996-qmp-pcie-phy" for 14nm PCIe phy on msm8996, | 10 | "qcom,msm8996-qmp-pcie-phy" for 14nm PCIe phy on msm8996, |
11 | "qcom,msm8996-qmp-usb3-phy" for 14nm USB3 phy on msm8996, | 11 | "qcom,msm8996-qmp-usb3-phy" for 14nm USB3 phy on msm8996, |
12 | "qcom,qmp-v3-usb3-phy" for USB3 QMP V3 phy. | 12 | "qcom,sdm845-qmp-usb3-phy" for USB3 QMP V3 phy on sdm845, |
13 | "qcom,sdm845-qmp-usb3-uni-phy" for USB3 QMP V3 UNI phy on sdm845. | ||
13 | 14 | ||
14 | - reg: offset and length of register set for PHY's common serdes block. | 15 | - reg: offset and length of register set for PHY's common serdes block. |
15 | 16 | ||
diff --git a/Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt b/Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt index 42c97426836e..03025d97998b 100644 --- a/Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt +++ b/Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt | |||
@@ -6,7 +6,7 @@ QUSB2 controller supports LS/FS/HS usb connectivity on Qualcomm chipsets. | |||
6 | Required properties: | 6 | Required properties: |
7 | - compatible: compatible list, contains | 7 | - compatible: compatible list, contains |
8 | "qcom,msm8996-qusb2-phy" for 14nm PHY on msm8996, | 8 | "qcom,msm8996-qusb2-phy" for 14nm PHY on msm8996, |
9 | "qcom,qusb2-v2-phy" for QUSB2 V2 PHY. | 9 | "qcom,sdm845-qusb2-phy" for 10nm PHY on sdm845. |
10 | 10 | ||
11 | - reg: offset and length of the PHY register set. | 11 | - reg: offset and length of the PHY register set. |
12 | - #phy-cells: must be 0. | 12 | - #phy-cells: must be 0. |
@@ -27,6 +27,27 @@ Optional properties: | |||
27 | tuning parameter value for qusb2 phy. | 27 | tuning parameter value for qusb2 phy. |
28 | 28 | ||
29 | - qcom,tcsr-syscon: Phandle to TCSR syscon register region. | 29 | - qcom,tcsr-syscon: Phandle to TCSR syscon register region. |
30 | - qcom,imp-res-offset-value: It is a 6 bit value that specifies offset to be | ||
31 | added to PHY refgen RESCODE via IMP_CTRL1 register. It is a PHY | ||
32 | tuning parameter that may vary for different boards of same SOC. | ||
33 | This property is applicable to only QUSB2 v2 PHY (sdm845). | ||
34 | - qcom,hstx-trim-value: It is a 4 bit value that specifies tuning for HSTX | ||
35 | output current. | ||
36 | Possible range is - 15mA to 24mA (stepsize of 600 uA). | ||
37 | See dt-bindings/phy/phy-qcom-qusb2.h for applicable values. | ||
38 | This property is applicable to only QUSB2 v2 PHY (sdm845). | ||
39 | Default value is 22.2mA for sdm845. | ||
40 | - qcom,preemphasis-level: It is a 2 bit value that specifies pre-emphasis level. | ||
41 | Possible range is 0 to 15% (stepsize of 5%). | ||
42 | See dt-bindings/phy/phy-qcom-qusb2.h for applicable values. | ||
43 | This property is applicable to only QUSB2 v2 PHY (sdm845). | ||
44 | Default value is 10% for sdm845. | ||
45 | - qcom,preemphasis-width: It is a 1 bit value that specifies how long the HSTX | ||
46 | pre-emphasis (specified using qcom,preemphasis-level) must be in | ||
47 | effect. Duration could be half-bit of full-bit. | ||
48 | See dt-bindings/phy/phy-qcom-qusb2.h for applicable values. | ||
49 | This property is applicable to only QUSB2 v2 PHY (sdm845). | ||
50 | Default value is full-bit width for sdm845. | ||
30 | 51 | ||
31 | Example: | 52 | Example: |
32 | hsusb_phy: phy@7411000 { | 53 | hsusb_phy: phy@7411000 { |
diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt index 0e03344e2e8b..2e9318151df7 100644 --- a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt +++ b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt | |||
@@ -76,6 +76,10 @@ Optional properties: | |||
76 | needs to make sure it does not send more than 90% | 76 | needs to make sure it does not send more than 90% |
77 | maximum_periodic_data_per_frame. The use case is multiple transactions, but | 77 | maximum_periodic_data_per_frame. The use case is multiple transactions, but |
78 | less frame rate. | 78 | less frame rate. |
79 | - mux-controls: The mux control for toggling host/device output of this | ||
80 | controller. It's expected that a mux state of 0 indicates device mode and a | ||
81 | mux state of 1 indicates host mode. | ||
82 | - mux-control-names: Shall be "usb_switch" if mux-controls is specified. | ||
79 | 83 | ||
80 | i.mx specific properties | 84 | i.mx specific properties |
81 | - fsl,usbmisc: phandler of non-core register device, with one | 85 | - fsl,usbmisc: phandler of non-core register device, with one |
@@ -102,4 +106,6 @@ Example: | |||
102 | rx-burst-size-dword = <0x10>; | 106 | rx-burst-size-dword = <0x10>; |
103 | extcon = <0>, <&usb_id>; | 107 | extcon = <0>, <&usb_id>; |
104 | phy-clkgate-delay-us = <400>; | 108 | phy-clkgate-delay-us = <400>; |
109 | mux-controls = <&usb_switch>; | ||
110 | mux-control-names = "usb_switch"; | ||
105 | }; | 111 | }; |
diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt index 0dbd3083e7dd..7f13ebef06cb 100644 --- a/Documentation/devicetree/bindings/usb/dwc3.txt +++ b/Documentation/devicetree/bindings/usb/dwc3.txt | |||
@@ -7,6 +7,26 @@ Required properties: | |||
7 | - compatible: must be "snps,dwc3" | 7 | - compatible: must be "snps,dwc3" |
8 | - reg : Address and length of the register set for the device | 8 | - reg : Address and length of the register set for the device |
9 | - interrupts: Interrupts used by the dwc3 controller. | 9 | - interrupts: Interrupts used by the dwc3 controller. |
10 | - clock-names: should contain "ref", "bus_early", "suspend" | ||
11 | - clocks: list of phandle and clock specifier pairs corresponding to | ||
12 | entries in the clock-names property. | ||
13 | |||
14 | Exception for clocks: | ||
15 | clocks are optional if the parent node (i.e. glue-layer) is compatible to | ||
16 | one of the following: | ||
17 | "amlogic,meson-axg-dwc3" | ||
18 | "amlogic,meson-gxl-dwc3" | ||
19 | "cavium,octeon-7130-usb-uctl" | ||
20 | "qcom,dwc3" | ||
21 | "samsung,exynos5250-dwusb3" | ||
22 | "samsung,exynos7-dwusb3" | ||
23 | "sprd,sc9860-dwc3" | ||
24 | "st,stih407-dwc3" | ||
25 | "ti,am437x-dwc3" | ||
26 | "ti,dwc3" | ||
27 | "ti,keystone-dwc3" | ||
28 | "rockchip,rk3399-dwc3" | ||
29 | "xlnx,zynqmp-dwc3" | ||
10 | 30 | ||
11 | Optional properties: | 31 | Optional properties: |
12 | - usb-phy : array of phandle for the PHY device. The first element | 32 | - usb-phy : array of phandle for the PHY device. The first element |
@@ -15,6 +35,7 @@ Optional properties: | |||
15 | - phys: from the *Generic PHY* bindings | 35 | - phys: from the *Generic PHY* bindings |
16 | - phy-names: from the *Generic PHY* bindings; supported names are "usb2-phy" | 36 | - phy-names: from the *Generic PHY* bindings; supported names are "usb2-phy" |
17 | or "usb3-phy". | 37 | or "usb3-phy". |
38 | - resets: a single pair of phandle and reset specifier | ||
18 | - snps,usb3_lpm_capable: determines if platform is USB3 LPM capable | 39 | - snps,usb3_lpm_capable: determines if platform is USB3 LPM capable |
19 | - snps,disable_scramble_quirk: true when SW should disable data scrambling. | 40 | - snps,disable_scramble_quirk: true when SW should disable data scrambling. |
20 | Only really useful for FPGA builds. | 41 | Only really useful for FPGA builds. |
diff --git a/Documentation/devicetree/bindings/usb/fcs,fusb302.txt b/Documentation/devicetree/bindings/usb/fcs,fusb302.txt index 472facfa5a71..6087dc7f209e 100644 --- a/Documentation/devicetree/bindings/usb/fcs,fusb302.txt +++ b/Documentation/devicetree/bindings/usb/fcs,fusb302.txt | |||
@@ -6,12 +6,6 @@ Required properties : | |||
6 | - interrupts : Interrupt specifier | 6 | - interrupts : Interrupt specifier |
7 | 7 | ||
8 | Optional properties : | 8 | Optional properties : |
9 | - fcs,max-sink-microvolt : Maximum voltage to negotiate when configured as sink | ||
10 | - fcs,max-sink-microamp : Maximum current to negotiate when configured as sink | ||
11 | - fcs,max-sink-microwatt : Maximum power to negotiate when configured as sink | ||
12 | If this is less then max-sink-microvolt * | ||
13 | max-sink-microamp then the configured current will | ||
14 | be clamped. | ||
15 | - fcs,operating-sink-microwatt : | 9 | - fcs,operating-sink-microwatt : |
16 | Minimum amount of power accepted from a sink | 10 | Minimum amount of power accepted from a sink |
17 | when negotiating | 11 | when negotiating |
diff --git a/Documentation/devicetree/bindings/usb/hisilicon,histb-xhci.txt b/Documentation/devicetree/bindings/usb/hisilicon,histb-xhci.txt new file mode 100644 index 000000000000..f4633496b122 --- /dev/null +++ b/Documentation/devicetree/bindings/usb/hisilicon,histb-xhci.txt | |||
@@ -0,0 +1,45 @@ | |||
1 | HiSilicon STB xHCI | ||
2 | |||
3 | The device node for HiSilicon STB xHCI host controller | ||
4 | |||
5 | Required properties: | ||
6 | - compatible: should be "hisilicon,hi3798cv200-xhci" | ||
7 | - reg: specifies physical base address and size of the registers | ||
8 | - interrupts : interrupt used by the controller | ||
9 | - clocks: a list of phandle + clock-specifier pairs, one for each | ||
10 | entry in clock-names | ||
11 | - clock-names: must contain | ||
12 | "bus": for bus clock | ||
13 | "utmi": for utmi clock | ||
14 | "pipe": for pipe clock | ||
15 | "suspend": for suspend clock | ||
16 | - resets: a list of phandle and reset specifier pairs as listed in | ||
17 | reset-names property. | ||
18 | - reset-names: must contain | ||
19 | "soft": for soft reset | ||
20 | - phys: a list of phandle + phy specifier pairs | ||
21 | - phy-names: must contain at least one of following: | ||
22 | "inno": for inno phy | ||
23 | "combo": for combo phy | ||
24 | |||
25 | Optional properties: | ||
26 | - usb2-lpm-disable: indicate if we don't want to enable USB2 HW LPM | ||
27 | - usb3-lpm-capable: determines if platform is USB3 LPM capable | ||
28 | - imod-interval-ns: default interrupt moderation interval is 40000ns | ||
29 | |||
30 | Example: | ||
31 | |||
32 | xhci0: xchi@f98a0000 { | ||
33 | compatible = "hisilicon,hi3798cv200-xhci"; | ||
34 | reg = <0xf98a0000 0x10000>; | ||
35 | interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>; | ||
36 | clocks = <&crg HISTB_USB3_BUS_CLK>, | ||
37 | <&crg HISTB_USB3_UTMI_CLK>, | ||
38 | <&crg HISTB_USB3_PIPE_CLK>, | ||
39 | <&crg HISTB_USB3_SUSPEND_CLK>; | ||
40 | clock-names = "bus", "utmi", "pipe", "suspend"; | ||
41 | resets = <&crg 0xb0 12>; | ||
42 | reset-names = "soft"; | ||
43 | phys = <&usb2_phy1_port1 0>, <&combphy0 PHY_TYPE_USB3>; | ||
44 | phy-names = "inno", "combo"; | ||
45 | }; | ||
diff --git a/Documentation/devicetree/bindings/usb/qcom,dwc3.txt b/Documentation/devicetree/bindings/usb/qcom,dwc3.txt index bc8a2fa5d2bf..95afdcf3c337 100644 --- a/Documentation/devicetree/bindings/usb/qcom,dwc3.txt +++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.txt | |||
@@ -1,54 +1,95 @@ | |||
1 | Qualcomm SuperSpeed DWC3 USB SoC controller | 1 | Qualcomm SuperSpeed DWC3 USB SoC controller |
2 | 2 | ||
3 | Required properties: | 3 | Required properties: |
4 | - compatible: should contain "qcom,dwc3" | 4 | - compatible: Compatible list, contains |
5 | "qcom,dwc3" | ||
6 | "qcom,msm8996-dwc3" for msm8996 SOC. | ||
7 | "qcom,sdm845-dwc3" for sdm845 SOC. | ||
8 | - reg: Offset and length of register set for QSCRATCH wrapper | ||
9 | - power-domains: specifies a phandle to PM domain provider node | ||
5 | - clocks: A list of phandle + clock-specifier pairs for the | 10 | - clocks: A list of phandle + clock-specifier pairs for the |
6 | clocks listed in clock-names | 11 | clocks listed in clock-names |
7 | - clock-names: Should contain the following: | 12 | - clock-names: Should contain the following: |
8 | "core" Master/Core clock, have to be >= 125 MHz for SS | 13 | "core" Master/Core clock, have to be >= 125 MHz for SS |
9 | operation and >= 60MHz for HS operation | 14 | operation and >= 60MHz for HS operation |
15 | "mock_utmi" Mock utmi clock needed for ITP/SOF generation in | ||
16 | host mode. Its frequency should be 19.2MHz. | ||
17 | "sleep" Sleep clock, used for wakeup when USB3 core goes | ||
18 | into low power mode (U3). | ||
10 | 19 | ||
11 | Optional clocks: | 20 | Optional clocks: |
12 | "iface" System bus AXI clock. Not present on all platforms | 21 | "iface" System bus AXI clock. |
13 | "sleep" Sleep clock, used when USB3 core goes into low | 22 | Not present on "qcom,msm8996-dwc3" compatible. |
14 | power mode (U3). | 23 | "cfg_noc" System Config NOC clock. |
24 | Not present on "qcom,msm8996-dwc3" compatible. | ||
25 | - assigned-clocks: Should be: | ||
26 | MOCK_UTMI_CLK | ||
27 | MASTER_CLK | ||
28 | - assigned-clock-rates: Should be: | ||
29 | 19.2Mhz (192000000) for MOCK_UTMI_CLK | ||
30 | >=125Mhz (125000000) for MASTER_CLK in SS mode | ||
31 | >=60Mhz (60000000) for MASTER_CLK in HS mode | ||
32 | |||
33 | Optional properties: | ||
34 | - resets: Phandle to reset control that resets core and wrapper. | ||
35 | - interrupts: specifies interrupts from controller wrapper used | ||
36 | to wakeup from low power/susepnd state. Must contain | ||
37 | one or more entry for interrupt-names property | ||
38 | - interrupt-names: Must include the following entries: | ||
39 | - "hs_phy_irq": The interrupt that is asserted when a | ||
40 | wakeup event is received on USB2 bus | ||
41 | - "ss_phy_irq": The interrupt that is asserted when a | ||
42 | wakeup event is received on USB3 bus | ||
43 | - "dm_hs_phy_irq" and "dp_hs_phy_irq": Separate | ||
44 | interrupts for any wakeup event on DM and DP lines | ||
45 | - qcom,select-utmi-as-pipe-clk: if present, disable USB3 pipe_clk requirement. | ||
46 | Used when dwc3 operates without SSPHY and only | ||
47 | HS/FS/LS modes are supported. | ||
15 | 48 | ||
16 | Required child node: | 49 | Required child node: |
17 | A child node must exist to represent the core DWC3 IP block. The name of | 50 | A child node must exist to represent the core DWC3 IP block. The name of |
18 | the node is not important. The content of the node is defined in dwc3.txt. | 51 | the node is not important. The content of the node is defined in dwc3.txt. |
19 | 52 | ||
20 | Phy documentation is provided in the following places: | 53 | Phy documentation is provided in the following places: |
21 | Documentation/devicetree/bindings/phy/qcom-dwc3-usb-phy.txt | 54 | Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt - USB3 QMP PHY |
55 | Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt - USB2 QUSB2 PHY | ||
22 | 56 | ||
23 | Example device nodes: | 57 | Example device nodes: |
24 | 58 | ||
25 | hs_phy: phy@100f8800 { | 59 | hs_phy: phy@100f8800 { |
26 | compatible = "qcom,dwc3-hs-usb-phy"; | 60 | compatible = "qcom,qusb2-v2-phy"; |
27 | reg = <0x100f8800 0x30>; | 61 | ... |
28 | clocks = <&gcc USB30_0_UTMI_CLK>; | ||
29 | clock-names = "ref"; | ||
30 | #phy-cells = <0>; | ||
31 | |||
32 | }; | 62 | }; |
33 | 63 | ||
34 | ss_phy: phy@100f8830 { | 64 | ss_phy: phy@100f8830 { |
35 | compatible = "qcom,dwc3-ss-usb-phy"; | 65 | compatible = "qcom,qmp-v3-usb3-phy"; |
36 | reg = <0x100f8830 0x30>; | 66 | ... |
37 | clocks = <&gcc USB30_0_MASTER_CLK>; | ||
38 | clock-names = "ref"; | ||
39 | #phy-cells = <0>; | ||
40 | |||
41 | }; | 67 | }; |
42 | 68 | ||
43 | usb3_0: usb30@0 { | 69 | usb3_0: usb30@a6f8800 { |
44 | compatible = "qcom,dwc3"; | 70 | compatible = "qcom,dwc3"; |
71 | reg = <0xa6f8800 0x400>; | ||
45 | #address-cells = <1>; | 72 | #address-cells = <1>; |
46 | #size-cells = <1>; | 73 | #size-cells = <1>; |
47 | clocks = <&gcc USB30_0_MASTER_CLK>; | ||
48 | clock-names = "core"; | ||
49 | |||
50 | ranges; | 74 | ranges; |
51 | 75 | ||
76 | interrupts = <0 131 0>, <0 486 0>, <0 488 0>, <0 489 0>; | ||
77 | interrupt-names = "hs_phy_irq", "ss_phy_irq", | ||
78 | "dm_hs_phy_irq", "dp_hs_phy_irq"; | ||
79 | |||
80 | clocks = <&gcc GCC_USB30_PRIM_MASTER_CLK>, | ||
81 | <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>, | ||
82 | <&gcc GCC_USB30_PRIM_SLEEP_CLK>; | ||
83 | clock-names = "core", "mock_utmi", "sleep"; | ||
84 | |||
85 | assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>, | ||
86 | <&gcc GCC_USB30_PRIM_MASTER_CLK>; | ||
87 | assigned-clock-rates = <19200000>, <133000000>; | ||
88 | |||
89 | resets = <&gcc GCC_USB30_PRIM_BCR>; | ||
90 | reset-names = "core_reset"; | ||
91 | power-domains = <&gcc USB30_PRIM_GDSC>; | ||
92 | qcom,select-utmi-as-pipe-clk; | ||
52 | 93 | ||
53 | dwc3@10000000 { | 94 | dwc3@10000000 { |
54 | compatible = "snps,dwc3"; | 95 | compatible = "snps,dwc3"; |
diff --git a/Documentation/devicetree/bindings/usb/richtek,rt1711h.txt b/Documentation/devicetree/bindings/usb/richtek,rt1711h.txt new file mode 100644 index 000000000000..09e847e92e5e --- /dev/null +++ b/Documentation/devicetree/bindings/usb/richtek,rt1711h.txt | |||
@@ -0,0 +1,17 @@ | |||
1 | Richtek RT1711H TypeC PD Controller. | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : Must be "richtek,rt1711h". | ||
5 | - reg : Must be 0x4e, it's slave address of RT1711H. | ||
6 | - interrupt-parent : the phandle for the interrupt controller that | ||
7 | provides interrupts for this device. | ||
8 | - interrupts : <a b> where a is the interrupt number and b represents an | ||
9 | encoding of the sense and level information for the interrupt. | ||
10 | |||
11 | Example : | ||
12 | rt1711h@4e { | ||
13 | compatible = "richtek,rt1711h"; | ||
14 | reg = <0x4e>; | ||
15 | interrupt-parent = <&gpio26>; | ||
16 | interrupts = <0 IRQ_TYPE_LEVEL_LOW>; | ||
17 | }; | ||
diff --git a/Documentation/driver-api/usb/dwc3.rst b/Documentation/driver-api/usb/dwc3.rst index c3dc84a50ce5..8b36ff11cef9 100644 --- a/Documentation/driver-api/usb/dwc3.rst +++ b/Documentation/driver-api/usb/dwc3.rst | |||
@@ -674,9 +674,8 @@ operations, both of which can be traced. Format is:: | |||
674 | __entry->flags & DWC3_EP_ENABLED ? 'E' : 'e', | 674 | __entry->flags & DWC3_EP_ENABLED ? 'E' : 'e', |
675 | __entry->flags & DWC3_EP_STALL ? 'S' : 's', | 675 | __entry->flags & DWC3_EP_STALL ? 'S' : 's', |
676 | __entry->flags & DWC3_EP_WEDGE ? 'W' : 'w', | 676 | __entry->flags & DWC3_EP_WEDGE ? 'W' : 'w', |
677 | __entry->flags & DWC3_EP_BUSY ? 'B' : 'b', | 677 | __entry->flags & DWC3_EP_TRANSFER_STARTED ? 'B' : 'b', |
678 | __entry->flags & DWC3_EP_PENDING_REQUEST ? 'P' : 'p', | 678 | __entry->flags & DWC3_EP_PENDING_REQUEST ? 'P' : 'p', |
679 | __entry->flags & DWC3_EP_MISSED_ISOC ? 'M' : 'm', | ||
680 | __entry->flags & DWC3_EP_END_TRANSFER_PENDING ? 'E' : 'e', | 679 | __entry->flags & DWC3_EP_END_TRANSFER_PENDING ? 'E' : 'e', |
681 | __entry->direction ? '<' : '>' | 680 | __entry->direction ? '<' : '>' |
682 | ) | 681 | ) |
diff --git a/MAINTAINERS b/MAINTAINERS index df6889859b33..756cbfaad7f9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -2331,6 +2331,14 @@ S: Maintained | |||
2331 | F: drivers/gpio/gpio-ath79.c | 2331 | F: drivers/gpio/gpio-ath79.c |
2332 | F: Documentation/devicetree/bindings/gpio/gpio-ath79.txt | 2332 | F: Documentation/devicetree/bindings/gpio/gpio-ath79.txt |
2333 | 2333 | ||
2334 | ATHEROS 71XX/9XXX USB PHY DRIVER | ||
2335 | M: Alban Bedel <albeu@free.fr> | ||
2336 | W: https://github.com/AlbanBedel/linux | ||
2337 | T: git git://github.com/AlbanBedel/linux | ||
2338 | S: Maintained | ||
2339 | F: drivers/phy/qualcomm/phy-ath79-usb.c | ||
2340 | F: Documentation/devicetree/bindings/phy/phy-ath79-usb.txt | ||
2341 | |||
2334 | ATHEROS ATH GENERIC UTILITIES | 2342 | ATHEROS ATH GENERIC UTILITIES |
2335 | M: Kalle Valo <kvalo@codeaurora.org> | 2343 | M: Kalle Valo <kvalo@codeaurora.org> |
2336 | L: linux-wireless@vger.kernel.org | 2344 | L: linux-wireless@vger.kernel.org |
@@ -11267,6 +11275,7 @@ M: Sebastian Reichel <sre@kernel.org> | |||
11267 | L: linux-pm@vger.kernel.org | 11275 | L: linux-pm@vger.kernel.org |
11268 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply.git | 11276 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply.git |
11269 | S: Maintained | 11277 | S: Maintained |
11278 | F: Documentation/ABI/testing/sysfs-class-power | ||
11270 | F: Documentation/devicetree/bindings/power/supply/ | 11279 | F: Documentation/devicetree/bindings/power/supply/ |
11271 | F: include/linux/power_supply.h | 11280 | F: include/linux/power_supply.h |
11272 | F: drivers/power/supply/ | 11281 | F: drivers/power/supply/ |
@@ -14692,6 +14701,7 @@ S: Maintained | |||
14692 | F: Documentation/usb/usbip_protocol.txt | 14701 | F: Documentation/usb/usbip_protocol.txt |
14693 | F: drivers/usb/usbip/ | 14702 | F: drivers/usb/usbip/ |
14694 | F: tools/usb/usbip/ | 14703 | F: tools/usb/usbip/ |
14704 | F: tools/testing/selftests/drivers/usb/usbip/ | ||
14695 | 14705 | ||
14696 | USB PEGASUS DRIVER | 14706 | USB PEGASUS DRIVER |
14697 | M: Petko Manolov <petkan@nucleusys.com> | 14707 | M: Petko Manolov <petkan@nucleusys.com> |
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 8d21b9825d71..fce9f2ca0570 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig | |||
@@ -202,8 +202,7 @@ config I2C_CHT_WC | |||
202 | 202 | ||
203 | Note this controller is hooked up to a TI bq24292i charger-IC, | 203 | Note this controller is hooked up to a TI bq24292i charger-IC, |
204 | combined with a FUSB302 Type-C port-controller as such it is advised | 204 | combined with a FUSB302 Type-C port-controller as such it is advised |
205 | to also select CONFIG_CHARGER_BQ24190=m and CONFIG_TYPEC_FUSB302=m | 205 | to also select CONFIG_TYPEC_FUSB302=m. |
206 | (the fusb302 driver currently is in drivers/staging). | ||
207 | 206 | ||
208 | config I2C_NFORCE2 | 207 | config I2C_NFORCE2 |
209 | tristate "Nvidia nForce2, nForce3 and nForce4" | 208 | tristate "Nvidia nForce2, nForce3 and nForce4" |
diff --git a/drivers/nfc/pn533/usb.c b/drivers/nfc/pn533/usb.c index e153e8b64bb8..d5553c47014f 100644 --- a/drivers/nfc/pn533/usb.c +++ b/drivers/nfc/pn533/usb.c | |||
@@ -62,6 +62,9 @@ struct pn533_usb_phy { | |||
62 | struct urb *out_urb; | 62 | struct urb *out_urb; |
63 | struct urb *in_urb; | 63 | struct urb *in_urb; |
64 | 64 | ||
65 | struct urb *ack_urb; | ||
66 | u8 *ack_buffer; | ||
67 | |||
65 | struct pn533 *priv; | 68 | struct pn533 *priv; |
66 | }; | 69 | }; |
67 | 70 | ||
@@ -150,13 +153,16 @@ static int pn533_usb_send_ack(struct pn533 *dev, gfp_t flags) | |||
150 | struct pn533_usb_phy *phy = dev->phy; | 153 | struct pn533_usb_phy *phy = dev->phy; |
151 | static const u8 ack[6] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00}; | 154 | static const u8 ack[6] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00}; |
152 | /* spec 7.1.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */ | 155 | /* spec 7.1.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */ |
153 | int rc; | ||
154 | 156 | ||
155 | phy->out_urb->transfer_buffer = (u8 *)ack; | 157 | if (!phy->ack_buffer) { |
156 | phy->out_urb->transfer_buffer_length = sizeof(ack); | 158 | phy->ack_buffer = kmemdup(ack, sizeof(ack), flags); |
157 | rc = usb_submit_urb(phy->out_urb, flags); | 159 | if (!phy->ack_buffer) |
160 | return -ENOMEM; | ||
161 | } | ||
158 | 162 | ||
159 | return rc; | 163 | phy->ack_urb->transfer_buffer = phy->ack_buffer; |
164 | phy->ack_urb->transfer_buffer_length = sizeof(ack); | ||
165 | return usb_submit_urb(phy->ack_urb, flags); | ||
160 | } | 166 | } |
161 | 167 | ||
162 | static int pn533_usb_send_frame(struct pn533 *dev, | 168 | static int pn533_usb_send_frame(struct pn533 *dev, |
@@ -375,26 +381,31 @@ static int pn533_acr122_poweron_rdr(struct pn533_usb_phy *phy) | |||
375 | /* Power on th reader (CCID cmd) */ | 381 | /* Power on th reader (CCID cmd) */ |
376 | u8 cmd[10] = {PN533_ACR122_PC_TO_RDR_ICCPOWERON, | 382 | u8 cmd[10] = {PN533_ACR122_PC_TO_RDR_ICCPOWERON, |
377 | 0, 0, 0, 0, 0, 0, 3, 0, 0}; | 383 | 0, 0, 0, 0, 0, 0, 3, 0, 0}; |
384 | char *buffer; | ||
385 | int transferred; | ||
378 | int rc; | 386 | int rc; |
379 | void *cntx; | 387 | void *cntx; |
380 | struct pn533_acr122_poweron_rdr_arg arg; | 388 | struct pn533_acr122_poweron_rdr_arg arg; |
381 | 389 | ||
382 | dev_dbg(&phy->udev->dev, "%s\n", __func__); | 390 | dev_dbg(&phy->udev->dev, "%s\n", __func__); |
383 | 391 | ||
392 | buffer = kmemdup(cmd, sizeof(cmd), GFP_KERNEL); | ||
393 | if (!buffer) | ||
394 | return -ENOMEM; | ||
395 | |||
384 | init_completion(&arg.done); | 396 | init_completion(&arg.done); |
385 | cntx = phy->in_urb->context; /* backup context */ | 397 | cntx = phy->in_urb->context; /* backup context */ |
386 | 398 | ||
387 | phy->in_urb->complete = pn533_acr122_poweron_rdr_resp; | 399 | phy->in_urb->complete = pn533_acr122_poweron_rdr_resp; |
388 | phy->in_urb->context = &arg; | 400 | phy->in_urb->context = &arg; |
389 | 401 | ||
390 | phy->out_urb->transfer_buffer = cmd; | ||
391 | phy->out_urb->transfer_buffer_length = sizeof(cmd); | ||
392 | |||
393 | print_hex_dump_debug("ACR122 TX: ", DUMP_PREFIX_NONE, 16, 1, | 402 | print_hex_dump_debug("ACR122 TX: ", DUMP_PREFIX_NONE, 16, 1, |
394 | cmd, sizeof(cmd), false); | 403 | cmd, sizeof(cmd), false); |
395 | 404 | ||
396 | rc = usb_submit_urb(phy->out_urb, GFP_KERNEL); | 405 | rc = usb_bulk_msg(phy->udev, phy->out_urb->pipe, buffer, sizeof(cmd), |
397 | if (rc) { | 406 | &transferred, 0); |
407 | kfree(buffer); | ||
408 | if (rc || (transferred != sizeof(cmd))) { | ||
398 | nfc_err(&phy->udev->dev, | 409 | nfc_err(&phy->udev->dev, |
399 | "Reader power on cmd error %d\n", rc); | 410 | "Reader power on cmd error %d\n", rc); |
400 | return rc; | 411 | return rc; |
@@ -490,8 +501,9 @@ static int pn533_usb_probe(struct usb_interface *interface, | |||
490 | 501 | ||
491 | phy->in_urb = usb_alloc_urb(0, GFP_KERNEL); | 502 | phy->in_urb = usb_alloc_urb(0, GFP_KERNEL); |
492 | phy->out_urb = usb_alloc_urb(0, GFP_KERNEL); | 503 | phy->out_urb = usb_alloc_urb(0, GFP_KERNEL); |
504 | phy->ack_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
493 | 505 | ||
494 | if (!phy->in_urb || !phy->out_urb) | 506 | if (!phy->in_urb || !phy->out_urb || !phy->ack_urb) |
495 | goto error; | 507 | goto error; |
496 | 508 | ||
497 | usb_fill_bulk_urb(phy->in_urb, phy->udev, | 509 | usb_fill_bulk_urb(phy->in_urb, phy->udev, |
@@ -501,7 +513,9 @@ static int pn533_usb_probe(struct usb_interface *interface, | |||
501 | usb_fill_bulk_urb(phy->out_urb, phy->udev, | 513 | usb_fill_bulk_urb(phy->out_urb, phy->udev, |
502 | usb_sndbulkpipe(phy->udev, out_endpoint), | 514 | usb_sndbulkpipe(phy->udev, out_endpoint), |
503 | NULL, 0, pn533_send_complete, phy); | 515 | NULL, 0, pn533_send_complete, phy); |
504 | 516 | usb_fill_bulk_urb(phy->ack_urb, phy->udev, | |
517 | usb_sndbulkpipe(phy->udev, out_endpoint), | ||
518 | NULL, 0, pn533_send_complete, phy); | ||
505 | 519 | ||
506 | switch (id->driver_info) { | 520 | switch (id->driver_info) { |
507 | case PN533_DEVICE_STD: | 521 | case PN533_DEVICE_STD: |
@@ -554,6 +568,7 @@ static int pn533_usb_probe(struct usb_interface *interface, | |||
554 | error: | 568 | error: |
555 | usb_free_urb(phy->in_urb); | 569 | usb_free_urb(phy->in_urb); |
556 | usb_free_urb(phy->out_urb); | 570 | usb_free_urb(phy->out_urb); |
571 | usb_free_urb(phy->ack_urb); | ||
557 | usb_put_dev(phy->udev); | 572 | usb_put_dev(phy->udev); |
558 | kfree(in_buf); | 573 | kfree(in_buf); |
559 | 574 | ||
@@ -573,10 +588,13 @@ static void pn533_usb_disconnect(struct usb_interface *interface) | |||
573 | 588 | ||
574 | usb_kill_urb(phy->in_urb); | 589 | usb_kill_urb(phy->in_urb); |
575 | usb_kill_urb(phy->out_urb); | 590 | usb_kill_urb(phy->out_urb); |
591 | usb_kill_urb(phy->ack_urb); | ||
576 | 592 | ||
577 | kfree(phy->in_urb->transfer_buffer); | 593 | kfree(phy->in_urb->transfer_buffer); |
578 | usb_free_urb(phy->in_urb); | 594 | usb_free_urb(phy->in_urb); |
579 | usb_free_urb(phy->out_urb); | 595 | usb_free_urb(phy->out_urb); |
596 | usb_free_urb(phy->ack_urb); | ||
597 | kfree(phy->ack_buffer); | ||
580 | 598 | ||
581 | nfc_info(&interface->dev, "NXP PN533 NFC device disconnected\n"); | 599 | nfc_info(&interface->dev, "NXP PN533 NFC device disconnected\n"); |
582 | } | 600 | } |
diff --git a/drivers/phy/mediatek/Kconfig b/drivers/phy/mediatek/Kconfig index 88ab4e25e34f..8857d00b3c65 100644 --- a/drivers/phy/mediatek/Kconfig +++ b/drivers/phy/mediatek/Kconfig | |||
@@ -12,3 +12,12 @@ config PHY_MTK_TPHY | |||
12 | different banks layout, the T-PHY with shared banks between | 12 | different banks layout, the T-PHY with shared banks between |
13 | multi-ports is first version, otherwise is second veriosn, | 13 | multi-ports is first version, otherwise is second veriosn, |
14 | so you can easily distinguish them by banks layout. | 14 | so you can easily distinguish them by banks layout. |
15 | |||
16 | config PHY_MTK_XSPHY | ||
17 | tristate "MediaTek XS-PHY Driver" | ||
18 | depends on ARCH_MEDIATEK && OF | ||
19 | select GENERIC_PHY | ||
20 | help | ||
21 | Enable this to support the SuperSpeedPlus XS-PHY transceiver for | ||
22 | USB3.1 GEN2 controllers on MediaTek chips. The driver supports | ||
23 | multiple USB2.0, USB3.1 GEN2 ports. | ||
diff --git a/drivers/phy/mediatek/Makefile b/drivers/phy/mediatek/Makefile index 763a92eefa00..e5074b607d3d 100644 --- a/drivers/phy/mediatek/Makefile +++ b/drivers/phy/mediatek/Makefile | |||
@@ -3,3 +3,4 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_PHY_MTK_TPHY) += phy-mtk-tphy.o | 5 | obj-$(CONFIG_PHY_MTK_TPHY) += phy-mtk-tphy.o |
6 | obj-$(CONFIG_PHY_MTK_XSPHY) += phy-mtk-xsphy.o | ||
diff --git a/drivers/phy/mediatek/phy-mtk-xsphy.c b/drivers/phy/mediatek/phy-mtk-xsphy.c new file mode 100644 index 000000000000..020cd0227397 --- /dev/null +++ b/drivers/phy/mediatek/phy-mtk-xsphy.c | |||
@@ -0,0 +1,600 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * MediaTek USB3.1 gen2 xsphy Driver | ||
4 | * | ||
5 | * Copyright (c) 2018 MediaTek Inc. | ||
6 | * Author: Chunfeng Yun <chunfeng.yun@mediatek.com> | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include <dt-bindings/phy/phy.h> | ||
11 | #include <linux/clk.h> | ||
12 | #include <linux/delay.h> | ||
13 | #include <linux/io.h> | ||
14 | #include <linux/iopoll.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/of_address.h> | ||
17 | #include <linux/phy/phy.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | |||
20 | /* u2 phy banks */ | ||
21 | #define SSUSB_SIFSLV_MISC 0x000 | ||
22 | #define SSUSB_SIFSLV_U2FREQ 0x100 | ||
23 | #define SSUSB_SIFSLV_U2PHY_COM 0x300 | ||
24 | |||
25 | /* u3 phy shared banks */ | ||
26 | #define SSPXTP_SIFSLV_DIG_GLB 0x000 | ||
27 | #define SSPXTP_SIFSLV_PHYA_GLB 0x100 | ||
28 | |||
29 | /* u3 phy banks */ | ||
30 | #define SSPXTP_SIFSLV_DIG_LN_TOP 0x000 | ||
31 | #define SSPXTP_SIFSLV_DIG_LN_TX0 0x100 | ||
32 | #define SSPXTP_SIFSLV_DIG_LN_RX0 0x200 | ||
33 | #define SSPXTP_SIFSLV_DIG_LN_DAIF 0x300 | ||
34 | #define SSPXTP_SIFSLV_PHYA_LN 0x400 | ||
35 | |||
36 | #define XSP_U2FREQ_FMCR0 ((SSUSB_SIFSLV_U2FREQ) + 0x00) | ||
37 | #define P2F_RG_FREQDET_EN BIT(24) | ||
38 | #define P2F_RG_CYCLECNT GENMASK(23, 0) | ||
39 | #define P2F_RG_CYCLECNT_VAL(x) ((P2F_RG_CYCLECNT) & (x)) | ||
40 | |||
41 | #define XSP_U2FREQ_MMONR0 ((SSUSB_SIFSLV_U2FREQ) + 0x0c) | ||
42 | |||
43 | #define XSP_U2FREQ_FMMONR1 ((SSUSB_SIFSLV_U2FREQ) + 0x10) | ||
44 | #define P2F_RG_FRCK_EN BIT(8) | ||
45 | #define P2F_USB_FM_VALID BIT(0) | ||
46 | |||
47 | #define XSP_USBPHYACR0 ((SSUSB_SIFSLV_U2PHY_COM) + 0x00) | ||
48 | #define P2A0_RG_INTR_EN BIT(5) | ||
49 | |||
50 | #define XSP_USBPHYACR1 ((SSUSB_SIFSLV_U2PHY_COM) + 0x04) | ||
51 | #define P2A1_RG_INTR_CAL GENMASK(23, 19) | ||
52 | #define P2A1_RG_INTR_CAL_VAL(x) ((0x1f & (x)) << 19) | ||
53 | #define P2A1_RG_VRT_SEL GENMASK(14, 12) | ||
54 | #define P2A1_RG_VRT_SEL_VAL(x) ((0x7 & (x)) << 12) | ||
55 | #define P2A1_RG_TERM_SEL GENMASK(10, 8) | ||
56 | #define P2A1_RG_TERM_SEL_VAL(x) ((0x7 & (x)) << 8) | ||
57 | |||
58 | #define XSP_USBPHYACR5 ((SSUSB_SIFSLV_U2PHY_COM) + 0x014) | ||
59 | #define P2A5_RG_HSTX_SRCAL_EN BIT(15) | ||
60 | #define P2A5_RG_HSTX_SRCTRL GENMASK(14, 12) | ||
61 | #define P2A5_RG_HSTX_SRCTRL_VAL(x) ((0x7 & (x)) << 12) | ||
62 | |||
63 | #define XSP_USBPHYACR6 ((SSUSB_SIFSLV_U2PHY_COM) + 0x018) | ||
64 | #define P2A6_RG_BC11_SW_EN BIT(23) | ||
65 | #define P2A6_RG_OTG_VBUSCMP_EN BIT(20) | ||
66 | |||
67 | #define XSP_U2PHYDTM1 ((SSUSB_SIFSLV_U2PHY_COM) + 0x06C) | ||
68 | #define P2D_FORCE_IDDIG BIT(9) | ||
69 | #define P2D_RG_VBUSVALID BIT(5) | ||
70 | #define P2D_RG_SESSEND BIT(4) | ||
71 | #define P2D_RG_AVALID BIT(2) | ||
72 | #define P2D_RG_IDDIG BIT(1) | ||
73 | |||
74 | #define SSPXTP_PHYA_GLB_00 ((SSPXTP_SIFSLV_PHYA_GLB) + 0x00) | ||
75 | #define RG_XTP_GLB_BIAS_INTR_CTRL GENMASK(21, 16) | ||
76 | #define RG_XTP_GLB_BIAS_INTR_CTRL_VAL(x) ((0x3f & (x)) << 16) | ||
77 | |||
78 | #define SSPXTP_PHYA_LN_04 ((SSPXTP_SIFSLV_PHYA_LN) + 0x04) | ||
79 | #define RG_XTP_LN0_TX_IMPSEL GENMASK(4, 0) | ||
80 | #define RG_XTP_LN0_TX_IMPSEL_VAL(x) (0x1f & (x)) | ||
81 | |||
82 | #define SSPXTP_PHYA_LN_14 ((SSPXTP_SIFSLV_PHYA_LN) + 0x014) | ||
83 | #define RG_XTP_LN0_RX_IMPSEL GENMASK(4, 0) | ||
84 | #define RG_XTP_LN0_RX_IMPSEL_VAL(x) (0x1f & (x)) | ||
85 | |||
86 | #define XSP_REF_CLK 26 /* MHZ */ | ||
87 | #define XSP_SLEW_RATE_COEF 17 | ||
88 | #define XSP_SR_COEF_DIVISOR 1000 | ||
89 | #define XSP_FM_DET_CYCLE_CNT 1024 | ||
90 | |||
91 | struct xsphy_instance { | ||
92 | struct phy *phy; | ||
93 | void __iomem *port_base; | ||
94 | struct clk *ref_clk; /* reference clock of anolog phy */ | ||
95 | u32 index; | ||
96 | u32 type; | ||
97 | /* only for HQA test */ | ||
98 | int efuse_intr; | ||
99 | int efuse_tx_imp; | ||
100 | int efuse_rx_imp; | ||
101 | /* u2 eye diagram */ | ||
102 | int eye_src; | ||
103 | int eye_vrt; | ||
104 | int eye_term; | ||
105 | }; | ||
106 | |||
107 | struct mtk_xsphy { | ||
108 | struct device *dev; | ||
109 | void __iomem *glb_base; /* only shared u3 sif */ | ||
110 | struct xsphy_instance **phys; | ||
111 | int nphys; | ||
112 | int src_ref_clk; /* MHZ, reference clock for slew rate calibrate */ | ||
113 | int src_coef; /* coefficient for slew rate calibrate */ | ||
114 | }; | ||
115 | |||
116 | static void u2_phy_slew_rate_calibrate(struct mtk_xsphy *xsphy, | ||
117 | struct xsphy_instance *inst) | ||
118 | { | ||
119 | void __iomem *pbase = inst->port_base; | ||
120 | int calib_val; | ||
121 | int fm_out; | ||
122 | u32 tmp; | ||
123 | |||
124 | /* use force value */ | ||
125 | if (inst->eye_src) | ||
126 | return; | ||
127 | |||
128 | /* enable USB ring oscillator */ | ||
129 | tmp = readl(pbase + XSP_USBPHYACR5); | ||
130 | tmp |= P2A5_RG_HSTX_SRCAL_EN; | ||
131 | writel(tmp, pbase + XSP_USBPHYACR5); | ||
132 | udelay(1); /* wait clock stable */ | ||
133 | |||
134 | /* enable free run clock */ | ||
135 | tmp = readl(pbase + XSP_U2FREQ_FMMONR1); | ||
136 | tmp |= P2F_RG_FRCK_EN; | ||
137 | writel(tmp, pbase + XSP_U2FREQ_FMMONR1); | ||
138 | |||
139 | /* set cycle count as 1024 */ | ||
140 | tmp = readl(pbase + XSP_U2FREQ_FMCR0); | ||
141 | tmp &= ~(P2F_RG_CYCLECNT); | ||
142 | tmp |= P2F_RG_CYCLECNT_VAL(XSP_FM_DET_CYCLE_CNT); | ||
143 | writel(tmp, pbase + XSP_U2FREQ_FMCR0); | ||
144 | |||
145 | /* enable frequency meter */ | ||
146 | tmp = readl(pbase + XSP_U2FREQ_FMCR0); | ||
147 | tmp |= P2F_RG_FREQDET_EN; | ||
148 | writel(tmp, pbase + XSP_U2FREQ_FMCR0); | ||
149 | |||
150 | /* ignore return value */ | ||
151 | readl_poll_timeout(pbase + XSP_U2FREQ_FMMONR1, tmp, | ||
152 | (tmp & P2F_USB_FM_VALID), 10, 200); | ||
153 | |||
154 | fm_out = readl(pbase + XSP_U2FREQ_MMONR0); | ||
155 | |||
156 | /* disable frequency meter */ | ||
157 | tmp = readl(pbase + XSP_U2FREQ_FMCR0); | ||
158 | tmp &= ~P2F_RG_FREQDET_EN; | ||
159 | writel(tmp, pbase + XSP_U2FREQ_FMCR0); | ||
160 | |||
161 | /* disable free run clock */ | ||
162 | tmp = readl(pbase + XSP_U2FREQ_FMMONR1); | ||
163 | tmp &= ~P2F_RG_FRCK_EN; | ||
164 | writel(tmp, pbase + XSP_U2FREQ_FMMONR1); | ||
165 | |||
166 | if (fm_out) { | ||
167 | /* (1024 / FM_OUT) x reference clock frequency x coefficient */ | ||
168 | tmp = xsphy->src_ref_clk * xsphy->src_coef; | ||
169 | tmp = (tmp * XSP_FM_DET_CYCLE_CNT) / fm_out; | ||
170 | calib_val = DIV_ROUND_CLOSEST(tmp, XSP_SR_COEF_DIVISOR); | ||
171 | } else { | ||
172 | /* if FM detection fail, set default value */ | ||
173 | calib_val = 3; | ||
174 | } | ||
175 | dev_dbg(xsphy->dev, "phy.%d, fm_out:%d, calib:%d (clk:%d, coef:%d)\n", | ||
176 | inst->index, fm_out, calib_val, | ||
177 | xsphy->src_ref_clk, xsphy->src_coef); | ||
178 | |||
179 | /* set HS slew rate */ | ||
180 | tmp = readl(pbase + XSP_USBPHYACR5); | ||
181 | tmp &= ~P2A5_RG_HSTX_SRCTRL; | ||
182 | tmp |= P2A5_RG_HSTX_SRCTRL_VAL(calib_val); | ||
183 | writel(tmp, pbase + XSP_USBPHYACR5); | ||
184 | |||
185 | /* disable USB ring oscillator */ | ||
186 | tmp = readl(pbase + XSP_USBPHYACR5); | ||
187 | tmp &= ~P2A5_RG_HSTX_SRCAL_EN; | ||
188 | writel(tmp, pbase + XSP_USBPHYACR5); | ||
189 | } | ||
190 | |||
191 | static void u2_phy_instance_init(struct mtk_xsphy *xsphy, | ||
192 | struct xsphy_instance *inst) | ||
193 | { | ||
194 | void __iomem *pbase = inst->port_base; | ||
195 | u32 tmp; | ||
196 | |||
197 | /* DP/DM BC1.1 path Disable */ | ||
198 | tmp = readl(pbase + XSP_USBPHYACR6); | ||
199 | tmp &= ~P2A6_RG_BC11_SW_EN; | ||
200 | writel(tmp, pbase + XSP_USBPHYACR6); | ||
201 | |||
202 | tmp = readl(pbase + XSP_USBPHYACR0); | ||
203 | tmp |= P2A0_RG_INTR_EN; | ||
204 | writel(tmp, pbase + XSP_USBPHYACR0); | ||
205 | } | ||
206 | |||
207 | static void u2_phy_instance_power_on(struct mtk_xsphy *xsphy, | ||
208 | struct xsphy_instance *inst) | ||
209 | { | ||
210 | void __iomem *pbase = inst->port_base; | ||
211 | u32 index = inst->index; | ||
212 | u32 tmp; | ||
213 | |||
214 | tmp = readl(pbase + XSP_USBPHYACR6); | ||
215 | tmp |= P2A6_RG_OTG_VBUSCMP_EN; | ||
216 | writel(tmp, pbase + XSP_USBPHYACR6); | ||
217 | |||
218 | tmp = readl(pbase + XSP_U2PHYDTM1); | ||
219 | tmp |= P2D_RG_VBUSVALID | P2D_RG_AVALID; | ||
220 | tmp &= ~P2D_RG_SESSEND; | ||
221 | writel(tmp, pbase + XSP_U2PHYDTM1); | ||
222 | |||
223 | dev_dbg(xsphy->dev, "%s(%d)\n", __func__, index); | ||
224 | } | ||
225 | |||
226 | static void u2_phy_instance_power_off(struct mtk_xsphy *xsphy, | ||
227 | struct xsphy_instance *inst) | ||
228 | { | ||
229 | void __iomem *pbase = inst->port_base; | ||
230 | u32 index = inst->index; | ||
231 | u32 tmp; | ||
232 | |||
233 | tmp = readl(pbase + XSP_USBPHYACR6); | ||
234 | tmp &= ~P2A6_RG_OTG_VBUSCMP_EN; | ||
235 | writel(tmp, pbase + XSP_USBPHYACR6); | ||
236 | |||
237 | tmp = readl(pbase + XSP_U2PHYDTM1); | ||
238 | tmp &= ~(P2D_RG_VBUSVALID | P2D_RG_AVALID); | ||
239 | tmp |= P2D_RG_SESSEND; | ||
240 | writel(tmp, pbase + XSP_U2PHYDTM1); | ||
241 | |||
242 | dev_dbg(xsphy->dev, "%s(%d)\n", __func__, index); | ||
243 | } | ||
244 | |||
245 | static void u2_phy_instance_set_mode(struct mtk_xsphy *xsphy, | ||
246 | struct xsphy_instance *inst, | ||
247 | enum phy_mode mode) | ||
248 | { | ||
249 | u32 tmp; | ||
250 | |||
251 | tmp = readl(inst->port_base + XSP_U2PHYDTM1); | ||
252 | switch (mode) { | ||
253 | case PHY_MODE_USB_DEVICE: | ||
254 | tmp |= P2D_FORCE_IDDIG | P2D_RG_IDDIG; | ||
255 | break; | ||
256 | case PHY_MODE_USB_HOST: | ||
257 | tmp |= P2D_FORCE_IDDIG; | ||
258 | tmp &= ~P2D_RG_IDDIG; | ||
259 | break; | ||
260 | case PHY_MODE_USB_OTG: | ||
261 | tmp &= ~(P2D_FORCE_IDDIG | P2D_RG_IDDIG); | ||
262 | break; | ||
263 | default: | ||
264 | return; | ||
265 | } | ||
266 | writel(tmp, inst->port_base + XSP_U2PHYDTM1); | ||
267 | } | ||
268 | |||
269 | static void phy_parse_property(struct mtk_xsphy *xsphy, | ||
270 | struct xsphy_instance *inst) | ||
271 | { | ||
272 | struct device *dev = &inst->phy->dev; | ||
273 | |||
274 | switch (inst->type) { | ||
275 | case PHY_TYPE_USB2: | ||
276 | device_property_read_u32(dev, "mediatek,efuse-intr", | ||
277 | &inst->efuse_intr); | ||
278 | device_property_read_u32(dev, "mediatek,eye-src", | ||
279 | &inst->eye_src); | ||
280 | device_property_read_u32(dev, "mediatek,eye-vrt", | ||
281 | &inst->eye_vrt); | ||
282 | device_property_read_u32(dev, "mediatek,eye-term", | ||
283 | &inst->eye_term); | ||
284 | dev_dbg(dev, "intr:%d, src:%d, vrt:%d, term:%d\n", | ||
285 | inst->efuse_intr, inst->eye_src, | ||
286 | inst->eye_vrt, inst->eye_term); | ||
287 | break; | ||
288 | case PHY_TYPE_USB3: | ||
289 | device_property_read_u32(dev, "mediatek,efuse-intr", | ||
290 | &inst->efuse_intr); | ||
291 | device_property_read_u32(dev, "mediatek,efuse-tx-imp", | ||
292 | &inst->efuse_tx_imp); | ||
293 | device_property_read_u32(dev, "mediatek,efuse-rx-imp", | ||
294 | &inst->efuse_rx_imp); | ||
295 | dev_dbg(dev, "intr:%d, tx-imp:%d, rx-imp:%d\n", | ||
296 | inst->efuse_intr, inst->efuse_tx_imp, | ||
297 | inst->efuse_rx_imp); | ||
298 | break; | ||
299 | default: | ||
300 | dev_err(xsphy->dev, "incompatible phy type\n"); | ||
301 | return; | ||
302 | } | ||
303 | } | ||
304 | |||
305 | static void u2_phy_props_set(struct mtk_xsphy *xsphy, | ||
306 | struct xsphy_instance *inst) | ||
307 | { | ||
308 | void __iomem *pbase = inst->port_base; | ||
309 | u32 tmp; | ||
310 | |||
311 | if (inst->efuse_intr) { | ||
312 | tmp = readl(pbase + XSP_USBPHYACR1); | ||
313 | tmp &= ~P2A1_RG_INTR_CAL; | ||
314 | tmp |= P2A1_RG_INTR_CAL_VAL(inst->efuse_intr); | ||
315 | writel(tmp, pbase + XSP_USBPHYACR1); | ||
316 | } | ||
317 | |||
318 | if (inst->eye_src) { | ||
319 | tmp = readl(pbase + XSP_USBPHYACR5); | ||
320 | tmp &= ~P2A5_RG_HSTX_SRCTRL; | ||
321 | tmp |= P2A5_RG_HSTX_SRCTRL_VAL(inst->eye_src); | ||
322 | writel(tmp, pbase + XSP_USBPHYACR5); | ||
323 | } | ||
324 | |||
325 | if (inst->eye_vrt) { | ||
326 | tmp = readl(pbase + XSP_USBPHYACR1); | ||
327 | tmp &= ~P2A1_RG_VRT_SEL; | ||
328 | tmp |= P2A1_RG_VRT_SEL_VAL(inst->eye_vrt); | ||
329 | writel(tmp, pbase + XSP_USBPHYACR1); | ||
330 | } | ||
331 | |||
332 | if (inst->eye_term) { | ||
333 | tmp = readl(pbase + XSP_USBPHYACR1); | ||
334 | tmp &= ~P2A1_RG_TERM_SEL; | ||
335 | tmp |= P2A1_RG_TERM_SEL_VAL(inst->eye_term); | ||
336 | writel(tmp, pbase + XSP_USBPHYACR1); | ||
337 | } | ||
338 | } | ||
339 | |||
340 | static void u3_phy_props_set(struct mtk_xsphy *xsphy, | ||
341 | struct xsphy_instance *inst) | ||
342 | { | ||
343 | void __iomem *pbase = inst->port_base; | ||
344 | u32 tmp; | ||
345 | |||
346 | if (inst->efuse_intr) { | ||
347 | tmp = readl(xsphy->glb_base + SSPXTP_PHYA_GLB_00); | ||
348 | tmp &= ~RG_XTP_GLB_BIAS_INTR_CTRL; | ||
349 | tmp |= RG_XTP_GLB_BIAS_INTR_CTRL_VAL(inst->efuse_intr); | ||
350 | writel(tmp, xsphy->glb_base + SSPXTP_PHYA_GLB_00); | ||
351 | } | ||
352 | |||
353 | if (inst->efuse_tx_imp) { | ||
354 | tmp = readl(pbase + SSPXTP_PHYA_LN_04); | ||
355 | tmp &= ~RG_XTP_LN0_TX_IMPSEL; | ||
356 | tmp |= RG_XTP_LN0_TX_IMPSEL_VAL(inst->efuse_tx_imp); | ||
357 | writel(tmp, pbase + SSPXTP_PHYA_LN_04); | ||
358 | } | ||
359 | |||
360 | if (inst->efuse_rx_imp) { | ||
361 | tmp = readl(pbase + SSPXTP_PHYA_LN_14); | ||
362 | tmp &= ~RG_XTP_LN0_RX_IMPSEL; | ||
363 | tmp |= RG_XTP_LN0_RX_IMPSEL_VAL(inst->efuse_rx_imp); | ||
364 | writel(tmp, pbase + SSPXTP_PHYA_LN_14); | ||
365 | } | ||
366 | } | ||
367 | |||
368 | static int mtk_phy_init(struct phy *phy) | ||
369 | { | ||
370 | struct xsphy_instance *inst = phy_get_drvdata(phy); | ||
371 | struct mtk_xsphy *xsphy = dev_get_drvdata(phy->dev.parent); | ||
372 | int ret; | ||
373 | |||
374 | ret = clk_prepare_enable(inst->ref_clk); | ||
375 | if (ret) { | ||
376 | dev_err(xsphy->dev, "failed to enable ref_clk\n"); | ||
377 | return ret; | ||
378 | } | ||
379 | |||
380 | switch (inst->type) { | ||
381 | case PHY_TYPE_USB2: | ||
382 | u2_phy_instance_init(xsphy, inst); | ||
383 | u2_phy_props_set(xsphy, inst); | ||
384 | break; | ||
385 | case PHY_TYPE_USB3: | ||
386 | u3_phy_props_set(xsphy, inst); | ||
387 | break; | ||
388 | default: | ||
389 | dev_err(xsphy->dev, "incompatible phy type\n"); | ||
390 | clk_disable_unprepare(inst->ref_clk); | ||
391 | return -EINVAL; | ||
392 | } | ||
393 | |||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | static int mtk_phy_power_on(struct phy *phy) | ||
398 | { | ||
399 | struct xsphy_instance *inst = phy_get_drvdata(phy); | ||
400 | struct mtk_xsphy *xsphy = dev_get_drvdata(phy->dev.parent); | ||
401 | |||
402 | if (inst->type == PHY_TYPE_USB2) { | ||
403 | u2_phy_instance_power_on(xsphy, inst); | ||
404 | u2_phy_slew_rate_calibrate(xsphy, inst); | ||
405 | } | ||
406 | |||
407 | return 0; | ||
408 | } | ||
409 | |||
410 | static int mtk_phy_power_off(struct phy *phy) | ||
411 | { | ||
412 | struct xsphy_instance *inst = phy_get_drvdata(phy); | ||
413 | struct mtk_xsphy *xsphy = dev_get_drvdata(phy->dev.parent); | ||
414 | |||
415 | if (inst->type == PHY_TYPE_USB2) | ||
416 | u2_phy_instance_power_off(xsphy, inst); | ||
417 | |||
418 | return 0; | ||
419 | } | ||
420 | |||
421 | static int mtk_phy_exit(struct phy *phy) | ||
422 | { | ||
423 | struct xsphy_instance *inst = phy_get_drvdata(phy); | ||
424 | |||
425 | clk_disable_unprepare(inst->ref_clk); | ||
426 | return 0; | ||
427 | } | ||
428 | |||
429 | static int mtk_phy_set_mode(struct phy *phy, enum phy_mode mode) | ||
430 | { | ||
431 | struct xsphy_instance *inst = phy_get_drvdata(phy); | ||
432 | struct mtk_xsphy *xsphy = dev_get_drvdata(phy->dev.parent); | ||
433 | |||
434 | if (inst->type == PHY_TYPE_USB2) | ||
435 | u2_phy_instance_set_mode(xsphy, inst, mode); | ||
436 | |||
437 | return 0; | ||
438 | } | ||
439 | |||
440 | static struct phy *mtk_phy_xlate(struct device *dev, | ||
441 | struct of_phandle_args *args) | ||
442 | { | ||
443 | struct mtk_xsphy *xsphy = dev_get_drvdata(dev); | ||
444 | struct xsphy_instance *inst = NULL; | ||
445 | struct device_node *phy_np = args->np; | ||
446 | int index; | ||
447 | |||
448 | if (args->args_count != 1) { | ||
449 | dev_err(dev, "invalid number of cells in 'phy' property\n"); | ||
450 | return ERR_PTR(-EINVAL); | ||
451 | } | ||
452 | |||
453 | for (index = 0; index < xsphy->nphys; index++) | ||
454 | if (phy_np == xsphy->phys[index]->phy->dev.of_node) { | ||
455 | inst = xsphy->phys[index]; | ||
456 | break; | ||
457 | } | ||
458 | |||
459 | if (!inst) { | ||
460 | dev_err(dev, "failed to find appropriate phy\n"); | ||
461 | return ERR_PTR(-EINVAL); | ||
462 | } | ||
463 | |||
464 | inst->type = args->args[0]; | ||
465 | if (!(inst->type == PHY_TYPE_USB2 || | ||
466 | inst->type == PHY_TYPE_USB3)) { | ||
467 | dev_err(dev, "unsupported phy type: %d\n", inst->type); | ||
468 | return ERR_PTR(-EINVAL); | ||
469 | } | ||
470 | |||
471 | phy_parse_property(xsphy, inst); | ||
472 | |||
473 | return inst->phy; | ||
474 | } | ||
475 | |||
476 | static const struct phy_ops mtk_xsphy_ops = { | ||
477 | .init = mtk_phy_init, | ||
478 | .exit = mtk_phy_exit, | ||
479 | .power_on = mtk_phy_power_on, | ||
480 | .power_off = mtk_phy_power_off, | ||
481 | .set_mode = mtk_phy_set_mode, | ||
482 | .owner = THIS_MODULE, | ||
483 | }; | ||
484 | |||
485 | static const struct of_device_id mtk_xsphy_id_table[] = { | ||
486 | { .compatible = "mediatek,xsphy", }, | ||
487 | { }, | ||
488 | }; | ||
489 | MODULE_DEVICE_TABLE(of, mtk_xsphy_id_table); | ||
490 | |||
491 | static int mtk_xsphy_probe(struct platform_device *pdev) | ||
492 | { | ||
493 | struct device *dev = &pdev->dev; | ||
494 | struct device_node *np = dev->of_node; | ||
495 | struct device_node *child_np; | ||
496 | struct phy_provider *provider; | ||
497 | struct resource *glb_res; | ||
498 | struct mtk_xsphy *xsphy; | ||
499 | struct resource res; | ||
500 | int port, retval; | ||
501 | |||
502 | xsphy = devm_kzalloc(dev, sizeof(*xsphy), GFP_KERNEL); | ||
503 | if (!xsphy) | ||
504 | return -ENOMEM; | ||
505 | |||
506 | xsphy->nphys = of_get_child_count(np); | ||
507 | xsphy->phys = devm_kcalloc(dev, xsphy->nphys, | ||
508 | sizeof(*xsphy->phys), GFP_KERNEL); | ||
509 | if (!xsphy->phys) | ||
510 | return -ENOMEM; | ||
511 | |||
512 | xsphy->dev = dev; | ||
513 | platform_set_drvdata(pdev, xsphy); | ||
514 | |||
515 | glb_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
516 | /* optional, may not exist if no u3 phys */ | ||
517 | if (glb_res) { | ||
518 | /* get banks shared by multiple u3 phys */ | ||
519 | xsphy->glb_base = devm_ioremap_resource(dev, glb_res); | ||
520 | if (IS_ERR(xsphy->glb_base)) { | ||
521 | dev_err(dev, "failed to remap glb regs\n"); | ||
522 | return PTR_ERR(xsphy->glb_base); | ||
523 | } | ||
524 | } | ||
525 | |||
526 | xsphy->src_ref_clk = XSP_REF_CLK; | ||
527 | xsphy->src_coef = XSP_SLEW_RATE_COEF; | ||
528 | /* update parameters of slew rate calibrate if exist */ | ||
529 | device_property_read_u32(dev, "mediatek,src-ref-clk-mhz", | ||
530 | &xsphy->src_ref_clk); | ||
531 | device_property_read_u32(dev, "mediatek,src-coef", &xsphy->src_coef); | ||
532 | |||
533 | port = 0; | ||
534 | for_each_child_of_node(np, child_np) { | ||
535 | struct xsphy_instance *inst; | ||
536 | struct phy *phy; | ||
537 | |||
538 | inst = devm_kzalloc(dev, sizeof(*inst), GFP_KERNEL); | ||
539 | if (!inst) { | ||
540 | retval = -ENOMEM; | ||
541 | goto put_child; | ||
542 | } | ||
543 | |||
544 | xsphy->phys[port] = inst; | ||
545 | |||
546 | phy = devm_phy_create(dev, child_np, &mtk_xsphy_ops); | ||
547 | if (IS_ERR(phy)) { | ||
548 | dev_err(dev, "failed to create phy\n"); | ||
549 | retval = PTR_ERR(phy); | ||
550 | goto put_child; | ||
551 | } | ||
552 | |||
553 | retval = of_address_to_resource(child_np, 0, &res); | ||
554 | if (retval) { | ||
555 | dev_err(dev, "failed to get address resource(id-%d)\n", | ||
556 | port); | ||
557 | goto put_child; | ||
558 | } | ||
559 | |||
560 | inst->port_base = devm_ioremap_resource(&phy->dev, &res); | ||
561 | if (IS_ERR(inst->port_base)) { | ||
562 | dev_err(dev, "failed to remap phy regs\n"); | ||
563 | retval = PTR_ERR(inst->port_base); | ||
564 | goto put_child; | ||
565 | } | ||
566 | |||
567 | inst->phy = phy; | ||
568 | inst->index = port; | ||
569 | phy_set_drvdata(phy, inst); | ||
570 | port++; | ||
571 | |||
572 | inst->ref_clk = devm_clk_get(&phy->dev, "ref"); | ||
573 | if (IS_ERR(inst->ref_clk)) { | ||
574 | dev_err(dev, "failed to get ref_clk(id-%d)\n", port); | ||
575 | retval = PTR_ERR(inst->ref_clk); | ||
576 | goto put_child; | ||
577 | } | ||
578 | } | ||
579 | |||
580 | provider = devm_of_phy_provider_register(dev, mtk_phy_xlate); | ||
581 | return PTR_ERR_OR_ZERO(provider); | ||
582 | |||
583 | put_child: | ||
584 | of_node_put(child_np); | ||
585 | return retval; | ||
586 | } | ||
587 | |||
588 | static struct platform_driver mtk_xsphy_driver = { | ||
589 | .probe = mtk_xsphy_probe, | ||
590 | .driver = { | ||
591 | .name = "mtk-xsphy", | ||
592 | .of_match_table = mtk_xsphy_id_table, | ||
593 | }, | ||
594 | }; | ||
595 | |||
596 | module_platform_driver(mtk_xsphy_driver); | ||
597 | |||
598 | MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>"); | ||
599 | MODULE_DESCRIPTION("MediaTek USB XS-PHY driver"); | ||
600 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/phy/motorola/phy-mapphone-mdm6600.c b/drivers/phy/motorola/phy-mapphone-mdm6600.c index 5439dd90d0dd..23705e1a0023 100644 --- a/drivers/phy/motorola/phy-mapphone-mdm6600.c +++ b/drivers/phy/motorola/phy-mapphone-mdm6600.c | |||
@@ -19,6 +19,8 @@ | |||
19 | 19 | ||
20 | #define PHY_MDM6600_PHY_DELAY_MS 4000 /* PHY enable 2.2s to 3.5s */ | 20 | #define PHY_MDM6600_PHY_DELAY_MS 4000 /* PHY enable 2.2s to 3.5s */ |
21 | #define PHY_MDM6600_ENABLED_DELAY_MS 8000 /* 8s more total for MDM6600 */ | 21 | #define PHY_MDM6600_ENABLED_DELAY_MS 8000 /* 8s more total for MDM6600 */ |
22 | #define MDM6600_MODEM_IDLE_DELAY_MS 1000 /* modem after USB suspend */ | ||
23 | #define MDM6600_MODEM_WAKE_DELAY_MS 200 /* modem response after idle */ | ||
22 | 24 | ||
23 | enum phy_mdm6600_ctrl_lines { | 25 | enum phy_mdm6600_ctrl_lines { |
24 | PHY_MDM6600_ENABLE, /* USB PHY enable */ | 26 | PHY_MDM6600_ENABLE, /* USB PHY enable */ |
@@ -93,9 +95,11 @@ struct phy_mdm6600 { | |||
93 | struct gpio_descs *cmd_gpios; | 95 | struct gpio_descs *cmd_gpios; |
94 | struct delayed_work bootup_work; | 96 | struct delayed_work bootup_work; |
95 | struct delayed_work status_work; | 97 | struct delayed_work status_work; |
98 | struct delayed_work modem_wake_work; | ||
96 | struct completion ack; | 99 | struct completion ack; |
97 | bool enabled; /* mdm6600 phy enabled */ | 100 | bool enabled; /* mdm6600 phy enabled */ |
98 | bool running; /* mdm6600 boot done */ | 101 | bool running; /* mdm6600 boot done */ |
102 | bool awake; /* mdm6600 respnds on n_gsm */ | ||
99 | int status; | 103 | int status; |
100 | }; | 104 | }; |
101 | 105 | ||
@@ -446,6 +450,62 @@ static void phy_mdm6600_deferred_power_on(struct work_struct *work) | |||
446 | dev_err(ddata->dev, "Device not functional\n"); | 450 | dev_err(ddata->dev, "Device not functional\n"); |
447 | } | 451 | } |
448 | 452 | ||
453 | /* | ||
454 | * USB suspend puts mdm6600 into low power mode. For any n_gsm using apps, | ||
455 | * we need to keep the modem awake by kicking it's mode0 GPIO. This will | ||
456 | * keep the modem awake for about 1.2 seconds. When no n_gsm apps are using | ||
457 | * the modem, runtime PM auto mode can be enabled so modem can enter low | ||
458 | * power mode. | ||
459 | */ | ||
460 | static void phy_mdm6600_wake_modem(struct phy_mdm6600 *ddata) | ||
461 | { | ||
462 | struct gpio_desc *mode_gpio0; | ||
463 | |||
464 | mode_gpio0 = ddata->mode_gpios->desc[PHY_MDM6600_MODE0]; | ||
465 | gpiod_set_value_cansleep(mode_gpio0, 1); | ||
466 | usleep_range(5, 15); | ||
467 | gpiod_set_value_cansleep(mode_gpio0, 0); | ||
468 | if (ddata->awake) | ||
469 | usleep_range(5, 15); | ||
470 | else | ||
471 | msleep(MDM6600_MODEM_WAKE_DELAY_MS); | ||
472 | } | ||
473 | |||
474 | static void phy_mdm6600_modem_wake(struct work_struct *work) | ||
475 | { | ||
476 | struct phy_mdm6600 *ddata; | ||
477 | |||
478 | ddata = container_of(work, struct phy_mdm6600, modem_wake_work.work); | ||
479 | phy_mdm6600_wake_modem(ddata); | ||
480 | schedule_delayed_work(&ddata->modem_wake_work, | ||
481 | msecs_to_jiffies(MDM6600_MODEM_IDLE_DELAY_MS)); | ||
482 | } | ||
483 | |||
484 | static int __maybe_unused phy_mdm6600_runtime_suspend(struct device *dev) | ||
485 | { | ||
486 | struct phy_mdm6600 *ddata = dev_get_drvdata(dev); | ||
487 | |||
488 | cancel_delayed_work_sync(&ddata->modem_wake_work); | ||
489 | ddata->awake = false; | ||
490 | |||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | static int __maybe_unused phy_mdm6600_runtime_resume(struct device *dev) | ||
495 | { | ||
496 | struct phy_mdm6600 *ddata = dev_get_drvdata(dev); | ||
497 | |||
498 | phy_mdm6600_modem_wake(&ddata->modem_wake_work.work); | ||
499 | ddata->awake = true; | ||
500 | |||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | static const struct dev_pm_ops phy_mdm6600_pm_ops = { | ||
505 | SET_RUNTIME_PM_OPS(phy_mdm6600_runtime_suspend, | ||
506 | phy_mdm6600_runtime_resume, NULL) | ||
507 | }; | ||
508 | |||
449 | static const struct of_device_id phy_mdm6600_id_table[] = { | 509 | static const struct of_device_id phy_mdm6600_id_table[] = { |
450 | { .compatible = "motorola,mapphone-mdm6600", }, | 510 | { .compatible = "motorola,mapphone-mdm6600", }, |
451 | {}, | 511 | {}, |
@@ -464,6 +524,7 @@ static int phy_mdm6600_probe(struct platform_device *pdev) | |||
464 | INIT_DELAYED_WORK(&ddata->bootup_work, | 524 | INIT_DELAYED_WORK(&ddata->bootup_work, |
465 | phy_mdm6600_deferred_power_on); | 525 | phy_mdm6600_deferred_power_on); |
466 | INIT_DELAYED_WORK(&ddata->status_work, phy_mdm6600_status); | 526 | INIT_DELAYED_WORK(&ddata->status_work, phy_mdm6600_status); |
527 | INIT_DELAYED_WORK(&ddata->modem_wake_work, phy_mdm6600_modem_wake); | ||
467 | init_completion(&ddata->ack); | 528 | init_completion(&ddata->ack); |
468 | 529 | ||
469 | ddata->dev = &pdev->dev; | 530 | ddata->dev = &pdev->dev; |
@@ -500,6 +561,24 @@ static int phy_mdm6600_probe(struct platform_device *pdev) | |||
500 | */ | 561 | */ |
501 | msleep(PHY_MDM6600_PHY_DELAY_MS + 500); | 562 | msleep(PHY_MDM6600_PHY_DELAY_MS + 500); |
502 | 563 | ||
564 | /* | ||
565 | * Enable PM runtime only after PHY has been powered up properly. | ||
566 | * It is currently only needed after USB suspends mdm6600 and n_gsm | ||
567 | * needs to access the device. We don't want to do this earlier as | ||
568 | * gpio mode0 pin doubles as mdm6600 wake-up gpio. | ||
569 | */ | ||
570 | pm_runtime_use_autosuspend(ddata->dev); | ||
571 | pm_runtime_set_autosuspend_delay(ddata->dev, | ||
572 | MDM6600_MODEM_IDLE_DELAY_MS); | ||
573 | pm_runtime_enable(ddata->dev); | ||
574 | error = pm_runtime_get_sync(ddata->dev); | ||
575 | if (error < 0) { | ||
576 | dev_warn(ddata->dev, "failed to wake modem: %i\n", error); | ||
577 | pm_runtime_put_noidle(ddata->dev); | ||
578 | } | ||
579 | pm_runtime_mark_last_busy(ddata->dev); | ||
580 | pm_runtime_put_autosuspend(ddata->dev); | ||
581 | |||
503 | return 0; | 582 | return 0; |
504 | 583 | ||
505 | cleanup: | 584 | cleanup: |
@@ -512,6 +591,10 @@ static int phy_mdm6600_remove(struct platform_device *pdev) | |||
512 | struct phy_mdm6600 *ddata = platform_get_drvdata(pdev); | 591 | struct phy_mdm6600 *ddata = platform_get_drvdata(pdev); |
513 | struct gpio_desc *reset_gpio = ddata->ctrl_gpios[PHY_MDM6600_RESET]; | 592 | struct gpio_desc *reset_gpio = ddata->ctrl_gpios[PHY_MDM6600_RESET]; |
514 | 593 | ||
594 | pm_runtime_dont_use_autosuspend(ddata->dev); | ||
595 | pm_runtime_put_sync(ddata->dev); | ||
596 | pm_runtime_disable(ddata->dev); | ||
597 | |||
515 | if (!ddata->running) | 598 | if (!ddata->running) |
516 | wait_for_completion_timeout(&ddata->ack, | 599 | wait_for_completion_timeout(&ddata->ack, |
517 | msecs_to_jiffies(PHY_MDM6600_ENABLED_DELAY_MS)); | 600 | msecs_to_jiffies(PHY_MDM6600_ENABLED_DELAY_MS)); |
@@ -519,6 +602,7 @@ static int phy_mdm6600_remove(struct platform_device *pdev) | |||
519 | gpiod_set_value_cansleep(reset_gpio, 1); | 602 | gpiod_set_value_cansleep(reset_gpio, 1); |
520 | phy_mdm6600_device_power_off(ddata); | 603 | phy_mdm6600_device_power_off(ddata); |
521 | 604 | ||
605 | cancel_delayed_work_sync(&ddata->modem_wake_work); | ||
522 | cancel_delayed_work_sync(&ddata->bootup_work); | 606 | cancel_delayed_work_sync(&ddata->bootup_work); |
523 | cancel_delayed_work_sync(&ddata->status_work); | 607 | cancel_delayed_work_sync(&ddata->status_work); |
524 | 608 | ||
@@ -530,6 +614,7 @@ static struct platform_driver phy_mdm6600_driver = { | |||
530 | .remove = phy_mdm6600_remove, | 614 | .remove = phy_mdm6600_remove, |
531 | .driver = { | 615 | .driver = { |
532 | .name = "phy-mapphone-mdm6600", | 616 | .name = "phy-mapphone-mdm6600", |
617 | .pm = &phy_mdm6600_pm_ops, | ||
533 | .of_match_table = of_match_ptr(phy_mdm6600_id_table), | 618 | .of_match_table = of_match_ptr(phy_mdm6600_id_table), |
534 | }, | 619 | }, |
535 | }; | 620 | }; |
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 09ac8afb97ac..35fd38c5a4a1 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c | |||
@@ -153,6 +153,9 @@ int phy_pm_runtime_get(struct phy *phy) | |||
153 | { | 153 | { |
154 | int ret; | 154 | int ret; |
155 | 155 | ||
156 | if (!phy) | ||
157 | return 0; | ||
158 | |||
156 | if (!pm_runtime_enabled(&phy->dev)) | 159 | if (!pm_runtime_enabled(&phy->dev)) |
157 | return -ENOTSUPP; | 160 | return -ENOTSUPP; |
158 | 161 | ||
@@ -168,6 +171,9 @@ int phy_pm_runtime_get_sync(struct phy *phy) | |||
168 | { | 171 | { |
169 | int ret; | 172 | int ret; |
170 | 173 | ||
174 | if (!phy) | ||
175 | return 0; | ||
176 | |||
171 | if (!pm_runtime_enabled(&phy->dev)) | 177 | if (!pm_runtime_enabled(&phy->dev)) |
172 | return -ENOTSUPP; | 178 | return -ENOTSUPP; |
173 | 179 | ||
@@ -181,6 +187,9 @@ EXPORT_SYMBOL_GPL(phy_pm_runtime_get_sync); | |||
181 | 187 | ||
182 | int phy_pm_runtime_put(struct phy *phy) | 188 | int phy_pm_runtime_put(struct phy *phy) |
183 | { | 189 | { |
190 | if (!phy) | ||
191 | return 0; | ||
192 | |||
184 | if (!pm_runtime_enabled(&phy->dev)) | 193 | if (!pm_runtime_enabled(&phy->dev)) |
185 | return -ENOTSUPP; | 194 | return -ENOTSUPP; |
186 | 195 | ||
@@ -190,6 +199,9 @@ EXPORT_SYMBOL_GPL(phy_pm_runtime_put); | |||
190 | 199 | ||
191 | int phy_pm_runtime_put_sync(struct phy *phy) | 200 | int phy_pm_runtime_put_sync(struct phy *phy) |
192 | { | 201 | { |
202 | if (!phy) | ||
203 | return 0; | ||
204 | |||
193 | if (!pm_runtime_enabled(&phy->dev)) | 205 | if (!pm_runtime_enabled(&phy->dev)) |
194 | return -ENOTSUPP; | 206 | return -ENOTSUPP; |
195 | 207 | ||
@@ -199,6 +211,9 @@ EXPORT_SYMBOL_GPL(phy_pm_runtime_put_sync); | |||
199 | 211 | ||
200 | void phy_pm_runtime_allow(struct phy *phy) | 212 | void phy_pm_runtime_allow(struct phy *phy) |
201 | { | 213 | { |
214 | if (!phy) | ||
215 | return; | ||
216 | |||
202 | if (!pm_runtime_enabled(&phy->dev)) | 217 | if (!pm_runtime_enabled(&phy->dev)) |
203 | return; | 218 | return; |
204 | 219 | ||
@@ -208,6 +223,9 @@ EXPORT_SYMBOL_GPL(phy_pm_runtime_allow); | |||
208 | 223 | ||
209 | void phy_pm_runtime_forbid(struct phy *phy) | 224 | void phy_pm_runtime_forbid(struct phy *phy) |
210 | { | 225 | { |
226 | if (!phy) | ||
227 | return; | ||
228 | |||
211 | if (!pm_runtime_enabled(&phy->dev)) | 229 | if (!pm_runtime_enabled(&phy->dev)) |
212 | return; | 230 | return; |
213 | 231 | ||
diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig index 7bfa64baf837..632a0e73ee10 100644 --- a/drivers/phy/qualcomm/Kconfig +++ b/drivers/phy/qualcomm/Kconfig | |||
@@ -1,6 +1,15 @@ | |||
1 | # | 1 | # |
2 | # Phy drivers for Qualcomm platforms | 2 | # Phy drivers for Qualcomm and Atheros platforms |
3 | # | 3 | # |
4 | config PHY_ATH79_USB | ||
5 | tristate "Atheros AR71XX/9XXX USB PHY driver" | ||
6 | depends on OF && (ATH79 || COMPILE_TEST) | ||
7 | default y if USB_EHCI_HCD_PLATFORM || USB_OHCI_HCD_PLATFORM | ||
8 | select RESET_CONTROLLER | ||
9 | select GENERIC_PHY | ||
10 | help | ||
11 | Enable this to support the USB PHY on Atheros AR71XX/9XXX SoCs. | ||
12 | |||
4 | config PHY_QCOM_APQ8064_SATA | 13 | config PHY_QCOM_APQ8064_SATA |
5 | tristate "Qualcomm APQ8064 SATA SerDes/PHY driver" | 14 | tristate "Qualcomm APQ8064 SATA SerDes/PHY driver" |
6 | depends on ARCH_QCOM | 15 | depends on ARCH_QCOM |
diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile index 9abb7899762a..deb831f453ae 100644 --- a/drivers/phy/qualcomm/Makefile +++ b/drivers/phy/qualcomm/Makefile | |||
@@ -1,4 +1,5 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
2 | obj-$(CONFIG_PHY_ATH79_USB) += phy-ath79-usb.o | ||
2 | obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o | 3 | obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o |
3 | obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o | 4 | obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o |
4 | obj-$(CONFIG_PHY_QCOM_QMP) += phy-qcom-qmp.o | 5 | obj-$(CONFIG_PHY_QCOM_QMP) += phy-qcom-qmp.o |
diff --git a/drivers/phy/qualcomm/phy-ath79-usb.c b/drivers/phy/qualcomm/phy-ath79-usb.c new file mode 100644 index 000000000000..6fd6e07ab345 --- /dev/null +++ b/drivers/phy/qualcomm/phy-ath79-usb.c | |||
@@ -0,0 +1,108 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | /* | ||
3 | * Atheros AR71XX/9XXX USB PHY driver | ||
4 | * | ||
5 | * Copyright (C) 2015-2018 Alban Bedel <albeu@free.fr> | ||
6 | */ | ||
7 | |||
8 | #include <linux/module.h> | ||
9 | #include <linux/platform_device.h> | ||
10 | #include <linux/phy/phy.h> | ||
11 | #include <linux/reset.h> | ||
12 | |||
13 | struct ath79_usb_phy { | ||
14 | struct reset_control *reset; | ||
15 | /* The suspend override logic is inverted, hence the no prefix | ||
16 | * to make the code a bit easier to understand. | ||
17 | */ | ||
18 | struct reset_control *no_suspend_override; | ||
19 | }; | ||
20 | |||
21 | static int ath79_usb_phy_power_on(struct phy *phy) | ||
22 | { | ||
23 | struct ath79_usb_phy *priv = phy_get_drvdata(phy); | ||
24 | int err = 0; | ||
25 | |||
26 | if (priv->no_suspend_override) { | ||
27 | err = reset_control_assert(priv->no_suspend_override); | ||
28 | if (err) | ||
29 | return err; | ||
30 | } | ||
31 | |||
32 | err = reset_control_deassert(priv->reset); | ||
33 | if (err && priv->no_suspend_override) | ||
34 | reset_control_assert(priv->no_suspend_override); | ||
35 | |||
36 | return err; | ||
37 | } | ||
38 | |||
39 | static int ath79_usb_phy_power_off(struct phy *phy) | ||
40 | { | ||
41 | struct ath79_usb_phy *priv = phy_get_drvdata(phy); | ||
42 | int err = 0; | ||
43 | |||
44 | err = reset_control_assert(priv->reset); | ||
45 | if (err) | ||
46 | return err; | ||
47 | |||
48 | if (priv->no_suspend_override) { | ||
49 | err = reset_control_deassert(priv->no_suspend_override); | ||
50 | if (err) | ||
51 | reset_control_deassert(priv->reset); | ||
52 | } | ||
53 | |||
54 | return err; | ||
55 | } | ||
56 | |||
57 | static const struct phy_ops ath79_usb_phy_ops = { | ||
58 | .power_on = ath79_usb_phy_power_on, | ||
59 | .power_off = ath79_usb_phy_power_off, | ||
60 | .owner = THIS_MODULE, | ||
61 | }; | ||
62 | |||
63 | static int ath79_usb_phy_probe(struct platform_device *pdev) | ||
64 | { | ||
65 | struct ath79_usb_phy *priv; | ||
66 | struct phy *phy; | ||
67 | |||
68 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||
69 | if (!priv) | ||
70 | return -ENOMEM; | ||
71 | |||
72 | priv->reset = devm_reset_control_get(&pdev->dev, "usb-phy"); | ||
73 | if (IS_ERR(priv->reset)) | ||
74 | return PTR_ERR(priv->reset); | ||
75 | |||
76 | priv->no_suspend_override = devm_reset_control_get_optional( | ||
77 | &pdev->dev, "usb-suspend-override"); | ||
78 | if (IS_ERR(priv->no_suspend_override)) | ||
79 | return PTR_ERR(priv->no_suspend_override); | ||
80 | |||
81 | phy = devm_phy_create(&pdev->dev, NULL, &ath79_usb_phy_ops); | ||
82 | if (IS_ERR(phy)) | ||
83 | return PTR_ERR(phy); | ||
84 | |||
85 | phy_set_drvdata(phy, priv); | ||
86 | |||
87 | return PTR_ERR_OR_ZERO(devm_of_phy_provider_register( | ||
88 | &pdev->dev, of_phy_simple_xlate)); | ||
89 | } | ||
90 | |||
91 | static const struct of_device_id ath79_usb_phy_of_match[] = { | ||
92 | { .compatible = "qca,ar7100-usb-phy" }, | ||
93 | {} | ||
94 | }; | ||
95 | MODULE_DEVICE_TABLE(of, ath79_usb_phy_of_match); | ||
96 | |||
97 | static struct platform_driver ath79_usb_phy_driver = { | ||
98 | .probe = ath79_usb_phy_probe, | ||
99 | .driver = { | ||
100 | .of_match_table = ath79_usb_phy_of_match, | ||
101 | .name = "ath79-usb-phy", | ||
102 | } | ||
103 | }; | ||
104 | module_platform_driver(ath79_usb_phy_driver); | ||
105 | |||
106 | MODULE_DESCRIPTION("ATH79 USB PHY driver"); | ||
107 | MODULE_AUTHOR("Alban Bedel <albeu@free.fr>"); | ||
108 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c index 6470c5d61d1c..4c470104a0d6 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp.c | |||
@@ -490,6 +490,118 @@ static const struct qmp_phy_init_tbl qmp_v3_usb3_pcs_tbl[] = { | |||
490 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), | 490 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), |
491 | }; | 491 | }; |
492 | 492 | ||
493 | static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_serdes_tbl[] = { | ||
494 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), | ||
495 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14), | ||
496 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04), | ||
497 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), | ||
498 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), | ||
499 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08), | ||
500 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), | ||
501 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), | ||
502 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80), | ||
503 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), | ||
504 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab), | ||
505 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea), | ||
506 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02), | ||
507 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), | ||
508 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), | ||
509 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), | ||
510 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), | ||
511 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), | ||
512 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), | ||
513 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), | ||
514 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), | ||
515 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), | ||
516 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34), | ||
517 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15), | ||
518 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04), | ||
519 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), | ||
520 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00), | ||
521 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), | ||
522 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x0a), | ||
523 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), | ||
524 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31), | ||
525 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), | ||
526 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00), | ||
527 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), | ||
528 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85), | ||
529 | QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07), | ||
530 | }; | ||
531 | |||
532 | static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_tx_tbl[] = { | ||
533 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), | ||
534 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), | ||
535 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0xc6), | ||
536 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x06), | ||
537 | QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x06), | ||
538 | }; | ||
539 | |||
540 | static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_rx_tbl[] = { | ||
541 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x0c), | ||
542 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x50), | ||
543 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), | ||
544 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e), | ||
545 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e), | ||
546 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18), | ||
547 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), | ||
548 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), | ||
549 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), | ||
550 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1c), | ||
551 | QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75), | ||
552 | }; | ||
553 | |||
554 | static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_pcs_tbl[] = { | ||
555 | /* FLL settings */ | ||
556 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), | ||
557 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), | ||
558 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), | ||
559 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40), | ||
560 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), | ||
561 | |||
562 | /* Lock Det settings */ | ||
563 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), | ||
564 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), | ||
565 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), | ||
566 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), | ||
567 | |||
568 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0xba), | ||
569 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f), | ||
570 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V1, 0x9f), | ||
571 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V2, 0xb5), | ||
572 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V3, 0x4c), | ||
573 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V4, 0x64), | ||
574 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_LS, 0x6a), | ||
575 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), | ||
576 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0d), | ||
577 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V1, 0x15), | ||
578 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1, 0x0d), | ||
579 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V2, 0x15), | ||
580 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2, 0x0d), | ||
581 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V3, 0x15), | ||
582 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3, 0x1d), | ||
583 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V4, 0x15), | ||
584 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4, 0x0d), | ||
585 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_LS, 0x15), | ||
586 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS, 0x0d), | ||
587 | |||
588 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_RATE_SLEW_CNTRL, 0x02), | ||
589 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), | ||
590 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), | ||
591 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), | ||
592 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), | ||
593 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), | ||
594 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), | ||
595 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), | ||
596 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), | ||
597 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), | ||
598 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), | ||
599 | |||
600 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG1, 0x21), | ||
601 | QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG2, 0x60), | ||
602 | }; | ||
603 | |||
604 | |||
493 | /* struct qmp_phy_cfg - per-PHY initialization config */ | 605 | /* struct qmp_phy_cfg - per-PHY initialization config */ |
494 | struct qmp_phy_cfg { | 606 | struct qmp_phy_cfg { |
495 | /* phy-type - PCIE/UFS/USB */ | 607 | /* phy-type - PCIE/UFS/USB */ |
@@ -766,6 +878,7 @@ static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = { | |||
766 | .pwrdn_ctrl = SW_PWRDN, | 878 | .pwrdn_ctrl = SW_PWRDN, |
767 | .mask_pcs_ready = PHYSTATUS, | 879 | .mask_pcs_ready = PHYSTATUS, |
768 | 880 | ||
881 | .has_pwrdn_delay = true, | ||
769 | .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, | 882 | .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, |
770 | .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, | 883 | .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, |
771 | 884 | ||
@@ -774,6 +887,35 @@ static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = { | |||
774 | .rx_b_lane_offset = 0x400, | 887 | .rx_b_lane_offset = 0x400, |
775 | }; | 888 | }; |
776 | 889 | ||
890 | static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = { | ||
891 | .type = PHY_TYPE_USB3, | ||
892 | .nlanes = 1, | ||
893 | |||
894 | .serdes_tbl = qmp_v3_usb3_uniphy_serdes_tbl, | ||
895 | .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_serdes_tbl), | ||
896 | .tx_tbl = qmp_v3_usb3_uniphy_tx_tbl, | ||
897 | .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_tx_tbl), | ||
898 | .rx_tbl = qmp_v3_usb3_uniphy_rx_tbl, | ||
899 | .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_rx_tbl), | ||
900 | .pcs_tbl = qmp_v3_usb3_uniphy_pcs_tbl, | ||
901 | .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_pcs_tbl), | ||
902 | .clk_list = qmp_v3_phy_clk_l, | ||
903 | .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), | ||
904 | .reset_list = msm8996_usb3phy_reset_l, | ||
905 | .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), | ||
906 | .vreg_list = msm8996_phy_vreg_l, | ||
907 | .num_vregs = ARRAY_SIZE(msm8996_phy_vreg_l), | ||
908 | .regs = qmp_v3_usb3phy_regs_layout, | ||
909 | |||
910 | .start_ctrl = SERDES_START | PCS_START, | ||
911 | .pwrdn_ctrl = SW_PWRDN, | ||
912 | .mask_pcs_ready = PHYSTATUS, | ||
913 | |||
914 | .has_pwrdn_delay = true, | ||
915 | .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, | ||
916 | .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, | ||
917 | }; | ||
918 | |||
777 | static void qcom_qmp_phy_configure(void __iomem *base, | 919 | static void qcom_qmp_phy_configure(void __iomem *base, |
778 | const unsigned int *regs, | 920 | const unsigned int *regs, |
779 | const struct qmp_phy_init_tbl tbl[], | 921 | const struct qmp_phy_init_tbl tbl[], |
@@ -793,19 +935,6 @@ static void qcom_qmp_phy_configure(void __iomem *base, | |||
793 | } | 935 | } |
794 | } | 936 | } |
795 | 937 | ||
796 | static int qcom_qmp_phy_poweron(struct phy *phy) | ||
797 | { | ||
798 | struct qmp_phy *qphy = phy_get_drvdata(phy); | ||
799 | struct qcom_qmp *qmp = qphy->qmp; | ||
800 | int ret; | ||
801 | |||
802 | ret = clk_prepare_enable(qphy->pipe_clk); | ||
803 | if (ret) | ||
804 | dev_err(qmp->dev, "pipe_clk enable failed, err=%d\n", ret); | ||
805 | |||
806 | return ret; | ||
807 | } | ||
808 | |||
809 | static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp) | 938 | static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp) |
810 | { | 939 | { |
811 | const struct qmp_phy_cfg *cfg = qmp->cfg; | 940 | const struct qmp_phy_cfg *cfg = qmp->cfg; |
@@ -974,6 +1103,12 @@ static int qcom_qmp_phy_init(struct phy *phy) | |||
974 | } | 1103 | } |
975 | } | 1104 | } |
976 | 1105 | ||
1106 | ret = clk_prepare_enable(qphy->pipe_clk); | ||
1107 | if (ret) { | ||
1108 | dev_err(qmp->dev, "pipe_clk enable failed err=%d\n", ret); | ||
1109 | goto err_clk_enable; | ||
1110 | } | ||
1111 | |||
977 | /* Tx, Rx, and PCS configurations */ | 1112 | /* Tx, Rx, and PCS configurations */ |
978 | qcom_qmp_phy_configure(tx, cfg->regs, cfg->tx_tbl, cfg->tx_tbl_num); | 1113 | qcom_qmp_phy_configure(tx, cfg->regs, cfg->tx_tbl, cfg->tx_tbl_num); |
979 | /* Configuration for other LANE for USB-DP combo PHY */ | 1114 | /* Configuration for other LANE for USB-DP combo PHY */ |
@@ -1019,6 +1154,8 @@ static int qcom_qmp_phy_init(struct phy *phy) | |||
1019 | return ret; | 1154 | return ret; |
1020 | 1155 | ||
1021 | err_pcs_ready: | 1156 | err_pcs_ready: |
1157 | clk_disable_unprepare(qphy->pipe_clk); | ||
1158 | err_clk_enable: | ||
1022 | if (cfg->has_lane_rst) | 1159 | if (cfg->has_lane_rst) |
1023 | reset_control_assert(qphy->lane_rst); | 1160 | reset_control_assert(qphy->lane_rst); |
1024 | err_lane_rst: | 1161 | err_lane_rst: |
@@ -1283,7 +1420,6 @@ static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np) | |||
1283 | static const struct phy_ops qcom_qmp_phy_gen_ops = { | 1420 | static const struct phy_ops qcom_qmp_phy_gen_ops = { |
1284 | .init = qcom_qmp_phy_init, | 1421 | .init = qcom_qmp_phy_init, |
1285 | .exit = qcom_qmp_phy_exit, | 1422 | .exit = qcom_qmp_phy_exit, |
1286 | .power_on = qcom_qmp_phy_poweron, | ||
1287 | .set_mode = qcom_qmp_phy_set_mode, | 1423 | .set_mode = qcom_qmp_phy_set_mode, |
1288 | .owner = THIS_MODULE, | 1424 | .owner = THIS_MODULE, |
1289 | }; | 1425 | }; |
@@ -1381,8 +1517,11 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = { | |||
1381 | .compatible = "qcom,ipq8074-qmp-pcie-phy", | 1517 | .compatible = "qcom,ipq8074-qmp-pcie-phy", |
1382 | .data = &ipq8074_pciephy_cfg, | 1518 | .data = &ipq8074_pciephy_cfg, |
1383 | }, { | 1519 | }, { |
1384 | .compatible = "qcom,qmp-v3-usb3-phy", | 1520 | .compatible = "qcom,sdm845-qmp-usb3-phy", |
1385 | .data = &qmp_v3_usb3phy_cfg, | 1521 | .data = &qmp_v3_usb3phy_cfg, |
1522 | }, { | ||
1523 | .compatible = "qcom,sdm845-qmp-usb3-uni-phy", | ||
1524 | .data = &qmp_v3_usb3_uniphy_cfg, | ||
1386 | }, | 1525 | }, |
1387 | { }, | 1526 | { }, |
1388 | }; | 1527 | }; |
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h index d1c6905d0439..5d78d43ba9fc 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.h +++ b/drivers/phy/qualcomm/phy-qcom-qmp.h | |||
@@ -214,6 +214,8 @@ | |||
214 | #define QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN 0x030 | 214 | #define QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN 0x030 |
215 | #define QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE 0x034 | 215 | #define QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE 0x034 |
216 | #define QSERDES_V3_RX_RX_TERM_BW 0x07c | 216 | #define QSERDES_V3_RX_RX_TERM_BW 0x07c |
217 | #define QSERDES_V3_RX_VGA_CAL_CNTRL1 0x0bc | ||
218 | #define QSERDES_V3_RX_VGA_CAL_CNTRL2 0x0c0 | ||
217 | #define QSERDES_V3_RX_RX_EQ_GAIN2_LSB 0x0c8 | 219 | #define QSERDES_V3_RX_RX_EQ_GAIN2_LSB 0x0c8 |
218 | #define QSERDES_V3_RX_RX_EQ_GAIN2_MSB 0x0cc | 220 | #define QSERDES_V3_RX_RX_EQ_GAIN2_MSB 0x0cc |
219 | #define QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2 0x0d4 | 221 | #define QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2 0x0d4 |
@@ -227,6 +229,7 @@ | |||
227 | #define QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL 0x10c | 229 | #define QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL 0x10c |
228 | #define QSERDES_V3_RX_RX_BAND 0x110 | 230 | #define QSERDES_V3_RX_RX_BAND 0x110 |
229 | #define QSERDES_V3_RX_RX_INTERFACE_MODE 0x11c | 231 | #define QSERDES_V3_RX_RX_INTERFACE_MODE 0x11c |
232 | #define QSERDES_V3_RX_RX_MODE_00 0x164 | ||
230 | 233 | ||
231 | /* Only for QMP V3 PHY - PCS registers */ | 234 | /* Only for QMP V3 PHY - PCS registers */ |
232 | #define QPHY_V3_PCS_POWER_DOWN_CONTROL 0x004 | 235 | #define QPHY_V3_PCS_POWER_DOWN_CONTROL 0x004 |
@@ -273,6 +276,8 @@ | |||
273 | #define QPHY_V3_PCS_FLL_CNT_VAL_H_TOL 0x0d0 | 276 | #define QPHY_V3_PCS_FLL_CNT_VAL_H_TOL 0x0d0 |
274 | #define QPHY_V3_PCS_FLL_MAN_CODE 0x0d4 | 277 | #define QPHY_V3_PCS_FLL_MAN_CODE 0x0d4 |
275 | #define QPHY_V3_PCS_RX_SIGDET_LVL 0x1d8 | 278 | #define QPHY_V3_PCS_RX_SIGDET_LVL 0x1d8 |
279 | #define QPHY_V3_PCS_REFGEN_REQ_CONFIG1 0x20c | ||
280 | #define QPHY_V3_PCS_REFGEN_REQ_CONFIG2 0x210 | ||
276 | 281 | ||
277 | /* Only for QMP V3 PHY - PCS_MISC registers */ | 282 | /* Only for QMP V3 PHY - PCS_MISC registers */ |
278 | #define QPHY_V3_PCS_MISC_CLAMP_ENABLE 0x0c | 283 | #define QPHY_V3_PCS_MISC_CLAMP_ENABLE 0x0c |
diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c index 94afeac1a19e..e70e425f26f5 100644 --- a/drivers/phy/qualcomm/phy-qcom-qusb2.c +++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <linux/reset.h> | 20 | #include <linux/reset.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | 22 | ||
23 | #include <dt-bindings/phy/phy-qcom-qusb2.h> | ||
24 | |||
23 | #define QUSB2PHY_PLL_TEST 0x04 | 25 | #define QUSB2PHY_PLL_TEST 0x04 |
24 | #define CLK_REF_SEL BIT(7) | 26 | #define CLK_REF_SEL BIT(7) |
25 | 27 | ||
@@ -60,6 +62,17 @@ | |||
60 | #define CORE_RESET BIT(5) | 62 | #define CORE_RESET BIT(5) |
61 | #define CORE_RESET_MUX BIT(6) | 63 | #define CORE_RESET_MUX BIT(6) |
62 | 64 | ||
65 | /* QUSB2PHY_IMP_CTRL1 register bits */ | ||
66 | #define IMP_RES_OFFSET_MASK GENMASK(5, 0) | ||
67 | #define IMP_RES_OFFSET_SHIFT 0x0 | ||
68 | |||
69 | /* QUSB2PHY_PORT_TUNE1 register bits */ | ||
70 | #define HSTX_TRIM_MASK GENMASK(7, 4) | ||
71 | #define HSTX_TRIM_SHIFT 0x4 | ||
72 | #define PREEMPH_WIDTH_HALF_BIT BIT(2) | ||
73 | #define PREEMPHASIS_EN_MASK GENMASK(1, 0) | ||
74 | #define PREEMPHASIS_EN_SHIFT 0x0 | ||
75 | |||
63 | #define QUSB2PHY_PLL_ANALOG_CONTROLS_TWO 0x04 | 76 | #define QUSB2PHY_PLL_ANALOG_CONTROLS_TWO 0x04 |
64 | #define QUSB2PHY_PLL_CLOCK_INVERTERS 0x18c | 77 | #define QUSB2PHY_PLL_CLOCK_INVERTERS 0x18c |
65 | #define QUSB2PHY_PLL_CMODE 0x2c | 78 | #define QUSB2PHY_PLL_CMODE 0x2c |
@@ -139,7 +152,7 @@ static const struct qusb2_phy_init_tbl msm8996_init_tbl[] = { | |||
139 | QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_PWR_CTRL, 0x00), | 152 | QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_PWR_CTRL, 0x00), |
140 | }; | 153 | }; |
141 | 154 | ||
142 | static const unsigned int qusb2_v2_regs_layout[] = { | 155 | static const unsigned int sdm845_regs_layout[] = { |
143 | [QUSB2PHY_PLL_CORE_INPUT_OVERRIDE] = 0xa8, | 156 | [QUSB2PHY_PLL_CORE_INPUT_OVERRIDE] = 0xa8, |
144 | [QUSB2PHY_PLL_STATUS] = 0x1a0, | 157 | [QUSB2PHY_PLL_STATUS] = 0x1a0, |
145 | [QUSB2PHY_PORT_TUNE1] = 0x240, | 158 | [QUSB2PHY_PORT_TUNE1] = 0x240, |
@@ -153,7 +166,7 @@ static const unsigned int qusb2_v2_regs_layout[] = { | |||
153 | [QUSB2PHY_INTR_CTRL] = 0x230, | 166 | [QUSB2PHY_INTR_CTRL] = 0x230, |
154 | }; | 167 | }; |
155 | 168 | ||
156 | static const struct qusb2_phy_init_tbl qusb2_v2_init_tbl[] = { | 169 | static const struct qusb2_phy_init_tbl sdm845_init_tbl[] = { |
157 | QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_ANALOG_CONTROLS_TWO, 0x03), | 170 | QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_ANALOG_CONTROLS_TWO, 0x03), |
158 | QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CLOCK_INVERTERS, 0x7c), | 171 | QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CLOCK_INVERTERS, 0x7c), |
159 | QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CMODE, 0x80), | 172 | QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CMODE, 0x80), |
@@ -208,10 +221,10 @@ static const struct qusb2_phy_cfg msm8996_phy_cfg = { | |||
208 | .autoresume_en = BIT(3), | 221 | .autoresume_en = BIT(3), |
209 | }; | 222 | }; |
210 | 223 | ||
211 | static const struct qusb2_phy_cfg qusb2_v2_phy_cfg = { | 224 | static const struct qusb2_phy_cfg sdm845_phy_cfg = { |
212 | .tbl = qusb2_v2_init_tbl, | 225 | .tbl = sdm845_init_tbl, |
213 | .tbl_num = ARRAY_SIZE(qusb2_v2_init_tbl), | 226 | .tbl_num = ARRAY_SIZE(sdm845_init_tbl), |
214 | .regs = qusb2_v2_regs_layout, | 227 | .regs = sdm845_regs_layout, |
215 | 228 | ||
216 | .disable_ctrl = (PWR_CTRL1_VREF_SUPPLY_TRIM | PWR_CTRL1_CLAMP_N_EN | | 229 | .disable_ctrl = (PWR_CTRL1_VREF_SUPPLY_TRIM | PWR_CTRL1_CLAMP_N_EN | |
217 | POWER_DOWN), | 230 | POWER_DOWN), |
@@ -241,6 +254,15 @@ static const char * const qusb2_phy_vreg_names[] = { | |||
241 | * @tcsr: TCSR syscon register map | 254 | * @tcsr: TCSR syscon register map |
242 | * @cell: nvmem cell containing phy tuning value | 255 | * @cell: nvmem cell containing phy tuning value |
243 | * | 256 | * |
257 | * @override_imp_res_offset: PHY should use different rescode offset | ||
258 | * @imp_res_offset_value: rescode offset to be updated in IMP_CTRL1 register | ||
259 | * @override_hstx_trim: PHY should use different HSTX o/p current value | ||
260 | * @hstx_trim_value: HSTX_TRIM value to be updated in TUNE1 register | ||
261 | * @override_preemphasis: PHY should use different pre-amphasis amplitude | ||
262 | * @preemphasis_level: Amplitude Pre-Emphasis to be updated in TUNE1 register | ||
263 | * @override_preemphasis_width: PHY should use different pre-emphasis duration | ||
264 | * @preemphasis_width: half/full-width Pre-Emphasis updated via TUNE1 | ||
265 | * | ||
244 | * @cfg: phy config data | 266 | * @cfg: phy config data |
245 | * @has_se_clk_scheme: indicate if PHY has single-ended ref clock scheme | 267 | * @has_se_clk_scheme: indicate if PHY has single-ended ref clock scheme |
246 | * @phy_initialized: indicate if PHY has been initialized | 268 | * @phy_initialized: indicate if PHY has been initialized |
@@ -259,12 +281,35 @@ struct qusb2_phy { | |||
259 | struct regmap *tcsr; | 281 | struct regmap *tcsr; |
260 | struct nvmem_cell *cell; | 282 | struct nvmem_cell *cell; |
261 | 283 | ||
284 | bool override_imp_res_offset; | ||
285 | u8 imp_res_offset_value; | ||
286 | bool override_hstx_trim; | ||
287 | u8 hstx_trim_value; | ||
288 | bool override_preemphasis; | ||
289 | u8 preemphasis_level; | ||
290 | bool override_preemphasis_width; | ||
291 | u8 preemphasis_width; | ||
292 | |||
262 | const struct qusb2_phy_cfg *cfg; | 293 | const struct qusb2_phy_cfg *cfg; |
263 | bool has_se_clk_scheme; | 294 | bool has_se_clk_scheme; |
264 | bool phy_initialized; | 295 | bool phy_initialized; |
265 | enum phy_mode mode; | 296 | enum phy_mode mode; |
266 | }; | 297 | }; |
267 | 298 | ||
299 | static inline void qusb2_write_mask(void __iomem *base, u32 offset, | ||
300 | u32 val, u32 mask) | ||
301 | { | ||
302 | u32 reg; | ||
303 | |||
304 | reg = readl(base + offset); | ||
305 | reg &= ~mask; | ||
306 | reg |= val & mask; | ||
307 | writel(reg, base + offset); | ||
308 | |||
309 | /* Ensure above write is completed */ | ||
310 | readl(base + offset); | ||
311 | } | ||
312 | |||
268 | static inline void qusb2_setbits(void __iomem *base, u32 offset, u32 val) | 313 | static inline void qusb2_setbits(void __iomem *base, u32 offset, u32 val) |
269 | { | 314 | { |
270 | u32 reg; | 315 | u32 reg; |
@@ -305,6 +350,42 @@ void qcom_qusb2_phy_configure(void __iomem *base, | |||
305 | } | 350 | } |
306 | 351 | ||
307 | /* | 352 | /* |
353 | * Update board specific PHY tuning override values if specified from | ||
354 | * device tree. | ||
355 | */ | ||
356 | static void qusb2_phy_override_phy_params(struct qusb2_phy *qphy) | ||
357 | { | ||
358 | const struct qusb2_phy_cfg *cfg = qphy->cfg; | ||
359 | |||
360 | if (qphy->override_imp_res_offset) | ||
361 | qusb2_write_mask(qphy->base, QUSB2PHY_IMP_CTRL1, | ||
362 | qphy->imp_res_offset_value << IMP_RES_OFFSET_SHIFT, | ||
363 | IMP_RES_OFFSET_MASK); | ||
364 | |||
365 | if (qphy->override_hstx_trim) | ||
366 | qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE1], | ||
367 | qphy->hstx_trim_value << HSTX_TRIM_SHIFT, | ||
368 | HSTX_TRIM_MASK); | ||
369 | |||
370 | if (qphy->override_preemphasis) | ||
371 | qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE1], | ||
372 | qphy->preemphasis_level << PREEMPHASIS_EN_SHIFT, | ||
373 | PREEMPHASIS_EN_MASK); | ||
374 | |||
375 | if (qphy->override_preemphasis_width) { | ||
376 | if (qphy->preemphasis_width == | ||
377 | QUSB2_V2_PREEMPHASIS_WIDTH_HALF_BIT) | ||
378 | qusb2_setbits(qphy->base, | ||
379 | cfg->regs[QUSB2PHY_PORT_TUNE1], | ||
380 | PREEMPH_WIDTH_HALF_BIT); | ||
381 | else | ||
382 | qusb2_clrbits(qphy->base, | ||
383 | cfg->regs[QUSB2PHY_PORT_TUNE1], | ||
384 | PREEMPH_WIDTH_HALF_BIT); | ||
385 | } | ||
386 | } | ||
387 | |||
388 | /* | ||
308 | * Fetches HS Tx tuning value from nvmem and sets the | 389 | * Fetches HS Tx tuning value from nvmem and sets the |
309 | * QUSB2PHY_PORT_TUNE1/2 register. | 390 | * QUSB2PHY_PORT_TUNE1/2 register. |
310 | * For error case, skip setting the value and use the default value. | 391 | * For error case, skip setting the value and use the default value. |
@@ -315,6 +396,10 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy) | |||
315 | const struct qusb2_phy_cfg *cfg = qphy->cfg; | 396 | const struct qusb2_phy_cfg *cfg = qphy->cfg; |
316 | u8 *val; | 397 | u8 *val; |
317 | 398 | ||
399 | /* efuse register is optional */ | ||
400 | if (!qphy->cell) | ||
401 | return; | ||
402 | |||
318 | /* | 403 | /* |
319 | * Read efuse register having TUNE2/1 parameter's high nibble. | 404 | * Read efuse register having TUNE2/1 parameter's high nibble. |
320 | * If efuse register shows value as 0x0, or if we fail to find | 405 | * If efuse register shows value as 0x0, or if we fail to find |
@@ -521,6 +606,9 @@ static int qusb2_phy_init(struct phy *phy) | |||
521 | qcom_qusb2_phy_configure(qphy->base, cfg->regs, cfg->tbl, | 606 | qcom_qusb2_phy_configure(qphy->base, cfg->regs, cfg->tbl, |
522 | cfg->tbl_num); | 607 | cfg->tbl_num); |
523 | 608 | ||
609 | /* Override board specific PHY tuning values */ | ||
610 | qusb2_phy_override_phy_params(qphy); | ||
611 | |||
524 | /* Set efuse value for tuning the PHY */ | 612 | /* Set efuse value for tuning the PHY */ |
525 | qusb2_phy_set_tune2_param(qphy); | 613 | qusb2_phy_set_tune2_param(qphy); |
526 | 614 | ||
@@ -643,8 +731,8 @@ static const struct of_device_id qusb2_phy_of_match_table[] = { | |||
643 | .compatible = "qcom,msm8996-qusb2-phy", | 731 | .compatible = "qcom,msm8996-qusb2-phy", |
644 | .data = &msm8996_phy_cfg, | 732 | .data = &msm8996_phy_cfg, |
645 | }, { | 733 | }, { |
646 | .compatible = "qcom,qusb2-v2-phy", | 734 | .compatible = "qcom,sdm845-qusb2-phy", |
647 | .data = &qusb2_v2_phy_cfg, | 735 | .data = &sdm845_phy_cfg, |
648 | }, | 736 | }, |
649 | { }, | 737 | { }, |
650 | }; | 738 | }; |
@@ -664,6 +752,7 @@ static int qusb2_phy_probe(struct platform_device *pdev) | |||
664 | struct resource *res; | 752 | struct resource *res; |
665 | int ret, i; | 753 | int ret, i; |
666 | int num; | 754 | int num; |
755 | u32 value; | ||
667 | 756 | ||
668 | qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL); | 757 | qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL); |
669 | if (!qphy) | 758 | if (!qphy) |
@@ -732,6 +821,31 @@ static int qusb2_phy_probe(struct platform_device *pdev) | |||
732 | qphy->cell = NULL; | 821 | qphy->cell = NULL; |
733 | dev_dbg(dev, "failed to lookup tune2 hstx trim value\n"); | 822 | dev_dbg(dev, "failed to lookup tune2 hstx trim value\n"); |
734 | } | 823 | } |
824 | |||
825 | if (!of_property_read_u32(dev->of_node, "qcom,imp-res-offset-value", | ||
826 | &value)) { | ||
827 | qphy->imp_res_offset_value = (u8)value; | ||
828 | qphy->override_imp_res_offset = true; | ||
829 | } | ||
830 | |||
831 | if (!of_property_read_u32(dev->of_node, "qcom,hstx-trim-value", | ||
832 | &value)) { | ||
833 | qphy->hstx_trim_value = (u8)value; | ||
834 | qphy->override_hstx_trim = true; | ||
835 | } | ||
836 | |||
837 | if (!of_property_read_u32(dev->of_node, "qcom,preemphasis-level", | ||
838 | &value)) { | ||
839 | qphy->preemphasis_level = (u8)value; | ||
840 | qphy->override_preemphasis = true; | ||
841 | } | ||
842 | |||
843 | if (!of_property_read_u32(dev->of_node, "qcom,preemphasis-width", | ||
844 | &value)) { | ||
845 | qphy->preemphasis_width = (u8)value; | ||
846 | qphy->override_preemphasis_width = true; | ||
847 | } | ||
848 | |||
735 | pm_runtime_set_active(dev); | 849 | pm_runtime_set_active(dev); |
736 | pm_runtime_enable(dev); | 850 | pm_runtime_enable(dev); |
737 | /* | 851 | /* |
diff --git a/drivers/phy/samsung/phy-exynos-mipi-video.c b/drivers/phy/samsung/phy-exynos-mipi-video.c index c198886f80a3..00d89599c67d 100644 --- a/drivers/phy/samsung/phy-exynos-mipi-video.c +++ b/drivers/phy/samsung/phy-exynos-mipi-video.c | |||
@@ -231,33 +231,27 @@ struct exynos_mipi_video_phy { | |||
231 | static int __set_phy_state(const struct exynos_mipi_phy_desc *data, | 231 | static int __set_phy_state(const struct exynos_mipi_phy_desc *data, |
232 | struct exynos_mipi_video_phy *state, unsigned int on) | 232 | struct exynos_mipi_video_phy *state, unsigned int on) |
233 | { | 233 | { |
234 | u32 val; | 234 | struct regmap *enable_map = state->regmaps[data->enable_map]; |
235 | struct regmap *resetn_map = state->regmaps[data->resetn_map]; | ||
235 | 236 | ||
236 | spin_lock(&state->slock); | 237 | spin_lock(&state->slock); |
237 | 238 | ||
238 | /* disable in PMU sysreg */ | 239 | /* disable in PMU sysreg */ |
239 | if (!on && data->coupled_phy_id >= 0 && | 240 | if (!on && data->coupled_phy_id >= 0 && |
240 | state->phys[data->coupled_phy_id].phy->power_count == 0) { | 241 | state->phys[data->coupled_phy_id].phy->power_count == 0) |
241 | regmap_read(state->regmaps[data->enable_map], data->enable_reg, | 242 | regmap_update_bits(enable_map, data->enable_reg, |
242 | &val); | 243 | data->enable_val, 0); |
243 | val &= ~data->enable_val; | ||
244 | regmap_write(state->regmaps[data->enable_map], data->enable_reg, | ||
245 | val); | ||
246 | } | ||
247 | |||
248 | /* PHY reset */ | 244 | /* PHY reset */ |
249 | regmap_read(state->regmaps[data->resetn_map], data->resetn_reg, &val); | 245 | if (on) |
250 | val = on ? (val | data->resetn_val) : (val & ~data->resetn_val); | 246 | regmap_update_bits(resetn_map, data->resetn_reg, |
251 | regmap_write(state->regmaps[data->resetn_map], data->resetn_reg, val); | 247 | data->resetn_val, data->resetn_val); |
252 | 248 | else | |
249 | regmap_update_bits(resetn_map, data->resetn_reg, | ||
250 | data->resetn_val, 0); | ||
253 | /* enable in PMU sysreg */ | 251 | /* enable in PMU sysreg */ |
254 | if (on) { | 252 | if (on) |
255 | regmap_read(state->regmaps[data->enable_map], data->enable_reg, | 253 | regmap_update_bits(enable_map, data->enable_reg, |
256 | &val); | 254 | data->enable_val, data->enable_val); |
257 | val |= data->enable_val; | ||
258 | regmap_write(state->regmaps[data->enable_map], data->enable_reg, | ||
259 | val); | ||
260 | } | ||
261 | 255 | ||
262 | spin_unlock(&state->slock); | 256 | spin_unlock(&state->slock); |
263 | 257 | ||
diff --git a/drivers/phy/st/phy-stm32-usbphyc.c b/drivers/phy/st/phy-stm32-usbphyc.c index bc4e78a19c91..1255cd1d9a60 100644 --- a/drivers/phy/st/phy-stm32-usbphyc.c +++ b/drivers/phy/st/phy-stm32-usbphyc.c | |||
@@ -71,7 +71,6 @@ struct stm32_usbphyc { | |||
71 | struct stm32_usbphyc_phy **phys; | 71 | struct stm32_usbphyc_phy **phys; |
72 | int nphys; | 72 | int nphys; |
73 | int switch_setup; | 73 | int switch_setup; |
74 | bool pll_enabled; | ||
75 | }; | 74 | }; |
76 | 75 | ||
77 | static inline void stm32_usbphyc_set_bits(void __iomem *reg, u32 bits) | 76 | static inline void stm32_usbphyc_set_bits(void __iomem *reg, u32 bits) |
@@ -84,7 +83,8 @@ static inline void stm32_usbphyc_clr_bits(void __iomem *reg, u32 bits) | |||
84 | writel_relaxed(readl_relaxed(reg) & ~bits, reg); | 83 | writel_relaxed(readl_relaxed(reg) & ~bits, reg); |
85 | } | 84 | } |
86 | 85 | ||
87 | static void stm32_usbphyc_get_pll_params(u32 clk_rate, struct pll_params *pll_params) | 86 | static void stm32_usbphyc_get_pll_params(u32 clk_rate, |
87 | struct pll_params *pll_params) | ||
88 | { | 88 | { |
89 | unsigned long long fvco, ndiv, frac; | 89 | unsigned long long fvco, ndiv, frac; |
90 | 90 | ||
@@ -271,7 +271,6 @@ static struct phy *stm32_usbphyc_of_xlate(struct device *dev, | |||
271 | struct stm32_usbphyc *usbphyc = dev_get_drvdata(dev); | 271 | struct stm32_usbphyc *usbphyc = dev_get_drvdata(dev); |
272 | struct stm32_usbphyc_phy *usbphyc_phy = NULL; | 272 | struct stm32_usbphyc_phy *usbphyc_phy = NULL; |
273 | struct device_node *phynode = args->np; | 273 | struct device_node *phynode = args->np; |
274 | |||
275 | int port = 0; | 274 | int port = 0; |
276 | 275 | ||
277 | for (port = 0; port < usbphyc->nphys; port++) { | 276 | for (port = 0; port < usbphyc->nphys; port++) { |
@@ -367,8 +366,8 @@ static int stm32_usbphyc_probe(struct platform_device *pdev) | |||
367 | if (IS_ERR(phy)) { | 366 | if (IS_ERR(phy)) { |
368 | ret = PTR_ERR(phy); | 367 | ret = PTR_ERR(phy); |
369 | if (ret != -EPROBE_DEFER) | 368 | if (ret != -EPROBE_DEFER) |
370 | dev_err(dev, | 369 | dev_err(dev, "failed to create phy%d: %d\n", |
371 | "failed to create phy%d: %d\n", i, ret); | 370 | port, ret); |
372 | goto put_child; | 371 | goto put_child; |
373 | } | 372 | } |
374 | 373 | ||
diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c index 11aa5902a9ac..de1b4ebe4de2 100644 --- a/drivers/phy/tegra/xusb.c +++ b/drivers/phy/tegra/xusb.c | |||
@@ -102,19 +102,6 @@ tegra_xusb_pad_find_phy_node(struct tegra_xusb_pad *pad, unsigned int index) | |||
102 | return np; | 102 | return np; |
103 | } | 103 | } |
104 | 104 | ||
105 | static int | ||
106 | tegra_xusb_lane_lookup_function(struct tegra_xusb_lane *lane, | ||
107 | const char *function) | ||
108 | { | ||
109 | unsigned int i; | ||
110 | |||
111 | for (i = 0; i < lane->soc->num_funcs; i++) | ||
112 | if (strcmp(function, lane->soc->funcs[i]) == 0) | ||
113 | return i; | ||
114 | |||
115 | return -EINVAL; | ||
116 | } | ||
117 | |||
118 | int tegra_xusb_lane_parse_dt(struct tegra_xusb_lane *lane, | 105 | int tegra_xusb_lane_parse_dt(struct tegra_xusb_lane *lane, |
119 | struct device_node *np) | 106 | struct device_node *np) |
120 | { | 107 | { |
@@ -126,7 +113,7 @@ int tegra_xusb_lane_parse_dt(struct tegra_xusb_lane *lane, | |||
126 | if (err < 0) | 113 | if (err < 0) |
127 | return err; | 114 | return err; |
128 | 115 | ||
129 | err = tegra_xusb_lane_lookup_function(lane, function); | 116 | err = match_string(lane->soc->funcs, lane->soc->num_funcs, function); |
130 | if (err < 0) { | 117 | if (err < 0) { |
131 | dev_err(dev, "invalid function \"%s\" for lane \"%s\"\n", | 118 | dev_err(dev, "invalid function \"%s\" for lane \"%s\"\n", |
132 | function, np->name); | 119 | function, np->name); |
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 566644bb496a..f27cb186437d 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
@@ -866,6 +866,7 @@ config ACPI_CMPC | |||
866 | config INTEL_CHT_INT33FE | 866 | config INTEL_CHT_INT33FE |
867 | tristate "Intel Cherry Trail ACPI INT33FE Driver" | 867 | tristate "Intel Cherry Trail ACPI INT33FE Driver" |
868 | depends on X86 && ACPI && I2C && REGULATOR | 868 | depends on X86 && ACPI && I2C && REGULATOR |
869 | depends on CHARGER_BQ24190=y || (CHARGER_BQ24190=m && m) | ||
869 | ---help--- | 870 | ---help--- |
870 | This driver add support for the INT33FE ACPI device found on | 871 | This driver add support for the INT33FE ACPI device found on |
871 | some Intel Cherry Trail devices. | 872 | some Intel Cherry Trail devices. |
@@ -877,8 +878,7 @@ config INTEL_CHT_INT33FE | |||
877 | i2c drivers for these chips can bind to the them. | 878 | i2c drivers for these chips can bind to the them. |
878 | 879 | ||
879 | If you enable this driver it is advised to also select | 880 | If you enable this driver it is advised to also select |
880 | CONFIG_TYPEC_FUSB302=m, CONFIG_CHARGER_BQ24190=m and | 881 | CONFIG_TYPEC_FUSB302=m and CONFIG_BATTERY_MAX17042=m. |
881 | CONFIG_BATTERY_MAX17042=m. | ||
882 | 882 | ||
883 | config INTEL_INT0002_VGPIO | 883 | config INTEL_INT0002_VGPIO |
884 | tristate "Intel ACPI INT0002 Virtual GPIO driver" | 884 | tristate "Intel ACPI INT0002 Virtual GPIO driver" |
diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index feac7b066e6c..f57ab0a27301 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/err.h> | 19 | #include <linux/err.h> |
20 | #include <linux/of.h> | 20 | #include <linux/of.h> |
21 | #include <linux/power_supply.h> | 21 | #include <linux/power_supply.h> |
22 | #include <linux/property.h> | ||
22 | #include <linux/thermal.h> | 23 | #include <linux/thermal.h> |
23 | #include "power_supply.h" | 24 | #include "power_supply.h" |
24 | 25 | ||
@@ -843,12 +844,21 @@ __power_supply_register(struct device *parent, | |||
843 | { | 844 | { |
844 | struct device *dev; | 845 | struct device *dev; |
845 | struct power_supply *psy; | 846 | struct power_supply *psy; |
846 | int rc; | 847 | int i, rc; |
847 | 848 | ||
848 | if (!parent) | 849 | if (!parent) |
849 | pr_warn("%s: Expected proper parent device for '%s'\n", | 850 | pr_warn("%s: Expected proper parent device for '%s'\n", |
850 | __func__, desc->name); | 851 | __func__, desc->name); |
851 | 852 | ||
853 | if (!desc || !desc->name || !desc->properties || !desc->num_properties) | ||
854 | return ERR_PTR(-EINVAL); | ||
855 | |||
856 | for (i = 0; i < desc->num_properties; ++i) { | ||
857 | if ((desc->properties[i] == POWER_SUPPLY_PROP_USB_TYPE) && | ||
858 | (!desc->usb_types || !desc->num_usb_types)) | ||
859 | return ERR_PTR(-EINVAL); | ||
860 | } | ||
861 | |||
852 | psy = kzalloc(sizeof(*psy), GFP_KERNEL); | 862 | psy = kzalloc(sizeof(*psy), GFP_KERNEL); |
853 | if (!psy) | 863 | if (!psy) |
854 | return ERR_PTR(-ENOMEM); | 864 | return ERR_PTR(-ENOMEM); |
@@ -865,7 +875,8 @@ __power_supply_register(struct device *parent, | |||
865 | psy->desc = desc; | 875 | psy->desc = desc; |
866 | if (cfg) { | 876 | if (cfg) { |
867 | psy->drv_data = cfg->drv_data; | 877 | psy->drv_data = cfg->drv_data; |
868 | psy->of_node = cfg->of_node; | 878 | psy->of_node = |
879 | cfg->fwnode ? to_of_node(cfg->fwnode) : cfg->of_node; | ||
869 | psy->supplied_to = cfg->supplied_to; | 880 | psy->supplied_to = cfg->supplied_to; |
870 | psy->num_supplicants = cfg->num_supplicants; | 881 | psy->num_supplicants = cfg->num_supplicants; |
871 | } | 882 | } |
diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c index 5204f115970f..1350068c401a 100644 --- a/drivers/power/supply/power_supply_sysfs.c +++ b/drivers/power/supply/power_supply_sysfs.c | |||
@@ -46,6 +46,11 @@ static const char * const power_supply_type_text[] = { | |||
46 | "USB_PD", "USB_PD_DRP", "BrickID" | 46 | "USB_PD", "USB_PD_DRP", "BrickID" |
47 | }; | 47 | }; |
48 | 48 | ||
49 | static const char * const power_supply_usb_type_text[] = { | ||
50 | "Unknown", "SDP", "DCP", "CDP", "ACA", "C", | ||
51 | "PD", "PD_DRP", "PD_PPS", "BrickID" | ||
52 | }; | ||
53 | |||
49 | static const char * const power_supply_status_text[] = { | 54 | static const char * const power_supply_status_text[] = { |
50 | "Unknown", "Charging", "Discharging", "Not charging", "Full" | 55 | "Unknown", "Charging", "Discharging", "Not charging", "Full" |
51 | }; | 56 | }; |
@@ -73,6 +78,41 @@ static const char * const power_supply_scope_text[] = { | |||
73 | "Unknown", "System", "Device" | 78 | "Unknown", "System", "Device" |
74 | }; | 79 | }; |
75 | 80 | ||
81 | static ssize_t power_supply_show_usb_type(struct device *dev, | ||
82 | enum power_supply_usb_type *usb_types, | ||
83 | ssize_t num_usb_types, | ||
84 | union power_supply_propval *value, | ||
85 | char *buf) | ||
86 | { | ||
87 | enum power_supply_usb_type usb_type; | ||
88 | ssize_t count = 0; | ||
89 | bool match = false; | ||
90 | int i; | ||
91 | |||
92 | for (i = 0; i < num_usb_types; ++i) { | ||
93 | usb_type = usb_types[i]; | ||
94 | |||
95 | if (value->intval == usb_type) { | ||
96 | count += sprintf(buf + count, "[%s] ", | ||
97 | power_supply_usb_type_text[usb_type]); | ||
98 | match = true; | ||
99 | } else { | ||
100 | count += sprintf(buf + count, "%s ", | ||
101 | power_supply_usb_type_text[usb_type]); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | if (!match) { | ||
106 | dev_warn(dev, "driver reporting unsupported connected type\n"); | ||
107 | return -EINVAL; | ||
108 | } | ||
109 | |||
110 | if (count) | ||
111 | buf[count - 1] = '\n'; | ||
112 | |||
113 | return count; | ||
114 | } | ||
115 | |||
76 | static ssize_t power_supply_show_property(struct device *dev, | 116 | static ssize_t power_supply_show_property(struct device *dev, |
77 | struct device_attribute *attr, | 117 | struct device_attribute *attr, |
78 | char *buf) { | 118 | char *buf) { |
@@ -115,6 +155,10 @@ static ssize_t power_supply_show_property(struct device *dev, | |||
115 | else if (off == POWER_SUPPLY_PROP_TYPE) | 155 | else if (off == POWER_SUPPLY_PROP_TYPE) |
116 | return sprintf(buf, "%s\n", | 156 | return sprintf(buf, "%s\n", |
117 | power_supply_type_text[value.intval]); | 157 | power_supply_type_text[value.intval]); |
158 | else if (off == POWER_SUPPLY_PROP_USB_TYPE) | ||
159 | return power_supply_show_usb_type(dev, psy->desc->usb_types, | ||
160 | psy->desc->num_usb_types, | ||
161 | &value, buf); | ||
118 | else if (off == POWER_SUPPLY_PROP_SCOPE) | 162 | else if (off == POWER_SUPPLY_PROP_SCOPE) |
119 | return sprintf(buf, "%s\n", | 163 | return sprintf(buf, "%s\n", |
120 | power_supply_scope_text[value.intval]); | 164 | power_supply_scope_text[value.intval]); |
@@ -241,6 +285,7 @@ static struct device_attribute power_supply_attrs[] = { | |||
241 | POWER_SUPPLY_ATTR(time_to_full_now), | 285 | POWER_SUPPLY_ATTR(time_to_full_now), |
242 | POWER_SUPPLY_ATTR(time_to_full_avg), | 286 | POWER_SUPPLY_ATTR(time_to_full_avg), |
243 | POWER_SUPPLY_ATTR(type), | 287 | POWER_SUPPLY_ATTR(type), |
288 | POWER_SUPPLY_ATTR(usb_type), | ||
244 | POWER_SUPPLY_ATTR(scope), | 289 | POWER_SUPPLY_ATTR(scope), |
245 | POWER_SUPPLY_ATTR(precharge_current), | 290 | POWER_SUPPLY_ATTR(precharge_current), |
246 | POWER_SUPPLY_ATTR(charge_term_current), | 291 | POWER_SUPPLY_ATTR(charge_term_current), |
diff --git a/drivers/staging/typec/Kconfig b/drivers/staging/typec/Kconfig index 5359f556d203..3aa981fbc8f5 100644 --- a/drivers/staging/typec/Kconfig +++ b/drivers/staging/typec/Kconfig | |||
@@ -9,6 +9,14 @@ config TYPEC_TCPCI | |||
9 | help | 9 | help |
10 | Type-C Port Controller driver for TCPCI-compliant controller. | 10 | Type-C Port Controller driver for TCPCI-compliant controller. |
11 | 11 | ||
12 | config TYPEC_RT1711H | ||
13 | tristate "Richtek RT1711H Type-C chip driver" | ||
14 | select TYPEC_TCPCI | ||
15 | help | ||
16 | Richtek RT1711H Type-C chip driver that works with | ||
17 | Type-C Port Controller Manager to provide USB PD and USB | ||
18 | Type-C functionalities. | ||
19 | |||
12 | endif | 20 | endif |
13 | 21 | ||
14 | endmenu | 22 | endmenu |
diff --git a/drivers/staging/typec/Makefile b/drivers/staging/typec/Makefile index 53d649abcb53..7803d485e1b3 100644 --- a/drivers/staging/typec/Makefile +++ b/drivers/staging/typec/Makefile | |||
@@ -1 +1,2 @@ | |||
1 | obj-$(CONFIG_TYPEC_TCPCI) += tcpci.o | 1 | obj-$(CONFIG_TYPEC_TCPCI) += tcpci.o |
2 | obj-$(CONFIG_TYPEC_RT1711H) += tcpci_rt1711h.o | ||
diff --git a/drivers/staging/typec/tcpci.h b/drivers/staging/typec/tcpci.h index 34c865f0dcf6..303ebde26546 100644 --- a/drivers/staging/typec/tcpci.h +++ b/drivers/staging/typec/tcpci.h | |||
@@ -59,6 +59,7 @@ | |||
59 | #define TCPC_POWER_CTRL_VCONN_ENABLE BIT(0) | 59 | #define TCPC_POWER_CTRL_VCONN_ENABLE BIT(0) |
60 | 60 | ||
61 | #define TCPC_CC_STATUS 0x1d | 61 | #define TCPC_CC_STATUS 0x1d |
62 | #define TCPC_CC_STATUS_TOGGLING BIT(5) | ||
62 | #define TCPC_CC_STATUS_TERM BIT(4) | 63 | #define TCPC_CC_STATUS_TERM BIT(4) |
63 | #define TCPC_CC_STATUS_CC2_SHIFT 2 | 64 | #define TCPC_CC_STATUS_CC2_SHIFT 2 |
64 | #define TCPC_CC_STATUS_CC2_MASK 0x3 | 65 | #define TCPC_CC_STATUS_CC2_MASK 0x3 |
diff --git a/drivers/staging/typec/tcpci_rt1711h.c b/drivers/staging/typec/tcpci_rt1711h.c new file mode 100644 index 000000000000..017389021b96 --- /dev/null +++ b/drivers/staging/typec/tcpci_rt1711h.c | |||
@@ -0,0 +1,312 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | /* | ||
3 | * Copyright (C) 2018, Richtek Technology Corporation | ||
4 | * | ||
5 | * Richtek RT1711H Type-C Chip Driver | ||
6 | */ | ||
7 | |||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/module.h> | ||
10 | #include <linux/i2c.h> | ||
11 | #include <linux/interrupt.h> | ||
12 | #include <linux/gpio/consumer.h> | ||
13 | #include <linux/usb/tcpm.h> | ||
14 | #include <linux/regmap.h> | ||
15 | #include "tcpci.h" | ||
16 | |||
17 | #define RT1711H_VID 0x29CF | ||
18 | #define RT1711H_PID 0x1711 | ||
19 | |||
20 | #define RT1711H_RTCTRL8 0x9B | ||
21 | |||
22 | /* Autoidle timeout = (tout * 2 + 1) * 6.4ms */ | ||
23 | #define RT1711H_RTCTRL8_SET(ck300, ship_off, auto_idle, tout) \ | ||
24 | (((ck300) << 7) | ((ship_off) << 5) | \ | ||
25 | ((auto_idle) << 3) | ((tout) & 0x07)) | ||
26 | |||
27 | #define RT1711H_RTCTRL11 0x9E | ||
28 | |||
29 | /* I2C timeout = (tout + 1) * 12.5ms */ | ||
30 | #define RT1711H_RTCTRL11_SET(en, tout) \ | ||
31 | (((en) << 7) | ((tout) & 0x0F)) | ||
32 | |||
33 | #define RT1711H_RTCTRL13 0xA0 | ||
34 | #define RT1711H_RTCTRL14 0xA1 | ||
35 | #define RT1711H_RTCTRL15 0xA2 | ||
36 | #define RT1711H_RTCTRL16 0xA3 | ||
37 | |||
38 | struct rt1711h_chip { | ||
39 | struct tcpci_data data; | ||
40 | struct tcpci *tcpci; | ||
41 | struct device *dev; | ||
42 | }; | ||
43 | |||
44 | static int rt1711h_read16(struct rt1711h_chip *chip, unsigned int reg, u16 *val) | ||
45 | { | ||
46 | return regmap_raw_read(chip->data.regmap, reg, val, sizeof(u16)); | ||
47 | } | ||
48 | |||
49 | static int rt1711h_write16(struct rt1711h_chip *chip, unsigned int reg, u16 val) | ||
50 | { | ||
51 | return regmap_raw_write(chip->data.regmap, reg, &val, sizeof(u16)); | ||
52 | } | ||
53 | |||
54 | static int rt1711h_read8(struct rt1711h_chip *chip, unsigned int reg, u8 *val) | ||
55 | { | ||
56 | return regmap_raw_read(chip->data.regmap, reg, val, sizeof(u8)); | ||
57 | } | ||
58 | |||
59 | static int rt1711h_write8(struct rt1711h_chip *chip, unsigned int reg, u8 val) | ||
60 | { | ||
61 | return regmap_raw_write(chip->data.regmap, reg, &val, sizeof(u8)); | ||
62 | } | ||
63 | |||
64 | static const struct regmap_config rt1711h_regmap_config = { | ||
65 | .reg_bits = 8, | ||
66 | .val_bits = 8, | ||
67 | |||
68 | .max_register = 0xFF, /* 0x80 .. 0xFF are vendor defined */ | ||
69 | }; | ||
70 | |||
71 | static struct rt1711h_chip *tdata_to_rt1711h(struct tcpci_data *tdata) | ||
72 | { | ||
73 | return container_of(tdata, struct rt1711h_chip, data); | ||
74 | } | ||
75 | |||
76 | static int rt1711h_init(struct tcpci *tcpci, struct tcpci_data *tdata) | ||
77 | { | ||
78 | int ret; | ||
79 | struct rt1711h_chip *chip = tdata_to_rt1711h(tdata); | ||
80 | |||
81 | /* CK 300K from 320K, shipping off, auto_idle enable, tout = 32ms */ | ||
82 | ret = rt1711h_write8(chip, RT1711H_RTCTRL8, | ||
83 | RT1711H_RTCTRL8_SET(0, 1, 1, 2)); | ||
84 | if (ret < 0) | ||
85 | return ret; | ||
86 | |||
87 | /* I2C reset : (val + 1) * 12.5ms */ | ||
88 | ret = rt1711h_write8(chip, RT1711H_RTCTRL11, | ||
89 | RT1711H_RTCTRL11_SET(1, 0x0F)); | ||
90 | if (ret < 0) | ||
91 | return ret; | ||
92 | |||
93 | /* tTCPCfilter : (26.7 * val) us */ | ||
94 | ret = rt1711h_write8(chip, RT1711H_RTCTRL14, 0x0F); | ||
95 | if (ret < 0) | ||
96 | return ret; | ||
97 | |||
98 | /* tDRP : (51.2 + 6.4 * val) ms */ | ||
99 | ret = rt1711h_write8(chip, RT1711H_RTCTRL15, 0x04); | ||
100 | if (ret < 0) | ||
101 | return ret; | ||
102 | |||
103 | /* dcSRC.DRP : 33% */ | ||
104 | return rt1711h_write16(chip, RT1711H_RTCTRL16, 330); | ||
105 | } | ||
106 | |||
107 | static int rt1711h_set_vconn(struct tcpci *tcpci, struct tcpci_data *tdata, | ||
108 | bool enable) | ||
109 | { | ||
110 | struct rt1711h_chip *chip = tdata_to_rt1711h(tdata); | ||
111 | |||
112 | return rt1711h_write8(chip, RT1711H_RTCTRL8, | ||
113 | RT1711H_RTCTRL8_SET(0, 1, !enable, 2)); | ||
114 | } | ||
115 | |||
116 | static int rt1711h_start_drp_toggling(struct tcpci *tcpci, | ||
117 | struct tcpci_data *tdata, | ||
118 | enum typec_cc_status cc) | ||
119 | { | ||
120 | struct rt1711h_chip *chip = tdata_to_rt1711h(tdata); | ||
121 | int ret; | ||
122 | unsigned int reg = 0; | ||
123 | |||
124 | switch (cc) { | ||
125 | default: | ||
126 | case TYPEC_CC_RP_DEF: | ||
127 | reg |= (TCPC_ROLE_CTRL_RP_VAL_DEF << | ||
128 | TCPC_ROLE_CTRL_RP_VAL_SHIFT); | ||
129 | break; | ||
130 | case TYPEC_CC_RP_1_5: | ||
131 | reg |= (TCPC_ROLE_CTRL_RP_VAL_1_5 << | ||
132 | TCPC_ROLE_CTRL_RP_VAL_SHIFT); | ||
133 | break; | ||
134 | case TYPEC_CC_RP_3_0: | ||
135 | reg |= (TCPC_ROLE_CTRL_RP_VAL_3_0 << | ||
136 | TCPC_ROLE_CTRL_RP_VAL_SHIFT); | ||
137 | break; | ||
138 | } | ||
139 | |||
140 | if (cc == TYPEC_CC_RD) | ||
141 | reg |= (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC1_SHIFT) | | ||
142 | (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC2_SHIFT); | ||
143 | else | ||
144 | reg |= (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT) | | ||
145 | (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT); | ||
146 | |||
147 | ret = rt1711h_write8(chip, TCPC_ROLE_CTRL, reg); | ||
148 | if (ret < 0) | ||
149 | return ret; | ||
150 | usleep_range(500, 1000); | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static irqreturn_t rt1711h_irq(int irq, void *dev_id) | ||
156 | { | ||
157 | int ret; | ||
158 | u16 alert; | ||
159 | u8 status; | ||
160 | struct rt1711h_chip *chip = dev_id; | ||
161 | |||
162 | if (!chip->tcpci) | ||
163 | return IRQ_HANDLED; | ||
164 | |||
165 | ret = rt1711h_read16(chip, TCPC_ALERT, &alert); | ||
166 | if (ret < 0) | ||
167 | goto out; | ||
168 | |||
169 | if (alert & TCPC_ALERT_CC_STATUS) { | ||
170 | ret = rt1711h_read8(chip, TCPC_CC_STATUS, &status); | ||
171 | if (ret < 0) | ||
172 | goto out; | ||
173 | /* Clear cc change event triggered by starting toggling */ | ||
174 | if (status & TCPC_CC_STATUS_TOGGLING) | ||
175 | rt1711h_write8(chip, TCPC_ALERT, TCPC_ALERT_CC_STATUS); | ||
176 | } | ||
177 | |||
178 | out: | ||
179 | return tcpci_irq(chip->tcpci); | ||
180 | } | ||
181 | |||
182 | static int rt1711h_init_alert(struct rt1711h_chip *chip, | ||
183 | struct i2c_client *client) | ||
184 | { | ||
185 | int ret; | ||
186 | |||
187 | /* Disable chip interrupts before requesting irq */ | ||
188 | ret = rt1711h_write16(chip, TCPC_ALERT_MASK, 0); | ||
189 | if (ret < 0) | ||
190 | return ret; | ||
191 | |||
192 | ret = devm_request_threaded_irq(chip->dev, client->irq, NULL, | ||
193 | rt1711h_irq, | ||
194 | IRQF_ONESHOT | IRQF_TRIGGER_LOW, | ||
195 | dev_name(chip->dev), chip); | ||
196 | if (ret < 0) | ||
197 | return ret; | ||
198 | enable_irq_wake(client->irq); | ||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static int rt1711h_sw_reset(struct rt1711h_chip *chip) | ||
203 | { | ||
204 | int ret; | ||
205 | |||
206 | ret = rt1711h_write8(chip, RT1711H_RTCTRL13, 0x01); | ||
207 | if (ret < 0) | ||
208 | return ret; | ||
209 | |||
210 | usleep_range(1000, 2000); | ||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static int rt1711h_check_revision(struct i2c_client *i2c) | ||
215 | { | ||
216 | int ret; | ||
217 | |||
218 | ret = i2c_smbus_read_word_data(i2c, TCPC_VENDOR_ID); | ||
219 | if (ret < 0) | ||
220 | return ret; | ||
221 | if (ret != RT1711H_VID) { | ||
222 | dev_err(&i2c->dev, "vid is not correct, 0x%04x\n", ret); | ||
223 | return -ENODEV; | ||
224 | } | ||
225 | ret = i2c_smbus_read_word_data(i2c, TCPC_PRODUCT_ID); | ||
226 | if (ret < 0) | ||
227 | return ret; | ||
228 | if (ret != RT1711H_PID) { | ||
229 | dev_err(&i2c->dev, "pid is not correct, 0x%04x\n", ret); | ||
230 | return -ENODEV; | ||
231 | } | ||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | static int rt1711h_probe(struct i2c_client *client, | ||
236 | const struct i2c_device_id *i2c_id) | ||
237 | { | ||
238 | int ret; | ||
239 | struct rt1711h_chip *chip; | ||
240 | |||
241 | ret = rt1711h_check_revision(client); | ||
242 | if (ret < 0) { | ||
243 | dev_err(&client->dev, "check vid/pid fail\n"); | ||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); | ||
248 | if (!chip) | ||
249 | return -ENOMEM; | ||
250 | |||
251 | chip->data.regmap = devm_regmap_init_i2c(client, | ||
252 | &rt1711h_regmap_config); | ||
253 | if (IS_ERR(chip->data.regmap)) | ||
254 | return PTR_ERR(chip->data.regmap); | ||
255 | |||
256 | chip->dev = &client->dev; | ||
257 | i2c_set_clientdata(client, chip); | ||
258 | |||
259 | ret = rt1711h_sw_reset(chip); | ||
260 | if (ret < 0) | ||
261 | return ret; | ||
262 | |||
263 | ret = rt1711h_init_alert(chip, client); | ||
264 | if (ret < 0) | ||
265 | return ret; | ||
266 | |||
267 | chip->data.init = rt1711h_init; | ||
268 | chip->data.set_vconn = rt1711h_set_vconn; | ||
269 | chip->data.start_drp_toggling = rt1711h_start_drp_toggling; | ||
270 | chip->tcpci = tcpci_register_port(chip->dev, &chip->data); | ||
271 | if (IS_ERR_OR_NULL(chip->tcpci)) | ||
272 | return PTR_ERR(chip->tcpci); | ||
273 | |||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | static int rt1711h_remove(struct i2c_client *client) | ||
278 | { | ||
279 | struct rt1711h_chip *chip = i2c_get_clientdata(client); | ||
280 | |||
281 | tcpci_unregister_port(chip->tcpci); | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static const struct i2c_device_id rt1711h_id[] = { | ||
286 | { "rt1711h", 0 }, | ||
287 | { } | ||
288 | }; | ||
289 | MODULE_DEVICE_TABLE(i2c, rt1711h_id); | ||
290 | |||
291 | #ifdef CONFIG_OF | ||
292 | static const struct of_device_id rt1711h_of_match[] = { | ||
293 | { .compatible = "richtek,rt1711h", }, | ||
294 | {}, | ||
295 | }; | ||
296 | MODULE_DEVICE_TABLE(of, rt1711h_of_match); | ||
297 | #endif | ||
298 | |||
299 | static struct i2c_driver rt1711h_i2c_driver = { | ||
300 | .driver = { | ||
301 | .name = "rt1711h", | ||
302 | .of_match_table = of_match_ptr(rt1711h_of_match), | ||
303 | }, | ||
304 | .probe = rt1711h_probe, | ||
305 | .remove = rt1711h_remove, | ||
306 | .id_table = rt1711h_id, | ||
307 | }; | ||
308 | module_i2c_driver(rt1711h_i2c_driver); | ||
309 | |||
310 | MODULE_AUTHOR("ShuFan Lee <shufan_lee@richtek.com>"); | ||
311 | MODULE_DESCRIPTION("RT1711H USB Type-C Port Controller Interface Driver"); | ||
312 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index d9b561d89432..d99fec44036c 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c | |||
@@ -290,7 +290,7 @@ EXPORT_SYMBOL(tty_termios_copy_hw); | |||
290 | * between the two termios structures, or a speed change is needed. | 290 | * between the two termios structures, or a speed change is needed. |
291 | */ | 291 | */ |
292 | 292 | ||
293 | int tty_termios_hw_change(struct ktermios *a, struct ktermios *b) | 293 | int tty_termios_hw_change(const struct ktermios *a, const struct ktermios *b) |
294 | { | 294 | { |
295 | if (a->c_ispeed != b->c_ispeed || a->c_ospeed != b->c_ospeed) | 295 | if (a->c_ispeed != b->c_ispeed || a->c_ospeed != b->c_ospeed) |
296 | return 1; | 296 | return 1; |
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h index 98b7cb3d0064..0bf244d50544 100644 --- a/drivers/usb/chipidea/ci.h +++ b/drivers/usb/chipidea/ci.h | |||
@@ -450,7 +450,7 @@ void hw_phymode_configure(struct ci_hdrc *ci); | |||
450 | 450 | ||
451 | void ci_platform_configure(struct ci_hdrc *ci); | 451 | void ci_platform_configure(struct ci_hdrc *ci); |
452 | 452 | ||
453 | int dbg_create_files(struct ci_hdrc *ci); | 453 | void dbg_create_files(struct ci_hdrc *ci); |
454 | 454 | ||
455 | void dbg_remove_files(struct ci_hdrc *ci); | 455 | void dbg_remove_files(struct ci_hdrc *ci); |
456 | #endif /* __DRIVERS_USB_CHIPIDEA_CI_H */ | 456 | #endif /* __DRIVERS_USB_CHIPIDEA_CI_H */ |
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index e431c5aafe35..19f5f5f2a48a 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.c +++ b/drivers/usb/chipidea/ci_hdrc_imx.c | |||
@@ -291,7 +291,8 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) | |||
291 | 291 | ||
292 | pdata.usb_phy = data->phy; | 292 | pdata.usb_phy = data->phy; |
293 | 293 | ||
294 | if (of_device_is_compatible(np, "fsl,imx53-usb") && pdata.usb_phy && | 294 | if ((of_device_is_compatible(np, "fsl,imx53-usb") || |
295 | of_device_is_compatible(np, "fsl,imx51-usb")) && pdata.usb_phy && | ||
295 | of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI) { | 296 | of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI) { |
296 | pdata.flags |= CI_HDRC_OVERRIDE_PHY_CONTROL; | 297 | pdata.flags |= CI_HDRC_OVERRIDE_PHY_CONTROL; |
297 | data->override_phy_control = true; | 298 | data->override_phy_control = true; |
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 33ae87fa3ff3..85fc6db48e44 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c | |||
@@ -1062,9 +1062,7 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
1062 | ci_hdrc_otg_fsm_start(ci); | 1062 | ci_hdrc_otg_fsm_start(ci); |
1063 | 1063 | ||
1064 | device_set_wakeup_capable(&pdev->dev, true); | 1064 | device_set_wakeup_capable(&pdev->dev, true); |
1065 | ret = dbg_create_files(ci); | 1065 | dbg_create_files(ci); |
1066 | if (ret) | ||
1067 | goto stop; | ||
1068 | 1066 | ||
1069 | ret = sysfs_create_group(&dev->kobj, &ci_attr_group); | 1067 | ret = sysfs_create_group(&dev->kobj, &ci_attr_group); |
1070 | if (ret) | 1068 | if (ret) |
diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c index ce648cb3ed94..fcc91a338875 100644 --- a/drivers/usb/chipidea/debug.c +++ b/drivers/usb/chipidea/debug.c | |||
@@ -340,54 +340,28 @@ DEFINE_SHOW_ATTRIBUTE(ci_registers); | |||
340 | * | 340 | * |
341 | * This function returns an error code | 341 | * This function returns an error code |
342 | */ | 342 | */ |
343 | int dbg_create_files(struct ci_hdrc *ci) | 343 | void dbg_create_files(struct ci_hdrc *ci) |
344 | { | 344 | { |
345 | struct dentry *dent; | ||
346 | |||
347 | ci->debugfs = debugfs_create_dir(dev_name(ci->dev), NULL); | 345 | ci->debugfs = debugfs_create_dir(dev_name(ci->dev), NULL); |
348 | if (!ci->debugfs) | ||
349 | return -ENOMEM; | ||
350 | |||
351 | dent = debugfs_create_file("device", S_IRUGO, ci->debugfs, ci, | ||
352 | &ci_device_fops); | ||
353 | if (!dent) | ||
354 | goto err; | ||
355 | |||
356 | dent = debugfs_create_file("port_test", S_IRUGO | S_IWUSR, ci->debugfs, | ||
357 | ci, &ci_port_test_fops); | ||
358 | if (!dent) | ||
359 | goto err; | ||
360 | |||
361 | dent = debugfs_create_file("qheads", S_IRUGO, ci->debugfs, ci, | ||
362 | &ci_qheads_fops); | ||
363 | if (!dent) | ||
364 | goto err; | ||
365 | 346 | ||
366 | dent = debugfs_create_file("requests", S_IRUGO, ci->debugfs, ci, | 347 | debugfs_create_file("device", S_IRUGO, ci->debugfs, ci, |
367 | &ci_requests_fops); | 348 | &ci_device_fops); |
368 | if (!dent) | 349 | debugfs_create_file("port_test", S_IRUGO | S_IWUSR, ci->debugfs, ci, |
369 | goto err; | 350 | &ci_port_test_fops); |
351 | debugfs_create_file("qheads", S_IRUGO, ci->debugfs, ci, | ||
352 | &ci_qheads_fops); | ||
353 | debugfs_create_file("requests", S_IRUGO, ci->debugfs, ci, | ||
354 | &ci_requests_fops); | ||
370 | 355 | ||
371 | if (ci_otg_is_fsm_mode(ci)) { | 356 | if (ci_otg_is_fsm_mode(ci)) { |
372 | dent = debugfs_create_file("otg", S_IRUGO, ci->debugfs, ci, | 357 | debugfs_create_file("otg", S_IRUGO, ci->debugfs, ci, |
373 | &ci_otg_fops); | 358 | &ci_otg_fops); |
374 | if (!dent) | ||
375 | goto err; | ||
376 | } | 359 | } |
377 | 360 | ||
378 | dent = debugfs_create_file("role", S_IRUGO | S_IWUSR, ci->debugfs, ci, | 361 | debugfs_create_file("role", S_IRUGO | S_IWUSR, ci->debugfs, ci, |
379 | &ci_role_fops); | 362 | &ci_role_fops); |
380 | if (!dent) | 363 | debugfs_create_file("registers", S_IRUGO, ci->debugfs, ci, |
381 | goto err; | 364 | &ci_registers_fops); |
382 | |||
383 | dent = debugfs_create_file("registers", S_IRUGO, ci->debugfs, ci, | ||
384 | &ci_registers_fops); | ||
385 | |||
386 | if (dent) | ||
387 | return 0; | ||
388 | err: | ||
389 | debugfs_remove_recursive(ci->debugfs); | ||
390 | return -ENOMEM; | ||
391 | } | 365 | } |
392 | 366 | ||
393 | /** | 367 | /** |
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index bdb1de0c0cef..529295a17579 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/usb/tmc.h> | 21 | #include <linux/usb/tmc.h> |
22 | 22 | ||
23 | 23 | ||
24 | #define RIGOL 1 | ||
25 | #define USBTMC_HEADER_SIZE 12 | 24 | #define USBTMC_HEADER_SIZE 12 |
26 | #define USBTMC_MINOR_BASE 176 | 25 | #define USBTMC_MINOR_BASE 176 |
27 | 26 | ||
@@ -93,8 +92,6 @@ struct usbtmc_device_data { | |||
93 | /* coalesced usb488_caps from usbtmc_dev_capabilities */ | 92 | /* coalesced usb488_caps from usbtmc_dev_capabilities */ |
94 | __u8 usb488_caps; | 93 | __u8 usb488_caps; |
95 | 94 | ||
96 | u8 rigol_quirk; | ||
97 | |||
98 | /* attributes from the USB TMC spec for this device */ | 95 | /* attributes from the USB TMC spec for this device */ |
99 | u8 TermChar; | 96 | u8 TermChar; |
100 | bool TermCharEnabled; | 97 | bool TermCharEnabled; |
@@ -110,17 +107,6 @@ struct usbtmc_device_data { | |||
110 | }; | 107 | }; |
111 | #define to_usbtmc_data(d) container_of(d, struct usbtmc_device_data, kref) | 108 | #define to_usbtmc_data(d) container_of(d, struct usbtmc_device_data, kref) |
112 | 109 | ||
113 | struct usbtmc_ID_rigol_quirk { | ||
114 | __u16 idVendor; | ||
115 | __u16 idProduct; | ||
116 | }; | ||
117 | |||
118 | static const struct usbtmc_ID_rigol_quirk usbtmc_id_quirk[] = { | ||
119 | { 0x1ab1, 0x0588 }, | ||
120 | { 0x1ab1, 0x04b0 }, | ||
121 | { 0, 0 } | ||
122 | }; | ||
123 | |||
124 | /* Forward declarations */ | 110 | /* Forward declarations */ |
125 | static struct usb_driver usbtmc_driver; | 111 | static struct usb_driver usbtmc_driver; |
126 | 112 | ||
@@ -603,16 +589,14 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, | |||
603 | goto exit; | 589 | goto exit; |
604 | } | 590 | } |
605 | 591 | ||
606 | if (data->rigol_quirk) { | 592 | dev_dbg(dev, "usb_bulk_msg_in: count(%zu)\n", count); |
607 | dev_dbg(dev, "usb_bulk_msg_in: count(%zu)\n", count); | ||
608 | 593 | ||
609 | retval = send_request_dev_dep_msg_in(data, count); | 594 | retval = send_request_dev_dep_msg_in(data, count); |
610 | 595 | ||
611 | if (retval < 0) { | 596 | if (retval < 0) { |
612 | if (data->auto_abort) | 597 | if (data->auto_abort) |
613 | usbtmc_ioctl_abort_bulk_out(data); | 598 | usbtmc_ioctl_abort_bulk_out(data); |
614 | goto exit; | 599 | goto exit; |
615 | } | ||
616 | } | 600 | } |
617 | 601 | ||
618 | /* Loop until we have fetched everything we requested */ | 602 | /* Loop until we have fetched everything we requested */ |
@@ -621,23 +605,6 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, | |||
621 | done = 0; | 605 | done = 0; |
622 | 606 | ||
623 | while (remaining > 0) { | 607 | while (remaining > 0) { |
624 | if (!data->rigol_quirk) { | ||
625 | dev_dbg(dev, "usb_bulk_msg_in: remaining(%zu), count(%zu)\n", remaining, count); | ||
626 | |||
627 | if (remaining > USBTMC_SIZE_IOBUFFER - USBTMC_HEADER_SIZE - 3) | ||
628 | this_part = USBTMC_SIZE_IOBUFFER - USBTMC_HEADER_SIZE - 3; | ||
629 | else | ||
630 | this_part = remaining; | ||
631 | |||
632 | retval = send_request_dev_dep_msg_in(data, this_part); | ||
633 | if (retval < 0) { | ||
634 | dev_err(dev, "usb_bulk_msg returned %d\n", retval); | ||
635 | if (data->auto_abort) | ||
636 | usbtmc_ioctl_abort_bulk_out(data); | ||
637 | goto exit; | ||
638 | } | ||
639 | } | ||
640 | |||
641 | /* Send bulk URB */ | 608 | /* Send bulk URB */ |
642 | retval = usb_bulk_msg(data->usb_dev, | 609 | retval = usb_bulk_msg(data->usb_dev, |
643 | usb_rcvbulkpipe(data->usb_dev, | 610 | usb_rcvbulkpipe(data->usb_dev, |
@@ -658,7 +625,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, | |||
658 | } | 625 | } |
659 | 626 | ||
660 | /* Parse header in first packet */ | 627 | /* Parse header in first packet */ |
661 | if ((done == 0) || !data->rigol_quirk) { | 628 | if (done == 0) { |
662 | /* Sanity checks for the header */ | 629 | /* Sanity checks for the header */ |
663 | if (actual < USBTMC_HEADER_SIZE) { | 630 | if (actual < USBTMC_HEADER_SIZE) { |
664 | dev_err(dev, "Device sent too small first packet: %u < %u\n", actual, USBTMC_HEADER_SIZE); | 631 | dev_err(dev, "Device sent too small first packet: %u < %u\n", actual, USBTMC_HEADER_SIZE); |
@@ -698,20 +665,11 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, | |||
698 | actual -= USBTMC_HEADER_SIZE; | 665 | actual -= USBTMC_HEADER_SIZE; |
699 | 666 | ||
700 | /* Check if the message is smaller than requested */ | 667 | /* Check if the message is smaller than requested */ |
701 | if (data->rigol_quirk) { | 668 | if (remaining > n_characters) |
702 | if (remaining > n_characters) | 669 | remaining = n_characters; |
703 | remaining = n_characters; | 670 | /* Remove padding if it exists */ |
704 | /* Remove padding if it exists */ | 671 | if (actual > remaining) |
705 | if (actual > remaining) | 672 | actual = remaining; |
706 | actual = remaining; | ||
707 | } | ||
708 | else { | ||
709 | if (this_part > n_characters) | ||
710 | this_part = n_characters; | ||
711 | /* Remove padding if it exists */ | ||
712 | if (actual > this_part) | ||
713 | actual = this_part; | ||
714 | } | ||
715 | 673 | ||
716 | dev_dbg(dev, "Bulk-IN header: N_characters(%u), bTransAttr(%u)\n", n_characters, buffer[8]); | 674 | dev_dbg(dev, "Bulk-IN header: N_characters(%u), bTransAttr(%u)\n", n_characters, buffer[8]); |
717 | 675 | ||
@@ -1365,7 +1323,6 @@ static int usbtmc_probe(struct usb_interface *intf, | |||
1365 | struct usbtmc_device_data *data; | 1323 | struct usbtmc_device_data *data; |
1366 | struct usb_host_interface *iface_desc; | 1324 | struct usb_host_interface *iface_desc; |
1367 | struct usb_endpoint_descriptor *bulk_in, *bulk_out, *int_in; | 1325 | struct usb_endpoint_descriptor *bulk_in, *bulk_out, *int_in; |
1368 | int n; | ||
1369 | int retcode; | 1326 | int retcode; |
1370 | 1327 | ||
1371 | dev_dbg(&intf->dev, "%s called\n", __func__); | 1328 | dev_dbg(&intf->dev, "%s called\n", __func__); |
@@ -1385,20 +1342,6 @@ static int usbtmc_probe(struct usb_interface *intf, | |||
1385 | atomic_set(&data->srq_asserted, 0); | 1342 | atomic_set(&data->srq_asserted, 0); |
1386 | data->zombie = 0; | 1343 | data->zombie = 0; |
1387 | 1344 | ||
1388 | /* Determine if it is a Rigol or not */ | ||
1389 | data->rigol_quirk = 0; | ||
1390 | dev_dbg(&intf->dev, "Trying to find if device Vendor 0x%04X Product 0x%04X has the RIGOL quirk\n", | ||
1391 | le16_to_cpu(data->usb_dev->descriptor.idVendor), | ||
1392 | le16_to_cpu(data->usb_dev->descriptor.idProduct)); | ||
1393 | for(n = 0; usbtmc_id_quirk[n].idVendor > 0; n++) { | ||
1394 | if ((usbtmc_id_quirk[n].idVendor == le16_to_cpu(data->usb_dev->descriptor.idVendor)) && | ||
1395 | (usbtmc_id_quirk[n].idProduct == le16_to_cpu(data->usb_dev->descriptor.idProduct))) { | ||
1396 | dev_dbg(&intf->dev, "Setting this device as having the RIGOL quirk\n"); | ||
1397 | data->rigol_quirk = 1; | ||
1398 | break; | ||
1399 | } | ||
1400 | } | ||
1401 | |||
1402 | /* Initialize USBTMC bTag and other fields */ | 1345 | /* Initialize USBTMC bTag and other fields */ |
1403 | data->bTag = 1; | 1346 | data->bTag = 1; |
1404 | data->TermCharEnabled = 0; | 1347 | data->TermCharEnabled = 0; |
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 0a42c5df3c0f..1c21955fe7c0 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <linux/phy/phy.h> | 33 | #include <linux/phy/phy.h> |
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/phy.h> | ||
37 | #include <linux/usb/otg.h> | 36 | #include <linux/usb/otg.h> |
38 | 37 | ||
39 | #include "usb.h" | 38 | #include "usb.h" |
@@ -568,6 +567,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) | |||
568 | switch (wValue & 0xff00) { | 567 | switch (wValue & 0xff00) { |
569 | case USB_DT_DEVICE << 8: | 568 | case USB_DT_DEVICE << 8: |
570 | switch (hcd->speed) { | 569 | switch (hcd->speed) { |
570 | case HCD_USB32: | ||
571 | case HCD_USB31: | 571 | case HCD_USB31: |
572 | bufp = usb31_rh_dev_descriptor; | 572 | bufp = usb31_rh_dev_descriptor; |
573 | break; | 573 | break; |
@@ -592,6 +592,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) | |||
592 | break; | 592 | break; |
593 | case USB_DT_CONFIG << 8: | 593 | case USB_DT_CONFIG << 8: |
594 | switch (hcd->speed) { | 594 | switch (hcd->speed) { |
595 | case HCD_USB32: | ||
595 | case HCD_USB31: | 596 | case HCD_USB31: |
596 | case HCD_USB3: | 597 | case HCD_USB3: |
597 | bufp = ss_rh_config_descriptor; | 598 | bufp = ss_rh_config_descriptor; |
@@ -2742,34 +2743,14 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
2742 | int retval; | 2743 | int retval; |
2743 | struct usb_device *rhdev; | 2744 | struct usb_device *rhdev; |
2744 | 2745 | ||
2745 | if (IS_ENABLED(CONFIG_USB_PHY) && !hcd->skip_phy_initialization) { | ||
2746 | struct usb_phy *phy = usb_get_phy_dev(hcd->self.sysdev, 0); | ||
2747 | |||
2748 | if (IS_ERR(phy)) { | ||
2749 | retval = PTR_ERR(phy); | ||
2750 | if (retval == -EPROBE_DEFER) | ||
2751 | return retval; | ||
2752 | } else { | ||
2753 | retval = usb_phy_init(phy); | ||
2754 | if (retval) { | ||
2755 | usb_put_phy(phy); | ||
2756 | return retval; | ||
2757 | } | ||
2758 | hcd->usb_phy = phy; | ||
2759 | hcd->remove_phy = 1; | ||
2760 | } | ||
2761 | } | ||
2762 | |||
2763 | if (!hcd->skip_phy_initialization && usb_hcd_is_primary_hcd(hcd)) { | 2746 | if (!hcd->skip_phy_initialization && usb_hcd_is_primary_hcd(hcd)) { |
2764 | hcd->phy_roothub = usb_phy_roothub_alloc(hcd->self.sysdev); | 2747 | hcd->phy_roothub = usb_phy_roothub_alloc(hcd->self.sysdev); |
2765 | if (IS_ERR(hcd->phy_roothub)) { | 2748 | if (IS_ERR(hcd->phy_roothub)) |
2766 | retval = PTR_ERR(hcd->phy_roothub); | 2749 | return PTR_ERR(hcd->phy_roothub); |
2767 | goto err_phy_roothub_alloc; | ||
2768 | } | ||
2769 | 2750 | ||
2770 | retval = usb_phy_roothub_init(hcd->phy_roothub); | 2751 | retval = usb_phy_roothub_init(hcd->phy_roothub); |
2771 | if (retval) | 2752 | if (retval) |
2772 | goto err_phy_roothub_alloc; | 2753 | return retval; |
2773 | 2754 | ||
2774 | retval = usb_phy_roothub_power_on(hcd->phy_roothub); | 2755 | retval = usb_phy_roothub_power_on(hcd->phy_roothub); |
2775 | if (retval) | 2756 | if (retval) |
@@ -2819,6 +2800,9 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
2819 | hcd->self.root_hub = rhdev; | 2800 | hcd->self.root_hub = rhdev; |
2820 | mutex_unlock(&usb_port_peer_mutex); | 2801 | mutex_unlock(&usb_port_peer_mutex); |
2821 | 2802 | ||
2803 | rhdev->rx_lanes = 1; | ||
2804 | rhdev->tx_lanes = 1; | ||
2805 | |||
2822 | switch (hcd->speed) { | 2806 | switch (hcd->speed) { |
2823 | case HCD_USB11: | 2807 | case HCD_USB11: |
2824 | rhdev->speed = USB_SPEED_FULL; | 2808 | rhdev->speed = USB_SPEED_FULL; |
@@ -2832,6 +2816,10 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
2832 | case HCD_USB3: | 2816 | case HCD_USB3: |
2833 | rhdev->speed = USB_SPEED_SUPER; | 2817 | rhdev->speed = USB_SPEED_SUPER; |
2834 | break; | 2818 | break; |
2819 | case HCD_USB32: | ||
2820 | rhdev->rx_lanes = 2; | ||
2821 | rhdev->tx_lanes = 2; | ||
2822 | /* fall through */ | ||
2835 | case HCD_USB31: | 2823 | case HCD_USB31: |
2836 | rhdev->speed = USB_SPEED_SUPER_PLUS; | 2824 | rhdev->speed = USB_SPEED_SUPER_PLUS; |
2837 | break; | 2825 | break; |
@@ -2943,12 +2931,7 @@ err_create_buf: | |||
2943 | usb_phy_roothub_power_off(hcd->phy_roothub); | 2931 | usb_phy_roothub_power_off(hcd->phy_roothub); |
2944 | err_usb_phy_roothub_power_on: | 2932 | err_usb_phy_roothub_power_on: |
2945 | usb_phy_roothub_exit(hcd->phy_roothub); | 2933 | usb_phy_roothub_exit(hcd->phy_roothub); |
2946 | err_phy_roothub_alloc: | 2934 | |
2947 | if (hcd->remove_phy && hcd->usb_phy) { | ||
2948 | usb_phy_shutdown(hcd->usb_phy); | ||
2949 | usb_put_phy(hcd->usb_phy); | ||
2950 | hcd->usb_phy = NULL; | ||
2951 | } | ||
2952 | return retval; | 2935 | return retval; |
2953 | } | 2936 | } |
2954 | EXPORT_SYMBOL_GPL(usb_add_hcd); | 2937 | EXPORT_SYMBOL_GPL(usb_add_hcd); |
@@ -3024,12 +3007,6 @@ void usb_remove_hcd(struct usb_hcd *hcd) | |||
3024 | usb_phy_roothub_power_off(hcd->phy_roothub); | 3007 | usb_phy_roothub_power_off(hcd->phy_roothub); |
3025 | usb_phy_roothub_exit(hcd->phy_roothub); | 3008 | usb_phy_roothub_exit(hcd->phy_roothub); |
3026 | 3009 | ||
3027 | if (hcd->remove_phy && hcd->usb_phy) { | ||
3028 | usb_phy_shutdown(hcd->usb_phy); | ||
3029 | usb_put_phy(hcd->usb_phy); | ||
3030 | hcd->usb_phy = NULL; | ||
3031 | } | ||
3032 | |||
3033 | usb_put_invalidate_rhdev(hcd); | 3010 | usb_put_invalidate_rhdev(hcd); |
3034 | hcd->flags = 0; | 3011 | hcd->flags = 0; |
3035 | } | 3012 | } |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index aa9968d90a48..26c2438d2889 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -2636,7 +2636,7 @@ static unsigned hub_is_wusb(struct usb_hub *hub) | |||
2636 | #define SET_ADDRESS_TRIES 2 | 2636 | #define SET_ADDRESS_TRIES 2 |
2637 | #define GET_DESCRIPTOR_TRIES 2 | 2637 | #define GET_DESCRIPTOR_TRIES 2 |
2638 | #define SET_CONFIG_TRIES (2 * (use_both_schemes + 1)) | 2638 | #define SET_CONFIG_TRIES (2 * (use_both_schemes + 1)) |
2639 | #define USE_NEW_SCHEME(i) ((i) / 2 == (int)old_scheme_first) | 2639 | #define USE_NEW_SCHEME(i, scheme) ((i) / 2 == (int)scheme) |
2640 | 2640 | ||
2641 | #define HUB_ROOT_RESET_TIME 60 /* times are in msec */ | 2641 | #define HUB_ROOT_RESET_TIME 60 /* times are in msec */ |
2642 | #define HUB_SHORT_RESET_TIME 10 | 2642 | #define HUB_SHORT_RESET_TIME 10 |
@@ -2651,12 +2651,16 @@ static unsigned hub_is_wusb(struct usb_hub *hub) | |||
2651 | * enumeration failures, so disable this enumeration scheme for USB3 | 2651 | * enumeration failures, so disable this enumeration scheme for USB3 |
2652 | * devices. | 2652 | * devices. |
2653 | */ | 2653 | */ |
2654 | static bool use_new_scheme(struct usb_device *udev, int retry) | 2654 | static bool use_new_scheme(struct usb_device *udev, int retry, |
2655 | struct usb_port *port_dev) | ||
2655 | { | 2656 | { |
2657 | int old_scheme_first_port = | ||
2658 | port_dev->quirks & USB_PORT_QUIRK_OLD_SCHEME; | ||
2659 | |||
2656 | if (udev->speed >= USB_SPEED_SUPER) | 2660 | if (udev->speed >= USB_SPEED_SUPER) |
2657 | return false; | 2661 | return false; |
2658 | 2662 | ||
2659 | return USE_NEW_SCHEME(retry); | 2663 | return USE_NEW_SCHEME(retry, old_scheme_first_port || old_scheme_first); |
2660 | } | 2664 | } |
2661 | 2665 | ||
2662 | /* Is a USB 3.0 port in the Inactive or Compliance Mode state? | 2666 | /* Is a USB 3.0 port in the Inactive or Compliance Mode state? |
@@ -2751,6 +2755,14 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, | |||
2751 | if (!udev) | 2755 | if (!udev) |
2752 | return 0; | 2756 | return 0; |
2753 | 2757 | ||
2758 | if (hub_is_superspeedplus(hub->hdev)) { | ||
2759 | /* extended portstatus Rx and Tx lane count are zero based */ | ||
2760 | udev->rx_lanes = USB_EXT_PORT_RX_LANES(ext_portstatus) + 1; | ||
2761 | udev->tx_lanes = USB_EXT_PORT_TX_LANES(ext_portstatus) + 1; | ||
2762 | } else { | ||
2763 | udev->rx_lanes = 1; | ||
2764 | udev->tx_lanes = 1; | ||
2765 | } | ||
2754 | if (hub_is_wusb(hub)) | 2766 | if (hub_is_wusb(hub)) |
2755 | udev->speed = USB_SPEED_WIRELESS; | 2767 | udev->speed = USB_SPEED_WIRELESS; |
2756 | else if (hub_is_superspeedplus(hub->hdev) && | 2768 | else if (hub_is_superspeedplus(hub->hdev) && |
@@ -2867,7 +2879,11 @@ static int hub_port_reset(struct usb_hub *hub, int port1, | |||
2867 | done: | 2879 | done: |
2868 | if (status == 0) { | 2880 | if (status == 0) { |
2869 | /* TRSTRCY = 10 ms; plus some extra */ | 2881 | /* TRSTRCY = 10 ms; plus some extra */ |
2870 | msleep(10 + 40); | 2882 | if (port_dev->quirks & USB_PORT_QUIRK_FAST_ENUM) |
2883 | usleep_range(10000, 12000); | ||
2884 | else | ||
2885 | msleep(10 + 40); | ||
2886 | |||
2871 | if (udev) { | 2887 | if (udev) { |
2872 | struct usb_hcd *hcd = bus_to_hcd(udev->bus); | 2888 | struct usb_hcd *hcd = bus_to_hcd(udev->bus); |
2873 | 2889 | ||
@@ -3376,6 +3392,10 @@ static int wait_for_connected(struct usb_device *udev, | |||
3376 | while (delay_ms < 2000) { | 3392 | while (delay_ms < 2000) { |
3377 | if (status || *portstatus & USB_PORT_STAT_CONNECTION) | 3393 | if (status || *portstatus & USB_PORT_STAT_CONNECTION) |
3378 | break; | 3394 | break; |
3395 | if (!port_is_power_on(hub, *portstatus)) { | ||
3396 | status = -ENODEV; | ||
3397 | break; | ||
3398 | } | ||
3379 | msleep(20); | 3399 | msleep(20); |
3380 | delay_ms += 20; | 3400 | delay_ms += 20; |
3381 | status = hub_port_status(hub, *port1, portstatus, portchange); | 3401 | status = hub_port_status(hub, *port1, portstatus, portchange); |
@@ -4380,6 +4400,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, | |||
4380 | { | 4400 | { |
4381 | struct usb_device *hdev = hub->hdev; | 4401 | struct usb_device *hdev = hub->hdev; |
4382 | struct usb_hcd *hcd = bus_to_hcd(hdev->bus); | 4402 | struct usb_hcd *hcd = bus_to_hcd(hdev->bus); |
4403 | struct usb_port *port_dev = hub->ports[port1 - 1]; | ||
4383 | int retries, operations, retval, i; | 4404 | int retries, operations, retval, i; |
4384 | unsigned delay = HUB_SHORT_RESET_TIME; | 4405 | unsigned delay = HUB_SHORT_RESET_TIME; |
4385 | enum usb_device_speed oldspeed = udev->speed; | 4406 | enum usb_device_speed oldspeed = udev->speed; |
@@ -4501,7 +4522,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, | |||
4501 | for (retries = 0; retries < GET_DESCRIPTOR_TRIES; (++retries, msleep(100))) { | 4522 | for (retries = 0; retries < GET_DESCRIPTOR_TRIES; (++retries, msleep(100))) { |
4502 | bool did_new_scheme = false; | 4523 | bool did_new_scheme = false; |
4503 | 4524 | ||
4504 | if (use_new_scheme(udev, retry_counter)) { | 4525 | if (use_new_scheme(udev, retry_counter, port_dev)) { |
4505 | struct usb_device_descriptor *buf; | 4526 | struct usb_device_descriptor *buf; |
4506 | int r = 0; | 4527 | int r = 0; |
4507 | 4528 | ||
@@ -4551,7 +4572,9 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, | |||
4551 | * reset. But only on the first attempt, | 4572 | * reset. But only on the first attempt, |
4552 | * lest we get into a time out/reset loop | 4573 | * lest we get into a time out/reset loop |
4553 | */ | 4574 | */ |
4554 | if (r == 0 || (r == -ETIMEDOUT && retries == 0)) | 4575 | if (r == 0 || (r == -ETIMEDOUT && |
4576 | retries == 0 && | ||
4577 | udev->speed > USB_SPEED_FULL)) | ||
4555 | break; | 4578 | break; |
4556 | } | 4579 | } |
4557 | udev->descriptor.bMaxPacketSize0 = | 4580 | udev->descriptor.bMaxPacketSize0 = |
@@ -4598,9 +4621,12 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, | |||
4598 | if (udev->speed >= USB_SPEED_SUPER) { | 4621 | if (udev->speed >= USB_SPEED_SUPER) { |
4599 | devnum = udev->devnum; | 4622 | devnum = udev->devnum; |
4600 | dev_info(&udev->dev, | 4623 | dev_info(&udev->dev, |
4601 | "%s SuperSpeed%s USB device number %d using %s\n", | 4624 | "%s SuperSpeed%s%s USB device number %d using %s\n", |
4602 | (udev->config) ? "reset" : "new", | 4625 | (udev->config) ? "reset" : "new", |
4603 | (udev->speed == USB_SPEED_SUPER_PLUS) ? "Plus" : "", | 4626 | (udev->speed == USB_SPEED_SUPER_PLUS) ? |
4627 | "Plus Gen 2" : " Gen 1", | ||
4628 | (udev->rx_lanes == 2 && udev->tx_lanes == 2) ? | ||
4629 | "x2" : "", | ||
4604 | devnum, driver_name); | 4630 | devnum, driver_name); |
4605 | } | 4631 | } |
4606 | 4632 | ||
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index 4dc769ee9c74..4accfb63f7dc 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h | |||
@@ -98,6 +98,7 @@ struct usb_port { | |||
98 | struct mutex status_lock; | 98 | struct mutex status_lock; |
99 | u32 over_current_count; | 99 | u32 over_current_count; |
100 | u8 portnum; | 100 | u8 portnum; |
101 | u32 quirks; | ||
101 | unsigned int is_superspeed:1; | 102 | unsigned int is_superspeed:1; |
102 | unsigned int usb3_lpm_u1_permit:1; | 103 | unsigned int usb3_lpm_u1_permit:1; |
103 | unsigned int usb3_lpm_u2_permit:1; | 104 | unsigned int usb3_lpm_u2_permit:1; |
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 0c11d40a12bc..7b137003c2be 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
@@ -940,7 +940,7 @@ int usb_set_isoch_delay(struct usb_device *dev) | |||
940 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 940 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
941 | USB_REQ_SET_ISOCH_DELAY, | 941 | USB_REQ_SET_ISOCH_DELAY, |
942 | USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, | 942 | USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, |
943 | cpu_to_le16(dev->hub_delay), 0, NULL, 0, | 943 | dev->hub_delay, 0, NULL, 0, |
944 | USB_CTRL_SET_TIMEOUT); | 944 | USB_CTRL_SET_TIMEOUT); |
945 | } | 945 | } |
946 | 946 | ||
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 6979bde87d31..4a2143195395 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c | |||
@@ -50,6 +50,28 @@ static ssize_t over_current_count_show(struct device *dev, | |||
50 | } | 50 | } |
51 | static DEVICE_ATTR_RO(over_current_count); | 51 | static DEVICE_ATTR_RO(over_current_count); |
52 | 52 | ||
53 | static ssize_t quirks_show(struct device *dev, | ||
54 | struct device_attribute *attr, char *buf) | ||
55 | { | ||
56 | struct usb_port *port_dev = to_usb_port(dev); | ||
57 | |||
58 | return sprintf(buf, "%08x\n", port_dev->quirks); | ||
59 | } | ||
60 | |||
61 | static ssize_t quirks_store(struct device *dev, struct device_attribute *attr, | ||
62 | const char *buf, size_t count) | ||
63 | { | ||
64 | struct usb_port *port_dev = to_usb_port(dev); | ||
65 | u32 value; | ||
66 | |||
67 | if (kstrtou32(buf, 16, &value)) | ||
68 | return -EINVAL; | ||
69 | |||
70 | port_dev->quirks = value; | ||
71 | return count; | ||
72 | } | ||
73 | static DEVICE_ATTR_RW(quirks); | ||
74 | |||
53 | static ssize_t usb3_lpm_permit_show(struct device *dev, | 75 | static ssize_t usb3_lpm_permit_show(struct device *dev, |
54 | struct device_attribute *attr, char *buf) | 76 | struct device_attribute *attr, char *buf) |
55 | { | 77 | { |
@@ -118,6 +140,7 @@ static DEVICE_ATTR_RW(usb3_lpm_permit); | |||
118 | 140 | ||
119 | static struct attribute *port_dev_attrs[] = { | 141 | static struct attribute *port_dev_attrs[] = { |
120 | &dev_attr_connect_type.attr, | 142 | &dev_attr_connect_type.attr, |
143 | &dev_attr_quirks.attr, | ||
121 | &dev_attr_over_current_count.attr, | 144 | &dev_attr_over_current_count.attr, |
122 | NULL, | 145 | NULL, |
123 | }; | 146 | }; |
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 27bb34043053..ea18284dfa9a 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c | |||
@@ -175,6 +175,26 @@ static ssize_t speed_show(struct device *dev, struct device_attribute *attr, | |||
175 | } | 175 | } |
176 | static DEVICE_ATTR_RO(speed); | 176 | static DEVICE_ATTR_RO(speed); |
177 | 177 | ||
178 | static ssize_t rx_lanes_show(struct device *dev, struct device_attribute *attr, | ||
179 | char *buf) | ||
180 | { | ||
181 | struct usb_device *udev; | ||
182 | |||
183 | udev = to_usb_device(dev); | ||
184 | return sprintf(buf, "%d\n", udev->rx_lanes); | ||
185 | } | ||
186 | static DEVICE_ATTR_RO(rx_lanes); | ||
187 | |||
188 | static ssize_t tx_lanes_show(struct device *dev, struct device_attribute *attr, | ||
189 | char *buf) | ||
190 | { | ||
191 | struct usb_device *udev; | ||
192 | |||
193 | udev = to_usb_device(dev); | ||
194 | return sprintf(buf, "%d\n", udev->tx_lanes); | ||
195 | } | ||
196 | static DEVICE_ATTR_RO(tx_lanes); | ||
197 | |||
178 | static ssize_t busnum_show(struct device *dev, struct device_attribute *attr, | 198 | static ssize_t busnum_show(struct device *dev, struct device_attribute *attr, |
179 | char *buf) | 199 | char *buf) |
180 | { | 200 | { |
@@ -790,6 +810,8 @@ static struct attribute *dev_attrs[] = { | |||
790 | &dev_attr_bNumConfigurations.attr, | 810 | &dev_attr_bNumConfigurations.attr, |
791 | &dev_attr_bMaxPacketSize0.attr, | 811 | &dev_attr_bMaxPacketSize0.attr, |
792 | &dev_attr_speed.attr, | 812 | &dev_attr_speed.attr, |
813 | &dev_attr_rx_lanes.attr, | ||
814 | &dev_attr_tx_lanes.attr, | ||
793 | &dev_attr_busnum.attr, | 815 | &dev_attr_busnum.attr, |
794 | &dev_attr_devnum.attr, | 816 | &dev_attr_devnum.attr, |
795 | &dev_attr_devpath.attr, | 817 | &dev_attr_devpath.attr, |
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 0adb6345ff2e..623be3174fb3 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c | |||
@@ -1167,30 +1167,16 @@ static struct notifier_block usb_bus_nb = { | |||
1167 | struct dentry *usb_debug_root; | 1167 | struct dentry *usb_debug_root; |
1168 | EXPORT_SYMBOL_GPL(usb_debug_root); | 1168 | EXPORT_SYMBOL_GPL(usb_debug_root); |
1169 | 1169 | ||
1170 | static struct dentry *usb_debug_devices; | 1170 | static void usb_debugfs_init(void) |
1171 | |||
1172 | static int usb_debugfs_init(void) | ||
1173 | { | 1171 | { |
1174 | usb_debug_root = debugfs_create_dir("usb", NULL); | 1172 | usb_debug_root = debugfs_create_dir("usb", NULL); |
1175 | if (!usb_debug_root) | 1173 | debugfs_create_file("devices", 0444, usb_debug_root, NULL, |
1176 | return -ENOENT; | 1174 | &usbfs_devices_fops); |
1177 | |||
1178 | usb_debug_devices = debugfs_create_file("devices", 0444, | ||
1179 | usb_debug_root, NULL, | ||
1180 | &usbfs_devices_fops); | ||
1181 | if (!usb_debug_devices) { | ||
1182 | debugfs_remove(usb_debug_root); | ||
1183 | usb_debug_root = NULL; | ||
1184 | return -ENOENT; | ||
1185 | } | ||
1186 | |||
1187 | return 0; | ||
1188 | } | 1175 | } |
1189 | 1176 | ||
1190 | static void usb_debugfs_cleanup(void) | 1177 | static void usb_debugfs_cleanup(void) |
1191 | { | 1178 | { |
1192 | debugfs_remove(usb_debug_devices); | 1179 | debugfs_remove_recursive(usb_debug_root); |
1193 | debugfs_remove(usb_debug_root); | ||
1194 | } | 1180 | } |
1195 | 1181 | ||
1196 | /* | 1182 | /* |
@@ -1205,9 +1191,7 @@ static int __init usb_init(void) | |||
1205 | } | 1191 | } |
1206 | usb_init_pool_max(); | 1192 | usb_init_pool_max(); |
1207 | 1193 | ||
1208 | retval = usb_debugfs_init(); | 1194 | usb_debugfs_init(); |
1209 | if (retval) | ||
1210 | goto out; | ||
1211 | 1195 | ||
1212 | usb_acpi_register(); | 1196 | usb_acpi_register(); |
1213 | retval = bus_register(&usb_bus_type); | 1197 | retval = bus_register(&usb_bus_type); |
diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index 18a0a1771289..1c36a6a9dd63 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c | |||
@@ -419,6 +419,8 @@ static void dwc2_wait_for_mode(struct dwc2_hsotg *hsotg, | |||
419 | /** | 419 | /** |
420 | * dwc2_iddig_filter_enabled() - Returns true if the IDDIG debounce | 420 | * dwc2_iddig_filter_enabled() - Returns true if the IDDIG debounce |
421 | * filter is enabled. | 421 | * filter is enabled. |
422 | * | ||
423 | * @hsotg: Programming view of DWC_otg controller | ||
422 | */ | 424 | */ |
423 | static bool dwc2_iddig_filter_enabled(struct dwc2_hsotg *hsotg) | 425 | static bool dwc2_iddig_filter_enabled(struct dwc2_hsotg *hsotg) |
424 | { | 426 | { |
@@ -564,6 +566,9 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait) | |||
564 | * If a force is done, it requires a IDDIG debounce filter delay if | 566 | * If a force is done, it requires a IDDIG debounce filter delay if |
565 | * the filter is configured and enabled. We poll the current mode of | 567 | * the filter is configured and enabled. We poll the current mode of |
566 | * the controller to account for this delay. | 568 | * the controller to account for this delay. |
569 | * | ||
570 | * @hsotg: Programming view of DWC_otg controller | ||
571 | * @host: Host mode flag | ||
567 | */ | 572 | */ |
568 | void dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host) | 573 | void dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host) |
569 | { | 574 | { |
@@ -610,6 +615,8 @@ void dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host) | |||
610 | * or not because the value of the connector ID status is affected by | 615 | * or not because the value of the connector ID status is affected by |
611 | * the force mode. We only need to call this once during probe if | 616 | * the force mode. We only need to call this once during probe if |
612 | * dr_mode == OTG. | 617 | * dr_mode == OTG. |
618 | * | ||
619 | * @hsotg: Programming view of DWC_otg controller | ||
613 | */ | 620 | */ |
614 | static void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg) | 621 | static void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg) |
615 | { | 622 | { |
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index a666e0758a99..4a56ac772a3c 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h | |||
@@ -164,12 +164,11 @@ struct dwc2_hsotg_req; | |||
164 | * and has yet to be completed (maybe due to data move, or simply | 164 | * and has yet to be completed (maybe due to data move, or simply |
165 | * awaiting an ack from the core all the data has been completed). | 165 | * awaiting an ack from the core all the data has been completed). |
166 | * @debugfs: File entry for debugfs file for this endpoint. | 166 | * @debugfs: File entry for debugfs file for this endpoint. |
167 | * @lock: State lock to protect contents of endpoint. | ||
168 | * @dir_in: Set to true if this endpoint is of the IN direction, which | 167 | * @dir_in: Set to true if this endpoint is of the IN direction, which |
169 | * means that it is sending data to the Host. | 168 | * means that it is sending data to the Host. |
170 | * @index: The index for the endpoint registers. | 169 | * @index: The index for the endpoint registers. |
171 | * @mc: Multi Count - number of transactions per microframe | 170 | * @mc: Multi Count - number of transactions per microframe |
172 | * @interval - Interval for periodic endpoints, in frames or microframes. | 171 | * @interval: Interval for periodic endpoints, in frames or microframes. |
173 | * @name: The name array passed to the USB core. | 172 | * @name: The name array passed to the USB core. |
174 | * @halted: Set if the endpoint has been halted. | 173 | * @halted: Set if the endpoint has been halted. |
175 | * @periodic: Set if this is a periodic ep, such as Interrupt | 174 | * @periodic: Set if this is a periodic ep, such as Interrupt |
@@ -178,10 +177,11 @@ struct dwc2_hsotg_req; | |||
178 | * @desc_list_dma: The DMA address of descriptor chain currently in use. | 177 | * @desc_list_dma: The DMA address of descriptor chain currently in use. |
179 | * @desc_list: Pointer to descriptor DMA chain head currently in use. | 178 | * @desc_list: Pointer to descriptor DMA chain head currently in use. |
180 | * @desc_count: Count of entries within the DMA descriptor chain of EP. | 179 | * @desc_count: Count of entries within the DMA descriptor chain of EP. |
181 | * @isoc_chain_num: Number of ISOC chain currently in use - either 0 or 1. | ||
182 | * @next_desc: index of next free descriptor in the ISOC chain under SW control. | 180 | * @next_desc: index of next free descriptor in the ISOC chain under SW control. |
181 | * @compl_desc: index of next descriptor to be completed by xFerComplete | ||
183 | * @total_data: The total number of data bytes done. | 182 | * @total_data: The total number of data bytes done. |
184 | * @fifo_size: The size of the FIFO (for periodic IN endpoints) | 183 | * @fifo_size: The size of the FIFO (for periodic IN endpoints) |
184 | * @fifo_index: For Dedicated FIFO operation, only FIFO0 can be used for EP0. | ||
185 | * @fifo_load: The amount of data loaded into the FIFO (periodic IN) | 185 | * @fifo_load: The amount of data loaded into the FIFO (periodic IN) |
186 | * @last_load: The offset of data for the last start of request. | 186 | * @last_load: The offset of data for the last start of request. |
187 | * @size_loaded: The last loaded size for DxEPTSIZE for periodic IN | 187 | * @size_loaded: The last loaded size for DxEPTSIZE for periodic IN |
@@ -231,8 +231,8 @@ struct dwc2_hsotg_ep { | |||
231 | struct dwc2_dma_desc *desc_list; | 231 | struct dwc2_dma_desc *desc_list; |
232 | u8 desc_count; | 232 | u8 desc_count; |
233 | 233 | ||
234 | unsigned char isoc_chain_num; | ||
235 | unsigned int next_desc; | 234 | unsigned int next_desc; |
235 | unsigned int compl_desc; | ||
236 | 236 | ||
237 | char name[10]; | 237 | char name[10]; |
238 | }; | 238 | }; |
@@ -380,6 +380,12 @@ enum dwc2_ep0_state { | |||
380 | * is FS. | 380 | * is FS. |
381 | * 0 - No (default) | 381 | * 0 - No (default) |
382 | * 1 - Yes | 382 | * 1 - Yes |
383 | * @ipg_isoc_en: Indicates the IPG supports is enabled or disabled. | ||
384 | * 0 - Disable (default) | ||
385 | * 1 - Enable | ||
386 | * @acg_enable: For enabling Active Clock Gating in the controller | ||
387 | * 0 - No | ||
388 | * 1 - Yes | ||
383 | * @ulpi_fs_ls: Make ULPI phy operate in FS/LS mode only | 389 | * @ulpi_fs_ls: Make ULPI phy operate in FS/LS mode only |
384 | * 0 - No (default) | 390 | * 0 - No (default) |
385 | * 1 - Yes | 391 | * 1 - Yes |
@@ -511,6 +517,7 @@ struct dwc2_core_params { | |||
511 | bool hird_threshold_en; | 517 | bool hird_threshold_en; |
512 | u8 hird_threshold; | 518 | u8 hird_threshold; |
513 | bool activate_stm_fs_transceiver; | 519 | bool activate_stm_fs_transceiver; |
520 | bool ipg_isoc_en; | ||
514 | u16 max_packet_count; | 521 | u16 max_packet_count; |
515 | u32 max_transfer_size; | 522 | u32 max_transfer_size; |
516 | u32 ahbcfg; | 523 | u32 ahbcfg; |
@@ -548,7 +555,7 @@ struct dwc2_core_params { | |||
548 | * | 555 | * |
549 | * The values that are not in dwc2_core_params are documented below. | 556 | * The values that are not in dwc2_core_params are documented below. |
550 | * | 557 | * |
551 | * @op_mode Mode of Operation | 558 | * @op_mode: Mode of Operation |
552 | * 0 - HNP- and SRP-Capable OTG (Host & Device) | 559 | * 0 - HNP- and SRP-Capable OTG (Host & Device) |
553 | * 1 - SRP-Capable OTG (Host & Device) | 560 | * 1 - SRP-Capable OTG (Host & Device) |
554 | * 2 - Non-HNP and Non-SRP Capable OTG (Host & Device) | 561 | * 2 - Non-HNP and Non-SRP Capable OTG (Host & Device) |
@@ -556,43 +563,102 @@ struct dwc2_core_params { | |||
556 | * 4 - Non-OTG Device | 563 | * 4 - Non-OTG Device |
557 | * 5 - SRP-Capable Host | 564 | * 5 - SRP-Capable Host |
558 | * 6 - Non-OTG Host | 565 | * 6 - Non-OTG Host |
559 | * @arch Architecture | 566 | * @arch: Architecture |
560 | * 0 - Slave only | 567 | * 0 - Slave only |
561 | * 1 - External DMA | 568 | * 1 - External DMA |
562 | * 2 - Internal DMA | 569 | * 2 - Internal DMA |
563 | * @power_optimized Are power optimizations enabled? | 570 | * @ipg_isoc_en: This feature indicates that the controller supports |
564 | * @num_dev_ep Number of device endpoints available | 571 | * the worst-case scenario of Rx followed by Rx |
565 | * @num_dev_in_eps Number of device IN endpoints available | 572 | * Interpacket Gap (IPG) (32 bitTimes) as per the utmi |
566 | * @num_dev_perio_in_ep Number of device periodic IN endpoints | 573 | * specification for any token following ISOC OUT token. |
567 | * available | 574 | * 0 - Don't support |
568 | * @dev_token_q_depth Device Mode IN Token Sequence Learning Queue | 575 | * 1 - Support |
576 | * @power_optimized: Are power optimizations enabled? | ||
577 | * @num_dev_ep: Number of device endpoints available | ||
578 | * @num_dev_in_eps: Number of device IN endpoints available | ||
579 | * @num_dev_perio_in_ep: Number of device periodic IN endpoints | ||
580 | * available | ||
581 | * @dev_token_q_depth: Device Mode IN Token Sequence Learning Queue | ||
569 | * Depth | 582 | * Depth |
570 | * 0 to 30 | 583 | * 0 to 30 |
571 | * @host_perio_tx_q_depth | 584 | * @host_perio_tx_q_depth: |
572 | * Host Mode Periodic Request Queue Depth | 585 | * Host Mode Periodic Request Queue Depth |
573 | * 2, 4 or 8 | 586 | * 2, 4 or 8 |
574 | * @nperio_tx_q_depth | 587 | * @nperio_tx_q_depth: |
575 | * Non-Periodic Request Queue Depth | 588 | * Non-Periodic Request Queue Depth |
576 | * 2, 4 or 8 | 589 | * 2, 4 or 8 |
577 | * @hs_phy_type High-speed PHY interface type | 590 | * @hs_phy_type: High-speed PHY interface type |
578 | * 0 - High-speed interface not supported | 591 | * 0 - High-speed interface not supported |
579 | * 1 - UTMI+ | 592 | * 1 - UTMI+ |
580 | * 2 - ULPI | 593 | * 2 - ULPI |
581 | * 3 - UTMI+ and ULPI | 594 | * 3 - UTMI+ and ULPI |
582 | * @fs_phy_type Full-speed PHY interface type | 595 | * @fs_phy_type: Full-speed PHY interface type |
583 | * 0 - Full speed interface not supported | 596 | * 0 - Full speed interface not supported |
584 | * 1 - Dedicated full speed interface | 597 | * 1 - Dedicated full speed interface |
585 | * 2 - FS pins shared with UTMI+ pins | 598 | * 2 - FS pins shared with UTMI+ pins |
586 | * 3 - FS pins shared with ULPI pins | 599 | * 3 - FS pins shared with ULPI pins |
587 | * @total_fifo_size: Total internal RAM for FIFOs (bytes) | 600 | * @total_fifo_size: Total internal RAM for FIFOs (bytes) |
588 | * @hibernation Is hibernation enabled? | 601 | * @hibernation: Is hibernation enabled? |
589 | * @utmi_phy_data_width UTMI+ PHY data width | 602 | * @utmi_phy_data_width: UTMI+ PHY data width |
590 | * 0 - 8 bits | 603 | * 0 - 8 bits |
591 | * 1 - 16 bits | 604 | * 1 - 16 bits |
592 | * 2 - 8 or 16 bits | 605 | * 2 - 8 or 16 bits |
593 | * @snpsid: Value from SNPSID register | 606 | * @snpsid: Value from SNPSID register |
594 | * @dev_ep_dirs: Direction of device endpoints (GHWCFG1) | 607 | * @dev_ep_dirs: Direction of device endpoints (GHWCFG1) |
595 | * @g_tx_fifo_size[] Power-on values of TxFIFO sizes | 608 | * @g_tx_fifo_size: Power-on values of TxFIFO sizes |
609 | * @dma_desc_enable: When DMA mode is enabled, specifies whether to use | ||
610 | * address DMA mode or descriptor DMA mode for accessing | ||
611 | * the data FIFOs. The driver will automatically detect the | ||
612 | * value for this if none is specified. | ||
613 | * 0 - Address DMA | ||
614 | * 1 - Descriptor DMA (default, if available) | ||
615 | * @enable_dynamic_fifo: 0 - Use coreConsultant-specified FIFO size parameters | ||
616 | * 1 - Allow dynamic FIFO sizing (default, if available) | ||
617 | * @en_multiple_tx_fifo: Specifies whether dedicated per-endpoint transmit FIFOs | ||
618 | * are enabled for non-periodic IN endpoints in device | ||
619 | * mode. | ||
620 | * @host_nperio_tx_fifo_size: Number of 4-byte words in the non-periodic Tx FIFO | ||
621 | * in host mode when dynamic FIFO sizing is enabled | ||
622 | * 16 to 32768 | ||
623 | * Actual maximum value is autodetected and also | ||
624 | * the default. | ||
625 | * @host_perio_tx_fifo_size: Number of 4-byte words in the periodic Tx FIFO in | ||
626 | * host mode when dynamic FIFO sizing is enabled | ||
627 | * 16 to 32768 | ||
628 | * Actual maximum value is autodetected and also | ||
629 | * the default. | ||
630 | * @max_transfer_size: The maximum transfer size supported, in bytes | ||
631 | * 2047 to 65,535 | ||
632 | * Actual maximum value is autodetected and also | ||
633 | * the default. | ||
634 | * @max_packet_count: The maximum number of packets in a transfer | ||
635 | * 15 to 511 | ||
636 | * Actual maximum value is autodetected and also | ||
637 | * the default. | ||
638 | * @host_channels: The number of host channel registers to use | ||
639 | * 1 to 16 | ||
640 | * Actual maximum value is autodetected and also | ||
641 | * the default. | ||
642 | * @dev_nperio_tx_fifo_size: Number of 4-byte words in the non-periodic Tx FIFO | ||
643 | * in device mode when dynamic FIFO sizing is enabled | ||
644 | * 16 to 32768 | ||
645 | * Actual maximum value is autodetected and also | ||
646 | * the default. | ||
647 | * @i2c_enable: Specifies whether to use the I2Cinterface for a full | ||
648 | * speed PHY. This parameter is only applicable if phy_type | ||
649 | * is FS. | ||
650 | * 0 - No (default) | ||
651 | * 1 - Yes | ||
652 | * @acg_enable: For enabling Active Clock Gating in the controller | ||
653 | * 0 - Disable | ||
654 | * 1 - Enable | ||
655 | * @lpm_mode: For enabling Link Power Management in the controller | ||
656 | * 0 - Disable | ||
657 | * 1 - Enable | ||
658 | * @rx_fifo_size: Number of 4-byte words in the Rx FIFO when dynamic | ||
659 | * FIFO sizing is enabled 16 to 32768 | ||
660 | * Actual maximum value is autodetected and also | ||
661 | * the default. | ||
596 | */ | 662 | */ |
597 | struct dwc2_hw_params { | 663 | struct dwc2_hw_params { |
598 | unsigned op_mode:3; | 664 | unsigned op_mode:3; |
@@ -622,6 +688,7 @@ struct dwc2_hw_params { | |||
622 | unsigned hibernation:1; | 688 | unsigned hibernation:1; |
623 | unsigned utmi_phy_data_width:2; | 689 | unsigned utmi_phy_data_width:2; |
624 | unsigned lpm_mode:1; | 690 | unsigned lpm_mode:1; |
691 | unsigned ipg_isoc_en:1; | ||
625 | u32 snpsid; | 692 | u32 snpsid; |
626 | u32 dev_ep_dirs; | 693 | u32 dev_ep_dirs; |
627 | u32 g_tx_fifo_size[MAX_EPS_CHANNELS]; | 694 | u32 g_tx_fifo_size[MAX_EPS_CHANNELS]; |
@@ -642,7 +709,11 @@ struct dwc2_hw_params { | |||
642 | * @gi2cctl: Backup of GI2CCTL register | 709 | * @gi2cctl: Backup of GI2CCTL register |
643 | * @glpmcfg: Backup of GLPMCFG register | 710 | * @glpmcfg: Backup of GLPMCFG register |
644 | * @gdfifocfg: Backup of GDFIFOCFG register | 711 | * @gdfifocfg: Backup of GDFIFOCFG register |
712 | * @pcgcctl: Backup of PCGCCTL register | ||
713 | * @pcgcctl1: Backup of PCGCCTL1 register | ||
714 | * @dtxfsiz: Backup of DTXFSIZ registers for each endpoint | ||
645 | * @gpwrdn: Backup of GPWRDN register | 715 | * @gpwrdn: Backup of GPWRDN register |
716 | * @valid: True if registers values backuped. | ||
646 | */ | 717 | */ |
647 | struct dwc2_gregs_backup { | 718 | struct dwc2_gregs_backup { |
648 | u32 gotgctl; | 719 | u32 gotgctl; |
@@ -675,6 +746,7 @@ struct dwc2_gregs_backup { | |||
675 | * @doeptsiz: Backup of DOEPTSIZ register | 746 | * @doeptsiz: Backup of DOEPTSIZ register |
676 | * @doepdma: Backup of DOEPDMA register | 747 | * @doepdma: Backup of DOEPDMA register |
677 | * @dtxfsiz: Backup of DTXFSIZ registers for each endpoint | 748 | * @dtxfsiz: Backup of DTXFSIZ registers for each endpoint |
749 | * @valid: True if registers values backuped. | ||
678 | */ | 750 | */ |
679 | struct dwc2_dregs_backup { | 751 | struct dwc2_dregs_backup { |
680 | u32 dcfg; | 752 | u32 dcfg; |
@@ -698,9 +770,10 @@ struct dwc2_dregs_backup { | |||
698 | * @hcfg: Backup of HCFG register | 770 | * @hcfg: Backup of HCFG register |
699 | * @haintmsk: Backup of HAINTMSK register | 771 | * @haintmsk: Backup of HAINTMSK register |
700 | * @hcintmsk: Backup of HCINTMSK register | 772 | * @hcintmsk: Backup of HCINTMSK register |
701 | * @hptr0: Backup of HPTR0 register | 773 | * @hprt0: Backup of HPTR0 register |
702 | * @hfir: Backup of HFIR register | 774 | * @hfir: Backup of HFIR register |
703 | * @hptxfsiz: Backup of HPTXFSIZ register | 775 | * @hptxfsiz: Backup of HPTXFSIZ register |
776 | * @valid: True if registers values backuped. | ||
704 | */ | 777 | */ |
705 | struct dwc2_hregs_backup { | 778 | struct dwc2_hregs_backup { |
706 | u32 hcfg; | 779 | u32 hcfg; |
@@ -800,7 +873,7 @@ struct dwc2_hregs_backup { | |||
800 | * @regs: Pointer to controller regs | 873 | * @regs: Pointer to controller regs |
801 | * @hw_params: Parameters that were autodetected from the | 874 | * @hw_params: Parameters that were autodetected from the |
802 | * hardware registers | 875 | * hardware registers |
803 | * @core_params: Parameters that define how the core should be configured | 876 | * @params: Parameters that define how the core should be configured |
804 | * @op_state: The operational State, during transitions (a_host=> | 877 | * @op_state: The operational State, during transitions (a_host=> |
805 | * a_peripheral and b_device=>b_host) this may not match | 878 | * a_peripheral and b_device=>b_host) this may not match |
806 | * the core, but allows the software to determine | 879 | * the core, but allows the software to determine |
@@ -809,10 +882,13 @@ struct dwc2_hregs_backup { | |||
809 | * - USB_DR_MODE_PERIPHERAL | 882 | * - USB_DR_MODE_PERIPHERAL |
810 | * - USB_DR_MODE_HOST | 883 | * - USB_DR_MODE_HOST |
811 | * - USB_DR_MODE_OTG | 884 | * - USB_DR_MODE_OTG |
812 | * @hcd_enabled Host mode sub-driver initialization indicator. | 885 | * @hcd_enabled: Host mode sub-driver initialization indicator. |
813 | * @gadget_enabled Peripheral mode sub-driver initialization indicator. | 886 | * @gadget_enabled: Peripheral mode sub-driver initialization indicator. |
814 | * @ll_hw_enabled Status of low-level hardware resources. | 887 | * @ll_hw_enabled: Status of low-level hardware resources. |
815 | * @hibernated: True if core is hibernated | 888 | * @hibernated: True if core is hibernated |
889 | * @frame_number: Frame number read from the core. For both device | ||
890 | * and host modes. The value ranges are from 0 | ||
891 | * to HFNUM_MAX_FRNUM. | ||
816 | * @phy: The otg phy transceiver structure for phy control. | 892 | * @phy: The otg phy transceiver structure for phy control. |
817 | * @uphy: The otg phy transceiver structure for old USB phy | 893 | * @uphy: The otg phy transceiver structure for old USB phy |
818 | * control. | 894 | * control. |
@@ -832,13 +908,25 @@ struct dwc2_hregs_backup { | |||
832 | * interrupt | 908 | * interrupt |
833 | * @wkp_timer: Timer object for handling Wakeup Detected interrupt | 909 | * @wkp_timer: Timer object for handling Wakeup Detected interrupt |
834 | * @lx_state: Lx state of connected device | 910 | * @lx_state: Lx state of connected device |
835 | * @gregs_backup: Backup of global registers during suspend | 911 | * @gr_backup: Backup of global registers during suspend |
836 | * @dregs_backup: Backup of device registers during suspend | 912 | * @dr_backup: Backup of device registers during suspend |
837 | * @hregs_backup: Backup of host registers during suspend | 913 | * @hr_backup: Backup of host registers during suspend |
838 | * | 914 | * |
839 | * These are for host mode: | 915 | * These are for host mode: |
840 | * | 916 | * |
841 | * @flags: Flags for handling root port state changes | 917 | * @flags: Flags for handling root port state changes |
918 | * @flags.d32: Contain all root port flags | ||
919 | * @flags.b: Separate root port flags from each other | ||
920 | * @flags.b.port_connect_status_change: True if root port connect status | ||
921 | * changed | ||
922 | * @flags.b.port_connect_status: True if device connected to root port | ||
923 | * @flags.b.port_reset_change: True if root port reset status changed | ||
924 | * @flags.b.port_enable_change: True if root port enable status changed | ||
925 | * @flags.b.port_suspend_change: True if root port suspend status changed | ||
926 | * @flags.b.port_over_current_change: True if root port over current state | ||
927 | * changed. | ||
928 | * @flags.b.port_l1_change: True if root port l1 status changed | ||
929 | * @flags.b.reserved: Reserved bits of root port register | ||
842 | * @non_periodic_sched_inactive: Inactive QHs in the non-periodic schedule. | 930 | * @non_periodic_sched_inactive: Inactive QHs in the non-periodic schedule. |
843 | * Transfers associated with these QHs are not currently | 931 | * Transfers associated with these QHs are not currently |
844 | * assigned to a host channel. | 932 | * assigned to a host channel. |
@@ -847,6 +935,9 @@ struct dwc2_hregs_backup { | |||
847 | * assigned to a host channel. | 935 | * assigned to a host channel. |
848 | * @non_periodic_qh_ptr: Pointer to next QH to process in the active | 936 | * @non_periodic_qh_ptr: Pointer to next QH to process in the active |
849 | * non-periodic schedule | 937 | * non-periodic schedule |
938 | * @non_periodic_sched_waiting: Waiting QHs in the non-periodic schedule. | ||
939 | * Transfers associated with these QHs are not currently | ||
940 | * assigned to a host channel. | ||
850 | * @periodic_sched_inactive: Inactive QHs in the periodic schedule. This is a | 941 | * @periodic_sched_inactive: Inactive QHs in the periodic schedule. This is a |
851 | * list of QHs for periodic transfers that are _not_ | 942 | * list of QHs for periodic transfers that are _not_ |
852 | * scheduled for the next frame. Each QH in the list has an | 943 | * scheduled for the next frame. Each QH in the list has an |
@@ -886,8 +977,6 @@ struct dwc2_hregs_backup { | |||
886 | * @hs_periodic_bitmap: Bitmap used by the microframe scheduler any time the | 977 | * @hs_periodic_bitmap: Bitmap used by the microframe scheduler any time the |
887 | * host is in high speed mode; low speed schedules are | 978 | * host is in high speed mode; low speed schedules are |
888 | * stored elsewhere since we need one per TT. | 979 | * stored elsewhere since we need one per TT. |
889 | * @frame_number: Frame number read from the core at SOF. The value ranges | ||
890 | * from 0 to HFNUM_MAX_FRNUM. | ||
891 | * @periodic_qh_count: Count of periodic QHs, if using several eps. Used for | 980 | * @periodic_qh_count: Count of periodic QHs, if using several eps. Used for |
892 | * SOF enable/disable. | 981 | * SOF enable/disable. |
893 | * @free_hc_list: Free host channels in the controller. This is a list of | 982 | * @free_hc_list: Free host channels in the controller. This is a list of |
@@ -898,8 +987,8 @@ struct dwc2_hregs_backup { | |||
898 | * host channel is available for non-periodic transactions. | 987 | * host channel is available for non-periodic transactions. |
899 | * @non_periodic_channels: Number of host channels assigned to non-periodic | 988 | * @non_periodic_channels: Number of host channels assigned to non-periodic |
900 | * transfers | 989 | * transfers |
901 | * @available_host_channels Number of host channels available for the microframe | 990 | * @available_host_channels: Number of host channels available for the |
902 | * scheduler to use | 991 | * microframe scheduler to use |
903 | * @hc_ptr_array: Array of pointers to the host channel descriptors. | 992 | * @hc_ptr_array: Array of pointers to the host channel descriptors. |
904 | * Allows accessing a host channel descriptor given the | 993 | * Allows accessing a host channel descriptor given the |
905 | * host channel number. This is useful in interrupt | 994 | * host channel number. This is useful in interrupt |
@@ -922,9 +1011,6 @@ struct dwc2_hregs_backup { | |||
922 | * @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos. | 1011 | * @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos. |
923 | * @num_of_eps: Number of available EPs (excluding EP0) | 1012 | * @num_of_eps: Number of available EPs (excluding EP0) |
924 | * @debug_root: Root directrory for debugfs. | 1013 | * @debug_root: Root directrory for debugfs. |
925 | * @debug_file: Main status file for debugfs. | ||
926 | * @debug_testmode: Testmode status file for debugfs. | ||
927 | * @debug_fifo: FIFO status file for debugfs. | ||
928 | * @ep0_reply: Request used for ep0 reply. | 1014 | * @ep0_reply: Request used for ep0 reply. |
929 | * @ep0_buff: Buffer for EP0 reply data, if needed. | 1015 | * @ep0_buff: Buffer for EP0 reply data, if needed. |
930 | * @ctrl_buff: Buffer for EP0 control requests. | 1016 | * @ctrl_buff: Buffer for EP0 control requests. |
@@ -939,7 +1025,37 @@ struct dwc2_hregs_backup { | |||
939 | * @ctrl_in_desc: EP0 IN data phase desc chain pointer | 1025 | * @ctrl_in_desc: EP0 IN data phase desc chain pointer |
940 | * @ctrl_out_desc_dma: EP0 OUT data phase desc chain DMA address | 1026 | * @ctrl_out_desc_dma: EP0 OUT data phase desc chain DMA address |
941 | * @ctrl_out_desc: EP0 OUT data phase desc chain pointer | 1027 | * @ctrl_out_desc: EP0 OUT data phase desc chain pointer |
942 | * @eps: The endpoints being supplied to the gadget framework | 1028 | * @irq: Interrupt request line number |
1029 | * @clk: Pointer to otg clock | ||
1030 | * @reset: Pointer to dwc2 reset controller | ||
1031 | * @reset_ecc: Pointer to dwc2 optional reset controller in Stratix10. | ||
1032 | * @regset: A pointer to a struct debugfs_regset32, which contains | ||
1033 | * a pointer to an array of register definitions, the | ||
1034 | * array size and the base address where the register bank | ||
1035 | * is to be found. | ||
1036 | * @bus_suspended: True if bus is suspended | ||
1037 | * @last_frame_num: Number of last frame. Range from 0 to 32768 | ||
1038 | * @frame_num_array: Used only if CONFIG_USB_DWC2_TRACK_MISSED_SOFS is | ||
1039 | * defined, for missed SOFs tracking. Array holds that | ||
1040 | * frame numbers, which not equal to last_frame_num +1 | ||
1041 | * @last_frame_num_array: Used only if CONFIG_USB_DWC2_TRACK_MISSED_SOFS is | ||
1042 | * defined, for missed SOFs tracking. | ||
1043 | * If current_frame_number != last_frame_num+1 | ||
1044 | * then last_frame_num added to this array | ||
1045 | * @frame_num_idx: Actual size of frame_num_array and last_frame_num_array | ||
1046 | * @dumped_frame_num_array: 1 - if missed SOFs frame numbers dumbed | ||
1047 | * 0 - if missed SOFs frame numbers not dumbed | ||
1048 | * @fifo_mem: Total internal RAM for FIFOs (bytes) | ||
1049 | * @fifo_map: Each bit intend for concrete fifo. If that bit is set, | ||
1050 | * then that fifo is used | ||
1051 | * @gadget: Represents a usb slave device | ||
1052 | * @connected: Used in slave mode. True if device connected with host | ||
1053 | * @eps_in: The IN endpoints being supplied to the gadget framework | ||
1054 | * @eps_out: The OUT endpoints being supplied to the gadget framework | ||
1055 | * @new_connection: Used in host mode. True if there are new connected | ||
1056 | * device | ||
1057 | * @enabled: Indicates the enabling state of controller | ||
1058 | * | ||
943 | */ | 1059 | */ |
944 | struct dwc2_hsotg { | 1060 | struct dwc2_hsotg { |
945 | struct device *dev; | 1061 | struct device *dev; |
@@ -954,6 +1070,7 @@ struct dwc2_hsotg { | |||
954 | unsigned int gadget_enabled:1; | 1070 | unsigned int gadget_enabled:1; |
955 | unsigned int ll_hw_enabled:1; | 1071 | unsigned int ll_hw_enabled:1; |
956 | unsigned int hibernated:1; | 1072 | unsigned int hibernated:1; |
1073 | u16 frame_number; | ||
957 | 1074 | ||
958 | struct phy *phy; | 1075 | struct phy *phy; |
959 | struct usb_phy *uphy; | 1076 | struct usb_phy *uphy; |
@@ -1029,7 +1146,6 @@ struct dwc2_hsotg { | |||
1029 | u16 periodic_usecs; | 1146 | u16 periodic_usecs; |
1030 | unsigned long hs_periodic_bitmap[ | 1147 | unsigned long hs_periodic_bitmap[ |
1031 | DIV_ROUND_UP(DWC2_HS_SCHEDULE_US, BITS_PER_LONG)]; | 1148 | DIV_ROUND_UP(DWC2_HS_SCHEDULE_US, BITS_PER_LONG)]; |
1032 | u16 frame_number; | ||
1033 | u16 periodic_qh_count; | 1149 | u16 periodic_qh_count; |
1034 | bool bus_suspended; | 1150 | bool bus_suspended; |
1035 | bool new_connection; | 1151 | bool new_connection; |
diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c index 2982a155734d..cc90b58b6b3c 100644 --- a/drivers/usb/dwc2/core_intr.c +++ b/drivers/usb/dwc2/core_intr.c | |||
@@ -778,6 +778,14 @@ irqreturn_t dwc2_handle_common_intr(int irq, void *dev) | |||
778 | goto out; | 778 | goto out; |
779 | } | 779 | } |
780 | 780 | ||
781 | /* Reading current frame number value in device or host modes. */ | ||
782 | if (dwc2_is_device_mode(hsotg)) | ||
783 | hsotg->frame_number = (dwc2_readl(hsotg->regs + DSTS) | ||
784 | & DSTS_SOFFN_MASK) >> DSTS_SOFFN_SHIFT; | ||
785 | else | ||
786 | hsotg->frame_number = (dwc2_readl(hsotg->regs + HFNUM) | ||
787 | & HFNUM_FRNUM_MASK) >> HFNUM_FRNUM_SHIFT; | ||
788 | |||
781 | gintsts = dwc2_read_common_intr(hsotg); | 789 | gintsts = dwc2_read_common_intr(hsotg); |
782 | if (gintsts & ~GINTSTS_PRTINT) | 790 | if (gintsts & ~GINTSTS_PRTINT) |
783 | retval = IRQ_HANDLED; | 791 | retval = IRQ_HANDLED; |
diff --git a/drivers/usb/dwc2/debug.h b/drivers/usb/dwc2/debug.h index 6f23219c13cb..a8c565b6bc34 100644 --- a/drivers/usb/dwc2/debug.h +++ b/drivers/usb/dwc2/debug.h | |||
@@ -1,5 +1,5 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /** | 2 | /* |
3 | * debug.h - Designware USB2 DRD controller debug header | 3 | * debug.h - Designware USB2 DRD controller debug header |
4 | * | 4 | * |
5 | * Copyright (C) 2015 Intel Corporation | 5 | * Copyright (C) 2015 Intel Corporation |
diff --git a/drivers/usb/dwc2/debugfs.c b/drivers/usb/dwc2/debugfs.c index 58c691f882a8..d0bdb7997557 100644 --- a/drivers/usb/dwc2/debugfs.c +++ b/drivers/usb/dwc2/debugfs.c | |||
@@ -1,5 +1,5 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /** | 2 | /* |
3 | * debugfs.c - Designware USB2 DRD controller debugfs | 3 | * debugfs.c - Designware USB2 DRD controller debugfs |
4 | * | 4 | * |
5 | * Copyright (C) 2015 Intel Corporation | 5 | * Copyright (C) 2015 Intel Corporation |
@@ -16,12 +16,13 @@ | |||
16 | 16 | ||
17 | #if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \ | 17 | #if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \ |
18 | IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) | 18 | IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) |
19 | |||
19 | /** | 20 | /** |
20 | * testmode_write - debugfs: change usb test mode | 21 | * testmode_write() - change usb test mode state. |
21 | * @seq: The seq file to write to. | 22 | * @file: The file to write to. |
22 | * @v: Unused parameter. | 23 | * @ubuf: The buffer where user wrote. |
23 | * | 24 | * @count: The ubuf size. |
24 | * This debugfs entry modify the current usb test mode. | 25 | * @ppos: Unused parameter. |
25 | */ | 26 | */ |
26 | static ssize_t testmode_write(struct file *file, const char __user *ubuf, size_t | 27 | static ssize_t testmode_write(struct file *file, const char __user *ubuf, size_t |
27 | count, loff_t *ppos) | 28 | count, loff_t *ppos) |
@@ -55,9 +56,9 @@ static ssize_t testmode_write(struct file *file, const char __user *ubuf, size_t | |||
55 | } | 56 | } |
56 | 57 | ||
57 | /** | 58 | /** |
58 | * testmode_show - debugfs: show usb test mode state | 59 | * testmode_show() - debugfs: show usb test mode state |
59 | * @seq: The seq file to write to. | 60 | * @s: The seq file to write to. |
60 | * @v: Unused parameter. | 61 | * @unused: Unused parameter. |
61 | * | 62 | * |
62 | * This debugfs entry shows which usb test mode is currently enabled. | 63 | * This debugfs entry shows which usb test mode is currently enabled. |
63 | */ | 64 | */ |
@@ -293,52 +294,30 @@ DEFINE_SHOW_ATTRIBUTE(ep); | |||
293 | static void dwc2_hsotg_create_debug(struct dwc2_hsotg *hsotg) | 294 | static void dwc2_hsotg_create_debug(struct dwc2_hsotg *hsotg) |
294 | { | 295 | { |
295 | struct dentry *root; | 296 | struct dentry *root; |
296 | struct dentry *file; | ||
297 | unsigned int epidx; | 297 | unsigned int epidx; |
298 | 298 | ||
299 | root = hsotg->debug_root; | 299 | root = hsotg->debug_root; |
300 | 300 | ||
301 | /* create general state file */ | 301 | /* create general state file */ |
302 | 302 | debugfs_create_file("state", 0444, root, hsotg, &state_fops); | |
303 | file = debugfs_create_file("state", 0444, root, hsotg, &state_fops); | 303 | debugfs_create_file("testmode", 0644, root, hsotg, &testmode_fops); |
304 | if (IS_ERR(file)) | 304 | debugfs_create_file("fifo", 0444, root, hsotg, &fifo_fops); |
305 | dev_err(hsotg->dev, "%s: failed to create state\n", __func__); | ||
306 | |||
307 | file = debugfs_create_file("testmode", 0644, root, hsotg, | ||
308 | &testmode_fops); | ||
309 | if (IS_ERR(file)) | ||
310 | dev_err(hsotg->dev, "%s: failed to create testmode\n", | ||
311 | __func__); | ||
312 | |||
313 | file = debugfs_create_file("fifo", 0444, root, hsotg, &fifo_fops); | ||
314 | if (IS_ERR(file)) | ||
315 | dev_err(hsotg->dev, "%s: failed to create fifo\n", __func__); | ||
316 | 305 | ||
317 | /* Create one file for each out endpoint */ | 306 | /* Create one file for each out endpoint */ |
318 | for (epidx = 0; epidx < hsotg->num_of_eps; epidx++) { | 307 | for (epidx = 0; epidx < hsotg->num_of_eps; epidx++) { |
319 | struct dwc2_hsotg_ep *ep; | 308 | struct dwc2_hsotg_ep *ep; |
320 | 309 | ||
321 | ep = hsotg->eps_out[epidx]; | 310 | ep = hsotg->eps_out[epidx]; |
322 | if (ep) { | 311 | if (ep) |
323 | file = debugfs_create_file(ep->name, 0444, | 312 | debugfs_create_file(ep->name, 0444, root, ep, &ep_fops); |
324 | root, ep, &ep_fops); | ||
325 | if (IS_ERR(file)) | ||
326 | dev_err(hsotg->dev, "failed to create %s debug file\n", | ||
327 | ep->name); | ||
328 | } | ||
329 | } | 313 | } |
330 | /* Create one file for each in endpoint. EP0 is handled with out eps */ | 314 | /* Create one file for each in endpoint. EP0 is handled with out eps */ |
331 | for (epidx = 1; epidx < hsotg->num_of_eps; epidx++) { | 315 | for (epidx = 1; epidx < hsotg->num_of_eps; epidx++) { |
332 | struct dwc2_hsotg_ep *ep; | 316 | struct dwc2_hsotg_ep *ep; |
333 | 317 | ||
334 | ep = hsotg->eps_in[epidx]; | 318 | ep = hsotg->eps_in[epidx]; |
335 | if (ep) { | 319 | if (ep) |
336 | file = debugfs_create_file(ep->name, 0444, | 320 | debugfs_create_file(ep->name, 0444, root, ep, &ep_fops); |
337 | root, ep, &ep_fops); | ||
338 | if (IS_ERR(file)) | ||
339 | dev_err(hsotg->dev, "failed to create %s debug file\n", | ||
340 | ep->name); | ||
341 | } | ||
342 | } | 321 | } |
343 | } | 322 | } |
344 | #else | 323 | #else |
@@ -368,7 +347,7 @@ static const struct debugfs_reg32 dwc2_regs[] = { | |||
368 | dump_register(GINTSTS), | 347 | dump_register(GINTSTS), |
369 | dump_register(GINTMSK), | 348 | dump_register(GINTMSK), |
370 | dump_register(GRXSTSR), | 349 | dump_register(GRXSTSR), |
371 | dump_register(GRXSTSP), | 350 | /* Omit GRXSTSP */ |
372 | dump_register(GRXFSIZ), | 351 | dump_register(GRXFSIZ), |
373 | dump_register(GNPTXFSIZ), | 352 | dump_register(GNPTXFSIZ), |
374 | dump_register(GNPTXSTS), | 353 | dump_register(GNPTXSTS), |
@@ -710,6 +689,7 @@ static int params_show(struct seq_file *seq, void *v) | |||
710 | print_param(seq, p, phy_ulpi_ddr); | 689 | print_param(seq, p, phy_ulpi_ddr); |
711 | print_param(seq, p, phy_ulpi_ext_vbus); | 690 | print_param(seq, p, phy_ulpi_ext_vbus); |
712 | print_param(seq, p, i2c_enable); | 691 | print_param(seq, p, i2c_enable); |
692 | print_param(seq, p, ipg_isoc_en); | ||
713 | print_param(seq, p, ulpi_fs_ls); | 693 | print_param(seq, p, ulpi_fs_ls); |
714 | print_param(seq, p, host_support_fs_ls_low_power); | 694 | print_param(seq, p, host_support_fs_ls_low_power); |
715 | print_param(seq, p, host_ls_low_power_phy_clk); | 695 | print_param(seq, p, host_ls_low_power_phy_clk); |
@@ -790,32 +770,14 @@ DEFINE_SHOW_ATTRIBUTE(dr_mode); | |||
790 | int dwc2_debugfs_init(struct dwc2_hsotg *hsotg) | 770 | int dwc2_debugfs_init(struct dwc2_hsotg *hsotg) |
791 | { | 771 | { |
792 | int ret; | 772 | int ret; |
793 | struct dentry *file; | 773 | struct dentry *root; |
794 | 774 | ||
795 | hsotg->debug_root = debugfs_create_dir(dev_name(hsotg->dev), NULL); | 775 | root = debugfs_create_dir(dev_name(hsotg->dev), NULL); |
796 | if (!hsotg->debug_root) { | 776 | hsotg->debug_root = root; |
797 | ret = -ENOMEM; | ||
798 | goto err0; | ||
799 | } | ||
800 | 777 | ||
801 | file = debugfs_create_file("params", 0444, | 778 | debugfs_create_file("params", 0444, root, hsotg, ¶ms_fops); |
802 | hsotg->debug_root, | 779 | debugfs_create_file("hw_params", 0444, root, hsotg, &hw_params_fops); |
803 | hsotg, ¶ms_fops); | 780 | debugfs_create_file("dr_mode", 0444, root, hsotg, &dr_mode_fops); |
804 | if (IS_ERR(file)) | ||
805 | dev_err(hsotg->dev, "%s: failed to create params\n", __func__); | ||
806 | |||
807 | file = debugfs_create_file("hw_params", 0444, | ||
808 | hsotg->debug_root, | ||
809 | hsotg, &hw_params_fops); | ||
810 | if (IS_ERR(file)) | ||
811 | dev_err(hsotg->dev, "%s: failed to create hw_params\n", | ||
812 | __func__); | ||
813 | |||
814 | file = debugfs_create_file("dr_mode", 0444, | ||
815 | hsotg->debug_root, | ||
816 | hsotg, &dr_mode_fops); | ||
817 | if (IS_ERR(file)) | ||
818 | dev_err(hsotg->dev, "%s: failed to create dr_mode\n", __func__); | ||
819 | 781 | ||
820 | /* Add gadget debugfs nodes */ | 782 | /* Add gadget debugfs nodes */ |
821 | dwc2_hsotg_create_debug(hsotg); | 783 | dwc2_hsotg_create_debug(hsotg); |
@@ -824,24 +786,18 @@ int dwc2_debugfs_init(struct dwc2_hsotg *hsotg) | |||
824 | GFP_KERNEL); | 786 | GFP_KERNEL); |
825 | if (!hsotg->regset) { | 787 | if (!hsotg->regset) { |
826 | ret = -ENOMEM; | 788 | ret = -ENOMEM; |
827 | goto err1; | 789 | goto err; |
828 | } | 790 | } |
829 | 791 | ||
830 | hsotg->regset->regs = dwc2_regs; | 792 | hsotg->regset->regs = dwc2_regs; |
831 | hsotg->regset->nregs = ARRAY_SIZE(dwc2_regs); | 793 | hsotg->regset->nregs = ARRAY_SIZE(dwc2_regs); |
832 | hsotg->regset->base = hsotg->regs; | 794 | hsotg->regset->base = hsotg->regs; |
833 | 795 | ||
834 | file = debugfs_create_regset32("regdump", 0444, hsotg->debug_root, | 796 | debugfs_create_regset32("regdump", 0444, root, hsotg->regset); |
835 | hsotg->regset); | ||
836 | if (!file) { | ||
837 | ret = -ENOMEM; | ||
838 | goto err1; | ||
839 | } | ||
840 | 797 | ||
841 | return 0; | 798 | return 0; |
842 | err1: | 799 | err: |
843 | debugfs_remove_recursive(hsotg->debug_root); | 800 | debugfs_remove_recursive(hsotg->debug_root); |
844 | err0: | ||
845 | return ret; | 801 | return ret; |
846 | } | 802 | } |
847 | 803 | ||
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 83cb5577a52f..f0d9ccf1d665 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c | |||
@@ -1,5 +1,5 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /** | 2 | /* |
3 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | 3 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. |
4 | * http://www.samsung.com | 4 | * http://www.samsung.com |
5 | * | 5 | * |
@@ -107,7 +107,6 @@ static inline bool using_desc_dma(struct dwc2_hsotg *hsotg) | |||
107 | /** | 107 | /** |
108 | * dwc2_gadget_incr_frame_num - Increments the targeted frame number. | 108 | * dwc2_gadget_incr_frame_num - Increments the targeted frame number. |
109 | * @hs_ep: The endpoint | 109 | * @hs_ep: The endpoint |
110 | * @increment: The value to increment by | ||
111 | * | 110 | * |
112 | * This function will also check if the frame number overruns DSTS_SOFFN_LIMIT. | 111 | * This function will also check if the frame number overruns DSTS_SOFFN_LIMIT. |
113 | * If an overrun occurs it will wrap the value and set the frame_overrun flag. | 112 | * If an overrun occurs it will wrap the value and set the frame_overrun flag. |
@@ -190,6 +189,8 @@ static void dwc2_hsotg_ctrl_epint(struct dwc2_hsotg *hsotg, | |||
190 | 189 | ||
191 | /** | 190 | /** |
192 | * dwc2_hsotg_tx_fifo_count - return count of TX FIFOs in device mode | 191 | * dwc2_hsotg_tx_fifo_count - return count of TX FIFOs in device mode |
192 | * | ||
193 | * @hsotg: Programming view of the DWC_otg controller | ||
193 | */ | 194 | */ |
194 | int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg) | 195 | int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg) |
195 | { | 196 | { |
@@ -204,6 +205,8 @@ int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg) | |||
204 | /** | 205 | /** |
205 | * dwc2_hsotg_tx_fifo_total_depth - return total FIFO depth available for | 206 | * dwc2_hsotg_tx_fifo_total_depth - return total FIFO depth available for |
206 | * device mode TX FIFOs | 207 | * device mode TX FIFOs |
208 | * | ||
209 | * @hsotg: Programming view of the DWC_otg controller | ||
207 | */ | 210 | */ |
208 | int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg) | 211 | int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg) |
209 | { | 212 | { |
@@ -227,6 +230,8 @@ int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg) | |||
227 | /** | 230 | /** |
228 | * dwc2_hsotg_tx_fifo_average_depth - returns average depth of device mode | 231 | * dwc2_hsotg_tx_fifo_average_depth - returns average depth of device mode |
229 | * TX FIFOs | 232 | * TX FIFOs |
233 | * | ||
234 | * @hsotg: Programming view of the DWC_otg controller | ||
230 | */ | 235 | */ |
231 | int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg) | 236 | int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg) |
232 | { | 237 | { |
@@ -327,6 +332,7 @@ static void dwc2_hsotg_init_fifo(struct dwc2_hsotg *hsotg) | |||
327 | } | 332 | } |
328 | 333 | ||
329 | /** | 334 | /** |
335 | * dwc2_hsotg_ep_alloc_request - allocate USB rerequest structure | ||
330 | * @ep: USB endpoint to allocate request for. | 336 | * @ep: USB endpoint to allocate request for. |
331 | * @flags: Allocation flags | 337 | * @flags: Allocation flags |
332 | * | 338 | * |
@@ -793,9 +799,7 @@ static void dwc2_gadget_config_nonisoc_xfer_ddma(struct dwc2_hsotg_ep *hs_ep, | |||
793 | * @dma_buff: usb requests dma buffer. | 799 | * @dma_buff: usb requests dma buffer. |
794 | * @len: usb request transfer length. | 800 | * @len: usb request transfer length. |
795 | * | 801 | * |
796 | * Finds out index of first free entry either in the bottom or up half of | 802 | * Fills next free descriptor with the data of the arrived usb request, |
797 | * descriptor chain depend on which is under SW control and not processed | ||
798 | * by HW. Then fills that descriptor with the data of the arrived usb request, | ||
799 | * frame info, sets Last and IOC bits increments next_desc. If filled | 803 | * frame info, sets Last and IOC bits increments next_desc. If filled |
800 | * descriptor is not the first one, removes L bit from the previous descriptor | 804 | * descriptor is not the first one, removes L bit from the previous descriptor |
801 | * status. | 805 | * status. |
@@ -810,34 +814,17 @@ static int dwc2_gadget_fill_isoc_desc(struct dwc2_hsotg_ep *hs_ep, | |||
810 | u32 mask = 0; | 814 | u32 mask = 0; |
811 | 815 | ||
812 | maxsize = dwc2_gadget_get_desc_params(hs_ep, &mask); | 816 | maxsize = dwc2_gadget_get_desc_params(hs_ep, &mask); |
813 | if (len > maxsize) { | ||
814 | dev_err(hsotg->dev, "wrong len %d\n", len); | ||
815 | return -EINVAL; | ||
816 | } | ||
817 | |||
818 | /* | ||
819 | * If SW has already filled half of chain, then return and wait for | ||
820 | * the other chain to be processed by HW. | ||
821 | */ | ||
822 | if (hs_ep->next_desc == MAX_DMA_DESC_NUM_GENERIC / 2) | ||
823 | return -EBUSY; | ||
824 | |||
825 | /* Increment frame number by interval for IN */ | ||
826 | if (hs_ep->dir_in) | ||
827 | dwc2_gadget_incr_frame_num(hs_ep); | ||
828 | 817 | ||
829 | index = (MAX_DMA_DESC_NUM_GENERIC / 2) * hs_ep->isoc_chain_num + | 818 | index = hs_ep->next_desc; |
830 | hs_ep->next_desc; | 819 | desc = &hs_ep->desc_list[index]; |
831 | 820 | ||
832 | /* Sanity check of calculated index */ | 821 | /* Check if descriptor chain full */ |
833 | if ((hs_ep->isoc_chain_num && index > MAX_DMA_DESC_NUM_GENERIC) || | 822 | if ((desc->status >> DEV_DMA_BUFF_STS_SHIFT) == |
834 | (!hs_ep->isoc_chain_num && index > MAX_DMA_DESC_NUM_GENERIC / 2)) { | 823 | DEV_DMA_BUFF_STS_HREADY) { |
835 | dev_err(hsotg->dev, "wrong index %d for iso chain\n", index); | 824 | dev_dbg(hsotg->dev, "%s: desc chain full\n", __func__); |
836 | return -EINVAL; | 825 | return 1; |
837 | } | 826 | } |
838 | 827 | ||
839 | desc = &hs_ep->desc_list[index]; | ||
840 | |||
841 | /* Clear L bit of previous desc if more than one entries in the chain */ | 828 | /* Clear L bit of previous desc if more than one entries in the chain */ |
842 | if (hs_ep->next_desc) | 829 | if (hs_ep->next_desc) |
843 | hs_ep->desc_list[index - 1].status &= ~DEV_DMA_L; | 830 | hs_ep->desc_list[index - 1].status &= ~DEV_DMA_L; |
@@ -865,8 +852,14 @@ static int dwc2_gadget_fill_isoc_desc(struct dwc2_hsotg_ep *hs_ep, | |||
865 | desc->status &= ~DEV_DMA_BUFF_STS_MASK; | 852 | desc->status &= ~DEV_DMA_BUFF_STS_MASK; |
866 | desc->status |= (DEV_DMA_BUFF_STS_HREADY << DEV_DMA_BUFF_STS_SHIFT); | 853 | desc->status |= (DEV_DMA_BUFF_STS_HREADY << DEV_DMA_BUFF_STS_SHIFT); |
867 | 854 | ||
855 | /* Increment frame number by interval for IN */ | ||
856 | if (hs_ep->dir_in) | ||
857 | dwc2_gadget_incr_frame_num(hs_ep); | ||
858 | |||
868 | /* Update index of last configured entry in the chain */ | 859 | /* Update index of last configured entry in the chain */ |
869 | hs_ep->next_desc++; | 860 | hs_ep->next_desc++; |
861 | if (hs_ep->next_desc >= MAX_DMA_DESC_NUM_GENERIC) | ||
862 | hs_ep->next_desc = 0; | ||
870 | 863 | ||
871 | return 0; | 864 | return 0; |
872 | } | 865 | } |
@@ -875,11 +868,8 @@ static int dwc2_gadget_fill_isoc_desc(struct dwc2_hsotg_ep *hs_ep, | |||
875 | * dwc2_gadget_start_isoc_ddma - start isochronous transfer in DDMA | 868 | * dwc2_gadget_start_isoc_ddma - start isochronous transfer in DDMA |
876 | * @hs_ep: The isochronous endpoint. | 869 | * @hs_ep: The isochronous endpoint. |
877 | * | 870 | * |
878 | * Prepare first descriptor chain for isochronous endpoints. Afterwards | 871 | * Prepare descriptor chain for isochronous endpoints. Afterwards |
879 | * write DMA address to HW and enable the endpoint. | 872 | * write DMA address to HW and enable the endpoint. |
880 | * | ||
881 | * Switch between descriptor chains via isoc_chain_num to give SW opportunity | ||
882 | * to prepare second descriptor chain while first one is being processed by HW. | ||
883 | */ | 873 | */ |
884 | static void dwc2_gadget_start_isoc_ddma(struct dwc2_hsotg_ep *hs_ep) | 874 | static void dwc2_gadget_start_isoc_ddma(struct dwc2_hsotg_ep *hs_ep) |
885 | { | 875 | { |
@@ -887,24 +877,34 @@ static void dwc2_gadget_start_isoc_ddma(struct dwc2_hsotg_ep *hs_ep) | |||
887 | struct dwc2_hsotg_req *hs_req, *treq; | 877 | struct dwc2_hsotg_req *hs_req, *treq; |
888 | int index = hs_ep->index; | 878 | int index = hs_ep->index; |
889 | int ret; | 879 | int ret; |
880 | int i; | ||
890 | u32 dma_reg; | 881 | u32 dma_reg; |
891 | u32 depctl; | 882 | u32 depctl; |
892 | u32 ctrl; | 883 | u32 ctrl; |
884 | struct dwc2_dma_desc *desc; | ||
893 | 885 | ||
894 | if (list_empty(&hs_ep->queue)) { | 886 | if (list_empty(&hs_ep->queue)) { |
895 | dev_dbg(hsotg->dev, "%s: No requests in queue\n", __func__); | 887 | dev_dbg(hsotg->dev, "%s: No requests in queue\n", __func__); |
896 | return; | 888 | return; |
897 | } | 889 | } |
898 | 890 | ||
891 | /* Initialize descriptor chain by Host Busy status */ | ||
892 | for (i = 0; i < MAX_DMA_DESC_NUM_GENERIC; i++) { | ||
893 | desc = &hs_ep->desc_list[i]; | ||
894 | desc->status = 0; | ||
895 | desc->status |= (DEV_DMA_BUFF_STS_HBUSY | ||
896 | << DEV_DMA_BUFF_STS_SHIFT); | ||
897 | } | ||
898 | |||
899 | hs_ep->next_desc = 0; | ||
899 | list_for_each_entry_safe(hs_req, treq, &hs_ep->queue, queue) { | 900 | list_for_each_entry_safe(hs_req, treq, &hs_ep->queue, queue) { |
900 | ret = dwc2_gadget_fill_isoc_desc(hs_ep, hs_req->req.dma, | 901 | ret = dwc2_gadget_fill_isoc_desc(hs_ep, hs_req->req.dma, |
901 | hs_req->req.length); | 902 | hs_req->req.length); |
902 | if (ret) { | 903 | if (ret) |
903 | dev_dbg(hsotg->dev, "%s: desc chain full\n", __func__); | ||
904 | break; | 904 | break; |
905 | } | ||
906 | } | 905 | } |
907 | 906 | ||
907 | hs_ep->compl_desc = 0; | ||
908 | depctl = hs_ep->dir_in ? DIEPCTL(index) : DOEPCTL(index); | 908 | depctl = hs_ep->dir_in ? DIEPCTL(index) : DOEPCTL(index); |
909 | dma_reg = hs_ep->dir_in ? DIEPDMA(index) : DOEPDMA(index); | 909 | dma_reg = hs_ep->dir_in ? DIEPDMA(index) : DOEPDMA(index); |
910 | 910 | ||
@@ -914,10 +914,6 @@ static void dwc2_gadget_start_isoc_ddma(struct dwc2_hsotg_ep *hs_ep) | |||
914 | ctrl = dwc2_readl(hsotg->regs + depctl); | 914 | ctrl = dwc2_readl(hsotg->regs + depctl); |
915 | ctrl |= DXEPCTL_EPENA | DXEPCTL_CNAK; | 915 | ctrl |= DXEPCTL_EPENA | DXEPCTL_CNAK; |
916 | dwc2_writel(ctrl, hsotg->regs + depctl); | 916 | dwc2_writel(ctrl, hsotg->regs + depctl); |
917 | |||
918 | /* Switch ISOC descriptor chain number being processed by SW*/ | ||
919 | hs_ep->isoc_chain_num = (hs_ep->isoc_chain_num ^ 1) & 0x1; | ||
920 | hs_ep->next_desc = 0; | ||
921 | } | 917 | } |
922 | 918 | ||
923 | /** | 919 | /** |
@@ -1235,7 +1231,7 @@ static bool dwc2_gadget_target_frame_elapsed(struct dwc2_hsotg_ep *hs_ep) | |||
1235 | { | 1231 | { |
1236 | struct dwc2_hsotg *hsotg = hs_ep->parent; | 1232 | struct dwc2_hsotg *hsotg = hs_ep->parent; |
1237 | u32 target_frame = hs_ep->target_frame; | 1233 | u32 target_frame = hs_ep->target_frame; |
1238 | u32 current_frame = dwc2_hsotg_read_frameno(hsotg); | 1234 | u32 current_frame = hsotg->frame_number; |
1239 | bool frame_overrun = hs_ep->frame_overrun; | 1235 | bool frame_overrun = hs_ep->frame_overrun; |
1240 | 1236 | ||
1241 | if (!frame_overrun && current_frame >= target_frame) | 1237 | if (!frame_overrun && current_frame >= target_frame) |
@@ -1291,6 +1287,9 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, | |||
1291 | struct dwc2_hsotg *hs = hs_ep->parent; | 1287 | struct dwc2_hsotg *hs = hs_ep->parent; |
1292 | bool first; | 1288 | bool first; |
1293 | int ret; | 1289 | int ret; |
1290 | u32 maxsize = 0; | ||
1291 | u32 mask = 0; | ||
1292 | |||
1294 | 1293 | ||
1295 | dev_dbg(hs->dev, "%s: req %p: %d@%p, noi=%d, zero=%d, snok=%d\n", | 1294 | dev_dbg(hs->dev, "%s: req %p: %d@%p, noi=%d, zero=%d, snok=%d\n", |
1296 | ep->name, req, req->length, req->buf, req->no_interrupt, | 1295 | ep->name, req, req->length, req->buf, req->no_interrupt, |
@@ -1308,6 +1307,24 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, | |||
1308 | req->actual = 0; | 1307 | req->actual = 0; |
1309 | req->status = -EINPROGRESS; | 1308 | req->status = -EINPROGRESS; |
1310 | 1309 | ||
1310 | /* In DDMA mode for ISOC's don't queue request if length greater | ||
1311 | * than descriptor limits. | ||
1312 | */ | ||
1313 | if (using_desc_dma(hs) && hs_ep->isochronous) { | ||
1314 | maxsize = dwc2_gadget_get_desc_params(hs_ep, &mask); | ||
1315 | if (hs_ep->dir_in && req->length > maxsize) { | ||
1316 | dev_err(hs->dev, "wrong length %d (maxsize=%d)\n", | ||
1317 | req->length, maxsize); | ||
1318 | return -EINVAL; | ||
1319 | } | ||
1320 | |||
1321 | if (!hs_ep->dir_in && req->length > hs_ep->ep.maxpacket) { | ||
1322 | dev_err(hs->dev, "ISOC OUT: wrong length %d (mps=%d)\n", | ||
1323 | req->length, hs_ep->ep.maxpacket); | ||
1324 | return -EINVAL; | ||
1325 | } | ||
1326 | } | ||
1327 | |||
1311 | ret = dwc2_hsotg_handle_unaligned_buf_start(hs, hs_ep, hs_req); | 1328 | ret = dwc2_hsotg_handle_unaligned_buf_start(hs, hs_ep, hs_req); |
1312 | if (ret) | 1329 | if (ret) |
1313 | return ret; | 1330 | return ret; |
@@ -1330,17 +1347,15 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, | |||
1330 | 1347 | ||
1331 | /* | 1348 | /* |
1332 | * Handle DDMA isochronous transfers separately - just add new entry | 1349 | * Handle DDMA isochronous transfers separately - just add new entry |
1333 | * to the half of descriptor chain that is not processed by HW. | 1350 | * to the descriptor chain. |
1334 | * Transfer will be started once SW gets either one of NAK or | 1351 | * Transfer will be started once SW gets either one of NAK or |
1335 | * OutTknEpDis interrupts. | 1352 | * OutTknEpDis interrupts. |
1336 | */ | 1353 | */ |
1337 | if (using_desc_dma(hs) && hs_ep->isochronous && | 1354 | if (using_desc_dma(hs) && hs_ep->isochronous) { |
1338 | hs_ep->target_frame != TARGET_FRAME_INITIAL) { | 1355 | if (hs_ep->target_frame != TARGET_FRAME_INITIAL) { |
1339 | ret = dwc2_gadget_fill_isoc_desc(hs_ep, hs_req->req.dma, | 1356 | dwc2_gadget_fill_isoc_desc(hs_ep, hs_req->req.dma, |
1340 | hs_req->req.length); | 1357 | hs_req->req.length); |
1341 | if (ret) | 1358 | } |
1342 | dev_dbg(hs->dev, "%s: ISO desc chain full\n", __func__); | ||
1343 | |||
1344 | return 0; | 1359 | return 0; |
1345 | } | 1360 | } |
1346 | 1361 | ||
@@ -1350,8 +1365,15 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, | |||
1350 | return 0; | 1365 | return 0; |
1351 | } | 1366 | } |
1352 | 1367 | ||
1353 | while (dwc2_gadget_target_frame_elapsed(hs_ep)) | 1368 | /* Update current frame number value. */ |
1369 | hs->frame_number = dwc2_hsotg_read_frameno(hs); | ||
1370 | while (dwc2_gadget_target_frame_elapsed(hs_ep)) { | ||
1354 | dwc2_gadget_incr_frame_num(hs_ep); | 1371 | dwc2_gadget_incr_frame_num(hs_ep); |
1372 | /* Update current frame number value once more as it | ||
1373 | * changes here. | ||
1374 | */ | ||
1375 | hs->frame_number = dwc2_hsotg_read_frameno(hs); | ||
1376 | } | ||
1355 | 1377 | ||
1356 | if (hs_ep->target_frame != TARGET_FRAME_INITIAL) | 1378 | if (hs_ep->target_frame != TARGET_FRAME_INITIAL) |
1357 | dwc2_hsotg_start_req(hs, hs_ep, hs_req, false); | 1379 | dwc2_hsotg_start_req(hs, hs_ep, hs_req, false); |
@@ -2011,108 +2033,75 @@ static void dwc2_hsotg_complete_request(struct dwc2_hsotg *hsotg, | |||
2011 | * @hs_ep: The endpoint the request was on. | 2033 | * @hs_ep: The endpoint the request was on. |
2012 | * | 2034 | * |
2013 | * Get first request from the ep queue, determine descriptor on which complete | 2035 | * Get first request from the ep queue, determine descriptor on which complete |
2014 | * happened. SW based on isoc_chain_num discovers which half of the descriptor | 2036 | * happened. SW discovers which descriptor currently in use by HW, adjusts |
2015 | * chain is currently in use by HW, adjusts dma_address and calculates index | 2037 | * dma_address and calculates index of completed descriptor based on the value |
2016 | * of completed descriptor based on the value of DEPDMA register. Update actual | 2038 | * of DEPDMA register. Update actual length of request, giveback to gadget. |
2017 | * length of request, giveback to gadget. | ||
2018 | */ | 2039 | */ |
2019 | static void dwc2_gadget_complete_isoc_request_ddma(struct dwc2_hsotg_ep *hs_ep) | 2040 | static void dwc2_gadget_complete_isoc_request_ddma(struct dwc2_hsotg_ep *hs_ep) |
2020 | { | 2041 | { |
2021 | struct dwc2_hsotg *hsotg = hs_ep->parent; | 2042 | struct dwc2_hsotg *hsotg = hs_ep->parent; |
2022 | struct dwc2_hsotg_req *hs_req; | 2043 | struct dwc2_hsotg_req *hs_req; |
2023 | struct usb_request *ureq; | 2044 | struct usb_request *ureq; |
2024 | int index; | ||
2025 | dma_addr_t dma_addr; | ||
2026 | u32 dma_reg; | ||
2027 | u32 depdma; | ||
2028 | u32 desc_sts; | 2045 | u32 desc_sts; |
2029 | u32 mask; | 2046 | u32 mask; |
2030 | 2047 | ||
2031 | hs_req = get_ep_head(hs_ep); | 2048 | desc_sts = hs_ep->desc_list[hs_ep->compl_desc].status; |
2032 | if (!hs_req) { | ||
2033 | dev_warn(hsotg->dev, "%s: ISOC EP queue empty\n", __func__); | ||
2034 | return; | ||
2035 | } | ||
2036 | ureq = &hs_req->req; | ||
2037 | |||
2038 | dma_addr = hs_ep->desc_list_dma; | ||
2039 | |||
2040 | /* | ||
2041 | * If lower half of descriptor chain is currently use by SW, | ||
2042 | * that means higher half is being processed by HW, so shift | ||
2043 | * DMA address to higher half of descriptor chain. | ||
2044 | */ | ||
2045 | if (!hs_ep->isoc_chain_num) | ||
2046 | dma_addr += sizeof(struct dwc2_dma_desc) * | ||
2047 | (MAX_DMA_DESC_NUM_GENERIC / 2); | ||
2048 | |||
2049 | dma_reg = hs_ep->dir_in ? DIEPDMA(hs_ep->index) : DOEPDMA(hs_ep->index); | ||
2050 | depdma = dwc2_readl(hsotg->regs + dma_reg); | ||
2051 | 2049 | ||
2052 | index = (depdma - dma_addr) / sizeof(struct dwc2_dma_desc) - 1; | 2050 | /* Process only descriptors with buffer status set to DMA done */ |
2053 | desc_sts = hs_ep->desc_list[index].status; | 2051 | while ((desc_sts & DEV_DMA_BUFF_STS_MASK) >> |
2052 | DEV_DMA_BUFF_STS_SHIFT == DEV_DMA_BUFF_STS_DMADONE) { | ||
2054 | 2053 | ||
2055 | mask = hs_ep->dir_in ? DEV_DMA_ISOC_TX_NBYTES_MASK : | 2054 | hs_req = get_ep_head(hs_ep); |
2056 | DEV_DMA_ISOC_RX_NBYTES_MASK; | 2055 | if (!hs_req) { |
2057 | ureq->actual = ureq->length - | 2056 | dev_warn(hsotg->dev, "%s: ISOC EP queue empty\n", __func__); |
2058 | ((desc_sts & mask) >> DEV_DMA_ISOC_NBYTES_SHIFT); | 2057 | return; |
2058 | } | ||
2059 | ureq = &hs_req->req; | ||
2060 | |||
2061 | /* Check completion status */ | ||
2062 | if ((desc_sts & DEV_DMA_STS_MASK) >> DEV_DMA_STS_SHIFT == | ||
2063 | DEV_DMA_STS_SUCC) { | ||
2064 | mask = hs_ep->dir_in ? DEV_DMA_ISOC_TX_NBYTES_MASK : | ||
2065 | DEV_DMA_ISOC_RX_NBYTES_MASK; | ||
2066 | ureq->actual = ureq->length - ((desc_sts & mask) >> | ||
2067 | DEV_DMA_ISOC_NBYTES_SHIFT); | ||
2068 | |||
2069 | /* Adjust actual len for ISOC Out if len is | ||
2070 | * not align of 4 | ||
2071 | */ | ||
2072 | if (!hs_ep->dir_in && ureq->length & 0x3) | ||
2073 | ureq->actual += 4 - (ureq->length & 0x3); | ||
2074 | } | ||
2059 | 2075 | ||
2060 | /* Adjust actual length for ISOC Out if length is not align of 4 */ | 2076 | dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, 0); |
2061 | if (!hs_ep->dir_in && ureq->length & 0x3) | ||
2062 | ureq->actual += 4 - (ureq->length & 0x3); | ||
2063 | 2077 | ||
2064 | dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, 0); | 2078 | hs_ep->compl_desc++; |
2079 | if (hs_ep->compl_desc > (MAX_DMA_DESC_NUM_GENERIC - 1)) | ||
2080 | hs_ep->compl_desc = 0; | ||
2081 | desc_sts = hs_ep->desc_list[hs_ep->compl_desc].status; | ||
2082 | } | ||
2065 | } | 2083 | } |
2066 | 2084 | ||
2067 | /* | 2085 | /* |
2068 | * dwc2_gadget_start_next_isoc_ddma - start next isoc request, if any. | 2086 | * dwc2_gadget_handle_isoc_bna - handle BNA interrupt for ISOC. |
2069 | * @hs_ep: The isochronous endpoint to be re-enabled. | 2087 | * @hs_ep: The isochronous endpoint. |
2070 | * | 2088 | * |
2071 | * If ep has been disabled due to last descriptor servicing (IN endpoint) or | 2089 | * If EP ISOC OUT then need to flush RX FIFO to remove source of BNA |
2072 | * BNA (OUT endpoint) check the status of other half of descriptor chain that | 2090 | * interrupt. Reset target frame and next_desc to allow to start |
2073 | * was under SW control till HW was busy and restart the endpoint if needed. | 2091 | * ISOC's on NAK interrupt for IN direction or on OUTTKNEPDIS |
2092 | * interrupt for OUT direction. | ||
2074 | */ | 2093 | */ |
2075 | static void dwc2_gadget_start_next_isoc_ddma(struct dwc2_hsotg_ep *hs_ep) | 2094 | static void dwc2_gadget_handle_isoc_bna(struct dwc2_hsotg_ep *hs_ep) |
2076 | { | 2095 | { |
2077 | struct dwc2_hsotg *hsotg = hs_ep->parent; | 2096 | struct dwc2_hsotg *hsotg = hs_ep->parent; |
2078 | u32 depctl; | ||
2079 | u32 dma_reg; | ||
2080 | u32 ctrl; | ||
2081 | u32 dma_addr = hs_ep->desc_list_dma; | ||
2082 | unsigned char index = hs_ep->index; | ||
2083 | |||
2084 | dma_reg = hs_ep->dir_in ? DIEPDMA(index) : DOEPDMA(index); | ||
2085 | depctl = hs_ep->dir_in ? DIEPCTL(index) : DOEPCTL(index); | ||
2086 | 2097 | ||
2087 | ctrl = dwc2_readl(hsotg->regs + depctl); | 2098 | if (!hs_ep->dir_in) |
2088 | 2099 | dwc2_flush_rx_fifo(hsotg); | |
2089 | /* | 2100 | dwc2_hsotg_complete_request(hsotg, hs_ep, get_ep_head(hs_ep), 0); |
2090 | * EP was disabled if HW has processed last descriptor or BNA was set. | ||
2091 | * So restart ep if SW has prepared new descriptor chain in ep_queue | ||
2092 | * routine while HW was busy. | ||
2093 | */ | ||
2094 | if (!(ctrl & DXEPCTL_EPENA)) { | ||
2095 | if (!hs_ep->next_desc) { | ||
2096 | dev_dbg(hsotg->dev, "%s: No more ISOC requests\n", | ||
2097 | __func__); | ||
2098 | return; | ||
2099 | } | ||
2100 | |||
2101 | dma_addr += sizeof(struct dwc2_dma_desc) * | ||
2102 | (MAX_DMA_DESC_NUM_GENERIC / 2) * | ||
2103 | hs_ep->isoc_chain_num; | ||
2104 | dwc2_writel(dma_addr, hsotg->regs + dma_reg); | ||
2105 | |||
2106 | ctrl |= DXEPCTL_EPENA | DXEPCTL_CNAK; | ||
2107 | dwc2_writel(ctrl, hsotg->regs + depctl); | ||
2108 | 2101 | ||
2109 | /* Switch ISOC descriptor chain number being processed by SW*/ | 2102 | hs_ep->target_frame = TARGET_FRAME_INITIAL; |
2110 | hs_ep->isoc_chain_num = (hs_ep->isoc_chain_num ^ 1) & 0x1; | 2103 | hs_ep->next_desc = 0; |
2111 | hs_ep->next_desc = 0; | 2104 | hs_ep->compl_desc = 0; |
2112 | |||
2113 | dev_dbg(hsotg->dev, "%s: Restarted isochronous endpoint\n", | ||
2114 | __func__); | ||
2115 | } | ||
2116 | } | 2105 | } |
2117 | 2106 | ||
2118 | /** | 2107 | /** |
@@ -2441,6 +2430,7 @@ static u32 dwc2_hsotg_ep0_mps(unsigned int mps) | |||
2441 | * @ep: The index number of the endpoint | 2430 | * @ep: The index number of the endpoint |
2442 | * @mps: The maximum packet size in bytes | 2431 | * @mps: The maximum packet size in bytes |
2443 | * @mc: The multicount value | 2432 | * @mc: The multicount value |
2433 | * @dir_in: True if direction is in. | ||
2444 | * | 2434 | * |
2445 | * Configure the maximum packet size for the given endpoint, updating | 2435 | * Configure the maximum packet size for the given endpoint, updating |
2446 | * the hardware control registers to reflect this. | 2436 | * the hardware control registers to reflect this. |
@@ -2731,6 +2721,8 @@ static void dwc2_gadget_handle_ep_disabled(struct dwc2_hsotg_ep *hs_ep) | |||
2731 | dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, | 2721 | dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, |
2732 | -ENODATA); | 2722 | -ENODATA); |
2733 | dwc2_gadget_incr_frame_num(hs_ep); | 2723 | dwc2_gadget_incr_frame_num(hs_ep); |
2724 | /* Update current frame number value. */ | ||
2725 | hsotg->frame_number = dwc2_hsotg_read_frameno(hsotg); | ||
2734 | } while (dwc2_gadget_target_frame_elapsed(hs_ep)); | 2726 | } while (dwc2_gadget_target_frame_elapsed(hs_ep)); |
2735 | 2727 | ||
2736 | dwc2_gadget_start_next_request(hs_ep); | 2728 | dwc2_gadget_start_next_request(hs_ep); |
@@ -2738,7 +2730,7 @@ static void dwc2_gadget_handle_ep_disabled(struct dwc2_hsotg_ep *hs_ep) | |||
2738 | 2730 | ||
2739 | /** | 2731 | /** |
2740 | * dwc2_gadget_handle_out_token_ep_disabled - handle DXEPINT_OUTTKNEPDIS | 2732 | * dwc2_gadget_handle_out_token_ep_disabled - handle DXEPINT_OUTTKNEPDIS |
2741 | * @hs_ep: The endpoint on which interrupt is asserted. | 2733 | * @ep: The endpoint on which interrupt is asserted. |
2742 | * | 2734 | * |
2743 | * This is starting point for ISOC-OUT transfer, synchronization done with | 2735 | * This is starting point for ISOC-OUT transfer, synchronization done with |
2744 | * first out token received from host while corresponding EP is disabled. | 2736 | * first out token received from host while corresponding EP is disabled. |
@@ -2763,7 +2755,7 @@ static void dwc2_gadget_handle_out_token_ep_disabled(struct dwc2_hsotg_ep *ep) | |||
2763 | */ | 2755 | */ |
2764 | tmp = dwc2_hsotg_read_frameno(hsotg); | 2756 | tmp = dwc2_hsotg_read_frameno(hsotg); |
2765 | 2757 | ||
2766 | dwc2_hsotg_complete_request(hsotg, ep, get_ep_head(ep), -ENODATA); | 2758 | dwc2_hsotg_complete_request(hsotg, ep, get_ep_head(ep), 0); |
2767 | 2759 | ||
2768 | if (using_desc_dma(hsotg)) { | 2760 | if (using_desc_dma(hsotg)) { |
2769 | if (ep->target_frame == TARGET_FRAME_INITIAL) { | 2761 | if (ep->target_frame == TARGET_FRAME_INITIAL) { |
@@ -2816,18 +2808,25 @@ static void dwc2_gadget_handle_nak(struct dwc2_hsotg_ep *hs_ep) | |||
2816 | { | 2808 | { |
2817 | struct dwc2_hsotg *hsotg = hs_ep->parent; | 2809 | struct dwc2_hsotg *hsotg = hs_ep->parent; |
2818 | int dir_in = hs_ep->dir_in; | 2810 | int dir_in = hs_ep->dir_in; |
2811 | u32 tmp; | ||
2819 | 2812 | ||
2820 | if (!dir_in || !hs_ep->isochronous) | 2813 | if (!dir_in || !hs_ep->isochronous) |
2821 | return; | 2814 | return; |
2822 | 2815 | ||
2823 | if (hs_ep->target_frame == TARGET_FRAME_INITIAL) { | 2816 | if (hs_ep->target_frame == TARGET_FRAME_INITIAL) { |
2824 | hs_ep->target_frame = dwc2_hsotg_read_frameno(hsotg); | ||
2825 | 2817 | ||
2818 | tmp = dwc2_hsotg_read_frameno(hsotg); | ||
2826 | if (using_desc_dma(hsotg)) { | 2819 | if (using_desc_dma(hsotg)) { |
2820 | dwc2_hsotg_complete_request(hsotg, hs_ep, | ||
2821 | get_ep_head(hs_ep), 0); | ||
2822 | |||
2823 | hs_ep->target_frame = tmp; | ||
2824 | dwc2_gadget_incr_frame_num(hs_ep); | ||
2827 | dwc2_gadget_start_isoc_ddma(hs_ep); | 2825 | dwc2_gadget_start_isoc_ddma(hs_ep); |
2828 | return; | 2826 | return; |
2829 | } | 2827 | } |
2830 | 2828 | ||
2829 | hs_ep->target_frame = tmp; | ||
2831 | if (hs_ep->interval > 1) { | 2830 | if (hs_ep->interval > 1) { |
2832 | u32 ctrl = dwc2_readl(hsotg->regs + | 2831 | u32 ctrl = dwc2_readl(hsotg->regs + |
2833 | DIEPCTL(hs_ep->index)); | 2832 | DIEPCTL(hs_ep->index)); |
@@ -2843,7 +2842,8 @@ static void dwc2_gadget_handle_nak(struct dwc2_hsotg_ep *hs_ep) | |||
2843 | get_ep_head(hs_ep), 0); | 2842 | get_ep_head(hs_ep), 0); |
2844 | } | 2843 | } |
2845 | 2844 | ||
2846 | dwc2_gadget_incr_frame_num(hs_ep); | 2845 | if (!using_desc_dma(hsotg)) |
2846 | dwc2_gadget_incr_frame_num(hs_ep); | ||
2847 | } | 2847 | } |
2848 | 2848 | ||
2849 | /** | 2849 | /** |
@@ -2901,9 +2901,9 @@ static void dwc2_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx, | |||
2901 | 2901 | ||
2902 | /* In DDMA handle isochronous requests separately */ | 2902 | /* In DDMA handle isochronous requests separately */ |
2903 | if (using_desc_dma(hsotg) && hs_ep->isochronous) { | 2903 | if (using_desc_dma(hsotg) && hs_ep->isochronous) { |
2904 | dwc2_gadget_complete_isoc_request_ddma(hs_ep); | 2904 | /* XferCompl set along with BNA */ |
2905 | /* Try to start next isoc request */ | 2905 | if (!(ints & DXEPINT_BNAINTR)) |
2906 | dwc2_gadget_start_next_isoc_ddma(hs_ep); | 2906 | dwc2_gadget_complete_isoc_request_ddma(hs_ep); |
2907 | } else if (dir_in) { | 2907 | } else if (dir_in) { |
2908 | /* | 2908 | /* |
2909 | * We get OutDone from the FIFO, so we only | 2909 | * We get OutDone from the FIFO, so we only |
@@ -2978,15 +2978,8 @@ static void dwc2_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx, | |||
2978 | 2978 | ||
2979 | if (ints & DXEPINT_BNAINTR) { | 2979 | if (ints & DXEPINT_BNAINTR) { |
2980 | dev_dbg(hsotg->dev, "%s: BNA interrupt\n", __func__); | 2980 | dev_dbg(hsotg->dev, "%s: BNA interrupt\n", __func__); |
2981 | |||
2982 | /* | ||
2983 | * Try to start next isoc request, if any. | ||
2984 | * Sometimes the endpoint remains enabled after BNA interrupt | ||
2985 | * assertion, which is not expected, hence we can enter here | ||
2986 | * couple of times. | ||
2987 | */ | ||
2988 | if (hs_ep->isochronous) | 2981 | if (hs_ep->isochronous) |
2989 | dwc2_gadget_start_next_isoc_ddma(hs_ep); | 2982 | dwc2_gadget_handle_isoc_bna(hs_ep); |
2990 | } | 2983 | } |
2991 | 2984 | ||
2992 | if (dir_in && !hs_ep->isochronous) { | 2985 | if (dir_in && !hs_ep->isochronous) { |
@@ -3197,6 +3190,7 @@ static void dwc2_hsotg_irq_fifoempty(struct dwc2_hsotg *hsotg, bool periodic) | |||
3197 | /** | 3190 | /** |
3198 | * dwc2_hsotg_core_init - issue softreset to the core | 3191 | * dwc2_hsotg_core_init - issue softreset to the core |
3199 | * @hsotg: The device state | 3192 | * @hsotg: The device state |
3193 | * @is_usb_reset: Usb resetting flag | ||
3200 | * | 3194 | * |
3201 | * Issue a soft reset to the core, and await the core finishing it. | 3195 | * Issue a soft reset to the core, and await the core finishing it. |
3202 | */ | 3196 | */ |
@@ -3259,6 +3253,9 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, | |||
3259 | dcfg |= DCFG_DEVSPD_HS; | 3253 | dcfg |= DCFG_DEVSPD_HS; |
3260 | } | 3254 | } |
3261 | 3255 | ||
3256 | if (hsotg->params.ipg_isoc_en) | ||
3257 | dcfg |= DCFG_IPG_ISOC_SUPPORDED; | ||
3258 | |||
3262 | dwc2_writel(dcfg, hsotg->regs + DCFG); | 3259 | dwc2_writel(dcfg, hsotg->regs + DCFG); |
3263 | 3260 | ||
3264 | /* Clear any pending OTG interrupts */ | 3261 | /* Clear any pending OTG interrupts */ |
@@ -3320,8 +3317,10 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg, | |||
3320 | hsotg->regs + DOEPMSK); | 3317 | hsotg->regs + DOEPMSK); |
3321 | 3318 | ||
3322 | /* Enable BNA interrupt for DDMA */ | 3319 | /* Enable BNA interrupt for DDMA */ |
3323 | if (using_desc_dma(hsotg)) | 3320 | if (using_desc_dma(hsotg)) { |
3324 | dwc2_set_bit(hsotg->regs + DOEPMSK, DOEPMSK_BNAMSK); | 3321 | dwc2_set_bit(hsotg->regs + DOEPMSK, DOEPMSK_BNAMSK); |
3322 | dwc2_set_bit(hsotg->regs + DIEPMSK, DIEPMSK_BNAININTRMSK); | ||
3323 | } | ||
3325 | 3324 | ||
3326 | dwc2_writel(0, hsotg->regs + DAINTMSK); | 3325 | dwc2_writel(0, hsotg->regs + DAINTMSK); |
3327 | 3326 | ||
@@ -3427,7 +3426,7 @@ static void dwc2_gadget_handle_incomplete_isoc_in(struct dwc2_hsotg *hsotg) | |||
3427 | 3426 | ||
3428 | daintmsk = dwc2_readl(hsotg->regs + DAINTMSK); | 3427 | daintmsk = dwc2_readl(hsotg->regs + DAINTMSK); |
3429 | 3428 | ||
3430 | for (idx = 1; idx <= hsotg->num_of_eps; idx++) { | 3429 | for (idx = 1; idx < hsotg->num_of_eps; idx++) { |
3431 | hs_ep = hsotg->eps_in[idx]; | 3430 | hs_ep = hsotg->eps_in[idx]; |
3432 | /* Proceed only unmasked ISOC EPs */ | 3431 | /* Proceed only unmasked ISOC EPs */ |
3433 | if (!hs_ep->isochronous || (BIT(idx) & ~daintmsk)) | 3432 | if (!hs_ep->isochronous || (BIT(idx) & ~daintmsk)) |
@@ -3473,7 +3472,7 @@ static void dwc2_gadget_handle_incomplete_isoc_out(struct dwc2_hsotg *hsotg) | |||
3473 | daintmsk = dwc2_readl(hsotg->regs + DAINTMSK); | 3472 | daintmsk = dwc2_readl(hsotg->regs + DAINTMSK); |
3474 | daintmsk >>= DAINT_OUTEP_SHIFT; | 3473 | daintmsk >>= DAINT_OUTEP_SHIFT; |
3475 | 3474 | ||
3476 | for (idx = 1; idx <= hsotg->num_of_eps; idx++) { | 3475 | for (idx = 1; idx < hsotg->num_of_eps; idx++) { |
3477 | hs_ep = hsotg->eps_out[idx]; | 3476 | hs_ep = hsotg->eps_out[idx]; |
3478 | /* Proceed only unmasked ISOC EPs */ | 3477 | /* Proceed only unmasked ISOC EPs */ |
3479 | if (!hs_ep->isochronous || (BIT(idx) & ~daintmsk)) | 3478 | if (!hs_ep->isochronous || (BIT(idx) & ~daintmsk)) |
@@ -3647,7 +3646,7 @@ irq_retry: | |||
3647 | dwc2_writel(gintmsk, hsotg->regs + GINTMSK); | 3646 | dwc2_writel(gintmsk, hsotg->regs + GINTMSK); |
3648 | 3647 | ||
3649 | dev_dbg(hsotg->dev, "GOUTNakEff triggered\n"); | 3648 | dev_dbg(hsotg->dev, "GOUTNakEff triggered\n"); |
3650 | for (idx = 1; idx <= hsotg->num_of_eps; idx++) { | 3649 | for (idx = 1; idx < hsotg->num_of_eps; idx++) { |
3651 | hs_ep = hsotg->eps_out[idx]; | 3650 | hs_ep = hsotg->eps_out[idx]; |
3652 | /* Proceed only unmasked ISOC EPs */ | 3651 | /* Proceed only unmasked ISOC EPs */ |
3653 | if (!hs_ep->isochronous || (BIT(idx) & ~daintmsk)) | 3652 | if (!hs_ep->isochronous || (BIT(idx) & ~daintmsk)) |
@@ -3789,6 +3788,7 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep, | |||
3789 | unsigned int dir_in; | 3788 | unsigned int dir_in; |
3790 | unsigned int i, val, size; | 3789 | unsigned int i, val, size; |
3791 | int ret = 0; | 3790 | int ret = 0; |
3791 | unsigned char ep_type; | ||
3792 | 3792 | ||
3793 | dev_dbg(hsotg->dev, | 3793 | dev_dbg(hsotg->dev, |
3794 | "%s: ep %s: a 0x%02x, attr 0x%02x, mps 0x%04x, intr %d\n", | 3794 | "%s: ep %s: a 0x%02x, attr 0x%02x, mps 0x%04x, intr %d\n", |
@@ -3807,9 +3807,26 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep, | |||
3807 | return -EINVAL; | 3807 | return -EINVAL; |
3808 | } | 3808 | } |
3809 | 3809 | ||
3810 | ep_type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; | ||
3810 | mps = usb_endpoint_maxp(desc); | 3811 | mps = usb_endpoint_maxp(desc); |
3811 | mc = usb_endpoint_maxp_mult(desc); | 3812 | mc = usb_endpoint_maxp_mult(desc); |
3812 | 3813 | ||
3814 | /* ISOC IN in DDMA supported bInterval up to 10 */ | ||
3815 | if (using_desc_dma(hsotg) && ep_type == USB_ENDPOINT_XFER_ISOC && | ||
3816 | dir_in && desc->bInterval > 10) { | ||
3817 | dev_err(hsotg->dev, | ||
3818 | "%s: ISOC IN, DDMA: bInterval>10 not supported!\n", __func__); | ||
3819 | return -EINVAL; | ||
3820 | } | ||
3821 | |||
3822 | /* High bandwidth ISOC OUT in DDMA not supported */ | ||
3823 | if (using_desc_dma(hsotg) && ep_type == USB_ENDPOINT_XFER_ISOC && | ||
3824 | !dir_in && mc > 1) { | ||
3825 | dev_err(hsotg->dev, | ||
3826 | "%s: ISOC OUT, DDMA: HB not supported!\n", __func__); | ||
3827 | return -EINVAL; | ||
3828 | } | ||
3829 | |||
3813 | /* note, we handle this here instead of dwc2_hsotg_set_ep_maxpacket */ | 3830 | /* note, we handle this here instead of dwc2_hsotg_set_ep_maxpacket */ |
3814 | 3831 | ||
3815 | epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index); | 3832 | epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index); |
@@ -3850,15 +3867,15 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep, | |||
3850 | hs_ep->halted = 0; | 3867 | hs_ep->halted = 0; |
3851 | hs_ep->interval = desc->bInterval; | 3868 | hs_ep->interval = desc->bInterval; |
3852 | 3869 | ||
3853 | switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { | 3870 | switch (ep_type) { |
3854 | case USB_ENDPOINT_XFER_ISOC: | 3871 | case USB_ENDPOINT_XFER_ISOC: |
3855 | epctrl |= DXEPCTL_EPTYPE_ISO; | 3872 | epctrl |= DXEPCTL_EPTYPE_ISO; |
3856 | epctrl |= DXEPCTL_SETEVENFR; | 3873 | epctrl |= DXEPCTL_SETEVENFR; |
3857 | hs_ep->isochronous = 1; | 3874 | hs_ep->isochronous = 1; |
3858 | hs_ep->interval = 1 << (desc->bInterval - 1); | 3875 | hs_ep->interval = 1 << (desc->bInterval - 1); |
3859 | hs_ep->target_frame = TARGET_FRAME_INITIAL; | 3876 | hs_ep->target_frame = TARGET_FRAME_INITIAL; |
3860 | hs_ep->isoc_chain_num = 0; | ||
3861 | hs_ep->next_desc = 0; | 3877 | hs_ep->next_desc = 0; |
3878 | hs_ep->compl_desc = 0; | ||
3862 | if (dir_in) { | 3879 | if (dir_in) { |
3863 | hs_ep->periodic = 1; | 3880 | hs_ep->periodic = 1; |
3864 | mask = dwc2_readl(hsotg->regs + DIEPMSK); | 3881 | mask = dwc2_readl(hsotg->regs + DIEPMSK); |
@@ -4301,7 +4318,6 @@ err: | |||
4301 | /** | 4318 | /** |
4302 | * dwc2_hsotg_udc_stop - stop the udc | 4319 | * dwc2_hsotg_udc_stop - stop the udc |
4303 | * @gadget: The usb gadget state | 4320 | * @gadget: The usb gadget state |
4304 | * @driver: The usb gadget driver | ||
4305 | * | 4321 | * |
4306 | * Stop udc hw block and stay tunned for future transmissions | 4322 | * Stop udc hw block and stay tunned for future transmissions |
4307 | */ | 4323 | */ |
@@ -4453,6 +4469,7 @@ static const struct usb_gadget_ops dwc2_hsotg_gadget_ops = { | |||
4453 | * @hsotg: The device state. | 4469 | * @hsotg: The device state. |
4454 | * @hs_ep: The endpoint to be initialised. | 4470 | * @hs_ep: The endpoint to be initialised. |
4455 | * @epnum: The endpoint number | 4471 | * @epnum: The endpoint number |
4472 | * @dir_in: True if direction is in. | ||
4456 | * | 4473 | * |
4457 | * Initialise the given endpoint (as part of the probe and device state | 4474 | * Initialise the given endpoint (as part of the probe and device state |
4458 | * creation) to give to the gadget driver. Setup the endpoint name, any | 4475 | * creation) to give to the gadget driver. Setup the endpoint name, any |
@@ -4526,7 +4543,7 @@ static void dwc2_hsotg_initep(struct dwc2_hsotg *hsotg, | |||
4526 | 4543 | ||
4527 | /** | 4544 | /** |
4528 | * dwc2_hsotg_hw_cfg - read HW configuration registers | 4545 | * dwc2_hsotg_hw_cfg - read HW configuration registers |
4529 | * @param: The device state | 4546 | * @hsotg: Programming view of the DWC_otg controller |
4530 | * | 4547 | * |
4531 | * Read the USB core HW configuration registers | 4548 | * Read the USB core HW configuration registers |
4532 | */ | 4549 | */ |
@@ -4582,7 +4599,8 @@ static int dwc2_hsotg_hw_cfg(struct dwc2_hsotg *hsotg) | |||
4582 | 4599 | ||
4583 | /** | 4600 | /** |
4584 | * dwc2_hsotg_dump - dump state of the udc | 4601 | * dwc2_hsotg_dump - dump state of the udc |
4585 | * @param: The device state | 4602 | * @hsotg: Programming view of the DWC_otg controller |
4603 | * | ||
4586 | */ | 4604 | */ |
4587 | static void dwc2_hsotg_dump(struct dwc2_hsotg *hsotg) | 4605 | static void dwc2_hsotg_dump(struct dwc2_hsotg *hsotg) |
4588 | { | 4606 | { |
@@ -4633,7 +4651,8 @@ static void dwc2_hsotg_dump(struct dwc2_hsotg *hsotg) | |||
4633 | 4651 | ||
4634 | /** | 4652 | /** |
4635 | * dwc2_gadget_init - init function for gadget | 4653 | * dwc2_gadget_init - init function for gadget |
4636 | * @dwc2: The data structure for the DWC2 driver. | 4654 | * @hsotg: Programming view of the DWC_otg controller |
4655 | * | ||
4637 | */ | 4656 | */ |
4638 | int dwc2_gadget_init(struct dwc2_hsotg *hsotg) | 4657 | int dwc2_gadget_init(struct dwc2_hsotg *hsotg) |
4639 | { | 4658 | { |
@@ -4730,7 +4749,8 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg) | |||
4730 | 4749 | ||
4731 | /** | 4750 | /** |
4732 | * dwc2_hsotg_remove - remove function for hsotg driver | 4751 | * dwc2_hsotg_remove - remove function for hsotg driver |
4733 | * @pdev: The platform information for the driver | 4752 | * @hsotg: Programming view of the DWC_otg controller |
4753 | * | ||
4734 | */ | 4754 | */ |
4735 | int dwc2_hsotg_remove(struct dwc2_hsotg *hsotg) | 4755 | int dwc2_hsotg_remove(struct dwc2_hsotg *hsotg) |
4736 | { | 4756 | { |
@@ -5011,7 +5031,7 @@ int dwc2_gadget_enter_hibernation(struct dwc2_hsotg *hsotg) | |||
5011 | * | 5031 | * |
5012 | * @hsotg: Programming view of the DWC_otg controller | 5032 | * @hsotg: Programming view of the DWC_otg controller |
5013 | * @rem_wakeup: indicates whether resume is initiated by Device or Host. | 5033 | * @rem_wakeup: indicates whether resume is initiated by Device or Host. |
5014 | * @param reset: indicates whether resume is initiated by Reset. | 5034 | * @reset: indicates whether resume is initiated by Reset. |
5015 | * | 5035 | * |
5016 | * Return non-zero if failed to exit from hibernation. | 5036 | * Return non-zero if failed to exit from hibernation. |
5017 | */ | 5037 | */ |
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index c51b73b3e048..1faefea16cec 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c | |||
@@ -597,7 +597,7 @@ u32 dwc2_calc_frame_interval(struct dwc2_hsotg *hsotg) | |||
597 | * dwc2_read_packet() - Reads a packet from the Rx FIFO into the destination | 597 | * dwc2_read_packet() - Reads a packet from the Rx FIFO into the destination |
598 | * buffer | 598 | * buffer |
599 | * | 599 | * |
600 | * @core_if: Programming view of DWC_otg controller | 600 | * @hsotg: Programming view of DWC_otg controller |
601 | * @dest: Destination buffer for the packet | 601 | * @dest: Destination buffer for the packet |
602 | * @bytes: Number of bytes to copy to the destination | 602 | * @bytes: Number of bytes to copy to the destination |
603 | */ | 603 | */ |
@@ -4087,7 +4087,6 @@ static struct dwc2_hsotg *dwc2_hcd_to_hsotg(struct usb_hcd *hcd) | |||
4087 | * then the refcount for the structure will go to 0 and we'll free it. | 4087 | * then the refcount for the structure will go to 0 and we'll free it. |
4088 | * | 4088 | * |
4089 | * @hsotg: The HCD state structure for the DWC OTG controller. | 4089 | * @hsotg: The HCD state structure for the DWC OTG controller. |
4090 | * @qh: The QH structure. | ||
4091 | * @context: The priv pointer from a struct dwc2_hcd_urb. | 4090 | * @context: The priv pointer from a struct dwc2_hcd_urb. |
4092 | * @mem_flags: Flags for allocating memory. | 4091 | * @mem_flags: Flags for allocating memory. |
4093 | * @ttport: We'll return this device's port number here. That's used to | 4092 | * @ttport: We'll return this device's port number here. That's used to |
diff --git a/drivers/usb/dwc2/hcd.h b/drivers/usb/dwc2/hcd.h index 96a9da5fb202..7db1ee7e7a77 100644 --- a/drivers/usb/dwc2/hcd.h +++ b/drivers/usb/dwc2/hcd.h | |||
@@ -80,7 +80,7 @@ struct dwc2_qh; | |||
80 | * @xfer_count: Number of bytes transferred so far | 80 | * @xfer_count: Number of bytes transferred so far |
81 | * @start_pkt_count: Packet count at start of transfer | 81 | * @start_pkt_count: Packet count at start of transfer |
82 | * @xfer_started: True if the transfer has been started | 82 | * @xfer_started: True if the transfer has been started |
83 | * @ping: True if a PING request should be issued on this channel | 83 | * @do_ping: True if a PING request should be issued on this channel |
84 | * @error_state: True if the error count for this transaction is non-zero | 84 | * @error_state: True if the error count for this transaction is non-zero |
85 | * @halt_on_queue: True if this channel should be halted the next time a | 85 | * @halt_on_queue: True if this channel should be halted the next time a |
86 | * request is queued for the channel. This is necessary in | 86 | * request is queued for the channel. This is necessary in |
@@ -102,7 +102,7 @@ struct dwc2_qh; | |||
102 | * @schinfo: Scheduling micro-frame bitmap | 102 | * @schinfo: Scheduling micro-frame bitmap |
103 | * @ntd: Number of transfer descriptors for the transfer | 103 | * @ntd: Number of transfer descriptors for the transfer |
104 | * @halt_status: Reason for halting the host channel | 104 | * @halt_status: Reason for halting the host channel |
105 | * @hcint Contents of the HCINT register when the interrupt came | 105 | * @hcint: Contents of the HCINT register when the interrupt came |
106 | * @qh: QH for the transfer being processed by this channel | 106 | * @qh: QH for the transfer being processed by this channel |
107 | * @hc_list_entry: For linking to list of host channels | 107 | * @hc_list_entry: For linking to list of host channels |
108 | * @desc_list_addr: Current QH's descriptor list DMA address | 108 | * @desc_list_addr: Current QH's descriptor list DMA address |
@@ -237,7 +237,7 @@ struct dwc2_tt { | |||
237 | /** | 237 | /** |
238 | * struct dwc2_hs_transfer_time - Info about a transfer on the high speed bus. | 238 | * struct dwc2_hs_transfer_time - Info about a transfer on the high speed bus. |
239 | * | 239 | * |
240 | * @start_schedule_usecs: The start time on the main bus schedule. Note that | 240 | * @start_schedule_us: The start time on the main bus schedule. Note that |
241 | * the main bus schedule is tightly packed and this | 241 | * the main bus schedule is tightly packed and this |
242 | * time should be interpreted as tightly packed (so | 242 | * time should be interpreted as tightly packed (so |
243 | * uFrame 0 starts at 0 us, uFrame 1 starts at 100 us | 243 | * uFrame 0 starts at 0 us, uFrame 1 starts at 100 us |
@@ -301,7 +301,6 @@ struct dwc2_hs_transfer_time { | |||
301 | * "struct dwc2_tt". Not used if this device is high | 301 | * "struct dwc2_tt". Not used if this device is high |
302 | * speed. Note that this is in "schedule slice" which | 302 | * speed. Note that this is in "schedule slice" which |
303 | * is tightly packed. | 303 | * is tightly packed. |
304 | * @ls_duration_us: Duration on the low speed bus schedule. | ||
305 | * @ntd: Actual number of transfer descriptors in a list | 304 | * @ntd: Actual number of transfer descriptors in a list |
306 | * @qtd_list: List of QTDs for this QH | 305 | * @qtd_list: List of QTDs for this QH |
307 | * @channel: Host channel currently processing transfers for this QH | 306 | * @channel: Host channel currently processing transfers for this QH |
@@ -315,7 +314,7 @@ struct dwc2_hs_transfer_time { | |||
315 | * descriptor | 314 | * descriptor |
316 | * @unreserve_timer: Timer for releasing periodic reservation. | 315 | * @unreserve_timer: Timer for releasing periodic reservation. |
317 | * @wait_timer: Timer used to wait before re-queuing. | 316 | * @wait_timer: Timer used to wait before re-queuing. |
318 | * @dwc2_tt: Pointer to our tt info (or NULL if no tt). | 317 | * @dwc_tt: Pointer to our tt info (or NULL if no tt). |
319 | * @ttport: Port number within our tt. | 318 | * @ttport: Port number within our tt. |
320 | * @tt_buffer_dirty True if clear_tt_buffer_complete is pending | 319 | * @tt_buffer_dirty True if clear_tt_buffer_complete is pending |
321 | * @unreserve_pending: True if we planned to unreserve but haven't yet. | 320 | * @unreserve_pending: True if we planned to unreserve but haven't yet. |
@@ -325,6 +324,7 @@ struct dwc2_hs_transfer_time { | |||
325 | * periodic transfers and is ignored for periodic ones. | 324 | * periodic transfers and is ignored for periodic ones. |
326 | * @wait_timer_cancel: Set to true to cancel the wait_timer. | 325 | * @wait_timer_cancel: Set to true to cancel the wait_timer. |
327 | * | 326 | * |
327 | * @tt_buffer_dirty: True if EP's TT buffer is not clean. | ||
328 | * A Queue Head (QH) holds the static characteristics of an endpoint and | 328 | * A Queue Head (QH) holds the static characteristics of an endpoint and |
329 | * maintains a list of transfers (QTDs) for that endpoint. A QH structure may | 329 | * maintains a list of transfers (QTDs) for that endpoint. A QH structure may |
330 | * be entered in either the non-periodic or periodic schedule. | 330 | * be entered in either the non-periodic or periodic schedule. |
@@ -400,6 +400,10 @@ struct dwc2_qh { | |||
400 | * @urb: URB for this transfer | 400 | * @urb: URB for this transfer |
401 | * @qh: Queue head for this QTD | 401 | * @qh: Queue head for this QTD |
402 | * @qtd_list_entry: For linking to the QH's list of QTDs | 402 | * @qtd_list_entry: For linking to the QH's list of QTDs |
403 | * @isoc_td_first: Index of first activated isochronous transfer | ||
404 | * descriptor in Descriptor DMA mode | ||
405 | * @isoc_td_last: Index of last activated isochronous transfer | ||
406 | * descriptor in Descriptor DMA mode | ||
403 | * | 407 | * |
404 | * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control, | 408 | * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control, |
405 | * interrupt, or isochronous transfer. A single QTD is created for each URB | 409 | * interrupt, or isochronous transfer. A single QTD is created for each URB |
diff --git a/drivers/usb/dwc2/hcd_ddma.c b/drivers/usb/dwc2/hcd_ddma.c index 28c8898b3b66..74f11c823f79 100644 --- a/drivers/usb/dwc2/hcd_ddma.c +++ b/drivers/usb/dwc2/hcd_ddma.c | |||
@@ -332,6 +332,7 @@ static void dwc2_release_channel_ddma(struct dwc2_hsotg *hsotg, | |||
332 | * | 332 | * |
333 | * @hsotg: The HCD state structure for the DWC OTG controller | 333 | * @hsotg: The HCD state structure for the DWC OTG controller |
334 | * @qh: The QH to init | 334 | * @qh: The QH to init |
335 | * @mem_flags: Indicates the type of memory allocation | ||
335 | * | 336 | * |
336 | * Return: 0 if successful, negative error code otherwise | 337 | * Return: 0 if successful, negative error code otherwise |
337 | * | 338 | * |
diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c index a5dfd9d8bd9a..fbea5e3fb947 100644 --- a/drivers/usb/dwc2/hcd_intr.c +++ b/drivers/usb/dwc2/hcd_intr.c | |||
@@ -478,6 +478,12 @@ static u32 dwc2_get_actual_xfer_length(struct dwc2_hsotg *hsotg, | |||
478 | * of the URB based on the number of bytes transferred via the host channel. | 478 | * of the URB based on the number of bytes transferred via the host channel. |
479 | * Sets the URB status if the data transfer is finished. | 479 | * Sets the URB status if the data transfer is finished. |
480 | * | 480 | * |
481 | * @hsotg: Programming view of the DWC_otg controller | ||
482 | * @chan: Programming view of host channel | ||
483 | * @chnum: Channel number | ||
484 | * @urb: Processing URB | ||
485 | * @qtd: Queue transfer descriptor | ||
486 | * | ||
481 | * Return: 1 if the data transfer specified by the URB is completely finished, | 487 | * Return: 1 if the data transfer specified by the URB is completely finished, |
482 | * 0 otherwise | 488 | * 0 otherwise |
483 | */ | 489 | */ |
@@ -566,6 +572,12 @@ void dwc2_hcd_save_data_toggle(struct dwc2_hsotg *hsotg, | |||
566 | * halt_status. Completes the Isochronous URB if all the URB frames have been | 572 | * halt_status. Completes the Isochronous URB if all the URB frames have been |
567 | * completed. | 573 | * completed. |
568 | * | 574 | * |
575 | * @hsotg: Programming view of the DWC_otg controller | ||
576 | * @chan: Programming view of host channel | ||
577 | * @chnum: Channel number | ||
578 | * @halt_status: Reason for halting a host channel | ||
579 | * @qtd: Queue transfer descriptor | ||
580 | * | ||
569 | * Return: DWC2_HC_XFER_COMPLETE if there are more frames remaining to be | 581 | * Return: DWC2_HC_XFER_COMPLETE if there are more frames remaining to be |
570 | * transferred in the URB. Otherwise return DWC2_HC_XFER_URB_COMPLETE. | 582 | * transferred in the URB. Otherwise return DWC2_HC_XFER_URB_COMPLETE. |
571 | */ | 583 | */ |
diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c index e34ad5e65350..d7c3d6c776d8 100644 --- a/drivers/usb/dwc2/hcd_queue.c +++ b/drivers/usb/dwc2/hcd_queue.c | |||
@@ -679,6 +679,7 @@ static int dwc2_hs_pmap_schedule(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, | |||
679 | * | 679 | * |
680 | * @hsotg: The HCD state structure for the DWC OTG controller. | 680 | * @hsotg: The HCD state structure for the DWC OTG controller. |
681 | * @qh: QH for the periodic transfer. | 681 | * @qh: QH for the periodic transfer. |
682 | * @index: Transfer index | ||
682 | */ | 683 | */ |
683 | static void dwc2_hs_pmap_unschedule(struct dwc2_hsotg *hsotg, | 684 | static void dwc2_hs_pmap_unschedule(struct dwc2_hsotg *hsotg, |
684 | struct dwc2_qh *qh, int index) | 685 | struct dwc2_qh *qh, int index) |
@@ -1276,7 +1277,7 @@ static void dwc2_do_unreserve(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) | |||
1276 | * release the reservation. This worker is called after the appropriate | 1277 | * release the reservation. This worker is called after the appropriate |
1277 | * delay. | 1278 | * delay. |
1278 | * | 1279 | * |
1279 | * @work: Pointer to a qh unreserve_work. | 1280 | * @t: Address to a qh unreserve_work. |
1280 | */ | 1281 | */ |
1281 | static void dwc2_unreserve_timer_fn(struct timer_list *t) | 1282 | static void dwc2_unreserve_timer_fn(struct timer_list *t) |
1282 | { | 1283 | { |
@@ -1631,7 +1632,7 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, | |||
1631 | * @hsotg: The HCD state structure for the DWC OTG controller | 1632 | * @hsotg: The HCD state structure for the DWC OTG controller |
1632 | * @urb: Holds the information about the device/endpoint needed | 1633 | * @urb: Holds the information about the device/endpoint needed |
1633 | * to initialize the QH | 1634 | * to initialize the QH |
1634 | * @atomic_alloc: Flag to do atomic allocation if needed | 1635 | * @mem_flags: Flags for allocating memory. |
1635 | * | 1636 | * |
1636 | * Return: Pointer to the newly allocated QH, or NULL on error | 1637 | * Return: Pointer to the newly allocated QH, or NULL on error |
1637 | */ | 1638 | */ |
diff --git a/drivers/usb/dwc2/hw.h b/drivers/usb/dwc2/hw.h index 38391e48351f..0ca8e7bc7aaf 100644 --- a/drivers/usb/dwc2/hw.h +++ b/drivers/usb/dwc2/hw.h | |||
@@ -311,6 +311,7 @@ | |||
311 | #define GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK (0x3 << 14) | 311 | #define GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK (0x3 << 14) |
312 | #define GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT 14 | 312 | #define GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT 14 |
313 | #define GHWCFG4_ACG_SUPPORTED BIT(12) | 313 | #define GHWCFG4_ACG_SUPPORTED BIT(12) |
314 | #define GHWCFG4_IPG_ISOC_SUPPORTED BIT(11) | ||
314 | #define GHWCFG4_UTMI_PHY_DATA_WIDTH_8 0 | 315 | #define GHWCFG4_UTMI_PHY_DATA_WIDTH_8 0 |
315 | #define GHWCFG4_UTMI_PHY_DATA_WIDTH_16 1 | 316 | #define GHWCFG4_UTMI_PHY_DATA_WIDTH_16 1 |
316 | #define GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16 2 | 317 | #define GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16 2 |
@@ -424,6 +425,7 @@ | |||
424 | #define DCFG_EPMISCNT_SHIFT 18 | 425 | #define DCFG_EPMISCNT_SHIFT 18 |
425 | #define DCFG_EPMISCNT_LIMIT 0x1f | 426 | #define DCFG_EPMISCNT_LIMIT 0x1f |
426 | #define DCFG_EPMISCNT(_x) ((_x) << 18) | 427 | #define DCFG_EPMISCNT(_x) ((_x) << 18) |
428 | #define DCFG_IPG_ISOC_SUPPORDED BIT(17) | ||
427 | #define DCFG_PERFRINT_MASK (0x3 << 11) | 429 | #define DCFG_PERFRINT_MASK (0x3 << 11) |
428 | #define DCFG_PERFRINT_SHIFT 11 | 430 | #define DCFG_PERFRINT_SHIFT 11 |
429 | #define DCFG_PERFRINT_LIMIT 0x3 | 431 | #define DCFG_PERFRINT_LIMIT 0x3 |
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index f03e41879224..af075d4da895 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c | |||
@@ -70,6 +70,7 @@ static void dwc2_set_his_params(struct dwc2_hsotg *hsotg) | |||
70 | GAHBCFG_HBSTLEN_SHIFT; | 70 | GAHBCFG_HBSTLEN_SHIFT; |
71 | p->uframe_sched = false; | 71 | p->uframe_sched = false; |
72 | p->change_speed_quirk = true; | 72 | p->change_speed_quirk = true; |
73 | p->power_down = false; | ||
73 | } | 74 | } |
74 | 75 | ||
75 | static void dwc2_set_rk_params(struct dwc2_hsotg *hsotg) | 76 | static void dwc2_set_rk_params(struct dwc2_hsotg *hsotg) |
@@ -269,6 +270,9 @@ static void dwc2_set_param_power_down(struct dwc2_hsotg *hsotg) | |||
269 | /** | 270 | /** |
270 | * dwc2_set_default_params() - Set all core parameters to their | 271 | * dwc2_set_default_params() - Set all core parameters to their |
271 | * auto-detected default values. | 272 | * auto-detected default values. |
273 | * | ||
274 | * @hsotg: Programming view of the DWC_otg controller | ||
275 | * | ||
272 | */ | 276 | */ |
273 | static void dwc2_set_default_params(struct dwc2_hsotg *hsotg) | 277 | static void dwc2_set_default_params(struct dwc2_hsotg *hsotg) |
274 | { | 278 | { |
@@ -298,6 +302,7 @@ static void dwc2_set_default_params(struct dwc2_hsotg *hsotg) | |||
298 | p->besl = true; | 302 | p->besl = true; |
299 | p->hird_threshold_en = true; | 303 | p->hird_threshold_en = true; |
300 | p->hird_threshold = 4; | 304 | p->hird_threshold = 4; |
305 | p->ipg_isoc_en = false; | ||
301 | p->max_packet_count = hw->max_packet_count; | 306 | p->max_packet_count = hw->max_packet_count; |
302 | p->max_transfer_size = hw->max_transfer_size; | 307 | p->max_transfer_size = hw->max_transfer_size; |
303 | p->ahbcfg = GAHBCFG_HBSTLEN_INCR << GAHBCFG_HBSTLEN_SHIFT; | 308 | p->ahbcfg = GAHBCFG_HBSTLEN_INCR << GAHBCFG_HBSTLEN_SHIFT; |
@@ -338,6 +343,8 @@ static void dwc2_set_default_params(struct dwc2_hsotg *hsotg) | |||
338 | /** | 343 | /** |
339 | * dwc2_get_device_properties() - Read in device properties. | 344 | * dwc2_get_device_properties() - Read in device properties. |
340 | * | 345 | * |
346 | * @hsotg: Programming view of the DWC_otg controller | ||
347 | * | ||
341 | * Read in the device properties and adjust core parameters if needed. | 348 | * Read in the device properties and adjust core parameters if needed. |
342 | */ | 349 | */ |
343 | static void dwc2_get_device_properties(struct dwc2_hsotg *hsotg) | 350 | static void dwc2_get_device_properties(struct dwc2_hsotg *hsotg) |
@@ -549,7 +556,7 @@ static void dwc2_check_param_tx_fifo_sizes(struct dwc2_hsotg *hsotg) | |||
549 | } | 556 | } |
550 | 557 | ||
551 | #define CHECK_RANGE(_param, _min, _max, _def) do { \ | 558 | #define CHECK_RANGE(_param, _min, _max, _def) do { \ |
552 | if ((hsotg->params._param) < (_min) || \ | 559 | if ((int)(hsotg->params._param) < (_min) || \ |
553 | (hsotg->params._param) > (_max)) { \ | 560 | (hsotg->params._param) > (_max)) { \ |
554 | dev_warn(hsotg->dev, "%s: Invalid parameter %s=%d\n", \ | 561 | dev_warn(hsotg->dev, "%s: Invalid parameter %s=%d\n", \ |
555 | __func__, #_param, hsotg->params._param); \ | 562 | __func__, #_param, hsotg->params._param); \ |
@@ -579,6 +586,7 @@ static void dwc2_check_params(struct dwc2_hsotg *hsotg) | |||
579 | CHECK_BOOL(enable_dynamic_fifo, hw->enable_dynamic_fifo); | 586 | CHECK_BOOL(enable_dynamic_fifo, hw->enable_dynamic_fifo); |
580 | CHECK_BOOL(en_multiple_tx_fifo, hw->en_multiple_tx_fifo); | 587 | CHECK_BOOL(en_multiple_tx_fifo, hw->en_multiple_tx_fifo); |
581 | CHECK_BOOL(i2c_enable, hw->i2c_enable); | 588 | CHECK_BOOL(i2c_enable, hw->i2c_enable); |
589 | CHECK_BOOL(ipg_isoc_en, hw->ipg_isoc_en); | ||
582 | CHECK_BOOL(acg_enable, hw->acg_enable); | 590 | CHECK_BOOL(acg_enable, hw->acg_enable); |
583 | CHECK_BOOL(reload_ctl, (hsotg->hw_params.snpsid > DWC2_CORE_REV_2_92a)); | 591 | CHECK_BOOL(reload_ctl, (hsotg->hw_params.snpsid > DWC2_CORE_REV_2_92a)); |
584 | CHECK_BOOL(lpm, (hsotg->hw_params.snpsid >= DWC2_CORE_REV_2_80a)); | 592 | CHECK_BOOL(lpm, (hsotg->hw_params.snpsid >= DWC2_CORE_REV_2_80a)); |
@@ -688,6 +696,9 @@ static void dwc2_get_dev_hwparams(struct dwc2_hsotg *hsotg) | |||
688 | /** | 696 | /** |
689 | * During device initialization, read various hardware configuration | 697 | * During device initialization, read various hardware configuration |
690 | * registers and interpret the contents. | 698 | * registers and interpret the contents. |
699 | * | ||
700 | * @hsotg: Programming view of the DWC_otg controller | ||
701 | * | ||
691 | */ | 702 | */ |
692 | int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) | 703 | int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) |
693 | { | 704 | { |
@@ -772,6 +783,7 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) | |||
772 | hw->utmi_phy_data_width = (hwcfg4 & GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK) >> | 783 | hw->utmi_phy_data_width = (hwcfg4 & GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK) >> |
773 | GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT; | 784 | GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT; |
774 | hw->acg_enable = !!(hwcfg4 & GHWCFG4_ACG_SUPPORTED); | 785 | hw->acg_enable = !!(hwcfg4 & GHWCFG4_ACG_SUPPORTED); |
786 | hw->ipg_isoc_en = !!(hwcfg4 & GHWCFG4_IPG_ISOC_SUPPORTED); | ||
775 | 787 | ||
776 | /* fifo sizes */ | 788 | /* fifo sizes */ |
777 | hw->rx_fifo_size = (grxfsiz & GRXFSIZ_DEPTH_MASK) >> | 789 | hw->rx_fifo_size = (grxfsiz & GRXFSIZ_DEPTH_MASK) >> |
diff --git a/drivers/usb/dwc2/pci.c b/drivers/usb/dwc2/pci.c index bea2e8ec0369..d257c541e51b 100644 --- a/drivers/usb/dwc2/pci.c +++ b/drivers/usb/dwc2/pci.c | |||
@@ -77,6 +77,12 @@ static int dwc2_pci_quirks(struct pci_dev *pdev, struct platform_device *dwc2) | |||
77 | return 0; | 77 | return 0; |
78 | } | 78 | } |
79 | 79 | ||
80 | /** | ||
81 | * dwc2_pci_probe() - Provides the cleanup entry points for the DWC_otg PCI | ||
82 | * driver | ||
83 | * | ||
84 | * @pci: The programming view of DWC_otg PCI | ||
85 | */ | ||
80 | static void dwc2_pci_remove(struct pci_dev *pci) | 86 | static void dwc2_pci_remove(struct pci_dev *pci) |
81 | { | 87 | { |
82 | struct dwc2_pci_glue *glue = pci_get_drvdata(pci); | 88 | struct dwc2_pci_glue *glue = pci_get_drvdata(pci); |
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index ab8c0e0d3b60..451012ea1294 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig | |||
@@ -106,4 +106,16 @@ config USB_DWC3_ST | |||
106 | inside (i.e. STiH407). | 106 | inside (i.e. STiH407). |
107 | Say 'Y' or 'M' if you have one such device. | 107 | Say 'Y' or 'M' if you have one such device. |
108 | 108 | ||
109 | config USB_DWC3_QCOM | ||
110 | tristate "Qualcomm Platform" | ||
111 | depends on ARCH_QCOM || COMPILE_TEST | ||
112 | depends on OF | ||
113 | default USB_DWC3 | ||
114 | help | ||
115 | Some Qualcomm SoCs use DesignWare Core IP for USB2/3 | ||
116 | functionality. | ||
117 | This driver also handles Qscratch wrapper which is needed | ||
118 | for peripheral mode support. | ||
119 | Say 'Y' or 'M' if you have one such device. | ||
120 | |||
109 | endif | 121 | endif |
diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index 025bc68094fc..5c07d8f925e0 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile | |||
@@ -48,3 +48,4 @@ obj-$(CONFIG_USB_DWC3_PCI) += dwc3-pci.o | |||
48 | obj-$(CONFIG_USB_DWC3_KEYSTONE) += dwc3-keystone.o | 48 | obj-$(CONFIG_USB_DWC3_KEYSTONE) += dwc3-keystone.o |
49 | obj-$(CONFIG_USB_DWC3_OF_SIMPLE) += dwc3-of-simple.o | 49 | obj-$(CONFIG_USB_DWC3_OF_SIMPLE) += dwc3-of-simple.o |
50 | obj-$(CONFIG_USB_DWC3_ST) += dwc3-st.o | 50 | obj-$(CONFIG_USB_DWC3_ST) += dwc3-st.o |
51 | obj-$(CONFIG_USB_DWC3_QCOM) += dwc3-qcom.o | ||
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index a15648d25e30..ea91310113b9 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 8 | * Sebastian Andrzej Siewior <bigeasy@linutronix.de> |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/clk.h> | ||
11 | #include <linux/version.h> | 12 | #include <linux/version.h> |
12 | #include <linux/module.h> | 13 | #include <linux/module.h> |
13 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
@@ -24,6 +25,7 @@ | |||
24 | #include <linux/of.h> | 25 | #include <linux/of.h> |
25 | #include <linux/acpi.h> | 26 | #include <linux/acpi.h> |
26 | #include <linux/pinctrl/consumer.h> | 27 | #include <linux/pinctrl/consumer.h> |
28 | #include <linux/reset.h> | ||
27 | 29 | ||
28 | #include <linux/usb/ch9.h> | 30 | #include <linux/usb/ch9.h> |
29 | #include <linux/usb/gadget.h> | 31 | #include <linux/usb/gadget.h> |
@@ -266,6 +268,12 @@ done: | |||
266 | return 0; | 268 | return 0; |
267 | } | 269 | } |
268 | 270 | ||
271 | static const struct clk_bulk_data dwc3_core_clks[] = { | ||
272 | { .id = "ref" }, | ||
273 | { .id = "bus_early" }, | ||
274 | { .id = "suspend" }, | ||
275 | }; | ||
276 | |||
269 | /* | 277 | /* |
270 | * dwc3_frame_length_adjustment - Adjusts frame length if required | 278 | * dwc3_frame_length_adjustment - Adjusts frame length if required |
271 | * @dwc3: Pointer to our controller context structure | 279 | * @dwc3: Pointer to our controller context structure |
@@ -667,6 +675,9 @@ static void dwc3_core_exit(struct dwc3 *dwc) | |||
667 | usb_phy_set_suspend(dwc->usb3_phy, 1); | 675 | usb_phy_set_suspend(dwc->usb3_phy, 1); |
668 | phy_power_off(dwc->usb2_generic_phy); | 676 | phy_power_off(dwc->usb2_generic_phy); |
669 | phy_power_off(dwc->usb3_generic_phy); | 677 | phy_power_off(dwc->usb3_generic_phy); |
678 | clk_bulk_disable(dwc->num_clks, dwc->clks); | ||
679 | clk_bulk_unprepare(dwc->num_clks, dwc->clks); | ||
680 | reset_control_assert(dwc->reset); | ||
670 | } | 681 | } |
671 | 682 | ||
672 | static bool dwc3_core_is_valid(struct dwc3 *dwc) | 683 | static bool dwc3_core_is_valid(struct dwc3 *dwc) |
@@ -1245,7 +1256,7 @@ static void dwc3_check_params(struct dwc3 *dwc) | |||
1245 | static int dwc3_probe(struct platform_device *pdev) | 1256 | static int dwc3_probe(struct platform_device *pdev) |
1246 | { | 1257 | { |
1247 | struct device *dev = &pdev->dev; | 1258 | struct device *dev = &pdev->dev; |
1248 | struct resource *res; | 1259 | struct resource *res, dwc_res; |
1249 | struct dwc3 *dwc; | 1260 | struct dwc3 *dwc; |
1250 | 1261 | ||
1251 | int ret; | 1262 | int ret; |
@@ -1256,6 +1267,12 @@ static int dwc3_probe(struct platform_device *pdev) | |||
1256 | if (!dwc) | 1267 | if (!dwc) |
1257 | return -ENOMEM; | 1268 | return -ENOMEM; |
1258 | 1269 | ||
1270 | dwc->clks = devm_kmemdup(dev, dwc3_core_clks, sizeof(dwc3_core_clks), | ||
1271 | GFP_KERNEL); | ||
1272 | if (!dwc->clks) | ||
1273 | return -ENOMEM; | ||
1274 | |||
1275 | dwc->num_clks = ARRAY_SIZE(dwc3_core_clks); | ||
1259 | dwc->dev = dev; | 1276 | dwc->dev = dev; |
1260 | 1277 | ||
1261 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1278 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -1270,23 +1287,48 @@ static int dwc3_probe(struct platform_device *pdev) | |||
1270 | dwc->xhci_resources[0].flags = res->flags; | 1287 | dwc->xhci_resources[0].flags = res->flags; |
1271 | dwc->xhci_resources[0].name = res->name; | 1288 | dwc->xhci_resources[0].name = res->name; |
1272 | 1289 | ||
1273 | res->start += DWC3_GLOBALS_REGS_START; | ||
1274 | |||
1275 | /* | 1290 | /* |
1276 | * Request memory region but exclude xHCI regs, | 1291 | * Request memory region but exclude xHCI regs, |
1277 | * since it will be requested by the xhci-plat driver. | 1292 | * since it will be requested by the xhci-plat driver. |
1278 | */ | 1293 | */ |
1279 | regs = devm_ioremap_resource(dev, res); | 1294 | dwc_res = *res; |
1280 | if (IS_ERR(regs)) { | 1295 | dwc_res.start += DWC3_GLOBALS_REGS_START; |
1281 | ret = PTR_ERR(regs); | 1296 | |
1282 | goto err0; | 1297 | regs = devm_ioremap_resource(dev, &dwc_res); |
1283 | } | 1298 | if (IS_ERR(regs)) |
1299 | return PTR_ERR(regs); | ||
1284 | 1300 | ||
1285 | dwc->regs = regs; | 1301 | dwc->regs = regs; |
1286 | dwc->regs_size = resource_size(res); | 1302 | dwc->regs_size = resource_size(&dwc_res); |
1287 | 1303 | ||
1288 | dwc3_get_properties(dwc); | 1304 | dwc3_get_properties(dwc); |
1289 | 1305 | ||
1306 | dwc->reset = devm_reset_control_get_optional_shared(dev, NULL); | ||
1307 | if (IS_ERR(dwc->reset)) | ||
1308 | return PTR_ERR(dwc->reset); | ||
1309 | |||
1310 | ret = clk_bulk_get(dev, dwc->num_clks, dwc->clks); | ||
1311 | if (ret == -EPROBE_DEFER) | ||
1312 | return ret; | ||
1313 | /* | ||
1314 | * Clocks are optional, but new DT platforms should support all clocks | ||
1315 | * as required by the DT-binding. | ||
1316 | */ | ||
1317 | if (ret) | ||
1318 | dwc->num_clks = 0; | ||
1319 | |||
1320 | ret = reset_control_deassert(dwc->reset); | ||
1321 | if (ret) | ||
1322 | goto put_clks; | ||
1323 | |||
1324 | ret = clk_bulk_prepare(dwc->num_clks, dwc->clks); | ||
1325 | if (ret) | ||
1326 | goto assert_reset; | ||
1327 | |||
1328 | ret = clk_bulk_enable(dwc->num_clks, dwc->clks); | ||
1329 | if (ret) | ||
1330 | goto unprepare_clks; | ||
1331 | |||
1290 | platform_set_drvdata(pdev, dwc); | 1332 | platform_set_drvdata(pdev, dwc); |
1291 | dwc3_cache_hwparams(dwc); | 1333 | dwc3_cache_hwparams(dwc); |
1292 | 1334 | ||
@@ -1350,13 +1392,13 @@ err1: | |||
1350 | pm_runtime_put_sync(&pdev->dev); | 1392 | pm_runtime_put_sync(&pdev->dev); |
1351 | pm_runtime_disable(&pdev->dev); | 1393 | pm_runtime_disable(&pdev->dev); |
1352 | 1394 | ||
1353 | err0: | 1395 | clk_bulk_disable(dwc->num_clks, dwc->clks); |
1354 | /* | 1396 | unprepare_clks: |
1355 | * restore res->start back to its original value so that, in case the | 1397 | clk_bulk_unprepare(dwc->num_clks, dwc->clks); |
1356 | * probe is deferred, we don't end up getting error in request the | 1398 | assert_reset: |
1357 | * memory region the next time probe is called. | 1399 | reset_control_assert(dwc->reset); |
1358 | */ | 1400 | put_clks: |
1359 | res->start -= DWC3_GLOBALS_REGS_START; | 1401 | clk_bulk_put(dwc->num_clks, dwc->clks); |
1360 | 1402 | ||
1361 | return ret; | 1403 | return ret; |
1362 | } | 1404 | } |
@@ -1364,15 +1406,8 @@ err0: | |||
1364 | static int dwc3_remove(struct platform_device *pdev) | 1406 | static int dwc3_remove(struct platform_device *pdev) |
1365 | { | 1407 | { |
1366 | struct dwc3 *dwc = platform_get_drvdata(pdev); | 1408 | struct dwc3 *dwc = platform_get_drvdata(pdev); |
1367 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1368 | 1409 | ||
1369 | pm_runtime_get_sync(&pdev->dev); | 1410 | pm_runtime_get_sync(&pdev->dev); |
1370 | /* | ||
1371 | * restore res->start back to its original value so that, in case the | ||
1372 | * probe is deferred, we don't end up getting error in request the | ||
1373 | * memory region the next time probe is called. | ||
1374 | */ | ||
1375 | res->start -= DWC3_GLOBALS_REGS_START; | ||
1376 | 1411 | ||
1377 | dwc3_debugfs_exit(dwc); | 1412 | dwc3_debugfs_exit(dwc); |
1378 | dwc3_core_exit_mode(dwc); | 1413 | dwc3_core_exit_mode(dwc); |
@@ -1386,14 +1421,48 @@ static int dwc3_remove(struct platform_device *pdev) | |||
1386 | 1421 | ||
1387 | dwc3_free_event_buffers(dwc); | 1422 | dwc3_free_event_buffers(dwc); |
1388 | dwc3_free_scratch_buffers(dwc); | 1423 | dwc3_free_scratch_buffers(dwc); |
1424 | clk_bulk_put(dwc->num_clks, dwc->clks); | ||
1389 | 1425 | ||
1390 | return 0; | 1426 | return 0; |
1391 | } | 1427 | } |
1392 | 1428 | ||
1393 | #ifdef CONFIG_PM | 1429 | #ifdef CONFIG_PM |
1430 | static int dwc3_core_init_for_resume(struct dwc3 *dwc) | ||
1431 | { | ||
1432 | int ret; | ||
1433 | |||
1434 | ret = reset_control_deassert(dwc->reset); | ||
1435 | if (ret) | ||
1436 | return ret; | ||
1437 | |||
1438 | ret = clk_bulk_prepare(dwc->num_clks, dwc->clks); | ||
1439 | if (ret) | ||
1440 | goto assert_reset; | ||
1441 | |||
1442 | ret = clk_bulk_enable(dwc->num_clks, dwc->clks); | ||
1443 | if (ret) | ||
1444 | goto unprepare_clks; | ||
1445 | |||
1446 | ret = dwc3_core_init(dwc); | ||
1447 | if (ret) | ||
1448 | goto disable_clks; | ||
1449 | |||
1450 | return 0; | ||
1451 | |||
1452 | disable_clks: | ||
1453 | clk_bulk_disable(dwc->num_clks, dwc->clks); | ||
1454 | unprepare_clks: | ||
1455 | clk_bulk_unprepare(dwc->num_clks, dwc->clks); | ||
1456 | assert_reset: | ||
1457 | reset_control_assert(dwc->reset); | ||
1458 | |||
1459 | return ret; | ||
1460 | } | ||
1461 | |||
1394 | static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) | 1462 | static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) |
1395 | { | 1463 | { |
1396 | unsigned long flags; | 1464 | unsigned long flags; |
1465 | u32 reg; | ||
1397 | 1466 | ||
1398 | switch (dwc->current_dr_role) { | 1467 | switch (dwc->current_dr_role) { |
1399 | case DWC3_GCTL_PRTCAP_DEVICE: | 1468 | case DWC3_GCTL_PRTCAP_DEVICE: |
@@ -1403,9 +1472,25 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) | |||
1403 | dwc3_core_exit(dwc); | 1472 | dwc3_core_exit(dwc); |
1404 | break; | 1473 | break; |
1405 | case DWC3_GCTL_PRTCAP_HOST: | 1474 | case DWC3_GCTL_PRTCAP_HOST: |
1406 | /* do nothing during host runtime_suspend */ | 1475 | if (!PMSG_IS_AUTO(msg)) { |
1407 | if (!PMSG_IS_AUTO(msg)) | ||
1408 | dwc3_core_exit(dwc); | 1476 | dwc3_core_exit(dwc); |
1477 | break; | ||
1478 | } | ||
1479 | |||
1480 | /* Let controller to suspend HSPHY before PHY driver suspends */ | ||
1481 | if (dwc->dis_u2_susphy_quirk || | ||
1482 | dwc->dis_enblslpm_quirk) { | ||
1483 | reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); | ||
1484 | reg |= DWC3_GUSB2PHYCFG_ENBLSLPM | | ||
1485 | DWC3_GUSB2PHYCFG_SUSPHY; | ||
1486 | dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); | ||
1487 | |||
1488 | /* Give some time for USB2 PHY to suspend */ | ||
1489 | usleep_range(5000, 6000); | ||
1490 | } | ||
1491 | |||
1492 | phy_pm_runtime_put_sync(dwc->usb2_generic_phy); | ||
1493 | phy_pm_runtime_put_sync(dwc->usb3_generic_phy); | ||
1409 | break; | 1494 | break; |
1410 | case DWC3_GCTL_PRTCAP_OTG: | 1495 | case DWC3_GCTL_PRTCAP_OTG: |
1411 | /* do nothing during runtime_suspend */ | 1496 | /* do nothing during runtime_suspend */ |
@@ -1433,10 +1518,11 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg) | |||
1433 | { | 1518 | { |
1434 | unsigned long flags; | 1519 | unsigned long flags; |
1435 | int ret; | 1520 | int ret; |
1521 | u32 reg; | ||
1436 | 1522 | ||
1437 | switch (dwc->current_dr_role) { | 1523 | switch (dwc->current_dr_role) { |
1438 | case DWC3_GCTL_PRTCAP_DEVICE: | 1524 | case DWC3_GCTL_PRTCAP_DEVICE: |
1439 | ret = dwc3_core_init(dwc); | 1525 | ret = dwc3_core_init_for_resume(dwc); |
1440 | if (ret) | 1526 | if (ret) |
1441 | return ret; | 1527 | return ret; |
1442 | 1528 | ||
@@ -1446,13 +1532,25 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg) | |||
1446 | spin_unlock_irqrestore(&dwc->lock, flags); | 1532 | spin_unlock_irqrestore(&dwc->lock, flags); |
1447 | break; | 1533 | break; |
1448 | case DWC3_GCTL_PRTCAP_HOST: | 1534 | case DWC3_GCTL_PRTCAP_HOST: |
1449 | /* nothing to do on host runtime_resume */ | ||
1450 | if (!PMSG_IS_AUTO(msg)) { | 1535 | if (!PMSG_IS_AUTO(msg)) { |
1451 | ret = dwc3_core_init(dwc); | 1536 | ret = dwc3_core_init_for_resume(dwc); |
1452 | if (ret) | 1537 | if (ret) |
1453 | return ret; | 1538 | return ret; |
1454 | dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); | 1539 | dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); |
1540 | break; | ||
1455 | } | 1541 | } |
1542 | /* Restore GUSB2PHYCFG bits that were modified in suspend */ | ||
1543 | reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); | ||
1544 | if (dwc->dis_u2_susphy_quirk) | ||
1545 | reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; | ||
1546 | |||
1547 | if (dwc->dis_enblslpm_quirk) | ||
1548 | reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; | ||
1549 | |||
1550 | dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); | ||
1551 | |||
1552 | phy_pm_runtime_get_sync(dwc->usb2_generic_phy); | ||
1553 | phy_pm_runtime_get_sync(dwc->usb3_generic_phy); | ||
1456 | break; | 1554 | break; |
1457 | case DWC3_GCTL_PRTCAP_OTG: | 1555 | case DWC3_GCTL_PRTCAP_OTG: |
1458 | /* nothing to do on runtime_resume */ | 1556 | /* nothing to do on runtime_resume */ |
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 4f3b43809917..285ce0ef3b91 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h | |||
@@ -639,8 +639,6 @@ struct dwc3_event_buffer { | |||
639 | * @resource_index: Resource transfer index | 639 | * @resource_index: Resource transfer index |
640 | * @frame_number: set to the frame number we want this transfer to start (ISOC) | 640 | * @frame_number: set to the frame number we want this transfer to start (ISOC) |
641 | * @interval: the interval on which the ISOC transfer is started | 641 | * @interval: the interval on which the ISOC transfer is started |
642 | * @allocated_requests: number of requests allocated | ||
643 | * @queued_requests: number of requests queued for transfer | ||
644 | * @name: a human readable name e.g. ep1out-bulk | 642 | * @name: a human readable name e.g. ep1out-bulk |
645 | * @direction: true for TX, false for RX | 643 | * @direction: true for TX, false for RX |
646 | * @stream_capable: true when streams are enabled | 644 | * @stream_capable: true when streams are enabled |
@@ -664,11 +662,9 @@ struct dwc3_ep { | |||
664 | #define DWC3_EP_ENABLED BIT(0) | 662 | #define DWC3_EP_ENABLED BIT(0) |
665 | #define DWC3_EP_STALL BIT(1) | 663 | #define DWC3_EP_STALL BIT(1) |
666 | #define DWC3_EP_WEDGE BIT(2) | 664 | #define DWC3_EP_WEDGE BIT(2) |
667 | #define DWC3_EP_BUSY BIT(4) | 665 | #define DWC3_EP_TRANSFER_STARTED BIT(3) |
668 | #define DWC3_EP_PENDING_REQUEST BIT(5) | 666 | #define DWC3_EP_PENDING_REQUEST BIT(5) |
669 | #define DWC3_EP_MISSED_ISOC BIT(6) | ||
670 | #define DWC3_EP_END_TRANSFER_PENDING BIT(7) | 667 | #define DWC3_EP_END_TRANSFER_PENDING BIT(7) |
671 | #define DWC3_EP_TRANSFER_STARTED BIT(8) | ||
672 | 668 | ||
673 | /* This last one is specific to EP0 */ | 669 | /* This last one is specific to EP0 */ |
674 | #define DWC3_EP0_DIR_IN BIT(31) | 670 | #define DWC3_EP0_DIR_IN BIT(31) |
@@ -688,8 +684,6 @@ struct dwc3_ep { | |||
688 | u8 number; | 684 | u8 number; |
689 | u8 type; | 685 | u8 type; |
690 | u8 resource_index; | 686 | u8 resource_index; |
691 | u32 allocated_requests; | ||
692 | u32 queued_requests; | ||
693 | u32 frame_number; | 687 | u32 frame_number; |
694 | u32 interval; | 688 | u32 interval; |
695 | 689 | ||
@@ -832,7 +826,9 @@ struct dwc3_hwparams { | |||
832 | * @list: a list_head used for request queueing | 826 | * @list: a list_head used for request queueing |
833 | * @dep: struct dwc3_ep owning this request | 827 | * @dep: struct dwc3_ep owning this request |
834 | * @sg: pointer to first incomplete sg | 828 | * @sg: pointer to first incomplete sg |
829 | * @start_sg: pointer to the sg which should be queued next | ||
835 | * @num_pending_sgs: counter to pending sgs | 830 | * @num_pending_sgs: counter to pending sgs |
831 | * @num_queued_sgs: counter to the number of sgs which already got queued | ||
836 | * @remaining: amount of data remaining | 832 | * @remaining: amount of data remaining |
837 | * @epnum: endpoint number to which this request refers | 833 | * @epnum: endpoint number to which this request refers |
838 | * @trb: pointer to struct dwc3_trb | 834 | * @trb: pointer to struct dwc3_trb |
@@ -848,8 +844,10 @@ struct dwc3_request { | |||
848 | struct list_head list; | 844 | struct list_head list; |
849 | struct dwc3_ep *dep; | 845 | struct dwc3_ep *dep; |
850 | struct scatterlist *sg; | 846 | struct scatterlist *sg; |
847 | struct scatterlist *start_sg; | ||
851 | 848 | ||
852 | unsigned num_pending_sgs; | 849 | unsigned num_pending_sgs; |
850 | unsigned int num_queued_sgs; | ||
853 | unsigned remaining; | 851 | unsigned remaining; |
854 | u8 epnum; | 852 | u8 epnum; |
855 | struct dwc3_trb *trb; | 853 | struct dwc3_trb *trb; |
@@ -891,6 +889,9 @@ struct dwc3_scratchpad_array { | |||
891 | * @eps: endpoint array | 889 | * @eps: endpoint array |
892 | * @gadget: device side representation of the peripheral controller | 890 | * @gadget: device side representation of the peripheral controller |
893 | * @gadget_driver: pointer to the gadget driver | 891 | * @gadget_driver: pointer to the gadget driver |
892 | * @clks: array of clocks | ||
893 | * @num_clks: number of clocks | ||
894 | * @reset: reset control | ||
894 | * @regs: base address for our registers | 895 | * @regs: base address for our registers |
895 | * @regs_size: address space size | 896 | * @regs_size: address space size |
896 | * @fladj: frame length adjustment | 897 | * @fladj: frame length adjustment |
@@ -1013,6 +1014,11 @@ struct dwc3 { | |||
1013 | struct usb_gadget gadget; | 1014 | struct usb_gadget gadget; |
1014 | struct usb_gadget_driver *gadget_driver; | 1015 | struct usb_gadget_driver *gadget_driver; |
1015 | 1016 | ||
1017 | struct clk_bulk_data *clks; | ||
1018 | int num_clks; | ||
1019 | |||
1020 | struct reset_control *reset; | ||
1021 | |||
1016 | struct usb_phy *usb2_phy; | 1022 | struct usb_phy *usb2_phy; |
1017 | struct usb_phy *usb3_phy; | 1023 | struct usb_phy *usb3_phy; |
1018 | 1024 | ||
@@ -1197,11 +1203,12 @@ struct dwc3_event_depevt { | |||
1197 | /* Within XferNotReady */ | 1203 | /* Within XferNotReady */ |
1198 | #define DEPEVT_STATUS_TRANSFER_ACTIVE BIT(3) | 1204 | #define DEPEVT_STATUS_TRANSFER_ACTIVE BIT(3) |
1199 | 1205 | ||
1200 | /* Within XferComplete */ | 1206 | /* Within XferComplete or XferInProgress */ |
1201 | #define DEPEVT_STATUS_BUSERR BIT(0) | 1207 | #define DEPEVT_STATUS_BUSERR BIT(0) |
1202 | #define DEPEVT_STATUS_SHORT BIT(1) | 1208 | #define DEPEVT_STATUS_SHORT BIT(1) |
1203 | #define DEPEVT_STATUS_IOC BIT(2) | 1209 | #define DEPEVT_STATUS_IOC BIT(2) |
1204 | #define DEPEVT_STATUS_LST BIT(3) | 1210 | #define DEPEVT_STATUS_LST BIT(3) /* XferComplete */ |
1211 | #define DEPEVT_STATUS_MISSED_ISOC BIT(3) /* XferInProgress */ | ||
1205 | 1212 | ||
1206 | /* Stream event only */ | 1213 | /* Stream event only */ |
1207 | #define DEPEVT_STREAMEVT_FOUND 1 | 1214 | #define DEPEVT_STREAMEVT_FOUND 1 |
diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h index bfb90c52d8fc..c66d216dcc30 100644 --- a/drivers/usb/dwc3/debug.h +++ b/drivers/usb/dwc3/debug.h | |||
@@ -475,21 +475,37 @@ dwc3_ep_event_string(char *str, const struct dwc3_event_depevt *event, | |||
475 | if (ret < 0) | 475 | if (ret < 0) |
476 | return "UNKNOWN"; | 476 | return "UNKNOWN"; |
477 | 477 | ||
478 | status = event->status; | ||
479 | |||
478 | switch (event->endpoint_event) { | 480 | switch (event->endpoint_event) { |
479 | case DWC3_DEPEVT_XFERCOMPLETE: | 481 | case DWC3_DEPEVT_XFERCOMPLETE: |
480 | strcat(str, "Transfer Complete"); | 482 | len = strlen(str); |
483 | sprintf(str + len, "Transfer Complete (%c%c%c)", | ||
484 | status & DEPEVT_STATUS_SHORT ? 'S' : 's', | ||
485 | status & DEPEVT_STATUS_IOC ? 'I' : 'i', | ||
486 | status & DEPEVT_STATUS_LST ? 'L' : 'l'); | ||
487 | |||
481 | len = strlen(str); | 488 | len = strlen(str); |
482 | 489 | ||
483 | if (epnum <= 1) | 490 | if (epnum <= 1) |
484 | sprintf(str + len, " [%s]", dwc3_ep0_state_string(ep0state)); | 491 | sprintf(str + len, " [%s]", dwc3_ep0_state_string(ep0state)); |
485 | break; | 492 | break; |
486 | case DWC3_DEPEVT_XFERINPROGRESS: | 493 | case DWC3_DEPEVT_XFERINPROGRESS: |
487 | strcat(str, "Transfer In-Progress"); | 494 | len = strlen(str); |
495 | |||
496 | sprintf(str + len, "Transfer In Progress [%d] (%c%c%c)", | ||
497 | event->parameters, | ||
498 | status & DEPEVT_STATUS_SHORT ? 'S' : 's', | ||
499 | status & DEPEVT_STATUS_IOC ? 'I' : 'i', | ||
500 | status & DEPEVT_STATUS_LST ? 'M' : 'm'); | ||
488 | break; | 501 | break; |
489 | case DWC3_DEPEVT_XFERNOTREADY: | 502 | case DWC3_DEPEVT_XFERNOTREADY: |
490 | strcat(str, "Transfer Not Ready"); | 503 | len = strlen(str); |
491 | status = event->status & DEPEVT_STATUS_TRANSFER_ACTIVE; | 504 | |
492 | strcat(str, status ? " (Active)" : " (Not Active)"); | 505 | sprintf(str + len, "Transfer Not Ready [%d]%s", |
506 | event->parameters, | ||
507 | status & DEPEVT_STATUS_TRANSFER_ACTIVE ? | ||
508 | " (Active)" : " (Not Active)"); | ||
493 | 509 | ||
494 | /* Control Endpoints */ | 510 | /* Control Endpoints */ |
495 | if (epnum <= 1) { | 511 | if (epnum <= 1) { |
diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 2f07be1e1f31..df8e73ec3342 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c | |||
@@ -716,9 +716,6 @@ static void dwc3_debugfs_create_endpoint_dir(struct dwc3_ep *dep, | |||
716 | struct dentry *dir; | 716 | struct dentry *dir; |
717 | 717 | ||
718 | dir = debugfs_create_dir(dep->name, parent); | 718 | dir = debugfs_create_dir(dep->name, parent); |
719 | if (IS_ERR_OR_NULL(dir)) | ||
720 | return; | ||
721 | |||
722 | dwc3_debugfs_create_endpoint_files(dep, dir); | 719 | dwc3_debugfs_create_endpoint_files(dep, dir); |
723 | } | 720 | } |
724 | 721 | ||
@@ -740,49 +737,31 @@ static void dwc3_debugfs_create_endpoint_dirs(struct dwc3 *dwc, | |||
740 | void dwc3_debugfs_init(struct dwc3 *dwc) | 737 | void dwc3_debugfs_init(struct dwc3 *dwc) |
741 | { | 738 | { |
742 | struct dentry *root; | 739 | struct dentry *root; |
743 | struct dentry *file; | ||
744 | |||
745 | root = debugfs_create_dir(dev_name(dwc->dev), NULL); | ||
746 | if (IS_ERR_OR_NULL(root)) { | ||
747 | if (!root) | ||
748 | dev_err(dwc->dev, "Can't create debugfs root\n"); | ||
749 | return; | ||
750 | } | ||
751 | dwc->root = root; | ||
752 | 740 | ||
753 | dwc->regset = kzalloc(sizeof(*dwc->regset), GFP_KERNEL); | 741 | dwc->regset = kzalloc(sizeof(*dwc->regset), GFP_KERNEL); |
754 | if (!dwc->regset) { | 742 | if (!dwc->regset) |
755 | debugfs_remove_recursive(root); | ||
756 | return; | 743 | return; |
757 | } | ||
758 | 744 | ||
759 | dwc->regset->regs = dwc3_regs; | 745 | dwc->regset->regs = dwc3_regs; |
760 | dwc->regset->nregs = ARRAY_SIZE(dwc3_regs); | 746 | dwc->regset->nregs = ARRAY_SIZE(dwc3_regs); |
761 | dwc->regset->base = dwc->regs - DWC3_GLOBALS_REGS_START; | 747 | dwc->regset->base = dwc->regs - DWC3_GLOBALS_REGS_START; |
762 | 748 | ||
763 | file = debugfs_create_regset32("regdump", S_IRUGO, root, dwc->regset); | 749 | root = debugfs_create_dir(dev_name(dwc->dev), NULL); |
764 | if (!file) | 750 | dwc->root = root; |
765 | dev_dbg(dwc->dev, "Can't create debugfs regdump\n"); | 751 | |
752 | debugfs_create_regset32("regdump", S_IRUGO, root, dwc->regset); | ||
766 | 753 | ||
767 | if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)) { | 754 | if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)) { |
768 | file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root, | 755 | debugfs_create_file("mode", S_IRUGO | S_IWUSR, root, dwc, |
769 | dwc, &dwc3_mode_fops); | 756 | &dwc3_mode_fops); |
770 | if (!file) | ||
771 | dev_dbg(dwc->dev, "Can't create debugfs mode\n"); | ||
772 | } | 757 | } |
773 | 758 | ||
774 | if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) || | 759 | if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) || |
775 | IS_ENABLED(CONFIG_USB_DWC3_GADGET)) { | 760 | IS_ENABLED(CONFIG_USB_DWC3_GADGET)) { |
776 | file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root, | 761 | debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root, dwc, |
777 | dwc, &dwc3_testmode_fops); | 762 | &dwc3_testmode_fops); |
778 | if (!file) | 763 | debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root, dwc, |
779 | dev_dbg(dwc->dev, "Can't create debugfs testmode\n"); | 764 | &dwc3_link_state_fops); |
780 | |||
781 | file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, | ||
782 | root, dwc, &dwc3_link_state_fops); | ||
783 | if (!file) | ||
784 | dev_dbg(dwc->dev, "Can't create debugfs link_state\n"); | ||
785 | |||
786 | dwc3_debugfs_create_endpoint_dirs(dwc, root); | 765 | dwc3_debugfs_create_endpoint_dirs(dwc, root); |
787 | } | 766 | } |
788 | } | 767 | } |
diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c index 1d8c557e97e0..218371f985ca 100644 --- a/drivers/usb/dwc3/drd.c +++ b/drivers/usb/dwc3/drd.c | |||
@@ -8,6 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/extcon.h> | 10 | #include <linux/extcon.h> |
11 | #include <linux/of_graph.h> | ||
11 | #include <linux/platform_device.h> | 12 | #include <linux/platform_device.h> |
12 | 13 | ||
13 | #include "debug.h" | 14 | #include "debug.h" |
@@ -439,17 +440,38 @@ static int dwc3_drd_notifier(struct notifier_block *nb, | |||
439 | return NOTIFY_DONE; | 440 | return NOTIFY_DONE; |
440 | } | 441 | } |
441 | 442 | ||
443 | static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc) | ||
444 | { | ||
445 | struct device *dev = dwc->dev; | ||
446 | struct device_node *np_phy, *np_conn; | ||
447 | struct extcon_dev *edev; | ||
448 | |||
449 | if (of_property_read_bool(dev->of_node, "extcon")) | ||
450 | return extcon_get_edev_by_phandle(dwc->dev, 0); | ||
451 | |||
452 | np_phy = of_parse_phandle(dev->of_node, "phys", 0); | ||
453 | np_conn = of_graph_get_remote_node(np_phy, -1, -1); | ||
454 | |||
455 | if (np_conn) | ||
456 | edev = extcon_find_edev_by_node(np_conn); | ||
457 | else | ||
458 | edev = NULL; | ||
459 | |||
460 | of_node_put(np_conn); | ||
461 | of_node_put(np_phy); | ||
462 | |||
463 | return edev; | ||
464 | } | ||
465 | |||
442 | int dwc3_drd_init(struct dwc3 *dwc) | 466 | int dwc3_drd_init(struct dwc3 *dwc) |
443 | { | 467 | { |
444 | int ret, irq; | 468 | int ret, irq; |
445 | 469 | ||
446 | if (dwc->dev->of_node && | 470 | dwc->edev = dwc3_get_extcon(dwc); |
447 | of_property_read_bool(dwc->dev->of_node, "extcon")) { | 471 | if (IS_ERR(dwc->edev)) |
448 | dwc->edev = extcon_get_edev_by_phandle(dwc->dev, 0); | 472 | return PTR_ERR(dwc->edev); |
449 | |||
450 | if (IS_ERR(dwc->edev)) | ||
451 | return PTR_ERR(dwc->edev); | ||
452 | 473 | ||
474 | if (dwc->edev) { | ||
453 | dwc->edev_nb.notifier_call = dwc3_drd_notifier; | 475 | dwc->edev_nb.notifier_call = dwc3_drd_notifier; |
454 | ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST, | 476 | ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST, |
455 | &dwc->edev_nb); | 477 | &dwc->edev_nb); |
diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c index cb2ee96fd3e8..6b3ccd542bd7 100644 --- a/drivers/usb/dwc3/dwc3-of-simple.c +++ b/drivers/usb/dwc3/dwc3-of-simple.c | |||
@@ -208,13 +208,13 @@ static const struct dev_pm_ops dwc3_of_simple_dev_pm_ops = { | |||
208 | }; | 208 | }; |
209 | 209 | ||
210 | static const struct of_device_id of_dwc3_simple_match[] = { | 210 | static const struct of_device_id of_dwc3_simple_match[] = { |
211 | { .compatible = "qcom,dwc3" }, | ||
212 | { .compatible = "rockchip,rk3399-dwc3" }, | 211 | { .compatible = "rockchip,rk3399-dwc3" }, |
213 | { .compatible = "xlnx,zynqmp-dwc3" }, | 212 | { .compatible = "xlnx,zynqmp-dwc3" }, |
214 | { .compatible = "cavium,octeon-7130-usb-uctl" }, | 213 | { .compatible = "cavium,octeon-7130-usb-uctl" }, |
215 | { .compatible = "sprd,sc9860-dwc3" }, | 214 | { .compatible = "sprd,sc9860-dwc3" }, |
216 | { .compatible = "amlogic,meson-axg-dwc3" }, | 215 | { .compatible = "amlogic,meson-axg-dwc3" }, |
217 | { .compatible = "amlogic,meson-gxl-dwc3" }, | 216 | { .compatible = "amlogic,meson-gxl-dwc3" }, |
217 | { .compatible = "allwinner,sun50i-h6-dwc3" }, | ||
218 | { /* Sentinel */ } | 218 | { /* Sentinel */ } |
219 | }; | 219 | }; |
220 | MODULE_DEVICE_TABLE(of, of_dwc3_simple_match); | 220 | MODULE_DEVICE_TABLE(of, of_dwc3_simple_match); |
diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c new file mode 100644 index 000000000000..b0e67ab2f98c --- /dev/null +++ b/drivers/usb/dwc3/dwc3-qcom.c | |||
@@ -0,0 +1,619 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
3 | * | ||
4 | * Inspired by dwc3-of-simple.c | ||
5 | */ | ||
6 | |||
7 | #include <linux/io.h> | ||
8 | #include <linux/of.h> | ||
9 | #include <linux/clk.h> | ||
10 | #include <linux/irq.h> | ||
11 | #include <linux/clk-provider.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/extcon.h> | ||
15 | #include <linux/of_platform.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/phy/phy.h> | ||
18 | #include <linux/usb/of.h> | ||
19 | #include <linux/reset.h> | ||
20 | #include <linux/iopoll.h> | ||
21 | |||
22 | #include "core.h" | ||
23 | |||
24 | /* USB QSCRATCH Hardware registers */ | ||
25 | #define QSCRATCH_HS_PHY_CTRL 0x10 | ||
26 | #define UTMI_OTG_VBUS_VALID BIT(20) | ||
27 | #define SW_SESSVLD_SEL BIT(28) | ||
28 | |||
29 | #define QSCRATCH_SS_PHY_CTRL 0x30 | ||
30 | #define LANE0_PWR_PRESENT BIT(24) | ||
31 | |||
32 | #define QSCRATCH_GENERAL_CFG 0x08 | ||
33 | #define PIPE_UTMI_CLK_SEL BIT(0) | ||
34 | #define PIPE3_PHYSTATUS_SW BIT(3) | ||
35 | #define PIPE_UTMI_CLK_DIS BIT(8) | ||
36 | |||
37 | #define PWR_EVNT_IRQ_STAT_REG 0x58 | ||
38 | #define PWR_EVNT_LPM_IN_L2_MASK BIT(4) | ||
39 | #define PWR_EVNT_LPM_OUT_L2_MASK BIT(5) | ||
40 | |||
41 | struct dwc3_qcom { | ||
42 | struct device *dev; | ||
43 | void __iomem *qscratch_base; | ||
44 | struct platform_device *dwc3; | ||
45 | struct clk **clks; | ||
46 | int num_clocks; | ||
47 | struct reset_control *resets; | ||
48 | |||
49 | int hs_phy_irq; | ||
50 | int dp_hs_phy_irq; | ||
51 | int dm_hs_phy_irq; | ||
52 | int ss_phy_irq; | ||
53 | |||
54 | struct extcon_dev *edev; | ||
55 | struct extcon_dev *host_edev; | ||
56 | struct notifier_block vbus_nb; | ||
57 | struct notifier_block host_nb; | ||
58 | |||
59 | enum usb_dr_mode mode; | ||
60 | bool is_suspended; | ||
61 | bool pm_suspended; | ||
62 | }; | ||
63 | |||
64 | static inline void dwc3_qcom_setbits(void __iomem *base, u32 offset, u32 val) | ||
65 | { | ||
66 | u32 reg; | ||
67 | |||
68 | reg = readl(base + offset); | ||
69 | reg |= val; | ||
70 | writel(reg, base + offset); | ||
71 | |||
72 | /* ensure that above write is through */ | ||
73 | readl(base + offset); | ||
74 | } | ||
75 | |||
76 | static inline void dwc3_qcom_clrbits(void __iomem *base, u32 offset, u32 val) | ||
77 | { | ||
78 | u32 reg; | ||
79 | |||
80 | reg = readl(base + offset); | ||
81 | reg &= ~val; | ||
82 | writel(reg, base + offset); | ||
83 | |||
84 | /* ensure that above write is through */ | ||
85 | readl(base + offset); | ||
86 | } | ||
87 | |||
88 | static void dwc3_qcom_vbus_overrride_enable(struct dwc3_qcom *qcom, bool enable) | ||
89 | { | ||
90 | if (enable) { | ||
91 | dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_SS_PHY_CTRL, | ||
92 | LANE0_PWR_PRESENT); | ||
93 | dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_HS_PHY_CTRL, | ||
94 | UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL); | ||
95 | } else { | ||
96 | dwc3_qcom_clrbits(qcom->qscratch_base, QSCRATCH_SS_PHY_CTRL, | ||
97 | LANE0_PWR_PRESENT); | ||
98 | dwc3_qcom_clrbits(qcom->qscratch_base, QSCRATCH_HS_PHY_CTRL, | ||
99 | UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL); | ||
100 | } | ||
101 | } | ||
102 | |||
103 | static int dwc3_qcom_vbus_notifier(struct notifier_block *nb, | ||
104 | unsigned long event, void *ptr) | ||
105 | { | ||
106 | struct dwc3_qcom *qcom = container_of(nb, struct dwc3_qcom, vbus_nb); | ||
107 | |||
108 | /* enable vbus override for device mode */ | ||
109 | dwc3_qcom_vbus_overrride_enable(qcom, event); | ||
110 | qcom->mode = event ? USB_DR_MODE_PERIPHERAL : USB_DR_MODE_HOST; | ||
111 | |||
112 | return NOTIFY_DONE; | ||
113 | } | ||
114 | |||
115 | static int dwc3_qcom_host_notifier(struct notifier_block *nb, | ||
116 | unsigned long event, void *ptr) | ||
117 | { | ||
118 | struct dwc3_qcom *qcom = container_of(nb, struct dwc3_qcom, host_nb); | ||
119 | |||
120 | /* disable vbus override in host mode */ | ||
121 | dwc3_qcom_vbus_overrride_enable(qcom, !event); | ||
122 | qcom->mode = event ? USB_DR_MODE_HOST : USB_DR_MODE_PERIPHERAL; | ||
123 | |||
124 | return NOTIFY_DONE; | ||
125 | } | ||
126 | |||
127 | static int dwc3_qcom_register_extcon(struct dwc3_qcom *qcom) | ||
128 | { | ||
129 | struct device *dev = qcom->dev; | ||
130 | struct extcon_dev *host_edev; | ||
131 | int ret; | ||
132 | |||
133 | if (!of_property_read_bool(dev->of_node, "extcon")) | ||
134 | return 0; | ||
135 | |||
136 | qcom->edev = extcon_get_edev_by_phandle(dev, 0); | ||
137 | if (IS_ERR(qcom->edev)) | ||
138 | return PTR_ERR(qcom->edev); | ||
139 | |||
140 | qcom->vbus_nb.notifier_call = dwc3_qcom_vbus_notifier; | ||
141 | |||
142 | qcom->host_edev = extcon_get_edev_by_phandle(dev, 1); | ||
143 | if (IS_ERR(qcom->host_edev)) | ||
144 | qcom->host_edev = NULL; | ||
145 | |||
146 | ret = devm_extcon_register_notifier(dev, qcom->edev, EXTCON_USB, | ||
147 | &qcom->vbus_nb); | ||
148 | if (ret < 0) { | ||
149 | dev_err(dev, "VBUS notifier register failed\n"); | ||
150 | return ret; | ||
151 | } | ||
152 | |||
153 | if (qcom->host_edev) | ||
154 | host_edev = qcom->host_edev; | ||
155 | else | ||
156 | host_edev = qcom->edev; | ||
157 | |||
158 | qcom->host_nb.notifier_call = dwc3_qcom_host_notifier; | ||
159 | ret = devm_extcon_register_notifier(dev, host_edev, EXTCON_USB_HOST, | ||
160 | &qcom->host_nb); | ||
161 | if (ret < 0) { | ||
162 | dev_err(dev, "Host notifier register failed\n"); | ||
163 | return ret; | ||
164 | } | ||
165 | |||
166 | /* Update initial VBUS override based on extcon state */ | ||
167 | if (extcon_get_state(qcom->edev, EXTCON_USB) || | ||
168 | !extcon_get_state(host_edev, EXTCON_USB_HOST)) | ||
169 | dwc3_qcom_vbus_notifier(&qcom->vbus_nb, true, qcom->edev); | ||
170 | else | ||
171 | dwc3_qcom_vbus_notifier(&qcom->vbus_nb, false, qcom->edev); | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static void dwc3_qcom_disable_interrupts(struct dwc3_qcom *qcom) | ||
177 | { | ||
178 | if (qcom->hs_phy_irq) { | ||
179 | disable_irq_wake(qcom->hs_phy_irq); | ||
180 | disable_irq_nosync(qcom->hs_phy_irq); | ||
181 | } | ||
182 | |||
183 | if (qcom->dp_hs_phy_irq) { | ||
184 | disable_irq_wake(qcom->dp_hs_phy_irq); | ||
185 | disable_irq_nosync(qcom->dp_hs_phy_irq); | ||
186 | } | ||
187 | |||
188 | if (qcom->dm_hs_phy_irq) { | ||
189 | disable_irq_wake(qcom->dm_hs_phy_irq); | ||
190 | disable_irq_nosync(qcom->dm_hs_phy_irq); | ||
191 | } | ||
192 | |||
193 | if (qcom->ss_phy_irq) { | ||
194 | disable_irq_wake(qcom->ss_phy_irq); | ||
195 | disable_irq_nosync(qcom->ss_phy_irq); | ||
196 | } | ||
197 | } | ||
198 | |||
199 | static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom) | ||
200 | { | ||
201 | if (qcom->hs_phy_irq) { | ||
202 | enable_irq(qcom->hs_phy_irq); | ||
203 | enable_irq_wake(qcom->hs_phy_irq); | ||
204 | } | ||
205 | |||
206 | if (qcom->dp_hs_phy_irq) { | ||
207 | enable_irq(qcom->dp_hs_phy_irq); | ||
208 | enable_irq_wake(qcom->dp_hs_phy_irq); | ||
209 | } | ||
210 | |||
211 | if (qcom->dm_hs_phy_irq) { | ||
212 | enable_irq(qcom->dm_hs_phy_irq); | ||
213 | enable_irq_wake(qcom->dm_hs_phy_irq); | ||
214 | } | ||
215 | |||
216 | if (qcom->ss_phy_irq) { | ||
217 | enable_irq(qcom->ss_phy_irq); | ||
218 | enable_irq_wake(qcom->ss_phy_irq); | ||
219 | } | ||
220 | } | ||
221 | |||
222 | static int dwc3_qcom_suspend(struct dwc3_qcom *qcom) | ||
223 | { | ||
224 | u32 val; | ||
225 | int i; | ||
226 | |||
227 | if (qcom->is_suspended) | ||
228 | return 0; | ||
229 | |||
230 | val = readl(qcom->qscratch_base + PWR_EVNT_IRQ_STAT_REG); | ||
231 | if (!(val & PWR_EVNT_LPM_IN_L2_MASK)) | ||
232 | dev_err(qcom->dev, "HS-PHY not in L2\n"); | ||
233 | |||
234 | for (i = qcom->num_clocks - 1; i >= 0; i--) | ||
235 | clk_disable_unprepare(qcom->clks[i]); | ||
236 | |||
237 | qcom->is_suspended = true; | ||
238 | dwc3_qcom_enable_interrupts(qcom); | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static int dwc3_qcom_resume(struct dwc3_qcom *qcom) | ||
244 | { | ||
245 | int ret; | ||
246 | int i; | ||
247 | |||
248 | if (!qcom->is_suspended) | ||
249 | return 0; | ||
250 | |||
251 | dwc3_qcom_disable_interrupts(qcom); | ||
252 | |||
253 | for (i = 0; i < qcom->num_clocks; i++) { | ||
254 | ret = clk_prepare_enable(qcom->clks[i]); | ||
255 | if (ret < 0) { | ||
256 | while (--i >= 0) | ||
257 | clk_disable_unprepare(qcom->clks[i]); | ||
258 | return ret; | ||
259 | } | ||
260 | } | ||
261 | |||
262 | /* Clear existing events from PHY related to L2 in/out */ | ||
263 | dwc3_qcom_setbits(qcom->qscratch_base, PWR_EVNT_IRQ_STAT_REG, | ||
264 | PWR_EVNT_LPM_IN_L2_MASK | PWR_EVNT_LPM_OUT_L2_MASK); | ||
265 | |||
266 | qcom->is_suspended = false; | ||
267 | |||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | static irqreturn_t qcom_dwc3_resume_irq(int irq, void *data) | ||
272 | { | ||
273 | struct dwc3_qcom *qcom = data; | ||
274 | struct dwc3 *dwc = platform_get_drvdata(qcom->dwc3); | ||
275 | |||
276 | /* If pm_suspended then let pm_resume take care of resuming h/w */ | ||
277 | if (qcom->pm_suspended) | ||
278 | return IRQ_HANDLED; | ||
279 | |||
280 | if (dwc->xhci) | ||
281 | pm_runtime_resume(&dwc->xhci->dev); | ||
282 | |||
283 | return IRQ_HANDLED; | ||
284 | } | ||
285 | |||
286 | static void dwc3_qcom_select_utmi_clk(struct dwc3_qcom *qcom) | ||
287 | { | ||
288 | /* Configure dwc3 to use UTMI clock as PIPE clock not present */ | ||
289 | dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG, | ||
290 | PIPE_UTMI_CLK_DIS); | ||
291 | |||
292 | usleep_range(100, 1000); | ||
293 | |||
294 | dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG, | ||
295 | PIPE_UTMI_CLK_SEL | PIPE3_PHYSTATUS_SW); | ||
296 | |||
297 | usleep_range(100, 1000); | ||
298 | |||
299 | dwc3_qcom_clrbits(qcom->qscratch_base, QSCRATCH_GENERAL_CFG, | ||
300 | PIPE_UTMI_CLK_DIS); | ||
301 | } | ||
302 | |||
303 | static int dwc3_qcom_setup_irq(struct platform_device *pdev) | ||
304 | { | ||
305 | struct dwc3_qcom *qcom = platform_get_drvdata(pdev); | ||
306 | int irq, ret; | ||
307 | |||
308 | irq = platform_get_irq_byname(pdev, "hs_phy_irq"); | ||
309 | if (irq > 0) { | ||
310 | /* Keep wakeup interrupts disabled until suspend */ | ||
311 | irq_set_status_flags(irq, IRQ_NOAUTOEN); | ||
312 | ret = devm_request_threaded_irq(qcom->dev, irq, NULL, | ||
313 | qcom_dwc3_resume_irq, | ||
314 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, | ||
315 | "qcom_dwc3 HS", qcom); | ||
316 | if (ret) { | ||
317 | dev_err(qcom->dev, "hs_phy_irq failed: %d\n", ret); | ||
318 | return ret; | ||
319 | } | ||
320 | qcom->hs_phy_irq = irq; | ||
321 | } | ||
322 | |||
323 | irq = platform_get_irq_byname(pdev, "dp_hs_phy_irq"); | ||
324 | if (irq > 0) { | ||
325 | irq_set_status_flags(irq, IRQ_NOAUTOEN); | ||
326 | ret = devm_request_threaded_irq(qcom->dev, irq, NULL, | ||
327 | qcom_dwc3_resume_irq, | ||
328 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, | ||
329 | "qcom_dwc3 DP_HS", qcom); | ||
330 | if (ret) { | ||
331 | dev_err(qcom->dev, "dp_hs_phy_irq failed: %d\n", ret); | ||
332 | return ret; | ||
333 | } | ||
334 | qcom->dp_hs_phy_irq = irq; | ||
335 | } | ||
336 | |||
337 | irq = platform_get_irq_byname(pdev, "dm_hs_phy_irq"); | ||
338 | if (irq > 0) { | ||
339 | irq_set_status_flags(irq, IRQ_NOAUTOEN); | ||
340 | ret = devm_request_threaded_irq(qcom->dev, irq, NULL, | ||
341 | qcom_dwc3_resume_irq, | ||
342 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, | ||
343 | "qcom_dwc3 DM_HS", qcom); | ||
344 | if (ret) { | ||
345 | dev_err(qcom->dev, "dm_hs_phy_irq failed: %d\n", ret); | ||
346 | return ret; | ||
347 | } | ||
348 | qcom->dm_hs_phy_irq = irq; | ||
349 | } | ||
350 | |||
351 | irq = platform_get_irq_byname(pdev, "ss_phy_irq"); | ||
352 | if (irq > 0) { | ||
353 | irq_set_status_flags(irq, IRQ_NOAUTOEN); | ||
354 | ret = devm_request_threaded_irq(qcom->dev, irq, NULL, | ||
355 | qcom_dwc3_resume_irq, | ||
356 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, | ||
357 | "qcom_dwc3 SS", qcom); | ||
358 | if (ret) { | ||
359 | dev_err(qcom->dev, "ss_phy_irq failed: %d\n", ret); | ||
360 | return ret; | ||
361 | } | ||
362 | qcom->ss_phy_irq = irq; | ||
363 | } | ||
364 | |||
365 | return 0; | ||
366 | } | ||
367 | |||
368 | static int dwc3_qcom_clk_init(struct dwc3_qcom *qcom, int count) | ||
369 | { | ||
370 | struct device *dev = qcom->dev; | ||
371 | struct device_node *np = dev->of_node; | ||
372 | int i; | ||
373 | |||
374 | qcom->num_clocks = count; | ||
375 | |||
376 | if (!count) | ||
377 | return 0; | ||
378 | |||
379 | qcom->clks = devm_kcalloc(dev, qcom->num_clocks, | ||
380 | sizeof(struct clk *), GFP_KERNEL); | ||
381 | if (!qcom->clks) | ||
382 | return -ENOMEM; | ||
383 | |||
384 | for (i = 0; i < qcom->num_clocks; i++) { | ||
385 | struct clk *clk; | ||
386 | int ret; | ||
387 | |||
388 | clk = of_clk_get(np, i); | ||
389 | if (IS_ERR(clk)) { | ||
390 | while (--i >= 0) | ||
391 | clk_put(qcom->clks[i]); | ||
392 | return PTR_ERR(clk); | ||
393 | } | ||
394 | |||
395 | ret = clk_prepare_enable(clk); | ||
396 | if (ret < 0) { | ||
397 | while (--i >= 0) { | ||
398 | clk_disable_unprepare(qcom->clks[i]); | ||
399 | clk_put(qcom->clks[i]); | ||
400 | } | ||
401 | clk_put(clk); | ||
402 | |||
403 | return ret; | ||
404 | } | ||
405 | |||
406 | qcom->clks[i] = clk; | ||
407 | } | ||
408 | |||
409 | return 0; | ||
410 | } | ||
411 | |||
412 | static int dwc3_qcom_probe(struct platform_device *pdev) | ||
413 | { | ||
414 | struct device_node *np = pdev->dev.of_node, *dwc3_np; | ||
415 | struct device *dev = &pdev->dev; | ||
416 | struct dwc3_qcom *qcom; | ||
417 | struct resource *res; | ||
418 | int ret, i; | ||
419 | bool ignore_pipe_clk; | ||
420 | |||
421 | qcom = devm_kzalloc(&pdev->dev, sizeof(*qcom), GFP_KERNEL); | ||
422 | if (!qcom) | ||
423 | return -ENOMEM; | ||
424 | |||
425 | platform_set_drvdata(pdev, qcom); | ||
426 | qcom->dev = &pdev->dev; | ||
427 | |||
428 | qcom->resets = devm_reset_control_array_get_optional_exclusive(dev); | ||
429 | if (IS_ERR(qcom->resets)) { | ||
430 | ret = PTR_ERR(qcom->resets); | ||
431 | dev_err(&pdev->dev, "failed to get resets, err=%d\n", ret); | ||
432 | return ret; | ||
433 | } | ||
434 | |||
435 | ret = reset_control_assert(qcom->resets); | ||
436 | if (ret) { | ||
437 | dev_err(&pdev->dev, "failed to assert resets, err=%d\n", ret); | ||
438 | return ret; | ||
439 | } | ||
440 | |||
441 | usleep_range(10, 1000); | ||
442 | |||
443 | ret = reset_control_deassert(qcom->resets); | ||
444 | if (ret) { | ||
445 | dev_err(&pdev->dev, "failed to deassert resets, err=%d\n", ret); | ||
446 | goto reset_assert; | ||
447 | } | ||
448 | |||
449 | ret = dwc3_qcom_clk_init(qcom, of_count_phandle_with_args(np, | ||
450 | "clocks", "#clock-cells")); | ||
451 | if (ret) { | ||
452 | dev_err(dev, "failed to get clocks\n"); | ||
453 | goto reset_assert; | ||
454 | } | ||
455 | |||
456 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
457 | qcom->qscratch_base = devm_ioremap_resource(dev, res); | ||
458 | if (IS_ERR(qcom->qscratch_base)) { | ||
459 | dev_err(dev, "failed to map qscratch, err=%d\n", ret); | ||
460 | ret = PTR_ERR(qcom->qscratch_base); | ||
461 | goto clk_disable; | ||
462 | } | ||
463 | |||
464 | ret = dwc3_qcom_setup_irq(pdev); | ||
465 | if (ret) | ||
466 | goto clk_disable; | ||
467 | |||
468 | dwc3_np = of_get_child_by_name(np, "dwc3"); | ||
469 | if (!dwc3_np) { | ||
470 | dev_err(dev, "failed to find dwc3 core child\n"); | ||
471 | ret = -ENODEV; | ||
472 | goto clk_disable; | ||
473 | } | ||
474 | |||
475 | /* | ||
476 | * Disable pipe_clk requirement if specified. Used when dwc3 | ||
477 | * operates without SSPHY and only HS/FS/LS modes are supported. | ||
478 | */ | ||
479 | ignore_pipe_clk = device_property_read_bool(dev, | ||
480 | "qcom,select-utmi-as-pipe-clk"); | ||
481 | if (ignore_pipe_clk) | ||
482 | dwc3_qcom_select_utmi_clk(qcom); | ||
483 | |||
484 | ret = of_platform_populate(np, NULL, NULL, dev); | ||
485 | if (ret) { | ||
486 | dev_err(dev, "failed to register dwc3 core - %d\n", ret); | ||
487 | goto clk_disable; | ||
488 | } | ||
489 | |||
490 | qcom->dwc3 = of_find_device_by_node(dwc3_np); | ||
491 | if (!qcom->dwc3) { | ||
492 | dev_err(&pdev->dev, "failed to get dwc3 platform device\n"); | ||
493 | goto depopulate; | ||
494 | } | ||
495 | |||
496 | qcom->mode = usb_get_dr_mode(&qcom->dwc3->dev); | ||
497 | |||
498 | /* enable vbus override for device mode */ | ||
499 | if (qcom->mode == USB_DR_MODE_PERIPHERAL) | ||
500 | dwc3_qcom_vbus_overrride_enable(qcom, true); | ||
501 | |||
502 | /* register extcon to override sw_vbus on Vbus change later */ | ||
503 | ret = dwc3_qcom_register_extcon(qcom); | ||
504 | if (ret) | ||
505 | goto depopulate; | ||
506 | |||
507 | device_init_wakeup(&pdev->dev, 1); | ||
508 | qcom->is_suspended = false; | ||
509 | pm_runtime_set_active(dev); | ||
510 | pm_runtime_enable(dev); | ||
511 | pm_runtime_forbid(dev); | ||
512 | |||
513 | return 0; | ||
514 | |||
515 | depopulate: | ||
516 | of_platform_depopulate(&pdev->dev); | ||
517 | clk_disable: | ||
518 | for (i = qcom->num_clocks - 1; i >= 0; i--) { | ||
519 | clk_disable_unprepare(qcom->clks[i]); | ||
520 | clk_put(qcom->clks[i]); | ||
521 | } | ||
522 | reset_assert: | ||
523 | reset_control_assert(qcom->resets); | ||
524 | |||
525 | return ret; | ||
526 | } | ||
527 | |||
528 | static int dwc3_qcom_remove(struct platform_device *pdev) | ||
529 | { | ||
530 | struct dwc3_qcom *qcom = platform_get_drvdata(pdev); | ||
531 | struct device *dev = &pdev->dev; | ||
532 | int i; | ||
533 | |||
534 | of_platform_depopulate(dev); | ||
535 | |||
536 | for (i = qcom->num_clocks - 1; i >= 0; i--) { | ||
537 | clk_disable_unprepare(qcom->clks[i]); | ||
538 | clk_put(qcom->clks[i]); | ||
539 | } | ||
540 | qcom->num_clocks = 0; | ||
541 | |||
542 | reset_control_assert(qcom->resets); | ||
543 | |||
544 | pm_runtime_allow(dev); | ||
545 | pm_runtime_disable(dev); | ||
546 | |||
547 | return 0; | ||
548 | } | ||
549 | |||
550 | #ifdef CONFIG_PM_SLEEP | ||
551 | static int dwc3_qcom_pm_suspend(struct device *dev) | ||
552 | { | ||
553 | struct dwc3_qcom *qcom = dev_get_drvdata(dev); | ||
554 | int ret = 0; | ||
555 | |||
556 | ret = dwc3_qcom_suspend(qcom); | ||
557 | if (!ret) | ||
558 | qcom->pm_suspended = true; | ||
559 | |||
560 | return ret; | ||
561 | } | ||
562 | |||
563 | static int dwc3_qcom_pm_resume(struct device *dev) | ||
564 | { | ||
565 | struct dwc3_qcom *qcom = dev_get_drvdata(dev); | ||
566 | int ret; | ||
567 | |||
568 | ret = dwc3_qcom_resume(qcom); | ||
569 | if (!ret) | ||
570 | qcom->pm_suspended = false; | ||
571 | |||
572 | return ret; | ||
573 | } | ||
574 | #endif | ||
575 | |||
576 | #ifdef CONFIG_PM | ||
577 | static int dwc3_qcom_runtime_suspend(struct device *dev) | ||
578 | { | ||
579 | struct dwc3_qcom *qcom = dev_get_drvdata(dev); | ||
580 | |||
581 | return dwc3_qcom_suspend(qcom); | ||
582 | } | ||
583 | |||
584 | static int dwc3_qcom_runtime_resume(struct device *dev) | ||
585 | { | ||
586 | struct dwc3_qcom *qcom = dev_get_drvdata(dev); | ||
587 | |||
588 | return dwc3_qcom_resume(qcom); | ||
589 | } | ||
590 | #endif | ||
591 | |||
592 | static const struct dev_pm_ops dwc3_qcom_dev_pm_ops = { | ||
593 | SET_SYSTEM_SLEEP_PM_OPS(dwc3_qcom_pm_suspend, dwc3_qcom_pm_resume) | ||
594 | SET_RUNTIME_PM_OPS(dwc3_qcom_runtime_suspend, dwc3_qcom_runtime_resume, | ||
595 | NULL) | ||
596 | }; | ||
597 | |||
598 | static const struct of_device_id dwc3_qcom_of_match[] = { | ||
599 | { .compatible = "qcom,dwc3" }, | ||
600 | { .compatible = "qcom,msm8996-dwc3" }, | ||
601 | { .compatible = "qcom,sdm845-dwc3" }, | ||
602 | { } | ||
603 | }; | ||
604 | MODULE_DEVICE_TABLE(of, dwc3_qcom_of_match); | ||
605 | |||
606 | static struct platform_driver dwc3_qcom_driver = { | ||
607 | .probe = dwc3_qcom_probe, | ||
608 | .remove = dwc3_qcom_remove, | ||
609 | .driver = { | ||
610 | .name = "dwc3-qcom", | ||
611 | .pm = &dwc3_qcom_dev_pm_ops, | ||
612 | .of_match_table = dwc3_qcom_of_match, | ||
613 | }, | ||
614 | }; | ||
615 | |||
616 | module_platform_driver(dwc3_qcom_driver); | ||
617 | |||
618 | MODULE_LICENSE("GPL v2"); | ||
619 | MODULE_DESCRIPTION("DesignWare DWC3 QCOM Glue Driver"); | ||
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 5a991bca8ed7..c77ff50a88a2 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c | |||
@@ -66,7 +66,7 @@ static int dwc3_ep0_start_trans(struct dwc3_ep *dep) | |||
66 | struct dwc3 *dwc; | 66 | struct dwc3 *dwc; |
67 | int ret; | 67 | int ret; |
68 | 68 | ||
69 | if (dep->flags & DWC3_EP_BUSY) | 69 | if (dep->flags & DWC3_EP_TRANSFER_STARTED) |
70 | return 0; | 70 | return 0; |
71 | 71 | ||
72 | dwc = dep->dwc; | 72 | dwc = dep->dwc; |
@@ -79,8 +79,6 @@ static int dwc3_ep0_start_trans(struct dwc3_ep *dep) | |||
79 | if (ret < 0) | 79 | if (ret < 0) |
80 | return ret; | 80 | return ret; |
81 | 81 | ||
82 | dep->flags |= DWC3_EP_BUSY; | ||
83 | dep->resource_index = dwc3_gadget_ep_get_transfer_index(dep); | ||
84 | dwc->ep0_next_event = DWC3_EP0_COMPLETE; | 82 | dwc->ep0_next_event = DWC3_EP0_COMPLETE; |
85 | 83 | ||
86 | return 0; | 84 | return 0; |
@@ -913,7 +911,7 @@ static void dwc3_ep0_xfer_complete(struct dwc3 *dwc, | |||
913 | { | 911 | { |
914 | struct dwc3_ep *dep = dwc->eps[event->endpoint_number]; | 912 | struct dwc3_ep *dep = dwc->eps[event->endpoint_number]; |
915 | 913 | ||
916 | dep->flags &= ~DWC3_EP_BUSY; | 914 | dep->flags &= ~DWC3_EP_TRANSFER_STARTED; |
917 | dep->resource_index = 0; | 915 | dep->resource_index = 0; |
918 | dwc->setup_packet_pending = false; | 916 | dwc->setup_packet_pending = false; |
919 | 917 | ||
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 0dedf8a799f4..69bf137aab37 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c | |||
@@ -27,6 +27,9 @@ | |||
27 | #include "gadget.h" | 27 | #include "gadget.h" |
28 | #include "io.h" | 28 | #include "io.h" |
29 | 29 | ||
30 | #define DWC3_ALIGN_FRAME(d) (((d)->frame_number + (d)->interval) \ | ||
31 | & ~((d)->interval - 1)) | ||
32 | |||
30 | /** | 33 | /** |
31 | * dwc3_gadget_set_test_mode - enables usb2 test modes | 34 | * dwc3_gadget_set_test_mode - enables usb2 test modes |
32 | * @dwc: pointer to our context structure | 35 | * @dwc: pointer to our context structure |
@@ -375,6 +378,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd, | |||
375 | switch (DWC3_DEPCMD_CMD(cmd)) { | 378 | switch (DWC3_DEPCMD_CMD(cmd)) { |
376 | case DWC3_DEPCMD_STARTTRANSFER: | 379 | case DWC3_DEPCMD_STARTTRANSFER: |
377 | dep->flags |= DWC3_EP_TRANSFER_STARTED; | 380 | dep->flags |= DWC3_EP_TRANSFER_STARTED; |
381 | dwc3_gadget_ep_get_transfer_index(dep); | ||
378 | break; | 382 | break; |
379 | case DWC3_DEPCMD_ENDTRANSFER: | 383 | case DWC3_DEPCMD_ENDTRANSFER: |
380 | dep->flags &= ~DWC3_EP_TRANSFER_STARTED; | 384 | dep->flags &= ~DWC3_EP_TRANSFER_STARTED; |
@@ -455,7 +459,17 @@ static void dwc3_free_trb_pool(struct dwc3_ep *dep) | |||
455 | dep->trb_pool_dma = 0; | 459 | dep->trb_pool_dma = 0; |
456 | } | 460 | } |
457 | 461 | ||
458 | static int dwc3_gadget_set_xfer_resource(struct dwc3 *dwc, struct dwc3_ep *dep); | 462 | static int dwc3_gadget_set_xfer_resource(struct dwc3_ep *dep) |
463 | { | ||
464 | struct dwc3_gadget_ep_cmd_params params; | ||
465 | |||
466 | memset(¶ms, 0x00, sizeof(params)); | ||
467 | |||
468 | params.param0 = DWC3_DEPXFERCFG_NUM_XFER_RES(1); | ||
469 | |||
470 | return dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETTRANSFRESOURCE, | ||
471 | ¶ms); | ||
472 | } | ||
459 | 473 | ||
460 | /** | 474 | /** |
461 | * dwc3_gadget_start_config - configure ep resources | 475 | * dwc3_gadget_start_config - configure ep resources |
@@ -491,9 +505,10 @@ static int dwc3_gadget_set_xfer_resource(struct dwc3 *dwc, struct dwc3_ep *dep); | |||
491 | * triggered only when called for EP0-out, which always happens first, and which | 505 | * triggered only when called for EP0-out, which always happens first, and which |
492 | * should only happen in one of the above conditions. | 506 | * should only happen in one of the above conditions. |
493 | */ | 507 | */ |
494 | static int dwc3_gadget_start_config(struct dwc3 *dwc, struct dwc3_ep *dep) | 508 | static int dwc3_gadget_start_config(struct dwc3_ep *dep) |
495 | { | 509 | { |
496 | struct dwc3_gadget_ep_cmd_params params; | 510 | struct dwc3_gadget_ep_cmd_params params; |
511 | struct dwc3 *dwc; | ||
497 | u32 cmd; | 512 | u32 cmd; |
498 | int i; | 513 | int i; |
499 | int ret; | 514 | int ret; |
@@ -503,6 +518,7 @@ static int dwc3_gadget_start_config(struct dwc3 *dwc, struct dwc3_ep *dep) | |||
503 | 518 | ||
504 | memset(¶ms, 0x00, sizeof(params)); | 519 | memset(¶ms, 0x00, sizeof(params)); |
505 | cmd = DWC3_DEPCMD_DEPSTARTCFG; | 520 | cmd = DWC3_DEPCMD_DEPSTARTCFG; |
521 | dwc = dep->dwc; | ||
506 | 522 | ||
507 | ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); | 523 | ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); |
508 | if (ret) | 524 | if (ret) |
@@ -514,7 +530,7 @@ static int dwc3_gadget_start_config(struct dwc3 *dwc, struct dwc3_ep *dep) | |||
514 | if (!dep) | 530 | if (!dep) |
515 | continue; | 531 | continue; |
516 | 532 | ||
517 | ret = dwc3_gadget_set_xfer_resource(dwc, dep); | 533 | ret = dwc3_gadget_set_xfer_resource(dep); |
518 | if (ret) | 534 | if (ret) |
519 | return ret; | 535 | return ret; |
520 | } | 536 | } |
@@ -522,16 +538,12 @@ static int dwc3_gadget_start_config(struct dwc3 *dwc, struct dwc3_ep *dep) | |||
522 | return 0; | 538 | return 0; |
523 | } | 539 | } |
524 | 540 | ||
525 | static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep, | 541 | static int dwc3_gadget_set_ep_config(struct dwc3_ep *dep, unsigned int action) |
526 | bool modify, bool restore) | ||
527 | { | 542 | { |
528 | const struct usb_ss_ep_comp_descriptor *comp_desc; | 543 | const struct usb_ss_ep_comp_descriptor *comp_desc; |
529 | const struct usb_endpoint_descriptor *desc; | 544 | const struct usb_endpoint_descriptor *desc; |
530 | struct dwc3_gadget_ep_cmd_params params; | 545 | struct dwc3_gadget_ep_cmd_params params; |
531 | 546 | struct dwc3 *dwc = dep->dwc; | |
532 | if (dev_WARN_ONCE(dwc->dev, modify && restore, | ||
533 | "Can't modify and restore\n")) | ||
534 | return -EINVAL; | ||
535 | 547 | ||
536 | comp_desc = dep->endpoint.comp_desc; | 548 | comp_desc = dep->endpoint.comp_desc; |
537 | desc = dep->endpoint.desc; | 549 | desc = dep->endpoint.desc; |
@@ -547,14 +559,9 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep, | |||
547 | params.param0 |= DWC3_DEPCFG_BURST_SIZE(burst - 1); | 559 | params.param0 |= DWC3_DEPCFG_BURST_SIZE(burst - 1); |
548 | } | 560 | } |
549 | 561 | ||
550 | if (modify) { | 562 | params.param0 |= action; |
551 | params.param0 |= DWC3_DEPCFG_ACTION_MODIFY; | 563 | if (action == DWC3_DEPCFG_ACTION_RESTORE) |
552 | } else if (restore) { | ||
553 | params.param0 |= DWC3_DEPCFG_ACTION_RESTORE; | ||
554 | params.param2 |= dep->saved_state; | 564 | params.param2 |= dep->saved_state; |
555 | } else { | ||
556 | params.param0 |= DWC3_DEPCFG_ACTION_INIT; | ||
557 | } | ||
558 | 565 | ||
559 | if (usb_endpoint_xfer_control(desc)) | 566 | if (usb_endpoint_xfer_control(desc)) |
560 | params.param1 = DWC3_DEPCFG_XFER_COMPLETE_EN; | 567 | params.param1 = DWC3_DEPCFG_XFER_COMPLETE_EN; |
@@ -594,29 +601,15 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep, | |||
594 | return dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETEPCONFIG, ¶ms); | 601 | return dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETEPCONFIG, ¶ms); |
595 | } | 602 | } |
596 | 603 | ||
597 | static int dwc3_gadget_set_xfer_resource(struct dwc3 *dwc, struct dwc3_ep *dep) | ||
598 | { | ||
599 | struct dwc3_gadget_ep_cmd_params params; | ||
600 | |||
601 | memset(¶ms, 0x00, sizeof(params)); | ||
602 | |||
603 | params.param0 = DWC3_DEPXFERCFG_NUM_XFER_RES(1); | ||
604 | |||
605 | return dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETTRANSFRESOURCE, | ||
606 | ¶ms); | ||
607 | } | ||
608 | |||
609 | /** | 604 | /** |
610 | * __dwc3_gadget_ep_enable - initializes a hw endpoint | 605 | * __dwc3_gadget_ep_enable - initializes a hw endpoint |
611 | * @dep: endpoint to be initialized | 606 | * @dep: endpoint to be initialized |
612 | * @modify: if true, modify existing endpoint configuration | 607 | * @action: one of INIT, MODIFY or RESTORE |
613 | * @restore: if true, restore endpoint configuration from scratch buffer | ||
614 | * | 608 | * |
615 | * Caller should take care of locking. Execute all necessary commands to | 609 | * Caller should take care of locking. Execute all necessary commands to |
616 | * initialize a HW endpoint so it can be used by a gadget driver. | 610 | * initialize a HW endpoint so it can be used by a gadget driver. |
617 | */ | 611 | */ |
618 | static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, | 612 | static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action) |
619 | bool modify, bool restore) | ||
620 | { | 613 | { |
621 | const struct usb_endpoint_descriptor *desc = dep->endpoint.desc; | 614 | const struct usb_endpoint_descriptor *desc = dep->endpoint.desc; |
622 | struct dwc3 *dwc = dep->dwc; | 615 | struct dwc3 *dwc = dep->dwc; |
@@ -625,12 +618,12 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, | |||
625 | int ret; | 618 | int ret; |
626 | 619 | ||
627 | if (!(dep->flags & DWC3_EP_ENABLED)) { | 620 | if (!(dep->flags & DWC3_EP_ENABLED)) { |
628 | ret = dwc3_gadget_start_config(dwc, dep); | 621 | ret = dwc3_gadget_start_config(dep); |
629 | if (ret) | 622 | if (ret) |
630 | return ret; | 623 | return ret; |
631 | } | 624 | } |
632 | 625 | ||
633 | ret = dwc3_gadget_set_ep_config(dwc, dep, modify, restore); | 626 | ret = dwc3_gadget_set_ep_config(dep, action); |
634 | if (ret) | 627 | if (ret) |
635 | return ret; | 628 | return ret; |
636 | 629 | ||
@@ -671,7 +664,8 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, | |||
671 | * Issue StartTransfer here with no-op TRB so we can always rely on No | 664 | * Issue StartTransfer here with no-op TRB so we can always rely on No |
672 | * Response Update Transfer command. | 665 | * Response Update Transfer command. |
673 | */ | 666 | */ |
674 | if (usb_endpoint_xfer_bulk(desc)) { | 667 | if (usb_endpoint_xfer_bulk(desc) || |
668 | usb_endpoint_xfer_int(desc)) { | ||
675 | struct dwc3_gadget_ep_cmd_params params; | 669 | struct dwc3_gadget_ep_cmd_params params; |
676 | struct dwc3_trb *trb; | 670 | struct dwc3_trb *trb; |
677 | dma_addr_t trb_dma; | 671 | dma_addr_t trb_dma; |
@@ -689,26 +683,20 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, | |||
689 | ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); | 683 | ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); |
690 | if (ret < 0) | 684 | if (ret < 0) |
691 | return ret; | 685 | return ret; |
692 | |||
693 | dep->flags |= DWC3_EP_BUSY; | ||
694 | |||
695 | dep->resource_index = dwc3_gadget_ep_get_transfer_index(dep); | ||
696 | WARN_ON_ONCE(!dep->resource_index); | ||
697 | } | 686 | } |
698 | 687 | ||
699 | |||
700 | out: | 688 | out: |
701 | trace_dwc3_gadget_ep_enable(dep); | 689 | trace_dwc3_gadget_ep_enable(dep); |
702 | 690 | ||
703 | return 0; | 691 | return 0; |
704 | } | 692 | } |
705 | 693 | ||
706 | static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force); | 694 | static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force); |
707 | static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep) | 695 | static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep) |
708 | { | 696 | { |
709 | struct dwc3_request *req; | 697 | struct dwc3_request *req; |
710 | 698 | ||
711 | dwc3_stop_active_transfer(dwc, dep->number, true); | 699 | dwc3_stop_active_transfer(dep, true); |
712 | 700 | ||
713 | /* - giveback all requests to gadget driver */ | 701 | /* - giveback all requests to gadget driver */ |
714 | while (!list_empty(&dep->started_list)) { | 702 | while (!list_empty(&dep->started_list)) { |
@@ -806,7 +794,7 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep, | |||
806 | return 0; | 794 | return 0; |
807 | 795 | ||
808 | spin_lock_irqsave(&dwc->lock, flags); | 796 | spin_lock_irqsave(&dwc->lock, flags); |
809 | ret = __dwc3_gadget_ep_enable(dep, false, false); | 797 | ret = __dwc3_gadget_ep_enable(dep, DWC3_DEPCFG_ACTION_INIT); |
810 | spin_unlock_irqrestore(&dwc->lock, flags); | 798 | spin_unlock_irqrestore(&dwc->lock, flags); |
811 | 799 | ||
812 | return ret; | 800 | return ret; |
@@ -840,7 +828,7 @@ static int dwc3_gadget_ep_disable(struct usb_ep *ep) | |||
840 | } | 828 | } |
841 | 829 | ||
842 | static struct usb_request *dwc3_gadget_ep_alloc_request(struct usb_ep *ep, | 830 | static struct usb_request *dwc3_gadget_ep_alloc_request(struct usb_ep *ep, |
843 | gfp_t gfp_flags) | 831 | gfp_t gfp_flags) |
844 | { | 832 | { |
845 | struct dwc3_request *req; | 833 | struct dwc3_request *req; |
846 | struct dwc3_ep *dep = to_dwc3_ep(ep); | 834 | struct dwc3_ep *dep = to_dwc3_ep(ep); |
@@ -849,11 +837,10 @@ static struct usb_request *dwc3_gadget_ep_alloc_request(struct usb_ep *ep, | |||
849 | if (!req) | 837 | if (!req) |
850 | return NULL; | 838 | return NULL; |
851 | 839 | ||
840 | req->direction = dep->direction; | ||
852 | req->epnum = dep->number; | 841 | req->epnum = dep->number; |
853 | req->dep = dep; | 842 | req->dep = dep; |
854 | 843 | ||
855 | dep->allocated_requests++; | ||
856 | |||
857 | trace_dwc3_alloc_request(req); | 844 | trace_dwc3_alloc_request(req); |
858 | 845 | ||
859 | return &req->request; | 846 | return &req->request; |
@@ -863,14 +850,58 @@ static void dwc3_gadget_ep_free_request(struct usb_ep *ep, | |||
863 | struct usb_request *request) | 850 | struct usb_request *request) |
864 | { | 851 | { |
865 | struct dwc3_request *req = to_dwc3_request(request); | 852 | struct dwc3_request *req = to_dwc3_request(request); |
866 | struct dwc3_ep *dep = to_dwc3_ep(ep); | ||
867 | 853 | ||
868 | dep->allocated_requests--; | ||
869 | trace_dwc3_free_request(req); | 854 | trace_dwc3_free_request(req); |
870 | kfree(req); | 855 | kfree(req); |
871 | } | 856 | } |
872 | 857 | ||
873 | static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep); | 858 | /** |
859 | * dwc3_ep_prev_trb - returns the previous TRB in the ring | ||
860 | * @dep: The endpoint with the TRB ring | ||
861 | * @index: The index of the current TRB in the ring | ||
862 | * | ||
863 | * Returns the TRB prior to the one pointed to by the index. If the | ||
864 | * index is 0, we will wrap backwards, skip the link TRB, and return | ||
865 | * the one just before that. | ||
866 | */ | ||
867 | static struct dwc3_trb *dwc3_ep_prev_trb(struct dwc3_ep *dep, u8 index) | ||
868 | { | ||
869 | u8 tmp = index; | ||
870 | |||
871 | if (!tmp) | ||
872 | tmp = DWC3_TRB_NUM - 1; | ||
873 | |||
874 | return &dep->trb_pool[tmp - 1]; | ||
875 | } | ||
876 | |||
877 | static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep) | ||
878 | { | ||
879 | struct dwc3_trb *tmp; | ||
880 | u8 trbs_left; | ||
881 | |||
882 | /* | ||
883 | * If enqueue & dequeue are equal than it is either full or empty. | ||
884 | * | ||
885 | * One way to know for sure is if the TRB right before us has HWO bit | ||
886 | * set or not. If it has, then we're definitely full and can't fit any | ||
887 | * more transfers in our ring. | ||
888 | */ | ||
889 | if (dep->trb_enqueue == dep->trb_dequeue) { | ||
890 | tmp = dwc3_ep_prev_trb(dep, dep->trb_enqueue); | ||
891 | if (tmp->ctrl & DWC3_TRB_CTRL_HWO) | ||
892 | return 0; | ||
893 | |||
894 | return DWC3_TRB_NUM - 1; | ||
895 | } | ||
896 | |||
897 | trbs_left = dep->trb_dequeue - dep->trb_enqueue; | ||
898 | trbs_left &= (DWC3_TRB_NUM - 1); | ||
899 | |||
900 | if (dep->trb_dequeue < dep->trb_enqueue) | ||
901 | trbs_left--; | ||
902 | |||
903 | return trbs_left; | ||
904 | } | ||
874 | 905 | ||
875 | static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb, | 906 | static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb, |
876 | dma_addr_t dma, unsigned length, unsigned chain, unsigned node, | 907 | dma_addr_t dma, unsigned length, unsigned chain, unsigned node, |
@@ -985,11 +1016,19 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, | |||
985 | struct dwc3_request *req, unsigned chain, unsigned node) | 1016 | struct dwc3_request *req, unsigned chain, unsigned node) |
986 | { | 1017 | { |
987 | struct dwc3_trb *trb; | 1018 | struct dwc3_trb *trb; |
988 | unsigned length = req->request.length; | 1019 | unsigned int length; |
1020 | dma_addr_t dma; | ||
989 | unsigned stream_id = req->request.stream_id; | 1021 | unsigned stream_id = req->request.stream_id; |
990 | unsigned short_not_ok = req->request.short_not_ok; | 1022 | unsigned short_not_ok = req->request.short_not_ok; |
991 | unsigned no_interrupt = req->request.no_interrupt; | 1023 | unsigned no_interrupt = req->request.no_interrupt; |
992 | dma_addr_t dma = req->request.dma; | 1024 | |
1025 | if (req->request.num_sgs > 0) { | ||
1026 | length = sg_dma_len(req->start_sg); | ||
1027 | dma = sg_dma_address(req->start_sg); | ||
1028 | } else { | ||
1029 | length = req->request.length; | ||
1030 | dma = req->request.dma; | ||
1031 | } | ||
993 | 1032 | ||
994 | trb = &dep->trb_pool[dep->trb_enqueue]; | 1033 | trb = &dep->trb_pool[dep->trb_enqueue]; |
995 | 1034 | ||
@@ -997,69 +1036,23 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, | |||
997 | dwc3_gadget_move_started_request(req); | 1036 | dwc3_gadget_move_started_request(req); |
998 | req->trb = trb; | 1037 | req->trb = trb; |
999 | req->trb_dma = dwc3_trb_dma_offset(dep, trb); | 1038 | req->trb_dma = dwc3_trb_dma_offset(dep, trb); |
1000 | dep->queued_requests++; | ||
1001 | } | 1039 | } |
1002 | 1040 | ||
1003 | __dwc3_prepare_one_trb(dep, trb, dma, length, chain, node, | 1041 | __dwc3_prepare_one_trb(dep, trb, dma, length, chain, node, |
1004 | stream_id, short_not_ok, no_interrupt); | 1042 | stream_id, short_not_ok, no_interrupt); |
1005 | } | 1043 | } |
1006 | 1044 | ||
1007 | /** | ||
1008 | * dwc3_ep_prev_trb - returns the previous TRB in the ring | ||
1009 | * @dep: The endpoint with the TRB ring | ||
1010 | * @index: The index of the current TRB in the ring | ||
1011 | * | ||
1012 | * Returns the TRB prior to the one pointed to by the index. If the | ||
1013 | * index is 0, we will wrap backwards, skip the link TRB, and return | ||
1014 | * the one just before that. | ||
1015 | */ | ||
1016 | static struct dwc3_trb *dwc3_ep_prev_trb(struct dwc3_ep *dep, u8 index) | ||
1017 | { | ||
1018 | u8 tmp = index; | ||
1019 | |||
1020 | if (!tmp) | ||
1021 | tmp = DWC3_TRB_NUM - 1; | ||
1022 | |||
1023 | return &dep->trb_pool[tmp - 1]; | ||
1024 | } | ||
1025 | |||
1026 | static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep) | ||
1027 | { | ||
1028 | struct dwc3_trb *tmp; | ||
1029 | u8 trbs_left; | ||
1030 | |||
1031 | /* | ||
1032 | * If enqueue & dequeue are equal than it is either full or empty. | ||
1033 | * | ||
1034 | * One way to know for sure is if the TRB right before us has HWO bit | ||
1035 | * set or not. If it has, then we're definitely full and can't fit any | ||
1036 | * more transfers in our ring. | ||
1037 | */ | ||
1038 | if (dep->trb_enqueue == dep->trb_dequeue) { | ||
1039 | tmp = dwc3_ep_prev_trb(dep, dep->trb_enqueue); | ||
1040 | if (tmp->ctrl & DWC3_TRB_CTRL_HWO) | ||
1041 | return 0; | ||
1042 | |||
1043 | return DWC3_TRB_NUM - 1; | ||
1044 | } | ||
1045 | |||
1046 | trbs_left = dep->trb_dequeue - dep->trb_enqueue; | ||
1047 | trbs_left &= (DWC3_TRB_NUM - 1); | ||
1048 | |||
1049 | if (dep->trb_dequeue < dep->trb_enqueue) | ||
1050 | trbs_left--; | ||
1051 | |||
1052 | return trbs_left; | ||
1053 | } | ||
1054 | |||
1055 | static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, | 1045 | static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, |
1056 | struct dwc3_request *req) | 1046 | struct dwc3_request *req) |
1057 | { | 1047 | { |
1058 | struct scatterlist *sg = req->sg; | 1048 | struct scatterlist *sg = req->start_sg; |
1059 | struct scatterlist *s; | 1049 | struct scatterlist *s; |
1060 | int i; | 1050 | int i; |
1061 | 1051 | ||
1062 | for_each_sg(sg, s, req->num_pending_sgs, i) { | 1052 | unsigned int remaining = req->request.num_mapped_sgs |
1053 | - req->num_queued_sgs; | ||
1054 | |||
1055 | for_each_sg(sg, s, remaining, i) { | ||
1063 | unsigned int length = req->request.length; | 1056 | unsigned int length = req->request.length; |
1064 | unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); | 1057 | unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); |
1065 | unsigned int rem = length % maxp; | 1058 | unsigned int rem = length % maxp; |
@@ -1088,6 +1081,18 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, | |||
1088 | dwc3_prepare_one_trb(dep, req, chain, i); | 1081 | dwc3_prepare_one_trb(dep, req, chain, i); |
1089 | } | 1082 | } |
1090 | 1083 | ||
1084 | /* | ||
1085 | * There can be a situation where all sgs in sglist are not | ||
1086 | * queued because of insufficient trb number. To handle this | ||
1087 | * case, update start_sg to next sg to be queued, so that | ||
1088 | * we have free trbs we can continue queuing from where we | ||
1089 | * previously stopped | ||
1090 | */ | ||
1091 | if (chain) | ||
1092 | req->start_sg = sg_next(s); | ||
1093 | |||
1094 | req->num_queued_sgs++; | ||
1095 | |||
1091 | if (!dwc3_calc_trbs_left(dep)) | 1096 | if (!dwc3_calc_trbs_left(dep)) |
1092 | break; | 1097 | break; |
1093 | } | 1098 | } |
@@ -1178,6 +1183,8 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep) | |||
1178 | return; | 1183 | return; |
1179 | 1184 | ||
1180 | req->sg = req->request.sg; | 1185 | req->sg = req->request.sg; |
1186 | req->start_sg = req->sg; | ||
1187 | req->num_queued_sgs = 0; | ||
1181 | req->num_pending_sgs = req->request.num_mapped_sgs; | 1188 | req->num_pending_sgs = req->request.num_mapped_sgs; |
1182 | 1189 | ||
1183 | if (req->num_pending_sgs > 0) | 1190 | if (req->num_pending_sgs > 0) |
@@ -1201,7 +1208,7 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep) | |||
1201 | if (!dwc3_calc_trbs_left(dep)) | 1208 | if (!dwc3_calc_trbs_left(dep)) |
1202 | return 0; | 1209 | return 0; |
1203 | 1210 | ||
1204 | starting = !(dep->flags & DWC3_EP_BUSY); | 1211 | starting = !(dep->flags & DWC3_EP_TRANSFER_STARTED); |
1205 | 1212 | ||
1206 | dwc3_prepare_trbs(dep); | 1213 | dwc3_prepare_trbs(dep); |
1207 | req = next_request(&dep->started_list); | 1214 | req = next_request(&dep->started_list); |
@@ -1233,18 +1240,10 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep) | |||
1233 | */ | 1240 | */ |
1234 | if (req->trb) | 1241 | if (req->trb) |
1235 | memset(req->trb, 0, sizeof(struct dwc3_trb)); | 1242 | memset(req->trb, 0, sizeof(struct dwc3_trb)); |
1236 | dep->queued_requests--; | ||
1237 | dwc3_gadget_del_and_unmap_request(dep, req, ret); | 1243 | dwc3_gadget_del_and_unmap_request(dep, req, ret); |
1238 | return ret; | 1244 | return ret; |
1239 | } | 1245 | } |
1240 | 1246 | ||
1241 | dep->flags |= DWC3_EP_BUSY; | ||
1242 | |||
1243 | if (starting) { | ||
1244 | dep->resource_index = dwc3_gadget_ep_get_transfer_index(dep); | ||
1245 | WARN_ON_ONCE(!dep->resource_index); | ||
1246 | } | ||
1247 | |||
1248 | return 0; | 1247 | return 0; |
1249 | } | 1248 | } |
1250 | 1249 | ||
@@ -1256,35 +1255,19 @@ static int __dwc3_gadget_get_frame(struct dwc3 *dwc) | |||
1256 | return DWC3_DSTS_SOFFN(reg); | 1255 | return DWC3_DSTS_SOFFN(reg); |
1257 | } | 1256 | } |
1258 | 1257 | ||
1259 | static void __dwc3_gadget_start_isoc(struct dwc3 *dwc, | 1258 | static void __dwc3_gadget_start_isoc(struct dwc3_ep *dep) |
1260 | struct dwc3_ep *dep, u32 cur_uf) | ||
1261 | { | 1259 | { |
1262 | if (list_empty(&dep->pending_list)) { | 1260 | if (list_empty(&dep->pending_list)) { |
1263 | dev_info(dwc->dev, "%s: ran out of requests\n", | 1261 | dev_info(dep->dwc->dev, "%s: ran out of requests\n", |
1264 | dep->name); | 1262 | dep->name); |
1265 | dep->flags |= DWC3_EP_PENDING_REQUEST; | 1263 | dep->flags |= DWC3_EP_PENDING_REQUEST; |
1266 | return; | 1264 | return; |
1267 | } | 1265 | } |
1268 | 1266 | ||
1269 | /* | 1267 | dep->frame_number = DWC3_ALIGN_FRAME(dep); |
1270 | * Schedule the first trb for one interval in the future or at | ||
1271 | * least 4 microframes. | ||
1272 | */ | ||
1273 | dep->frame_number = cur_uf + max_t(u32, 4, dep->interval); | ||
1274 | __dwc3_gadget_kick_transfer(dep); | 1268 | __dwc3_gadget_kick_transfer(dep); |
1275 | } | 1269 | } |
1276 | 1270 | ||
1277 | static void dwc3_gadget_start_isoc(struct dwc3 *dwc, | ||
1278 | struct dwc3_ep *dep, const struct dwc3_event_depevt *event) | ||
1279 | { | ||
1280 | u32 cur_uf, mask; | ||
1281 | |||
1282 | mask = ~(dep->interval - 1); | ||
1283 | cur_uf = event->parameters & mask; | ||
1284 | |||
1285 | __dwc3_gadget_start_isoc(dwc, dep, cur_uf); | ||
1286 | } | ||
1287 | |||
1288 | static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) | 1271 | static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) |
1289 | { | 1272 | { |
1290 | struct dwc3 *dwc = dep->dwc; | 1273 | struct dwc3 *dwc = dep->dwc; |
@@ -1303,8 +1286,6 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) | |||
1303 | 1286 | ||
1304 | req->request.actual = 0; | 1287 | req->request.actual = 0; |
1305 | req->request.status = -EINPROGRESS; | 1288 | req->request.status = -EINPROGRESS; |
1306 | req->direction = dep->direction; | ||
1307 | req->epnum = dep->number; | ||
1308 | 1289 | ||
1309 | trace_dwc3_ep_queue(req); | 1290 | trace_dwc3_ep_queue(req); |
1310 | 1291 | ||
@@ -1319,28 +1300,18 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) | |||
1319 | * errors which will force us issue EndTransfer command. | 1300 | * errors which will force us issue EndTransfer command. |
1320 | */ | 1301 | */ |
1321 | if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { | 1302 | if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { |
1322 | if ((dep->flags & DWC3_EP_PENDING_REQUEST)) { | 1303 | if (!(dep->flags & DWC3_EP_PENDING_REQUEST) && |
1323 | if (dep->flags & DWC3_EP_TRANSFER_STARTED) { | 1304 | !(dep->flags & DWC3_EP_TRANSFER_STARTED)) |
1324 | dwc3_stop_active_transfer(dwc, dep->number, true); | 1305 | return 0; |
1325 | dep->flags = DWC3_EP_ENABLED; | ||
1326 | } else { | ||
1327 | u32 cur_uf; | ||
1328 | 1306 | ||
1329 | cur_uf = __dwc3_gadget_get_frame(dwc); | 1307 | if ((dep->flags & DWC3_EP_PENDING_REQUEST)) { |
1330 | __dwc3_gadget_start_isoc(dwc, dep, cur_uf); | 1308 | if (!(dep->flags & DWC3_EP_TRANSFER_STARTED)) { |
1331 | dep->flags &= ~DWC3_EP_PENDING_REQUEST; | 1309 | __dwc3_gadget_start_isoc(dep); |
1310 | return 0; | ||
1332 | } | 1311 | } |
1333 | return 0; | ||
1334 | } | 1312 | } |
1335 | |||
1336 | if ((dep->flags & DWC3_EP_BUSY) && | ||
1337 | !(dep->flags & DWC3_EP_MISSED_ISOC)) | ||
1338 | goto out; | ||
1339 | |||
1340 | return 0; | ||
1341 | } | 1313 | } |
1342 | 1314 | ||
1343 | out: | ||
1344 | return __dwc3_gadget_kick_transfer(dep); | 1315 | return __dwc3_gadget_kick_transfer(dep); |
1345 | } | 1316 | } |
1346 | 1317 | ||
@@ -1390,7 +1361,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, | |||
1390 | } | 1361 | } |
1391 | if (r == req) { | 1362 | if (r == req) { |
1392 | /* wait until it is processed */ | 1363 | /* wait until it is processed */ |
1393 | dwc3_stop_active_transfer(dwc, dep->number, true); | 1364 | dwc3_stop_active_transfer(dep, true); |
1394 | 1365 | ||
1395 | /* | 1366 | /* |
1396 | * If request was already started, this means we had to | 1367 | * If request was already started, this means we had to |
@@ -1463,7 +1434,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, | |||
1463 | 1434 | ||
1464 | out1: | 1435 | out1: |
1465 | /* giveback the request */ | 1436 | /* giveback the request */ |
1466 | dep->queued_requests--; | 1437 | |
1467 | dwc3_gadget_giveback(dep, req, -ECONNRESET); | 1438 | dwc3_gadget_giveback(dep, req, -ECONNRESET); |
1468 | 1439 | ||
1469 | out0: | 1440 | out0: |
@@ -1878,14 +1849,14 @@ static int __dwc3_gadget_start(struct dwc3 *dwc) | |||
1878 | dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); | 1849 | dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); |
1879 | 1850 | ||
1880 | dep = dwc->eps[0]; | 1851 | dep = dwc->eps[0]; |
1881 | ret = __dwc3_gadget_ep_enable(dep, false, false); | 1852 | ret = __dwc3_gadget_ep_enable(dep, DWC3_DEPCFG_ACTION_INIT); |
1882 | if (ret) { | 1853 | if (ret) { |
1883 | dev_err(dwc->dev, "failed to enable %s\n", dep->name); | 1854 | dev_err(dwc->dev, "failed to enable %s\n", dep->name); |
1884 | goto err0; | 1855 | goto err0; |
1885 | } | 1856 | } |
1886 | 1857 | ||
1887 | dep = dwc->eps[1]; | 1858 | dep = dwc->eps[1]; |
1888 | ret = __dwc3_gadget_ep_enable(dep, false, false); | 1859 | ret = __dwc3_gadget_ep_enable(dep, DWC3_DEPCFG_ACTION_INIT); |
1889 | if (ret) { | 1860 | if (ret) { |
1890 | dev_err(dwc->dev, "failed to enable %s\n", dep->name); | 1861 | dev_err(dwc->dev, "failed to enable %s\n", dep->name); |
1891 | goto err1; | 1862 | goto err1; |
@@ -2082,113 +2053,142 @@ static const struct usb_gadget_ops dwc3_gadget_ops = { | |||
2082 | 2053 | ||
2083 | /* -------------------------------------------------------------------------- */ | 2054 | /* -------------------------------------------------------------------------- */ |
2084 | 2055 | ||
2085 | static int dwc3_gadget_init_endpoints(struct dwc3 *dwc, u8 total) | 2056 | static int dwc3_gadget_init_control_endpoint(struct dwc3_ep *dep) |
2086 | { | 2057 | { |
2087 | struct dwc3_ep *dep; | 2058 | struct dwc3 *dwc = dep->dwc; |
2088 | u8 epnum; | ||
2089 | 2059 | ||
2090 | INIT_LIST_HEAD(&dwc->gadget.ep_list); | 2060 | usb_ep_set_maxpacket_limit(&dep->endpoint, 512); |
2061 | dep->endpoint.maxburst = 1; | ||
2062 | dep->endpoint.ops = &dwc3_gadget_ep0_ops; | ||
2063 | if (!dep->direction) | ||
2064 | dwc->gadget.ep0 = &dep->endpoint; | ||
2091 | 2065 | ||
2092 | for (epnum = 0; epnum < total; epnum++) { | 2066 | dep->endpoint.caps.type_control = true; |
2093 | bool direction = epnum & 1; | ||
2094 | u8 num = epnum >> 1; | ||
2095 | 2067 | ||
2096 | dep = kzalloc(sizeof(*dep), GFP_KERNEL); | 2068 | return 0; |
2097 | if (!dep) | 2069 | } |
2098 | return -ENOMEM; | ||
2099 | 2070 | ||
2100 | dep->dwc = dwc; | 2071 | static int dwc3_gadget_init_in_endpoint(struct dwc3_ep *dep) |
2101 | dep->number = epnum; | 2072 | { |
2102 | dep->direction = direction; | 2073 | struct dwc3 *dwc = dep->dwc; |
2103 | dep->regs = dwc->regs + DWC3_DEP_BASE(epnum); | 2074 | int mdwidth; |
2104 | dwc->eps[epnum] = dep; | 2075 | int kbytes; |
2076 | int size; | ||
2105 | 2077 | ||
2106 | snprintf(dep->name, sizeof(dep->name), "ep%u%s", num, | 2078 | mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0); |
2107 | direction ? "in" : "out"); | 2079 | /* MDWIDTH is represented in bits, we need it in bytes */ |
2080 | mdwidth /= 8; | ||
2108 | 2081 | ||
2109 | dep->endpoint.name = dep->name; | 2082 | size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(dep->number >> 1)); |
2083 | if (dwc3_is_usb31(dwc)) | ||
2084 | size = DWC31_GTXFIFOSIZ_TXFDEF(size); | ||
2085 | else | ||
2086 | size = DWC3_GTXFIFOSIZ_TXFDEF(size); | ||
2110 | 2087 | ||
2111 | if (!(dep->number > 1)) { | 2088 | /* FIFO Depth is in MDWDITH bytes. Multiply */ |
2112 | dep->endpoint.desc = &dwc3_gadget_ep0_desc; | 2089 | size *= mdwidth; |
2113 | dep->endpoint.comp_desc = NULL; | ||
2114 | } | ||
2115 | 2090 | ||
2116 | spin_lock_init(&dep->lock); | 2091 | kbytes = size / 1024; |
2117 | 2092 | if (kbytes == 0) | |
2118 | if (num == 0) { | 2093 | kbytes = 1; |
2119 | usb_ep_set_maxpacket_limit(&dep->endpoint, 512); | ||
2120 | dep->endpoint.maxburst = 1; | ||
2121 | dep->endpoint.ops = &dwc3_gadget_ep0_ops; | ||
2122 | if (!direction) | ||
2123 | dwc->gadget.ep0 = &dep->endpoint; | ||
2124 | } else if (direction) { | ||
2125 | int mdwidth; | ||
2126 | int kbytes; | ||
2127 | int size; | ||
2128 | int ret; | ||
2129 | |||
2130 | mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0); | ||
2131 | /* MDWIDTH is represented in bits, we need it in bytes */ | ||
2132 | mdwidth /= 8; | ||
2133 | |||
2134 | size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(num)); | ||
2135 | if (dwc3_is_usb31(dwc)) | ||
2136 | size = DWC31_GTXFIFOSIZ_TXFDEF(size); | ||
2137 | else | ||
2138 | size = DWC3_GTXFIFOSIZ_TXFDEF(size); | ||
2139 | 2094 | ||
2140 | /* FIFO Depth is in MDWDITH bytes. Multiply */ | 2095 | /* |
2141 | size *= mdwidth; | 2096 | * FIFO sizes account an extra MDWIDTH * (kbytes + 1) bytes for |
2097 | * internal overhead. We don't really know how these are used, | ||
2098 | * but documentation say it exists. | ||
2099 | */ | ||
2100 | size -= mdwidth * (kbytes + 1); | ||
2101 | size /= kbytes; | ||
2142 | 2102 | ||
2143 | kbytes = size / 1024; | 2103 | usb_ep_set_maxpacket_limit(&dep->endpoint, size); |
2144 | if (kbytes == 0) | ||
2145 | kbytes = 1; | ||
2146 | 2104 | ||
2147 | /* | 2105 | dep->endpoint.max_streams = 15; |
2148 | * FIFO sizes account an extra MDWIDTH * (kbytes + 1) bytes for | 2106 | dep->endpoint.ops = &dwc3_gadget_ep_ops; |
2149 | * internal overhead. We don't really know how these are used, | 2107 | list_add_tail(&dep->endpoint.ep_list, |
2150 | * but documentation say it exists. | 2108 | &dwc->gadget.ep_list); |
2151 | */ | 2109 | dep->endpoint.caps.type_iso = true; |
2152 | size -= mdwidth * (kbytes + 1); | 2110 | dep->endpoint.caps.type_bulk = true; |
2153 | size /= kbytes; | 2111 | dep->endpoint.caps.type_int = true; |
2154 | 2112 | ||
2155 | usb_ep_set_maxpacket_limit(&dep->endpoint, size); | 2113 | return dwc3_alloc_trb_pool(dep); |
2114 | } | ||
2156 | 2115 | ||
2157 | dep->endpoint.max_streams = 15; | 2116 | static int dwc3_gadget_init_out_endpoint(struct dwc3_ep *dep) |
2158 | dep->endpoint.ops = &dwc3_gadget_ep_ops; | 2117 | { |
2159 | list_add_tail(&dep->endpoint.ep_list, | 2118 | struct dwc3 *dwc = dep->dwc; |
2160 | &dwc->gadget.ep_list); | ||
2161 | 2119 | ||
2162 | ret = dwc3_alloc_trb_pool(dep); | 2120 | usb_ep_set_maxpacket_limit(&dep->endpoint, 1024); |
2163 | if (ret) | 2121 | dep->endpoint.max_streams = 15; |
2164 | return ret; | 2122 | dep->endpoint.ops = &dwc3_gadget_ep_ops; |
2165 | } else { | 2123 | list_add_tail(&dep->endpoint.ep_list, |
2166 | int ret; | 2124 | &dwc->gadget.ep_list); |
2125 | dep->endpoint.caps.type_iso = true; | ||
2126 | dep->endpoint.caps.type_bulk = true; | ||
2127 | dep->endpoint.caps.type_int = true; | ||
2167 | 2128 | ||
2168 | usb_ep_set_maxpacket_limit(&dep->endpoint, 1024); | 2129 | return dwc3_alloc_trb_pool(dep); |
2169 | dep->endpoint.max_streams = 15; | 2130 | } |
2170 | dep->endpoint.ops = &dwc3_gadget_ep_ops; | ||
2171 | list_add_tail(&dep->endpoint.ep_list, | ||
2172 | &dwc->gadget.ep_list); | ||
2173 | 2131 | ||
2174 | ret = dwc3_alloc_trb_pool(dep); | 2132 | static int dwc3_gadget_init_endpoint(struct dwc3 *dwc, u8 epnum) |
2175 | if (ret) | 2133 | { |
2176 | return ret; | 2134 | struct dwc3_ep *dep; |
2177 | } | 2135 | bool direction = epnum & 1; |
2136 | int ret; | ||
2137 | u8 num = epnum >> 1; | ||
2178 | 2138 | ||
2179 | if (num == 0) { | 2139 | dep = kzalloc(sizeof(*dep), GFP_KERNEL); |
2180 | dep->endpoint.caps.type_control = true; | 2140 | if (!dep) |
2181 | } else { | 2141 | return -ENOMEM; |
2182 | dep->endpoint.caps.type_iso = true; | ||
2183 | dep->endpoint.caps.type_bulk = true; | ||
2184 | dep->endpoint.caps.type_int = true; | ||
2185 | } | ||
2186 | 2142 | ||
2187 | dep->endpoint.caps.dir_in = direction; | 2143 | dep->dwc = dwc; |
2188 | dep->endpoint.caps.dir_out = !direction; | 2144 | dep->number = epnum; |
2145 | dep->direction = direction; | ||
2146 | dep->regs = dwc->regs + DWC3_DEP_BASE(epnum); | ||
2147 | dwc->eps[epnum] = dep; | ||
2189 | 2148 | ||
2190 | INIT_LIST_HEAD(&dep->pending_list); | 2149 | snprintf(dep->name, sizeof(dep->name), "ep%u%s", num, |
2191 | INIT_LIST_HEAD(&dep->started_list); | 2150 | direction ? "in" : "out"); |
2151 | |||
2152 | dep->endpoint.name = dep->name; | ||
2153 | |||
2154 | if (!(dep->number > 1)) { | ||
2155 | dep->endpoint.desc = &dwc3_gadget_ep0_desc; | ||
2156 | dep->endpoint.comp_desc = NULL; | ||
2157 | } | ||
2158 | |||
2159 | spin_lock_init(&dep->lock); | ||
2160 | |||
2161 | if (num == 0) | ||
2162 | ret = dwc3_gadget_init_control_endpoint(dep); | ||
2163 | else if (direction) | ||
2164 | ret = dwc3_gadget_init_in_endpoint(dep); | ||
2165 | else | ||
2166 | ret = dwc3_gadget_init_out_endpoint(dep); | ||
2167 | |||
2168 | if (ret) | ||
2169 | return ret; | ||
2170 | |||
2171 | dep->endpoint.caps.dir_in = direction; | ||
2172 | dep->endpoint.caps.dir_out = !direction; | ||
2173 | |||
2174 | INIT_LIST_HEAD(&dep->pending_list); | ||
2175 | INIT_LIST_HEAD(&dep->started_list); | ||
2176 | |||
2177 | return 0; | ||
2178 | } | ||
2179 | |||
2180 | static int dwc3_gadget_init_endpoints(struct dwc3 *dwc, u8 total) | ||
2181 | { | ||
2182 | u8 epnum; | ||
2183 | |||
2184 | INIT_LIST_HEAD(&dwc->gadget.ep_list); | ||
2185 | |||
2186 | for (epnum = 0; epnum < total; epnum++) { | ||
2187 | int ret; | ||
2188 | |||
2189 | ret = dwc3_gadget_init_endpoint(dwc, epnum); | ||
2190 | if (ret) | ||
2191 | return ret; | ||
2192 | } | 2192 | } |
2193 | 2193 | ||
2194 | return 0; | 2194 | return 0; |
@@ -2223,20 +2223,14 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc) | |||
2223 | 2223 | ||
2224 | /* -------------------------------------------------------------------------- */ | 2224 | /* -------------------------------------------------------------------------- */ |
2225 | 2225 | ||
2226 | static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep, | 2226 | static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep, |
2227 | struct dwc3_request *req, struct dwc3_trb *trb, | 2227 | struct dwc3_request *req, struct dwc3_trb *trb, |
2228 | const struct dwc3_event_depevt *event, int status, | 2228 | const struct dwc3_event_depevt *event, int status, int chain) |
2229 | int chain) | ||
2230 | { | 2229 | { |
2231 | unsigned int count; | 2230 | unsigned int count; |
2232 | unsigned int s_pkt = 0; | ||
2233 | unsigned int trb_status; | ||
2234 | 2231 | ||
2235 | dwc3_ep_inc_deq(dep); | 2232 | dwc3_ep_inc_deq(dep); |
2236 | 2233 | ||
2237 | if (req->trb == trb) | ||
2238 | dep->queued_requests--; | ||
2239 | |||
2240 | trace_dwc3_complete_trb(dep, trb); | 2234 | trace_dwc3_complete_trb(dep, trb); |
2241 | 2235 | ||
2242 | /* | 2236 | /* |
@@ -2268,159 +2262,140 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep, | |||
2268 | if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN) | 2262 | if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN) |
2269 | return 1; | 2263 | return 1; |
2270 | 2264 | ||
2271 | if (dep->direction) { | 2265 | if (event->status & DEPEVT_STATUS_SHORT && !chain) |
2272 | if (count) { | ||
2273 | trb_status = DWC3_TRB_SIZE_TRBSTS(trb->size); | ||
2274 | if (trb_status == DWC3_TRBSTS_MISSED_ISOC) { | ||
2275 | /* | ||
2276 | * If missed isoc occurred and there is | ||
2277 | * no request queued then issue END | ||
2278 | * TRANSFER, so that core generates | ||
2279 | * next xfernotready and we will issue | ||
2280 | * a fresh START TRANSFER. | ||
2281 | * If there are still queued request | ||
2282 | * then wait, do not issue either END | ||
2283 | * or UPDATE TRANSFER, just attach next | ||
2284 | * request in pending_list during | ||
2285 | * giveback.If any future queued request | ||
2286 | * is successfully transferred then we | ||
2287 | * will issue UPDATE TRANSFER for all | ||
2288 | * request in the pending_list. | ||
2289 | */ | ||
2290 | dep->flags |= DWC3_EP_MISSED_ISOC; | ||
2291 | } else { | ||
2292 | dev_err(dwc->dev, "incomplete IN transfer %s\n", | ||
2293 | dep->name); | ||
2294 | status = -ECONNRESET; | ||
2295 | } | ||
2296 | } else { | ||
2297 | dep->flags &= ~DWC3_EP_MISSED_ISOC; | ||
2298 | } | ||
2299 | } else { | ||
2300 | if (count && (event->status & DEPEVT_STATUS_SHORT)) | ||
2301 | s_pkt = 1; | ||
2302 | } | ||
2303 | |||
2304 | if (s_pkt && !chain) | ||
2305 | return 1; | 2266 | return 1; |
2306 | 2267 | ||
2307 | if ((event->status & DEPEVT_STATUS_IOC) && | 2268 | if (event->status & DEPEVT_STATUS_IOC) |
2308 | (trb->ctrl & DWC3_TRB_CTRL_IOC)) | ||
2309 | return 1; | 2269 | return 1; |
2310 | 2270 | ||
2311 | return 0; | 2271 | return 0; |
2312 | } | 2272 | } |
2313 | 2273 | ||
2314 | static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, | 2274 | static int dwc3_gadget_ep_reclaim_trb_sg(struct dwc3_ep *dep, |
2315 | const struct dwc3_event_depevt *event, int status) | 2275 | struct dwc3_request *req, const struct dwc3_event_depevt *event, |
2276 | int status) | ||
2316 | { | 2277 | { |
2317 | struct dwc3_request *req, *n; | 2278 | struct dwc3_trb *trb = &dep->trb_pool[dep->trb_dequeue]; |
2318 | struct dwc3_trb *trb; | 2279 | struct scatterlist *sg = req->sg; |
2319 | bool ioc = false; | 2280 | struct scatterlist *s; |
2320 | int ret = 0; | 2281 | unsigned int pending = req->num_pending_sgs; |
2282 | unsigned int i; | ||
2283 | int ret = 0; | ||
2321 | 2284 | ||
2322 | list_for_each_entry_safe(req, n, &dep->started_list, list) { | 2285 | for_each_sg(sg, s, pending, i) { |
2323 | unsigned length; | 2286 | trb = &dep->trb_pool[dep->trb_dequeue]; |
2324 | int chain; | ||
2325 | 2287 | ||
2326 | length = req->request.length; | 2288 | if (trb->ctrl & DWC3_TRB_CTRL_HWO) |
2327 | chain = req->num_pending_sgs > 0; | 2289 | break; |
2328 | if (chain) { | ||
2329 | struct scatterlist *sg = req->sg; | ||
2330 | struct scatterlist *s; | ||
2331 | unsigned int pending = req->num_pending_sgs; | ||
2332 | unsigned int i; | ||
2333 | |||
2334 | for_each_sg(sg, s, pending, i) { | ||
2335 | trb = &dep->trb_pool[dep->trb_dequeue]; | ||
2336 | |||
2337 | if (trb->ctrl & DWC3_TRB_CTRL_HWO) | ||
2338 | break; | ||
2339 | |||
2340 | req->sg = sg_next(s); | ||
2341 | req->num_pending_sgs--; | ||
2342 | |||
2343 | ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb, | ||
2344 | event, status, chain); | ||
2345 | if (ret) | ||
2346 | break; | ||
2347 | } | ||
2348 | } else { | ||
2349 | trb = &dep->trb_pool[dep->trb_dequeue]; | ||
2350 | ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb, | ||
2351 | event, status, chain); | ||
2352 | } | ||
2353 | 2290 | ||
2354 | if (req->unaligned || req->zero) { | 2291 | req->sg = sg_next(s); |
2355 | trb = &dep->trb_pool[dep->trb_dequeue]; | 2292 | req->num_pending_sgs--; |
2356 | ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb, | ||
2357 | event, status, false); | ||
2358 | req->unaligned = false; | ||
2359 | req->zero = false; | ||
2360 | } | ||
2361 | 2293 | ||
2362 | req->request.actual = length - req->remaining; | 2294 | ret = dwc3_gadget_ep_reclaim_completed_trb(dep, req, |
2295 | trb, event, status, true); | ||
2296 | if (ret) | ||
2297 | break; | ||
2298 | } | ||
2299 | |||
2300 | return ret; | ||
2301 | } | ||
2363 | 2302 | ||
2364 | if ((req->request.actual < length) && req->num_pending_sgs) | 2303 | static int dwc3_gadget_ep_reclaim_trb_linear(struct dwc3_ep *dep, |
2365 | return __dwc3_gadget_kick_transfer(dep); | 2304 | struct dwc3_request *req, const struct dwc3_event_depevt *event, |
2305 | int status) | ||
2306 | { | ||
2307 | struct dwc3_trb *trb = &dep->trb_pool[dep->trb_dequeue]; | ||
2366 | 2308 | ||
2367 | dwc3_gadget_giveback(dep, req, status); | 2309 | return dwc3_gadget_ep_reclaim_completed_trb(dep, req, trb, |
2310 | event, status, false); | ||
2311 | } | ||
2368 | 2312 | ||
2369 | if (ret) { | 2313 | static bool dwc3_gadget_ep_request_completed(struct dwc3_request *req) |
2370 | if ((event->status & DEPEVT_STATUS_IOC) && | 2314 | { |
2371 | (trb->ctrl & DWC3_TRB_CTRL_IOC)) | 2315 | return req->request.actual == req->request.length; |
2372 | ioc = true; | 2316 | } |
2373 | break; | 2317 | |
2374 | } | 2318 | static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep, |
2319 | const struct dwc3_event_depevt *event, | ||
2320 | struct dwc3_request *req, int status) | ||
2321 | { | ||
2322 | int ret; | ||
2323 | |||
2324 | if (req->num_pending_sgs) | ||
2325 | ret = dwc3_gadget_ep_reclaim_trb_sg(dep, req, event, | ||
2326 | status); | ||
2327 | else | ||
2328 | ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, | ||
2329 | status); | ||
2330 | |||
2331 | if (req->unaligned || req->zero) { | ||
2332 | ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, | ||
2333 | status); | ||
2334 | req->unaligned = false; | ||
2335 | req->zero = false; | ||
2375 | } | 2336 | } |
2376 | 2337 | ||
2377 | /* | 2338 | req->request.actual = req->request.length - req->remaining; |
2378 | * Our endpoint might get disabled by another thread during | ||
2379 | * dwc3_gadget_giveback(). If that happens, we're just gonna return 1 | ||
2380 | * early on so DWC3_EP_BUSY flag gets cleared | ||
2381 | */ | ||
2382 | if (!dep->endpoint.desc) | ||
2383 | return 1; | ||
2384 | 2339 | ||
2385 | if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && | 2340 | if (!dwc3_gadget_ep_request_completed(req) && |
2386 | list_empty(&dep->started_list)) { | 2341 | req->num_pending_sgs) { |
2387 | if (list_empty(&dep->pending_list)) { | 2342 | __dwc3_gadget_kick_transfer(dep); |
2388 | /* | 2343 | goto out; |
2389 | * If there is no entry in request list then do | ||
2390 | * not issue END TRANSFER now. Just set PENDING | ||
2391 | * flag, so that END TRANSFER is issued when an | ||
2392 | * entry is added into request list. | ||
2393 | */ | ||
2394 | dep->flags = DWC3_EP_PENDING_REQUEST; | ||
2395 | } else { | ||
2396 | dwc3_stop_active_transfer(dwc, dep->number, true); | ||
2397 | dep->flags = DWC3_EP_ENABLED; | ||
2398 | } | ||
2399 | return 1; | ||
2400 | } | 2344 | } |
2401 | 2345 | ||
2402 | if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && ioc) | 2346 | dwc3_gadget_giveback(dep, req, status); |
2403 | return 0; | 2347 | |
2348 | out: | ||
2349 | return ret; | ||
2350 | } | ||
2351 | |||
2352 | static void dwc3_gadget_ep_cleanup_completed_requests(struct dwc3_ep *dep, | ||
2353 | const struct dwc3_event_depevt *event, int status) | ||
2354 | { | ||
2355 | struct dwc3_request *req; | ||
2356 | struct dwc3_request *tmp; | ||
2357 | |||
2358 | list_for_each_entry_safe(req, tmp, &dep->started_list, list) { | ||
2359 | int ret; | ||
2360 | |||
2361 | ret = dwc3_gadget_ep_cleanup_completed_request(dep, event, | ||
2362 | req, status); | ||
2363 | if (ret) | ||
2364 | break; | ||
2365 | } | ||
2366 | } | ||
2404 | 2367 | ||
2405 | return 1; | 2368 | static void dwc3_gadget_endpoint_frame_from_event(struct dwc3_ep *dep, |
2369 | const struct dwc3_event_depevt *event) | ||
2370 | { | ||
2371 | dep->frame_number = event->parameters; | ||
2406 | } | 2372 | } |
2407 | 2373 | ||
2408 | static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc, | 2374 | static void dwc3_gadget_endpoint_transfer_in_progress(struct dwc3_ep *dep, |
2409 | struct dwc3_ep *dep, const struct dwc3_event_depevt *event) | 2375 | const struct dwc3_event_depevt *event) |
2410 | { | 2376 | { |
2377 | struct dwc3 *dwc = dep->dwc; | ||
2411 | unsigned status = 0; | 2378 | unsigned status = 0; |
2412 | int clean_busy; | 2379 | bool stop = false; |
2413 | u32 is_xfer_complete; | ||
2414 | 2380 | ||
2415 | is_xfer_complete = (event->endpoint_event == DWC3_DEPEVT_XFERCOMPLETE); | 2381 | dwc3_gadget_endpoint_frame_from_event(dep, event); |
2416 | 2382 | ||
2417 | if (event->status & DEPEVT_STATUS_BUSERR) | 2383 | if (event->status & DEPEVT_STATUS_BUSERR) |
2418 | status = -ECONNRESET; | 2384 | status = -ECONNRESET; |
2419 | 2385 | ||
2420 | clean_busy = dwc3_cleanup_done_reqs(dwc, dep, event, status); | 2386 | if (event->status & DEPEVT_STATUS_MISSED_ISOC) { |
2421 | if (clean_busy && (!dep->endpoint.desc || is_xfer_complete || | 2387 | status = -EXDEV; |
2422 | usb_endpoint_xfer_isoc(dep->endpoint.desc))) | 2388 | |
2423 | dep->flags &= ~DWC3_EP_BUSY; | 2389 | if (list_empty(&dep->started_list)) |
2390 | stop = true; | ||
2391 | } | ||
2392 | |||
2393 | dwc3_gadget_ep_cleanup_completed_requests(dep, event, status); | ||
2394 | |||
2395 | if (stop) { | ||
2396 | dwc3_stop_active_transfer(dep, true); | ||
2397 | dep->flags = DWC3_EP_ENABLED; | ||
2398 | } | ||
2424 | 2399 | ||
2425 | /* | 2400 | /* |
2426 | * WORKAROUND: This is the 2nd half of U1/U2 -> U0 workaround. | 2401 | * WORKAROUND: This is the 2nd half of U1/U2 -> U0 workaround. |
@@ -2446,17 +2421,13 @@ static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc, | |||
2446 | 2421 | ||
2447 | dwc->u1u2 = 0; | 2422 | dwc->u1u2 = 0; |
2448 | } | 2423 | } |
2424 | } | ||
2449 | 2425 | ||
2450 | /* | 2426 | static void dwc3_gadget_endpoint_transfer_not_ready(struct dwc3_ep *dep, |
2451 | * Our endpoint might get disabled by another thread during | 2427 | const struct dwc3_event_depevt *event) |
2452 | * dwc3_gadget_giveback(). If that happens, we're just gonna return 1 | 2428 | { |
2453 | * early on so DWC3_EP_BUSY flag gets cleared | 2429 | dwc3_gadget_endpoint_frame_from_event(dep, event); |
2454 | */ | 2430 | __dwc3_gadget_start_isoc(dep); |
2455 | if (!dep->endpoint.desc) | ||
2456 | return; | ||
2457 | |||
2458 | if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) | ||
2459 | __dwc3_gadget_kick_transfer(dep); | ||
2460 | } | 2431 | } |
2461 | 2432 | ||
2462 | static void dwc3_endpoint_interrupt(struct dwc3 *dwc, | 2433 | static void dwc3_endpoint_interrupt(struct dwc3 *dwc, |
@@ -2483,32 +2454,11 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, | |||
2483 | } | 2454 | } |
2484 | 2455 | ||
2485 | switch (event->endpoint_event) { | 2456 | switch (event->endpoint_event) { |
2486 | case DWC3_DEPEVT_XFERCOMPLETE: | ||
2487 | dep->resource_index = 0; | ||
2488 | |||
2489 | if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { | ||
2490 | dev_err(dwc->dev, "XferComplete for Isochronous endpoint\n"); | ||
2491 | return; | ||
2492 | } | ||
2493 | |||
2494 | dwc3_endpoint_transfer_complete(dwc, dep, event); | ||
2495 | break; | ||
2496 | case DWC3_DEPEVT_XFERINPROGRESS: | 2457 | case DWC3_DEPEVT_XFERINPROGRESS: |
2497 | dwc3_endpoint_transfer_complete(dwc, dep, event); | 2458 | dwc3_gadget_endpoint_transfer_in_progress(dep, event); |
2498 | break; | 2459 | break; |
2499 | case DWC3_DEPEVT_XFERNOTREADY: | 2460 | case DWC3_DEPEVT_XFERNOTREADY: |
2500 | if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) | 2461 | dwc3_gadget_endpoint_transfer_not_ready(dep, event); |
2501 | dwc3_gadget_start_isoc(dwc, dep, event); | ||
2502 | else | ||
2503 | __dwc3_gadget_kick_transfer(dep); | ||
2504 | |||
2505 | break; | ||
2506 | case DWC3_DEPEVT_STREAMEVT: | ||
2507 | if (!usb_endpoint_xfer_bulk(dep->endpoint.desc)) { | ||
2508 | dev_err(dwc->dev, "Stream event for non-Bulk %s\n", | ||
2509 | dep->name); | ||
2510 | return; | ||
2511 | } | ||
2512 | break; | 2462 | break; |
2513 | case DWC3_DEPEVT_EPCMDCMPLT: | 2463 | case DWC3_DEPEVT_EPCMDCMPLT: |
2514 | cmd = DEPEVT_PARAMETER_CMD(event->parameters); | 2464 | cmd = DEPEVT_PARAMETER_CMD(event->parameters); |
@@ -2518,6 +2468,8 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, | |||
2518 | wake_up(&dep->wait_end_transfer); | 2468 | wake_up(&dep->wait_end_transfer); |
2519 | } | 2469 | } |
2520 | break; | 2470 | break; |
2471 | case DWC3_DEPEVT_STREAMEVT: | ||
2472 | case DWC3_DEPEVT_XFERCOMPLETE: | ||
2521 | case DWC3_DEPEVT_RXTXFIFOEVT: | 2473 | case DWC3_DEPEVT_RXTXFIFOEVT: |
2522 | break; | 2474 | break; |
2523 | } | 2475 | } |
@@ -2562,15 +2514,13 @@ static void dwc3_reset_gadget(struct dwc3 *dwc) | |||
2562 | } | 2514 | } |
2563 | } | 2515 | } |
2564 | 2516 | ||
2565 | static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force) | 2517 | static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force) |
2566 | { | 2518 | { |
2567 | struct dwc3_ep *dep; | 2519 | struct dwc3 *dwc = dep->dwc; |
2568 | struct dwc3_gadget_ep_cmd_params params; | 2520 | struct dwc3_gadget_ep_cmd_params params; |
2569 | u32 cmd; | 2521 | u32 cmd; |
2570 | int ret; | 2522 | int ret; |
2571 | 2523 | ||
2572 | dep = dwc->eps[epnum]; | ||
2573 | |||
2574 | if ((dep->flags & DWC3_EP_END_TRANSFER_PENDING) || | 2524 | if ((dep->flags & DWC3_EP_END_TRANSFER_PENDING) || |
2575 | !dep->resource_index) | 2525 | !dep->resource_index) |
2576 | return; | 2526 | return; |
@@ -2614,7 +2564,6 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force) | |||
2614 | ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); | 2564 | ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); |
2615 | WARN_ON_ONCE(ret); | 2565 | WARN_ON_ONCE(ret); |
2616 | dep->resource_index = 0; | 2566 | dep->resource_index = 0; |
2617 | dep->flags &= ~DWC3_EP_BUSY; | ||
2618 | 2567 | ||
2619 | if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A) { | 2568 | if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A) { |
2620 | dep->flags |= DWC3_EP_END_TRANSFER_PENDING; | 2569 | dep->flags |= DWC3_EP_END_TRANSFER_PENDING; |
@@ -2816,14 +2765,14 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) | |||
2816 | } | 2765 | } |
2817 | 2766 | ||
2818 | dep = dwc->eps[0]; | 2767 | dep = dwc->eps[0]; |
2819 | ret = __dwc3_gadget_ep_enable(dep, true, false); | 2768 | ret = __dwc3_gadget_ep_enable(dep, DWC3_DEPCFG_ACTION_MODIFY); |
2820 | if (ret) { | 2769 | if (ret) { |
2821 | dev_err(dwc->dev, "failed to enable %s\n", dep->name); | 2770 | dev_err(dwc->dev, "failed to enable %s\n", dep->name); |
2822 | return; | 2771 | return; |
2823 | } | 2772 | } |
2824 | 2773 | ||
2825 | dep = dwc->eps[1]; | 2774 | dep = dwc->eps[1]; |
2826 | ret = __dwc3_gadget_ep_enable(dep, true, false); | 2775 | ret = __dwc3_gadget_ep_enable(dep, DWC3_DEPCFG_ACTION_MODIFY); |
2827 | if (ret) { | 2776 | if (ret) { |
2828 | dev_err(dwc->dev, "failed to enable %s\n", dep->name); | 2777 | dev_err(dwc->dev, "failed to enable %s\n", dep->name); |
2829 | return; | 2778 | return; |
diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h index 578aa856f986..db610c56f1d6 100644 --- a/drivers/usb/dwc3/gadget.h +++ b/drivers/usb/dwc3/gadget.h | |||
@@ -98,13 +98,12 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol); | |||
98 | * Caller should take care of locking. Returns the transfer resource | 98 | * Caller should take care of locking. Returns the transfer resource |
99 | * index for a given endpoint. | 99 | * index for a given endpoint. |
100 | */ | 100 | */ |
101 | static inline u32 dwc3_gadget_ep_get_transfer_index(struct dwc3_ep *dep) | 101 | static inline void dwc3_gadget_ep_get_transfer_index(struct dwc3_ep *dep) |
102 | { | 102 | { |
103 | u32 res_id; | 103 | u32 res_id; |
104 | 104 | ||
105 | res_id = dwc3_readl(dep->regs, DWC3_DEPCMD); | 105 | res_id = dwc3_readl(dep->regs, DWC3_DEPCMD); |
106 | 106 | dep->resource_index = DWC3_DEPCMD_GET_RSC_IDX(res_id); | |
107 | return DWC3_DEPCMD_GET_RSC_IDX(res_id); | ||
108 | } | 107 | } |
109 | 108 | ||
110 | #endif /* __DRIVERS_USB_DWC3_GADGET_H */ | 109 | #endif /* __DRIVERS_USB_DWC3_GADGET_H */ |
diff --git a/drivers/usb/dwc3/trace.h b/drivers/usb/dwc3/trace.h index babaee981aa7..f22714cce070 100644 --- a/drivers/usb/dwc3/trace.h +++ b/drivers/usb/dwc3/trace.h | |||
@@ -230,17 +230,14 @@ DECLARE_EVENT_CLASS(dwc3_log_trb, | |||
230 | TP_fast_assign( | 230 | TP_fast_assign( |
231 | __assign_str(name, dep->name); | 231 | __assign_str(name, dep->name); |
232 | __entry->trb = trb; | 232 | __entry->trb = trb; |
233 | __entry->allocated = dep->allocated_requests; | ||
234 | __entry->queued = dep->queued_requests; | ||
235 | __entry->bpl = trb->bpl; | 233 | __entry->bpl = trb->bpl; |
236 | __entry->bph = trb->bph; | 234 | __entry->bph = trb->bph; |
237 | __entry->size = trb->size; | 235 | __entry->size = trb->size; |
238 | __entry->ctrl = trb->ctrl; | 236 | __entry->ctrl = trb->ctrl; |
239 | __entry->type = usb_endpoint_type(dep->endpoint.desc); | 237 | __entry->type = usb_endpoint_type(dep->endpoint.desc); |
240 | ), | 238 | ), |
241 | TP_printk("%s: %d/%d trb %p buf %08x%08x size %s%d ctrl %08x (%c%c%c%c:%c%c:%s)", | 239 | TP_printk("%s: trb %p buf %08x%08x size %s%d ctrl %08x (%c%c%c%c:%c%c:%s)", |
242 | __get_str(name), __entry->queued, __entry->allocated, | 240 | __get_str(name), __entry->trb, __entry->bph, __entry->bpl, |
243 | __entry->trb, __entry->bph, __entry->bpl, | ||
244 | ({char *s; | 241 | ({char *s; |
245 | int pcm = ((__entry->size >> 24) & 3) + 1; | 242 | int pcm = ((__entry->size >> 24) & 3) + 1; |
246 | switch (__entry->type) { | 243 | switch (__entry->type) { |
@@ -306,7 +303,7 @@ DECLARE_EVENT_CLASS(dwc3_log_ep, | |||
306 | __entry->trb_enqueue = dep->trb_enqueue; | 303 | __entry->trb_enqueue = dep->trb_enqueue; |
307 | __entry->trb_dequeue = dep->trb_dequeue; | 304 | __entry->trb_dequeue = dep->trb_dequeue; |
308 | ), | 305 | ), |
309 | TP_printk("%s: mps %d/%d streams %d burst %d ring %d/%d flags %c:%c%c%c%c%c:%c:%c", | 306 | TP_printk("%s: mps %d/%d streams %d burst %d ring %d/%d flags %c:%c%c%c%c:%c:%c", |
310 | __get_str(name), __entry->maxpacket, | 307 | __get_str(name), __entry->maxpacket, |
311 | __entry->maxpacket_limit, __entry->max_streams, | 308 | __entry->maxpacket_limit, __entry->max_streams, |
312 | __entry->maxburst, __entry->trb_enqueue, | 309 | __entry->maxburst, __entry->trb_enqueue, |
@@ -314,9 +311,8 @@ DECLARE_EVENT_CLASS(dwc3_log_ep, | |||
314 | __entry->flags & DWC3_EP_ENABLED ? 'E' : 'e', | 311 | __entry->flags & DWC3_EP_ENABLED ? 'E' : 'e', |
315 | __entry->flags & DWC3_EP_STALL ? 'S' : 's', | 312 | __entry->flags & DWC3_EP_STALL ? 'S' : 's', |
316 | __entry->flags & DWC3_EP_WEDGE ? 'W' : 'w', | 313 | __entry->flags & DWC3_EP_WEDGE ? 'W' : 'w', |
317 | __entry->flags & DWC3_EP_BUSY ? 'B' : 'b', | 314 | __entry->flags & DWC3_EP_TRANSFER_STARTED ? 'B' : 'b', |
318 | __entry->flags & DWC3_EP_PENDING_REQUEST ? 'P' : 'p', | 315 | __entry->flags & DWC3_EP_PENDING_REQUEST ? 'P' : 'p', |
319 | __entry->flags & DWC3_EP_MISSED_ISOC ? 'M' : 'm', | ||
320 | __entry->flags & DWC3_EP_END_TRANSFER_PENDING ? 'E' : 'e', | 316 | __entry->flags & DWC3_EP_END_TRANSFER_PENDING ? 'E' : 'e', |
321 | __entry->direction ? '<' : '>' | 317 | __entry->direction ? '<' : '>' |
322 | ) | 318 | ) |
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 63a7cb87514a..f242c2bcea81 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c | |||
@@ -1601,7 +1601,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) | |||
1601 | cdev->gadget->ep0->maxpacket; | 1601 | cdev->gadget->ep0->maxpacket; |
1602 | if (gadget_is_superspeed(gadget)) { | 1602 | if (gadget_is_superspeed(gadget)) { |
1603 | if (gadget->speed >= USB_SPEED_SUPER) { | 1603 | if (gadget->speed >= USB_SPEED_SUPER) { |
1604 | cdev->desc.bcdUSB = cpu_to_le16(0x0310); | 1604 | cdev->desc.bcdUSB = cpu_to_le16(0x0320); |
1605 | cdev->desc.bMaxPacketSize0 = 9; | 1605 | cdev->desc.bMaxPacketSize0 = 9; |
1606 | } else { | 1606 | } else { |
1607 | cdev->desc.bcdUSB = cpu_to_le16(0x0210); | 1607 | cdev->desc.bcdUSB = cpu_to_le16(0x0210); |
diff --git a/drivers/usb/gadget/function/f_ecm.c b/drivers/usb/gadget/function/f_ecm.c index b104ed0c1ab5..6ce044008cf6 100644 --- a/drivers/usb/gadget/function/f_ecm.c +++ b/drivers/usb/gadget/function/f_ecm.c | |||
@@ -705,6 +705,8 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f) | |||
705 | ecm_opts->bound = true; | 705 | ecm_opts->bound = true; |
706 | } | 706 | } |
707 | 707 | ||
708 | ecm_string_defs[1].s = ecm->ethaddr; | ||
709 | |||
708 | us = usb_gstrings_attach(cdev, ecm_strings, | 710 | us = usb_gstrings_attach(cdev, ecm_strings, |
709 | ARRAY_SIZE(ecm_string_defs)); | 711 | ARRAY_SIZE(ecm_string_defs)); |
710 | if (IS_ERR(us)) | 712 | if (IS_ERR(us)) |
@@ -928,7 +930,6 @@ static struct usb_function *ecm_alloc(struct usb_function_instance *fi) | |||
928 | mutex_unlock(&opts->lock); | 930 | mutex_unlock(&opts->lock); |
929 | return ERR_PTR(-EINVAL); | 931 | return ERR_PTR(-EINVAL); |
930 | } | 932 | } |
931 | ecm_string_defs[1].s = ecm->ethaddr; | ||
932 | 933 | ||
933 | ecm->port.ioport = netdev_priv(opts->net); | 934 | ecm->port.ioport = netdev_priv(opts->net); |
934 | mutex_unlock(&opts->lock); | 935 | mutex_unlock(&opts->lock); |
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 0294e4f18873..199d25700050 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c | |||
@@ -1266,6 +1266,14 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code, | |||
1266 | return ret; | 1266 | return ret; |
1267 | } | 1267 | } |
1268 | 1268 | ||
1269 | #ifdef CONFIG_COMPAT | ||
1270 | static long ffs_epfile_compat_ioctl(struct file *file, unsigned code, | ||
1271 | unsigned long value) | ||
1272 | { | ||
1273 | return ffs_epfile_ioctl(file, code, value); | ||
1274 | } | ||
1275 | #endif | ||
1276 | |||
1269 | static const struct file_operations ffs_epfile_operations = { | 1277 | static const struct file_operations ffs_epfile_operations = { |
1270 | .llseek = no_llseek, | 1278 | .llseek = no_llseek, |
1271 | 1279 | ||
@@ -1274,6 +1282,9 @@ static const struct file_operations ffs_epfile_operations = { | |||
1274 | .read_iter = ffs_epfile_read_iter, | 1282 | .read_iter = ffs_epfile_read_iter, |
1275 | .release = ffs_epfile_release, | 1283 | .release = ffs_epfile_release, |
1276 | .unlocked_ioctl = ffs_epfile_ioctl, | 1284 | .unlocked_ioctl = ffs_epfile_ioctl, |
1285 | #ifdef CONFIG_COMPAT | ||
1286 | .compat_ioctl = ffs_epfile_compat_ioctl, | ||
1287 | #endif | ||
1277 | }; | 1288 | }; |
1278 | 1289 | ||
1279 | 1290 | ||
diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c index e8f35db42394..f80699747ee0 100644 --- a/drivers/usb/gadget/function/f_midi.c +++ b/drivers/usb/gadget/function/f_midi.c | |||
@@ -109,6 +109,7 @@ static inline struct f_midi *func_to_midi(struct usb_function *f) | |||
109 | 109 | ||
110 | static void f_midi_transmit(struct f_midi *midi); | 110 | static void f_midi_transmit(struct f_midi *midi); |
111 | static void f_midi_rmidi_free(struct snd_rawmidi *rmidi); | 111 | static void f_midi_rmidi_free(struct snd_rawmidi *rmidi); |
112 | static void f_midi_free_inst(struct usb_function_instance *f); | ||
112 | 113 | ||
113 | DECLARE_UAC_AC_HEADER_DESCRIPTOR(1); | 114 | DECLARE_UAC_AC_HEADER_DESCRIPTOR(1); |
114 | DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1); | 115 | DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1); |
@@ -1102,7 +1103,7 @@ static ssize_t f_midi_opts_##name##_store(struct config_item *item, \ | |||
1102 | u32 num; \ | 1103 | u32 num; \ |
1103 | \ | 1104 | \ |
1104 | mutex_lock(&opts->lock); \ | 1105 | mutex_lock(&opts->lock); \ |
1105 | if (opts->refcnt) { \ | 1106 | if (opts->refcnt > 1) { \ |
1106 | ret = -EBUSY; \ | 1107 | ret = -EBUSY; \ |
1107 | goto end; \ | 1108 | goto end; \ |
1108 | } \ | 1109 | } \ |
@@ -1157,7 +1158,7 @@ static ssize_t f_midi_opts_id_store(struct config_item *item, | |||
1157 | char *c; | 1158 | char *c; |
1158 | 1159 | ||
1159 | mutex_lock(&opts->lock); | 1160 | mutex_lock(&opts->lock); |
1160 | if (opts->refcnt) { | 1161 | if (opts->refcnt > 1) { |
1161 | ret = -EBUSY; | 1162 | ret = -EBUSY; |
1162 | goto end; | 1163 | goto end; |
1163 | } | 1164 | } |
@@ -1198,13 +1199,21 @@ static const struct config_item_type midi_func_type = { | |||
1198 | static void f_midi_free_inst(struct usb_function_instance *f) | 1199 | static void f_midi_free_inst(struct usb_function_instance *f) |
1199 | { | 1200 | { |
1200 | struct f_midi_opts *opts; | 1201 | struct f_midi_opts *opts; |
1202 | bool free = false; | ||
1201 | 1203 | ||
1202 | opts = container_of(f, struct f_midi_opts, func_inst); | 1204 | opts = container_of(f, struct f_midi_opts, func_inst); |
1203 | 1205 | ||
1204 | if (opts->id_allocated) | 1206 | mutex_lock(&opts->lock); |
1205 | kfree(opts->id); | 1207 | if (!--opts->refcnt) { |
1208 | free = true; | ||
1209 | } | ||
1210 | mutex_unlock(&opts->lock); | ||
1206 | 1211 | ||
1207 | kfree(opts); | 1212 | if (free) { |
1213 | if (opts->id_allocated) | ||
1214 | kfree(opts->id); | ||
1215 | kfree(opts); | ||
1216 | } | ||
1208 | } | 1217 | } |
1209 | 1218 | ||
1210 | static struct usb_function_instance *f_midi_alloc_inst(void) | 1219 | static struct usb_function_instance *f_midi_alloc_inst(void) |
@@ -1223,6 +1232,7 @@ static struct usb_function_instance *f_midi_alloc_inst(void) | |||
1223 | opts->qlen = 32; | 1232 | opts->qlen = 32; |
1224 | opts->in_ports = 1; | 1233 | opts->in_ports = 1; |
1225 | opts->out_ports = 1; | 1234 | opts->out_ports = 1; |
1235 | opts->refcnt = 1; | ||
1226 | 1236 | ||
1227 | config_group_init_type_name(&opts->func_inst.group, "", | 1237 | config_group_init_type_name(&opts->func_inst.group, "", |
1228 | &midi_func_type); | 1238 | &midi_func_type); |
@@ -1234,6 +1244,7 @@ static void f_midi_free(struct usb_function *f) | |||
1234 | { | 1244 | { |
1235 | struct f_midi *midi; | 1245 | struct f_midi *midi; |
1236 | struct f_midi_opts *opts; | 1246 | struct f_midi_opts *opts; |
1247 | bool free = false; | ||
1237 | 1248 | ||
1238 | midi = func_to_midi(f); | 1249 | midi = func_to_midi(f); |
1239 | opts = container_of(f->fi, struct f_midi_opts, func_inst); | 1250 | opts = container_of(f->fi, struct f_midi_opts, func_inst); |
@@ -1242,9 +1253,12 @@ static void f_midi_free(struct usb_function *f) | |||
1242 | kfree(midi->id); | 1253 | kfree(midi->id); |
1243 | kfifo_free(&midi->in_req_fifo); | 1254 | kfifo_free(&midi->in_req_fifo); |
1244 | kfree(midi); | 1255 | kfree(midi); |
1245 | --opts->refcnt; | 1256 | free = true; |
1246 | } | 1257 | } |
1247 | mutex_unlock(&opts->lock); | 1258 | mutex_unlock(&opts->lock); |
1259 | |||
1260 | if (free) | ||
1261 | f_midi_free_inst(&opts->func_inst); | ||
1248 | } | 1262 | } |
1249 | 1263 | ||
1250 | static void f_midi_rmidi_free(struct snd_rawmidi *rmidi) | 1264 | static void f_midi_rmidi_free(struct snd_rawmidi *rmidi) |
diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c index d359efe06c76..9c7ed2539ff7 100644 --- a/drivers/usb/gadget/function/f_printer.c +++ b/drivers/usb/gadget/function/f_printer.c | |||
@@ -631,19 +631,19 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) | |||
631 | return -EAGAIN; | 631 | return -EAGAIN; |
632 | } | 632 | } |
633 | 633 | ||
634 | list_add(&req->list, &dev->tx_reqs_active); | ||
635 | |||
634 | /* here, we unlock, and only unlock, to avoid deadlock. */ | 636 | /* here, we unlock, and only unlock, to avoid deadlock. */ |
635 | spin_unlock(&dev->lock); | 637 | spin_unlock(&dev->lock); |
636 | value = usb_ep_queue(dev->in_ep, req, GFP_ATOMIC); | 638 | value = usb_ep_queue(dev->in_ep, req, GFP_ATOMIC); |
637 | spin_lock(&dev->lock); | 639 | spin_lock(&dev->lock); |
638 | if (value) { | 640 | if (value) { |
641 | list_del(&req->list); | ||
639 | list_add(&req->list, &dev->tx_reqs); | 642 | list_add(&req->list, &dev->tx_reqs); |
640 | spin_unlock_irqrestore(&dev->lock, flags); | 643 | spin_unlock_irqrestore(&dev->lock, flags); |
641 | mutex_unlock(&dev->lock_printer_io); | 644 | mutex_unlock(&dev->lock_printer_io); |
642 | return -EAGAIN; | 645 | return -EAGAIN; |
643 | } | 646 | } |
644 | |||
645 | list_add(&req->list, &dev->tx_reqs_active); | ||
646 | |||
647 | } | 647 | } |
648 | 648 | ||
649 | spin_unlock_irqrestore(&dev->lock, flags); | 649 | spin_unlock_irqrestore(&dev->lock, flags); |
diff --git a/drivers/usb/gadget/function/rndis.c b/drivers/usb/gadget/function/rndis.c index 51dd3e90b06c..04c142c13075 100644 --- a/drivers/usb/gadget/function/rndis.c +++ b/drivers/usb/gadget/function/rndis.c | |||
@@ -851,6 +851,9 @@ int rndis_msg_parser(struct rndis_params *params, u8 *buf) | |||
851 | */ | 851 | */ |
852 | pr_warn("%s: unknown RNDIS message 0x%08X len %d\n", | 852 | pr_warn("%s: unknown RNDIS message 0x%08X len %d\n", |
853 | __func__, MsgType, MsgLength); | 853 | __func__, MsgType, MsgLength); |
854 | /* Garbled message can be huge, so limit what we display */ | ||
855 | if (MsgLength > 16) | ||
856 | MsgLength = 16; | ||
854 | print_hex_dump_bytes(__func__, DUMP_PREFIX_OFFSET, | 857 | print_hex_dump_bytes(__func__, DUMP_PREFIX_OFFSET, |
855 | buf, MsgLength); | 858 | buf, MsgLength); |
856 | break; | 859 | break; |
diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c index 6fcda62f55ea..1000d864929c 100644 --- a/drivers/usb/gadget/function/u_ether.c +++ b/drivers/usb/gadget/function/u_ether.c | |||
@@ -844,6 +844,10 @@ struct net_device *gether_setup_name_default(const char *netname) | |||
844 | net->ethtool_ops = &ops; | 844 | net->ethtool_ops = &ops; |
845 | SET_NETDEV_DEVTYPE(net, &gadget_type); | 845 | SET_NETDEV_DEVTYPE(net, &gadget_type); |
846 | 846 | ||
847 | /* MTU range: 14 - 15412 */ | ||
848 | net->min_mtu = ETH_HLEN; | ||
849 | net->max_mtu = GETHER_MAX_ETH_FRAME_LEN; | ||
850 | |||
847 | return net; | 851 | return net; |
848 | } | 852 | } |
849 | EXPORT_SYMBOL_GPL(gether_setup_name_default); | 853 | EXPORT_SYMBOL_GPL(gether_setup_name_default); |
diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig index 0875d38476ee..1df4dedffe86 100644 --- a/drivers/usb/gadget/udc/Kconfig +++ b/drivers/usb/gadget/udc/Kconfig | |||
@@ -179,7 +179,7 @@ config USB_R8A66597 | |||
179 | 179 | ||
180 | config USB_RENESAS_USBHS_UDC | 180 | config USB_RENESAS_USBHS_UDC |
181 | tristate 'Renesas USBHS controller' | 181 | tristate 'Renesas USBHS controller' |
182 | depends on USB_RENESAS_USBHS && HAS_DMA | 182 | depends on USB_RENESAS_USBHS |
183 | help | 183 | help |
184 | Renesas USBHS is a discrete USB host and peripheral controller chip | 184 | Renesas USBHS is a discrete USB host and peripheral controller chip |
185 | that supports both full and high speed USB 2.0 data transfers. | 185 | that supports both full and high speed USB 2.0 data transfers. |
@@ -192,7 +192,7 @@ config USB_RENESAS_USBHS_UDC | |||
192 | config USB_RENESAS_USB3 | 192 | config USB_RENESAS_USB3 |
193 | tristate 'Renesas USB3.0 Peripheral controller' | 193 | tristate 'Renesas USB3.0 Peripheral controller' |
194 | depends on ARCH_RENESAS || COMPILE_TEST | 194 | depends on ARCH_RENESAS || COMPILE_TEST |
195 | depends on EXTCON && HAS_DMA | 195 | depends on EXTCON |
196 | help | 196 | help |
197 | Renesas USB3.0 Peripheral controller is a USB peripheral controller | 197 | Renesas USB3.0 Peripheral controller is a USB peripheral controller |
198 | 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. |
@@ -438,6 +438,8 @@ config USB_GADGET_XILINX | |||
438 | dynamically linked module called "udc-xilinx" and force all | 438 | dynamically linked module called "udc-xilinx" and force all |
439 | gadget drivers to also be dynamically linked. | 439 | gadget drivers to also be dynamically linked. |
440 | 440 | ||
441 | source "drivers/usb/gadget/udc/aspeed-vhub/Kconfig" | ||
442 | |||
441 | # | 443 | # |
442 | # LAST -- dummy/emulated controller | 444 | # LAST -- dummy/emulated controller |
443 | # | 445 | # |
diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile index ce865b129fd6..897f648f3cf1 100644 --- a/drivers/usb/gadget/udc/Makefile +++ b/drivers/usb/gadget/udc/Makefile | |||
@@ -39,4 +39,5 @@ obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o | |||
39 | obj-$(CONFIG_USB_GR_UDC) += gr_udc.o | 39 | obj-$(CONFIG_USB_GR_UDC) += gr_udc.o |
40 | obj-$(CONFIG_USB_GADGET_XILINX) += udc-xilinx.o | 40 | obj-$(CONFIG_USB_GADGET_XILINX) += udc-xilinx.o |
41 | obj-$(CONFIG_USB_SNP_UDC_PLAT) += snps_udc_plat.o | 41 | obj-$(CONFIG_USB_SNP_UDC_PLAT) += snps_udc_plat.o |
42 | obj-$(CONFIG_USB_ASPEED_VHUB) += aspeed-vhub/ | ||
42 | obj-$(CONFIG_USB_BDC_UDC) += bdc/ | 43 | obj-$(CONFIG_USB_BDC_UDC) += bdc/ |
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/Kconfig b/drivers/usb/gadget/udc/aspeed-vhub/Kconfig new file mode 100644 index 000000000000..f0cdf89b8503 --- /dev/null +++ b/drivers/usb/gadget/udc/aspeed-vhub/Kconfig | |||
@@ -0,0 +1,7 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0+ | ||
2 | config USB_ASPEED_VHUB | ||
3 | tristate "Aspeed vHub UDC driver" | ||
4 | depends on ARCH_ASPEED || COMPILE_TEST | ||
5 | help | ||
6 | USB peripheral controller for the Aspeed AST2500 family | ||
7 | SoCs supporting the "vHub" functionality and USB2.0 | ||
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/Makefile b/drivers/usb/gadget/udc/aspeed-vhub/Makefile new file mode 100644 index 000000000000..9f3add605f8e --- /dev/null +++ b/drivers/usb/gadget/udc/aspeed-vhub/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0+ | ||
2 | obj-$(CONFIG_USB_ASPEED_VHUB) += aspeed-vhub.o | ||
3 | aspeed-vhub-y := core.o ep0.o epn.o dev.o hub.o | ||
4 | |||
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/core.c b/drivers/usb/gadget/udc/aspeed-vhub/core.c new file mode 100644 index 000000000000..db3628be38c0 --- /dev/null +++ b/drivers/usb/gadget/udc/aspeed-vhub/core.c | |||
@@ -0,0 +1,425 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | /* | ||
3 | * aspeed-vhub -- Driver for Aspeed SoC "vHub" USB gadget | ||
4 | * | ||
5 | * core.c - Top level support | ||
6 | * | ||
7 | * Copyright 2017 IBM Corporation | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/ioport.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/errno.h> | ||
22 | #include <linux/list.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/proc_fs.h> | ||
25 | #include <linux/prefetch.h> | ||
26 | #include <linux/clk.h> | ||
27 | #include <linux/usb/gadget.h> | ||
28 | #include <linux/of.h> | ||
29 | #include <linux/of_gpio.h> | ||
30 | #include <linux/regmap.h> | ||
31 | #include <linux/dma-mapping.h> | ||
32 | |||
33 | #include "vhub.h" | ||
34 | |||
35 | void ast_vhub_done(struct ast_vhub_ep *ep, struct ast_vhub_req *req, | ||
36 | int status) | ||
37 | { | ||
38 | bool internal = req->internal; | ||
39 | |||
40 | EPVDBG(ep, "completing request @%p, status %d\n", req, status); | ||
41 | |||
42 | list_del_init(&req->queue); | ||
43 | |||
44 | if (req->req.status == -EINPROGRESS) | ||
45 | req->req.status = status; | ||
46 | |||
47 | if (req->req.dma) { | ||
48 | if (!WARN_ON(!ep->dev)) | ||
49 | usb_gadget_unmap_request(&ep->dev->gadget, | ||
50 | &req->req, ep->epn.is_in); | ||
51 | req->req.dma = 0; | ||
52 | } | ||
53 | |||
54 | /* | ||
55 | * If this isn't an internal EP0 request, call the core | ||
56 | * to call the gadget completion. | ||
57 | */ | ||
58 | if (!internal) { | ||
59 | spin_unlock(&ep->vhub->lock); | ||
60 | usb_gadget_giveback_request(&ep->ep, &req->req); | ||
61 | spin_lock(&ep->vhub->lock); | ||
62 | } | ||
63 | } | ||
64 | |||
65 | void ast_vhub_nuke(struct ast_vhub_ep *ep, int status) | ||
66 | { | ||
67 | struct ast_vhub_req *req; | ||
68 | |||
69 | EPDBG(ep, "Nuking\n"); | ||
70 | |||
71 | /* Beware, lock will be dropped & req-acquired by done() */ | ||
72 | while (!list_empty(&ep->queue)) { | ||
73 | req = list_first_entry(&ep->queue, struct ast_vhub_req, queue); | ||
74 | ast_vhub_done(ep, req, status); | ||
75 | } | ||
76 | } | ||
77 | |||
78 | struct usb_request *ast_vhub_alloc_request(struct usb_ep *u_ep, | ||
79 | gfp_t gfp_flags) | ||
80 | { | ||
81 | struct ast_vhub_req *req; | ||
82 | |||
83 | req = kzalloc(sizeof(*req), gfp_flags); | ||
84 | if (!req) | ||
85 | return NULL; | ||
86 | return &req->req; | ||
87 | } | ||
88 | |||
89 | void ast_vhub_free_request(struct usb_ep *u_ep, struct usb_request *u_req) | ||
90 | { | ||
91 | struct ast_vhub_req *req = to_ast_req(u_req); | ||
92 | |||
93 | kfree(req); | ||
94 | } | ||
95 | |||
96 | static irqreturn_t ast_vhub_irq(int irq, void *data) | ||
97 | { | ||
98 | struct ast_vhub *vhub = data; | ||
99 | irqreturn_t iret = IRQ_NONE; | ||
100 | u32 istat; | ||
101 | |||
102 | /* Stale interrupt while tearing down */ | ||
103 | if (!vhub->ep0_bufs) | ||
104 | return IRQ_NONE; | ||
105 | |||
106 | spin_lock(&vhub->lock); | ||
107 | |||
108 | /* Read and ACK interrupts */ | ||
109 | istat = readl(vhub->regs + AST_VHUB_ISR); | ||
110 | if (!istat) | ||
111 | goto bail; | ||
112 | writel(istat, vhub->regs + AST_VHUB_ISR); | ||
113 | iret = IRQ_HANDLED; | ||
114 | |||
115 | UDCVDBG(vhub, "irq status=%08x, ep_acks=%08x ep_nacks=%08x\n", | ||
116 | istat, | ||
117 | readl(vhub->regs + AST_VHUB_EP_ACK_ISR), | ||
118 | readl(vhub->regs + AST_VHUB_EP_NACK_ISR)); | ||
119 | |||
120 | /* Handle generic EPs first */ | ||
121 | if (istat & VHUB_IRQ_EP_POOL_ACK_STALL) { | ||
122 | u32 i, ep_acks = readl(vhub->regs + AST_VHUB_EP_ACK_ISR); | ||
123 | writel(ep_acks, vhub->regs + AST_VHUB_EP_ACK_ISR); | ||
124 | |||
125 | for (i = 0; ep_acks && i < AST_VHUB_NUM_GEN_EPs; i++) { | ||
126 | u32 mask = VHUB_EP_IRQ(i); | ||
127 | if (ep_acks & mask) { | ||
128 | ast_vhub_epn_ack_irq(&vhub->epns[i]); | ||
129 | ep_acks &= ~mask; | ||
130 | } | ||
131 | } | ||
132 | } | ||
133 | |||
134 | /* Handle device interrupts */ | ||
135 | if (istat & (VHUB_IRQ_DEVICE1 | | ||
136 | VHUB_IRQ_DEVICE2 | | ||
137 | VHUB_IRQ_DEVICE3 | | ||
138 | VHUB_IRQ_DEVICE4 | | ||
139 | VHUB_IRQ_DEVICE5)) { | ||
140 | if (istat & VHUB_IRQ_DEVICE1) | ||
141 | ast_vhub_dev_irq(&vhub->ports[0].dev); | ||
142 | if (istat & VHUB_IRQ_DEVICE2) | ||
143 | ast_vhub_dev_irq(&vhub->ports[1].dev); | ||
144 | if (istat & VHUB_IRQ_DEVICE3) | ||
145 | ast_vhub_dev_irq(&vhub->ports[2].dev); | ||
146 | if (istat & VHUB_IRQ_DEVICE4) | ||
147 | ast_vhub_dev_irq(&vhub->ports[3].dev); | ||
148 | if (istat & VHUB_IRQ_DEVICE5) | ||
149 | ast_vhub_dev_irq(&vhub->ports[4].dev); | ||
150 | } | ||
151 | |||
152 | /* Handle top-level vHub EP0 interrupts */ | ||
153 | if (istat & (VHUB_IRQ_HUB_EP0_OUT_ACK_STALL | | ||
154 | VHUB_IRQ_HUB_EP0_IN_ACK_STALL | | ||
155 | VHUB_IRQ_HUB_EP0_SETUP)) { | ||
156 | if (istat & VHUB_IRQ_HUB_EP0_IN_ACK_STALL) | ||
157 | ast_vhub_ep0_handle_ack(&vhub->ep0, true); | ||
158 | if (istat & VHUB_IRQ_HUB_EP0_OUT_ACK_STALL) | ||
159 | ast_vhub_ep0_handle_ack(&vhub->ep0, false); | ||
160 | if (istat & VHUB_IRQ_HUB_EP0_SETUP) | ||
161 | ast_vhub_ep0_handle_setup(&vhub->ep0); | ||
162 | } | ||
163 | |||
164 | /* Various top level bus events */ | ||
165 | if (istat & (VHUB_IRQ_BUS_RESUME | | ||
166 | VHUB_IRQ_BUS_SUSPEND | | ||
167 | VHUB_IRQ_BUS_RESET)) { | ||
168 | if (istat & VHUB_IRQ_BUS_RESUME) | ||
169 | ast_vhub_hub_resume(vhub); | ||
170 | if (istat & VHUB_IRQ_BUS_SUSPEND) | ||
171 | ast_vhub_hub_suspend(vhub); | ||
172 | if (istat & VHUB_IRQ_BUS_RESET) | ||
173 | ast_vhub_hub_reset(vhub); | ||
174 | } | ||
175 | |||
176 | bail: | ||
177 | spin_unlock(&vhub->lock); | ||
178 | return iret; | ||
179 | } | ||
180 | |||
181 | void ast_vhub_init_hw(struct ast_vhub *vhub) | ||
182 | { | ||
183 | u32 ctrl; | ||
184 | |||
185 | UDCDBG(vhub,"(Re)Starting HW ...\n"); | ||
186 | |||
187 | /* Enable PHY */ | ||
188 | ctrl = VHUB_CTRL_PHY_CLK | | ||
189 | VHUB_CTRL_PHY_RESET_DIS; | ||
190 | |||
191 | /* | ||
192 | * We do *NOT* set the VHUB_CTRL_CLK_STOP_SUSPEND bit | ||
193 | * to stop the logic clock during suspend because | ||
194 | * it causes the registers to become inaccessible and | ||
195 | * we haven't yet figured out a good wayt to bring the | ||
196 | * controller back into life to issue a wakeup. | ||
197 | */ | ||
198 | |||
199 | /* | ||
200 | * Set some ISO & split control bits according to Aspeed | ||
201 | * recommendation | ||
202 | * | ||
203 | * VHUB_CTRL_ISO_RSP_CTRL: When set tells the HW to respond | ||
204 | * with 0 bytes data packet to ISO IN endpoints when no data | ||
205 | * is available. | ||
206 | * | ||
207 | * VHUB_CTRL_SPLIT_IN: This makes a SOF complete a split IN | ||
208 | * transaction. | ||
209 | */ | ||
210 | ctrl |= VHUB_CTRL_ISO_RSP_CTRL | VHUB_CTRL_SPLIT_IN; | ||
211 | writel(ctrl, vhub->regs + AST_VHUB_CTRL); | ||
212 | udelay(1); | ||
213 | |||
214 | /* Set descriptor ring size */ | ||
215 | if (AST_VHUB_DESCS_COUNT == 256) { | ||
216 | ctrl |= VHUB_CTRL_LONG_DESC; | ||
217 | writel(ctrl, vhub->regs + AST_VHUB_CTRL); | ||
218 | } else { | ||
219 | BUILD_BUG_ON(AST_VHUB_DESCS_COUNT != 32); | ||
220 | } | ||
221 | |||
222 | /* Reset all devices */ | ||
223 | writel(VHUB_SW_RESET_ALL, vhub->regs + AST_VHUB_SW_RESET); | ||
224 | udelay(1); | ||
225 | writel(0, vhub->regs + AST_VHUB_SW_RESET); | ||
226 | |||
227 | /* Disable and cleanup EP ACK/NACK interrupts */ | ||
228 | writel(0, vhub->regs + AST_VHUB_EP_ACK_IER); | ||
229 | writel(0, vhub->regs + AST_VHUB_EP_NACK_IER); | ||
230 | writel(VHUB_EP_IRQ_ALL, vhub->regs + AST_VHUB_EP_ACK_ISR); | ||
231 | writel(VHUB_EP_IRQ_ALL, vhub->regs + AST_VHUB_EP_NACK_ISR); | ||
232 | |||
233 | /* Default settings for EP0, enable HW hub EP1 */ | ||
234 | writel(0, vhub->regs + AST_VHUB_EP0_CTRL); | ||
235 | writel(VHUB_EP1_CTRL_RESET_TOGGLE | | ||
236 | VHUB_EP1_CTRL_ENABLE, | ||
237 | vhub->regs + AST_VHUB_EP1_CTRL); | ||
238 | writel(0, vhub->regs + AST_VHUB_EP1_STS_CHG); | ||
239 | |||
240 | /* Configure EP0 DMA buffer */ | ||
241 | writel(vhub->ep0.buf_dma, vhub->regs + AST_VHUB_EP0_DATA); | ||
242 | |||
243 | /* Clear address */ | ||
244 | writel(0, vhub->regs + AST_VHUB_CONF); | ||
245 | |||
246 | /* Pullup hub (activate on host) */ | ||
247 | if (vhub->force_usb1) | ||
248 | ctrl |= VHUB_CTRL_FULL_SPEED_ONLY; | ||
249 | |||
250 | ctrl |= VHUB_CTRL_UPSTREAM_CONNECT; | ||
251 | writel(ctrl, vhub->regs + AST_VHUB_CTRL); | ||
252 | |||
253 | /* Enable some interrupts */ | ||
254 | writel(VHUB_IRQ_HUB_EP0_IN_ACK_STALL | | ||
255 | VHUB_IRQ_HUB_EP0_OUT_ACK_STALL | | ||
256 | VHUB_IRQ_HUB_EP0_SETUP | | ||
257 | VHUB_IRQ_EP_POOL_ACK_STALL | | ||
258 | VHUB_IRQ_BUS_RESUME | | ||
259 | VHUB_IRQ_BUS_SUSPEND | | ||
260 | VHUB_IRQ_BUS_RESET, | ||
261 | vhub->regs + AST_VHUB_IER); | ||
262 | } | ||
263 | |||
264 | static int ast_vhub_remove(struct platform_device *pdev) | ||
265 | { | ||
266 | struct ast_vhub *vhub = platform_get_drvdata(pdev); | ||
267 | unsigned long flags; | ||
268 | int i; | ||
269 | |||
270 | if (!vhub || !vhub->regs) | ||
271 | return 0; | ||
272 | |||
273 | /* Remove devices */ | ||
274 | for (i = 0; i < AST_VHUB_NUM_PORTS; i++) | ||
275 | ast_vhub_del_dev(&vhub->ports[i].dev); | ||
276 | |||
277 | spin_lock_irqsave(&vhub->lock, flags); | ||
278 | |||
279 | /* Mask & ack all interrupts */ | ||
280 | writel(0, vhub->regs + AST_VHUB_IER); | ||
281 | writel(VHUB_IRQ_ACK_ALL, vhub->regs + AST_VHUB_ISR); | ||
282 | |||
283 | /* Pull device, leave PHY enabled */ | ||
284 | writel(VHUB_CTRL_PHY_CLK | | ||
285 | VHUB_CTRL_PHY_RESET_DIS, | ||
286 | vhub->regs + AST_VHUB_CTRL); | ||
287 | |||
288 | if (vhub->clk) | ||
289 | clk_disable_unprepare(vhub->clk); | ||
290 | |||
291 | spin_unlock_irqrestore(&vhub->lock, flags); | ||
292 | |||
293 | if (vhub->ep0_bufs) | ||
294 | dma_free_coherent(&pdev->dev, | ||
295 | AST_VHUB_EP0_MAX_PACKET * | ||
296 | (AST_VHUB_NUM_PORTS + 1), | ||
297 | vhub->ep0_bufs, | ||
298 | vhub->ep0_bufs_dma); | ||
299 | vhub->ep0_bufs = NULL; | ||
300 | |||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | static int ast_vhub_probe(struct platform_device *pdev) | ||
305 | { | ||
306 | enum usb_device_speed max_speed; | ||
307 | struct ast_vhub *vhub; | ||
308 | struct resource *res; | ||
309 | int i, rc = 0; | ||
310 | |||
311 | vhub = devm_kzalloc(&pdev->dev, sizeof(*vhub), GFP_KERNEL); | ||
312 | if (!vhub) | ||
313 | return -ENOMEM; | ||
314 | |||
315 | spin_lock_init(&vhub->lock); | ||
316 | vhub->pdev = pdev; | ||
317 | |||
318 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
319 | vhub->regs = devm_ioremap_resource(&pdev->dev, res); | ||
320 | if (IS_ERR(vhub->regs)) { | ||
321 | dev_err(&pdev->dev, "Failed to map resources\n"); | ||
322 | return PTR_ERR(vhub->regs); | ||
323 | } | ||
324 | UDCDBG(vhub, "vHub@%pR mapped @%p\n", res, vhub->regs); | ||
325 | |||
326 | platform_set_drvdata(pdev, vhub); | ||
327 | |||
328 | vhub->clk = devm_clk_get(&pdev->dev, NULL); | ||
329 | if (IS_ERR(vhub->clk)) { | ||
330 | rc = PTR_ERR(vhub->clk); | ||
331 | goto err; | ||
332 | } | ||
333 | rc = clk_prepare_enable(vhub->clk); | ||
334 | if (rc) { | ||
335 | dev_err(&pdev->dev, "Error couldn't enable clock (%d)\n", rc); | ||
336 | goto err; | ||
337 | } | ||
338 | |||
339 | /* Check if we need to limit the HW to USB1 */ | ||
340 | max_speed = usb_get_maximum_speed(&pdev->dev); | ||
341 | if (max_speed != USB_SPEED_UNKNOWN && max_speed < USB_SPEED_HIGH) | ||
342 | vhub->force_usb1 = true; | ||
343 | |||
344 | /* Mask & ack all interrupts before installing the handler */ | ||
345 | writel(0, vhub->regs + AST_VHUB_IER); | ||
346 | writel(VHUB_IRQ_ACK_ALL, vhub->regs + AST_VHUB_ISR); | ||
347 | |||
348 | /* Find interrupt and install handler */ | ||
349 | vhub->irq = platform_get_irq(pdev, 0); | ||
350 | if (vhub->irq < 0) { | ||
351 | dev_err(&pdev->dev, "Failed to get interrupt\n"); | ||
352 | rc = vhub->irq; | ||
353 | goto err; | ||
354 | } | ||
355 | rc = devm_request_irq(&pdev->dev, vhub->irq, ast_vhub_irq, 0, | ||
356 | KBUILD_MODNAME, vhub); | ||
357 | if (rc) { | ||
358 | dev_err(&pdev->dev, "Failed to request interrupt\n"); | ||
359 | goto err; | ||
360 | } | ||
361 | |||
362 | /* | ||
363 | * Allocate DMA buffers for all EP0s in one chunk, | ||
364 | * one per port and one for the vHub itself | ||
365 | */ | ||
366 | vhub->ep0_bufs = dma_alloc_coherent(&pdev->dev, | ||
367 | AST_VHUB_EP0_MAX_PACKET * | ||
368 | (AST_VHUB_NUM_PORTS + 1), | ||
369 | &vhub->ep0_bufs_dma, GFP_KERNEL); | ||
370 | if (!vhub->ep0_bufs) { | ||
371 | dev_err(&pdev->dev, "Failed to allocate EP0 DMA buffers\n"); | ||
372 | rc = -ENOMEM; | ||
373 | goto err; | ||
374 | } | ||
375 | UDCVDBG(vhub, "EP0 DMA buffers @%p (DMA 0x%08x)\n", | ||
376 | vhub->ep0_bufs, (u32)vhub->ep0_bufs_dma); | ||
377 | |||
378 | /* Init vHub EP0 */ | ||
379 | ast_vhub_init_ep0(vhub, &vhub->ep0, NULL); | ||
380 | |||
381 | /* Init devices */ | ||
382 | for (i = 0; i < AST_VHUB_NUM_PORTS && rc == 0; i++) | ||
383 | rc = ast_vhub_init_dev(vhub, i); | ||
384 | if (rc) | ||
385 | goto err; | ||
386 | |||
387 | /* Init hub emulation */ | ||
388 | ast_vhub_init_hub(vhub); | ||
389 | |||
390 | /* Initialize HW */ | ||
391 | ast_vhub_init_hw(vhub); | ||
392 | |||
393 | dev_info(&pdev->dev, "Initialized virtual hub in USB%d mode\n", | ||
394 | vhub->force_usb1 ? 1 : 2); | ||
395 | |||
396 | return 0; | ||
397 | err: | ||
398 | ast_vhub_remove(pdev); | ||
399 | return rc; | ||
400 | } | ||
401 | |||
402 | static const struct of_device_id ast_vhub_dt_ids[] = { | ||
403 | { | ||
404 | .compatible = "aspeed,ast2400-usb-vhub", | ||
405 | }, | ||
406 | { | ||
407 | .compatible = "aspeed,ast2500-usb-vhub", | ||
408 | }, | ||
409 | { } | ||
410 | }; | ||
411 | MODULE_DEVICE_TABLE(of, ast_vhub_dt_ids); | ||
412 | |||
413 | static struct platform_driver ast_vhub_driver = { | ||
414 | .probe = ast_vhub_probe, | ||
415 | .remove = ast_vhub_remove, | ||
416 | .driver = { | ||
417 | .name = KBUILD_MODNAME, | ||
418 | .of_match_table = ast_vhub_dt_ids, | ||
419 | }, | ||
420 | }; | ||
421 | module_platform_driver(ast_vhub_driver); | ||
422 | |||
423 | MODULE_DESCRIPTION("Aspeed vHub udc driver"); | ||
424 | MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>"); | ||
425 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/dev.c b/drivers/usb/gadget/udc/aspeed-vhub/dev.c new file mode 100644 index 000000000000..f0233912bace --- /dev/null +++ b/drivers/usb/gadget/udc/aspeed-vhub/dev.c | |||
@@ -0,0 +1,589 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | /* | ||
3 | * aspeed-vhub -- Driver for Aspeed SoC "vHub" USB gadget | ||
4 | * | ||
5 | * dev.c - Individual device/gadget management (ie, a port = a gadget) | ||
6 | * | ||
7 | * Copyright 2017 IBM Corporation | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/ioport.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/errno.h> | ||
22 | #include <linux/list.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/proc_fs.h> | ||
25 | #include <linux/prefetch.h> | ||
26 | #include <linux/clk.h> | ||
27 | #include <linux/usb/gadget.h> | ||
28 | #include <linux/of.h> | ||
29 | #include <linux/of_gpio.h> | ||
30 | #include <linux/regmap.h> | ||
31 | #include <linux/dma-mapping.h> | ||
32 | #include <linux/usb.h> | ||
33 | #include <linux/usb/hcd.h> | ||
34 | |||
35 | #include "vhub.h" | ||
36 | |||
37 | void ast_vhub_dev_irq(struct ast_vhub_dev *d) | ||
38 | { | ||
39 | u32 istat = readl(d->regs + AST_VHUB_DEV_ISR); | ||
40 | |||
41 | writel(istat, d->regs + AST_VHUB_DEV_ISR); | ||
42 | |||
43 | if (istat & VHUV_DEV_IRQ_EP0_IN_ACK_STALL) | ||
44 | ast_vhub_ep0_handle_ack(&d->ep0, true); | ||
45 | if (istat & VHUV_DEV_IRQ_EP0_OUT_ACK_STALL) | ||
46 | ast_vhub_ep0_handle_ack(&d->ep0, false); | ||
47 | if (istat & VHUV_DEV_IRQ_EP0_SETUP) | ||
48 | ast_vhub_ep0_handle_setup(&d->ep0); | ||
49 | } | ||
50 | |||
51 | static void ast_vhub_dev_enable(struct ast_vhub_dev *d) | ||
52 | { | ||
53 | u32 reg, hmsk; | ||
54 | |||
55 | if (d->enabled) | ||
56 | return; | ||
57 | |||
58 | /* Enable device and its EP0 interrupts */ | ||
59 | reg = VHUB_DEV_EN_ENABLE_PORT | | ||
60 | VHUB_DEV_EN_EP0_IN_ACK_IRQEN | | ||
61 | VHUB_DEV_EN_EP0_OUT_ACK_IRQEN | | ||
62 | VHUB_DEV_EN_EP0_SETUP_IRQEN; | ||
63 | if (d->gadget.speed == USB_SPEED_HIGH) | ||
64 | reg |= VHUB_DEV_EN_SPEED_SEL_HIGH; | ||
65 | writel(reg, d->regs + AST_VHUB_DEV_EN_CTRL); | ||
66 | |||
67 | /* Enable device interrupt in the hub as well */ | ||
68 | hmsk = VHUB_IRQ_DEVICE1 << d->index; | ||
69 | reg = readl(d->vhub->regs + AST_VHUB_IER); | ||
70 | reg |= hmsk; | ||
71 | writel(reg, d->vhub->regs + AST_VHUB_IER); | ||
72 | |||
73 | /* Set EP0 DMA buffer address */ | ||
74 | writel(d->ep0.buf_dma, d->regs + AST_VHUB_DEV_EP0_DATA); | ||
75 | |||
76 | d->enabled = true; | ||
77 | } | ||
78 | |||
79 | static void ast_vhub_dev_disable(struct ast_vhub_dev *d) | ||
80 | { | ||
81 | u32 reg, hmsk; | ||
82 | |||
83 | if (!d->enabled) | ||
84 | return; | ||
85 | |||
86 | /* Disable device interrupt in the hub */ | ||
87 | hmsk = VHUB_IRQ_DEVICE1 << d->index; | ||
88 | reg = readl(d->vhub->regs + AST_VHUB_IER); | ||
89 | reg &= ~hmsk; | ||
90 | writel(reg, d->vhub->regs + AST_VHUB_IER); | ||
91 | |||
92 | /* Then disable device */ | ||
93 | writel(0, d->regs + AST_VHUB_DEV_EN_CTRL); | ||
94 | d->gadget.speed = USB_SPEED_UNKNOWN; | ||
95 | d->enabled = false; | ||
96 | d->suspended = false; | ||
97 | } | ||
98 | |||
99 | static int ast_vhub_dev_feature(struct ast_vhub_dev *d, | ||
100 | u16 wIndex, u16 wValue, | ||
101 | bool is_set) | ||
102 | { | ||
103 | DDBG(d, "%s_FEATURE(dev val=%02x)\n", | ||
104 | is_set ? "SET" : "CLEAR", wValue); | ||
105 | |||
106 | if (wValue != USB_DEVICE_REMOTE_WAKEUP) | ||
107 | return std_req_driver; | ||
108 | |||
109 | d->wakeup_en = is_set; | ||
110 | |||
111 | return std_req_complete; | ||
112 | } | ||
113 | |||
114 | static int ast_vhub_ep_feature(struct ast_vhub_dev *d, | ||
115 | u16 wIndex, u16 wValue, bool is_set) | ||
116 | { | ||
117 | struct ast_vhub_ep *ep; | ||
118 | int ep_num; | ||
119 | |||
120 | ep_num = wIndex & USB_ENDPOINT_NUMBER_MASK; | ||
121 | DDBG(d, "%s_FEATURE(ep%d val=%02x)\n", | ||
122 | is_set ? "SET" : "CLEAR", ep_num, wValue); | ||
123 | if (ep_num == 0) | ||
124 | return std_req_complete; | ||
125 | if (ep_num >= AST_VHUB_NUM_GEN_EPs || !d->epns[ep_num - 1]) | ||
126 | return std_req_stall; | ||
127 | if (wValue != USB_ENDPOINT_HALT) | ||
128 | return std_req_driver; | ||
129 | |||
130 | ep = d->epns[ep_num - 1]; | ||
131 | if (WARN_ON(!ep)) | ||
132 | return std_req_stall; | ||
133 | |||
134 | if (!ep->epn.enabled || !ep->ep.desc || ep->epn.is_iso || | ||
135 | ep->epn.is_in != !!(wIndex & USB_DIR_IN)) | ||
136 | return std_req_stall; | ||
137 | |||
138 | DDBG(d, "%s stall on EP %d\n", | ||
139 | is_set ? "setting" : "clearing", ep_num); | ||
140 | ep->epn.stalled = is_set; | ||
141 | ast_vhub_update_epn_stall(ep); | ||
142 | |||
143 | return std_req_complete; | ||
144 | } | ||
145 | |||
146 | static int ast_vhub_dev_status(struct ast_vhub_dev *d, | ||
147 | u16 wIndex, u16 wValue) | ||
148 | { | ||
149 | u8 st0; | ||
150 | |||
151 | DDBG(d, "GET_STATUS(dev)\n"); | ||
152 | |||
153 | st0 = d->gadget.is_selfpowered << USB_DEVICE_SELF_POWERED; | ||
154 | if (d->wakeup_en) | ||
155 | st0 |= 1 << USB_DEVICE_REMOTE_WAKEUP; | ||
156 | |||
157 | return ast_vhub_simple_reply(&d->ep0, st0, 0); | ||
158 | } | ||
159 | |||
160 | static int ast_vhub_ep_status(struct ast_vhub_dev *d, | ||
161 | u16 wIndex, u16 wValue) | ||
162 | { | ||
163 | int ep_num = wIndex & USB_ENDPOINT_NUMBER_MASK; | ||
164 | struct ast_vhub_ep *ep; | ||
165 | u8 st0 = 0; | ||
166 | |||
167 | DDBG(d, "GET_STATUS(ep%d)\n", ep_num); | ||
168 | |||
169 | if (ep_num >= AST_VHUB_NUM_GEN_EPs) | ||
170 | return std_req_stall; | ||
171 | if (ep_num != 0) { | ||
172 | ep = d->epns[ep_num - 1]; | ||
173 | if (!ep) | ||
174 | return std_req_stall; | ||
175 | if (!ep->epn.enabled || !ep->ep.desc || ep->epn.is_iso || | ||
176 | ep->epn.is_in != !!(wIndex & USB_DIR_IN)) | ||
177 | return std_req_stall; | ||
178 | if (ep->epn.stalled) | ||
179 | st0 |= 1 << USB_ENDPOINT_HALT; | ||
180 | } | ||
181 | |||
182 | return ast_vhub_simple_reply(&d->ep0, st0, 0); | ||
183 | } | ||
184 | |||
185 | static void ast_vhub_dev_set_address(struct ast_vhub_dev *d, u8 addr) | ||
186 | { | ||
187 | u32 reg; | ||
188 | |||
189 | DDBG(d, "SET_ADDRESS: Got address %x\n", addr); | ||
190 | |||
191 | reg = readl(d->regs + AST_VHUB_DEV_EN_CTRL); | ||
192 | reg &= ~VHUB_DEV_EN_ADDR_MASK; | ||
193 | reg |= VHUB_DEV_EN_SET_ADDR(addr); | ||
194 | writel(reg, d->regs + AST_VHUB_DEV_EN_CTRL); | ||
195 | } | ||
196 | |||
197 | int ast_vhub_std_dev_request(struct ast_vhub_ep *ep, | ||
198 | struct usb_ctrlrequest *crq) | ||
199 | { | ||
200 | struct ast_vhub_dev *d = ep->dev; | ||
201 | u16 wValue, wIndex; | ||
202 | |||
203 | /* No driver, we shouldn't be enabled ... */ | ||
204 | if (!d->driver || !d->enabled || d->suspended) { | ||
205 | EPDBG(ep, | ||
206 | "Device is wrong state driver=%p enabled=%d" | ||
207 | " suspended=%d\n", | ||
208 | d->driver, d->enabled, d->suspended); | ||
209 | return std_req_stall; | ||
210 | } | ||
211 | |||
212 | /* First packet, grab speed */ | ||
213 | if (d->gadget.speed == USB_SPEED_UNKNOWN) { | ||
214 | d->gadget.speed = ep->vhub->speed; | ||
215 | if (d->gadget.speed > d->driver->max_speed) | ||
216 | d->gadget.speed = d->driver->max_speed; | ||
217 | DDBG(d, "fist packet, captured speed %d\n", | ||
218 | d->gadget.speed); | ||
219 | } | ||
220 | |||
221 | wValue = le16_to_cpu(crq->wValue); | ||
222 | wIndex = le16_to_cpu(crq->wIndex); | ||
223 | |||
224 | switch ((crq->bRequestType << 8) | crq->bRequest) { | ||
225 | /* SET_ADDRESS */ | ||
226 | case DeviceOutRequest | USB_REQ_SET_ADDRESS: | ||
227 | ast_vhub_dev_set_address(d, wValue); | ||
228 | return std_req_complete; | ||
229 | |||
230 | /* GET_STATUS */ | ||
231 | case DeviceRequest | USB_REQ_GET_STATUS: | ||
232 | return ast_vhub_dev_status(d, wIndex, wValue); | ||
233 | case InterfaceRequest | USB_REQ_GET_STATUS: | ||
234 | return ast_vhub_simple_reply(ep, 0, 0); | ||
235 | case EndpointRequest | USB_REQ_GET_STATUS: | ||
236 | return ast_vhub_ep_status(d, wIndex, wValue); | ||
237 | |||
238 | /* SET/CLEAR_FEATURE */ | ||
239 | case DeviceOutRequest | USB_REQ_SET_FEATURE: | ||
240 | return ast_vhub_dev_feature(d, wIndex, wValue, true); | ||
241 | case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: | ||
242 | return ast_vhub_dev_feature(d, wIndex, wValue, false); | ||
243 | case EndpointOutRequest | USB_REQ_SET_FEATURE: | ||
244 | return ast_vhub_ep_feature(d, wIndex, wValue, true); | ||
245 | case EndpointOutRequest | USB_REQ_CLEAR_FEATURE: | ||
246 | return ast_vhub_ep_feature(d, wIndex, wValue, false); | ||
247 | } | ||
248 | return std_req_driver; | ||
249 | } | ||
250 | |||
251 | static int ast_vhub_udc_wakeup(struct usb_gadget* gadget) | ||
252 | { | ||
253 | struct ast_vhub_dev *d = to_ast_dev(gadget); | ||
254 | unsigned long flags; | ||
255 | int rc = -EINVAL; | ||
256 | |||
257 | spin_lock_irqsave(&d->vhub->lock, flags); | ||
258 | if (!d->wakeup_en) | ||
259 | goto err; | ||
260 | |||
261 | DDBG(d, "Device initiated wakeup\n"); | ||
262 | |||
263 | /* Wakeup the host */ | ||
264 | ast_vhub_hub_wake_all(d->vhub); | ||
265 | rc = 0; | ||
266 | err: | ||
267 | spin_unlock_irqrestore(&d->vhub->lock, flags); | ||
268 | return rc; | ||
269 | } | ||
270 | |||
271 | static int ast_vhub_udc_get_frame(struct usb_gadget* gadget) | ||
272 | { | ||
273 | struct ast_vhub_dev *d = to_ast_dev(gadget); | ||
274 | |||
275 | return (readl(d->vhub->regs + AST_VHUB_USBSTS) >> 16) & 0x7ff; | ||
276 | } | ||
277 | |||
278 | static void ast_vhub_dev_nuke(struct ast_vhub_dev *d) | ||
279 | { | ||
280 | unsigned int i; | ||
281 | |||
282 | for (i = 0; i < AST_VHUB_NUM_GEN_EPs; i++) { | ||
283 | if (!d->epns[i]) | ||
284 | continue; | ||
285 | ast_vhub_nuke(d->epns[i], -ESHUTDOWN); | ||
286 | } | ||
287 | } | ||
288 | |||
289 | static int ast_vhub_udc_pullup(struct usb_gadget* gadget, int on) | ||
290 | { | ||
291 | struct ast_vhub_dev *d = to_ast_dev(gadget); | ||
292 | unsigned long flags; | ||
293 | |||
294 | spin_lock_irqsave(&d->vhub->lock, flags); | ||
295 | |||
296 | DDBG(d, "pullup(%d)\n", on); | ||
297 | |||
298 | /* Mark disconnected in the hub */ | ||
299 | ast_vhub_device_connect(d->vhub, d->index, on); | ||
300 | |||
301 | /* | ||
302 | * If enabled, nuke all requests if any (there shouldn't be) | ||
303 | * and disable the port. This will clear the address too. | ||
304 | */ | ||
305 | if (d->enabled) { | ||
306 | ast_vhub_dev_nuke(d); | ||
307 | ast_vhub_dev_disable(d); | ||
308 | } | ||
309 | |||
310 | spin_unlock_irqrestore(&d->vhub->lock, flags); | ||
311 | |||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | static int ast_vhub_udc_start(struct usb_gadget *gadget, | ||
316 | struct usb_gadget_driver *driver) | ||
317 | { | ||
318 | struct ast_vhub_dev *d = to_ast_dev(gadget); | ||
319 | unsigned long flags; | ||
320 | |||
321 | spin_lock_irqsave(&d->vhub->lock, flags); | ||
322 | |||
323 | DDBG(d, "start\n"); | ||
324 | |||
325 | /* We don't do much more until the hub enables us */ | ||
326 | d->driver = driver; | ||
327 | d->gadget.is_selfpowered = 1; | ||
328 | |||
329 | spin_unlock_irqrestore(&d->vhub->lock, flags); | ||
330 | |||
331 | return 0; | ||
332 | } | ||
333 | |||
334 | static struct usb_ep *ast_vhub_udc_match_ep(struct usb_gadget *gadget, | ||
335 | struct usb_endpoint_descriptor *desc, | ||
336 | struct usb_ss_ep_comp_descriptor *ss) | ||
337 | { | ||
338 | struct ast_vhub_dev *d = to_ast_dev(gadget); | ||
339 | struct ast_vhub_ep *ep; | ||
340 | struct usb_ep *u_ep; | ||
341 | unsigned int max, addr, i; | ||
342 | |||
343 | DDBG(d, "Match EP type %d\n", usb_endpoint_type(desc)); | ||
344 | |||
345 | /* | ||
346 | * First we need to look for an existing unclaimed EP as another | ||
347 | * configuration may have already associated a bunch of EPs with | ||
348 | * this gadget. This duplicates the code in usb_ep_autoconfig_ss() | ||
349 | * unfortunately. | ||
350 | */ | ||
351 | list_for_each_entry(u_ep, &gadget->ep_list, ep_list) { | ||
352 | if (usb_gadget_ep_match_desc(gadget, u_ep, desc, ss)) { | ||
353 | DDBG(d, " -> using existing EP%d\n", | ||
354 | to_ast_ep(u_ep)->d_idx); | ||
355 | return u_ep; | ||
356 | } | ||
357 | } | ||
358 | |||
359 | /* | ||
360 | * We didn't find one, we need to grab one from the pool. | ||
361 | * | ||
362 | * First let's do some sanity checking | ||
363 | */ | ||
364 | switch(usb_endpoint_type(desc)) { | ||
365 | case USB_ENDPOINT_XFER_CONTROL: | ||
366 | /* Only EP0 can be a control endpoint */ | ||
367 | return NULL; | ||
368 | case USB_ENDPOINT_XFER_ISOC: | ||
369 | /* ISO: limit 1023 bytes full speed, 1024 high/super speed */ | ||
370 | if (gadget_is_dualspeed(gadget)) | ||
371 | max = 1024; | ||
372 | else | ||
373 | max = 1023; | ||
374 | break; | ||
375 | case USB_ENDPOINT_XFER_BULK: | ||
376 | if (gadget_is_dualspeed(gadget)) | ||
377 | max = 512; | ||
378 | else | ||
379 | max = 64; | ||
380 | break; | ||
381 | case USB_ENDPOINT_XFER_INT: | ||
382 | if (gadget_is_dualspeed(gadget)) | ||
383 | max = 1024; | ||
384 | else | ||
385 | max = 64; | ||
386 | break; | ||
387 | } | ||
388 | if (usb_endpoint_maxp(desc) > max) | ||
389 | return NULL; | ||
390 | |||
391 | /* | ||
392 | * Find a free EP address for that device. We can't | ||
393 | * let the generic code assign these as it would | ||
394 | * create overlapping numbers for IN and OUT which | ||
395 | * we don't support, so also create a suitable name | ||
396 | * that will allow the generic code to use our | ||
397 | * assigned address. | ||
398 | */ | ||
399 | for (i = 0; i < AST_VHUB_NUM_GEN_EPs; i++) | ||
400 | if (d->epns[i] == NULL) | ||
401 | break; | ||
402 | if (i >= AST_VHUB_NUM_GEN_EPs) | ||
403 | return NULL; | ||
404 | addr = i + 1; | ||
405 | |||
406 | /* | ||
407 | * Now grab an EP from the shared pool and associate | ||
408 | * it with our device | ||
409 | */ | ||
410 | ep = ast_vhub_alloc_epn(d, addr); | ||
411 | if (!ep) | ||
412 | return NULL; | ||
413 | DDBG(d, "Allocated epn#%d for port EP%d\n", | ||
414 | ep->epn.g_idx, addr); | ||
415 | |||
416 | return &ep->ep; | ||
417 | } | ||
418 | |||
419 | static int ast_vhub_udc_stop(struct usb_gadget *gadget) | ||
420 | { | ||
421 | struct ast_vhub_dev *d = to_ast_dev(gadget); | ||
422 | unsigned long flags; | ||
423 | |||
424 | spin_lock_irqsave(&d->vhub->lock, flags); | ||
425 | |||
426 | DDBG(d, "stop\n"); | ||
427 | |||
428 | d->driver = NULL; | ||
429 | d->gadget.speed = USB_SPEED_UNKNOWN; | ||
430 | |||
431 | ast_vhub_dev_nuke(d); | ||
432 | |||
433 | if (d->enabled) | ||
434 | ast_vhub_dev_disable(d); | ||
435 | |||
436 | spin_unlock_irqrestore(&d->vhub->lock, flags); | ||
437 | |||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | static struct usb_gadget_ops ast_vhub_udc_ops = { | ||
442 | .get_frame = ast_vhub_udc_get_frame, | ||
443 | .wakeup = ast_vhub_udc_wakeup, | ||
444 | .pullup = ast_vhub_udc_pullup, | ||
445 | .udc_start = ast_vhub_udc_start, | ||
446 | .udc_stop = ast_vhub_udc_stop, | ||
447 | .match_ep = ast_vhub_udc_match_ep, | ||
448 | }; | ||
449 | |||
450 | void ast_vhub_dev_suspend(struct ast_vhub_dev *d) | ||
451 | { | ||
452 | d->suspended = true; | ||
453 | if (d->driver) { | ||
454 | spin_unlock(&d->vhub->lock); | ||
455 | d->driver->suspend(&d->gadget); | ||
456 | spin_lock(&d->vhub->lock); | ||
457 | } | ||
458 | } | ||
459 | |||
460 | void ast_vhub_dev_resume(struct ast_vhub_dev *d) | ||
461 | { | ||
462 | d->suspended = false; | ||
463 | if (d->driver) { | ||
464 | spin_unlock(&d->vhub->lock); | ||
465 | d->driver->resume(&d->gadget); | ||
466 | spin_lock(&d->vhub->lock); | ||
467 | } | ||
468 | } | ||
469 | |||
470 | void ast_vhub_dev_reset(struct ast_vhub_dev *d) | ||
471 | { | ||
472 | /* | ||
473 | * If speed is not set, we enable the port. If it is, | ||
474 | * send reset to the gadget and reset "speed". | ||
475 | * | ||
476 | * Speed is an indication that we have got the first | ||
477 | * setup packet to the device. | ||
478 | */ | ||
479 | if (d->gadget.speed == USB_SPEED_UNKNOWN && !d->enabled) { | ||
480 | DDBG(d, "Reset at unknown speed of disabled device, enabling...\n"); | ||
481 | ast_vhub_dev_enable(d); | ||
482 | d->suspended = false; | ||
483 | } | ||
484 | if (d->gadget.speed != USB_SPEED_UNKNOWN && d->driver) { | ||
485 | unsigned int i; | ||
486 | |||
487 | DDBG(d, "Reset at known speed of bound device, resetting...\n"); | ||
488 | spin_unlock(&d->vhub->lock); | ||
489 | d->driver->reset(&d->gadget); | ||
490 | spin_lock(&d->vhub->lock); | ||
491 | |||
492 | /* | ||
493 | * Disable/re-enable HW, this will clear the address | ||
494 | * and speed setting. | ||
495 | */ | ||
496 | ast_vhub_dev_disable(d); | ||
497 | ast_vhub_dev_enable(d); | ||
498 | |||
499 | /* Clear stall on all EPs */ | ||
500 | for (i = 0; i < AST_VHUB_NUM_GEN_EPs; i++) { | ||
501 | struct ast_vhub_ep *ep = d->epns[i]; | ||
502 | |||
503 | if (ep && ep->epn.stalled) { | ||
504 | ep->epn.stalled = false; | ||
505 | ast_vhub_update_epn_stall(ep); | ||
506 | } | ||
507 | } | ||
508 | |||
509 | /* Additional cleanups */ | ||
510 | d->wakeup_en = false; | ||
511 | d->suspended = false; | ||
512 | } | ||
513 | } | ||
514 | |||
515 | void ast_vhub_del_dev(struct ast_vhub_dev *d) | ||
516 | { | ||
517 | unsigned long flags; | ||
518 | |||
519 | spin_lock_irqsave(&d->vhub->lock, flags); | ||
520 | if (!d->registered) { | ||
521 | spin_unlock_irqrestore(&d->vhub->lock, flags); | ||
522 | return; | ||
523 | } | ||
524 | d->registered = false; | ||
525 | spin_unlock_irqrestore(&d->vhub->lock, flags); | ||
526 | |||
527 | usb_del_gadget_udc(&d->gadget); | ||
528 | device_unregister(d->port_dev); | ||
529 | } | ||
530 | |||
531 | static void ast_vhub_dev_release(struct device *dev) | ||
532 | { | ||
533 | kfree(dev); | ||
534 | } | ||
535 | |||
536 | int ast_vhub_init_dev(struct ast_vhub *vhub, unsigned int idx) | ||
537 | { | ||
538 | struct ast_vhub_dev *d = &vhub->ports[idx].dev; | ||
539 | struct device *parent = &vhub->pdev->dev; | ||
540 | int rc; | ||
541 | |||
542 | d->vhub = vhub; | ||
543 | d->index = idx; | ||
544 | d->name = devm_kasprintf(parent, GFP_KERNEL, "port%d", idx+1); | ||
545 | d->regs = vhub->regs + 0x100 + 0x10 * idx; | ||
546 | |||
547 | ast_vhub_init_ep0(vhub, &d->ep0, d); | ||
548 | |||
549 | /* | ||
550 | * The UDC core really needs us to have separate and uniquely | ||
551 | * named "parent" devices for each port so we create a sub device | ||
552 | * here for that purpose | ||
553 | */ | ||
554 | d->port_dev = kzalloc(sizeof(struct device), GFP_KERNEL); | ||
555 | if (!d->port_dev) | ||
556 | return -ENOMEM; | ||
557 | device_initialize(d->port_dev); | ||
558 | d->port_dev->release = ast_vhub_dev_release; | ||
559 | d->port_dev->parent = parent; | ||
560 | dev_set_name(d->port_dev, "%s:p%d", dev_name(parent), idx + 1); | ||
561 | rc = device_add(d->port_dev); | ||
562 | if (rc) | ||
563 | goto fail_add; | ||
564 | |||
565 | /* Populate gadget */ | ||
566 | INIT_LIST_HEAD(&d->gadget.ep_list); | ||
567 | d->gadget.ops = &ast_vhub_udc_ops; | ||
568 | d->gadget.ep0 = &d->ep0.ep; | ||
569 | d->gadget.name = KBUILD_MODNAME; | ||
570 | if (vhub->force_usb1) | ||
571 | d->gadget.max_speed = USB_SPEED_FULL; | ||
572 | else | ||
573 | d->gadget.max_speed = USB_SPEED_HIGH; | ||
574 | d->gadget.speed = USB_SPEED_UNKNOWN; | ||
575 | d->gadget.dev.of_node = vhub->pdev->dev.of_node; | ||
576 | |||
577 | rc = usb_add_gadget_udc(d->port_dev, &d->gadget); | ||
578 | if (rc != 0) | ||
579 | goto fail_udc; | ||
580 | d->registered = true; | ||
581 | |||
582 | return 0; | ||
583 | fail_udc: | ||
584 | device_del(d->port_dev); | ||
585 | fail_add: | ||
586 | put_device(d->port_dev); | ||
587 | |||
588 | return rc; | ||
589 | } | ||
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/ep0.c b/drivers/usb/gadget/udc/aspeed-vhub/ep0.c new file mode 100644 index 000000000000..20ffb03ff6ac --- /dev/null +++ b/drivers/usb/gadget/udc/aspeed-vhub/ep0.c | |||
@@ -0,0 +1,486 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | /* | ||
3 | * aspeed-vhub -- Driver for Aspeed SoC "vHub" USB gadget | ||
4 | * | ||
5 | * ep0.c - Endpoint 0 handling | ||
6 | * | ||
7 | * Copyright 2017 IBM Corporation | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/ioport.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/errno.h> | ||
22 | #include <linux/list.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/proc_fs.h> | ||
25 | #include <linux/prefetch.h> | ||
26 | #include <linux/clk.h> | ||
27 | #include <linux/usb/gadget.h> | ||
28 | #include <linux/of.h> | ||
29 | #include <linux/of_gpio.h> | ||
30 | #include <linux/regmap.h> | ||
31 | #include <linux/dma-mapping.h> | ||
32 | |||
33 | #include "vhub.h" | ||
34 | |||
35 | int ast_vhub_reply(struct ast_vhub_ep *ep, char *ptr, int len) | ||
36 | { | ||
37 | struct usb_request *req = &ep->ep0.req.req; | ||
38 | int rc; | ||
39 | |||
40 | if (WARN_ON(ep->d_idx != 0)) | ||
41 | return std_req_stall; | ||
42 | if (WARN_ON(!ep->ep0.dir_in)) | ||
43 | return std_req_stall; | ||
44 | if (WARN_ON(len > AST_VHUB_EP0_MAX_PACKET)) | ||
45 | return std_req_stall; | ||
46 | if (WARN_ON(req->status == -EINPROGRESS)) | ||
47 | return std_req_stall; | ||
48 | |||
49 | req->buf = ptr; | ||
50 | req->length = len; | ||
51 | req->complete = NULL; | ||
52 | req->zero = true; | ||
53 | |||
54 | /* | ||
55 | * Call internal queue directly after dropping the lock. This is | ||
56 | * safe to do as the reply is always the last thing done when | ||
57 | * processing a SETUP packet, usually as a tail call | ||
58 | */ | ||
59 | spin_unlock(&ep->vhub->lock); | ||
60 | if (ep->ep.ops->queue(&ep->ep, req, GFP_ATOMIC)) | ||
61 | rc = std_req_stall; | ||
62 | else | ||
63 | rc = std_req_data; | ||
64 | spin_lock(&ep->vhub->lock); | ||
65 | return rc; | ||
66 | } | ||
67 | |||
68 | int __ast_vhub_simple_reply(struct ast_vhub_ep *ep, int len, ...) | ||
69 | { | ||
70 | u8 *buffer = ep->buf; | ||
71 | unsigned int i; | ||
72 | va_list args; | ||
73 | |||
74 | va_start(args, len); | ||
75 | |||
76 | /* Copy data directly into EP buffer */ | ||
77 | for (i = 0; i < len; i++) | ||
78 | buffer[i] = va_arg(args, int); | ||
79 | va_end(args); | ||
80 | |||
81 | /* req->buf NULL means data is already there */ | ||
82 | return ast_vhub_reply(ep, NULL, len); | ||
83 | } | ||
84 | |||
85 | void ast_vhub_ep0_handle_setup(struct ast_vhub_ep *ep) | ||
86 | { | ||
87 | struct usb_ctrlrequest crq; | ||
88 | enum std_req_rc std_req_rc; | ||
89 | int rc = -ENODEV; | ||
90 | |||
91 | if (WARN_ON(ep->d_idx != 0)) | ||
92 | return; | ||
93 | |||
94 | /* | ||
95 | * Grab the setup packet from the chip and byteswap | ||
96 | * interesting fields | ||
97 | */ | ||
98 | memcpy_fromio(&crq, ep->ep0.setup, sizeof(crq)); | ||
99 | |||
100 | EPDBG(ep, "SETUP packet %02x/%02x/%04x/%04x/%04x [%s] st=%d\n", | ||
101 | crq.bRequestType, crq.bRequest, | ||
102 | le16_to_cpu(crq.wValue), | ||
103 | le16_to_cpu(crq.wIndex), | ||
104 | le16_to_cpu(crq.wLength), | ||
105 | (crq.bRequestType & USB_DIR_IN) ? "in" : "out", | ||
106 | ep->ep0.state); | ||
107 | |||
108 | /* Check our state, cancel pending requests if needed */ | ||
109 | if (ep->ep0.state != ep0_state_token) { | ||
110 | EPDBG(ep, "wrong state\n"); | ||
111 | ast_vhub_nuke(ep, 0); | ||
112 | goto stall; | ||
113 | } | ||
114 | |||
115 | /* Calculate next state for EP0 */ | ||
116 | ep->ep0.state = ep0_state_data; | ||
117 | ep->ep0.dir_in = !!(crq.bRequestType & USB_DIR_IN); | ||
118 | |||
119 | /* If this is the vHub, we handle requests differently */ | ||
120 | std_req_rc = std_req_driver; | ||
121 | if (ep->dev == NULL) { | ||
122 | if ((crq.bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) | ||
123 | std_req_rc = ast_vhub_std_hub_request(ep, &crq); | ||
124 | else if ((crq.bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS) | ||
125 | std_req_rc = ast_vhub_class_hub_request(ep, &crq); | ||
126 | else | ||
127 | std_req_rc = std_req_stall; | ||
128 | } else if ((crq.bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) | ||
129 | std_req_rc = ast_vhub_std_dev_request(ep, &crq); | ||
130 | |||
131 | /* Act upon result */ | ||
132 | switch(std_req_rc) { | ||
133 | case std_req_complete: | ||
134 | goto complete; | ||
135 | case std_req_stall: | ||
136 | goto stall; | ||
137 | case std_req_driver: | ||
138 | break; | ||
139 | case std_req_data: | ||
140 | return; | ||
141 | } | ||
142 | |||
143 | /* Pass request up to the gadget driver */ | ||
144 | if (WARN_ON(!ep->dev)) | ||
145 | goto stall; | ||
146 | if (ep->dev->driver) { | ||
147 | EPDBG(ep, "forwarding to gadget...\n"); | ||
148 | spin_unlock(&ep->vhub->lock); | ||
149 | rc = ep->dev->driver->setup(&ep->dev->gadget, &crq); | ||
150 | spin_lock(&ep->vhub->lock); | ||
151 | EPDBG(ep, "driver returned %d\n", rc); | ||
152 | } else { | ||
153 | EPDBG(ep, "no gadget for request !\n"); | ||
154 | } | ||
155 | if (rc >= 0) | ||
156 | return; | ||
157 | |||
158 | stall: | ||
159 | EPDBG(ep, "stalling\n"); | ||
160 | writel(VHUB_EP0_CTRL_STALL, ep->ep0.ctlstat); | ||
161 | ep->ep0.state = ep0_state_status; | ||
162 | ep->ep0.dir_in = false; | ||
163 | return; | ||
164 | |||
165 | complete: | ||
166 | EPVDBG(ep, "sending [in] status with no data\n"); | ||
167 | writel(VHUB_EP0_TX_BUFF_RDY, ep->ep0.ctlstat); | ||
168 | ep->ep0.state = ep0_state_status; | ||
169 | ep->ep0.dir_in = false; | ||
170 | } | ||
171 | |||
172 | |||
173 | static void ast_vhub_ep0_do_send(struct ast_vhub_ep *ep, | ||
174 | struct ast_vhub_req *req) | ||
175 | { | ||
176 | unsigned int chunk; | ||
177 | u32 reg; | ||
178 | |||
179 | /* If this is a 0-length request, it's the gadget trying to | ||
180 | * send a status on our behalf. We take it from here. | ||
181 | */ | ||
182 | if (req->req.length == 0) | ||
183 | req->last_desc = 1; | ||
184 | |||
185 | /* Are we done ? Complete request, otherwise wait for next interrupt */ | ||
186 | if (req->last_desc >= 0) { | ||
187 | EPVDBG(ep, "complete send %d/%d\n", | ||
188 | req->req.actual, req->req.length); | ||
189 | ep->ep0.state = ep0_state_status; | ||
190 | writel(VHUB_EP0_RX_BUFF_RDY, ep->ep0.ctlstat); | ||
191 | ast_vhub_done(ep, req, 0); | ||
192 | return; | ||
193 | } | ||
194 | |||
195 | /* | ||
196 | * Next chunk cropped to max packet size. Also check if this | ||
197 | * is the last packet | ||
198 | */ | ||
199 | chunk = req->req.length - req->req.actual; | ||
200 | if (chunk > ep->ep.maxpacket) | ||
201 | chunk = ep->ep.maxpacket; | ||
202 | else if ((chunk < ep->ep.maxpacket) || !req->req.zero) | ||
203 | req->last_desc = 1; | ||
204 | |||
205 | EPVDBG(ep, "send chunk=%d last=%d, req->act=%d mp=%d\n", | ||
206 | chunk, req->last_desc, req->req.actual, ep->ep.maxpacket); | ||
207 | |||
208 | /* | ||
209 | * Copy data if any (internal requests already have data | ||
210 | * in the EP buffer) | ||
211 | */ | ||
212 | if (chunk && req->req.buf) | ||
213 | memcpy(ep->buf, req->req.buf + req->req.actual, chunk); | ||
214 | |||
215 | /* Remember chunk size and trigger send */ | ||
216 | reg = VHUB_EP0_SET_TX_LEN(chunk); | ||
217 | writel(reg, ep->ep0.ctlstat); | ||
218 | writel(reg | VHUB_EP0_TX_BUFF_RDY, ep->ep0.ctlstat); | ||
219 | req->req.actual += chunk; | ||
220 | } | ||
221 | |||
222 | static void ast_vhub_ep0_rx_prime(struct ast_vhub_ep *ep) | ||
223 | { | ||
224 | EPVDBG(ep, "rx prime\n"); | ||
225 | |||
226 | /* Prime endpoint for receiving data */ | ||
227 | writel(VHUB_EP0_RX_BUFF_RDY, ep->ep0.ctlstat + AST_VHUB_EP0_CTRL); | ||
228 | } | ||
229 | |||
230 | static void ast_vhub_ep0_do_receive(struct ast_vhub_ep *ep, struct ast_vhub_req *req, | ||
231 | unsigned int len) | ||
232 | { | ||
233 | unsigned int remain; | ||
234 | int rc = 0; | ||
235 | |||
236 | /* We are receiving... grab request */ | ||
237 | remain = req->req.length - req->req.actual; | ||
238 | |||
239 | EPVDBG(ep, "receive got=%d remain=%d\n", len, remain); | ||
240 | |||
241 | /* Are we getting more than asked ? */ | ||
242 | if (len > remain) { | ||
243 | EPDBG(ep, "receiving too much (ovf: %d) !\n", | ||
244 | len - remain); | ||
245 | len = remain; | ||
246 | rc = -EOVERFLOW; | ||
247 | } | ||
248 | if (len && req->req.buf) | ||
249 | memcpy(req->req.buf + req->req.actual, ep->buf, len); | ||
250 | req->req.actual += len; | ||
251 | |||
252 | /* Done ? */ | ||
253 | if (len < ep->ep.maxpacket || len == remain) { | ||
254 | ep->ep0.state = ep0_state_status; | ||
255 | writel(VHUB_EP0_TX_BUFF_RDY, ep->ep0.ctlstat); | ||
256 | ast_vhub_done(ep, req, rc); | ||
257 | } else | ||
258 | ast_vhub_ep0_rx_prime(ep); | ||
259 | } | ||
260 | |||
261 | void ast_vhub_ep0_handle_ack(struct ast_vhub_ep *ep, bool in_ack) | ||
262 | { | ||
263 | struct ast_vhub_req *req; | ||
264 | struct ast_vhub *vhub = ep->vhub; | ||
265 | struct device *dev = &vhub->pdev->dev; | ||
266 | bool stall = false; | ||
267 | u32 stat; | ||
268 | |||
269 | /* Read EP0 status */ | ||
270 | stat = readl(ep->ep0.ctlstat); | ||
271 | |||
272 | /* Grab current request if any */ | ||
273 | req = list_first_entry_or_null(&ep->queue, struct ast_vhub_req, queue); | ||
274 | |||
275 | EPVDBG(ep, "ACK status=%08x,state=%d is_in=%d in_ack=%d req=%p\n", | ||
276 | stat, ep->ep0.state, ep->ep0.dir_in, in_ack, req); | ||
277 | |||
278 | switch(ep->ep0.state) { | ||
279 | case ep0_state_token: | ||
280 | /* There should be no request queued in that state... */ | ||
281 | if (req) { | ||
282 | dev_warn(dev, "request present while in TOKEN state\n"); | ||
283 | ast_vhub_nuke(ep, -EINVAL); | ||
284 | } | ||
285 | dev_warn(dev, "ack while in TOKEN state\n"); | ||
286 | stall = true; | ||
287 | break; | ||
288 | case ep0_state_data: | ||
289 | /* Check the state bits corresponding to our direction */ | ||
290 | if ((ep->ep0.dir_in && (stat & VHUB_EP0_TX_BUFF_RDY)) || | ||
291 | (!ep->ep0.dir_in && (stat & VHUB_EP0_RX_BUFF_RDY)) || | ||
292 | (ep->ep0.dir_in != in_ack)) { | ||
293 | dev_warn(dev, "irq state mismatch"); | ||
294 | stall = true; | ||
295 | break; | ||
296 | } | ||
297 | /* | ||
298 | * We are in data phase and there's no request, something is | ||
299 | * wrong, stall | ||
300 | */ | ||
301 | if (!req) { | ||
302 | dev_warn(dev, "data phase, no request\n"); | ||
303 | stall = true; | ||
304 | break; | ||
305 | } | ||
306 | |||
307 | /* We have a request, handle data transfers */ | ||
308 | if (ep->ep0.dir_in) | ||
309 | ast_vhub_ep0_do_send(ep, req); | ||
310 | else | ||
311 | ast_vhub_ep0_do_receive(ep, req, VHUB_EP0_RX_LEN(stat)); | ||
312 | return; | ||
313 | case ep0_state_status: | ||
314 | /* Nuke stale requests */ | ||
315 | if (req) { | ||
316 | dev_warn(dev, "request present while in STATUS state\n"); | ||
317 | ast_vhub_nuke(ep, -EINVAL); | ||
318 | } | ||
319 | |||
320 | /* | ||
321 | * If the status phase completes with the wrong ack, stall | ||
322 | * the endpoint just in case, to abort whatever the host | ||
323 | * was doing. | ||
324 | */ | ||
325 | if (ep->ep0.dir_in == in_ack) { | ||
326 | dev_warn(dev, "status direction mismatch\n"); | ||
327 | stall = true; | ||
328 | } | ||
329 | } | ||
330 | |||
331 | /* Reset to token state */ | ||
332 | ep->ep0.state = ep0_state_token; | ||
333 | if (stall) | ||
334 | writel(VHUB_EP0_CTRL_STALL, ep->ep0.ctlstat); | ||
335 | } | ||
336 | |||
337 | static int ast_vhub_ep0_queue(struct usb_ep* u_ep, struct usb_request *u_req, | ||
338 | gfp_t gfp_flags) | ||
339 | { | ||
340 | struct ast_vhub_req *req = to_ast_req(u_req); | ||
341 | struct ast_vhub_ep *ep = to_ast_ep(u_ep); | ||
342 | struct ast_vhub *vhub = ep->vhub; | ||
343 | struct device *dev = &vhub->pdev->dev; | ||
344 | unsigned long flags; | ||
345 | |||
346 | /* Paranoid cheks */ | ||
347 | if (!u_req || (!u_req->complete && !req->internal)) { | ||
348 | dev_warn(dev, "Bogus EP0 request ! u_req=%p\n", u_req); | ||
349 | if (u_req) { | ||
350 | dev_warn(dev, "complete=%p internal=%d\n", | ||
351 | u_req->complete, req->internal); | ||
352 | } | ||
353 | return -EINVAL; | ||
354 | } | ||
355 | |||
356 | /* Not endpoint 0 ? */ | ||
357 | if (WARN_ON(ep->d_idx != 0)) | ||
358 | return -EINVAL; | ||
359 | |||
360 | /* Disabled device */ | ||
361 | if (ep->dev && (!ep->dev->enabled || ep->dev->suspended)) | ||
362 | return -ESHUTDOWN; | ||
363 | |||
364 | /* Data, no buffer and not internal ? */ | ||
365 | if (u_req->length && !u_req->buf && !req->internal) { | ||
366 | dev_warn(dev, "Request with no buffer !\n"); | ||
367 | return -EINVAL; | ||
368 | } | ||
369 | |||
370 | EPVDBG(ep, "enqueue req @%p\n", req); | ||
371 | EPVDBG(ep, " l=%d zero=%d noshort=%d is_in=%d\n", | ||
372 | u_req->length, u_req->zero, | ||
373 | u_req->short_not_ok, ep->ep0.dir_in); | ||
374 | |||
375 | /* Initialize request progress fields */ | ||
376 | u_req->status = -EINPROGRESS; | ||
377 | u_req->actual = 0; | ||
378 | req->last_desc = -1; | ||
379 | req->active = false; | ||
380 | |||
381 | spin_lock_irqsave(&vhub->lock, flags); | ||
382 | |||
383 | /* EP0 can only support a single request at a time */ | ||
384 | if (!list_empty(&ep->queue) || ep->ep0.state == ep0_state_token) { | ||
385 | dev_warn(dev, "EP0: Request in wrong state\n"); | ||
386 | spin_unlock_irqrestore(&vhub->lock, flags); | ||
387 | return -EBUSY; | ||
388 | } | ||
389 | |||
390 | /* Add request to list and kick processing if empty */ | ||
391 | list_add_tail(&req->queue, &ep->queue); | ||
392 | |||
393 | if (ep->ep0.dir_in) { | ||
394 | /* IN request, send data */ | ||
395 | ast_vhub_ep0_do_send(ep, req); | ||
396 | } else if (u_req->length == 0) { | ||
397 | /* 0-len request, send completion as rx */ | ||
398 | EPVDBG(ep, "0-length rx completion\n"); | ||
399 | ep->ep0.state = ep0_state_status; | ||
400 | writel(VHUB_EP0_TX_BUFF_RDY, ep->ep0.ctlstat); | ||
401 | ast_vhub_done(ep, req, 0); | ||
402 | } else { | ||
403 | /* OUT request, start receiver */ | ||
404 | ast_vhub_ep0_rx_prime(ep); | ||
405 | } | ||
406 | |||
407 | spin_unlock_irqrestore(&vhub->lock, flags); | ||
408 | |||
409 | return 0; | ||
410 | } | ||
411 | |||
412 | static int ast_vhub_ep0_dequeue(struct usb_ep* u_ep, struct usb_request *u_req) | ||
413 | { | ||
414 | struct ast_vhub_ep *ep = to_ast_ep(u_ep); | ||
415 | struct ast_vhub *vhub = ep->vhub; | ||
416 | struct ast_vhub_req *req; | ||
417 | unsigned long flags; | ||
418 | int rc = -EINVAL; | ||
419 | |||
420 | spin_lock_irqsave(&vhub->lock, flags); | ||
421 | |||
422 | /* Only one request can be in the queue */ | ||
423 | req = list_first_entry_or_null(&ep->queue, struct ast_vhub_req, queue); | ||
424 | |||
425 | /* Is it ours ? */ | ||
426 | if (req && u_req == &req->req) { | ||
427 | EPVDBG(ep, "dequeue req @%p\n", req); | ||
428 | |||
429 | /* | ||
430 | * We don't have to deal with "active" as all | ||
431 | * DMAs go to the EP buffers, not the request. | ||
432 | */ | ||
433 | ast_vhub_done(ep, req, -ECONNRESET); | ||
434 | |||
435 | /* We do stall the EP to clean things up in HW */ | ||
436 | writel(VHUB_EP0_CTRL_STALL, ep->ep0.ctlstat); | ||
437 | ep->ep0.state = ep0_state_status; | ||
438 | ep->ep0.dir_in = false; | ||
439 | rc = 0; | ||
440 | } | ||
441 | spin_unlock_irqrestore(&vhub->lock, flags); | ||
442 | return rc; | ||
443 | } | ||
444 | |||
445 | |||
446 | static const struct usb_ep_ops ast_vhub_ep0_ops = { | ||
447 | .queue = ast_vhub_ep0_queue, | ||
448 | .dequeue = ast_vhub_ep0_dequeue, | ||
449 | .alloc_request = ast_vhub_alloc_request, | ||
450 | .free_request = ast_vhub_free_request, | ||
451 | }; | ||
452 | |||
453 | void ast_vhub_init_ep0(struct ast_vhub *vhub, struct ast_vhub_ep *ep, | ||
454 | struct ast_vhub_dev *dev) | ||
455 | { | ||
456 | memset(ep, 0, sizeof(*ep)); | ||
457 | |||
458 | INIT_LIST_HEAD(&ep->ep.ep_list); | ||
459 | INIT_LIST_HEAD(&ep->queue); | ||
460 | ep->ep.ops = &ast_vhub_ep0_ops; | ||
461 | ep->ep.name = "ep0"; | ||
462 | ep->ep.caps.type_control = true; | ||
463 | usb_ep_set_maxpacket_limit(&ep->ep, AST_VHUB_EP0_MAX_PACKET); | ||
464 | ep->d_idx = 0; | ||
465 | ep->dev = dev; | ||
466 | ep->vhub = vhub; | ||
467 | ep->ep0.state = ep0_state_token; | ||
468 | INIT_LIST_HEAD(&ep->ep0.req.queue); | ||
469 | ep->ep0.req.internal = true; | ||
470 | |||
471 | /* Small difference between vHub and devices */ | ||
472 | if (dev) { | ||
473 | ep->ep0.ctlstat = dev->regs + AST_VHUB_DEV_EP0_CTRL; | ||
474 | ep->ep0.setup = vhub->regs + | ||
475 | AST_VHUB_SETUP0 + 8 * (dev->index + 1); | ||
476 | ep->buf = vhub->ep0_bufs + | ||
477 | AST_VHUB_EP0_MAX_PACKET * (dev->index + 1); | ||
478 | ep->buf_dma = vhub->ep0_bufs_dma + | ||
479 | AST_VHUB_EP0_MAX_PACKET * (dev->index + 1); | ||
480 | } else { | ||
481 | ep->ep0.ctlstat = vhub->regs + AST_VHUB_EP0_CTRL; | ||
482 | ep->ep0.setup = vhub->regs + AST_VHUB_SETUP0; | ||
483 | ep->buf = vhub->ep0_bufs; | ||
484 | ep->buf_dma = vhub->ep0_bufs_dma; | ||
485 | } | ||
486 | } | ||
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/epn.c b/drivers/usb/gadget/udc/aspeed-vhub/epn.c new file mode 100644 index 000000000000..80c9feac5147 --- /dev/null +++ b/drivers/usb/gadget/udc/aspeed-vhub/epn.c | |||
@@ -0,0 +1,843 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | /* | ||
3 | * aspeed-vhub -- Driver for Aspeed SoC "vHub" USB gadget | ||
4 | * | ||
5 | * epn.c - Generic endpoints management | ||
6 | * | ||
7 | * Copyright 2017 IBM Corporation | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/ioport.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/errno.h> | ||
22 | #include <linux/list.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/proc_fs.h> | ||
25 | #include <linux/prefetch.h> | ||
26 | #include <linux/clk.h> | ||
27 | #include <linux/usb/gadget.h> | ||
28 | #include <linux/of.h> | ||
29 | #include <linux/of_gpio.h> | ||
30 | #include <linux/regmap.h> | ||
31 | #include <linux/dma-mapping.h> | ||
32 | |||
33 | #include "vhub.h" | ||
34 | |||
35 | #define EXTRA_CHECKS | ||
36 | |||
37 | #ifdef EXTRA_CHECKS | ||
38 | #define CHECK(ep, expr, fmt...) \ | ||
39 | do { \ | ||
40 | if (!(expr)) EPDBG(ep, "CHECK:" fmt); \ | ||
41 | } while(0) | ||
42 | #else | ||
43 | #define CHECK(ep, expr, fmt...) do { } while(0) | ||
44 | #endif | ||
45 | |||
46 | static void ast_vhub_epn_kick(struct ast_vhub_ep *ep, struct ast_vhub_req *req) | ||
47 | { | ||
48 | unsigned int act = req->req.actual; | ||
49 | unsigned int len = req->req.length; | ||
50 | unsigned int chunk; | ||
51 | |||
52 | /* There should be no DMA ongoing */ | ||
53 | WARN_ON(req->active); | ||
54 | |||
55 | /* Calculate next chunk size */ | ||
56 | chunk = len - act; | ||
57 | if (chunk > ep->ep.maxpacket) | ||
58 | chunk = ep->ep.maxpacket; | ||
59 | else if ((chunk < ep->ep.maxpacket) || !req->req.zero) | ||
60 | req->last_desc = 1; | ||
61 | |||
62 | EPVDBG(ep, "kick req %p act=%d/%d chunk=%d last=%d\n", | ||
63 | req, act, len, chunk, req->last_desc); | ||
64 | |||
65 | /* If DMA unavailable, using staging EP buffer */ | ||
66 | if (!req->req.dma) { | ||
67 | |||
68 | /* For IN transfers, copy data over first */ | ||
69 | if (ep->epn.is_in) | ||
70 | memcpy(ep->buf, req->req.buf + act, chunk); | ||
71 | writel(ep->buf_dma, ep->epn.regs + AST_VHUB_EP_DESC_BASE); | ||
72 | } else | ||
73 | writel(req->req.dma + act, ep->epn.regs + AST_VHUB_EP_DESC_BASE); | ||
74 | |||
75 | /* Start DMA */ | ||
76 | req->active = true; | ||
77 | writel(VHUB_EP_DMA_SET_TX_SIZE(chunk), | ||
78 | ep->epn.regs + AST_VHUB_EP_DESC_STATUS); | ||
79 | writel(VHUB_EP_DMA_SET_TX_SIZE(chunk) | VHUB_EP_DMA_SINGLE_KICK, | ||
80 | ep->epn.regs + AST_VHUB_EP_DESC_STATUS); | ||
81 | } | ||
82 | |||
83 | static void ast_vhub_epn_handle_ack(struct ast_vhub_ep *ep) | ||
84 | { | ||
85 | struct ast_vhub_req *req; | ||
86 | unsigned int len; | ||
87 | u32 stat; | ||
88 | |||
89 | /* Read EP status */ | ||
90 | stat = readl(ep->epn.regs + AST_VHUB_EP_DESC_STATUS); | ||
91 | |||
92 | /* Grab current request if any */ | ||
93 | req = list_first_entry_or_null(&ep->queue, struct ast_vhub_req, queue); | ||
94 | |||
95 | EPVDBG(ep, "ACK status=%08x is_in=%d, req=%p (active=%d)\n", | ||
96 | stat, ep->epn.is_in, req, req ? req->active : 0); | ||
97 | |||
98 | /* In absence of a request, bail out, must have been dequeued */ | ||
99 | if (!req) | ||
100 | return; | ||
101 | |||
102 | /* | ||
103 | * Request not active, move on to processing queue, active request | ||
104 | * was probably dequeued | ||
105 | */ | ||
106 | if (!req->active) | ||
107 | goto next_chunk; | ||
108 | |||
109 | /* Check if HW has moved on */ | ||
110 | if (VHUB_EP_DMA_RPTR(stat) != 0) { | ||
111 | EPDBG(ep, "DMA read pointer not 0 !\n"); | ||
112 | return; | ||
113 | } | ||
114 | |||
115 | /* No current DMA ongoing */ | ||
116 | req->active = false; | ||
117 | |||
118 | /* Grab lenght out of HW */ | ||
119 | len = VHUB_EP_DMA_TX_SIZE(stat); | ||
120 | |||
121 | /* If not using DMA, copy data out if needed */ | ||
122 | if (!req->req.dma && !ep->epn.is_in && len) | ||
123 | memcpy(req->req.buf + req->req.actual, ep->buf, len); | ||
124 | |||
125 | /* Adjust size */ | ||
126 | req->req.actual += len; | ||
127 | |||
128 | /* Check for short packet */ | ||
129 | if (len < ep->ep.maxpacket) | ||
130 | req->last_desc = 1; | ||
131 | |||
132 | /* That's it ? complete the request and pick a new one */ | ||
133 | if (req->last_desc >= 0) { | ||
134 | ast_vhub_done(ep, req, 0); | ||
135 | req = list_first_entry_or_null(&ep->queue, struct ast_vhub_req, | ||
136 | queue); | ||
137 | |||
138 | /* | ||
139 | * Due to lock dropping inside "done" the next request could | ||
140 | * already be active, so check for that and bail if needed. | ||
141 | */ | ||
142 | if (!req || req->active) | ||
143 | return; | ||
144 | } | ||
145 | |||
146 | next_chunk: | ||
147 | ast_vhub_epn_kick(ep, req); | ||
148 | } | ||
149 | |||
150 | static inline unsigned int ast_vhub_count_free_descs(struct ast_vhub_ep *ep) | ||
151 | { | ||
152 | /* | ||
153 | * d_next == d_last means descriptor list empty to HW, | ||
154 | * thus we can only have AST_VHUB_DESCS_COUNT-1 descriptors | ||
155 | * in the list | ||
156 | */ | ||
157 | return (ep->epn.d_last + AST_VHUB_DESCS_COUNT - ep->epn.d_next - 1) & | ||
158 | (AST_VHUB_DESCS_COUNT - 1); | ||
159 | } | ||
160 | |||
161 | static void ast_vhub_epn_kick_desc(struct ast_vhub_ep *ep, | ||
162 | struct ast_vhub_req *req) | ||
163 | { | ||
164 | unsigned int act = req->act_count; | ||
165 | unsigned int len = req->req.length; | ||
166 | unsigned int chunk; | ||
167 | |||
168 | /* Mark request active if not already */ | ||
169 | req->active = true; | ||
170 | |||
171 | /* If the request was already completely written, do nothing */ | ||
172 | if (req->last_desc >= 0) | ||
173 | return; | ||
174 | |||
175 | EPVDBG(ep, "kick act=%d/%d chunk_max=%d free_descs=%d\n", | ||
176 | act, len, ep->epn.chunk_max, ast_vhub_count_free_descs(ep)); | ||
177 | |||
178 | /* While we can create descriptors */ | ||
179 | while (ast_vhub_count_free_descs(ep) && req->last_desc < 0) { | ||
180 | struct ast_vhub_desc *desc; | ||
181 | unsigned int d_num; | ||
182 | |||
183 | /* Grab next free descriptor */ | ||
184 | d_num = ep->epn.d_next; | ||
185 | desc = &ep->epn.descs[d_num]; | ||
186 | ep->epn.d_next = (d_num + 1) & (AST_VHUB_DESCS_COUNT - 1); | ||
187 | |||
188 | /* Calculate next chunk size */ | ||
189 | chunk = len - act; | ||
190 | if (chunk <= ep->epn.chunk_max) { | ||
191 | /* | ||
192 | * Is this the last packet ? Because of having up to 8 | ||
193 | * packets in a descriptor we can't just compare "chunk" | ||
194 | * with ep.maxpacket. We have to see if it's a multiple | ||
195 | * of it to know if we have to send a zero packet. | ||
196 | * Sadly that involves a modulo which is a bit expensive | ||
197 | * but probably still better than not doing it. | ||
198 | */ | ||
199 | if (!chunk || !req->req.zero || (chunk % ep->ep.maxpacket) != 0) | ||
200 | req->last_desc = d_num; | ||
201 | } else { | ||
202 | chunk = ep->epn.chunk_max; | ||
203 | } | ||
204 | |||
205 | EPVDBG(ep, " chunk: act=%d/%d chunk=%d last=%d desc=%d free=%d\n", | ||
206 | act, len, chunk, req->last_desc, d_num, | ||
207 | ast_vhub_count_free_descs(ep)); | ||
208 | |||
209 | /* Populate descriptor */ | ||
210 | desc->w0 = cpu_to_le32(req->req.dma + act); | ||
211 | |||
212 | /* Interrupt if end of request or no more descriptors */ | ||
213 | |||
214 | /* | ||
215 | * TODO: Be smarter about it, if we don't have enough | ||
216 | * descriptors request an interrupt before queue empty | ||
217 | * or so in order to be able to populate more before | ||
218 | * the HW runs out. This isn't a problem at the moment | ||
219 | * as we use 256 descriptors and only put at most one | ||
220 | * request in the ring. | ||
221 | */ | ||
222 | desc->w1 = cpu_to_le32(VHUB_DSC1_IN_SET_LEN(chunk)); | ||
223 | if (req->last_desc >= 0 || !ast_vhub_count_free_descs(ep)) | ||
224 | desc->w1 |= cpu_to_le32(VHUB_DSC1_IN_INTERRUPT); | ||
225 | |||
226 | /* Account packet */ | ||
227 | req->act_count = act = act + chunk; | ||
228 | } | ||
229 | |||
230 | /* Tell HW about new descriptors */ | ||
231 | writel(VHUB_EP_DMA_SET_CPU_WPTR(ep->epn.d_next), | ||
232 | ep->epn.regs + AST_VHUB_EP_DESC_STATUS); | ||
233 | |||
234 | EPVDBG(ep, "HW kicked, d_next=%d dstat=%08x\n", | ||
235 | ep->epn.d_next, readl(ep->epn.regs + AST_VHUB_EP_DESC_STATUS)); | ||
236 | } | ||
237 | |||
238 | static void ast_vhub_epn_handle_ack_desc(struct ast_vhub_ep *ep) | ||
239 | { | ||
240 | struct ast_vhub_req *req; | ||
241 | unsigned int len, d_last; | ||
242 | u32 stat, stat1; | ||
243 | |||
244 | /* Read EP status, workaround HW race */ | ||
245 | do { | ||
246 | stat = readl(ep->epn.regs + AST_VHUB_EP_DESC_STATUS); | ||
247 | stat1 = readl(ep->epn.regs + AST_VHUB_EP_DESC_STATUS); | ||
248 | } while(stat != stat1); | ||
249 | |||
250 | /* Extract RPTR */ | ||
251 | d_last = VHUB_EP_DMA_RPTR(stat); | ||
252 | |||
253 | /* Grab current request if any */ | ||
254 | req = list_first_entry_or_null(&ep->queue, struct ast_vhub_req, queue); | ||
255 | |||
256 | EPVDBG(ep, "ACK status=%08x is_in=%d ep->d_last=%d..%d\n", | ||
257 | stat, ep->epn.is_in, ep->epn.d_last, d_last); | ||
258 | |||
259 | /* Check all completed descriptors */ | ||
260 | while (ep->epn.d_last != d_last) { | ||
261 | struct ast_vhub_desc *desc; | ||
262 | unsigned int d_num; | ||
263 | bool is_last_desc; | ||
264 | |||
265 | /* Grab next completed descriptor */ | ||
266 | d_num = ep->epn.d_last; | ||
267 | desc = &ep->epn.descs[d_num]; | ||
268 | ep->epn.d_last = (d_num + 1) & (AST_VHUB_DESCS_COUNT - 1); | ||
269 | |||
270 | /* Grab len out of descriptor */ | ||
271 | len = VHUB_DSC1_IN_LEN(le32_to_cpu(desc->w1)); | ||
272 | |||
273 | EPVDBG(ep, " desc %d len=%d req=%p (act=%d)\n", | ||
274 | d_num, len, req, req ? req->active : 0); | ||
275 | |||
276 | /* If no active request pending, move on */ | ||
277 | if (!req || !req->active) | ||
278 | continue; | ||
279 | |||
280 | /* Adjust size */ | ||
281 | req->req.actual += len; | ||
282 | |||
283 | /* Is that the last chunk ? */ | ||
284 | is_last_desc = req->last_desc == d_num; | ||
285 | CHECK(ep, is_last_desc == (len < ep->ep.maxpacket || | ||
286 | (req->req.actual >= req->req.length && | ||
287 | !req->req.zero)), | ||
288 | "Last packet discrepancy: last_desc=%d len=%d r.act=%d " | ||
289 | "r.len=%d r.zero=%d mp=%d\n", | ||
290 | is_last_desc, len, req->req.actual, req->req.length, | ||
291 | req->req.zero, ep->ep.maxpacket); | ||
292 | |||
293 | if (is_last_desc) { | ||
294 | /* | ||
295 | * Because we can only have one request at a time | ||
296 | * in our descriptor list in this implementation, | ||
297 | * d_last and ep->d_last should now be equal | ||
298 | */ | ||
299 | CHECK(ep, d_last == ep->epn.d_last, | ||
300 | "DMA read ptr mismatch %d vs %d\n", | ||
301 | d_last, ep->epn.d_last); | ||
302 | |||
303 | /* Note: done will drop and re-acquire the lock */ | ||
304 | ast_vhub_done(ep, req, 0); | ||
305 | req = list_first_entry_or_null(&ep->queue, | ||
306 | struct ast_vhub_req, | ||
307 | queue); | ||
308 | break; | ||
309 | } | ||
310 | } | ||
311 | |||
312 | /* More work ? */ | ||
313 | if (req) | ||
314 | ast_vhub_epn_kick_desc(ep, req); | ||
315 | } | ||
316 | |||
317 | void ast_vhub_epn_ack_irq(struct ast_vhub_ep *ep) | ||
318 | { | ||
319 | if (ep->epn.desc_mode) | ||
320 | ast_vhub_epn_handle_ack_desc(ep); | ||
321 | else | ||
322 | ast_vhub_epn_handle_ack(ep); | ||
323 | } | ||
324 | |||
325 | static int ast_vhub_epn_queue(struct usb_ep* u_ep, struct usb_request *u_req, | ||
326 | gfp_t gfp_flags) | ||
327 | { | ||
328 | struct ast_vhub_req *req = to_ast_req(u_req); | ||
329 | struct ast_vhub_ep *ep = to_ast_ep(u_ep); | ||
330 | struct ast_vhub *vhub = ep->vhub; | ||
331 | unsigned long flags; | ||
332 | bool empty; | ||
333 | int rc; | ||
334 | |||
335 | /* Paranoid checks */ | ||
336 | if (!u_req || !u_req->complete || !u_req->buf) { | ||
337 | dev_warn(&vhub->pdev->dev, "Bogus EPn request ! u_req=%p\n", u_req); | ||
338 | if (u_req) { | ||
339 | dev_warn(&vhub->pdev->dev, "complete=%p internal=%d\n", | ||
340 | u_req->complete, req->internal); | ||
341 | } | ||
342 | return -EINVAL; | ||
343 | } | ||
344 | |||
345 | /* Endpoint enabled ? */ | ||
346 | if (!ep->epn.enabled || !u_ep->desc || !ep->dev || !ep->d_idx || | ||
347 | !ep->dev->enabled || ep->dev->suspended) { | ||
348 | EPDBG(ep,"Enqueing request on wrong or disabled EP\n"); | ||
349 | return -ESHUTDOWN; | ||
350 | } | ||
351 | |||
352 | /* Map request for DMA if possible. For now, the rule for DMA is | ||
353 | * that: | ||
354 | * | ||
355 | * * For single stage mode (no descriptors): | ||
356 | * | ||
357 | * - The buffer is aligned to a 8 bytes boundary (HW requirement) | ||
358 | * - For a OUT endpoint, the request size is a multiple of the EP | ||
359 | * packet size (otherwise the controller will DMA past the end | ||
360 | * of the buffer if the host is sending a too long packet). | ||
361 | * | ||
362 | * * For descriptor mode (tx only for now), always. | ||
363 | * | ||
364 | * We could relax the latter by making the decision to use the bounce | ||
365 | * buffer based on the size of a given *segment* of the request rather | ||
366 | * than the whole request. | ||
367 | */ | ||
368 | if (ep->epn.desc_mode || | ||
369 | ((((unsigned long)u_req->buf & 7) == 0) && | ||
370 | (ep->epn.is_in || !(u_req->length & (u_ep->maxpacket - 1))))) { | ||
371 | rc = usb_gadget_map_request(&ep->dev->gadget, u_req, | ||
372 | ep->epn.is_in); | ||
373 | if (rc) { | ||
374 | dev_warn(&vhub->pdev->dev, | ||
375 | "Request mapping failure %d\n", rc); | ||
376 | return rc; | ||
377 | } | ||
378 | } else | ||
379 | u_req->dma = 0; | ||
380 | |||
381 | EPVDBG(ep, "enqueue req @%p\n", req); | ||
382 | EPVDBG(ep, " l=%d dma=0x%x zero=%d noshort=%d noirq=%d is_in=%d\n", | ||
383 | u_req->length, (u32)u_req->dma, u_req->zero, | ||
384 | u_req->short_not_ok, u_req->no_interrupt, | ||
385 | ep->epn.is_in); | ||
386 | |||
387 | /* Initialize request progress fields */ | ||
388 | u_req->status = -EINPROGRESS; | ||
389 | u_req->actual = 0; | ||
390 | req->act_count = 0; | ||
391 | req->active = false; | ||
392 | req->last_desc = -1; | ||
393 | spin_lock_irqsave(&vhub->lock, flags); | ||
394 | empty = list_empty(&ep->queue); | ||
395 | |||
396 | /* Add request to list and kick processing if empty */ | ||
397 | list_add_tail(&req->queue, &ep->queue); | ||
398 | if (empty) { | ||
399 | if (ep->epn.desc_mode) | ||
400 | ast_vhub_epn_kick_desc(ep, req); | ||
401 | else | ||
402 | ast_vhub_epn_kick(ep, req); | ||
403 | } | ||
404 | spin_unlock_irqrestore(&vhub->lock, flags); | ||
405 | |||
406 | return 0; | ||
407 | } | ||
408 | |||
409 | static void ast_vhub_stop_active_req(struct ast_vhub_ep *ep, | ||
410 | bool restart_ep) | ||
411 | { | ||
412 | u32 state, reg, loops; | ||
413 | |||
414 | /* Stop DMA activity */ | ||
415 | writel(0, ep->epn.regs + AST_VHUB_EP_DMA_CTLSTAT); | ||
416 | |||
417 | /* Wait for it to complete */ | ||
418 | for (loops = 0; loops < 1000; loops++) { | ||
419 | state = readl(ep->epn.regs + AST_VHUB_EP_DMA_CTLSTAT); | ||
420 | state = VHUB_EP_DMA_PROC_STATUS(state); | ||
421 | if (state == EP_DMA_PROC_RX_IDLE || | ||
422 | state == EP_DMA_PROC_TX_IDLE) | ||
423 | break; | ||
424 | udelay(1); | ||
425 | } | ||
426 | if (loops >= 1000) | ||
427 | dev_warn(&ep->vhub->pdev->dev, "Timeout waiting for DMA\n"); | ||
428 | |||
429 | /* If we don't have to restart the endpoint, that's it */ | ||
430 | if (!restart_ep) | ||
431 | return; | ||
432 | |||
433 | /* Restart the endpoint */ | ||
434 | if (ep->epn.desc_mode) { | ||
435 | /* | ||
436 | * Take out descriptors by resetting the DMA read | ||
437 | * pointer to be equal to the CPU write pointer. | ||
438 | * | ||
439 | * Note: If we ever support creating descriptors for | ||
440 | * requests that aren't the head of the queue, we | ||
441 | * may have to do something more complex here, | ||
442 | * especially if the request being taken out is | ||
443 | * not the current head descriptors. | ||
444 | */ | ||
445 | reg = VHUB_EP_DMA_SET_RPTR(ep->epn.d_next) | | ||
446 | VHUB_EP_DMA_SET_CPU_WPTR(ep->epn.d_next); | ||
447 | writel(reg, ep->epn.regs + AST_VHUB_EP_DESC_STATUS); | ||
448 | |||
449 | /* Then turn it back on */ | ||
450 | writel(ep->epn.dma_conf, | ||
451 | ep->epn.regs + AST_VHUB_EP_DMA_CTLSTAT); | ||
452 | } else { | ||
453 | /* Single mode: just turn it back on */ | ||
454 | writel(ep->epn.dma_conf, | ||
455 | ep->epn.regs + AST_VHUB_EP_DMA_CTLSTAT); | ||
456 | } | ||
457 | } | ||
458 | |||
459 | static int ast_vhub_epn_dequeue(struct usb_ep* u_ep, struct usb_request *u_req) | ||
460 | { | ||
461 | struct ast_vhub_ep *ep = to_ast_ep(u_ep); | ||
462 | struct ast_vhub *vhub = ep->vhub; | ||
463 | struct ast_vhub_req *req; | ||
464 | unsigned long flags; | ||
465 | int rc = -EINVAL; | ||
466 | |||
467 | spin_lock_irqsave(&vhub->lock, flags); | ||
468 | |||
469 | /* Make sure it's actually queued on this endpoint */ | ||
470 | list_for_each_entry (req, &ep->queue, queue) { | ||
471 | if (&req->req == u_req) | ||
472 | break; | ||
473 | } | ||
474 | |||
475 | if (&req->req == u_req) { | ||
476 | EPVDBG(ep, "dequeue req @%p active=%d\n", | ||
477 | req, req->active); | ||
478 | if (req->active) | ||
479 | ast_vhub_stop_active_req(ep, true); | ||
480 | ast_vhub_done(ep, req, -ECONNRESET); | ||
481 | rc = 0; | ||
482 | } | ||
483 | |||
484 | spin_unlock_irqrestore(&vhub->lock, flags); | ||
485 | return rc; | ||
486 | } | ||
487 | |||
488 | void ast_vhub_update_epn_stall(struct ast_vhub_ep *ep) | ||
489 | { | ||
490 | u32 reg; | ||
491 | |||
492 | if (WARN_ON(ep->d_idx == 0)) | ||
493 | return; | ||
494 | reg = readl(ep->epn.regs + AST_VHUB_EP_CONFIG); | ||
495 | if (ep->epn.stalled || ep->epn.wedged) | ||
496 | reg |= VHUB_EP_CFG_STALL_CTRL; | ||
497 | else | ||
498 | reg &= ~VHUB_EP_CFG_STALL_CTRL; | ||
499 | writel(reg, ep->epn.regs + AST_VHUB_EP_CONFIG); | ||
500 | |||
501 | if (!ep->epn.stalled && !ep->epn.wedged) | ||
502 | writel(VHUB_EP_TOGGLE_SET_EPNUM(ep->epn.g_idx), | ||
503 | ep->vhub->regs + AST_VHUB_EP_TOGGLE); | ||
504 | } | ||
505 | |||
506 | static int ast_vhub_set_halt_and_wedge(struct usb_ep* u_ep, bool halt, | ||
507 | bool wedge) | ||
508 | { | ||
509 | struct ast_vhub_ep *ep = to_ast_ep(u_ep); | ||
510 | struct ast_vhub *vhub = ep->vhub; | ||
511 | unsigned long flags; | ||
512 | |||
513 | EPDBG(ep, "Set halt (%d) & wedge (%d)\n", halt, wedge); | ||
514 | |||
515 | if (!u_ep || !u_ep->desc) | ||
516 | return -EINVAL; | ||
517 | if (ep->d_idx == 0) | ||
518 | return 0; | ||
519 | if (ep->epn.is_iso) | ||
520 | return -EOPNOTSUPP; | ||
521 | |||
522 | spin_lock_irqsave(&vhub->lock, flags); | ||
523 | |||
524 | /* Fail with still-busy IN endpoints */ | ||
525 | if (halt && ep->epn.is_in && !list_empty(&ep->queue)) { | ||
526 | spin_unlock_irqrestore(&vhub->lock, flags); | ||
527 | return -EAGAIN; | ||
528 | } | ||
529 | ep->epn.stalled = halt; | ||
530 | ep->epn.wedged = wedge; | ||
531 | ast_vhub_update_epn_stall(ep); | ||
532 | |||
533 | spin_unlock_irqrestore(&vhub->lock, flags); | ||
534 | |||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | static int ast_vhub_epn_set_halt(struct usb_ep *u_ep, int value) | ||
539 | { | ||
540 | return ast_vhub_set_halt_and_wedge(u_ep, value != 0, false); | ||
541 | } | ||
542 | |||
543 | static int ast_vhub_epn_set_wedge(struct usb_ep *u_ep) | ||
544 | { | ||
545 | return ast_vhub_set_halt_and_wedge(u_ep, true, true); | ||
546 | } | ||
547 | |||
548 | static int ast_vhub_epn_disable(struct usb_ep* u_ep) | ||
549 | { | ||
550 | struct ast_vhub_ep *ep = to_ast_ep(u_ep); | ||
551 | struct ast_vhub *vhub = ep->vhub; | ||
552 | unsigned long flags; | ||
553 | u32 imask, ep_ier; | ||
554 | |||
555 | EPDBG(ep, "Disabling !\n"); | ||
556 | |||
557 | spin_lock_irqsave(&vhub->lock, flags); | ||
558 | |||
559 | ep->epn.enabled = false; | ||
560 | |||
561 | /* Stop active DMA if any */ | ||
562 | ast_vhub_stop_active_req(ep, false); | ||
563 | |||
564 | /* Disable endpoint */ | ||
565 | writel(0, ep->epn.regs + AST_VHUB_EP_CONFIG); | ||
566 | |||
567 | /* Disable ACK interrupt */ | ||
568 | imask = VHUB_EP_IRQ(ep->epn.g_idx); | ||
569 | ep_ier = readl(vhub->regs + AST_VHUB_EP_ACK_IER); | ||
570 | ep_ier &= ~imask; | ||
571 | writel(ep_ier, vhub->regs + AST_VHUB_EP_ACK_IER); | ||
572 | writel(imask, vhub->regs + AST_VHUB_EP_ACK_ISR); | ||
573 | |||
574 | /* Nuke all pending requests */ | ||
575 | ast_vhub_nuke(ep, -ESHUTDOWN); | ||
576 | |||
577 | /* No more descriptor associated with request */ | ||
578 | ep->ep.desc = NULL; | ||
579 | |||
580 | spin_unlock_irqrestore(&vhub->lock, flags); | ||
581 | |||
582 | return 0; | ||
583 | } | ||
584 | |||
585 | static int ast_vhub_epn_enable(struct usb_ep* u_ep, | ||
586 | const struct usb_endpoint_descriptor *desc) | ||
587 | { | ||
588 | static const char *ep_type_string[] __maybe_unused = { "ctrl", | ||
589 | "isoc", | ||
590 | "bulk", | ||
591 | "intr" }; | ||
592 | struct ast_vhub_ep *ep = to_ast_ep(u_ep); | ||
593 | struct ast_vhub_dev *dev; | ||
594 | struct ast_vhub *vhub; | ||
595 | u16 maxpacket, type; | ||
596 | unsigned long flags; | ||
597 | u32 ep_conf, ep_ier, imask; | ||
598 | |||
599 | /* Check arguments */ | ||
600 | if (!u_ep || !desc) | ||
601 | return -EINVAL; | ||
602 | |||
603 | maxpacket = usb_endpoint_maxp(desc); | ||
604 | if (!ep->d_idx || !ep->dev || | ||
605 | desc->bDescriptorType != USB_DT_ENDPOINT || | ||
606 | maxpacket == 0 || maxpacket > ep->ep.maxpacket) { | ||
607 | EPDBG(ep, "Invalid EP enable,d_idx=%d,dev=%p,type=%d,mp=%d/%d\n", | ||
608 | ep->d_idx, ep->dev, desc->bDescriptorType, | ||
609 | maxpacket, ep->ep.maxpacket); | ||
610 | return -EINVAL; | ||
611 | } | ||
612 | if (ep->d_idx != usb_endpoint_num(desc)) { | ||
613 | EPDBG(ep, "EP number mismatch !\n"); | ||
614 | return -EINVAL; | ||
615 | } | ||
616 | |||
617 | if (ep->epn.enabled) { | ||
618 | EPDBG(ep, "Already enabled\n"); | ||
619 | return -EBUSY; | ||
620 | } | ||
621 | dev = ep->dev; | ||
622 | vhub = ep->vhub; | ||
623 | |||
624 | /* Check device state */ | ||
625 | if (!dev->driver) { | ||
626 | EPDBG(ep, "Bogus device state: driver=%p speed=%d\n", | ||
627 | dev->driver, dev->gadget.speed); | ||
628 | return -ESHUTDOWN; | ||
629 | } | ||
630 | |||
631 | /* Grab some info from the descriptor */ | ||
632 | ep->epn.is_in = usb_endpoint_dir_in(desc); | ||
633 | ep->ep.maxpacket = maxpacket; | ||
634 | type = usb_endpoint_type(desc); | ||
635 | ep->epn.d_next = ep->epn.d_last = 0; | ||
636 | ep->epn.is_iso = false; | ||
637 | ep->epn.stalled = false; | ||
638 | ep->epn.wedged = false; | ||
639 | |||
640 | EPDBG(ep, "Enabling [%s] %s num %d maxpacket=%d\n", | ||
641 | ep->epn.is_in ? "in" : "out", ep_type_string[type], | ||
642 | usb_endpoint_num(desc), maxpacket); | ||
643 | |||
644 | /* Can we use DMA descriptor mode ? */ | ||
645 | ep->epn.desc_mode = ep->epn.descs && ep->epn.is_in; | ||
646 | if (ep->epn.desc_mode) | ||
647 | memset(ep->epn.descs, 0, 8 * AST_VHUB_DESCS_COUNT); | ||
648 | |||
649 | /* | ||
650 | * Large send function can send up to 8 packets from | ||
651 | * one descriptor with a limit of 4095 bytes. | ||
652 | */ | ||
653 | ep->epn.chunk_max = ep->ep.maxpacket; | ||
654 | if (ep->epn.is_in) { | ||
655 | ep->epn.chunk_max <<= 3; | ||
656 | while (ep->epn.chunk_max > 4095) | ||
657 | ep->epn.chunk_max -= ep->ep.maxpacket; | ||
658 | } | ||
659 | |||
660 | switch(type) { | ||
661 | case USB_ENDPOINT_XFER_CONTROL: | ||
662 | EPDBG(ep, "Only one control endpoint\n"); | ||
663 | return -EINVAL; | ||
664 | case USB_ENDPOINT_XFER_INT: | ||
665 | ep_conf = VHUB_EP_CFG_SET_TYPE(EP_TYPE_INT); | ||
666 | break; | ||
667 | case USB_ENDPOINT_XFER_BULK: | ||
668 | ep_conf = VHUB_EP_CFG_SET_TYPE(EP_TYPE_BULK); | ||
669 | break; | ||
670 | case USB_ENDPOINT_XFER_ISOC: | ||
671 | ep_conf = VHUB_EP_CFG_SET_TYPE(EP_TYPE_ISO); | ||
672 | ep->epn.is_iso = true; | ||
673 | break; | ||
674 | default: | ||
675 | return -EINVAL; | ||
676 | } | ||
677 | |||
678 | /* Encode the rest of the EP config register */ | ||
679 | if (maxpacket < 1024) | ||
680 | ep_conf |= VHUB_EP_CFG_SET_MAX_PKT(maxpacket); | ||
681 | if (!ep->epn.is_in) | ||
682 | ep_conf |= VHUB_EP_CFG_DIR_OUT; | ||
683 | ep_conf |= VHUB_EP_CFG_SET_EP_NUM(usb_endpoint_num(desc)); | ||
684 | ep_conf |= VHUB_EP_CFG_ENABLE; | ||
685 | ep_conf |= VHUB_EP_CFG_SET_DEV(dev->index + 1); | ||
686 | EPVDBG(ep, "config=%08x\n", ep_conf); | ||
687 | |||
688 | spin_lock_irqsave(&vhub->lock, flags); | ||
689 | |||
690 | /* Disable HW and reset DMA */ | ||
691 | writel(0, ep->epn.regs + AST_VHUB_EP_CONFIG); | ||
692 | writel(VHUB_EP_DMA_CTRL_RESET, | ||
693 | ep->epn.regs + AST_VHUB_EP_DMA_CTLSTAT); | ||
694 | |||
695 | /* Configure and enable */ | ||
696 | writel(ep_conf, ep->epn.regs + AST_VHUB_EP_CONFIG); | ||
697 | |||
698 | if (ep->epn.desc_mode) { | ||
699 | /* Clear DMA status, including the DMA read ptr */ | ||
700 | writel(0, ep->epn.regs + AST_VHUB_EP_DESC_STATUS); | ||
701 | |||
702 | /* Set descriptor base */ | ||
703 | writel(ep->epn.descs_dma, | ||
704 | ep->epn.regs + AST_VHUB_EP_DESC_BASE); | ||
705 | |||
706 | /* Set base DMA config value */ | ||
707 | ep->epn.dma_conf = VHUB_EP_DMA_DESC_MODE; | ||
708 | if (ep->epn.is_in) | ||
709 | ep->epn.dma_conf |= VHUB_EP_DMA_IN_LONG_MODE; | ||
710 | |||
711 | /* First reset and disable all operations */ | ||
712 | writel(ep->epn.dma_conf | VHUB_EP_DMA_CTRL_RESET, | ||
713 | ep->epn.regs + AST_VHUB_EP_DMA_CTLSTAT); | ||
714 | |||
715 | /* Enable descriptor mode */ | ||
716 | writel(ep->epn.dma_conf, | ||
717 | ep->epn.regs + AST_VHUB_EP_DMA_CTLSTAT); | ||
718 | } else { | ||
719 | /* Set base DMA config value */ | ||
720 | ep->epn.dma_conf = VHUB_EP_DMA_SINGLE_STAGE; | ||
721 | |||
722 | /* Reset and switch to single stage mode */ | ||
723 | writel(ep->epn.dma_conf | VHUB_EP_DMA_CTRL_RESET, | ||
724 | ep->epn.regs + AST_VHUB_EP_DMA_CTLSTAT); | ||
725 | writel(ep->epn.dma_conf, | ||
726 | ep->epn.regs + AST_VHUB_EP_DMA_CTLSTAT); | ||
727 | writel(0, ep->epn.regs + AST_VHUB_EP_DESC_STATUS); | ||
728 | } | ||
729 | |||
730 | /* Cleanup data toggle just in case */ | ||
731 | writel(VHUB_EP_TOGGLE_SET_EPNUM(ep->epn.g_idx), | ||
732 | vhub->regs + AST_VHUB_EP_TOGGLE); | ||
733 | |||
734 | /* Cleanup and enable ACK interrupt */ | ||
735 | imask = VHUB_EP_IRQ(ep->epn.g_idx); | ||
736 | writel(imask, vhub->regs + AST_VHUB_EP_ACK_ISR); | ||
737 | ep_ier = readl(vhub->regs + AST_VHUB_EP_ACK_IER); | ||
738 | ep_ier |= imask; | ||
739 | writel(ep_ier, vhub->regs + AST_VHUB_EP_ACK_IER); | ||
740 | |||
741 | /* Woot, we are online ! */ | ||
742 | ep->epn.enabled = true; | ||
743 | |||
744 | spin_unlock_irqrestore(&vhub->lock, flags); | ||
745 | |||
746 | return 0; | ||
747 | } | ||
748 | |||
749 | static void ast_vhub_epn_dispose(struct usb_ep *u_ep) | ||
750 | { | ||
751 | struct ast_vhub_ep *ep = to_ast_ep(u_ep); | ||
752 | |||
753 | if (WARN_ON(!ep->dev || !ep->d_idx)) | ||
754 | return; | ||
755 | |||
756 | EPDBG(ep, "Releasing endpoint\n"); | ||
757 | |||
758 | /* Take it out of the EP list */ | ||
759 | list_del_init(&ep->ep.ep_list); | ||
760 | |||
761 | /* Mark the address free in the device */ | ||
762 | ep->dev->epns[ep->d_idx - 1] = NULL; | ||
763 | |||
764 | /* Free name & DMA buffers */ | ||
765 | kfree(ep->ep.name); | ||
766 | ep->ep.name = NULL; | ||
767 | dma_free_coherent(&ep->vhub->pdev->dev, | ||
768 | AST_VHUB_EPn_MAX_PACKET + | ||
769 | 8 * AST_VHUB_DESCS_COUNT, | ||
770 | ep->buf, ep->buf_dma); | ||
771 | ep->buf = NULL; | ||
772 | ep->epn.descs = NULL; | ||
773 | |||
774 | /* Mark free */ | ||
775 | ep->dev = NULL; | ||
776 | } | ||
777 | |||
778 | static const struct usb_ep_ops ast_vhub_epn_ops = { | ||
779 | .enable = ast_vhub_epn_enable, | ||
780 | .disable = ast_vhub_epn_disable, | ||
781 | .dispose = ast_vhub_epn_dispose, | ||
782 | .queue = ast_vhub_epn_queue, | ||
783 | .dequeue = ast_vhub_epn_dequeue, | ||
784 | .set_halt = ast_vhub_epn_set_halt, | ||
785 | .set_wedge = ast_vhub_epn_set_wedge, | ||
786 | .alloc_request = ast_vhub_alloc_request, | ||
787 | .free_request = ast_vhub_free_request, | ||
788 | }; | ||
789 | |||
790 | struct ast_vhub_ep *ast_vhub_alloc_epn(struct ast_vhub_dev *d, u8 addr) | ||
791 | { | ||
792 | struct ast_vhub *vhub = d->vhub; | ||
793 | struct ast_vhub_ep *ep; | ||
794 | unsigned long flags; | ||
795 | int i; | ||
796 | |||
797 | /* Find a free one (no device) */ | ||
798 | spin_lock_irqsave(&vhub->lock, flags); | ||
799 | for (i = 0; i < AST_VHUB_NUM_GEN_EPs; i++) | ||
800 | if (vhub->epns[i].dev == NULL) | ||
801 | break; | ||
802 | if (i >= AST_VHUB_NUM_GEN_EPs) { | ||
803 | spin_unlock_irqrestore(&vhub->lock, flags); | ||
804 | return NULL; | ||
805 | } | ||
806 | |||
807 | /* Set it up */ | ||
808 | ep = &vhub->epns[i]; | ||
809 | ep->dev = d; | ||
810 | spin_unlock_irqrestore(&vhub->lock, flags); | ||
811 | |||
812 | DDBG(d, "Allocating gen EP %d for addr %d\n", i, addr); | ||
813 | INIT_LIST_HEAD(&ep->queue); | ||
814 | ep->d_idx = addr; | ||
815 | ep->vhub = vhub; | ||
816 | ep->ep.ops = &ast_vhub_epn_ops; | ||
817 | ep->ep.name = kasprintf(GFP_KERNEL, "ep%d", addr); | ||
818 | d->epns[addr-1] = ep; | ||
819 | ep->epn.g_idx = i; | ||
820 | ep->epn.regs = vhub->regs + 0x200 + (i * 0x10); | ||
821 | |||
822 | ep->buf = dma_alloc_coherent(&vhub->pdev->dev, | ||
823 | AST_VHUB_EPn_MAX_PACKET + | ||
824 | 8 * AST_VHUB_DESCS_COUNT, | ||
825 | &ep->buf_dma, GFP_KERNEL); | ||
826 | if (!ep->buf) { | ||
827 | kfree(ep->ep.name); | ||
828 | ep->ep.name = NULL; | ||
829 | return NULL; | ||
830 | } | ||
831 | ep->epn.descs = ep->buf + AST_VHUB_EPn_MAX_PACKET; | ||
832 | ep->epn.descs_dma = ep->buf_dma + AST_VHUB_EPn_MAX_PACKET; | ||
833 | |||
834 | usb_ep_set_maxpacket_limit(&ep->ep, AST_VHUB_EPn_MAX_PACKET); | ||
835 | list_add_tail(&ep->ep.ep_list, &d->gadget.ep_list); | ||
836 | ep->ep.caps.type_iso = true; | ||
837 | ep->ep.caps.type_bulk = true; | ||
838 | ep->ep.caps.type_int = true; | ||
839 | ep->ep.caps.dir_in = true; | ||
840 | ep->ep.caps.dir_out = true; | ||
841 | |||
842 | return ep; | ||
843 | } | ||
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/hub.c b/drivers/usb/gadget/udc/aspeed-vhub/hub.c new file mode 100644 index 000000000000..35ba0e55a2e9 --- /dev/null +++ b/drivers/usb/gadget/udc/aspeed-vhub/hub.c | |||
@@ -0,0 +1,829 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | /* | ||
3 | * aspeed-vhub -- Driver for Aspeed SoC "vHub" USB gadget | ||
4 | * | ||
5 | * hub.c - virtual hub handling | ||
6 | * | ||
7 | * Copyright 2017 IBM Corporation | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/ioport.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/errno.h> | ||
22 | #include <linux/list.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/proc_fs.h> | ||
25 | #include <linux/prefetch.h> | ||
26 | #include <linux/clk.h> | ||
27 | #include <linux/usb/gadget.h> | ||
28 | #include <linux/of.h> | ||
29 | #include <linux/of_gpio.h> | ||
30 | #include <linux/regmap.h> | ||
31 | #include <linux/dma-mapping.h> | ||
32 | #include <linux/bcd.h> | ||
33 | #include <linux/version.h> | ||
34 | #include <linux/usb.h> | ||
35 | #include <linux/usb/hcd.h> | ||
36 | |||
37 | #include "vhub.h" | ||
38 | |||
39 | /* usb 2.0 hub device descriptor | ||
40 | * | ||
41 | * A few things we may want to improve here: | ||
42 | * | ||
43 | * - We may need to indicate TT support | ||
44 | * - We may need a device qualifier descriptor | ||
45 | * as devices can pretend to be usb1 or 2 | ||
46 | * - Make vid/did overridable | ||
47 | * - make it look like usb1 if usb1 mode forced | ||
48 | */ | ||
49 | #define KERNEL_REL bin2bcd(((LINUX_VERSION_CODE >> 16) & 0x0ff)) | ||
50 | #define KERNEL_VER bin2bcd(((LINUX_VERSION_CODE >> 8) & 0x0ff)) | ||
51 | |||
52 | enum { | ||
53 | AST_VHUB_STR_MANUF = 3, | ||
54 | AST_VHUB_STR_PRODUCT = 2, | ||
55 | AST_VHUB_STR_SERIAL = 1, | ||
56 | }; | ||
57 | |||
58 | static const struct usb_device_descriptor ast_vhub_dev_desc = { | ||
59 | .bLength = USB_DT_DEVICE_SIZE, | ||
60 | .bDescriptorType = USB_DT_DEVICE, | ||
61 | .bcdUSB = cpu_to_le16(0x0200), | ||
62 | .bDeviceClass = USB_CLASS_HUB, | ||
63 | .bDeviceSubClass = 0, | ||
64 | .bDeviceProtocol = 1, | ||
65 | .bMaxPacketSize0 = 64, | ||
66 | .idVendor = cpu_to_le16(0x1d6b), | ||
67 | .idProduct = cpu_to_le16(0x0107), | ||
68 | .bcdDevice = cpu_to_le16(0x0100), | ||
69 | .iManufacturer = AST_VHUB_STR_MANUF, | ||
70 | .iProduct = AST_VHUB_STR_PRODUCT, | ||
71 | .iSerialNumber = AST_VHUB_STR_SERIAL, | ||
72 | .bNumConfigurations = 1, | ||
73 | }; | ||
74 | |||
75 | /* Patches to the above when forcing USB1 mode */ | ||
76 | static void ast_vhub_patch_dev_desc_usb1(struct usb_device_descriptor *desc) | ||
77 | { | ||
78 | desc->bcdUSB = cpu_to_le16(0x0100); | ||
79 | desc->bDeviceProtocol = 0; | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * Configuration descriptor: same comments as above | ||
84 | * regarding handling USB1 mode. | ||
85 | */ | ||
86 | |||
87 | /* | ||
88 | * We don't use sizeof() as Linux definition of | ||
89 | * struct usb_endpoint_descriptor contains 2 | ||
90 | * extra bytes | ||
91 | */ | ||
92 | #define AST_VHUB_CONF_DESC_SIZE (USB_DT_CONFIG_SIZE + \ | ||
93 | USB_DT_INTERFACE_SIZE + \ | ||
94 | USB_DT_ENDPOINT_SIZE) | ||
95 | |||
96 | static const struct ast_vhub_full_cdesc { | ||
97 | struct usb_config_descriptor cfg; | ||
98 | struct usb_interface_descriptor intf; | ||
99 | struct usb_endpoint_descriptor ep; | ||
100 | } __attribute__ ((packed)) ast_vhub_conf_desc = { | ||
101 | .cfg = { | ||
102 | .bLength = USB_DT_CONFIG_SIZE, | ||
103 | .bDescriptorType = USB_DT_CONFIG, | ||
104 | .wTotalLength = cpu_to_le16(AST_VHUB_CONF_DESC_SIZE), | ||
105 | .bNumInterfaces = 1, | ||
106 | .bConfigurationValue = 1, | ||
107 | .iConfiguration = 0, | ||
108 | .bmAttributes = USB_CONFIG_ATT_ONE | | ||
109 | USB_CONFIG_ATT_SELFPOWER | | ||
110 | USB_CONFIG_ATT_WAKEUP, | ||
111 | .bMaxPower = 0, | ||
112 | }, | ||
113 | .intf = { | ||
114 | .bLength = USB_DT_INTERFACE_SIZE, | ||
115 | .bDescriptorType = USB_DT_INTERFACE, | ||
116 | .bInterfaceNumber = 0, | ||
117 | .bAlternateSetting = 0, | ||
118 | .bNumEndpoints = 1, | ||
119 | .bInterfaceClass = USB_CLASS_HUB, | ||
120 | .bInterfaceSubClass = 0, | ||
121 | .bInterfaceProtocol = 0, | ||
122 | .iInterface = 0, | ||
123 | }, | ||
124 | .ep = { | ||
125 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
126 | .bDescriptorType = USB_DT_ENDPOINT, | ||
127 | .bEndpointAddress = 0x81, | ||
128 | .bmAttributes = USB_ENDPOINT_XFER_INT, | ||
129 | .wMaxPacketSize = cpu_to_le16(1), | ||
130 | .bInterval = 0x0c, | ||
131 | }, | ||
132 | }; | ||
133 | |||
134 | #define AST_VHUB_HUB_DESC_SIZE (USB_DT_HUB_NONVAR_SIZE + 2) | ||
135 | |||
136 | static const struct usb_hub_descriptor ast_vhub_hub_desc = { | ||
137 | .bDescLength = AST_VHUB_HUB_DESC_SIZE, | ||
138 | .bDescriptorType = USB_DT_HUB, | ||
139 | .bNbrPorts = AST_VHUB_NUM_PORTS, | ||
140 | .wHubCharacteristics = cpu_to_le16(HUB_CHAR_NO_LPSM), | ||
141 | .bPwrOn2PwrGood = 10, | ||
142 | .bHubContrCurrent = 0, | ||
143 | .u.hs.DeviceRemovable[0] = 0, | ||
144 | .u.hs.DeviceRemovable[1] = 0xff, | ||
145 | }; | ||
146 | |||
147 | /* | ||
148 | * These strings converted to UTF-16 must be smaller than | ||
149 | * our EP0 buffer. | ||
150 | */ | ||
151 | static const struct usb_string ast_vhub_str_array[] = { | ||
152 | { | ||
153 | .id = AST_VHUB_STR_SERIAL, | ||
154 | .s = "00000000" | ||
155 | }, | ||
156 | { | ||
157 | .id = AST_VHUB_STR_PRODUCT, | ||
158 | .s = "USB Virtual Hub" | ||
159 | }, | ||
160 | { | ||
161 | .id = AST_VHUB_STR_MANUF, | ||
162 | .s = "Aspeed" | ||
163 | }, | ||
164 | { } | ||
165 | }; | ||
166 | |||
167 | static const struct usb_gadget_strings ast_vhub_strings = { | ||
168 | .language = 0x0409, | ||
169 | .strings = (struct usb_string *)ast_vhub_str_array | ||
170 | }; | ||
171 | |||
172 | static int ast_vhub_hub_dev_status(struct ast_vhub_ep *ep, | ||
173 | u16 wIndex, u16 wValue) | ||
174 | { | ||
175 | u8 st0; | ||
176 | |||
177 | EPDBG(ep, "GET_STATUS(dev)\n"); | ||
178 | |||
179 | /* | ||
180 | * Mark it as self-powered, I doubt the BMC is powered off | ||
181 | * the USB bus ... | ||
182 | */ | ||
183 | st0 = 1 << USB_DEVICE_SELF_POWERED; | ||
184 | |||
185 | /* | ||
186 | * Need to double check how remote wakeup actually works | ||
187 | * on that chip and what triggers it. | ||
188 | */ | ||
189 | if (ep->vhub->wakeup_en) | ||
190 | st0 |= 1 << USB_DEVICE_REMOTE_WAKEUP; | ||
191 | |||
192 | return ast_vhub_simple_reply(ep, st0, 0); | ||
193 | } | ||
194 | |||
195 | static int ast_vhub_hub_ep_status(struct ast_vhub_ep *ep, | ||
196 | u16 wIndex, u16 wValue) | ||
197 | { | ||
198 | int ep_num; | ||
199 | u8 st0 = 0; | ||
200 | |||
201 | ep_num = wIndex & USB_ENDPOINT_NUMBER_MASK; | ||
202 | EPDBG(ep, "GET_STATUS(ep%d)\n", ep_num); | ||
203 | |||
204 | /* On the hub we have only EP 0 and 1 */ | ||
205 | if (ep_num == 1) { | ||
206 | if (ep->vhub->ep1_stalled) | ||
207 | st0 |= 1 << USB_ENDPOINT_HALT; | ||
208 | } else if (ep_num != 0) | ||
209 | return std_req_stall; | ||
210 | |||
211 | return ast_vhub_simple_reply(ep, st0, 0); | ||
212 | } | ||
213 | |||
214 | static int ast_vhub_hub_dev_feature(struct ast_vhub_ep *ep, | ||
215 | u16 wIndex, u16 wValue, | ||
216 | bool is_set) | ||
217 | { | ||
218 | EPDBG(ep, "%s_FEATURE(dev val=%02x)\n", | ||
219 | is_set ? "SET" : "CLEAR", wValue); | ||
220 | |||
221 | if (wValue != USB_DEVICE_REMOTE_WAKEUP) | ||
222 | return std_req_stall; | ||
223 | |||
224 | ep->vhub->wakeup_en = is_set; | ||
225 | EPDBG(ep, "Hub remote wakeup %s\n", | ||
226 | is_set ? "enabled" : "disabled"); | ||
227 | |||
228 | return std_req_complete; | ||
229 | } | ||
230 | |||
231 | static int ast_vhub_hub_ep_feature(struct ast_vhub_ep *ep, | ||
232 | u16 wIndex, u16 wValue, | ||
233 | bool is_set) | ||
234 | { | ||
235 | int ep_num; | ||
236 | u32 reg; | ||
237 | |||
238 | ep_num = wIndex & USB_ENDPOINT_NUMBER_MASK; | ||
239 | EPDBG(ep, "%s_FEATURE(ep%d val=%02x)\n", | ||
240 | is_set ? "SET" : "CLEAR", ep_num, wValue); | ||
241 | |||
242 | if (ep_num > 1) | ||
243 | return std_req_stall; | ||
244 | if (wValue != USB_ENDPOINT_HALT) | ||
245 | return std_req_stall; | ||
246 | if (ep_num == 0) | ||
247 | return std_req_complete; | ||
248 | |||
249 | EPDBG(ep, "%s stall on EP 1\n", | ||
250 | is_set ? "setting" : "clearing"); | ||
251 | |||
252 | ep->vhub->ep1_stalled = is_set; | ||
253 | reg = readl(ep->vhub->regs + AST_VHUB_EP1_CTRL); | ||
254 | if (is_set) { | ||
255 | reg |= VHUB_EP1_CTRL_STALL; | ||
256 | } else { | ||
257 | reg &= ~VHUB_EP1_CTRL_STALL; | ||
258 | reg |= VHUB_EP1_CTRL_RESET_TOGGLE; | ||
259 | } | ||
260 | writel(reg, ep->vhub->regs + AST_VHUB_EP1_CTRL); | ||
261 | |||
262 | return std_req_complete; | ||
263 | } | ||
264 | |||
265 | static int ast_vhub_rep_desc(struct ast_vhub_ep *ep, | ||
266 | u8 desc_type, u16 len) | ||
267 | { | ||
268 | size_t dsize; | ||
269 | |||
270 | EPDBG(ep, "GET_DESCRIPTOR(type:%d)\n", desc_type); | ||
271 | |||
272 | /* | ||
273 | * Copy first to EP buffer and send from there, so | ||
274 | * we can do some in-place patching if needed. We know | ||
275 | * the EP buffer is big enough but ensure that doesn't | ||
276 | * change. We do that now rather than later after we | ||
277 | * have checked sizes etc... to avoid a gcc bug where | ||
278 | * it thinks len is constant and barfs about read | ||
279 | * overflows in memcpy. | ||
280 | */ | ||
281 | switch(desc_type) { | ||
282 | case USB_DT_DEVICE: | ||
283 | dsize = USB_DT_DEVICE_SIZE; | ||
284 | memcpy(ep->buf, &ast_vhub_dev_desc, dsize); | ||
285 | BUILD_BUG_ON(dsize > sizeof(ast_vhub_dev_desc)); | ||
286 | BUILD_BUG_ON(USB_DT_DEVICE_SIZE >= AST_VHUB_EP0_MAX_PACKET); | ||
287 | break; | ||
288 | case USB_DT_CONFIG: | ||
289 | dsize = AST_VHUB_CONF_DESC_SIZE; | ||
290 | memcpy(ep->buf, &ast_vhub_conf_desc, dsize); | ||
291 | BUILD_BUG_ON(dsize > sizeof(ast_vhub_conf_desc)); | ||
292 | BUILD_BUG_ON(AST_VHUB_CONF_DESC_SIZE >= AST_VHUB_EP0_MAX_PACKET); | ||
293 | break; | ||
294 | case USB_DT_HUB: | ||
295 | dsize = AST_VHUB_HUB_DESC_SIZE; | ||
296 | memcpy(ep->buf, &ast_vhub_hub_desc, dsize); | ||
297 | BUILD_BUG_ON(dsize > sizeof(ast_vhub_hub_desc)); | ||
298 | BUILD_BUG_ON(AST_VHUB_HUB_DESC_SIZE >= AST_VHUB_EP0_MAX_PACKET); | ||
299 | break; | ||
300 | default: | ||
301 | return std_req_stall; | ||
302 | } | ||
303 | |||
304 | /* Crop requested length */ | ||
305 | if (len > dsize) | ||
306 | len = dsize; | ||
307 | |||
308 | /* Patch it if forcing USB1 */ | ||
309 | if (desc_type == USB_DT_DEVICE && ep->vhub->force_usb1) | ||
310 | ast_vhub_patch_dev_desc_usb1(ep->buf); | ||
311 | |||
312 | /* Shoot it from the EP buffer */ | ||
313 | return ast_vhub_reply(ep, NULL, len); | ||
314 | } | ||
315 | |||
316 | static int ast_vhub_rep_string(struct ast_vhub_ep *ep, | ||
317 | u8 string_id, u16 lang_id, | ||
318 | u16 len) | ||
319 | { | ||
320 | int rc = usb_gadget_get_string (&ast_vhub_strings, string_id, ep->buf); | ||
321 | |||
322 | /* | ||
323 | * This should never happen unless we put too big strings in | ||
324 | * the array above | ||
325 | */ | ||
326 | BUG_ON(rc >= AST_VHUB_EP0_MAX_PACKET); | ||
327 | |||
328 | if (rc < 0) | ||
329 | return std_req_stall; | ||
330 | |||
331 | /* Shoot it from the EP buffer */ | ||
332 | return ast_vhub_reply(ep, NULL, min_t(u16, rc, len)); | ||
333 | } | ||
334 | |||
335 | enum std_req_rc ast_vhub_std_hub_request(struct ast_vhub_ep *ep, | ||
336 | struct usb_ctrlrequest *crq) | ||
337 | { | ||
338 | struct ast_vhub *vhub = ep->vhub; | ||
339 | u16 wValue, wIndex, wLength; | ||
340 | |||
341 | wValue = le16_to_cpu(crq->wValue); | ||
342 | wIndex = le16_to_cpu(crq->wIndex); | ||
343 | wLength = le16_to_cpu(crq->wLength); | ||
344 | |||
345 | /* First packet, grab speed */ | ||
346 | if (vhub->speed == USB_SPEED_UNKNOWN) { | ||
347 | u32 ustat = readl(vhub->regs + AST_VHUB_USBSTS); | ||
348 | if (ustat & VHUB_USBSTS_HISPEED) | ||
349 | vhub->speed = USB_SPEED_HIGH; | ||
350 | else | ||
351 | vhub->speed = USB_SPEED_FULL; | ||
352 | UDCDBG(vhub, "USB status=%08x speed=%s\n", ustat, | ||
353 | vhub->speed == USB_SPEED_HIGH ? "high" : "full"); | ||
354 | } | ||
355 | |||
356 | switch ((crq->bRequestType << 8) | crq->bRequest) { | ||
357 | /* SET_ADDRESS */ | ||
358 | case DeviceOutRequest | USB_REQ_SET_ADDRESS: | ||
359 | EPDBG(ep, "SET_ADDRESS: Got address %x\n", wValue); | ||
360 | writel(wValue, vhub->regs + AST_VHUB_CONF); | ||
361 | return std_req_complete; | ||
362 | |||
363 | /* GET_STATUS */ | ||
364 | case DeviceRequest | USB_REQ_GET_STATUS: | ||
365 | return ast_vhub_hub_dev_status(ep, wIndex, wValue); | ||
366 | case InterfaceRequest | USB_REQ_GET_STATUS: | ||
367 | return ast_vhub_simple_reply(ep, 0, 0); | ||
368 | case EndpointRequest | USB_REQ_GET_STATUS: | ||
369 | return ast_vhub_hub_ep_status(ep, wIndex, wValue); | ||
370 | |||
371 | /* SET/CLEAR_FEATURE */ | ||
372 | case DeviceOutRequest | USB_REQ_SET_FEATURE: | ||
373 | return ast_vhub_hub_dev_feature(ep, wIndex, wValue, true); | ||
374 | case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: | ||
375 | return ast_vhub_hub_dev_feature(ep, wIndex, wValue, false); | ||
376 | case EndpointOutRequest | USB_REQ_SET_FEATURE: | ||
377 | return ast_vhub_hub_ep_feature(ep, wIndex, wValue, true); | ||
378 | case EndpointOutRequest | USB_REQ_CLEAR_FEATURE: | ||
379 | return ast_vhub_hub_ep_feature(ep, wIndex, wValue, false); | ||
380 | |||
381 | /* GET/SET_CONFIGURATION */ | ||
382 | case DeviceRequest | USB_REQ_GET_CONFIGURATION: | ||
383 | return ast_vhub_simple_reply(ep, 1); | ||
384 | case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: | ||
385 | if (wValue != 1) | ||
386 | return std_req_stall; | ||
387 | return std_req_complete; | ||
388 | |||
389 | /* GET_DESCRIPTOR */ | ||
390 | case DeviceRequest | USB_REQ_GET_DESCRIPTOR: | ||
391 | switch (wValue >> 8) { | ||
392 | case USB_DT_DEVICE: | ||
393 | case USB_DT_CONFIG: | ||
394 | return ast_vhub_rep_desc(ep, wValue >> 8, | ||
395 | wLength); | ||
396 | case USB_DT_STRING: | ||
397 | return ast_vhub_rep_string(ep, wValue & 0xff, | ||
398 | wIndex, wLength); | ||
399 | } | ||
400 | return std_req_stall; | ||
401 | |||
402 | /* GET/SET_INTERFACE */ | ||
403 | case DeviceRequest | USB_REQ_GET_INTERFACE: | ||
404 | return ast_vhub_simple_reply(ep, 0); | ||
405 | case DeviceOutRequest | USB_REQ_SET_INTERFACE: | ||
406 | if (wValue != 0 || wIndex != 0) | ||
407 | return std_req_stall; | ||
408 | return std_req_complete; | ||
409 | } | ||
410 | return std_req_stall; | ||
411 | } | ||
412 | |||
413 | static void ast_vhub_update_hub_ep1(struct ast_vhub *vhub, | ||
414 | unsigned int port) | ||
415 | { | ||
416 | /* Update HW EP1 response */ | ||
417 | u32 reg = readl(vhub->regs + AST_VHUB_EP1_STS_CHG); | ||
418 | u32 pmask = (1 << (port + 1)); | ||
419 | if (vhub->ports[port].change) | ||
420 | reg |= pmask; | ||
421 | else | ||
422 | reg &= ~pmask; | ||
423 | writel(reg, vhub->regs + AST_VHUB_EP1_STS_CHG); | ||
424 | } | ||
425 | |||
426 | static void ast_vhub_change_port_stat(struct ast_vhub *vhub, | ||
427 | unsigned int port, | ||
428 | u16 clr_flags, | ||
429 | u16 set_flags, | ||
430 | bool set_c) | ||
431 | { | ||
432 | struct ast_vhub_port *p = &vhub->ports[port]; | ||
433 | u16 prev; | ||
434 | |||
435 | /* Update port status */ | ||
436 | prev = p->status; | ||
437 | p->status = (prev & ~clr_flags) | set_flags; | ||
438 | DDBG(&p->dev, "port %d status %04x -> %04x (C=%d)\n", | ||
439 | port + 1, prev, p->status, set_c); | ||
440 | |||
441 | /* Update change bits if needed */ | ||
442 | if (set_c) { | ||
443 | u16 chg = p->status ^ prev; | ||
444 | |||
445 | /* Only these are relevant for change */ | ||
446 | chg &= USB_PORT_STAT_C_CONNECTION | | ||
447 | USB_PORT_STAT_C_ENABLE | | ||
448 | USB_PORT_STAT_C_SUSPEND | | ||
449 | USB_PORT_STAT_C_OVERCURRENT | | ||
450 | USB_PORT_STAT_C_RESET | | ||
451 | USB_PORT_STAT_C_L1; | ||
452 | p->change |= chg; | ||
453 | |||
454 | ast_vhub_update_hub_ep1(vhub, port); | ||
455 | } | ||
456 | } | ||
457 | |||
458 | static void ast_vhub_send_host_wakeup(struct ast_vhub *vhub) | ||
459 | { | ||
460 | u32 reg = readl(vhub->regs + AST_VHUB_CTRL); | ||
461 | UDCDBG(vhub, "Waking up host !\n"); | ||
462 | reg |= VHUB_CTRL_MANUAL_REMOTE_WAKEUP; | ||
463 | writel(reg, vhub->regs + AST_VHUB_CTRL); | ||
464 | } | ||
465 | |||
466 | void ast_vhub_device_connect(struct ast_vhub *vhub, | ||
467 | unsigned int port, bool on) | ||
468 | { | ||
469 | if (on) | ||
470 | ast_vhub_change_port_stat(vhub, port, 0, | ||
471 | USB_PORT_STAT_CONNECTION, true); | ||
472 | else | ||
473 | ast_vhub_change_port_stat(vhub, port, | ||
474 | USB_PORT_STAT_CONNECTION | | ||
475 | USB_PORT_STAT_ENABLE, | ||
476 | 0, true); | ||
477 | |||
478 | /* | ||
479 | * If the hub is set to wakup the host on connection events | ||
480 | * then send a wakeup. | ||
481 | */ | ||
482 | if (vhub->wakeup_en) | ||
483 | ast_vhub_send_host_wakeup(vhub); | ||
484 | } | ||
485 | |||
486 | static void ast_vhub_wake_work(struct work_struct *work) | ||
487 | { | ||
488 | struct ast_vhub *vhub = container_of(work, | ||
489 | struct ast_vhub, | ||
490 | wake_work); | ||
491 | unsigned long flags; | ||
492 | unsigned int i; | ||
493 | |||
494 | /* | ||
495 | * Wake all sleeping ports. If a port is suspended by | ||
496 | * the host suspend (without explicit state suspend), | ||
497 | * we let the normal host wake path deal with it later. | ||
498 | */ | ||
499 | spin_lock_irqsave(&vhub->lock, flags); | ||
500 | for (i = 0; i < AST_VHUB_NUM_PORTS; i++) { | ||
501 | struct ast_vhub_port *p = &vhub->ports[i]; | ||
502 | |||
503 | if (!(p->status & USB_PORT_STAT_SUSPEND)) | ||
504 | continue; | ||
505 | ast_vhub_change_port_stat(vhub, i, | ||
506 | USB_PORT_STAT_SUSPEND, | ||
507 | 0, true); | ||
508 | ast_vhub_dev_resume(&p->dev); | ||
509 | } | ||
510 | ast_vhub_send_host_wakeup(vhub); | ||
511 | spin_unlock_irqrestore(&vhub->lock, flags); | ||
512 | } | ||
513 | |||
514 | void ast_vhub_hub_wake_all(struct ast_vhub *vhub) | ||
515 | { | ||
516 | /* | ||
517 | * A device is trying to wake the world, because this | ||
518 | * can recurse into the device, we break the call chain | ||
519 | * using a work queue | ||
520 | */ | ||
521 | schedule_work(&vhub->wake_work); | ||
522 | } | ||
523 | |||
524 | static void ast_vhub_port_reset(struct ast_vhub *vhub, u8 port) | ||
525 | { | ||
526 | struct ast_vhub_port *p = &vhub->ports[port]; | ||
527 | u16 set, clr, speed; | ||
528 | |||
529 | /* First mark disabled */ | ||
530 | ast_vhub_change_port_stat(vhub, port, | ||
531 | USB_PORT_STAT_ENABLE | | ||
532 | USB_PORT_STAT_SUSPEND, | ||
533 | USB_PORT_STAT_RESET, | ||
534 | false); | ||
535 | |||
536 | if (!p->dev.driver) | ||
537 | return; | ||
538 | |||
539 | /* | ||
540 | * This will either "start" the port or reset the | ||
541 | * device if already started... | ||
542 | */ | ||
543 | ast_vhub_dev_reset(&p->dev); | ||
544 | |||
545 | /* Grab the right speed */ | ||
546 | speed = p->dev.driver->max_speed; | ||
547 | if (speed == USB_SPEED_UNKNOWN || speed > vhub->speed) | ||
548 | speed = vhub->speed; | ||
549 | |||
550 | switch (speed) { | ||
551 | case USB_SPEED_LOW: | ||
552 | set = USB_PORT_STAT_LOW_SPEED; | ||
553 | clr = USB_PORT_STAT_HIGH_SPEED; | ||
554 | break; | ||
555 | case USB_SPEED_FULL: | ||
556 | set = 0; | ||
557 | clr = USB_PORT_STAT_LOW_SPEED | | ||
558 | USB_PORT_STAT_HIGH_SPEED; | ||
559 | break; | ||
560 | case USB_SPEED_HIGH: | ||
561 | set = USB_PORT_STAT_HIGH_SPEED; | ||
562 | clr = USB_PORT_STAT_LOW_SPEED; | ||
563 | break; | ||
564 | default: | ||
565 | UDCDBG(vhub, "Unsupported speed %d when" | ||
566 | " connecting device\n", | ||
567 | speed); | ||
568 | return; | ||
569 | } | ||
570 | clr |= USB_PORT_STAT_RESET; | ||
571 | set |= USB_PORT_STAT_ENABLE; | ||
572 | |||
573 | /* This should ideally be delayed ... */ | ||
574 | ast_vhub_change_port_stat(vhub, port, clr, set, true); | ||
575 | } | ||
576 | |||
577 | static enum std_req_rc ast_vhub_set_port_feature(struct ast_vhub_ep *ep, | ||
578 | u8 port, u16 feat) | ||
579 | { | ||
580 | struct ast_vhub *vhub = ep->vhub; | ||
581 | struct ast_vhub_port *p; | ||
582 | |||
583 | if (port == 0 || port > AST_VHUB_NUM_PORTS) | ||
584 | return std_req_stall; | ||
585 | port--; | ||
586 | p = &vhub->ports[port]; | ||
587 | |||
588 | switch(feat) { | ||
589 | case USB_PORT_FEAT_SUSPEND: | ||
590 | if (!(p->status & USB_PORT_STAT_ENABLE)) | ||
591 | return std_req_complete; | ||
592 | ast_vhub_change_port_stat(vhub, port, | ||
593 | 0, USB_PORT_STAT_SUSPEND, | ||
594 | false); | ||
595 | ast_vhub_dev_suspend(&p->dev); | ||
596 | return std_req_complete; | ||
597 | case USB_PORT_FEAT_RESET: | ||
598 | EPDBG(ep, "Port reset !\n"); | ||
599 | ast_vhub_port_reset(vhub, port); | ||
600 | return std_req_complete; | ||
601 | case USB_PORT_FEAT_POWER: | ||
602 | /* | ||
603 | * On Power-on, we mark the connected flag changed, | ||
604 | * if there's a connected device, some hosts will | ||
605 | * otherwise fail to detect it. | ||
606 | */ | ||
607 | if (p->status & USB_PORT_STAT_CONNECTION) { | ||
608 | p->change |= USB_PORT_STAT_C_CONNECTION; | ||
609 | ast_vhub_update_hub_ep1(vhub, port); | ||
610 | } | ||
611 | return std_req_complete; | ||
612 | case USB_PORT_FEAT_TEST: | ||
613 | case USB_PORT_FEAT_INDICATOR: | ||
614 | /* We don't do anything with these */ | ||
615 | return std_req_complete; | ||
616 | } | ||
617 | return std_req_stall; | ||
618 | } | ||
619 | |||
620 | static enum std_req_rc ast_vhub_clr_port_feature(struct ast_vhub_ep *ep, | ||
621 | u8 port, u16 feat) | ||
622 | { | ||
623 | struct ast_vhub *vhub = ep->vhub; | ||
624 | struct ast_vhub_port *p; | ||
625 | |||
626 | if (port == 0 || port > AST_VHUB_NUM_PORTS) | ||
627 | return std_req_stall; | ||
628 | port--; | ||
629 | p = &vhub->ports[port]; | ||
630 | |||
631 | switch(feat) { | ||
632 | case USB_PORT_FEAT_ENABLE: | ||
633 | ast_vhub_change_port_stat(vhub, port, | ||
634 | USB_PORT_STAT_ENABLE | | ||
635 | USB_PORT_STAT_SUSPEND, 0, | ||
636 | false); | ||
637 | ast_vhub_dev_suspend(&p->dev); | ||
638 | return std_req_complete; | ||
639 | case USB_PORT_FEAT_SUSPEND: | ||
640 | if (!(p->status & USB_PORT_STAT_SUSPEND)) | ||
641 | return std_req_complete; | ||
642 | ast_vhub_change_port_stat(vhub, port, | ||
643 | USB_PORT_STAT_SUSPEND, 0, | ||
644 | false); | ||
645 | ast_vhub_dev_resume(&p->dev); | ||
646 | return std_req_complete; | ||
647 | case USB_PORT_FEAT_POWER: | ||
648 | /* We don't do power control */ | ||
649 | return std_req_complete; | ||
650 | case USB_PORT_FEAT_INDICATOR: | ||
651 | /* We don't have indicators */ | ||
652 | return std_req_complete; | ||
653 | case USB_PORT_FEAT_C_CONNECTION: | ||
654 | case USB_PORT_FEAT_C_ENABLE: | ||
655 | case USB_PORT_FEAT_C_SUSPEND: | ||
656 | case USB_PORT_FEAT_C_OVER_CURRENT: | ||
657 | case USB_PORT_FEAT_C_RESET: | ||
658 | /* Clear state-change feature */ | ||
659 | p->change &= ~(1u << (feat - 16)); | ||
660 | ast_vhub_update_hub_ep1(vhub, port); | ||
661 | return std_req_complete; | ||
662 | } | ||
663 | return std_req_stall; | ||
664 | } | ||
665 | |||
666 | static enum std_req_rc ast_vhub_get_port_stat(struct ast_vhub_ep *ep, | ||
667 | u8 port) | ||
668 | { | ||
669 | struct ast_vhub *vhub = ep->vhub; | ||
670 | u16 stat, chg; | ||
671 | |||
672 | if (port == 0 || port > AST_VHUB_NUM_PORTS) | ||
673 | return std_req_stall; | ||
674 | port--; | ||
675 | |||
676 | stat = vhub->ports[port].status; | ||
677 | chg = vhub->ports[port].change; | ||
678 | |||
679 | /* We always have power */ | ||
680 | stat |= USB_PORT_STAT_POWER; | ||
681 | |||
682 | EPDBG(ep, " port status=%04x change=%04x\n", stat, chg); | ||
683 | |||
684 | return ast_vhub_simple_reply(ep, | ||
685 | stat & 0xff, | ||
686 | stat >> 8, | ||
687 | chg & 0xff, | ||
688 | chg >> 8); | ||
689 | } | ||
690 | |||
691 | enum std_req_rc ast_vhub_class_hub_request(struct ast_vhub_ep *ep, | ||
692 | struct usb_ctrlrequest *crq) | ||
693 | { | ||
694 | u16 wValue, wIndex, wLength; | ||
695 | |||
696 | wValue = le16_to_cpu(crq->wValue); | ||
697 | wIndex = le16_to_cpu(crq->wIndex); | ||
698 | wLength = le16_to_cpu(crq->wLength); | ||
699 | |||
700 | switch ((crq->bRequestType << 8) | crq->bRequest) { | ||
701 | case GetHubStatus: | ||
702 | EPDBG(ep, "GetHubStatus\n"); | ||
703 | return ast_vhub_simple_reply(ep, 0, 0, 0, 0); | ||
704 | case GetPortStatus: | ||
705 | EPDBG(ep, "GetPortStatus(%d)\n", wIndex & 0xff); | ||
706 | return ast_vhub_get_port_stat(ep, wIndex & 0xf); | ||
707 | case GetHubDescriptor: | ||
708 | if (wValue != (USB_DT_HUB << 8)) | ||
709 | return std_req_stall; | ||
710 | EPDBG(ep, "GetHubDescriptor(%d)\n", wIndex & 0xff); | ||
711 | return ast_vhub_rep_desc(ep, USB_DT_HUB, wLength); | ||
712 | case SetHubFeature: | ||
713 | case ClearHubFeature: | ||
714 | EPDBG(ep, "Get/SetHubFeature(%d)\n", wValue); | ||
715 | /* No feature, just complete the requests */ | ||
716 | if (wValue == C_HUB_LOCAL_POWER || | ||
717 | wValue == C_HUB_OVER_CURRENT) | ||
718 | return std_req_complete; | ||
719 | return std_req_stall; | ||
720 | case SetPortFeature: | ||
721 | EPDBG(ep, "SetPortFeature(%d,%d)\n", wIndex & 0xf, wValue); | ||
722 | return ast_vhub_set_port_feature(ep, wIndex & 0xf, wValue); | ||
723 | case ClearPortFeature: | ||
724 | EPDBG(ep, "ClearPortFeature(%d,%d)\n", wIndex & 0xf, wValue); | ||
725 | return ast_vhub_clr_port_feature(ep, wIndex & 0xf, wValue); | ||
726 | default: | ||
727 | EPDBG(ep, "Unknown class request\n"); | ||
728 | } | ||
729 | return std_req_stall; | ||
730 | } | ||
731 | |||
732 | void ast_vhub_hub_suspend(struct ast_vhub *vhub) | ||
733 | { | ||
734 | unsigned int i; | ||
735 | |||
736 | UDCDBG(vhub, "USB bus suspend\n"); | ||
737 | |||
738 | if (vhub->suspended) | ||
739 | return; | ||
740 | |||
741 | vhub->suspended = true; | ||
742 | |||
743 | /* | ||
744 | * Forward to unsuspended ports without changing | ||
745 | * their connection status. | ||
746 | */ | ||
747 | for (i = 0; i < AST_VHUB_NUM_PORTS; i++) { | ||
748 | struct ast_vhub_port *p = &vhub->ports[i]; | ||
749 | |||
750 | if (!(p->status & USB_PORT_STAT_SUSPEND)) | ||
751 | ast_vhub_dev_suspend(&p->dev); | ||
752 | } | ||
753 | } | ||
754 | |||
755 | void ast_vhub_hub_resume(struct ast_vhub *vhub) | ||
756 | { | ||
757 | unsigned int i; | ||
758 | |||
759 | UDCDBG(vhub, "USB bus resume\n"); | ||
760 | |||
761 | if (!vhub->suspended) | ||
762 | return; | ||
763 | |||
764 | vhub->suspended = false; | ||
765 | |||
766 | /* | ||
767 | * Forward to unsuspended ports without changing | ||
768 | * their connection status. | ||
769 | */ | ||
770 | for (i = 0; i < AST_VHUB_NUM_PORTS; i++) { | ||
771 | struct ast_vhub_port *p = &vhub->ports[i]; | ||
772 | |||
773 | if (!(p->status & USB_PORT_STAT_SUSPEND)) | ||
774 | ast_vhub_dev_resume(&p->dev); | ||
775 | } | ||
776 | } | ||
777 | |||
778 | void ast_vhub_hub_reset(struct ast_vhub *vhub) | ||
779 | { | ||
780 | unsigned int i; | ||
781 | |||
782 | UDCDBG(vhub, "USB bus reset\n"); | ||
783 | |||
784 | /* | ||
785 | * Is the speed known ? If not we don't care, we aren't | ||
786 | * initialized yet and ports haven't been enabled. | ||
787 | */ | ||
788 | if (vhub->speed == USB_SPEED_UNKNOWN) | ||
789 | return; | ||
790 | |||
791 | /* We aren't suspended anymore obviously */ | ||
792 | vhub->suspended = false; | ||
793 | |||
794 | /* No speed set */ | ||
795 | vhub->speed = USB_SPEED_UNKNOWN; | ||
796 | |||
797 | /* Wakeup not enabled anymore */ | ||
798 | vhub->wakeup_en = false; | ||
799 | |||
800 | /* | ||
801 | * Clear all port status, disable gadgets and "suspend" | ||
802 | * them. They will be woken up by a port reset. | ||
803 | */ | ||
804 | for (i = 0; i < AST_VHUB_NUM_PORTS; i++) { | ||
805 | struct ast_vhub_port *p = &vhub->ports[i]; | ||
806 | |||
807 | /* Only keep the connected flag */ | ||
808 | p->status &= USB_PORT_STAT_CONNECTION; | ||
809 | p->change = 0; | ||
810 | |||
811 | /* Suspend the gadget if any */ | ||
812 | ast_vhub_dev_suspend(&p->dev); | ||
813 | } | ||
814 | |||
815 | /* Cleanup HW */ | ||
816 | writel(0, vhub->regs + AST_VHUB_CONF); | ||
817 | writel(0, vhub->regs + AST_VHUB_EP0_CTRL); | ||
818 | writel(VHUB_EP1_CTRL_RESET_TOGGLE | | ||
819 | VHUB_EP1_CTRL_ENABLE, | ||
820 | vhub->regs + AST_VHUB_EP1_CTRL); | ||
821 | writel(0, vhub->regs + AST_VHUB_EP1_STS_CHG); | ||
822 | } | ||
823 | |||
824 | void ast_vhub_init_hub(struct ast_vhub *vhub) | ||
825 | { | ||
826 | vhub->speed = USB_SPEED_UNKNOWN; | ||
827 | INIT_WORK(&vhub->wake_work, ast_vhub_wake_work); | ||
828 | } | ||
829 | |||
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/vhub.h b/drivers/usb/gadget/udc/aspeed-vhub/vhub.h new file mode 100644 index 000000000000..2b040257bc1f --- /dev/null +++ b/drivers/usb/gadget/udc/aspeed-vhub/vhub.h | |||
@@ -0,0 +1,514 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0+ */ | ||
2 | #ifndef __ASPEED_VHUB_H | ||
3 | #define __ASPEED_VHUB_H | ||
4 | |||
5 | /***************************** | ||
6 | * * | ||
7 | * VHUB register definitions * | ||
8 | * * | ||
9 | *****************************/ | ||
10 | |||
11 | #define AST_VHUB_CTRL 0x00 /* Root Function Control & Status Register */ | ||
12 | #define AST_VHUB_CONF 0x04 /* Root Configuration Setting Register */ | ||
13 | #define AST_VHUB_IER 0x08 /* Interrupt Ctrl Register */ | ||
14 | #define AST_VHUB_ISR 0x0C /* Interrupt Status Register */ | ||
15 | #define AST_VHUB_EP_ACK_IER 0x10 /* Programmable Endpoint Pool ACK Interrupt Enable Register */ | ||
16 | #define AST_VHUB_EP_NACK_IER 0x14 /* Programmable Endpoint Pool NACK Interrupt Enable Register */ | ||
17 | #define AST_VHUB_EP_ACK_ISR 0x18 /* Programmable Endpoint Pool ACK Interrupt Status Register */ | ||
18 | #define AST_VHUB_EP_NACK_ISR 0x1C /* Programmable Endpoint Pool NACK Interrupt Status Register */ | ||
19 | #define AST_VHUB_SW_RESET 0x20 /* Device Controller Soft Reset Enable Register */ | ||
20 | #define AST_VHUB_USBSTS 0x24 /* USB Status Register */ | ||
21 | #define AST_VHUB_EP_TOGGLE 0x28 /* Programmable Endpoint Pool Data Toggle Value Set */ | ||
22 | #define AST_VHUB_ISO_FAIL_ACC 0x2C /* Isochronous Transaction Fail Accumulator */ | ||
23 | #define AST_VHUB_EP0_CTRL 0x30 /* Endpoint 0 Contrl/Status Register */ | ||
24 | #define AST_VHUB_EP0_DATA 0x34 /* Base Address of Endpoint 0 In/OUT Data Buffer Register */ | ||
25 | #define AST_VHUB_EP1_CTRL 0x38 /* Endpoint 1 Contrl/Status Register */ | ||
26 | #define AST_VHUB_EP1_STS_CHG 0x3C /* Endpoint 1 Status Change Bitmap Data */ | ||
27 | #define AST_VHUB_SETUP0 0x80 /* Root Device Setup Data Buffer0 */ | ||
28 | #define AST_VHUB_SETUP1 0x84 /* Root Device Setup Data Buffer1 */ | ||
29 | |||
30 | /* Main control reg */ | ||
31 | #define VHUB_CTRL_PHY_CLK (1 << 31) | ||
32 | #define VHUB_CTRL_PHY_LOOP_TEST (1 << 25) | ||
33 | #define VHUB_CTRL_DN_PWN (1 << 24) | ||
34 | #define VHUB_CTRL_DP_PWN (1 << 23) | ||
35 | #define VHUB_CTRL_LONG_DESC (1 << 18) | ||
36 | #define VHUB_CTRL_ISO_RSP_CTRL (1 << 17) | ||
37 | #define VHUB_CTRL_SPLIT_IN (1 << 16) | ||
38 | #define VHUB_CTRL_LOOP_T_RESULT (1 << 15) | ||
39 | #define VHUB_CTRL_LOOP_T_STS (1 << 14) | ||
40 | #define VHUB_CTRL_PHY_BIST_RESULT (1 << 13) | ||
41 | #define VHUB_CTRL_PHY_BIST_CTRL (1 << 12) | ||
42 | #define VHUB_CTRL_PHY_RESET_DIS (1 << 11) | ||
43 | #define VHUB_CTRL_SET_TEST_MODE(x) ((x) << 8) | ||
44 | #define VHUB_CTRL_MANUAL_REMOTE_WAKEUP (1 << 4) | ||
45 | #define VHUB_CTRL_AUTO_REMOTE_WAKEUP (1 << 3) | ||
46 | #define VHUB_CTRL_CLK_STOP_SUSPEND (1 << 2) | ||
47 | #define VHUB_CTRL_FULL_SPEED_ONLY (1 << 1) | ||
48 | #define VHUB_CTRL_UPSTREAM_CONNECT (1 << 0) | ||
49 | |||
50 | /* IER & ISR */ | ||
51 | #define VHUB_IRQ_USB_CMD_DEADLOCK (1 << 18) | ||
52 | #define VHUB_IRQ_EP_POOL_NAK (1 << 17) | ||
53 | #define VHUB_IRQ_EP_POOL_ACK_STALL (1 << 16) | ||
54 | #define VHUB_IRQ_DEVICE5 (1 << 13) | ||
55 | #define VHUB_IRQ_DEVICE4 (1 << 12) | ||
56 | #define VHUB_IRQ_DEVICE3 (1 << 11) | ||
57 | #define VHUB_IRQ_DEVICE2 (1 << 10) | ||
58 | #define VHUB_IRQ_DEVICE1 (1 << 9) | ||
59 | #define VHUB_IRQ_BUS_RESUME (1 << 8) | ||
60 | #define VHUB_IRQ_BUS_SUSPEND (1 << 7) | ||
61 | #define VHUB_IRQ_BUS_RESET (1 << 6) | ||
62 | #define VHUB_IRQ_HUB_EP1_IN_DATA_ACK (1 << 5) | ||
63 | #define VHUB_IRQ_HUB_EP0_IN_DATA_NAK (1 << 4) | ||
64 | #define VHUB_IRQ_HUB_EP0_IN_ACK_STALL (1 << 3) | ||
65 | #define VHUB_IRQ_HUB_EP0_OUT_NAK (1 << 2) | ||
66 | #define VHUB_IRQ_HUB_EP0_OUT_ACK_STALL (1 << 1) | ||
67 | #define VHUB_IRQ_HUB_EP0_SETUP (1 << 0) | ||
68 | #define VHUB_IRQ_ACK_ALL 0x1ff | ||
69 | |||
70 | /* SW reset reg */ | ||
71 | #define VHUB_SW_RESET_EP_POOL (1 << 9) | ||
72 | #define VHUB_SW_RESET_DMA_CONTROLLER (1 << 8) | ||
73 | #define VHUB_SW_RESET_DEVICE5 (1 << 5) | ||
74 | #define VHUB_SW_RESET_DEVICE4 (1 << 4) | ||
75 | #define VHUB_SW_RESET_DEVICE3 (1 << 3) | ||
76 | #define VHUB_SW_RESET_DEVICE2 (1 << 2) | ||
77 | #define VHUB_SW_RESET_DEVICE1 (1 << 1) | ||
78 | #define VHUB_SW_RESET_ROOT_HUB (1 << 0) | ||
79 | #define VHUB_SW_RESET_ALL (VHUB_SW_RESET_EP_POOL | \ | ||
80 | VHUB_SW_RESET_DMA_CONTROLLER | \ | ||
81 | VHUB_SW_RESET_DEVICE5 | \ | ||
82 | VHUB_SW_RESET_DEVICE4 | \ | ||
83 | VHUB_SW_RESET_DEVICE3 | \ | ||
84 | VHUB_SW_RESET_DEVICE2 | \ | ||
85 | VHUB_SW_RESET_DEVICE1 | \ | ||
86 | VHUB_SW_RESET_ROOT_HUB) | ||
87 | /* EP ACK/NACK IRQ masks */ | ||
88 | #define VHUB_EP_IRQ(n) (1 << (n)) | ||
89 | #define VHUB_EP_IRQ_ALL 0x7fff /* 15 EPs */ | ||
90 | |||
91 | /* USB status reg */ | ||
92 | #define VHUB_USBSTS_HISPEED (1 << 27) | ||
93 | |||
94 | /* EP toggle */ | ||
95 | #define VHUB_EP_TOGGLE_VALUE (1 << 8) | ||
96 | #define VHUB_EP_TOGGLE_SET_EPNUM(x) ((x) & 0x1f) | ||
97 | |||
98 | /* HUB EP0 control */ | ||
99 | #define VHUB_EP0_CTRL_STALL (1 << 0) | ||
100 | #define VHUB_EP0_TX_BUFF_RDY (1 << 1) | ||
101 | #define VHUB_EP0_RX_BUFF_RDY (1 << 2) | ||
102 | #define VHUB_EP0_RX_LEN(x) (((x) >> 16) & 0x7f) | ||
103 | #define VHUB_EP0_SET_TX_LEN(x) (((x) & 0x7f) << 8) | ||
104 | |||
105 | /* HUB EP1 control */ | ||
106 | #define VHUB_EP1_CTRL_RESET_TOGGLE (1 << 2) | ||
107 | #define VHUB_EP1_CTRL_STALL (1 << 1) | ||
108 | #define VHUB_EP1_CTRL_ENABLE (1 << 0) | ||
109 | |||
110 | /*********************************** | ||
111 | * * | ||
112 | * per-device register definitions * | ||
113 | * * | ||
114 | ***********************************/ | ||
115 | #define AST_VHUB_DEV_EN_CTRL 0x00 | ||
116 | #define AST_VHUB_DEV_ISR 0x04 | ||
117 | #define AST_VHUB_DEV_EP0_CTRL 0x08 | ||
118 | #define AST_VHUB_DEV_EP0_DATA 0x0c | ||
119 | |||
120 | /* Device enable control */ | ||
121 | #define VHUB_DEV_EN_SET_ADDR(x) ((x) << 8) | ||
122 | #define VHUB_DEV_EN_ADDR_MASK ((0xff) << 8) | ||
123 | #define VHUB_DEV_EN_EP0_NAK_IRQEN (1 << 6) | ||
124 | #define VHUB_DEV_EN_EP0_IN_ACK_IRQEN (1 << 5) | ||
125 | #define VHUB_DEV_EN_EP0_OUT_NAK_IRQEN (1 << 4) | ||
126 | #define VHUB_DEV_EN_EP0_OUT_ACK_IRQEN (1 << 3) | ||
127 | #define VHUB_DEV_EN_EP0_SETUP_IRQEN (1 << 2) | ||
128 | #define VHUB_DEV_EN_SPEED_SEL_HIGH (1 << 1) | ||
129 | #define VHUB_DEV_EN_ENABLE_PORT (1 << 0) | ||
130 | |||
131 | /* Interrupt status */ | ||
132 | #define VHUV_DEV_IRQ_EP0_IN_DATA_NACK (1 << 4) | ||
133 | #define VHUV_DEV_IRQ_EP0_IN_ACK_STALL (1 << 3) | ||
134 | #define VHUV_DEV_IRQ_EP0_OUT_DATA_NACK (1 << 2) | ||
135 | #define VHUV_DEV_IRQ_EP0_OUT_ACK_STALL (1 << 1) | ||
136 | #define VHUV_DEV_IRQ_EP0_SETUP (1 << 0) | ||
137 | |||
138 | /* Control bits. | ||
139 | * | ||
140 | * Note: The driver relies on the bulk of those bits | ||
141 | * matching corresponding vHub EP0 control bits | ||
142 | */ | ||
143 | #define VHUB_DEV_EP0_CTRL_STALL VHUB_EP0_CTRL_STALL | ||
144 | #define VHUB_DEV_EP0_TX_BUFF_RDY VHUB_EP0_TX_BUFF_RDY | ||
145 | #define VHUB_DEV_EP0_RX_BUFF_RDY VHUB_EP0_RX_BUFF_RDY | ||
146 | #define VHUB_DEV_EP0_RX_LEN(x) VHUB_EP0_RX_LEN(x) | ||
147 | #define VHUB_DEV_EP0_SET_TX_LEN(x) VHUB_EP0_SET_TX_LEN(x) | ||
148 | |||
149 | /************************************* | ||
150 | * * | ||
151 | * per-endpoint register definitions * | ||
152 | * * | ||
153 | *************************************/ | ||
154 | |||
155 | #define AST_VHUB_EP_CONFIG 0x00 | ||
156 | #define AST_VHUB_EP_DMA_CTLSTAT 0x04 | ||
157 | #define AST_VHUB_EP_DESC_BASE 0x08 | ||
158 | #define AST_VHUB_EP_DESC_STATUS 0x0C | ||
159 | |||
160 | /* EP config reg */ | ||
161 | #define VHUB_EP_CFG_SET_MAX_PKT(x) (((x) & 0x3ff) << 16) | ||
162 | #define VHUB_EP_CFG_AUTO_DATA_DISABLE (1 << 13) | ||
163 | #define VHUB_EP_CFG_STALL_CTRL (1 << 12) | ||
164 | #define VHUB_EP_CFG_SET_EP_NUM(x) (((x) & 0xf) << 8) | ||
165 | #define VHUB_EP_CFG_SET_TYPE(x) ((x) << 5) | ||
166 | #define EP_TYPE_OFF 0 | ||
167 | #define EP_TYPE_BULK 1 | ||
168 | #define EP_TYPE_INT 2 | ||
169 | #define EP_TYPE_ISO 3 | ||
170 | #define VHUB_EP_CFG_DIR_OUT (1 << 4) | ||
171 | #define VHUB_EP_CFG_SET_DEV(x) ((x) << 1) | ||
172 | #define VHUB_EP_CFG_ENABLE (1 << 0) | ||
173 | |||
174 | /* EP DMA control */ | ||
175 | #define VHUB_EP_DMA_PROC_STATUS(x) (((x) >> 4) & 0xf) | ||
176 | #define EP_DMA_PROC_RX_IDLE 0 | ||
177 | #define EP_DMA_PROC_TX_IDLE 8 | ||
178 | #define VHUB_EP_DMA_IN_LONG_MODE (1 << 3) | ||
179 | #define VHUB_EP_DMA_OUT_CONTIG_MODE (1 << 3) | ||
180 | #define VHUB_EP_DMA_CTRL_RESET (1 << 2) | ||
181 | #define VHUB_EP_DMA_SINGLE_STAGE (1 << 1) | ||
182 | #define VHUB_EP_DMA_DESC_MODE (1 << 0) | ||
183 | |||
184 | /* EP DMA status */ | ||
185 | #define VHUB_EP_DMA_SET_TX_SIZE(x) ((x) << 16) | ||
186 | #define VHUB_EP_DMA_TX_SIZE(x) (((x) >> 16) & 0x7ff) | ||
187 | #define VHUB_EP_DMA_RPTR(x) (((x) >> 8) & 0xff) | ||
188 | #define VHUB_EP_DMA_SET_RPTR(x) (((x) & 0xff) << 8) | ||
189 | #define VHUB_EP_DMA_SET_CPU_WPTR(x) (x) | ||
190 | #define VHUB_EP_DMA_SINGLE_KICK (1 << 0) /* WPTR = 1 for single mode */ | ||
191 | |||
192 | /******************************* | ||
193 | * * | ||
194 | * DMA descriptors definitions * | ||
195 | * * | ||
196 | *******************************/ | ||
197 | |||
198 | /* Desc W1 IN */ | ||
199 | #define VHUB_DSC1_IN_INTERRUPT (1 << 31) | ||
200 | #define VHUB_DSC1_IN_SPID_DATA0 (0 << 14) | ||
201 | #define VHUB_DSC1_IN_SPID_DATA2 (1 << 14) | ||
202 | #define VHUB_DSC1_IN_SPID_DATA1 (2 << 14) | ||
203 | #define VHUB_DSC1_IN_SPID_MDATA (3 << 14) | ||
204 | #define VHUB_DSC1_IN_SET_LEN(x) ((x) & 0xfff) | ||
205 | #define VHUB_DSC1_IN_LEN(x) ((x) & 0xfff) | ||
206 | |||
207 | /**************************************** | ||
208 | * * | ||
209 | * Data structures and misc definitions * | ||
210 | * * | ||
211 | ****************************************/ | ||
212 | |||
213 | #define AST_VHUB_NUM_GEN_EPs 15 /* Generic non-0 EPs */ | ||
214 | #define AST_VHUB_NUM_PORTS 5 /* vHub ports */ | ||
215 | #define AST_VHUB_EP0_MAX_PACKET 64 /* EP0's max packet size */ | ||
216 | #define AST_VHUB_EPn_MAX_PACKET 1024 /* Generic EPs max packet size */ | ||
217 | #define AST_VHUB_DESCS_COUNT 256 /* Use 256 descriptor mode (valid | ||
218 | * values are 256 and 32) | ||
219 | */ | ||
220 | |||
221 | struct ast_vhub; | ||
222 | struct ast_vhub_dev; | ||
223 | |||
224 | /* | ||
225 | * DMA descriptor (generic EPs only, currently only used | ||
226 | * for IN endpoints | ||
227 | */ | ||
228 | struct ast_vhub_desc { | ||
229 | __le32 w0; | ||
230 | __le32 w1; | ||
231 | }; | ||
232 | |||
233 | /* A transfer request, either core-originated or internal */ | ||
234 | struct ast_vhub_req { | ||
235 | struct usb_request req; | ||
236 | struct list_head queue; | ||
237 | |||
238 | /* Actual count written to descriptors (desc mode only) */ | ||
239 | unsigned int act_count; | ||
240 | |||
241 | /* | ||
242 | * Desc number of the final packet or -1. For non-desc | ||
243 | * mode (or ep0), any >= 0 value means "last packet" | ||
244 | */ | ||
245 | int last_desc; | ||
246 | |||
247 | /* Request active (pending DMAs) */ | ||
248 | bool active : 1; | ||
249 | |||
250 | /* Internal request (don't call back core) */ | ||
251 | bool internal : 1; | ||
252 | }; | ||
253 | #define to_ast_req(__ureq) container_of(__ureq, struct ast_vhub_req, req) | ||
254 | |||
255 | /* Current state of an EP0 */ | ||
256 | enum ep0_state { | ||
257 | ep0_state_token, | ||
258 | ep0_state_data, | ||
259 | ep0_state_status, | ||
260 | }; | ||
261 | |||
262 | /* | ||
263 | * An endpoint, either generic, ep0, actual gadget EP | ||
264 | * or internal use vhub EP0. vhub EP1 doesn't have an | ||
265 | * associated structure as it's mostly HW managed. | ||
266 | */ | ||
267 | struct ast_vhub_ep { | ||
268 | struct usb_ep ep; | ||
269 | |||
270 | /* Request queue */ | ||
271 | struct list_head queue; | ||
272 | |||
273 | /* EP index in the device, 0 means this is an EP0 */ | ||
274 | unsigned int d_idx; | ||
275 | |||
276 | /* Dev pointer or NULL for vHub EP0 */ | ||
277 | struct ast_vhub_dev *dev; | ||
278 | |||
279 | /* vHub itself */ | ||
280 | struct ast_vhub *vhub; | ||
281 | |||
282 | /* | ||
283 | * DMA buffer for EP0, fallback DMA buffer for misaligned | ||
284 | * OUT transfers for generic EPs | ||
285 | */ | ||
286 | void *buf; | ||
287 | dma_addr_t buf_dma; | ||
288 | |||
289 | /* The rest depends on the EP type */ | ||
290 | union { | ||
291 | /* EP0 (either device or vhub) */ | ||
292 | struct { | ||
293 | /* | ||
294 | * EP0 registers are "similar" for | ||
295 | * vHub and devices but located in | ||
296 | * different places. | ||
297 | */ | ||
298 | void __iomem *ctlstat; | ||
299 | void __iomem *setup; | ||
300 | |||
301 | /* Current state & direction */ | ||
302 | enum ep0_state state; | ||
303 | bool dir_in; | ||
304 | |||
305 | /* Internal use request */ | ||
306 | struct ast_vhub_req req; | ||
307 | } ep0; | ||
308 | |||
309 | /* Generic endpoint (aka EPn) */ | ||
310 | struct { | ||
311 | /* Registers */ | ||
312 | void __iomem *regs; | ||
313 | |||
314 | /* Index in global pool (0..14) */ | ||
315 | unsigned int g_idx; | ||
316 | |||
317 | /* DMA Descriptors */ | ||
318 | struct ast_vhub_desc *descs; | ||
319 | dma_addr_t descs_dma; | ||
320 | unsigned int d_next; | ||
321 | unsigned int d_last; | ||
322 | unsigned int dma_conf; | ||
323 | |||
324 | /* Max chunk size for IN EPs */ | ||
325 | unsigned int chunk_max; | ||
326 | |||
327 | /* State flags */ | ||
328 | bool is_in : 1; | ||
329 | bool is_iso : 1; | ||
330 | bool stalled : 1; | ||
331 | bool wedged : 1; | ||
332 | bool enabled : 1; | ||
333 | bool desc_mode : 1; | ||
334 | } epn; | ||
335 | }; | ||
336 | }; | ||
337 | #define to_ast_ep(__uep) container_of(__uep, struct ast_vhub_ep, ep) | ||
338 | |||
339 | /* A device attached to a vHub port */ | ||
340 | struct ast_vhub_dev { | ||
341 | struct ast_vhub *vhub; | ||
342 | void __iomem *regs; | ||
343 | |||
344 | /* Device index (0...4) and name string */ | ||
345 | unsigned int index; | ||
346 | const char *name; | ||
347 | |||
348 | /* sysfs enclosure for the gadget gunk */ | ||
349 | struct device *port_dev; | ||
350 | |||
351 | /* Link to gadget core */ | ||
352 | struct usb_gadget gadget; | ||
353 | struct usb_gadget_driver *driver; | ||
354 | bool registered : 1; | ||
355 | bool wakeup_en : 1; | ||
356 | bool suspended : 1; | ||
357 | bool enabled : 1; | ||
358 | |||
359 | /* Endpoint structures */ | ||
360 | struct ast_vhub_ep ep0; | ||
361 | struct ast_vhub_ep *epns[AST_VHUB_NUM_GEN_EPs]; | ||
362 | |||
363 | }; | ||
364 | #define to_ast_dev(__g) container_of(__g, struct ast_vhub_dev, gadget) | ||
365 | |||
366 | /* Per vhub port stateinfo structure */ | ||
367 | struct ast_vhub_port { | ||
368 | /* Port status & status change registers */ | ||
369 | u16 status; | ||
370 | u16 change; | ||
371 | |||
372 | /* Associated device slot */ | ||
373 | struct ast_vhub_dev dev; | ||
374 | }; | ||
375 | |||
376 | /* Global vhub structure */ | ||
377 | struct ast_vhub { | ||
378 | struct platform_device *pdev; | ||
379 | void __iomem *regs; | ||
380 | int irq; | ||
381 | spinlock_t lock; | ||
382 | struct work_struct wake_work; | ||
383 | struct clk *clk; | ||
384 | |||
385 | /* EP0 DMA buffers allocated in one chunk */ | ||
386 | void *ep0_bufs; | ||
387 | dma_addr_t ep0_bufs_dma; | ||
388 | |||
389 | /* EP0 of the vhub itself */ | ||
390 | struct ast_vhub_ep ep0; | ||
391 | |||
392 | /* State of vhub ep1 */ | ||
393 | bool ep1_stalled : 1; | ||
394 | |||
395 | /* Per-port info */ | ||
396 | struct ast_vhub_port ports[AST_VHUB_NUM_PORTS]; | ||
397 | |||
398 | /* Generic EP data structures */ | ||
399 | struct ast_vhub_ep epns[AST_VHUB_NUM_GEN_EPs]; | ||
400 | |||
401 | /* Upstream bus is suspended ? */ | ||
402 | bool suspended : 1; | ||
403 | |||
404 | /* Hub itself can signal remote wakeup */ | ||
405 | bool wakeup_en : 1; | ||
406 | |||
407 | /* Force full speed only */ | ||
408 | bool force_usb1 : 1; | ||
409 | |||
410 | /* Upstream bus speed captured at bus reset */ | ||
411 | unsigned int speed; | ||
412 | }; | ||
413 | |||
414 | /* Standard request handlers result codes */ | ||
415 | enum std_req_rc { | ||
416 | std_req_stall = -1, /* Stall requested */ | ||
417 | std_req_complete = 0, /* Request completed with no data */ | ||
418 | std_req_data = 1, /* Request completed with data */ | ||
419 | std_req_driver = 2, /* Pass to driver pls */ | ||
420 | }; | ||
421 | |||
422 | #ifdef CONFIG_USB_GADGET_VERBOSE | ||
423 | #define UDCVDBG(u, fmt...) dev_dbg(&(u)->pdev->dev, fmt) | ||
424 | |||
425 | #define EPVDBG(ep, fmt, ...) do { \ | ||
426 | dev_dbg(&(ep)->vhub->pdev->dev, \ | ||
427 | "%s:EP%d " fmt, \ | ||
428 | (ep)->dev ? (ep)->dev->name : "hub", \ | ||
429 | (ep)->d_idx, ##__VA_ARGS__); \ | ||
430 | } while(0) | ||
431 | |||
432 | #define DVDBG(d, fmt, ...) do { \ | ||
433 | dev_dbg(&(d)->vhub->pdev->dev, \ | ||
434 | "%s " fmt, (d)->name, \ | ||
435 | ##__VA_ARGS__); \ | ||
436 | } while(0) | ||
437 | |||
438 | #else | ||
439 | #define UDCVDBG(u, fmt...) do { } while(0) | ||
440 | #define EPVDBG(ep, fmt, ...) do { } while(0) | ||
441 | #define DVDBG(d, fmt, ...) do { } while(0) | ||
442 | #endif | ||
443 | |||
444 | #ifdef CONFIG_USB_GADGET_DEBUG | ||
445 | #define UDCDBG(u, fmt...) dev_dbg(&(u)->pdev->dev, fmt) | ||
446 | |||
447 | #define EPDBG(ep, fmt, ...) do { \ | ||
448 | dev_dbg(&(ep)->vhub->pdev->dev, \ | ||
449 | "%s:EP%d " fmt, \ | ||
450 | (ep)->dev ? (ep)->dev->name : "hub", \ | ||
451 | (ep)->d_idx, ##__VA_ARGS__); \ | ||
452 | } while(0) | ||
453 | |||
454 | #define DDBG(d, fmt, ...) do { \ | ||
455 | dev_dbg(&(d)->vhub->pdev->dev, \ | ||
456 | "%s " fmt, (d)->name, \ | ||
457 | ##__VA_ARGS__); \ | ||
458 | } while(0) | ||
459 | #else | ||
460 | #define UDCDBG(u, fmt...) do { } while(0) | ||
461 | #define EPDBG(ep, fmt, ...) do { } while(0) | ||
462 | #define DDBG(d, fmt, ...) do { } while(0) | ||
463 | #endif | ||
464 | |||
465 | /* core.c */ | ||
466 | void ast_vhub_done(struct ast_vhub_ep *ep, struct ast_vhub_req *req, | ||
467 | int status); | ||
468 | void ast_vhub_nuke(struct ast_vhub_ep *ep, int status); | ||
469 | struct usb_request *ast_vhub_alloc_request(struct usb_ep *u_ep, | ||
470 | gfp_t gfp_flags); | ||
471 | void ast_vhub_free_request(struct usb_ep *u_ep, struct usb_request *u_req); | ||
472 | void ast_vhub_init_hw(struct ast_vhub *vhub); | ||
473 | |||
474 | /* ep0.c */ | ||
475 | void ast_vhub_ep0_handle_ack(struct ast_vhub_ep *ep, bool in_ack); | ||
476 | void ast_vhub_ep0_handle_setup(struct ast_vhub_ep *ep); | ||
477 | void ast_vhub_init_ep0(struct ast_vhub *vhub, struct ast_vhub_ep *ep, | ||
478 | struct ast_vhub_dev *dev); | ||
479 | int ast_vhub_reply(struct ast_vhub_ep *ep, char *ptr, int len); | ||
480 | int __ast_vhub_simple_reply(struct ast_vhub_ep *ep, int len, ...); | ||
481 | #define ast_vhub_simple_reply(udc, ...) \ | ||
482 | __ast_vhub_simple_reply((udc), \ | ||
483 | sizeof((u8[]) { __VA_ARGS__ })/sizeof(u8), \ | ||
484 | __VA_ARGS__) | ||
485 | |||
486 | /* hub.c */ | ||
487 | void ast_vhub_init_hub(struct ast_vhub *vhub); | ||
488 | enum std_req_rc ast_vhub_std_hub_request(struct ast_vhub_ep *ep, | ||
489 | struct usb_ctrlrequest *crq); | ||
490 | enum std_req_rc ast_vhub_class_hub_request(struct ast_vhub_ep *ep, | ||
491 | struct usb_ctrlrequest *crq); | ||
492 | void ast_vhub_device_connect(struct ast_vhub *vhub, unsigned int port, | ||
493 | bool on); | ||
494 | void ast_vhub_hub_suspend(struct ast_vhub *vhub); | ||
495 | void ast_vhub_hub_resume(struct ast_vhub *vhub); | ||
496 | void ast_vhub_hub_reset(struct ast_vhub *vhub); | ||
497 | void ast_vhub_hub_wake_all(struct ast_vhub *vhub); | ||
498 | |||
499 | /* dev.c */ | ||
500 | int ast_vhub_init_dev(struct ast_vhub *vhub, unsigned int idx); | ||
501 | void ast_vhub_del_dev(struct ast_vhub_dev *d); | ||
502 | void ast_vhub_dev_irq(struct ast_vhub_dev *d); | ||
503 | int ast_vhub_std_dev_request(struct ast_vhub_ep *ep, | ||
504 | struct usb_ctrlrequest *crq); | ||
505 | |||
506 | /* epn.c */ | ||
507 | void ast_vhub_epn_ack_irq(struct ast_vhub_ep *ep); | ||
508 | void ast_vhub_update_epn_stall(struct ast_vhub_ep *ep); | ||
509 | struct ast_vhub_ep *ast_vhub_alloc_epn(struct ast_vhub_dev *d, u8 addr); | ||
510 | void ast_vhub_dev_suspend(struct ast_vhub_dev *d); | ||
511 | void ast_vhub_dev_resume(struct ast_vhub_dev *d); | ||
512 | void ast_vhub_dev_reset(struct ast_vhub_dev *d); | ||
513 | |||
514 | #endif /* __ASPEED_VHUB_H */ | ||
diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index 27c16399c7e8..a4d99bf50f2f 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/ctype.h> | 20 | #include <linux/ctype.h> |
21 | #include <linux/usb/ch9.h> | 21 | #include <linux/usb/ch9.h> |
22 | #include <linux/usb/gadget.h> | 22 | #include <linux/usb/gadget.h> |
23 | #include <linux/usb/atmel_usba_udc.h> | ||
24 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
25 | #include <linux/of.h> | 24 | #include <linux/of.h> |
26 | #include <linux/irq.h> | 25 | #include <linux/irq.h> |
@@ -207,94 +206,45 @@ static void usba_ep_init_debugfs(struct usba_udc *udc, | |||
207 | struct dentry *ep_root; | 206 | struct dentry *ep_root; |
208 | 207 | ||
209 | ep_root = debugfs_create_dir(ep->ep.name, udc->debugfs_root); | 208 | ep_root = debugfs_create_dir(ep->ep.name, udc->debugfs_root); |
210 | if (!ep_root) | ||
211 | goto err_root; | ||
212 | ep->debugfs_dir = ep_root; | 209 | ep->debugfs_dir = ep_root; |
213 | 210 | ||
214 | ep->debugfs_queue = debugfs_create_file("queue", 0400, ep_root, | 211 | debugfs_create_file("queue", 0400, ep_root, ep, &queue_dbg_fops); |
215 | ep, &queue_dbg_fops); | ||
216 | if (!ep->debugfs_queue) | ||
217 | goto err_queue; | ||
218 | |||
219 | if (ep->can_dma) { | ||
220 | ep->debugfs_dma_status | ||
221 | = debugfs_create_u32("dma_status", 0400, ep_root, | ||
222 | &ep->last_dma_status); | ||
223 | if (!ep->debugfs_dma_status) | ||
224 | goto err_dma_status; | ||
225 | } | ||
226 | if (ep_is_control(ep)) { | ||
227 | ep->debugfs_state | ||
228 | = debugfs_create_u32("state", 0400, ep_root, | ||
229 | &ep->state); | ||
230 | if (!ep->debugfs_state) | ||
231 | goto err_state; | ||
232 | } | ||
233 | |||
234 | return; | ||
235 | |||
236 | err_state: | ||
237 | if (ep->can_dma) | 212 | if (ep->can_dma) |
238 | debugfs_remove(ep->debugfs_dma_status); | 213 | debugfs_create_u32("dma_status", 0400, ep_root, |
239 | err_dma_status: | 214 | &ep->last_dma_status); |
240 | debugfs_remove(ep->debugfs_queue); | 215 | if (ep_is_control(ep)) |
241 | err_queue: | 216 | debugfs_create_u32("state", 0400, ep_root, &ep->state); |
242 | debugfs_remove(ep_root); | ||
243 | err_root: | ||
244 | dev_err(&ep->udc->pdev->dev, | ||
245 | "failed to create debugfs directory for %s\n", ep->ep.name); | ||
246 | } | 217 | } |
247 | 218 | ||
248 | static void usba_ep_cleanup_debugfs(struct usba_ep *ep) | 219 | static void usba_ep_cleanup_debugfs(struct usba_ep *ep) |
249 | { | 220 | { |
250 | debugfs_remove(ep->debugfs_queue); | 221 | debugfs_remove_recursive(ep->debugfs_dir); |
251 | debugfs_remove(ep->debugfs_dma_status); | ||
252 | debugfs_remove(ep->debugfs_state); | ||
253 | debugfs_remove(ep->debugfs_dir); | ||
254 | ep->debugfs_dma_status = NULL; | ||
255 | ep->debugfs_dir = NULL; | ||
256 | } | 222 | } |
257 | 223 | ||
258 | static void usba_init_debugfs(struct usba_udc *udc) | 224 | static void usba_init_debugfs(struct usba_udc *udc) |
259 | { | 225 | { |
260 | struct dentry *root, *regs; | 226 | struct dentry *root; |
261 | struct resource *regs_resource; | 227 | struct resource *regs_resource; |
262 | 228 | ||
263 | root = debugfs_create_dir(udc->gadget.name, NULL); | 229 | root = debugfs_create_dir(udc->gadget.name, NULL); |
264 | if (IS_ERR(root) || !root) | ||
265 | goto err_root; | ||
266 | udc->debugfs_root = root; | 230 | udc->debugfs_root = root; |
267 | 231 | ||
268 | regs_resource = platform_get_resource(udc->pdev, IORESOURCE_MEM, | 232 | regs_resource = platform_get_resource(udc->pdev, IORESOURCE_MEM, |
269 | CTRL_IOMEM_ID); | 233 | CTRL_IOMEM_ID); |
270 | 234 | ||
271 | if (regs_resource) { | 235 | if (regs_resource) { |
272 | regs = debugfs_create_file_size("regs", 0400, root, udc, | 236 | debugfs_create_file_size("regs", 0400, root, udc, |
273 | ®s_dbg_fops, | 237 | ®s_dbg_fops, |
274 | resource_size(regs_resource)); | 238 | resource_size(regs_resource)); |
275 | if (!regs) | ||
276 | goto err_regs; | ||
277 | udc->debugfs_regs = regs; | ||
278 | } | 239 | } |
279 | 240 | ||
280 | usba_ep_init_debugfs(udc, to_usba_ep(udc->gadget.ep0)); | 241 | usba_ep_init_debugfs(udc, to_usba_ep(udc->gadget.ep0)); |
281 | |||
282 | return; | ||
283 | |||
284 | err_regs: | ||
285 | debugfs_remove(root); | ||
286 | err_root: | ||
287 | udc->debugfs_root = NULL; | ||
288 | dev_err(&udc->pdev->dev, "debugfs is not available\n"); | ||
289 | } | 242 | } |
290 | 243 | ||
291 | static void usba_cleanup_debugfs(struct usba_udc *udc) | 244 | static void usba_cleanup_debugfs(struct usba_udc *udc) |
292 | { | 245 | { |
293 | usba_ep_cleanup_debugfs(to_usba_ep(udc->gadget.ep0)); | 246 | usba_ep_cleanup_debugfs(to_usba_ep(udc->gadget.ep0)); |
294 | debugfs_remove(udc->debugfs_regs); | 247 | debugfs_remove_recursive(udc->debugfs_root); |
295 | debugfs_remove(udc->debugfs_root); | ||
296 | udc->debugfs_regs = NULL; | ||
297 | udc->debugfs_root = NULL; | ||
298 | } | 248 | } |
299 | #else | 249 | #else |
300 | static inline void usba_ep_init_debugfs(struct usba_udc *udc, | 250 | static inline void usba_ep_init_debugfs(struct usba_udc *udc, |
@@ -417,7 +367,7 @@ static inline void usba_int_enb_set(struct usba_udc *udc, u32 val) | |||
417 | static int vbus_is_present(struct usba_udc *udc) | 367 | static int vbus_is_present(struct usba_udc *udc) |
418 | { | 368 | { |
419 | if (udc->vbus_pin) | 369 | if (udc->vbus_pin) |
420 | return gpiod_get_value(udc->vbus_pin) ^ udc->vbus_pin_inverted; | 370 | return gpiod_get_value(udc->vbus_pin); |
421 | 371 | ||
422 | /* No Vbus detection: Assume always present */ | 372 | /* No Vbus detection: Assume always present */ |
423 | return 1; | 373 | return 1; |
@@ -2076,7 +2026,6 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, | |||
2076 | 2026 | ||
2077 | udc->vbus_pin = devm_gpiod_get_optional(&pdev->dev, "atmel,vbus", | 2027 | udc->vbus_pin = devm_gpiod_get_optional(&pdev->dev, "atmel,vbus", |
2078 | GPIOD_IN); | 2028 | GPIOD_IN); |
2079 | udc->vbus_pin_inverted = gpiod_is_active_low(udc->vbus_pin); | ||
2080 | 2029 | ||
2081 | if (fifo_mode == 0) { | 2030 | if (fifo_mode == 0) { |
2082 | pp = NULL; | 2031 | pp = NULL; |
@@ -2279,15 +2228,15 @@ static int usba_udc_probe(struct platform_device *pdev) | |||
2279 | if (udc->vbus_pin) { | 2228 | if (udc->vbus_pin) { |
2280 | irq_set_status_flags(gpiod_to_irq(udc->vbus_pin), IRQ_NOAUTOEN); | 2229 | irq_set_status_flags(gpiod_to_irq(udc->vbus_pin), IRQ_NOAUTOEN); |
2281 | ret = devm_request_threaded_irq(&pdev->dev, | 2230 | ret = devm_request_threaded_irq(&pdev->dev, |
2282 | gpiod_to_irq(udc->vbus_pin), NULL, | 2231 | gpiod_to_irq(udc->vbus_pin), NULL, |
2283 | usba_vbus_irq_thread, USBA_VBUS_IRQFLAGS, | 2232 | usba_vbus_irq_thread, USBA_VBUS_IRQFLAGS, |
2284 | "atmel_usba_udc", udc); | 2233 | "atmel_usba_udc", udc); |
2285 | if (ret) { | 2234 | if (ret) { |
2286 | udc->vbus_pin = NULL; | 2235 | udc->vbus_pin = NULL; |
2287 | dev_warn(&udc->pdev->dev, | 2236 | dev_warn(&udc->pdev->dev, |
2288 | "failed to request vbus irq; " | 2237 | "failed to request vbus irq; " |
2289 | "assuming always on\n"); | 2238 | "assuming always on\n"); |
2290 | } | 2239 | } |
2291 | } | 2240 | } |
2292 | 2241 | ||
2293 | ret = usb_add_gadget_udc(&pdev->dev, &udc->gadget); | 2242 | ret = usb_add_gadget_udc(&pdev->dev, &udc->gadget); |
diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.h b/drivers/usb/gadget/udc/atmel_usba_udc.h index 969ce8f3c3e2..030bf797cd25 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.h +++ b/drivers/usb/gadget/udc/atmel_usba_udc.h | |||
@@ -287,9 +287,6 @@ struct usba_ep { | |||
287 | #ifdef CONFIG_USB_GADGET_DEBUG_FS | 287 | #ifdef CONFIG_USB_GADGET_DEBUG_FS |
288 | u32 last_dma_status; | 288 | u32 last_dma_status; |
289 | struct dentry *debugfs_dir; | 289 | struct dentry *debugfs_dir; |
290 | struct dentry *debugfs_queue; | ||
291 | struct dentry *debugfs_dma_status; | ||
292 | struct dentry *debugfs_state; | ||
293 | #endif | 290 | #endif |
294 | }; | 291 | }; |
295 | 292 | ||
@@ -326,7 +323,6 @@ struct usba_udc { | |||
326 | const struct usba_udc_errata *errata; | 323 | const struct usba_udc_errata *errata; |
327 | int irq; | 324 | int irq; |
328 | struct gpio_desc *vbus_pin; | 325 | struct gpio_desc *vbus_pin; |
329 | int vbus_pin_inverted; | ||
330 | int num_ep; | 326 | int num_ep; |
331 | int configured_ep; | 327 | int configured_ep; |
332 | struct usba_fifo_cfg *fifo_cfg; | 328 | struct usba_fifo_cfg *fifo_cfg; |
@@ -345,7 +341,6 @@ struct usba_udc { | |||
345 | 341 | ||
346 | #ifdef CONFIG_USB_GADGET_DEBUG_FS | 342 | #ifdef CONFIG_USB_GADGET_DEBUG_FS |
347 | struct dentry *debugfs_root; | 343 | struct dentry *debugfs_root; |
348 | struct dentry *debugfs_regs; | ||
349 | #endif | 344 | #endif |
350 | 345 | ||
351 | struct regmap *pmc; | 346 | struct regmap *pmc; |
diff --git a/drivers/usb/gadget/udc/bcm63xx_udc.c b/drivers/usb/gadget/udc/bcm63xx_udc.c index 3a8df8601074..c1fcc77403ea 100644 --- a/drivers/usb/gadget/udc/bcm63xx_udc.c +++ b/drivers/usb/gadget/udc/bcm63xx_udc.c | |||
@@ -288,8 +288,6 @@ struct bcm63xx_req { | |||
288 | * @ep0_reply: Pending reply from gadget driver. | 288 | * @ep0_reply: Pending reply from gadget driver. |
289 | * @ep0_request: Outstanding ep0 request. | 289 | * @ep0_request: Outstanding ep0 request. |
290 | * @debugfs_root: debugfs directory: /sys/kernel/debug/<DRV_MODULE_NAME>. | 290 | * @debugfs_root: debugfs directory: /sys/kernel/debug/<DRV_MODULE_NAME>. |
291 | * @debugfs_usbd: debugfs file "usbd" for controller state. | ||
292 | * @debugfs_iudma: debugfs file "usbd" for IUDMA state. | ||
293 | */ | 291 | */ |
294 | struct bcm63xx_udc { | 292 | struct bcm63xx_udc { |
295 | spinlock_t lock; | 293 | spinlock_t lock; |
@@ -330,8 +328,6 @@ struct bcm63xx_udc { | |||
330 | struct usb_request *ep0_request; | 328 | struct usb_request *ep0_request; |
331 | 329 | ||
332 | struct dentry *debugfs_root; | 330 | struct dentry *debugfs_root; |
333 | struct dentry *debugfs_usbd; | ||
334 | struct dentry *debugfs_iudma; | ||
335 | }; | 331 | }; |
336 | 332 | ||
337 | static const struct usb_ep_ops bcm63xx_udc_ep_ops; | 333 | static const struct usb_ep_ops bcm63xx_udc_ep_ops; |
@@ -2247,34 +2243,16 @@ DEFINE_SHOW_ATTRIBUTE(bcm63xx_iudma_dbg); | |||
2247 | */ | 2243 | */ |
2248 | static void bcm63xx_udc_init_debugfs(struct bcm63xx_udc *udc) | 2244 | static void bcm63xx_udc_init_debugfs(struct bcm63xx_udc *udc) |
2249 | { | 2245 | { |
2250 | struct dentry *root, *usbd, *iudma; | 2246 | struct dentry *root; |
2251 | 2247 | ||
2252 | if (!IS_ENABLED(CONFIG_USB_GADGET_DEBUG_FS)) | 2248 | if (!IS_ENABLED(CONFIG_USB_GADGET_DEBUG_FS)) |
2253 | return; | 2249 | return; |
2254 | 2250 | ||
2255 | root = debugfs_create_dir(udc->gadget.name, NULL); | 2251 | root = debugfs_create_dir(udc->gadget.name, NULL); |
2256 | if (IS_ERR(root) || !root) | ||
2257 | goto err_root; | ||
2258 | |||
2259 | usbd = debugfs_create_file("usbd", 0400, root, udc, | ||
2260 | &bcm63xx_usbd_dbg_fops); | ||
2261 | if (!usbd) | ||
2262 | goto err_usbd; | ||
2263 | iudma = debugfs_create_file("iudma", 0400, root, udc, | ||
2264 | &bcm63xx_iudma_dbg_fops); | ||
2265 | if (!iudma) | ||
2266 | goto err_iudma; | ||
2267 | |||
2268 | udc->debugfs_root = root; | 2252 | udc->debugfs_root = root; |
2269 | udc->debugfs_usbd = usbd; | 2253 | |
2270 | udc->debugfs_iudma = iudma; | 2254 | debugfs_create_file("usbd", 0400, root, udc, &bcm63xx_usbd_dbg_fops); |
2271 | return; | 2255 | debugfs_create_file("iudma", 0400, root, udc, &bcm63xx_iudma_dbg_fops); |
2272 | err_iudma: | ||
2273 | debugfs_remove(usbd); | ||
2274 | err_usbd: | ||
2275 | debugfs_remove(root); | ||
2276 | err_root: | ||
2277 | dev_err(udc->dev, "debugfs is not available\n"); | ||
2278 | } | 2256 | } |
2279 | 2257 | ||
2280 | /** | 2258 | /** |
@@ -2285,12 +2263,7 @@ err_root: | |||
2285 | */ | 2263 | */ |
2286 | static void bcm63xx_udc_cleanup_debugfs(struct bcm63xx_udc *udc) | 2264 | static void bcm63xx_udc_cleanup_debugfs(struct bcm63xx_udc *udc) |
2287 | { | 2265 | { |
2288 | debugfs_remove(udc->debugfs_iudma); | 2266 | debugfs_remove_recursive(udc->debugfs_root); |
2289 | debugfs_remove(udc->debugfs_usbd); | ||
2290 | debugfs_remove(udc->debugfs_root); | ||
2291 | udc->debugfs_iudma = NULL; | ||
2292 | udc->debugfs_usbd = NULL; | ||
2293 | udc->debugfs_root = NULL; | ||
2294 | } | 2267 | } |
2295 | 2268 | ||
2296 | /*********************************************************************** | 2269 | /*********************************************************************** |
diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index 842814bc0e4f..cab5e4f09924 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c | |||
@@ -244,6 +244,12 @@ EXPORT_SYMBOL_GPL(usb_ep_free_request); | |||
244 | * Returns zero, or a negative error code. Endpoints that are not enabled | 244 | * Returns zero, or a negative error code. Endpoints that are not enabled |
245 | * report errors; errors will also be | 245 | * report errors; errors will also be |
246 | * reported when the usb peripheral is disconnected. | 246 | * reported when the usb peripheral is disconnected. |
247 | * | ||
248 | * If and only if @req is successfully queued (the return value is zero), | ||
249 | * @req->complete() will be called exactly once, when the Gadget core and | ||
250 | * UDC are finished with the request. When the completion function is called, | ||
251 | * control of the request is returned to the device driver which submitted it. | ||
252 | * The completion handler may then immediately free or reuse @req. | ||
247 | */ | 253 | */ |
248 | int usb_ep_queue(struct usb_ep *ep, | 254 | int usb_ep_queue(struct usb_ep *ep, |
249 | struct usb_request *req, gfp_t gfp_flags) | 255 | struct usb_request *req, gfp_t gfp_flags) |
diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c index 7d8af299dfc7..9a3f7db26a5e 100644 --- a/drivers/usb/gadget/udc/fsl_udc_core.c +++ b/drivers/usb/gadget/udc/fsl_udc_core.c | |||
@@ -253,6 +253,7 @@ static int dr_controller_setup(struct fsl_udc *udc) | |||
253 | portctrl |= PORTSCX_PTW_16BIT; | 253 | portctrl |= PORTSCX_PTW_16BIT; |
254 | /* fall through */ | 254 | /* fall through */ |
255 | case FSL_USB2_PHY_UTMI: | 255 | case FSL_USB2_PHY_UTMI: |
256 | case FSL_USB2_PHY_UTMI_DUAL: | ||
256 | if (udc->pdata->have_sysif_regs) { | 257 | if (udc->pdata->have_sysif_regs) { |
257 | if (udc->pdata->controller_ver) { | 258 | if (udc->pdata->controller_ver) { |
258 | /* controller version 1.6 or above */ | 259 | /* controller version 1.6 or above */ |
diff --git a/drivers/usb/gadget/udc/gr_udc.c b/drivers/usb/gadget/udc/gr_udc.c index ca83c15d8ea4..729e60e49564 100644 --- a/drivers/usb/gadget/udc/gr_udc.c +++ b/drivers/usb/gadget/udc/gr_udc.c | |||
@@ -209,15 +209,12 @@ static void gr_dfs_create(struct gr_udc *dev) | |||
209 | const char *name = "gr_udc_state"; | 209 | const char *name = "gr_udc_state"; |
210 | 210 | ||
211 | dev->dfs_root = debugfs_create_dir(dev_name(dev->dev), NULL); | 211 | dev->dfs_root = debugfs_create_dir(dev_name(dev->dev), NULL); |
212 | dev->dfs_state = debugfs_create_file(name, 0444, dev->dfs_root, dev, | 212 | debugfs_create_file(name, 0444, dev->dfs_root, dev, &gr_dfs_fops); |
213 | &gr_dfs_fops); | ||
214 | } | 213 | } |
215 | 214 | ||
216 | static void gr_dfs_delete(struct gr_udc *dev) | 215 | static void gr_dfs_delete(struct gr_udc *dev) |
217 | { | 216 | { |
218 | /* Handles NULL and ERR pointers internally */ | 217 | debugfs_remove_recursive(dev->dfs_root); |
219 | debugfs_remove(dev->dfs_state); | ||
220 | debugfs_remove(dev->dfs_root); | ||
221 | } | 218 | } |
222 | 219 | ||
223 | #else /* !CONFIG_USB_GADGET_DEBUG_FS */ | 220 | #else /* !CONFIG_USB_GADGET_DEBUG_FS */ |
diff --git a/drivers/usb/gadget/udc/gr_udc.h b/drivers/usb/gadget/udc/gr_udc.h index 3e913268c8c5..417ad2aa2cc7 100644 --- a/drivers/usb/gadget/udc/gr_udc.h +++ b/drivers/usb/gadget/udc/gr_udc.h | |||
@@ -217,7 +217,6 @@ struct gr_udc { | |||
217 | spinlock_t lock; /* General lock, a.k.a. "dev->lock" in comments */ | 217 | spinlock_t lock; /* General lock, a.k.a. "dev->lock" in comments */ |
218 | 218 | ||
219 | struct dentry *dfs_root; | 219 | struct dentry *dfs_root; |
220 | struct dentry *dfs_state; | ||
221 | }; | 220 | }; |
222 | 221 | ||
223 | #define to_gr_udc(gadget) (container_of((gadget), struct gr_udc, gadget)) | 222 | #define to_gr_udc(gadget) (container_of((gadget), struct gr_udc, gadget)) |
diff --git a/drivers/usb/gadget/udc/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c index a58242e901df..014233252299 100644 --- a/drivers/usb/gadget/udc/pxa27x_udc.c +++ b/drivers/usb/gadget/udc/pxa27x_udc.c | |||
@@ -205,50 +205,19 @@ DEFINE_SHOW_ATTRIBUTE(eps_dbg); | |||
205 | 205 | ||
206 | static void pxa_init_debugfs(struct pxa_udc *udc) | 206 | static void pxa_init_debugfs(struct pxa_udc *udc) |
207 | { | 207 | { |
208 | struct dentry *root, *state, *queues, *eps; | 208 | struct dentry *root; |
209 | 209 | ||
210 | root = debugfs_create_dir(udc->gadget.name, NULL); | 210 | root = debugfs_create_dir(udc->gadget.name, NULL); |
211 | if (IS_ERR(root) || !root) | ||
212 | goto err_root; | ||
213 | |||
214 | state = debugfs_create_file("udcstate", 0400, root, udc, | ||
215 | &state_dbg_fops); | ||
216 | if (!state) | ||
217 | goto err_state; | ||
218 | queues = debugfs_create_file("queues", 0400, root, udc, | ||
219 | &queues_dbg_fops); | ||
220 | if (!queues) | ||
221 | goto err_queues; | ||
222 | eps = debugfs_create_file("epstate", 0400, root, udc, | ||
223 | &eps_dbg_fops); | ||
224 | if (!eps) | ||
225 | goto err_eps; | ||
226 | |||
227 | udc->debugfs_root = root; | 211 | udc->debugfs_root = root; |
228 | udc->debugfs_state = state; | 212 | |
229 | udc->debugfs_queues = queues; | 213 | debugfs_create_file("udcstate", 0400, root, udc, &state_dbg_fops); |
230 | udc->debugfs_eps = eps; | 214 | debugfs_create_file("queues", 0400, root, udc, &queues_dbg_fops); |
231 | return; | 215 | debugfs_create_file("epstate", 0400, root, udc, &eps_dbg_fops); |
232 | err_eps: | ||
233 | debugfs_remove(eps); | ||
234 | err_queues: | ||
235 | debugfs_remove(queues); | ||
236 | err_state: | ||
237 | debugfs_remove(root); | ||
238 | err_root: | ||
239 | dev_err(udc->dev, "debugfs is not available\n"); | ||
240 | } | 216 | } |
241 | 217 | ||
242 | static void pxa_cleanup_debugfs(struct pxa_udc *udc) | 218 | static void pxa_cleanup_debugfs(struct pxa_udc *udc) |
243 | { | 219 | { |
244 | debugfs_remove(udc->debugfs_eps); | 220 | debugfs_remove_recursive(udc->debugfs_root); |
245 | debugfs_remove(udc->debugfs_queues); | ||
246 | debugfs_remove(udc->debugfs_state); | ||
247 | debugfs_remove(udc->debugfs_root); | ||
248 | udc->debugfs_eps = NULL; | ||
249 | udc->debugfs_queues = NULL; | ||
250 | udc->debugfs_state = NULL; | ||
251 | udc->debugfs_root = NULL; | ||
252 | } | 221 | } |
253 | 222 | ||
254 | #else | 223 | #else |
diff --git a/drivers/usb/gadget/udc/pxa27x_udc.h b/drivers/usb/gadget/udc/pxa27x_udc.h index 1128d39a4255..13b2977399ab 100644 --- a/drivers/usb/gadget/udc/pxa27x_udc.h +++ b/drivers/usb/gadget/udc/pxa27x_udc.h | |||
@@ -476,9 +476,6 @@ struct pxa_udc { | |||
476 | #endif | 476 | #endif |
477 | #ifdef CONFIG_USB_GADGET_DEBUG_FS | 477 | #ifdef CONFIG_USB_GADGET_DEBUG_FS |
478 | struct dentry *debugfs_root; | 478 | struct dentry *debugfs_root; |
479 | struct dentry *debugfs_state; | ||
480 | struct dentry *debugfs_queues; | ||
481 | struct dentry *debugfs_eps; | ||
482 | #endif | 479 | #endif |
483 | }; | 480 | }; |
484 | #define to_pxa(g) (container_of((g), struct pxa_udc, gadget)) | 481 | #define to_pxa(g) (container_of((g), struct pxa_udc, gadget)) |
diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index 409cde4e6a51..977ea1a02cf9 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c | |||
@@ -333,6 +333,7 @@ struct renesas_usb3 { | |||
333 | struct extcon_dev *extcon; | 333 | struct extcon_dev *extcon; |
334 | struct work_struct extcon_work; | 334 | struct work_struct extcon_work; |
335 | struct phy *phy; | 335 | struct phy *phy; |
336 | struct dentry *dentry; | ||
336 | 337 | ||
337 | struct renesas_usb3_ep *usb3_ep; | 338 | struct renesas_usb3_ep *usb3_ep; |
338 | int num_usb3_eps; | 339 | int num_usb3_eps; |
@@ -622,6 +623,13 @@ static void usb3_disconnect(struct renesas_usb3 *usb3) | |||
622 | usb3_usb2_pullup(usb3, 0); | 623 | usb3_usb2_pullup(usb3, 0); |
623 | usb3_clear_bit(usb3, USB30_CON_B3_CONNECT, USB3_USB30_CON); | 624 | usb3_clear_bit(usb3, USB30_CON_B3_CONNECT, USB3_USB30_CON); |
624 | usb3_reset_epc(usb3); | 625 | usb3_reset_epc(usb3); |
626 | usb3_disable_irq_1(usb3, USB_INT_1_B2_RSUM | USB_INT_1_B3_PLLWKUP | | ||
627 | USB_INT_1_B3_LUPSUCS | USB_INT_1_B3_DISABLE | | ||
628 | USB_INT_1_SPEED | USB_INT_1_B3_WRMRST | | ||
629 | USB_INT_1_B3_HOTRST | USB_INT_1_B2_SPND | | ||
630 | USB_INT_1_B2_L1SPND | USB_INT_1_B2_USBRST); | ||
631 | usb3_clear_bit(usb3, USB_COM_CON_SPD_MODE, USB3_USB_COM_CON); | ||
632 | usb3_init_epc_registers(usb3); | ||
625 | 633 | ||
626 | if (usb3->driver) | 634 | if (usb3->driver) |
627 | usb3->driver->disconnect(&usb3->gadget); | 635 | usb3->driver->disconnect(&usb3->gadget); |
@@ -2383,18 +2391,10 @@ static const struct file_operations renesas_usb3_b_device_fops = { | |||
2383 | static void renesas_usb3_debugfs_init(struct renesas_usb3 *usb3, | 2391 | static void renesas_usb3_debugfs_init(struct renesas_usb3 *usb3, |
2384 | struct device *dev) | 2392 | struct device *dev) |
2385 | { | 2393 | { |
2386 | struct dentry *root, *file; | 2394 | usb3->dentry = debugfs_create_dir(dev_name(dev), NULL); |
2387 | |||
2388 | root = debugfs_create_dir(dev_name(dev), NULL); | ||
2389 | if (IS_ERR_OR_NULL(root)) { | ||
2390 | dev_info(dev, "%s: Can't create the root\n", __func__); | ||
2391 | return; | ||
2392 | } | ||
2393 | 2395 | ||
2394 | file = debugfs_create_file("b_device", 0644, root, usb3, | 2396 | debugfs_create_file("b_device", 0644, usb3->dentry, usb3, |
2395 | &renesas_usb3_b_device_fops); | 2397 | &renesas_usb3_b_device_fops); |
2396 | if (!file) | ||
2397 | dev_info(dev, "%s: Can't create debugfs mode\n", __func__); | ||
2398 | } | 2398 | } |
2399 | 2399 | ||
2400 | /*------- platform_driver ------------------------------------------------*/ | 2400 | /*------- platform_driver ------------------------------------------------*/ |
@@ -2402,14 +2402,13 @@ static int renesas_usb3_remove(struct platform_device *pdev) | |||
2402 | { | 2402 | { |
2403 | struct renesas_usb3 *usb3 = platform_get_drvdata(pdev); | 2403 | struct renesas_usb3 *usb3 = platform_get_drvdata(pdev); |
2404 | 2404 | ||
2405 | debugfs_remove_recursive(usb3->dentry); | ||
2405 | device_remove_file(&pdev->dev, &dev_attr_role); | 2406 | device_remove_file(&pdev->dev, &dev_attr_role); |
2406 | 2407 | ||
2407 | usb_del_gadget_udc(&usb3->gadget); | 2408 | usb_del_gadget_udc(&usb3->gadget); |
2408 | renesas_usb3_dma_free_prd(usb3, &pdev->dev); | 2409 | renesas_usb3_dma_free_prd(usb3, &pdev->dev); |
2409 | 2410 | ||
2410 | __renesas_usb3_ep_free_request(usb3->ep0_req); | 2411 | __renesas_usb3_ep_free_request(usb3->ep0_req); |
2411 | if (usb3->phy) | ||
2412 | phy_put(usb3->phy); | ||
2413 | pm_runtime_disable(&pdev->dev); | 2412 | pm_runtime_disable(&pdev->dev); |
2414 | 2413 | ||
2415 | return 0; | 2414 | return 0; |
@@ -2628,6 +2627,17 @@ static int renesas_usb3_probe(struct platform_device *pdev) | |||
2628 | if (ret < 0) | 2627 | if (ret < 0) |
2629 | goto err_alloc_prd; | 2628 | goto err_alloc_prd; |
2630 | 2629 | ||
2630 | /* | ||
2631 | * This is optional. So, if this driver cannot get a phy, | ||
2632 | * this driver will not handle a phy anymore. | ||
2633 | */ | ||
2634 | usb3->phy = devm_phy_optional_get(&pdev->dev, "usb"); | ||
2635 | if (IS_ERR(usb3->phy)) { | ||
2636 | ret = PTR_ERR(usb3->phy); | ||
2637 | goto err_add_udc; | ||
2638 | } | ||
2639 | |||
2640 | pm_runtime_enable(&pdev->dev); | ||
2631 | ret = usb_add_gadget_udc(&pdev->dev, &usb3->gadget); | 2641 | ret = usb_add_gadget_udc(&pdev->dev, &usb3->gadget); |
2632 | if (ret < 0) | 2642 | if (ret < 0) |
2633 | goto err_add_udc; | 2643 | goto err_add_udc; |
@@ -2636,20 +2646,11 @@ static int renesas_usb3_probe(struct platform_device *pdev) | |||
2636 | if (ret < 0) | 2646 | if (ret < 0) |
2637 | goto err_dev_create; | 2647 | goto err_dev_create; |
2638 | 2648 | ||
2639 | /* | ||
2640 | * This is an optional. So, if this driver cannot get a phy, | ||
2641 | * this driver will not handle a phy anymore. | ||
2642 | */ | ||
2643 | usb3->phy = devm_phy_get(&pdev->dev, "usb"); | ||
2644 | if (IS_ERR(usb3->phy)) | ||
2645 | usb3->phy = NULL; | ||
2646 | |||
2647 | usb3->workaround_for_vbus = priv->workaround_for_vbus; | 2649 | usb3->workaround_for_vbus = priv->workaround_for_vbus; |
2648 | 2650 | ||
2649 | renesas_usb3_debugfs_init(usb3, &pdev->dev); | 2651 | renesas_usb3_debugfs_init(usb3, &pdev->dev); |
2650 | 2652 | ||
2651 | dev_info(&pdev->dev, "probed%s\n", usb3->phy ? " with phy" : ""); | 2653 | dev_info(&pdev->dev, "probed%s\n", usb3->phy ? " with phy" : ""); |
2652 | pm_runtime_enable(usb3_to_dev(usb3)); | ||
2653 | 2654 | ||
2654 | return 0; | 2655 | return 0; |
2655 | 2656 | ||
diff --git a/drivers/usb/gadget/udc/s3c2410_udc.c b/drivers/usb/gadget/udc/s3c2410_udc.c index f154f49e98c8..8bf5ad7a59ad 100644 --- a/drivers/usb/gadget/udc/s3c2410_udc.c +++ b/drivers/usb/gadget/udc/s3c2410_udc.c | |||
@@ -1871,13 +1871,9 @@ static int s3c2410_udc_probe(struct platform_device *pdev) | |||
1871 | if (retval) | 1871 | if (retval) |
1872 | goto err_add_udc; | 1872 | goto err_add_udc; |
1873 | 1873 | ||
1874 | if (s3c2410_udc_debugfs_root) { | 1874 | udc->regs_info = debugfs_create_file("registers", S_IRUGO, |
1875 | udc->regs_info = debugfs_create_file("registers", S_IRUGO, | 1875 | s3c2410_udc_debugfs_root, udc, |
1876 | s3c2410_udc_debugfs_root, | 1876 | &s3c2410_udc_debugfs_fops); |
1877 | udc, &s3c2410_udc_debugfs_fops); | ||
1878 | if (!udc->regs_info) | ||
1879 | dev_warn(dev, "debugfs file creation failed\n"); | ||
1880 | } | ||
1881 | 1877 | ||
1882 | dev_dbg(dev, "probe ok\n"); | 1878 | dev_dbg(dev, "probe ok\n"); |
1883 | 1879 | ||
@@ -1994,11 +1990,6 @@ static int __init udc_init(void) | |||
1994 | dprintk(DEBUG_NORMAL, "%s\n", gadget_name); | 1990 | dprintk(DEBUG_NORMAL, "%s\n", gadget_name); |
1995 | 1991 | ||
1996 | s3c2410_udc_debugfs_root = debugfs_create_dir(gadget_name, NULL); | 1992 | s3c2410_udc_debugfs_root = debugfs_create_dir(gadget_name, NULL); |
1997 | if (IS_ERR(s3c2410_udc_debugfs_root)) { | ||
1998 | pr_err("%s: debugfs dir creation failed %ld\n", | ||
1999 | gadget_name, PTR_ERR(s3c2410_udc_debugfs_root)); | ||
2000 | s3c2410_udc_debugfs_root = NULL; | ||
2001 | } | ||
2002 | 1993 | ||
2003 | retval = platform_driver_register(&udc_driver_24x0); | 1994 | retval = platform_driver_register(&udc_driver_24x0); |
2004 | if (retval) | 1995 | if (retval) |
@@ -2014,7 +2005,7 @@ err: | |||
2014 | static void __exit udc_exit(void) | 2005 | static void __exit udc_exit(void) |
2015 | { | 2006 | { |
2016 | platform_driver_unregister(&udc_driver_24x0); | 2007 | platform_driver_unregister(&udc_driver_24x0); |
2017 | debugfs_remove(s3c2410_udc_debugfs_root); | 2008 | debugfs_remove_recursive(s3c2410_udc_debugfs_root); |
2018 | } | 2009 | } |
2019 | 2010 | ||
2020 | module_init(udc_init); | 2011 | module_init(udc_init); |
diff --git a/drivers/usb/gadget/usbstring.c b/drivers/usb/gadget/usbstring.c index 566ab261e8b7..7c24d1ce1088 100644 --- a/drivers/usb/gadget/usbstring.c +++ b/drivers/usb/gadget/usbstring.c | |||
@@ -33,7 +33,7 @@ | |||
33 | * characters (which are also widely used in C strings). | 33 | * characters (which are also widely used in C strings). |
34 | */ | 34 | */ |
35 | int | 35 | int |
36 | usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf) | 36 | usb_gadget_get_string (const struct usb_gadget_strings *table, int id, u8 *buf) |
37 | { | 37 | { |
38 | struct usb_string *s; | 38 | struct usb_string *s; |
39 | int len; | 39 | int len; |
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 5d958da8e1bc..6e64d3a64dbb 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
@@ -52,6 +52,13 @@ config USB_XHCI_PLATFORM | |||
52 | 52 | ||
53 | If unsure, say N. | 53 | If unsure, say N. |
54 | 54 | ||
55 | config USB_XHCI_HISTB | ||
56 | tristate "xHCI support for HiSilicon STB SoCs" | ||
57 | depends on USB_XHCI_PLATFORM && (ARCH_HISI || COMPILE_TEST) | ||
58 | help | ||
59 | Say 'Y' to enable the support for the xHCI host controller | ||
60 | found in HiSilicon STB SoCs. | ||
61 | |||
55 | config USB_XHCI_MTK | 62 | config USB_XHCI_MTK |
56 | tristate "xHCI support for MediaTek SoCs" | 63 | tristate "xHCI support for MediaTek SoCs" |
57 | select MFD_SYSCON | 64 | select MFD_SYSCON |
@@ -234,9 +241,7 @@ config USB_EHCI_TEGRA | |||
234 | tristate "NVIDIA Tegra HCD support" | 241 | tristate "NVIDIA Tegra HCD support" |
235 | depends on ARCH_TEGRA | 242 | depends on ARCH_TEGRA |
236 | select USB_EHCI_ROOT_HUB_TT | 243 | select USB_EHCI_ROOT_HUB_TT |
237 | select USB_PHY | 244 | select USB_TEGRA_PHY |
238 | select USB_ULPI | ||
239 | select USB_ULPI_VIEWPORT | ||
240 | help | 245 | help |
241 | This driver enables support for the internal USB Host Controllers | 246 | This driver enables support for the internal USB Host Controllers |
242 | found in NVIDIA Tegra SoCs. The controllers are EHCI compliant. | 247 | found in NVIDIA Tegra SoCs. The controllers are EHCI compliant. |
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 8a8cffe0b445..9b669c9f9a48 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile | |||
@@ -74,6 +74,7 @@ obj-$(CONFIG_USB_FHCI_HCD) += fhci.o | |||
74 | obj-$(CONFIG_USB_XHCI_HCD) += xhci-hcd.o | 74 | obj-$(CONFIG_USB_XHCI_HCD) += xhci-hcd.o |
75 | obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o | 75 | obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o |
76 | obj-$(CONFIG_USB_XHCI_PLATFORM) += xhci-plat-hcd.o | 76 | obj-$(CONFIG_USB_XHCI_PLATFORM) += xhci-plat-hcd.o |
77 | obj-$(CONFIG_USB_XHCI_HISTB) += xhci-histb.o | ||
77 | obj-$(CONFIG_USB_XHCI_MTK) += xhci-mtk.o | 78 | obj-$(CONFIG_USB_XHCI_MTK) += xhci-mtk.o |
78 | obj-$(CONFIG_USB_XHCI_TEGRA) += xhci-tegra.o | 79 | obj-$(CONFIG_USB_XHCI_TEGRA) += xhci-tegra.o |
79 | obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o | 80 | obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o |
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 3ed75aaa09d9..7619cfb06883 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c | |||
@@ -1028,29 +1028,15 @@ static inline void create_debug_files(struct ehci_hcd *ehci) | |||
1028 | struct usb_bus *bus = &ehci_to_hcd(ehci)->self; | 1028 | struct usb_bus *bus = &ehci_to_hcd(ehci)->self; |
1029 | 1029 | ||
1030 | ehci->debug_dir = debugfs_create_dir(bus->bus_name, ehci_debug_root); | 1030 | ehci->debug_dir = debugfs_create_dir(bus->bus_name, ehci_debug_root); |
1031 | if (!ehci->debug_dir) | ||
1032 | return; | ||
1033 | 1031 | ||
1034 | if (!debugfs_create_file("async", S_IRUGO, ehci->debug_dir, bus, | 1032 | debugfs_create_file("async", S_IRUGO, ehci->debug_dir, bus, |
1035 | &debug_async_fops)) | 1033 | &debug_async_fops); |
1036 | goto file_error; | 1034 | debugfs_create_file("bandwidth", S_IRUGO, ehci->debug_dir, bus, |
1037 | 1035 | &debug_bandwidth_fops); | |
1038 | if (!debugfs_create_file("bandwidth", S_IRUGO, ehci->debug_dir, bus, | 1036 | debugfs_create_file("periodic", S_IRUGO, ehci->debug_dir, bus, |
1039 | &debug_bandwidth_fops)) | 1037 | &debug_periodic_fops); |
1040 | goto file_error; | 1038 | debugfs_create_file("registers", S_IRUGO, ehci->debug_dir, bus, |
1041 | 1039 | &debug_registers_fops); | |
1042 | if (!debugfs_create_file("periodic", S_IRUGO, ehci->debug_dir, bus, | ||
1043 | &debug_periodic_fops)) | ||
1044 | goto file_error; | ||
1045 | |||
1046 | if (!debugfs_create_file("registers", S_IRUGO, ehci->debug_dir, bus, | ||
1047 | &debug_registers_fops)) | ||
1048 | goto file_error; | ||
1049 | |||
1050 | return; | ||
1051 | |||
1052 | file_error: | ||
1053 | debugfs_remove_recursive(ehci->debug_dir); | ||
1054 | } | 1040 | } |
1055 | 1041 | ||
1056 | static inline void remove_debug_files(struct ehci_hcd *ehci) | 1042 | static inline void remove_debug_files(struct ehci_hcd *ehci) |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index d927adf3afcd..89c47ae5c7d3 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -1311,10 +1311,6 @@ static int __init ehci_hcd_init(void) | |||
1311 | 1311 | ||
1312 | #ifdef CONFIG_DYNAMIC_DEBUG | 1312 | #ifdef CONFIG_DYNAMIC_DEBUG |
1313 | ehci_debug_root = debugfs_create_dir("ehci", usb_debug_root); | 1313 | ehci_debug_root = debugfs_create_dir("ehci", usb_debug_root); |
1314 | if (!ehci_debug_root) { | ||
1315 | retval = -ENOENT; | ||
1316 | goto err_debug; | ||
1317 | } | ||
1318 | #endif | 1314 | #endif |
1319 | 1315 | ||
1320 | #ifdef PLATFORM_DRIVER | 1316 | #ifdef PLATFORM_DRIVER |
@@ -1361,7 +1357,6 @@ clean0: | |||
1361 | #ifdef CONFIG_DYNAMIC_DEBUG | 1357 | #ifdef CONFIG_DYNAMIC_DEBUG |
1362 | debugfs_remove(ehci_debug_root); | 1358 | debugfs_remove(ehci_debug_root); |
1363 | ehci_debug_root = NULL; | 1359 | ehci_debug_root = NULL; |
1364 | err_debug: | ||
1365 | #endif | 1360 | #endif |
1366 | clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); | 1361 | clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); |
1367 | return retval; | 1362 | return retval; |
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 8d8bafc70c1f..7e4c13346a1e 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c | |||
@@ -157,10 +157,7 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) | |||
157 | struct usb_phy *phy; | 157 | struct usb_phy *phy; |
158 | 158 | ||
159 | /* get the PHY device */ | 159 | /* get the PHY device */ |
160 | if (dev->of_node) | 160 | phy = devm_usb_get_phy_by_phandle(dev, "phys", i); |
161 | phy = devm_usb_get_phy_by_phandle(dev, "phys", i); | ||
162 | else | ||
163 | phy = devm_usb_get_phy_dev(dev, i); | ||
164 | if (IS_ERR(phy)) { | 161 | if (IS_ERR(phy)) { |
165 | /* Don't bail out if PHY is not absolutely necessary */ | 162 | /* Don't bail out if PHY is not absolutely necessary */ |
166 | if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) | 163 | if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) |
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index a6f4389f7e88..4d2cdec4cb78 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #define DRV_NAME "tegra-ehci" | 36 | #define DRV_NAME "tegra-ehci" |
37 | 37 | ||
38 | static struct hc_driver __read_mostly tegra_ehci_hc_driver; | 38 | static struct hc_driver __read_mostly tegra_ehci_hc_driver; |
39 | static bool usb1_reset_attempted; | ||
40 | 39 | ||
41 | struct tegra_ehci_soc_config { | 40 | struct tegra_ehci_soc_config { |
42 | bool has_hostpc; | 41 | bool has_hostpc; |
@@ -51,67 +50,54 @@ struct tegra_ehci_hcd { | |||
51 | enum tegra_usb_phy_port_speed port_speed; | 50 | enum tegra_usb_phy_port_speed port_speed; |
52 | }; | 51 | }; |
53 | 52 | ||
54 | /* | ||
55 | * The 1st USB controller contains some UTMI pad registers that are global for | ||
56 | * all the controllers on the chip. Those registers are also cleared when | ||
57 | * reset is asserted to the 1st controller. This means that the 1st controller | ||
58 | * can only be reset when no other controlled has finished probing. So we'll | ||
59 | * reset the 1st controller before doing any other setup on any of the | ||
60 | * controllers, and then never again. | ||
61 | * | ||
62 | * Since this is a PHY issue, the Tegra PHY driver should probably be doing | ||
63 | * the resetting of the USB controllers. But to keep compatibility with old | ||
64 | * device trees that don't have reset phandles in the PHYs, do it here. | ||
65 | * Those old DTs will be vulnerable to total USB breakage if the 1st EHCI | ||
66 | * device isn't the first one to finish probing, so warn them. | ||
67 | */ | ||
68 | static int tegra_reset_usb_controller(struct platform_device *pdev) | 53 | static int tegra_reset_usb_controller(struct platform_device *pdev) |
69 | { | 54 | { |
70 | struct device_node *phy_np; | 55 | struct device_node *phy_np; |
71 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | 56 | struct usb_hcd *hcd = platform_get_drvdata(pdev); |
72 | struct tegra_ehci_hcd *tegra = | 57 | struct tegra_ehci_hcd *tegra = |
73 | (struct tegra_ehci_hcd *)hcd_to_ehci(hcd)->priv; | 58 | (struct tegra_ehci_hcd *)hcd_to_ehci(hcd)->priv; |
74 | bool has_utmi_pad_registers = false; | 59 | struct reset_control *rst; |
60 | int err; | ||
75 | 61 | ||
76 | phy_np = of_parse_phandle(pdev->dev.of_node, "nvidia,phy", 0); | 62 | phy_np = of_parse_phandle(pdev->dev.of_node, "nvidia,phy", 0); |
77 | if (!phy_np) | 63 | if (!phy_np) |
78 | return -ENOENT; | 64 | return -ENOENT; |
79 | 65 | ||
80 | if (of_property_read_bool(phy_np, "nvidia,has-utmi-pad-registers")) | 66 | /* |
81 | has_utmi_pad_registers = true; | 67 | * The 1st USB controller contains some UTMI pad registers that are |
68 | * global for all the controllers on the chip. Those registers are | ||
69 | * also cleared when reset is asserted to the 1st controller. | ||
70 | */ | ||
71 | rst = of_reset_control_get_shared(phy_np, "utmi-pads"); | ||
72 | if (IS_ERR(rst)) { | ||
73 | dev_warn(&pdev->dev, | ||
74 | "can't get utmi-pads reset from the PHY\n"); | ||
75 | dev_warn(&pdev->dev, | ||
76 | "continuing, but please update your DT\n"); | ||
77 | } else { | ||
78 | /* | ||
79 | * PHY driver performs UTMI-pads reset in a case of | ||
80 | * non-legacy DT. | ||
81 | */ | ||
82 | reset_control_put(rst); | ||
83 | } | ||
82 | 84 | ||
83 | if (!usb1_reset_attempted) { | 85 | of_node_put(phy_np); |
84 | struct reset_control *usb1_reset; | ||
85 | 86 | ||
86 | if (!has_utmi_pad_registers) | 87 | /* reset control is shared, hence initialize it first */ |
87 | usb1_reset = of_reset_control_get(phy_np, "utmi-pads"); | 88 | err = reset_control_deassert(tegra->rst); |
88 | else | 89 | if (err) |
89 | usb1_reset = tegra->rst; | 90 | return err; |
90 | |||
91 | if (IS_ERR(usb1_reset)) { | ||
92 | dev_warn(&pdev->dev, | ||
93 | "can't get utmi-pads reset from the PHY\n"); | ||
94 | dev_warn(&pdev->dev, | ||
95 | "continuing, but please update your DT\n"); | ||
96 | } else { | ||
97 | reset_control_assert(usb1_reset); | ||
98 | udelay(1); | ||
99 | reset_control_deassert(usb1_reset); | ||
100 | |||
101 | if (!has_utmi_pad_registers) | ||
102 | reset_control_put(usb1_reset); | ||
103 | } | ||
104 | 91 | ||
105 | usb1_reset_attempted = true; | 92 | err = reset_control_assert(tegra->rst); |
106 | } | 93 | if (err) |
94 | return err; | ||
107 | 95 | ||
108 | if (!has_utmi_pad_registers) { | 96 | udelay(1); |
109 | reset_control_assert(tegra->rst); | ||
110 | udelay(1); | ||
111 | reset_control_deassert(tegra->rst); | ||
112 | } | ||
113 | 97 | ||
114 | of_node_put(phy_np); | 98 | err = reset_control_deassert(tegra->rst); |
99 | if (err) | ||
100 | return err; | ||
115 | 101 | ||
116 | return 0; | 102 | return 0; |
117 | } | 103 | } |
@@ -440,7 +426,7 @@ static int tegra_ehci_probe(struct platform_device *pdev) | |||
440 | goto cleanup_hcd_create; | 426 | goto cleanup_hcd_create; |
441 | } | 427 | } |
442 | 428 | ||
443 | tegra->rst = devm_reset_control_get(&pdev->dev, "usb"); | 429 | tegra->rst = devm_reset_control_get_shared(&pdev->dev, "usb"); |
444 | if (IS_ERR(tegra->rst)) { | 430 | if (IS_ERR(tegra->rst)) { |
445 | dev_err(&pdev->dev, "Can't get ehci reset\n"); | 431 | dev_err(&pdev->dev, "Can't get ehci reset\n"); |
446 | err = PTR_ERR(tegra->rst); | 432 | err = PTR_ERR(tegra->rst); |
@@ -452,8 +438,10 @@ static int tegra_ehci_probe(struct platform_device *pdev) | |||
452 | goto cleanup_hcd_create; | 438 | goto cleanup_hcd_create; |
453 | 439 | ||
454 | err = tegra_reset_usb_controller(pdev); | 440 | err = tegra_reset_usb_controller(pdev); |
455 | if (err) | 441 | if (err) { |
442 | dev_err(&pdev->dev, "Failed to reset controller\n"); | ||
456 | goto cleanup_clk_en; | 443 | goto cleanup_clk_en; |
444 | } | ||
457 | 445 | ||
458 | u_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "nvidia,phy", 0); | 446 | u_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "nvidia,phy", 0); |
459 | if (IS_ERR(u_phy)) { | 447 | if (IS_ERR(u_phy)) { |
@@ -538,6 +526,9 @@ static int tegra_ehci_remove(struct platform_device *pdev) | |||
538 | usb_phy_shutdown(hcd->usb_phy); | 526 | usb_phy_shutdown(hcd->usb_phy); |
539 | usb_remove_hcd(hcd); | 527 | usb_remove_hcd(hcd); |
540 | 528 | ||
529 | reset_control_assert(tegra->rst); | ||
530 | udelay(1); | ||
531 | |||
541 | clk_disable_unprepare(tegra->clk); | 532 | clk_disable_unprepare(tegra->clk); |
542 | 533 | ||
543 | usb_put_hcd(hcd); | 534 | usb_put_hcd(hcd); |
diff --git a/drivers/usb/host/fhci-dbg.c b/drivers/usb/host/fhci-dbg.c index ebf9bb219f75..100048b3bd17 100644 --- a/drivers/usb/host/fhci-dbg.c +++ b/drivers/usb/host/fhci-dbg.c | |||
@@ -83,27 +83,14 @@ void fhci_dfs_create(struct fhci_hcd *fhci) | |||
83 | struct device *dev = fhci_to_hcd(fhci)->self.controller; | 83 | struct device *dev = fhci_to_hcd(fhci)->self.controller; |
84 | 84 | ||
85 | fhci->dfs_root = debugfs_create_dir(dev_name(dev), usb_debug_root); | 85 | fhci->dfs_root = debugfs_create_dir(dev_name(dev), usb_debug_root); |
86 | if (!fhci->dfs_root) { | ||
87 | WARN_ON(1); | ||
88 | return; | ||
89 | } | ||
90 | |||
91 | fhci->dfs_regs = debugfs_create_file("regs", S_IFREG | S_IRUGO, | ||
92 | fhci->dfs_root, fhci, &fhci_dfs_regs_fops); | ||
93 | 86 | ||
94 | fhci->dfs_irq_stat = debugfs_create_file("irq_stat", | 87 | debugfs_create_file("regs", S_IFREG | S_IRUGO, fhci->dfs_root, fhci, |
95 | S_IFREG | S_IRUGO, fhci->dfs_root, fhci, | 88 | &fhci_dfs_regs_fops); |
96 | &fhci_dfs_irq_stat_fops); | 89 | debugfs_create_file("irq_stat", S_IFREG | S_IRUGO, fhci->dfs_root, fhci, |
97 | 90 | &fhci_dfs_irq_stat_fops); | |
98 | WARN_ON(!fhci->dfs_regs || !fhci->dfs_irq_stat); | ||
99 | } | 91 | } |
100 | 92 | ||
101 | void fhci_dfs_destroy(struct fhci_hcd *fhci) | 93 | void fhci_dfs_destroy(struct fhci_hcd *fhci) |
102 | { | 94 | { |
103 | if (!fhci->dfs_root) | 95 | debugfs_remove_recursive(fhci->dfs_root); |
104 | return; | ||
105 | |||
106 | debugfs_remove(fhci->dfs_irq_stat); | ||
107 | debugfs_remove(fhci->dfs_regs); | ||
108 | debugfs_remove(fhci->dfs_root); | ||
109 | } | 96 | } |
diff --git a/drivers/usb/host/fhci.h b/drivers/usb/host/fhci.h index e7ec41d62410..2ce5031d866d 100644 --- a/drivers/usb/host/fhci.h +++ b/drivers/usb/host/fhci.h | |||
@@ -262,8 +262,6 @@ struct fhci_hcd { | |||
262 | #ifdef CONFIG_FHCI_DEBUG | 262 | #ifdef CONFIG_FHCI_DEBUG |
263 | int usb_irq_stat[13]; | 263 | int usb_irq_stat[13]; |
264 | struct dentry *dfs_root; | 264 | struct dentry *dfs_root; |
265 | struct dentry *dfs_regs; | ||
266 | struct dentry *dfs_irq_stat; | ||
267 | #endif | 265 | #endif |
268 | }; | 266 | }; |
269 | 267 | ||
diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c index d8abf401918a..e64eb47770c8 100644 --- a/drivers/usb/host/fotg210-hcd.c +++ b/drivers/usb/host/fotg210-hcd.c | |||
@@ -844,28 +844,16 @@ static int debug_registers_open(struct inode *inode, struct file *file) | |||
844 | static inline void create_debug_files(struct fotg210_hcd *fotg210) | 844 | static inline void create_debug_files(struct fotg210_hcd *fotg210) |
845 | { | 845 | { |
846 | struct usb_bus *bus = &fotg210_to_hcd(fotg210)->self; | 846 | struct usb_bus *bus = &fotg210_to_hcd(fotg210)->self; |
847 | struct dentry *root; | ||
847 | 848 | ||
848 | fotg210->debug_dir = debugfs_create_dir(bus->bus_name, | 849 | root = debugfs_create_dir(bus->bus_name, fotg210_debug_root); |
849 | fotg210_debug_root); | 850 | fotg210->debug_dir = root; |
850 | if (!fotg210->debug_dir) | ||
851 | return; | ||
852 | |||
853 | if (!debugfs_create_file("async", S_IRUGO, fotg210->debug_dir, bus, | ||
854 | &debug_async_fops)) | ||
855 | goto file_error; | ||
856 | |||
857 | if (!debugfs_create_file("periodic", S_IRUGO, fotg210->debug_dir, bus, | ||
858 | &debug_periodic_fops)) | ||
859 | goto file_error; | ||
860 | 851 | ||
861 | if (!debugfs_create_file("registers", S_IRUGO, fotg210->debug_dir, bus, | 852 | debugfs_create_file("async", S_IRUGO, root, bus, &debug_async_fops); |
862 | &debug_registers_fops)) | 853 | debugfs_create_file("periodic", S_IRUGO, root, bus, |
863 | goto file_error; | 854 | &debug_periodic_fops); |
864 | 855 | debugfs_create_file("registers", S_IRUGO, root, bus, | |
865 | return; | 856 | &debug_registers_fops); |
866 | |||
867 | file_error: | ||
868 | debugfs_remove_recursive(fotg210->debug_dir); | ||
869 | } | 857 | } |
870 | 858 | ||
871 | static inline void remove_debug_files(struct fotg210_hcd *fotg210) | 859 | static inline void remove_debug_files(struct fotg210_hcd *fotg210) |
@@ -5686,10 +5674,6 @@ static int __init fotg210_hcd_init(void) | |||
5686 | sizeof(struct fotg210_itd)); | 5674 | sizeof(struct fotg210_itd)); |
5687 | 5675 | ||
5688 | fotg210_debug_root = debugfs_create_dir("fotg210", usb_debug_root); | 5676 | fotg210_debug_root = debugfs_create_dir("fotg210", usb_debug_root); |
5689 | if (!fotg210_debug_root) { | ||
5690 | retval = -ENOENT; | ||
5691 | goto err_debug; | ||
5692 | } | ||
5693 | 5677 | ||
5694 | retval = platform_driver_register(&fotg210_hcd_driver); | 5678 | retval = platform_driver_register(&fotg210_hcd_driver); |
5695 | if (retval < 0) | 5679 | if (retval < 0) |
@@ -5699,7 +5683,7 @@ static int __init fotg210_hcd_init(void) | |||
5699 | clean: | 5683 | clean: |
5700 | debugfs_remove(fotg210_debug_root); | 5684 | debugfs_remove(fotg210_debug_root); |
5701 | fotg210_debug_root = NULL; | 5685 | fotg210_debug_root = NULL; |
5702 | err_debug: | 5686 | |
5703 | clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); | 5687 | clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); |
5704 | return retval; | 5688 | return retval; |
5705 | } | 5689 | } |
diff --git a/drivers/usb/host/imx21-dbg.c b/drivers/usb/host/imx21-dbg.c index a213ed6f07b5..7fcf1d9dd7f3 100644 --- a/drivers/usb/host/imx21-dbg.c +++ b/drivers/usb/host/imx21-dbg.c | |||
@@ -417,46 +417,22 @@ DEFINE_SHOW_ATTRIBUTE(debug_isoc); | |||
417 | 417 | ||
418 | static void create_debug_files(struct imx21 *imx21) | 418 | static void create_debug_files(struct imx21 *imx21) |
419 | { | 419 | { |
420 | imx21->debug_root = debugfs_create_dir(dev_name(imx21->dev), NULL); | 420 | struct dentry *root; |
421 | if (!imx21->debug_root) | ||
422 | goto failed_create_rootdir; | ||
423 | 421 | ||
424 | if (!debugfs_create_file("status", S_IRUGO, | 422 | root = debugfs_create_dir(dev_name(imx21->dev), NULL); |
425 | imx21->debug_root, imx21, &debug_status_fops)) | 423 | imx21->debug_root = root; |
426 | goto failed_create; | ||
427 | 424 | ||
428 | if (!debugfs_create_file("dmem", S_IRUGO, | 425 | debugfs_create_file("status", S_IRUGO, root, imx21, &debug_status_fops); |
429 | imx21->debug_root, imx21, &debug_dmem_fops)) | 426 | debugfs_create_file("dmem", S_IRUGO, root, imx21, &debug_dmem_fops); |
430 | goto failed_create; | 427 | debugfs_create_file("etd", S_IRUGO, root, imx21, &debug_etd_fops); |
431 | 428 | debugfs_create_file("statistics", S_IRUGO, root, imx21, | |
432 | if (!debugfs_create_file("etd", S_IRUGO, | 429 | &debug_statistics_fops); |
433 | imx21->debug_root, imx21, &debug_etd_fops)) | 430 | debugfs_create_file("isoc", S_IRUGO, root, imx21, &debug_isoc_fops); |
434 | goto failed_create; | ||
435 | |||
436 | if (!debugfs_create_file("statistics", S_IRUGO, | ||
437 | imx21->debug_root, imx21, &debug_statistics_fops)) | ||
438 | goto failed_create; | ||
439 | |||
440 | if (!debugfs_create_file("isoc", S_IRUGO, | ||
441 | imx21->debug_root, imx21, &debug_isoc_fops)) | ||
442 | goto failed_create; | ||
443 | |||
444 | return; | ||
445 | |||
446 | failed_create: | ||
447 | debugfs_remove_recursive(imx21->debug_root); | ||
448 | |||
449 | failed_create_rootdir: | ||
450 | imx21->debug_root = NULL; | ||
451 | } | 431 | } |
452 | 432 | ||
453 | |||
454 | static void remove_debug_files(struct imx21 *imx21) | 433 | static void remove_debug_files(struct imx21 *imx21) |
455 | { | 434 | { |
456 | if (imx21->debug_root) { | 435 | debugfs_remove_recursive(imx21->debug_root); |
457 | debugfs_remove_recursive(imx21->debug_root); | ||
458 | imx21->debug_root = NULL; | ||
459 | } | ||
460 | } | 436 | } |
461 | 437 | ||
462 | #endif | 438 | #endif |
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 4602ed801f0a..74da136d322a 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c | |||
@@ -1198,14 +1198,11 @@ static int isp116x_debug_show(struct seq_file *s, void *unused) | |||
1198 | } | 1198 | } |
1199 | DEFINE_SHOW_ATTRIBUTE(isp116x_debug); | 1199 | DEFINE_SHOW_ATTRIBUTE(isp116x_debug); |
1200 | 1200 | ||
1201 | static int create_debug_file(struct isp116x *isp116x) | 1201 | static void create_debug_file(struct isp116x *isp116x) |
1202 | { | 1202 | { |
1203 | isp116x->dentry = debugfs_create_file(hcd_name, | 1203 | isp116x->dentry = debugfs_create_file(hcd_name, |
1204 | S_IRUGO, NULL, isp116x, | 1204 | S_IRUGO, NULL, isp116x, |
1205 | &isp116x_debug_fops); | 1205 | &isp116x_debug_fops); |
1206 | if (!isp116x->dentry) | ||
1207 | return -ENOMEM; | ||
1208 | return 0; | ||
1209 | } | 1206 | } |
1210 | 1207 | ||
1211 | static void remove_debug_file(struct isp116x *isp116x) | 1208 | static void remove_debug_file(struct isp116x *isp116x) |
@@ -1215,8 +1212,8 @@ static void remove_debug_file(struct isp116x *isp116x) | |||
1215 | 1212 | ||
1216 | #else | 1213 | #else |
1217 | 1214 | ||
1218 | #define create_debug_file(d) 0 | 1215 | static inline void create_debug_file(struct isp116x *isp116x) { } |
1219 | #define remove_debug_file(d) do{}while(0) | 1216 | static inline void remove_debug_file(struct isp116x *isp116x) { } |
1220 | 1217 | ||
1221 | #endif /* CONFIG_DEBUG_FS */ | 1218 | #endif /* CONFIG_DEBUG_FS */ |
1222 | 1219 | ||
@@ -1643,16 +1640,10 @@ static int isp116x_probe(struct platform_device *pdev) | |||
1643 | 1640 | ||
1644 | device_wakeup_enable(hcd->self.controller); | 1641 | device_wakeup_enable(hcd->self.controller); |
1645 | 1642 | ||
1646 | ret = create_debug_file(isp116x); | 1643 | create_debug_file(isp116x); |
1647 | if (ret) { | ||
1648 | ERR("Couldn't create debugfs entry\n"); | ||
1649 | goto err7; | ||
1650 | } | ||
1651 | 1644 | ||
1652 | return 0; | 1645 | return 0; |
1653 | 1646 | ||
1654 | err7: | ||
1655 | usb_remove_hcd(hcd); | ||
1656 | err6: | 1647 | err6: |
1657 | usb_put_hcd(hcd); | 1648 | usb_put_hcd(hcd); |
1658 | err5: | 1649 | err5: |
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 5ad9e9bdc8ee..e98673954020 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c | |||
@@ -212,7 +212,7 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, | |||
212 | 212 | ||
213 | ohci_at91->sfr_regmap = at91_dt_syscon_sfr(); | 213 | ohci_at91->sfr_regmap = at91_dt_syscon_sfr(); |
214 | if (!ohci_at91->sfr_regmap) | 214 | if (!ohci_at91->sfr_regmap) |
215 | dev_warn(dev, "failed to find sfr node\n"); | 215 | dev_dbg(dev, "failed to find sfr node\n"); |
216 | 216 | ||
217 | board = hcd->self.controller->platform_data; | 217 | board = hcd->self.controller->platform_data; |
218 | ohci = hcd_to_ohci(hcd); | 218 | ohci = hcd_to_ohci(hcd); |
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index ac7d4ac34b02..d3ee1f52aaab 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c | |||
@@ -762,50 +762,23 @@ static int debug_registers_open(struct inode *inode, struct file *file) | |||
762 | static inline void create_debug_files (struct ohci_hcd *ohci) | 762 | static inline void create_debug_files (struct ohci_hcd *ohci) |
763 | { | 763 | { |
764 | struct usb_bus *bus = &ohci_to_hcd(ohci)->self; | 764 | struct usb_bus *bus = &ohci_to_hcd(ohci)->self; |
765 | struct dentry *root; | ||
765 | 766 | ||
766 | ohci->debug_dir = debugfs_create_dir(bus->bus_name, ohci_debug_root); | 767 | root = debugfs_create_dir(bus->bus_name, ohci_debug_root); |
767 | if (!ohci->debug_dir) | 768 | ohci->debug_dir = root; |
768 | goto dir_error; | ||
769 | 769 | ||
770 | ohci->debug_async = debugfs_create_file("async", S_IRUGO, | 770 | debugfs_create_file("async", S_IRUGO, root, ohci, &debug_async_fops); |
771 | ohci->debug_dir, ohci, | 771 | debugfs_create_file("periodic", S_IRUGO, root, ohci, |
772 | &debug_async_fops); | 772 | &debug_periodic_fops); |
773 | if (!ohci->debug_async) | 773 | debugfs_create_file("registers", S_IRUGO, root, ohci, |
774 | goto async_error; | 774 | &debug_registers_fops); |
775 | |||
776 | ohci->debug_periodic = debugfs_create_file("periodic", S_IRUGO, | ||
777 | ohci->debug_dir, ohci, | ||
778 | &debug_periodic_fops); | ||
779 | if (!ohci->debug_periodic) | ||
780 | goto periodic_error; | ||
781 | |||
782 | ohci->debug_registers = debugfs_create_file("registers", S_IRUGO, | ||
783 | ohci->debug_dir, ohci, | ||
784 | &debug_registers_fops); | ||
785 | if (!ohci->debug_registers) | ||
786 | goto registers_error; | ||
787 | 775 | ||
788 | ohci_dbg (ohci, "created debug files\n"); | 776 | ohci_dbg (ohci, "created debug files\n"); |
789 | return; | ||
790 | |||
791 | registers_error: | ||
792 | debugfs_remove(ohci->debug_periodic); | ||
793 | periodic_error: | ||
794 | debugfs_remove(ohci->debug_async); | ||
795 | async_error: | ||
796 | debugfs_remove(ohci->debug_dir); | ||
797 | dir_error: | ||
798 | ohci->debug_periodic = NULL; | ||
799 | ohci->debug_async = NULL; | ||
800 | ohci->debug_dir = NULL; | ||
801 | } | 777 | } |
802 | 778 | ||
803 | static inline void remove_debug_files (struct ohci_hcd *ohci) | 779 | static inline void remove_debug_files (struct ohci_hcd *ohci) |
804 | { | 780 | { |
805 | debugfs_remove(ohci->debug_registers); | 781 | debugfs_remove_recursive(ohci->debug_dir); |
806 | debugfs_remove(ohci->debug_periodic); | ||
807 | debugfs_remove(ohci->debug_async); | ||
808 | debugfs_remove(ohci->debug_dir); | ||
809 | } | 782 | } |
810 | 783 | ||
811 | /*-------------------------------------------------------------------------*/ | 784 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 4806e0f9e8d4..210181fd98d2 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
@@ -1258,10 +1258,6 @@ static int __init ohci_hcd_mod_init(void) | |||
1258 | set_bit(USB_OHCI_LOADED, &usb_hcds_loaded); | 1258 | set_bit(USB_OHCI_LOADED, &usb_hcds_loaded); |
1259 | 1259 | ||
1260 | ohci_debug_root = debugfs_create_dir("ohci", usb_debug_root); | 1260 | ohci_debug_root = debugfs_create_dir("ohci", usb_debug_root); |
1261 | if (!ohci_debug_root) { | ||
1262 | retval = -ENOENT; | ||
1263 | goto error_debug; | ||
1264 | } | ||
1265 | 1261 | ||
1266 | #ifdef PS3_SYSTEM_BUS_DRIVER | 1262 | #ifdef PS3_SYSTEM_BUS_DRIVER |
1267 | retval = ps3_ohci_driver_register(&PS3_SYSTEM_BUS_DRIVER); | 1263 | retval = ps3_ohci_driver_register(&PS3_SYSTEM_BUS_DRIVER); |
@@ -1318,7 +1314,6 @@ static int __init ohci_hcd_mod_init(void) | |||
1318 | #endif | 1314 | #endif |
1319 | debugfs_remove(ohci_debug_root); | 1315 | debugfs_remove(ohci_debug_root); |
1320 | ohci_debug_root = NULL; | 1316 | ohci_debug_root = NULL; |
1321 | error_debug: | ||
1322 | 1317 | ||
1323 | clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded); | 1318 | clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded); |
1324 | return retval; | 1319 | return retval; |
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 508a803139dd..ef4813bfc5bf 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h | |||
@@ -431,9 +431,6 @@ struct ohci_hcd { | |||
431 | struct work_struct nec_work; /* Worker for NEC quirk */ | 431 | struct work_struct nec_work; /* Worker for NEC quirk */ |
432 | 432 | ||
433 | struct dentry *debug_dir; | 433 | struct dentry *debug_dir; |
434 | struct dentry *debug_async; | ||
435 | struct dentry *debug_periodic; | ||
436 | struct dentry *debug_registers; | ||
437 | 434 | ||
438 | /* platform-specific data -- must come last */ | 435 | /* platform-specific data -- must come last */ |
439 | unsigned long priv[0] __aligned(sizeof(s64)); | 436 | unsigned long priv[0] __aligned(sizeof(s64)); |
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 67ad4bb6919a..3625a5c1a41b 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c | |||
@@ -1268,23 +1268,3 @@ static void quirk_usb_early_handoff(struct pci_dev *pdev) | |||
1268 | } | 1268 | } |
1269 | DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID, | 1269 | DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID, |
1270 | PCI_CLASS_SERIAL_USB, 8, quirk_usb_early_handoff); | 1270 | PCI_CLASS_SERIAL_USB, 8, quirk_usb_early_handoff); |
1271 | |||
1272 | bool usb_xhci_needs_pci_reset(struct pci_dev *pdev) | ||
1273 | { | ||
1274 | /* | ||
1275 | * Our dear uPD72020{1,2} friend only partially resets when | ||
1276 | * asked to via the XHCI interface, and may end up doing DMA | ||
1277 | * at the wrong addresses, as it keeps the top 32bit of some | ||
1278 | * addresses from its previous programming under obscure | ||
1279 | * circumstances. | ||
1280 | * Give it a good wack at probe time. Unfortunately, this | ||
1281 | * needs to happen before we've had a chance to discover any | ||
1282 | * quirk, or the system will be in a rather bad state. | ||
1283 | */ | ||
1284 | if (pdev->vendor == PCI_VENDOR_ID_RENESAS && | ||
1285 | (pdev->device == 0x0014 || pdev->device == 0x0015)) | ||
1286 | return true; | ||
1287 | |||
1288 | return false; | ||
1289 | } | ||
1290 | EXPORT_SYMBOL_GPL(usb_xhci_needs_pci_reset); | ||
diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h index 4ca0d9b7e463..63c633077d9e 100644 --- a/drivers/usb/host/pci-quirks.h +++ b/drivers/usb/host/pci-quirks.h | |||
@@ -16,7 +16,6 @@ void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev); | |||
16 | void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev); | 16 | void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev); |
17 | void usb_disable_xhci_ports(struct pci_dev *xhci_pdev); | 17 | void usb_disable_xhci_ports(struct pci_dev *xhci_pdev); |
18 | void sb800_prefetch(struct device *dev, int on); | 18 | void sb800_prefetch(struct device *dev, int on); |
19 | bool usb_xhci_needs_pci_reset(struct pci_dev *pdev); | ||
20 | bool usb_amd_pt_check_port(struct device *device, int port); | 19 | bool usb_amd_pt_check_port(struct device *device, int port); |
21 | #else | 20 | #else |
22 | struct pci_dev; | 21 | struct pci_dev; |
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index f9c3947577fc..6218bfe54f52 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -590,14 +590,10 @@ static int uhci_start(struct usb_hcd *hcd) | |||
590 | init_waitqueue_head(&uhci->waitqh); | 590 | init_waitqueue_head(&uhci->waitqh); |
591 | 591 | ||
592 | #ifdef UHCI_DEBUG_OPS | 592 | #ifdef UHCI_DEBUG_OPS |
593 | dentry = debugfs_create_file(hcd->self.bus_name, | 593 | uhci->dentry = debugfs_create_file(hcd->self.bus_name, |
594 | S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, | 594 | S_IFREG|S_IRUGO|S_IWUSR, |
595 | uhci, &uhci_debug_operations); | 595 | uhci_debugfs_root, uhci, |
596 | if (!dentry) { | 596 | &uhci_debug_operations); |
597 | dev_err(uhci_dev(uhci), "couldn't create uhci debugfs entry\n"); | ||
598 | return -ENOMEM; | ||
599 | } | ||
600 | uhci->dentry = dentry; | ||
601 | #endif | 597 | #endif |
602 | 598 | ||
603 | uhci->frame = dma_zalloc_coherent(uhci_dev(uhci), | 599 | uhci->frame = dma_zalloc_coherent(uhci_dev(uhci), |
@@ -882,8 +878,6 @@ static int __init uhci_hcd_init(void) | |||
882 | if (!errbuf) | 878 | if (!errbuf) |
883 | goto errbuf_failed; | 879 | goto errbuf_failed; |
884 | uhci_debugfs_root = debugfs_create_dir("uhci", usb_debug_root); | 880 | uhci_debugfs_root = debugfs_create_dir("uhci", usb_debug_root); |
885 | if (!uhci_debugfs_root) | ||
886 | goto debug_failed; | ||
887 | #endif | 881 | #endif |
888 | 882 | ||
889 | uhci_up_cachep = kmem_cache_create("uhci_urb_priv", | 883 | uhci_up_cachep = kmem_cache_create("uhci_urb_priv", |
@@ -918,7 +912,6 @@ up_failed: | |||
918 | #if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) | 912 | #if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) |
919 | debugfs_remove(uhci_debugfs_root); | 913 | debugfs_remove(uhci_debugfs_root); |
920 | 914 | ||
921 | debug_failed: | ||
922 | kfree(errbuf); | 915 | kfree(errbuf); |
923 | 916 | ||
924 | errbuf_failed: | 917 | errbuf_failed: |
diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c index c359bae7b754..1fbfd89d0a0f 100644 --- a/drivers/usb/host/xhci-dbgcap.c +++ b/drivers/usb/host/xhci-dbgcap.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /** | 2 | /** |
2 | * xhci-dbgcap.c - xHCI debug capability support | 3 | * xhci-dbgcap.c - xHCI debug capability support |
3 | * | 4 | * |
diff --git a/drivers/usb/host/xhci-dbgcap.h b/drivers/usb/host/xhci-dbgcap.h index e66ea0748ba3..ce0c6072bd48 100644 --- a/drivers/usb/host/xhci-dbgcap.h +++ b/drivers/usb/host/xhci-dbgcap.h | |||
@@ -1,4 +1,4 @@ | |||
1 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ | |
2 | /** | 2 | /** |
3 | * xhci-dbgcap.h - xHCI debug capability support | 3 | * xhci-dbgcap.h - xHCI debug capability support |
4 | * | 4 | * |
diff --git a/drivers/usb/host/xhci-dbgtty.c b/drivers/usb/host/xhci-dbgtty.c index eb494ec547e8..aff79ff5aba4 100644 --- a/drivers/usb/host/xhci-dbgtty.c +++ b/drivers/usb/host/xhci-dbgtty.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /** | 2 | /** |
2 | * xhci-dbgtty.c - tty glue for xHCI debug capability | 3 | * xhci-dbgtty.c - tty glue for xHCI debug capability |
3 | * | 4 | * |
diff --git a/drivers/usb/host/xhci-debugfs.c b/drivers/usb/host/xhci-debugfs.c index 5851052d4668..cadc01336bf8 100644 --- a/drivers/usb/host/xhci-debugfs.c +++ b/drivers/usb/host/xhci-debugfs.c | |||
@@ -8,6 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
11 | #include <linux/uaccess.h> | ||
11 | 12 | ||
12 | #include "xhci.h" | 13 | #include "xhci.h" |
13 | #include "xhci-debugfs.h" | 14 | #include "xhci-debugfs.h" |
@@ -333,6 +334,67 @@ static const struct file_operations xhci_context_fops = { | |||
333 | .release = single_release, | 334 | .release = single_release, |
334 | }; | 335 | }; |
335 | 336 | ||
337 | |||
338 | |||
339 | static int xhci_portsc_show(struct seq_file *s, void *unused) | ||
340 | { | ||
341 | struct xhci_port *port = s->private; | ||
342 | u32 portsc; | ||
343 | |||
344 | portsc = readl(port->addr); | ||
345 | seq_printf(s, "%s\n", xhci_decode_portsc(portsc)); | ||
346 | |||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | static int xhci_port_open(struct inode *inode, struct file *file) | ||
351 | { | ||
352 | return single_open(file, xhci_portsc_show, inode->i_private); | ||
353 | } | ||
354 | |||
355 | static ssize_t xhci_port_write(struct file *file, const char __user *ubuf, | ||
356 | size_t count, loff_t *ppos) | ||
357 | { | ||
358 | struct seq_file *s = file->private_data; | ||
359 | struct xhci_port *port = s->private; | ||
360 | struct xhci_hcd *xhci = hcd_to_xhci(port->rhub->hcd); | ||
361 | char buf[32]; | ||
362 | u32 portsc; | ||
363 | unsigned long flags; | ||
364 | |||
365 | if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) | ||
366 | return -EFAULT; | ||
367 | |||
368 | if (!strncmp(buf, "compliance", 10)) { | ||
369 | /* If CTC is clear, compliance is enabled by default */ | ||
370 | if (!HCC2_CTC(xhci->hcc_params2)) | ||
371 | return count; | ||
372 | spin_lock_irqsave(&xhci->lock, flags); | ||
373 | /* compliance mode can only be enabled on ports in RxDetect */ | ||
374 | portsc = readl(port->addr); | ||
375 | if ((portsc & PORT_PLS_MASK) != XDEV_RXDETECT) { | ||
376 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
377 | return -EPERM; | ||
378 | } | ||
379 | portsc = xhci_port_state_to_neutral(portsc); | ||
380 | portsc &= ~PORT_PLS_MASK; | ||
381 | portsc |= PORT_LINK_STROBE | XDEV_COMP_MODE; | ||
382 | writel(portsc, port->addr); | ||
383 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
384 | } else { | ||
385 | return -EINVAL; | ||
386 | } | ||
387 | return count; | ||
388 | } | ||
389 | |||
390 | static const struct file_operations port_fops = { | ||
391 | .open = xhci_port_open, | ||
392 | .write = xhci_port_write, | ||
393 | .read = seq_read, | ||
394 | .llseek = seq_lseek, | ||
395 | .release = single_release, | ||
396 | }; | ||
397 | |||
336 | static void xhci_debugfs_create_files(struct xhci_hcd *xhci, | 398 | static void xhci_debugfs_create_files(struct xhci_hcd *xhci, |
337 | struct xhci_file_map *files, | 399 | struct xhci_file_map *files, |
338 | size_t nentries, void *data, | 400 | size_t nentries, void *data, |
@@ -449,6 +511,27 @@ void xhci_debugfs_remove_slot(struct xhci_hcd *xhci, int slot_id) | |||
449 | dev->debugfs_private = NULL; | 511 | dev->debugfs_private = NULL; |
450 | } | 512 | } |
451 | 513 | ||
514 | static void xhci_debugfs_create_ports(struct xhci_hcd *xhci, | ||
515 | struct dentry *parent) | ||
516 | { | ||
517 | unsigned int num_ports; | ||
518 | char port_name[8]; | ||
519 | struct xhci_port *port; | ||
520 | struct dentry *dir; | ||
521 | |||
522 | num_ports = HCS_MAX_PORTS(xhci->hcs_params1); | ||
523 | |||
524 | parent = debugfs_create_dir("ports", parent); | ||
525 | |||
526 | while (num_ports--) { | ||
527 | scnprintf(port_name, sizeof(port_name), "port%02d", | ||
528 | num_ports + 1); | ||
529 | dir = debugfs_create_dir(port_name, parent); | ||
530 | port = &xhci->hw_ports[num_ports]; | ||
531 | debugfs_create_file("portsc", 0644, dir, port, &port_fops); | ||
532 | } | ||
533 | } | ||
534 | |||
452 | void xhci_debugfs_init(struct xhci_hcd *xhci) | 535 | void xhci_debugfs_init(struct xhci_hcd *xhci) |
453 | { | 536 | { |
454 | struct device *dev = xhci_to_hcd(xhci)->self.controller; | 537 | struct device *dev = xhci_to_hcd(xhci)->self.controller; |
@@ -497,6 +580,8 @@ void xhci_debugfs_init(struct xhci_hcd *xhci) | |||
497 | xhci->debugfs_root); | 580 | xhci->debugfs_root); |
498 | 581 | ||
499 | xhci->debugfs_slots = debugfs_create_dir("devices", xhci->debugfs_root); | 582 | xhci->debugfs_slots = debugfs_create_dir("devices", xhci->debugfs_root); |
583 | |||
584 | xhci_debugfs_create_ports(xhci, xhci->debugfs_root); | ||
500 | } | 585 | } |
501 | 586 | ||
502 | void xhci_debugfs_exit(struct xhci_hcd *xhci) | 587 | void xhci_debugfs_exit(struct xhci_hcd *xhci) |
diff --git a/drivers/usb/host/xhci-histb.c b/drivers/usb/host/xhci-histb.c new file mode 100644 index 000000000000..27f00160332e --- /dev/null +++ b/drivers/usb/host/xhci-histb.c | |||
@@ -0,0 +1,410 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * xHCI host controller driver for HiSilicon STB SoCs | ||
4 | * | ||
5 | * Copyright (C) 2017-2018 HiSilicon Co., Ltd. http://www.hisilicon.com | ||
6 | * | ||
7 | * Authors: Jianguo Sun <sunjianguo1@huawei.com> | ||
8 | */ | ||
9 | |||
10 | #include <linux/clk.h> | ||
11 | #include <linux/dma-mapping.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/of.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/pm_runtime.h> | ||
17 | #include <linux/reset.h> | ||
18 | |||
19 | #include "xhci.h" | ||
20 | |||
21 | #define GTXTHRCFG 0xc108 | ||
22 | #define GRXTHRCFG 0xc10c | ||
23 | #define REG_GUSB2PHYCFG0 0xc200 | ||
24 | #define BIT_UTMI_8_16 BIT(3) | ||
25 | #define BIT_UTMI_ULPI BIT(4) | ||
26 | #define BIT_FREECLK_EXIST BIT(30) | ||
27 | |||
28 | #define REG_GUSB3PIPECTL0 0xc2c0 | ||
29 | #define USB3_DEEMPHASIS_MASK GENMASK(2, 1) | ||
30 | #define USB3_DEEMPHASIS0 BIT(1) | ||
31 | #define USB3_TX_MARGIN1 BIT(4) | ||
32 | |||
33 | struct xhci_hcd_histb { | ||
34 | struct device *dev; | ||
35 | struct usb_hcd *hcd; | ||
36 | void __iomem *ctrl; | ||
37 | struct clk *bus_clk; | ||
38 | struct clk *utmi_clk; | ||
39 | struct clk *pipe_clk; | ||
40 | struct clk *suspend_clk; | ||
41 | struct reset_control *soft_reset; | ||
42 | }; | ||
43 | |||
44 | static inline struct xhci_hcd_histb *hcd_to_histb(struct usb_hcd *hcd) | ||
45 | { | ||
46 | return dev_get_drvdata(hcd->self.controller); | ||
47 | } | ||
48 | |||
49 | static int xhci_histb_config(struct xhci_hcd_histb *histb) | ||
50 | { | ||
51 | struct device_node *np = histb->dev->of_node; | ||
52 | u32 regval; | ||
53 | |||
54 | if (of_property_match_string(np, "phys-names", "inno") >= 0) { | ||
55 | /* USB2 PHY chose ulpi 8bit interface */ | ||
56 | regval = readl(histb->ctrl + REG_GUSB2PHYCFG0); | ||
57 | regval &= ~BIT_UTMI_ULPI; | ||
58 | regval &= ~(BIT_UTMI_8_16); | ||
59 | regval &= ~BIT_FREECLK_EXIST; | ||
60 | writel(regval, histb->ctrl + REG_GUSB2PHYCFG0); | ||
61 | } | ||
62 | |||
63 | if (of_property_match_string(np, "phys-names", "combo") >= 0) { | ||
64 | /* | ||
65 | * write 0x010c0012 to GUSB3PIPECTL0 | ||
66 | * GUSB3PIPECTL0[5:3] = 010 : Tx Margin = 900mV , | ||
67 | * decrease TX voltage | ||
68 | * GUSB3PIPECTL0[2:1] = 01 : Tx Deemphasis = -3.5dB, | ||
69 | * refer to xHCI spec | ||
70 | */ | ||
71 | regval = readl(histb->ctrl + REG_GUSB3PIPECTL0); | ||
72 | regval &= ~USB3_DEEMPHASIS_MASK; | ||
73 | regval |= USB3_DEEMPHASIS0; | ||
74 | regval |= USB3_TX_MARGIN1; | ||
75 | writel(regval, histb->ctrl + REG_GUSB3PIPECTL0); | ||
76 | } | ||
77 | |||
78 | writel(0x23100000, histb->ctrl + GTXTHRCFG); | ||
79 | writel(0x23100000, histb->ctrl + GRXTHRCFG); | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static int xhci_histb_clks_get(struct xhci_hcd_histb *histb) | ||
85 | { | ||
86 | struct device *dev = histb->dev; | ||
87 | |||
88 | histb->bus_clk = devm_clk_get(dev, "bus"); | ||
89 | if (IS_ERR(histb->bus_clk)) { | ||
90 | dev_err(dev, "fail to get bus clk\n"); | ||
91 | return PTR_ERR(histb->bus_clk); | ||
92 | } | ||
93 | |||
94 | histb->utmi_clk = devm_clk_get(dev, "utmi"); | ||
95 | if (IS_ERR(histb->utmi_clk)) { | ||
96 | dev_err(dev, "fail to get utmi clk\n"); | ||
97 | return PTR_ERR(histb->utmi_clk); | ||
98 | } | ||
99 | |||
100 | histb->pipe_clk = devm_clk_get(dev, "pipe"); | ||
101 | if (IS_ERR(histb->pipe_clk)) { | ||
102 | dev_err(dev, "fail to get pipe clk\n"); | ||
103 | return PTR_ERR(histb->pipe_clk); | ||
104 | } | ||
105 | |||
106 | histb->suspend_clk = devm_clk_get(dev, "suspend"); | ||
107 | if (IS_ERR(histb->suspend_clk)) { | ||
108 | dev_err(dev, "fail to get suspend clk\n"); | ||
109 | return PTR_ERR(histb->suspend_clk); | ||
110 | } | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static int xhci_histb_host_enable(struct xhci_hcd_histb *histb) | ||
116 | { | ||
117 | int ret; | ||
118 | |||
119 | ret = clk_prepare_enable(histb->bus_clk); | ||
120 | if (ret) { | ||
121 | dev_err(histb->dev, "failed to enable bus clk\n"); | ||
122 | return ret; | ||
123 | } | ||
124 | |||
125 | ret = clk_prepare_enable(histb->utmi_clk); | ||
126 | if (ret) { | ||
127 | dev_err(histb->dev, "failed to enable utmi clk\n"); | ||
128 | goto err_utmi_clk; | ||
129 | } | ||
130 | |||
131 | ret = clk_prepare_enable(histb->pipe_clk); | ||
132 | if (ret) { | ||
133 | dev_err(histb->dev, "failed to enable pipe clk\n"); | ||
134 | goto err_pipe_clk; | ||
135 | } | ||
136 | |||
137 | ret = clk_prepare_enable(histb->suspend_clk); | ||
138 | if (ret) { | ||
139 | dev_err(histb->dev, "failed to enable suspend clk\n"); | ||
140 | goto err_suspend_clk; | ||
141 | } | ||
142 | |||
143 | reset_control_deassert(histb->soft_reset); | ||
144 | |||
145 | return 0; | ||
146 | |||
147 | err_suspend_clk: | ||
148 | clk_disable_unprepare(histb->pipe_clk); | ||
149 | err_pipe_clk: | ||
150 | clk_disable_unprepare(histb->utmi_clk); | ||
151 | err_utmi_clk: | ||
152 | clk_disable_unprepare(histb->bus_clk); | ||
153 | |||
154 | return ret; | ||
155 | } | ||
156 | |||
157 | static void xhci_histb_host_disable(struct xhci_hcd_histb *histb) | ||
158 | { | ||
159 | reset_control_assert(histb->soft_reset); | ||
160 | |||
161 | clk_disable_unprepare(histb->suspend_clk); | ||
162 | clk_disable_unprepare(histb->pipe_clk); | ||
163 | clk_disable_unprepare(histb->utmi_clk); | ||
164 | clk_disable_unprepare(histb->bus_clk); | ||
165 | } | ||
166 | |||
167 | static void xhci_histb_quirks(struct device *dev, struct xhci_hcd *xhci) | ||
168 | { | ||
169 | /* | ||
170 | * As of now platform drivers don't provide MSI support so we ensure | ||
171 | * here that the generic code does not try to make a pci_dev from our | ||
172 | * dev struct in order to setup MSI | ||
173 | */ | ||
174 | xhci->quirks |= XHCI_PLAT; | ||
175 | } | ||
176 | |||
177 | /* called during probe() after chip reset completes */ | ||
178 | static int xhci_histb_setup(struct usb_hcd *hcd) | ||
179 | { | ||
180 | struct xhci_hcd_histb *histb = hcd_to_histb(hcd); | ||
181 | int ret; | ||
182 | |||
183 | if (usb_hcd_is_primary_hcd(hcd)) { | ||
184 | ret = xhci_histb_config(histb); | ||
185 | if (ret) | ||
186 | return ret; | ||
187 | } | ||
188 | |||
189 | return xhci_gen_setup(hcd, xhci_histb_quirks); | ||
190 | } | ||
191 | |||
192 | static const struct xhci_driver_overrides xhci_histb_overrides __initconst = { | ||
193 | .reset = xhci_histb_setup, | ||
194 | }; | ||
195 | |||
196 | static struct hc_driver __read_mostly xhci_histb_hc_driver; | ||
197 | static int xhci_histb_probe(struct platform_device *pdev) | ||
198 | { | ||
199 | struct device *dev = &pdev->dev; | ||
200 | struct xhci_hcd_histb *histb; | ||
201 | const struct hc_driver *driver; | ||
202 | struct usb_hcd *hcd; | ||
203 | struct xhci_hcd *xhci; | ||
204 | struct resource *res; | ||
205 | int irq; | ||
206 | int ret = -ENODEV; | ||
207 | |||
208 | if (usb_disabled()) | ||
209 | return -ENODEV; | ||
210 | |||
211 | driver = &xhci_histb_hc_driver; | ||
212 | histb = devm_kzalloc(dev, sizeof(*histb), GFP_KERNEL); | ||
213 | if (!histb) | ||
214 | return -ENOMEM; | ||
215 | |||
216 | histb->dev = dev; | ||
217 | |||
218 | irq = platform_get_irq(pdev, 0); | ||
219 | if (irq < 0) | ||
220 | return irq; | ||
221 | |||
222 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
223 | histb->ctrl = devm_ioremap_resource(&pdev->dev, res); | ||
224 | if (IS_ERR(histb->ctrl)) | ||
225 | return PTR_ERR(histb->ctrl); | ||
226 | |||
227 | ret = xhci_histb_clks_get(histb); | ||
228 | if (ret) | ||
229 | return ret; | ||
230 | |||
231 | histb->soft_reset = devm_reset_control_get(dev, "soft"); | ||
232 | if (IS_ERR(histb->soft_reset)) { | ||
233 | dev_err(dev, "failed to get soft reset\n"); | ||
234 | return PTR_ERR(histb->soft_reset); | ||
235 | } | ||
236 | |||
237 | pm_runtime_enable(dev); | ||
238 | pm_runtime_get_sync(dev); | ||
239 | device_enable_async_suspend(dev); | ||
240 | |||
241 | /* Initialize dma_mask and coherent_dma_mask to 32-bits */ | ||
242 | ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); | ||
243 | if (ret) | ||
244 | return ret; | ||
245 | |||
246 | hcd = usb_create_hcd(driver, dev, dev_name(dev)); | ||
247 | if (!hcd) { | ||
248 | ret = -ENOMEM; | ||
249 | goto disable_pm; | ||
250 | } | ||
251 | |||
252 | hcd->regs = histb->ctrl; | ||
253 | hcd->rsrc_start = res->start; | ||
254 | hcd->rsrc_len = resource_size(res); | ||
255 | |||
256 | histb->hcd = hcd; | ||
257 | dev_set_drvdata(hcd->self.controller, histb); | ||
258 | |||
259 | ret = xhci_histb_host_enable(histb); | ||
260 | if (ret) | ||
261 | goto put_hcd; | ||
262 | |||
263 | xhci = hcd_to_xhci(hcd); | ||
264 | |||
265 | device_wakeup_enable(hcd->self.controller); | ||
266 | |||
267 | xhci->main_hcd = hcd; | ||
268 | xhci->shared_hcd = usb_create_shared_hcd(driver, dev, dev_name(dev), | ||
269 | hcd); | ||
270 | if (!xhci->shared_hcd) { | ||
271 | ret = -ENOMEM; | ||
272 | goto disable_host; | ||
273 | } | ||
274 | |||
275 | if (device_property_read_bool(dev, "usb2-lpm-disable")) | ||
276 | xhci->quirks |= XHCI_HW_LPM_DISABLE; | ||
277 | |||
278 | if (device_property_read_bool(dev, "usb3-lpm-capable")) | ||
279 | xhci->quirks |= XHCI_LPM_SUPPORT; | ||
280 | |||
281 | /* imod_interval is the interrupt moderation value in nanoseconds. */ | ||
282 | xhci->imod_interval = 40000; | ||
283 | device_property_read_u32(dev, "imod-interval-ns", | ||
284 | &xhci->imod_interval); | ||
285 | |||
286 | ret = usb_add_hcd(hcd, irq, IRQF_SHARED); | ||
287 | if (ret) | ||
288 | goto put_usb3_hcd; | ||
289 | |||
290 | if (HCC_MAX_PSA(xhci->hcc_params) >= 4) | ||
291 | xhci->shared_hcd->can_do_streams = 1; | ||
292 | |||
293 | ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); | ||
294 | if (ret) | ||
295 | goto dealloc_usb2_hcd; | ||
296 | |||
297 | device_enable_async_suspend(dev); | ||
298 | pm_runtime_put_noidle(dev); | ||
299 | |||
300 | /* | ||
301 | * Prevent runtime pm from being on as default, users should enable | ||
302 | * runtime pm using power/control in sysfs. | ||
303 | */ | ||
304 | pm_runtime_forbid(dev); | ||
305 | |||
306 | return 0; | ||
307 | |||
308 | dealloc_usb2_hcd: | ||
309 | usb_remove_hcd(hcd); | ||
310 | put_usb3_hcd: | ||
311 | usb_put_hcd(xhci->shared_hcd); | ||
312 | disable_host: | ||
313 | xhci_histb_host_disable(histb); | ||
314 | put_hcd: | ||
315 | usb_put_hcd(hcd); | ||
316 | disable_pm: | ||
317 | pm_runtime_put_sync(dev); | ||
318 | pm_runtime_disable(dev); | ||
319 | |||
320 | return ret; | ||
321 | } | ||
322 | |||
323 | static int xhci_histb_remove(struct platform_device *dev) | ||
324 | { | ||
325 | struct xhci_hcd_histb *histb = platform_get_drvdata(dev); | ||
326 | struct usb_hcd *hcd = histb->hcd; | ||
327 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | ||
328 | |||
329 | xhci->xhc_state |= XHCI_STATE_REMOVING; | ||
330 | |||
331 | usb_remove_hcd(xhci->shared_hcd); | ||
332 | device_wakeup_disable(&dev->dev); | ||
333 | |||
334 | usb_remove_hcd(hcd); | ||
335 | usb_put_hcd(xhci->shared_hcd); | ||
336 | |||
337 | xhci_histb_host_disable(histb); | ||
338 | usb_put_hcd(hcd); | ||
339 | pm_runtime_put_sync(&dev->dev); | ||
340 | pm_runtime_disable(&dev->dev); | ||
341 | |||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static int __maybe_unused xhci_histb_suspend(struct device *dev) | ||
346 | { | ||
347 | struct xhci_hcd_histb *histb = dev_get_drvdata(dev); | ||
348 | struct usb_hcd *hcd = histb->hcd; | ||
349 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | ||
350 | int ret; | ||
351 | |||
352 | ret = xhci_suspend(xhci, device_may_wakeup(dev)); | ||
353 | |||
354 | if (!device_may_wakeup(dev)) | ||
355 | xhci_histb_host_disable(histb); | ||
356 | |||
357 | return ret; | ||
358 | } | ||
359 | |||
360 | static int __maybe_unused xhci_histb_resume(struct device *dev) | ||
361 | { | ||
362 | struct xhci_hcd_histb *histb = dev_get_drvdata(dev); | ||
363 | struct usb_hcd *hcd = histb->hcd; | ||
364 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | ||
365 | |||
366 | if (!device_may_wakeup(dev)) | ||
367 | xhci_histb_host_enable(histb); | ||
368 | |||
369 | return xhci_resume(xhci, 0); | ||
370 | } | ||
371 | |||
372 | static const struct dev_pm_ops xhci_histb_pm_ops = { | ||
373 | SET_SYSTEM_SLEEP_PM_OPS(xhci_histb_suspend, xhci_histb_resume) | ||
374 | }; | ||
375 | #define DEV_PM_OPS (IS_ENABLED(CONFIG_PM) ? &xhci_histb_pm_ops : NULL) | ||
376 | |||
377 | #ifdef CONFIG_OF | ||
378 | static const struct of_device_id histb_xhci_of_match[] = { | ||
379 | { .compatible = "hisilicon,hi3798cv200-xhci"}, | ||
380 | { }, | ||
381 | }; | ||
382 | MODULE_DEVICE_TABLE(of, histb_xhci_of_match); | ||
383 | #endif | ||
384 | |||
385 | static struct platform_driver histb_xhci_driver = { | ||
386 | .probe = xhci_histb_probe, | ||
387 | .remove = xhci_histb_remove, | ||
388 | .driver = { | ||
389 | .name = "xhci-histb", | ||
390 | .pm = DEV_PM_OPS, | ||
391 | .of_match_table = of_match_ptr(histb_xhci_of_match), | ||
392 | }, | ||
393 | }; | ||
394 | MODULE_ALIAS("platform:xhci-histb"); | ||
395 | |||
396 | static int __init xhci_histb_init(void) | ||
397 | { | ||
398 | xhci_init_driver(&xhci_histb_hc_driver, &xhci_histb_overrides); | ||
399 | return platform_driver_register(&histb_xhci_driver); | ||
400 | } | ||
401 | module_init(xhci_histb_init); | ||
402 | |||
403 | static void __exit xhci_histb_exit(void) | ||
404 | { | ||
405 | platform_driver_unregister(&histb_xhci_driver); | ||
406 | } | ||
407 | module_exit(xhci_histb_exit); | ||
408 | |||
409 | MODULE_DESCRIPTION("HiSilicon STB xHCI Host Controller Driver"); | ||
410 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 32cd52ca8318..a4b95d019f84 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c | |||
@@ -189,9 +189,10 @@ static void xhci_usb2_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, | |||
189 | __u8 port_removable[(USB_MAXCHILDREN + 1 + 7) / 8]; | 189 | __u8 port_removable[(USB_MAXCHILDREN + 1 + 7) / 8]; |
190 | u32 portsc; | 190 | u32 portsc; |
191 | unsigned int i; | 191 | unsigned int i; |
192 | struct xhci_hub *rhub; | ||
192 | 193 | ||
193 | ports = xhci->num_usb2_ports; | 194 | rhub = &xhci->usb2_rhub; |
194 | 195 | ports = rhub->num_ports; | |
195 | xhci_common_hub_descriptor(xhci, desc, ports); | 196 | xhci_common_hub_descriptor(xhci, desc, ports); |
196 | desc->bDescriptorType = USB_DT_HUB; | 197 | desc->bDescriptorType = USB_DT_HUB; |
197 | temp = 1 + (ports / 8); | 198 | temp = 1 + (ports / 8); |
@@ -202,7 +203,7 @@ static void xhci_usb2_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, | |||
202 | */ | 203 | */ |
203 | memset(port_removable, 0, sizeof(port_removable)); | 204 | memset(port_removable, 0, sizeof(port_removable)); |
204 | for (i = 0; i < ports; i++) { | 205 | for (i = 0; i < ports; i++) { |
205 | portsc = readl(xhci->usb2_ports[i]); | 206 | portsc = readl(rhub->ports[i]->addr); |
206 | /* If a device is removable, PORTSC reports a 0, same as in the | 207 | /* If a device is removable, PORTSC reports a 0, same as in the |
207 | * hub descriptor DeviceRemovable bits. | 208 | * hub descriptor DeviceRemovable bits. |
208 | */ | 209 | */ |
@@ -241,8 +242,10 @@ static void xhci_usb3_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, | |||
241 | u16 port_removable; | 242 | u16 port_removable; |
242 | u32 portsc; | 243 | u32 portsc; |
243 | unsigned int i; | 244 | unsigned int i; |
245 | struct xhci_hub *rhub; | ||
244 | 246 | ||
245 | ports = xhci->num_usb3_ports; | 247 | rhub = &xhci->usb3_rhub; |
248 | ports = rhub->num_ports; | ||
246 | xhci_common_hub_descriptor(xhci, desc, ports); | 249 | xhci_common_hub_descriptor(xhci, desc, ports); |
247 | desc->bDescriptorType = USB_DT_SS_HUB; | 250 | desc->bDescriptorType = USB_DT_SS_HUB; |
248 | desc->bDescLength = USB_DT_SS_HUB_SIZE; | 251 | desc->bDescLength = USB_DT_SS_HUB_SIZE; |
@@ -256,7 +259,7 @@ static void xhci_usb3_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, | |||
256 | port_removable = 0; | 259 | port_removable = 0; |
257 | /* bit 0 is reserved, bit 1 is for port 1, etc. */ | 260 | /* bit 0 is reserved, bit 1 is for port 1, etc. */ |
258 | for (i = 0; i < ports; i++) { | 261 | for (i = 0; i < ports; i++) { |
259 | portsc = readl(xhci->usb3_ports[i]); | 262 | portsc = readl(rhub->ports[i]->addr); |
260 | if (portsc & PORT_DEV_REMOVE) | 263 | if (portsc & PORT_DEV_REMOVE) |
261 | port_removable |= 1 << (i + 1); | 264 | port_removable |= 1 << (i + 1); |
262 | } | 265 | } |
@@ -538,28 +541,13 @@ static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue, | |||
538 | port_change_bit, wIndex, port_status); | 541 | port_change_bit, wIndex, port_status); |
539 | } | 542 | } |
540 | 543 | ||
541 | static int xhci_get_ports(struct usb_hcd *hcd, __le32 __iomem ***port_array) | 544 | struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd) |
542 | { | 545 | { |
543 | int max_ports; | ||
544 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 546 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
545 | 547 | ||
546 | if (hcd->speed >= HCD_USB3) { | 548 | if (hcd->speed >= HCD_USB3) |
547 | max_ports = xhci->num_usb3_ports; | 549 | return &xhci->usb3_rhub; |
548 | *port_array = xhci->usb3_ports; | 550 | return &xhci->usb2_rhub; |
549 | } else { | ||
550 | max_ports = xhci->num_usb2_ports; | ||
551 | *port_array = xhci->usb2_ports; | ||
552 | } | ||
553 | |||
554 | return max_ports; | ||
555 | } | ||
556 | |||
557 | static __le32 __iomem *xhci_get_port_io_addr(struct usb_hcd *hcd, int index) | ||
558 | { | ||
559 | __le32 __iomem **port_array; | ||
560 | |||
561 | xhci_get_ports(hcd, &port_array); | ||
562 | return port_array[index]; | ||
563 | } | 551 | } |
564 | 552 | ||
565 | /* | 553 | /* |
@@ -570,21 +558,23 @@ static __le32 __iomem *xhci_get_port_io_addr(struct usb_hcd *hcd, int index) | |||
570 | static void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd, | 558 | static void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd, |
571 | u16 index, bool on, unsigned long *flags) | 559 | u16 index, bool on, unsigned long *flags) |
572 | { | 560 | { |
573 | __le32 __iomem *addr; | 561 | struct xhci_hub *rhub; |
562 | struct xhci_port *port; | ||
574 | u32 temp; | 563 | u32 temp; |
575 | 564 | ||
576 | addr = xhci_get_port_io_addr(hcd, index); | 565 | rhub = xhci_get_rhub(hcd); |
577 | temp = readl(addr); | 566 | port = rhub->ports[index]; |
567 | temp = readl(port->addr); | ||
578 | temp = xhci_port_state_to_neutral(temp); | 568 | temp = xhci_port_state_to_neutral(temp); |
579 | if (on) { | 569 | if (on) { |
580 | /* Power on */ | 570 | /* Power on */ |
581 | writel(temp | PORT_POWER, addr); | 571 | writel(temp | PORT_POWER, port->addr); |
582 | temp = readl(addr); | 572 | temp = readl(port->addr); |
583 | xhci_dbg(xhci, "set port power, actual port %d status = 0x%x\n", | 573 | xhci_dbg(xhci, "set port power, actual port %d status = 0x%x\n", |
584 | index, temp); | 574 | index, temp); |
585 | } else { | 575 | } else { |
586 | /* Power off */ | 576 | /* Power off */ |
587 | writel(temp & ~PORT_POWER, addr); | 577 | writel(temp & ~PORT_POWER, port->addr); |
588 | } | 578 | } |
589 | 579 | ||
590 | spin_unlock_irqrestore(&xhci->lock, *flags); | 580 | spin_unlock_irqrestore(&xhci->lock, *flags); |
@@ -600,13 +590,13 @@ static void xhci_port_set_test_mode(struct xhci_hcd *xhci, | |||
600 | u16 test_mode, u16 wIndex) | 590 | u16 test_mode, u16 wIndex) |
601 | { | 591 | { |
602 | u32 temp; | 592 | u32 temp; |
603 | __le32 __iomem *addr; | 593 | struct xhci_port *port; |
604 | 594 | ||
605 | /* xhci only supports test mode for usb2 ports, i.e. xhci->main_hcd */ | 595 | /* xhci only supports test mode for usb2 ports */ |
606 | addr = xhci_get_port_io_addr(xhci->main_hcd, wIndex); | 596 | port = xhci->usb2_rhub.ports[wIndex]; |
607 | temp = readl(addr + PORTPMSC); | 597 | temp = readl(port->addr + PORTPMSC); |
608 | temp |= test_mode << PORT_TEST_MODE_SHIFT; | 598 | temp |= test_mode << PORT_TEST_MODE_SHIFT; |
609 | writel(temp, addr + PORTPMSC); | 599 | writel(temp, port->addr + PORTPMSC); |
610 | xhci->test_mode = test_mode; | 600 | xhci->test_mode = test_mode; |
611 | if (test_mode == TEST_FORCE_EN) | 601 | if (test_mode == TEST_FORCE_EN) |
612 | xhci_start(xhci); | 602 | xhci_start(xhci); |
@@ -633,10 +623,10 @@ static int xhci_enter_test_mode(struct xhci_hcd *xhci, | |||
633 | /* Put all ports to the Disable state by clear PP */ | 623 | /* Put all ports to the Disable state by clear PP */ |
634 | xhci_dbg(xhci, "Disable all port (PP = 0)\n"); | 624 | xhci_dbg(xhci, "Disable all port (PP = 0)\n"); |
635 | /* Power off USB3 ports*/ | 625 | /* Power off USB3 ports*/ |
636 | for (i = 0; i < xhci->num_usb3_ports; i++) | 626 | for (i = 0; i < xhci->usb3_rhub.num_ports; i++) |
637 | xhci_set_port_power(xhci, xhci->shared_hcd, i, false, flags); | 627 | xhci_set_port_power(xhci, xhci->shared_hcd, i, false, flags); |
638 | /* Power off USB2 ports*/ | 628 | /* Power off USB2 ports*/ |
639 | for (i = 0; i < xhci->num_usb2_ports; i++) | 629 | for (i = 0; i < xhci->usb2_rhub.num_ports; i++) |
640 | xhci_set_port_power(xhci, xhci->main_hcd, i, false, flags); | 630 | xhci_set_port_power(xhci, xhci->main_hcd, i, false, flags); |
641 | /* Stop the controller */ | 631 | /* Stop the controller */ |
642 | xhci_dbg(xhci, "Stop controller\n"); | 632 | xhci_dbg(xhci, "Stop controller\n"); |
@@ -672,24 +662,24 @@ static int xhci_exit_test_mode(struct xhci_hcd *xhci) | |||
672 | return xhci_reset(xhci); | 662 | return xhci_reset(xhci); |
673 | } | 663 | } |
674 | 664 | ||
675 | void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array, | 665 | void xhci_set_link_state(struct xhci_hcd *xhci, struct xhci_port *port, |
676 | int port_id, u32 link_state) | 666 | u32 link_state) |
677 | { | 667 | { |
678 | u32 temp; | 668 | u32 temp; |
679 | 669 | ||
680 | temp = readl(port_array[port_id]); | 670 | temp = readl(port->addr); |
681 | temp = xhci_port_state_to_neutral(temp); | 671 | temp = xhci_port_state_to_neutral(temp); |
682 | temp &= ~PORT_PLS_MASK; | 672 | temp &= ~PORT_PLS_MASK; |
683 | temp |= PORT_LINK_STROBE | link_state; | 673 | temp |= PORT_LINK_STROBE | link_state; |
684 | writel(temp, port_array[port_id]); | 674 | writel(temp, port->addr); |
685 | } | 675 | } |
686 | 676 | ||
687 | static void xhci_set_remote_wake_mask(struct xhci_hcd *xhci, | 677 | static void xhci_set_remote_wake_mask(struct xhci_hcd *xhci, |
688 | __le32 __iomem **port_array, int port_id, u16 wake_mask) | 678 | struct xhci_port *port, u16 wake_mask) |
689 | { | 679 | { |
690 | u32 temp; | 680 | u32 temp; |
691 | 681 | ||
692 | temp = readl(port_array[port_id]); | 682 | temp = readl(port->addr); |
693 | temp = xhci_port_state_to_neutral(temp); | 683 | temp = xhci_port_state_to_neutral(temp); |
694 | 684 | ||
695 | if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_CONNECT) | 685 | if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_CONNECT) |
@@ -707,20 +697,20 @@ static void xhci_set_remote_wake_mask(struct xhci_hcd *xhci, | |||
707 | else | 697 | else |
708 | temp &= ~PORT_WKOC_E; | 698 | temp &= ~PORT_WKOC_E; |
709 | 699 | ||
710 | writel(temp, port_array[port_id]); | 700 | writel(temp, port->addr); |
711 | } | 701 | } |
712 | 702 | ||
713 | /* Test and clear port RWC bit */ | 703 | /* Test and clear port RWC bit */ |
714 | void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array, | 704 | void xhci_test_and_clear_bit(struct xhci_hcd *xhci, struct xhci_port *port, |
715 | int port_id, u32 port_bit) | 705 | u32 port_bit) |
716 | { | 706 | { |
717 | u32 temp; | 707 | u32 temp; |
718 | 708 | ||
719 | temp = readl(port_array[port_id]); | 709 | temp = readl(port->addr); |
720 | if (temp & port_bit) { | 710 | if (temp & port_bit) { |
721 | temp = xhci_port_state_to_neutral(temp); | 711 | temp = xhci_port_state_to_neutral(temp); |
722 | temp |= port_bit; | 712 | temp |= port_bit; |
723 | writel(temp, port_array[port_id]); | 713 | writel(temp, port->addr); |
724 | } | 714 | } |
725 | } | 715 | } |
726 | 716 | ||
@@ -794,7 +784,7 @@ static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci, | |||
794 | static void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, | 784 | static void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, |
795 | u16 wIndex) | 785 | u16 wIndex) |
796 | { | 786 | { |
797 | u32 all_ports_seen_u0 = ((1 << xhci->num_usb3_ports)-1); | 787 | u32 all_ports_seen_u0 = ((1 << xhci->usb3_rhub.num_ports) - 1); |
798 | bool port_in_u0 = ((status & PORT_PLS_MASK) == XDEV_U0); | 788 | bool port_in_u0 = ((status & PORT_PLS_MASK) == XDEV_U0); |
799 | 789 | ||
800 | if (!(xhci->quirks & XHCI_COMP_MODE_QUIRK)) | 790 | if (!(xhci->quirks & XHCI_COMP_MODE_QUIRK)) |
@@ -840,8 +830,7 @@ static u32 xhci_get_ext_port_status(u32 raw_port_status, u32 port_li) | |||
840 | */ | 830 | */ |
841 | static u32 xhci_get_port_status(struct usb_hcd *hcd, | 831 | static u32 xhci_get_port_status(struct usb_hcd *hcd, |
842 | struct xhci_bus_state *bus_state, | 832 | struct xhci_bus_state *bus_state, |
843 | __le32 __iomem **port_array, | 833 | u16 wIndex, u32 raw_port_status, |
844 | u16 wIndex, u32 raw_port_status, | ||
845 | unsigned long flags) | 834 | unsigned long flags) |
846 | __releases(&xhci->lock) | 835 | __releases(&xhci->lock) |
847 | __acquires(&xhci->lock) | 836 | __acquires(&xhci->lock) |
@@ -849,6 +838,11 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, | |||
849 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 838 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
850 | u32 status = 0; | 839 | u32 status = 0; |
851 | int slot_id; | 840 | int slot_id; |
841 | struct xhci_hub *rhub; | ||
842 | struct xhci_port *port; | ||
843 | |||
844 | rhub = xhci_get_rhub(hcd); | ||
845 | port = rhub->ports[wIndex]; | ||
852 | 846 | ||
853 | /* wPortChange bits */ | 847 | /* wPortChange bits */ |
854 | if (raw_port_status & PORT_CSC) | 848 | if (raw_port_status & PORT_CSC) |
@@ -919,10 +913,8 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, | |||
919 | 913 | ||
920 | set_bit(wIndex, &bus_state->rexit_ports); | 914 | set_bit(wIndex, &bus_state->rexit_ports); |
921 | 915 | ||
922 | xhci_test_and_clear_bit(xhci, port_array, wIndex, | 916 | xhci_test_and_clear_bit(xhci, port, PORT_PLC); |
923 | PORT_PLC); | 917 | xhci_set_link_state(xhci, port, XDEV_U0); |
924 | xhci_set_link_state(xhci, port_array, wIndex, | ||
925 | XDEV_U0); | ||
926 | 918 | ||
927 | spin_unlock_irqrestore(&xhci->lock, flags); | 919 | spin_unlock_irqrestore(&xhci->lock, flags); |
928 | time_left = wait_for_completion_timeout( | 920 | time_left = wait_for_completion_timeout( |
@@ -940,7 +932,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, | |||
940 | } | 932 | } |
941 | xhci_ring_device(xhci, slot_id); | 933 | xhci_ring_device(xhci, slot_id); |
942 | } else { | 934 | } else { |
943 | int port_status = readl(port_array[wIndex]); | 935 | int port_status = readl(port->addr); |
944 | xhci_warn(xhci, "Port resume took longer than %i msec, port status = 0x%x\n", | 936 | xhci_warn(xhci, "Port resume took longer than %i msec, port status = 0x%x\n", |
945 | XHCI_MAX_REXIT_TIMEOUT, | 937 | XHCI_MAX_REXIT_TIMEOUT, |
946 | port_status); | 938 | port_status); |
@@ -1024,15 +1016,18 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
1024 | unsigned long flags; | 1016 | unsigned long flags; |
1025 | u32 temp, status; | 1017 | u32 temp, status; |
1026 | int retval = 0; | 1018 | int retval = 0; |
1027 | __le32 __iomem **port_array; | ||
1028 | int slot_id; | 1019 | int slot_id; |
1029 | struct xhci_bus_state *bus_state; | 1020 | struct xhci_bus_state *bus_state; |
1030 | u16 link_state = 0; | 1021 | u16 link_state = 0; |
1031 | u16 wake_mask = 0; | 1022 | u16 wake_mask = 0; |
1032 | u16 timeout = 0; | 1023 | u16 timeout = 0; |
1033 | u16 test_mode = 0; | 1024 | u16 test_mode = 0; |
1025 | struct xhci_hub *rhub; | ||
1026 | struct xhci_port **ports; | ||
1034 | 1027 | ||
1035 | max_ports = xhci_get_ports(hcd, &port_array); | 1028 | rhub = xhci_get_rhub(hcd); |
1029 | ports = rhub->ports; | ||
1030 | max_ports = rhub->num_ports; | ||
1036 | bus_state = &xhci->bus_state[hcd_index(hcd)]; | 1031 | bus_state = &xhci->bus_state[hcd_index(hcd)]; |
1037 | 1032 | ||
1038 | spin_lock_irqsave(&xhci->lock, flags); | 1033 | spin_lock_irqsave(&xhci->lock, flags); |
@@ -1070,15 +1065,15 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
1070 | if (!wIndex || wIndex > max_ports) | 1065 | if (!wIndex || wIndex > max_ports) |
1071 | goto error; | 1066 | goto error; |
1072 | wIndex--; | 1067 | wIndex--; |
1073 | temp = readl(port_array[wIndex]); | 1068 | temp = readl(ports[wIndex]->addr); |
1074 | if (temp == ~(u32)0) { | 1069 | if (temp == ~(u32)0) { |
1075 | xhci_hc_died(xhci); | 1070 | xhci_hc_died(xhci); |
1076 | retval = -ENODEV; | 1071 | retval = -ENODEV; |
1077 | break; | 1072 | break; |
1078 | } | 1073 | } |
1079 | trace_xhci_get_port_status(wIndex, temp); | 1074 | trace_xhci_get_port_status(wIndex, temp); |
1080 | status = xhci_get_port_status(hcd, bus_state, port_array, | 1075 | status = xhci_get_port_status(hcd, bus_state, wIndex, temp, |
1081 | wIndex, temp, flags); | 1076 | flags); |
1082 | if (status == 0xffffffff) | 1077 | if (status == 0xffffffff) |
1083 | goto error; | 1078 | goto error; |
1084 | 1079 | ||
@@ -1096,7 +1091,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
1096 | retval = -EINVAL; | 1091 | retval = -EINVAL; |
1097 | break; | 1092 | break; |
1098 | } | 1093 | } |
1099 | port_li = readl(port_array[wIndex] + PORTLI); | 1094 | port_li = readl(ports[wIndex]->addr + PORTLI); |
1100 | status = xhci_get_ext_port_status(temp, port_li); | 1095 | status = xhci_get_ext_port_status(temp, port_li); |
1101 | put_unaligned_le32(cpu_to_le32(status), &buf[4]); | 1096 | put_unaligned_le32(cpu_to_le32(status), &buf[4]); |
1102 | } | 1097 | } |
@@ -1114,7 +1109,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
1114 | if (!wIndex || wIndex > max_ports) | 1109 | if (!wIndex || wIndex > max_ports) |
1115 | goto error; | 1110 | goto error; |
1116 | wIndex--; | 1111 | wIndex--; |
1117 | temp = readl(port_array[wIndex]); | 1112 | temp = readl(ports[wIndex]->addr); |
1118 | if (temp == ~(u32)0) { | 1113 | if (temp == ~(u32)0) { |
1119 | xhci_hc_died(xhci); | 1114 | xhci_hc_died(xhci); |
1120 | retval = -ENODEV; | 1115 | retval = -ENODEV; |
@@ -1124,10 +1119,10 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
1124 | /* FIXME: What new port features do we need to support? */ | 1119 | /* FIXME: What new port features do we need to support? */ |
1125 | switch (wValue) { | 1120 | switch (wValue) { |
1126 | case USB_PORT_FEAT_SUSPEND: | 1121 | case USB_PORT_FEAT_SUSPEND: |
1127 | temp = readl(port_array[wIndex]); | 1122 | temp = readl(ports[wIndex]->addr); |
1128 | if ((temp & PORT_PLS_MASK) != XDEV_U0) { | 1123 | if ((temp & PORT_PLS_MASK) != XDEV_U0) { |
1129 | /* Resume the port to U0 first */ | 1124 | /* Resume the port to U0 first */ |
1130 | xhci_set_link_state(xhci, port_array, wIndex, | 1125 | xhci_set_link_state(xhci, ports[wIndex], |
1131 | XDEV_U0); | 1126 | XDEV_U0); |
1132 | spin_unlock_irqrestore(&xhci->lock, flags); | 1127 | spin_unlock_irqrestore(&xhci->lock, flags); |
1133 | msleep(10); | 1128 | msleep(10); |
@@ -1137,7 +1132,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
1137 | * a port unless the port reports that it is in the | 1132 | * a port unless the port reports that it is in the |
1138 | * enabled (PED = ‘1’,PLS < ‘3’) state. | 1133 | * enabled (PED = ‘1’,PLS < ‘3’) state. |
1139 | */ | 1134 | */ |
1140 | temp = readl(port_array[wIndex]); | 1135 | temp = readl(ports[wIndex]->addr); |
1141 | if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) | 1136 | if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) |
1142 | || (temp & PORT_PLS_MASK) >= XDEV_U3) { | 1137 | || (temp & PORT_PLS_MASK) >= XDEV_U3) { |
1143 | xhci_warn(xhci, "USB core suspending device not in U0/U1/U2.\n"); | 1138 | xhci_warn(xhci, "USB core suspending device not in U0/U1/U2.\n"); |
@@ -1155,18 +1150,17 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
1155 | xhci_stop_device(xhci, slot_id, 1); | 1150 | xhci_stop_device(xhci, slot_id, 1); |
1156 | spin_lock_irqsave(&xhci->lock, flags); | 1151 | spin_lock_irqsave(&xhci->lock, flags); |
1157 | 1152 | ||
1158 | xhci_set_link_state(xhci, port_array, wIndex, XDEV_U3); | 1153 | xhci_set_link_state(xhci, ports[wIndex], XDEV_U3); |
1159 | 1154 | ||
1160 | spin_unlock_irqrestore(&xhci->lock, flags); | 1155 | spin_unlock_irqrestore(&xhci->lock, flags); |
1161 | msleep(10); /* wait device to enter */ | 1156 | msleep(10); /* wait device to enter */ |
1162 | spin_lock_irqsave(&xhci->lock, flags); | 1157 | spin_lock_irqsave(&xhci->lock, flags); |
1163 | 1158 | ||
1164 | temp = readl(port_array[wIndex]); | 1159 | temp = readl(ports[wIndex]->addr); |
1165 | bus_state->suspended_ports |= 1 << wIndex; | 1160 | bus_state->suspended_ports |= 1 << wIndex; |
1166 | break; | 1161 | break; |
1167 | case USB_PORT_FEAT_LINK_STATE: | 1162 | case USB_PORT_FEAT_LINK_STATE: |
1168 | temp = readl(port_array[wIndex]); | 1163 | temp = readl(ports[wIndex]->addr); |
1169 | |||
1170 | /* Disable port */ | 1164 | /* Disable port */ |
1171 | if (link_state == USB_SS_PORT_LS_SS_DISABLED) { | 1165 | if (link_state == USB_SS_PORT_LS_SS_DISABLED) { |
1172 | xhci_dbg(xhci, "Disable port %d\n", wIndex); | 1166 | xhci_dbg(xhci, "Disable port %d\n", wIndex); |
@@ -1178,17 +1172,17 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
1178 | temp |= PORT_CSC | PORT_PEC | PORT_WRC | | 1172 | temp |= PORT_CSC | PORT_PEC | PORT_WRC | |
1179 | PORT_OCC | PORT_RC | PORT_PLC | | 1173 | PORT_OCC | PORT_RC | PORT_PLC | |
1180 | PORT_CEC; | 1174 | PORT_CEC; |
1181 | writel(temp | PORT_PE, port_array[wIndex]); | 1175 | writel(temp | PORT_PE, ports[wIndex]->addr); |
1182 | temp = readl(port_array[wIndex]); | 1176 | temp = readl(ports[wIndex]->addr); |
1183 | break; | 1177 | break; |
1184 | } | 1178 | } |
1185 | 1179 | ||
1186 | /* Put link in RxDetect (enable port) */ | 1180 | /* Put link in RxDetect (enable port) */ |
1187 | if (link_state == USB_SS_PORT_LS_RX_DETECT) { | 1181 | if (link_state == USB_SS_PORT_LS_RX_DETECT) { |
1188 | xhci_dbg(xhci, "Enable port %d\n", wIndex); | 1182 | xhci_dbg(xhci, "Enable port %d\n", wIndex); |
1189 | xhci_set_link_state(xhci, port_array, wIndex, | 1183 | xhci_set_link_state(xhci, ports[wIndex], |
1190 | link_state); | 1184 | link_state); |
1191 | temp = readl(port_array[wIndex]); | 1185 | temp = readl(ports[wIndex]->addr); |
1192 | break; | 1186 | break; |
1193 | } | 1187 | } |
1194 | 1188 | ||
@@ -1219,9 +1213,10 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
1219 | 1213 | ||
1220 | xhci_dbg(xhci, "Enable compliance mode transition for port %d\n", | 1214 | xhci_dbg(xhci, "Enable compliance mode transition for port %d\n", |
1221 | wIndex); | 1215 | wIndex); |
1222 | xhci_set_link_state(xhci, port_array, wIndex, | 1216 | xhci_set_link_state(xhci, ports[wIndex], |
1223 | link_state); | 1217 | link_state); |
1224 | temp = readl(port_array[wIndex]); | 1218 | |
1219 | temp = readl(ports[wIndex]->addr); | ||
1225 | break; | 1220 | break; |
1226 | } | 1221 | } |
1227 | /* Port must be enabled */ | 1222 | /* Port must be enabled */ |
@@ -1248,14 +1243,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
1248 | } | 1243 | } |
1249 | } | 1244 | } |
1250 | 1245 | ||
1251 | xhci_set_link_state(xhci, port_array, wIndex, | 1246 | xhci_set_link_state(xhci, ports[wIndex], link_state); |
1252 | link_state); | ||
1253 | 1247 | ||
1254 | spin_unlock_irqrestore(&xhci->lock, flags); | 1248 | spin_unlock_irqrestore(&xhci->lock, flags); |
1255 | msleep(20); /* wait device to enter */ | 1249 | msleep(20); /* wait device to enter */ |
1256 | spin_lock_irqsave(&xhci->lock, flags); | 1250 | spin_lock_irqsave(&xhci->lock, flags); |
1257 | 1251 | ||
1258 | temp = readl(port_array[wIndex]); | 1252 | temp = readl(ports[wIndex]->addr); |
1259 | if (link_state == USB_SS_PORT_LS_U3) | 1253 | if (link_state == USB_SS_PORT_LS_U3) |
1260 | bus_state->suspended_ports |= 1 << wIndex; | 1254 | bus_state->suspended_ports |= 1 << wIndex; |
1261 | break; | 1255 | break; |
@@ -1270,40 +1264,39 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
1270 | break; | 1264 | break; |
1271 | case USB_PORT_FEAT_RESET: | 1265 | case USB_PORT_FEAT_RESET: |
1272 | temp = (temp | PORT_RESET); | 1266 | temp = (temp | PORT_RESET); |
1273 | writel(temp, port_array[wIndex]); | 1267 | writel(temp, ports[wIndex]->addr); |
1274 | 1268 | ||
1275 | temp = readl(port_array[wIndex]); | 1269 | temp = readl(ports[wIndex]->addr); |
1276 | xhci_dbg(xhci, "set port reset, actual port %d status = 0x%x\n", wIndex, temp); | 1270 | xhci_dbg(xhci, "set port reset, actual port %d status = 0x%x\n", wIndex, temp); |
1277 | break; | 1271 | break; |
1278 | case USB_PORT_FEAT_REMOTE_WAKE_MASK: | 1272 | case USB_PORT_FEAT_REMOTE_WAKE_MASK: |
1279 | xhci_set_remote_wake_mask(xhci, port_array, | 1273 | xhci_set_remote_wake_mask(xhci, ports[wIndex], |
1280 | wIndex, wake_mask); | 1274 | wake_mask); |
1281 | temp = readl(port_array[wIndex]); | 1275 | temp = readl(ports[wIndex]->addr); |
1282 | xhci_dbg(xhci, "set port remote wake mask, " | 1276 | xhci_dbg(xhci, "set port remote wake mask, " |
1283 | "actual port %d status = 0x%x\n", | 1277 | "actual port %d status = 0x%x\n", |
1284 | wIndex, temp); | 1278 | wIndex, temp); |
1285 | break; | 1279 | break; |
1286 | case USB_PORT_FEAT_BH_PORT_RESET: | 1280 | case USB_PORT_FEAT_BH_PORT_RESET: |
1287 | temp |= PORT_WR; | 1281 | temp |= PORT_WR; |
1288 | writel(temp, port_array[wIndex]); | 1282 | writel(temp, ports[wIndex]->addr); |
1289 | 1283 | temp = readl(ports[wIndex]->addr); | |
1290 | temp = readl(port_array[wIndex]); | ||
1291 | break; | 1284 | break; |
1292 | case USB_PORT_FEAT_U1_TIMEOUT: | 1285 | case USB_PORT_FEAT_U1_TIMEOUT: |
1293 | if (hcd->speed < HCD_USB3) | 1286 | if (hcd->speed < HCD_USB3) |
1294 | goto error; | 1287 | goto error; |
1295 | temp = readl(port_array[wIndex] + PORTPMSC); | 1288 | temp = readl(ports[wIndex]->addr + PORTPMSC); |
1296 | temp &= ~PORT_U1_TIMEOUT_MASK; | 1289 | temp &= ~PORT_U1_TIMEOUT_MASK; |
1297 | temp |= PORT_U1_TIMEOUT(timeout); | 1290 | temp |= PORT_U1_TIMEOUT(timeout); |
1298 | writel(temp, port_array[wIndex] + PORTPMSC); | 1291 | writel(temp, ports[wIndex]->addr + PORTPMSC); |
1299 | break; | 1292 | break; |
1300 | case USB_PORT_FEAT_U2_TIMEOUT: | 1293 | case USB_PORT_FEAT_U2_TIMEOUT: |
1301 | if (hcd->speed < HCD_USB3) | 1294 | if (hcd->speed < HCD_USB3) |
1302 | goto error; | 1295 | goto error; |
1303 | temp = readl(port_array[wIndex] + PORTPMSC); | 1296 | temp = readl(ports[wIndex]->addr + PORTPMSC); |
1304 | temp &= ~PORT_U2_TIMEOUT_MASK; | 1297 | temp &= ~PORT_U2_TIMEOUT_MASK; |
1305 | temp |= PORT_U2_TIMEOUT(timeout); | 1298 | temp |= PORT_U2_TIMEOUT(timeout); |
1306 | writel(temp, port_array[wIndex] + PORTPMSC); | 1299 | writel(temp, ports[wIndex]->addr + PORTPMSC); |
1307 | break; | 1300 | break; |
1308 | case USB_PORT_FEAT_TEST: | 1301 | case USB_PORT_FEAT_TEST: |
1309 | /* 4.19.6 Port Test Modes (USB2 Test Mode) */ | 1302 | /* 4.19.6 Port Test Modes (USB2 Test Mode) */ |
@@ -1318,13 +1311,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
1318 | goto error; | 1311 | goto error; |
1319 | } | 1312 | } |
1320 | /* unblock any posted writes */ | 1313 | /* unblock any posted writes */ |
1321 | temp = readl(port_array[wIndex]); | 1314 | temp = readl(ports[wIndex]->addr); |
1322 | break; | 1315 | break; |
1323 | case ClearPortFeature: | 1316 | case ClearPortFeature: |
1324 | if (!wIndex || wIndex > max_ports) | 1317 | if (!wIndex || wIndex > max_ports) |
1325 | goto error; | 1318 | goto error; |
1326 | wIndex--; | 1319 | wIndex--; |
1327 | temp = readl(port_array[wIndex]); | 1320 | temp = readl(ports[wIndex]->addr); |
1328 | if (temp == ~(u32)0) { | 1321 | if (temp == ~(u32)0) { |
1329 | xhci_hc_died(xhci); | 1322 | xhci_hc_died(xhci); |
1330 | retval = -ENODEV; | 1323 | retval = -ENODEV; |
@@ -1334,7 +1327,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
1334 | temp = xhci_port_state_to_neutral(temp); | 1327 | temp = xhci_port_state_to_neutral(temp); |
1335 | switch (wValue) { | 1328 | switch (wValue) { |
1336 | case USB_PORT_FEAT_SUSPEND: | 1329 | case USB_PORT_FEAT_SUSPEND: |
1337 | temp = readl(port_array[wIndex]); | 1330 | temp = readl(ports[wIndex]->addr); |
1338 | xhci_dbg(xhci, "clear USB_PORT_FEAT_SUSPEND\n"); | 1331 | xhci_dbg(xhci, "clear USB_PORT_FEAT_SUSPEND\n"); |
1339 | xhci_dbg(xhci, "PORTSC %04x\n", temp); | 1332 | xhci_dbg(xhci, "PORTSC %04x\n", temp); |
1340 | if (temp & PORT_RESET) | 1333 | if (temp & PORT_RESET) |
@@ -1344,12 +1337,12 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
1344 | goto error; | 1337 | goto error; |
1345 | 1338 | ||
1346 | set_bit(wIndex, &bus_state->resuming_ports); | 1339 | set_bit(wIndex, &bus_state->resuming_ports); |
1347 | xhci_set_link_state(xhci, port_array, wIndex, | 1340 | xhci_set_link_state(xhci, ports[wIndex], |
1348 | XDEV_RESUME); | 1341 | XDEV_RESUME); |
1349 | spin_unlock_irqrestore(&xhci->lock, flags); | 1342 | spin_unlock_irqrestore(&xhci->lock, flags); |
1350 | msleep(USB_RESUME_TIMEOUT); | 1343 | msleep(USB_RESUME_TIMEOUT); |
1351 | spin_lock_irqsave(&xhci->lock, flags); | 1344 | spin_lock_irqsave(&xhci->lock, flags); |
1352 | xhci_set_link_state(xhci, port_array, wIndex, | 1345 | xhci_set_link_state(xhci, ports[wIndex], |
1353 | XDEV_U0); | 1346 | XDEV_U0); |
1354 | clear_bit(wIndex, &bus_state->resuming_ports); | 1347 | clear_bit(wIndex, &bus_state->resuming_ports); |
1355 | } | 1348 | } |
@@ -1374,11 +1367,11 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
1374 | case USB_PORT_FEAT_C_PORT_LINK_STATE: | 1367 | case USB_PORT_FEAT_C_PORT_LINK_STATE: |
1375 | case USB_PORT_FEAT_C_PORT_CONFIG_ERROR: | 1368 | case USB_PORT_FEAT_C_PORT_CONFIG_ERROR: |
1376 | xhci_clear_port_change_bit(xhci, wValue, wIndex, | 1369 | xhci_clear_port_change_bit(xhci, wValue, wIndex, |
1377 | port_array[wIndex], temp); | 1370 | ports[wIndex]->addr, temp); |
1378 | break; | 1371 | break; |
1379 | case USB_PORT_FEAT_ENABLE: | 1372 | case USB_PORT_FEAT_ENABLE: |
1380 | xhci_disable_port(hcd, xhci, wIndex, | 1373 | xhci_disable_port(hcd, xhci, wIndex, |
1381 | port_array[wIndex], temp); | 1374 | ports[wIndex]->addr, temp); |
1382 | break; | 1375 | break; |
1383 | case USB_PORT_FEAT_POWER: | 1376 | case USB_PORT_FEAT_POWER: |
1384 | xhci_set_port_power(xhci, hcd, wIndex, false, &flags); | 1377 | xhci_set_port_power(xhci, hcd, wIndex, false, &flags); |
@@ -1415,11 +1408,14 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
1415 | int i, retval; | 1408 | int i, retval; |
1416 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 1409 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
1417 | int max_ports; | 1410 | int max_ports; |
1418 | __le32 __iomem **port_array; | ||
1419 | struct xhci_bus_state *bus_state; | 1411 | struct xhci_bus_state *bus_state; |
1420 | bool reset_change = false; | 1412 | bool reset_change = false; |
1413 | struct xhci_hub *rhub; | ||
1414 | struct xhci_port **ports; | ||
1421 | 1415 | ||
1422 | max_ports = xhci_get_ports(hcd, &port_array); | 1416 | rhub = xhci_get_rhub(hcd); |
1417 | ports = rhub->ports; | ||
1418 | max_ports = rhub->num_ports; | ||
1423 | bus_state = &xhci->bus_state[hcd_index(hcd)]; | 1419 | bus_state = &xhci->bus_state[hcd_index(hcd)]; |
1424 | 1420 | ||
1425 | /* Initial status is no changes */ | 1421 | /* Initial status is no changes */ |
@@ -1437,7 +1433,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
1437 | spin_lock_irqsave(&xhci->lock, flags); | 1433 | spin_lock_irqsave(&xhci->lock, flags); |
1438 | /* For each port, did anything change? If so, set that bit in buf. */ | 1434 | /* For each port, did anything change? If so, set that bit in buf. */ |
1439 | for (i = 0; i < max_ports; i++) { | 1435 | for (i = 0; i < max_ports; i++) { |
1440 | temp = readl(port_array[i]); | 1436 | temp = readl(ports[i]->addr); |
1441 | if (temp == ~(u32)0) { | 1437 | if (temp == ~(u32)0) { |
1442 | xhci_hc_died(xhci); | 1438 | xhci_hc_died(xhci); |
1443 | retval = -ENODEV; | 1439 | retval = -ENODEV; |
@@ -1469,11 +1465,14 @@ int xhci_bus_suspend(struct usb_hcd *hcd) | |||
1469 | { | 1465 | { |
1470 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 1466 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
1471 | int max_ports, port_index; | 1467 | int max_ports, port_index; |
1472 | __le32 __iomem **port_array; | ||
1473 | struct xhci_bus_state *bus_state; | 1468 | struct xhci_bus_state *bus_state; |
1474 | unsigned long flags; | 1469 | unsigned long flags; |
1470 | struct xhci_hub *rhub; | ||
1471 | struct xhci_port **ports; | ||
1475 | 1472 | ||
1476 | max_ports = xhci_get_ports(hcd, &port_array); | 1473 | rhub = xhci_get_rhub(hcd); |
1474 | ports = rhub->ports; | ||
1475 | max_ports = rhub->num_ports; | ||
1477 | bus_state = &xhci->bus_state[hcd_index(hcd)]; | 1476 | bus_state = &xhci->bus_state[hcd_index(hcd)]; |
1478 | 1477 | ||
1479 | spin_lock_irqsave(&xhci->lock, flags); | 1478 | spin_lock_irqsave(&xhci->lock, flags); |
@@ -1494,7 +1493,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd) | |||
1494 | u32 t1, t2; | 1493 | u32 t1, t2; |
1495 | int slot_id; | 1494 | int slot_id; |
1496 | 1495 | ||
1497 | t1 = readl(port_array[port_index]); | 1496 | t1 = readl(ports[port_index]->addr); |
1498 | t2 = xhci_port_state_to_neutral(t1); | 1497 | t2 = xhci_port_state_to_neutral(t1); |
1499 | 1498 | ||
1500 | if ((t1 & PORT_PE) && !(t1 & PORT_PLS_MASK)) { | 1499 | if ((t1 & PORT_PE) && !(t1 & PORT_PLS_MASK)) { |
@@ -1534,7 +1533,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd) | |||
1534 | 1533 | ||
1535 | t1 = xhci_port_state_to_neutral(t1); | 1534 | t1 = xhci_port_state_to_neutral(t1); |
1536 | if (t1 != t2) | 1535 | if (t1 != t2) |
1537 | writel(t2, port_array[port_index]); | 1536 | writel(t2, ports[port_index]->addr); |
1538 | } | 1537 | } |
1539 | hcd->state = HC_STATE_SUSPENDED; | 1538 | hcd->state = HC_STATE_SUSPENDED; |
1540 | bus_state->next_statechange = jiffies + msecs_to_jiffies(10); | 1539 | bus_state->next_statechange = jiffies + msecs_to_jiffies(10); |
@@ -1547,12 +1546,11 @@ int xhci_bus_suspend(struct usb_hcd *hcd) | |||
1547 | * warm reset a USB3 device stuck in polling or compliance mode after resume. | 1546 | * warm reset a USB3 device stuck in polling or compliance mode after resume. |
1548 | * See Intel 100/c230 series PCH specification update Doc #332692-006 Errata #8 | 1547 | * See Intel 100/c230 series PCH specification update Doc #332692-006 Errata #8 |
1549 | */ | 1548 | */ |
1550 | static bool xhci_port_missing_cas_quirk(int port_index, | 1549 | static bool xhci_port_missing_cas_quirk(struct xhci_port *port) |
1551 | __le32 __iomem **port_array) | ||
1552 | { | 1550 | { |
1553 | u32 portsc; | 1551 | u32 portsc; |
1554 | 1552 | ||
1555 | portsc = readl(port_array[port_index]); | 1553 | portsc = readl(port->addr); |
1556 | 1554 | ||
1557 | /* if any of these are set we are not stuck */ | 1555 | /* if any of these are set we are not stuck */ |
1558 | if (portsc & (PORT_CONNECT | PORT_CAS)) | 1556 | if (portsc & (PORT_CONNECT | PORT_CAS)) |
@@ -1565,9 +1563,9 @@ static bool xhci_port_missing_cas_quirk(int port_index, | |||
1565 | /* clear wakeup/change bits, and do a warm port reset */ | 1563 | /* clear wakeup/change bits, and do a warm port reset */ |
1566 | portsc &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS); | 1564 | portsc &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS); |
1567 | portsc |= PORT_WR; | 1565 | portsc |= PORT_WR; |
1568 | writel(portsc, port_array[port_index]); | 1566 | writel(portsc, port->addr); |
1569 | /* flush write */ | 1567 | /* flush write */ |
1570 | readl(port_array[port_index]); | 1568 | readl(port->addr); |
1571 | return true; | 1569 | return true; |
1572 | } | 1570 | } |
1573 | 1571 | ||
@@ -1575,15 +1573,18 @@ int xhci_bus_resume(struct usb_hcd *hcd) | |||
1575 | { | 1573 | { |
1576 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 1574 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
1577 | struct xhci_bus_state *bus_state; | 1575 | struct xhci_bus_state *bus_state; |
1578 | __le32 __iomem **port_array; | ||
1579 | unsigned long flags; | 1576 | unsigned long flags; |
1580 | int max_ports, port_index; | 1577 | int max_ports, port_index; |
1581 | int slot_id; | 1578 | int slot_id; |
1582 | int sret; | 1579 | int sret; |
1583 | u32 next_state; | 1580 | u32 next_state; |
1584 | u32 temp, portsc; | 1581 | u32 temp, portsc; |
1582 | struct xhci_hub *rhub; | ||
1583 | struct xhci_port **ports; | ||
1585 | 1584 | ||
1586 | max_ports = xhci_get_ports(hcd, &port_array); | 1585 | rhub = xhci_get_rhub(hcd); |
1586 | ports = rhub->ports; | ||
1587 | max_ports = rhub->num_ports; | ||
1587 | bus_state = &xhci->bus_state[hcd_index(hcd)]; | 1588 | bus_state = &xhci->bus_state[hcd_index(hcd)]; |
1588 | 1589 | ||
1589 | if (time_before(jiffies, bus_state->next_statechange)) | 1590 | if (time_before(jiffies, bus_state->next_statechange)) |
@@ -1608,12 +1609,12 @@ int xhci_bus_resume(struct usb_hcd *hcd) | |||
1608 | 1609 | ||
1609 | port_index = max_ports; | 1610 | port_index = max_ports; |
1610 | while (port_index--) { | 1611 | while (port_index--) { |
1611 | portsc = readl(port_array[port_index]); | 1612 | portsc = readl(ports[port_index]->addr); |
1612 | 1613 | ||
1613 | /* warm reset CAS limited ports stuck in polling/compliance */ | 1614 | /* warm reset CAS limited ports stuck in polling/compliance */ |
1614 | if ((xhci->quirks & XHCI_MISSING_CAS) && | 1615 | if ((xhci->quirks & XHCI_MISSING_CAS) && |
1615 | (hcd->speed >= HCD_USB3) && | 1616 | (hcd->speed >= HCD_USB3) && |
1616 | xhci_port_missing_cas_quirk(port_index, port_array)) { | 1617 | xhci_port_missing_cas_quirk(ports[port_index])) { |
1617 | xhci_dbg(xhci, "reset stuck port %d\n", port_index); | 1618 | xhci_dbg(xhci, "reset stuck port %d\n", port_index); |
1618 | clear_bit(port_index, &bus_state->bus_suspended); | 1619 | clear_bit(port_index, &bus_state->bus_suspended); |
1619 | continue; | 1620 | continue; |
@@ -1637,7 +1638,7 @@ int xhci_bus_resume(struct usb_hcd *hcd) | |||
1637 | } | 1638 | } |
1638 | /* disable wake for all ports, write new link state if needed */ | 1639 | /* disable wake for all ports, write new link state if needed */ |
1639 | portsc &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS); | 1640 | portsc &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS); |
1640 | writel(portsc, port_array[port_index]); | 1641 | writel(portsc, ports[port_index]->addr); |
1641 | } | 1642 | } |
1642 | 1643 | ||
1643 | /* USB2 specific resume signaling delay and U0 link state transition */ | 1644 | /* USB2 specific resume signaling delay and U0 link state transition */ |
@@ -1650,23 +1651,22 @@ int xhci_bus_resume(struct usb_hcd *hcd) | |||
1650 | for_each_set_bit(port_index, &bus_state->bus_suspended, | 1651 | for_each_set_bit(port_index, &bus_state->bus_suspended, |
1651 | BITS_PER_LONG) { | 1652 | BITS_PER_LONG) { |
1652 | /* Clear PLC to poll it later for U0 transition */ | 1653 | /* Clear PLC to poll it later for U0 transition */ |
1653 | xhci_test_and_clear_bit(xhci, port_array, port_index, | 1654 | xhci_test_and_clear_bit(xhci, ports[port_index], |
1654 | PORT_PLC); | 1655 | PORT_PLC); |
1655 | xhci_set_link_state(xhci, port_array, port_index, | 1656 | xhci_set_link_state(xhci, ports[port_index], XDEV_U0); |
1656 | XDEV_U0); | ||
1657 | } | 1657 | } |
1658 | } | 1658 | } |
1659 | 1659 | ||
1660 | /* poll for U0 link state complete, both USB2 and USB3 */ | 1660 | /* poll for U0 link state complete, both USB2 and USB3 */ |
1661 | for_each_set_bit(port_index, &bus_state->bus_suspended, BITS_PER_LONG) { | 1661 | for_each_set_bit(port_index, &bus_state->bus_suspended, BITS_PER_LONG) { |
1662 | sret = xhci_handshake(port_array[port_index], PORT_PLC, | 1662 | sret = xhci_handshake(ports[port_index]->addr, PORT_PLC, |
1663 | PORT_PLC, 10 * 1000); | 1663 | PORT_PLC, 10 * 1000); |
1664 | if (sret) { | 1664 | if (sret) { |
1665 | xhci_warn(xhci, "port %d resume PLC timeout\n", | 1665 | xhci_warn(xhci, "port %d resume PLC timeout\n", |
1666 | port_index); | 1666 | port_index); |
1667 | continue; | 1667 | continue; |
1668 | } | 1668 | } |
1669 | xhci_test_and_clear_bit(xhci, port_array, port_index, PORT_PLC); | 1669 | xhci_test_and_clear_bit(xhci, ports[port_index], PORT_PLC); |
1670 | slot_id = xhci_find_slot_id_by_port(hcd, xhci, port_index + 1); | 1670 | slot_id = xhci_find_slot_id_by_port(hcd, xhci, port_index + 1); |
1671 | if (slot_id) | 1671 | if (slot_id) |
1672 | xhci_ring_device(xhci, slot_id); | 1672 | xhci_ring_device(xhci, slot_id); |
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index e5ace8995b3b..4fe74711938e 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c | |||
@@ -33,8 +33,9 @@ static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci, | |||
33 | struct xhci_segment *seg; | 33 | struct xhci_segment *seg; |
34 | dma_addr_t dma; | 34 | dma_addr_t dma; |
35 | int i; | 35 | int i; |
36 | struct device *dev = xhci_to_hcd(xhci)->self.sysdev; | ||
36 | 37 | ||
37 | seg = kzalloc(sizeof *seg, flags); | 38 | seg = kzalloc_node(sizeof(*seg), flags, dev_to_node(dev)); |
38 | if (!seg) | 39 | if (!seg) |
39 | return NULL; | 40 | return NULL; |
40 | 41 | ||
@@ -45,7 +46,8 @@ static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci, | |||
45 | } | 46 | } |
46 | 47 | ||
47 | if (max_packet) { | 48 | if (max_packet) { |
48 | seg->bounce_buf = kzalloc(max_packet, flags); | 49 | seg->bounce_buf = kzalloc_node(max_packet, flags, |
50 | dev_to_node(dev)); | ||
49 | if (!seg->bounce_buf) { | 51 | if (!seg->bounce_buf) { |
50 | dma_pool_free(xhci->segment_pool, seg->trbs, dma); | 52 | dma_pool_free(xhci->segment_pool, seg->trbs, dma); |
51 | kfree(seg); | 53 | kfree(seg); |
@@ -363,8 +365,9 @@ struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci, | |||
363 | { | 365 | { |
364 | struct xhci_ring *ring; | 366 | struct xhci_ring *ring; |
365 | int ret; | 367 | int ret; |
368 | struct device *dev = xhci_to_hcd(xhci)->self.sysdev; | ||
366 | 369 | ||
367 | ring = kzalloc(sizeof *(ring), flags); | 370 | ring = kzalloc_node(sizeof(*ring), flags, dev_to_node(dev)); |
368 | if (!ring) | 371 | if (!ring) |
369 | return NULL; | 372 | return NULL; |
370 | 373 | ||
@@ -458,11 +461,12 @@ struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci, | |||
458 | int type, gfp_t flags) | 461 | int type, gfp_t flags) |
459 | { | 462 | { |
460 | struct xhci_container_ctx *ctx; | 463 | struct xhci_container_ctx *ctx; |
464 | struct device *dev = xhci_to_hcd(xhci)->self.sysdev; | ||
461 | 465 | ||
462 | if ((type != XHCI_CTX_TYPE_DEVICE) && (type != XHCI_CTX_TYPE_INPUT)) | 466 | if ((type != XHCI_CTX_TYPE_DEVICE) && (type != XHCI_CTX_TYPE_INPUT)) |
463 | return NULL; | 467 | return NULL; |
464 | 468 | ||
465 | ctx = kzalloc(sizeof(*ctx), flags); | 469 | ctx = kzalloc_node(sizeof(*ctx), flags, dev_to_node(dev)); |
466 | if (!ctx) | 470 | if (!ctx) |
467 | return NULL; | 471 | return NULL; |
468 | 472 | ||
@@ -615,6 +619,7 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci, | |||
615 | struct xhci_ring *cur_ring; | 619 | struct xhci_ring *cur_ring; |
616 | u64 addr; | 620 | u64 addr; |
617 | int ret; | 621 | int ret; |
622 | struct device *dev = xhci_to_hcd(xhci)->self.sysdev; | ||
618 | 623 | ||
619 | xhci_dbg(xhci, "Allocating %u streams and %u " | 624 | xhci_dbg(xhci, "Allocating %u streams and %u " |
620 | "stream context array entries.\n", | 625 | "stream context array entries.\n", |
@@ -625,7 +630,8 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci, | |||
625 | } | 630 | } |
626 | xhci->cmd_ring_reserved_trbs++; | 631 | xhci->cmd_ring_reserved_trbs++; |
627 | 632 | ||
628 | stream_info = kzalloc(sizeof(struct xhci_stream_info), mem_flags); | 633 | stream_info = kzalloc_node(sizeof(*stream_info), mem_flags, |
634 | dev_to_node(dev)); | ||
629 | if (!stream_info) | 635 | if (!stream_info) |
630 | goto cleanup_trbs; | 636 | goto cleanup_trbs; |
631 | 637 | ||
@@ -633,9 +639,9 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci, | |||
633 | stream_info->num_stream_ctxs = num_stream_ctxs; | 639 | stream_info->num_stream_ctxs = num_stream_ctxs; |
634 | 640 | ||
635 | /* Initialize the array of virtual pointers to stream rings. */ | 641 | /* Initialize the array of virtual pointers to stream rings. */ |
636 | stream_info->stream_rings = kzalloc( | 642 | stream_info->stream_rings = kcalloc_node( |
637 | sizeof(struct xhci_ring *)*num_streams, | 643 | num_streams, sizeof(struct xhci_ring *), mem_flags, |
638 | mem_flags); | 644 | dev_to_node(dev)); |
639 | if (!stream_info->stream_rings) | 645 | if (!stream_info->stream_rings) |
640 | goto cleanup_info; | 646 | goto cleanup_info; |
641 | 647 | ||
@@ -831,6 +837,7 @@ int xhci_alloc_tt_info(struct xhci_hcd *xhci, | |||
831 | struct xhci_tt_bw_info *tt_info; | 837 | struct xhci_tt_bw_info *tt_info; |
832 | unsigned int num_ports; | 838 | unsigned int num_ports; |
833 | int i, j; | 839 | int i, j; |
840 | struct device *dev = xhci_to_hcd(xhci)->self.sysdev; | ||
834 | 841 | ||
835 | if (!tt->multi) | 842 | if (!tt->multi) |
836 | num_ports = 1; | 843 | num_ports = 1; |
@@ -840,7 +847,8 @@ int xhci_alloc_tt_info(struct xhci_hcd *xhci, | |||
840 | for (i = 0; i < num_ports; i++, tt_info++) { | 847 | for (i = 0; i < num_ports; i++, tt_info++) { |
841 | struct xhci_interval_bw_table *bw_table; | 848 | struct xhci_interval_bw_table *bw_table; |
842 | 849 | ||
843 | tt_info = kzalloc(sizeof(*tt_info), mem_flags); | 850 | tt_info = kzalloc_node(sizeof(*tt_info), mem_flags, |
851 | dev_to_node(dev)); | ||
844 | if (!tt_info) | 852 | if (!tt_info) |
845 | goto free_tts; | 853 | goto free_tts; |
846 | INIT_LIST_HEAD(&tt_info->tt_list); | 854 | INIT_LIST_HEAD(&tt_info->tt_list); |
@@ -1054,8 +1062,7 @@ void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci, | |||
1054 | 1062 | ||
1055 | /* | 1063 | /* |
1056 | * The xHCI roothub may have ports of differing speeds in any order in the port | 1064 | * The xHCI roothub may have ports of differing speeds in any order in the port |
1057 | * status registers. xhci->port_array provides an array of the port speed for | 1065 | * status registers. |
1058 | * each offset into the port status registers. | ||
1059 | * | 1066 | * |
1060 | * The xHCI hardware wants to know the roothub port number that the USB device | 1067 | * The xHCI hardware wants to know the roothub port number that the USB device |
1061 | * is attached to (or the roothub port its ancestor hub is attached to). All we | 1068 | * is attached to (or the roothub port its ancestor hub is attached to). All we |
@@ -1642,7 +1649,8 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) | |||
1642 | if (!num_sp) | 1649 | if (!num_sp) |
1643 | return 0; | 1650 | return 0; |
1644 | 1651 | ||
1645 | xhci->scratchpad = kzalloc(sizeof(*xhci->scratchpad), flags); | 1652 | xhci->scratchpad = kzalloc_node(sizeof(*xhci->scratchpad), flags, |
1653 | dev_to_node(dev)); | ||
1646 | if (!xhci->scratchpad) | 1654 | if (!xhci->scratchpad) |
1647 | goto fail_sp; | 1655 | goto fail_sp; |
1648 | 1656 | ||
@@ -1652,7 +1660,8 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) | |||
1652 | if (!xhci->scratchpad->sp_array) | 1660 | if (!xhci->scratchpad->sp_array) |
1653 | goto fail_sp2; | 1661 | goto fail_sp2; |
1654 | 1662 | ||
1655 | xhci->scratchpad->sp_buffers = kzalloc(sizeof(void *) * num_sp, flags); | 1663 | xhci->scratchpad->sp_buffers = kcalloc_node(num_sp, sizeof(void *), |
1664 | flags, dev_to_node(dev)); | ||
1656 | if (!xhci->scratchpad->sp_buffers) | 1665 | if (!xhci->scratchpad->sp_buffers) |
1657 | goto fail_sp3; | 1666 | goto fail_sp3; |
1658 | 1667 | ||
@@ -1720,14 +1729,16 @@ struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci, | |||
1720 | bool allocate_completion, gfp_t mem_flags) | 1729 | bool allocate_completion, gfp_t mem_flags) |
1721 | { | 1730 | { |
1722 | struct xhci_command *command; | 1731 | struct xhci_command *command; |
1732 | struct device *dev = xhci_to_hcd(xhci)->self.sysdev; | ||
1723 | 1733 | ||
1724 | command = kzalloc(sizeof(*command), mem_flags); | 1734 | command = kzalloc_node(sizeof(*command), mem_flags, dev_to_node(dev)); |
1725 | if (!command) | 1735 | if (!command) |
1726 | return NULL; | 1736 | return NULL; |
1727 | 1737 | ||
1728 | if (allocate_completion) { | 1738 | if (allocate_completion) { |
1729 | command->completion = | 1739 | command->completion = |
1730 | kzalloc(sizeof(struct completion), mem_flags); | 1740 | kzalloc_node(sizeof(struct completion), mem_flags, |
1741 | dev_to_node(dev)); | ||
1731 | if (!command->completion) { | 1742 | if (!command->completion) { |
1732 | kfree(command); | 1743 | kfree(command); |
1733 | return NULL; | 1744 | return NULL; |
@@ -1890,18 +1901,18 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) | |||
1890 | 1901 | ||
1891 | no_bw: | 1902 | no_bw: |
1892 | xhci->cmd_ring_reserved_trbs = 0; | 1903 | xhci->cmd_ring_reserved_trbs = 0; |
1893 | xhci->num_usb2_ports = 0; | 1904 | xhci->usb2_rhub.num_ports = 0; |
1894 | xhci->num_usb3_ports = 0; | 1905 | xhci->usb3_rhub.num_ports = 0; |
1895 | xhci->num_active_eps = 0; | 1906 | xhci->num_active_eps = 0; |
1896 | kfree(xhci->usb2_ports); | 1907 | kfree(xhci->usb2_rhub.ports); |
1897 | kfree(xhci->usb3_ports); | 1908 | kfree(xhci->usb3_rhub.ports); |
1898 | kfree(xhci->port_array); | 1909 | kfree(xhci->hw_ports); |
1899 | kfree(xhci->rh_bw); | 1910 | kfree(xhci->rh_bw); |
1900 | kfree(xhci->ext_caps); | 1911 | kfree(xhci->ext_caps); |
1901 | 1912 | ||
1902 | xhci->usb2_ports = NULL; | 1913 | xhci->usb2_rhub.ports = NULL; |
1903 | xhci->usb3_ports = NULL; | 1914 | xhci->usb3_rhub.ports = NULL; |
1904 | xhci->port_array = NULL; | 1915 | xhci->hw_ports = NULL; |
1905 | xhci->rh_bw = NULL; | 1916 | xhci->rh_bw = NULL; |
1906 | xhci->ext_caps = NULL; | 1917 | xhci->ext_caps = NULL; |
1907 | 1918 | ||
@@ -2100,6 +2111,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, | |||
2100 | int i; | 2111 | int i; |
2101 | u8 major_revision, minor_revision; | 2112 | u8 major_revision, minor_revision; |
2102 | struct xhci_hub *rhub; | 2113 | struct xhci_hub *rhub; |
2114 | struct device *dev = xhci_to_hcd(xhci)->self.sysdev; | ||
2103 | 2115 | ||
2104 | temp = readl(addr); | 2116 | temp = readl(addr); |
2105 | major_revision = XHCI_EXT_PORT_MAJOR(temp); | 2117 | major_revision = XHCI_EXT_PORT_MAJOR(temp); |
@@ -2136,8 +2148,8 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, | |||
2136 | 2148 | ||
2137 | rhub->psi_count = XHCI_EXT_PORT_PSIC(temp); | 2149 | rhub->psi_count = XHCI_EXT_PORT_PSIC(temp); |
2138 | if (rhub->psi_count) { | 2150 | if (rhub->psi_count) { |
2139 | rhub->psi = kcalloc(rhub->psi_count, sizeof(*rhub->psi), | 2151 | rhub->psi = kcalloc_node(rhub->psi_count, sizeof(*rhub->psi), |
2140 | GFP_KERNEL); | 2152 | GFP_KERNEL, dev_to_node(dev)); |
2141 | if (!rhub->psi) | 2153 | if (!rhub->psi) |
2142 | rhub->psi_count = 0; | 2154 | rhub->psi_count = 0; |
2143 | 2155 | ||
@@ -2186,36 +2198,53 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, | |||
2186 | 2198 | ||
2187 | port_offset--; | 2199 | port_offset--; |
2188 | for (i = port_offset; i < (port_offset + port_count); i++) { | 2200 | for (i = port_offset; i < (port_offset + port_count); i++) { |
2201 | struct xhci_port *hw_port = &xhci->hw_ports[i]; | ||
2189 | /* Duplicate entry. Ignore the port if the revisions differ. */ | 2202 | /* Duplicate entry. Ignore the port if the revisions differ. */ |
2190 | if (xhci->port_array[i] != 0) { | 2203 | if (hw_port->rhub) { |
2191 | xhci_warn(xhci, "Duplicate port entry, Ext Cap %p," | 2204 | xhci_warn(xhci, "Duplicate port entry, Ext Cap %p," |
2192 | " port %u\n", addr, i); | 2205 | " port %u\n", addr, i); |
2193 | xhci_warn(xhci, "Port was marked as USB %u, " | 2206 | xhci_warn(xhci, "Port was marked as USB %u, " |
2194 | "duplicated as USB %u\n", | 2207 | "duplicated as USB %u\n", |
2195 | xhci->port_array[i], major_revision); | 2208 | hw_port->rhub->maj_rev, major_revision); |
2196 | /* Only adjust the roothub port counts if we haven't | 2209 | /* Only adjust the roothub port counts if we haven't |
2197 | * found a similar duplicate. | 2210 | * found a similar duplicate. |
2198 | */ | 2211 | */ |
2199 | if (xhci->port_array[i] != major_revision && | 2212 | if (hw_port->rhub != rhub && |
2200 | xhci->port_array[i] != DUPLICATE_ENTRY) { | 2213 | hw_port->hcd_portnum != DUPLICATE_ENTRY) { |
2201 | if (xhci->port_array[i] == 0x03) | 2214 | hw_port->rhub->num_ports--; |
2202 | xhci->num_usb3_ports--; | 2215 | hw_port->hcd_portnum = DUPLICATE_ENTRY; |
2203 | else | ||
2204 | xhci->num_usb2_ports--; | ||
2205 | xhci->port_array[i] = DUPLICATE_ENTRY; | ||
2206 | } | 2216 | } |
2207 | /* FIXME: Should we disable the port? */ | ||
2208 | continue; | 2217 | continue; |
2209 | } | 2218 | } |
2210 | xhci->port_array[i] = major_revision; | 2219 | hw_port->rhub = rhub; |
2211 | if (major_revision == 0x03) | 2220 | rhub->num_ports++; |
2212 | xhci->num_usb3_ports++; | ||
2213 | else | ||
2214 | xhci->num_usb2_ports++; | ||
2215 | } | 2221 | } |
2216 | /* FIXME: Should we disable ports not in the Extended Capabilities? */ | 2222 | /* FIXME: Should we disable ports not in the Extended Capabilities? */ |
2217 | } | 2223 | } |
2218 | 2224 | ||
2225 | static void xhci_create_rhub_port_array(struct xhci_hcd *xhci, | ||
2226 | struct xhci_hub *rhub, gfp_t flags) | ||
2227 | { | ||
2228 | int port_index = 0; | ||
2229 | int i; | ||
2230 | struct device *dev = xhci_to_hcd(xhci)->self.sysdev; | ||
2231 | |||
2232 | if (!rhub->num_ports) | ||
2233 | return; | ||
2234 | rhub->ports = kcalloc_node(rhub->num_ports, sizeof(rhub->ports), flags, | ||
2235 | dev_to_node(dev)); | ||
2236 | for (i = 0; i < HCS_MAX_PORTS(xhci->hcs_params1); i++) { | ||
2237 | if (xhci->hw_ports[i].rhub != rhub || | ||
2238 | xhci->hw_ports[i].hcd_portnum == DUPLICATE_ENTRY) | ||
2239 | continue; | ||
2240 | xhci->hw_ports[i].hcd_portnum = port_index; | ||
2241 | rhub->ports[port_index] = &xhci->hw_ports[i]; | ||
2242 | port_index++; | ||
2243 | if (port_index == rhub->num_ports) | ||
2244 | break; | ||
2245 | } | ||
2246 | } | ||
2247 | |||
2219 | /* | 2248 | /* |
2220 | * Scan the Extended Capabilities for the "Supported Protocol Capabilities" that | 2249 | * Scan the Extended Capabilities for the "Supported Protocol Capabilities" that |
2221 | * specify what speeds each port is supposed to be. We can't count on the port | 2250 | * specify what speeds each port is supposed to be. We can't count on the port |
@@ -2228,16 +2257,25 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) | |||
2228 | void __iomem *base; | 2257 | void __iomem *base; |
2229 | u32 offset; | 2258 | u32 offset; |
2230 | unsigned int num_ports; | 2259 | unsigned int num_ports; |
2231 | int i, j, port_index; | 2260 | int i, j; |
2232 | int cap_count = 0; | 2261 | int cap_count = 0; |
2233 | u32 cap_start; | 2262 | u32 cap_start; |
2263 | struct device *dev = xhci_to_hcd(xhci)->self.sysdev; | ||
2234 | 2264 | ||
2235 | num_ports = HCS_MAX_PORTS(xhci->hcs_params1); | 2265 | num_ports = HCS_MAX_PORTS(xhci->hcs_params1); |
2236 | xhci->port_array = kzalloc(sizeof(*xhci->port_array)*num_ports, flags); | 2266 | xhci->hw_ports = kcalloc_node(num_ports, sizeof(*xhci->hw_ports), |
2237 | if (!xhci->port_array) | 2267 | flags, dev_to_node(dev)); |
2268 | if (!xhci->hw_ports) | ||
2238 | return -ENOMEM; | 2269 | return -ENOMEM; |
2239 | 2270 | ||
2240 | xhci->rh_bw = kzalloc(sizeof(*xhci->rh_bw)*num_ports, flags); | 2271 | for (i = 0; i < num_ports; i++) { |
2272 | xhci->hw_ports[i].addr = &xhci->op_regs->port_status_base + | ||
2273 | NUM_PORT_REGS * i; | ||
2274 | xhci->hw_ports[i].hw_portnum = i; | ||
2275 | } | ||
2276 | |||
2277 | xhci->rh_bw = kzalloc_node(sizeof(*xhci->rh_bw)*num_ports, flags, | ||
2278 | dev_to_node(dev)); | ||
2241 | if (!xhci->rh_bw) | 2279 | if (!xhci->rh_bw) |
2242 | return -ENOMEM; | 2280 | return -ENOMEM; |
2243 | for (i = 0; i < num_ports; i++) { | 2281 | for (i = 0; i < num_ports; i++) { |
@@ -2264,7 +2302,8 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) | |||
2264 | XHCI_EXT_CAPS_PROTOCOL); | 2302 | XHCI_EXT_CAPS_PROTOCOL); |
2265 | } | 2303 | } |
2266 | 2304 | ||
2267 | xhci->ext_caps = kzalloc(sizeof(*xhci->ext_caps) * cap_count, flags); | 2305 | xhci->ext_caps = kcalloc_node(cap_count, sizeof(*xhci->ext_caps), |
2306 | flags, dev_to_node(dev)); | ||
2268 | if (!xhci->ext_caps) | 2307 | if (!xhci->ext_caps) |
2269 | return -ENOMEM; | 2308 | return -ENOMEM; |
2270 | 2309 | ||
@@ -2272,86 +2311,44 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) | |||
2272 | 2311 | ||
2273 | while (offset) { | 2312 | while (offset) { |
2274 | xhci_add_in_port(xhci, num_ports, base + offset, cap_count); | 2313 | xhci_add_in_port(xhci, num_ports, base + offset, cap_count); |
2275 | if (xhci->num_usb2_ports + xhci->num_usb3_ports == num_ports) | 2314 | if (xhci->usb2_rhub.num_ports + xhci->usb3_rhub.num_ports == |
2315 | num_ports) | ||
2276 | break; | 2316 | break; |
2277 | offset = xhci_find_next_ext_cap(base, offset, | 2317 | offset = xhci_find_next_ext_cap(base, offset, |
2278 | XHCI_EXT_CAPS_PROTOCOL); | 2318 | XHCI_EXT_CAPS_PROTOCOL); |
2279 | } | 2319 | } |
2280 | 2320 | if (xhci->usb2_rhub.num_ports == 0 && xhci->usb3_rhub.num_ports == 0) { | |
2281 | if (xhci->num_usb2_ports == 0 && xhci->num_usb3_ports == 0) { | ||
2282 | xhci_warn(xhci, "No ports on the roothubs?\n"); | 2321 | xhci_warn(xhci, "No ports on the roothubs?\n"); |
2283 | return -ENODEV; | 2322 | return -ENODEV; |
2284 | } | 2323 | } |
2285 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, | 2324 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, |
2286 | "Found %u USB 2.0 ports and %u USB 3.0 ports.", | 2325 | "Found %u USB 2.0 ports and %u USB 3.0 ports.", |
2287 | xhci->num_usb2_ports, xhci->num_usb3_ports); | 2326 | xhci->usb2_rhub.num_ports, xhci->usb3_rhub.num_ports); |
2288 | 2327 | ||
2289 | /* Place limits on the number of roothub ports so that the hub | 2328 | /* Place limits on the number of roothub ports so that the hub |
2290 | * descriptors aren't longer than the USB core will allocate. | 2329 | * descriptors aren't longer than the USB core will allocate. |
2291 | */ | 2330 | */ |
2292 | if (xhci->num_usb3_ports > USB_SS_MAXPORTS) { | 2331 | if (xhci->usb3_rhub.num_ports > USB_SS_MAXPORTS) { |
2293 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, | 2332 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, |
2294 | "Limiting USB 3.0 roothub ports to %u.", | 2333 | "Limiting USB 3.0 roothub ports to %u.", |
2295 | USB_SS_MAXPORTS); | 2334 | USB_SS_MAXPORTS); |
2296 | xhci->num_usb3_ports = USB_SS_MAXPORTS; | 2335 | xhci->usb3_rhub.num_ports = USB_SS_MAXPORTS; |
2297 | } | 2336 | } |
2298 | if (xhci->num_usb2_ports > USB_MAXCHILDREN) { | 2337 | if (xhci->usb2_rhub.num_ports > USB_MAXCHILDREN) { |
2299 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, | 2338 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, |
2300 | "Limiting USB 2.0 roothub ports to %u.", | 2339 | "Limiting USB 2.0 roothub ports to %u.", |
2301 | USB_MAXCHILDREN); | 2340 | USB_MAXCHILDREN); |
2302 | xhci->num_usb2_ports = USB_MAXCHILDREN; | 2341 | xhci->usb2_rhub.num_ports = USB_MAXCHILDREN; |
2303 | } | 2342 | } |
2304 | 2343 | ||
2305 | /* | 2344 | /* |
2306 | * Note we could have all USB 3.0 ports, or all USB 2.0 ports. | 2345 | * Note we could have all USB 3.0 ports, or all USB 2.0 ports. |
2307 | * Not sure how the USB core will handle a hub with no ports... | 2346 | * Not sure how the USB core will handle a hub with no ports... |
2308 | */ | 2347 | */ |
2309 | if (xhci->num_usb2_ports) { | ||
2310 | xhci->usb2_ports = kmalloc(sizeof(*xhci->usb2_ports)* | ||
2311 | xhci->num_usb2_ports, flags); | ||
2312 | if (!xhci->usb2_ports) | ||
2313 | return -ENOMEM; | ||
2314 | |||
2315 | port_index = 0; | ||
2316 | for (i = 0; i < num_ports; i++) { | ||
2317 | if (xhci->port_array[i] == 0x03 || | ||
2318 | xhci->port_array[i] == 0 || | ||
2319 | xhci->port_array[i] == DUPLICATE_ENTRY) | ||
2320 | continue; | ||
2321 | 2348 | ||
2322 | xhci->usb2_ports[port_index] = | 2349 | xhci_create_rhub_port_array(xhci, &xhci->usb2_rhub, flags); |
2323 | &xhci->op_regs->port_status_base + | 2350 | xhci_create_rhub_port_array(xhci, &xhci->usb3_rhub, flags); |
2324 | NUM_PORT_REGS*i; | ||
2325 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, | ||
2326 | "USB 2.0 port at index %u, " | ||
2327 | "addr = %p", i, | ||
2328 | xhci->usb2_ports[port_index]); | ||
2329 | port_index++; | ||
2330 | if (port_index == xhci->num_usb2_ports) | ||
2331 | break; | ||
2332 | } | ||
2333 | } | ||
2334 | if (xhci->num_usb3_ports) { | ||
2335 | xhci->usb3_ports = kmalloc(sizeof(*xhci->usb3_ports)* | ||
2336 | xhci->num_usb3_ports, flags); | ||
2337 | if (!xhci->usb3_ports) | ||
2338 | return -ENOMEM; | ||
2339 | 2351 | ||
2340 | port_index = 0; | ||
2341 | for (i = 0; i < num_ports; i++) | ||
2342 | if (xhci->port_array[i] == 0x03) { | ||
2343 | xhci->usb3_ports[port_index] = | ||
2344 | &xhci->op_regs->port_status_base + | ||
2345 | NUM_PORT_REGS*i; | ||
2346 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, | ||
2347 | "USB 3.0 port at index %u, " | ||
2348 | "addr = %p", i, | ||
2349 | xhci->usb3_ports[port_index]); | ||
2350 | port_index++; | ||
2351 | if (port_index == xhci->num_usb3_ports) | ||
2352 | break; | ||
2353 | } | ||
2354 | } | ||
2355 | return 0; | 2352 | return 0; |
2356 | } | 2353 | } |
2357 | 2354 | ||
diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c index eea7360a18fc..fa33d6e5b1cb 100644 --- a/drivers/usb/host/xhci-mtk-sch.c +++ b/drivers/usb/host/xhci-mtk-sch.c | |||
@@ -58,7 +58,7 @@ static int get_bw_index(struct xhci_hcd *xhci, struct usb_device *udev, | |||
58 | bw_index = (virt_dev->real_port - 1) * 2 + 1; | 58 | bw_index = (virt_dev->real_port - 1) * 2 + 1; |
59 | } else { | 59 | } else { |
60 | /* add one more for each SS port */ | 60 | /* add one more for each SS port */ |
61 | bw_index = virt_dev->real_port + xhci->num_usb3_ports - 1; | 61 | bw_index = virt_dev->real_port + xhci->usb3_rhub.num_ports - 1; |
62 | } | 62 | } |
63 | 63 | ||
64 | return bw_index; | 64 | return bw_index; |
@@ -284,7 +284,7 @@ int xhci_mtk_sch_init(struct xhci_hcd_mtk *mtk) | |||
284 | int i; | 284 | int i; |
285 | 285 | ||
286 | /* ss IN and OUT are separated */ | 286 | /* ss IN and OUT are separated */ |
287 | num_usb_bus = xhci->num_usb3_ports * 2 + xhci->num_usb2_ports; | 287 | num_usb_bus = xhci->usb3_rhub.num_ports * 2 + xhci->usb2_rhub.num_ports; |
288 | 288 | ||
289 | sch_array = kcalloc(num_usb_bus, sizeof(*sch_array), GFP_KERNEL); | 289 | sch_array = kcalloc(num_usb_bus, sizeof(*sch_array), GFP_KERNEL); |
290 | if (sch_array == NULL) | 290 | if (sch_array == NULL) |
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 85ffda85f8ab..6372edf339d9 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c | |||
@@ -196,11 +196,15 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) | |||
196 | xhci->quirks |= XHCI_BROKEN_STREAMS; | 196 | xhci->quirks |= XHCI_BROKEN_STREAMS; |
197 | } | 197 | } |
198 | if (pdev->vendor == PCI_VENDOR_ID_RENESAS && | 198 | if (pdev->vendor == PCI_VENDOR_ID_RENESAS && |
199 | pdev->device == 0x0014) | 199 | pdev->device == 0x0014) { |
200 | xhci->quirks |= XHCI_TRUST_TX_LENGTH; | 200 | xhci->quirks |= XHCI_TRUST_TX_LENGTH; |
201 | xhci->quirks |= XHCI_ZERO_64B_REGS; | ||
202 | } | ||
201 | if (pdev->vendor == PCI_VENDOR_ID_RENESAS && | 203 | if (pdev->vendor == PCI_VENDOR_ID_RENESAS && |
202 | pdev->device == 0x0015) | 204 | pdev->device == 0x0015) { |
203 | xhci->quirks |= XHCI_RESET_ON_RESUME; | 205 | xhci->quirks |= XHCI_RESET_ON_RESUME; |
206 | xhci->quirks |= XHCI_ZERO_64B_REGS; | ||
207 | } | ||
204 | if (pdev->vendor == PCI_VENDOR_ID_VIA) | 208 | if (pdev->vendor == PCI_VENDOR_ID_VIA) |
205 | xhci->quirks |= XHCI_RESET_ON_RESUME; | 209 | xhci->quirks |= XHCI_RESET_ON_RESUME; |
206 | 210 | ||
@@ -284,13 +288,6 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
284 | 288 | ||
285 | driver = (struct hc_driver *)id->driver_data; | 289 | driver = (struct hc_driver *)id->driver_data; |
286 | 290 | ||
287 | /* For some HW implementation, a XHCI reset is just not enough... */ | ||
288 | if (usb_xhci_needs_pci_reset(dev)) { | ||
289 | dev_info(&dev->dev, "Resetting\n"); | ||
290 | if (pci_reset_function_locked(dev)) | ||
291 | dev_warn(&dev->dev, "Reset failed"); | ||
292 | } | ||
293 | |||
294 | /* Prevent runtime suspending between USB-2 and USB-3 initialization */ | 291 | /* Prevent runtime suspending between USB-2 and USB-3 initialization */ |
295 | pm_runtime_get_noresume(&dev->dev); | 292 | pm_runtime_get_noresume(&dev->dev); |
296 | 293 | ||
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 91a1a824673d..f0a99aa0ac58 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
@@ -1497,44 +1497,6 @@ static void handle_vendor_event(struct xhci_hcd *xhci, | |||
1497 | handle_cmd_completion(xhci, &event->event_cmd); | 1497 | handle_cmd_completion(xhci, &event->event_cmd); |
1498 | } | 1498 | } |
1499 | 1499 | ||
1500 | /* @port_id: the one-based port ID from the hardware (indexed from array of all | ||
1501 | * port registers -- USB 3.0 and USB 2.0). | ||
1502 | * | ||
1503 | * Returns a zero-based port number, which is suitable for indexing into each of | ||
1504 | * the split roothubs' port arrays and bus state arrays. | ||
1505 | * Add one to it in order to call xhci_find_slot_id_by_port. | ||
1506 | */ | ||
1507 | static unsigned int find_faked_portnum_from_hw_portnum(struct usb_hcd *hcd, | ||
1508 | struct xhci_hcd *xhci, u32 port_id) | ||
1509 | { | ||
1510 | unsigned int i; | ||
1511 | unsigned int num_similar_speed_ports = 0; | ||
1512 | |||
1513 | /* port_id from the hardware is 1-based, but port_array[], usb3_ports[], | ||
1514 | * and usb2_ports are 0-based indexes. Count the number of similar | ||
1515 | * speed ports, up to 1 port before this port. | ||
1516 | */ | ||
1517 | for (i = 0; i < (port_id - 1); i++) { | ||
1518 | u8 port_speed = xhci->port_array[i]; | ||
1519 | |||
1520 | /* | ||
1521 | * Skip ports that don't have known speeds, or have duplicate | ||
1522 | * Extended Capabilities port speed entries. | ||
1523 | */ | ||
1524 | if (port_speed == 0 || port_speed == DUPLICATE_ENTRY) | ||
1525 | continue; | ||
1526 | |||
1527 | /* | ||
1528 | * USB 3.0 ports are always under a USB 3.0 hub. USB 2.0 and | ||
1529 | * 1.1 ports are under the USB 2.0 hub. If the port speed | ||
1530 | * matches the device speed, it's a similar speed port. | ||
1531 | */ | ||
1532 | if ((port_speed == 0x03) == (hcd->speed >= HCD_USB3)) | ||
1533 | num_similar_speed_ports++; | ||
1534 | } | ||
1535 | return num_similar_speed_ports; | ||
1536 | } | ||
1537 | |||
1538 | static void handle_device_notification(struct xhci_hcd *xhci, | 1500 | static void handle_device_notification(struct xhci_hcd *xhci, |
1539 | union xhci_trb *event) | 1501 | union xhci_trb *event) |
1540 | { | 1502 | { |
@@ -1563,11 +1525,10 @@ static void handle_port_status(struct xhci_hcd *xhci, | |||
1563 | u32 portsc, cmd_reg; | 1525 | u32 portsc, cmd_reg; |
1564 | int max_ports; | 1526 | int max_ports; |
1565 | int slot_id; | 1527 | int slot_id; |
1566 | unsigned int faked_port_index; | 1528 | unsigned int hcd_portnum; |
1567 | u8 major_revision; | ||
1568 | struct xhci_bus_state *bus_state; | 1529 | struct xhci_bus_state *bus_state; |
1569 | __le32 __iomem **port_array; | ||
1570 | bool bogus_port_status = false; | 1530 | bool bogus_port_status = false; |
1531 | struct xhci_port *port; | ||
1571 | 1532 | ||
1572 | /* Port status change events always have a successful completion code */ | 1533 | /* Port status change events always have a successful completion code */ |
1573 | if (GET_COMP_CODE(le32_to_cpu(event->generic.field[2])) != COMP_SUCCESS) | 1534 | if (GET_COMP_CODE(le32_to_cpu(event->generic.field[2])) != COMP_SUCCESS) |
@@ -1584,49 +1545,19 @@ static void handle_port_status(struct xhci_hcd *xhci, | |||
1584 | return; | 1545 | return; |
1585 | } | 1546 | } |
1586 | 1547 | ||
1587 | /* Figure out which usb_hcd this port is attached to: | 1548 | port = &xhci->hw_ports[port_id - 1]; |
1588 | * is it a USB 3.0 port or a USB 2.0/1.1 port? | 1549 | if (!port || !port->rhub || port->hcd_portnum == DUPLICATE_ENTRY) { |
1589 | */ | 1550 | xhci_warn(xhci, "Event for invalid port %u\n", port_id); |
1590 | major_revision = xhci->port_array[port_id - 1]; | ||
1591 | |||
1592 | /* Find the right roothub. */ | ||
1593 | hcd = xhci_to_hcd(xhci); | ||
1594 | if ((major_revision == 0x03) != (hcd->speed >= HCD_USB3)) | ||
1595 | hcd = xhci->shared_hcd; | ||
1596 | |||
1597 | if (major_revision == 0) { | ||
1598 | xhci_warn(xhci, "Event for port %u not in " | ||
1599 | "Extended Capabilities, ignoring.\n", | ||
1600 | port_id); | ||
1601 | bogus_port_status = true; | ||
1602 | goto cleanup; | ||
1603 | } | ||
1604 | if (major_revision == DUPLICATE_ENTRY) { | ||
1605 | xhci_warn(xhci, "Event for port %u duplicated in" | ||
1606 | "Extended Capabilities, ignoring.\n", | ||
1607 | port_id); | ||
1608 | bogus_port_status = true; | 1551 | bogus_port_status = true; |
1609 | goto cleanup; | 1552 | goto cleanup; |
1610 | } | 1553 | } |
1611 | 1554 | ||
1612 | /* | 1555 | hcd = port->rhub->hcd; |
1613 | * Hardware port IDs reported by a Port Status Change Event include USB | ||
1614 | * 3.0 and USB 2.0 ports. We want to check if the port has reported a | ||
1615 | * resume event, but we first need to translate the hardware port ID | ||
1616 | * into the index into the ports on the correct split roothub, and the | ||
1617 | * correct bus_state structure. | ||
1618 | */ | ||
1619 | bus_state = &xhci->bus_state[hcd_index(hcd)]; | 1556 | bus_state = &xhci->bus_state[hcd_index(hcd)]; |
1620 | if (hcd->speed >= HCD_USB3) | 1557 | hcd_portnum = port->hcd_portnum; |
1621 | port_array = xhci->usb3_ports; | 1558 | portsc = readl(port->addr); |
1622 | else | ||
1623 | port_array = xhci->usb2_ports; | ||
1624 | /* Find the faked port hub number */ | ||
1625 | faked_port_index = find_faked_portnum_from_hw_portnum(hcd, xhci, | ||
1626 | port_id); | ||
1627 | portsc = readl(port_array[faked_port_index]); | ||
1628 | 1559 | ||
1629 | trace_xhci_handle_port_status(faked_port_index, portsc); | 1560 | trace_xhci_handle_port_status(hcd_portnum, portsc); |
1630 | 1561 | ||
1631 | if (hcd->state == HC_STATE_SUSPENDED) { | 1562 | if (hcd->state == HC_STATE_SUSPENDED) { |
1632 | xhci_dbg(xhci, "resume root hub\n"); | 1563 | xhci_dbg(xhci, "resume root hub\n"); |
@@ -1634,7 +1565,7 @@ static void handle_port_status(struct xhci_hcd *xhci, | |||
1634 | } | 1565 | } |
1635 | 1566 | ||
1636 | if (hcd->speed >= HCD_USB3 && (portsc & PORT_PLS_MASK) == XDEV_INACTIVE) | 1567 | if (hcd->speed >= HCD_USB3 && (portsc & PORT_PLS_MASK) == XDEV_INACTIVE) |
1637 | bus_state->port_remote_wakeup &= ~(1 << faked_port_index); | 1568 | bus_state->port_remote_wakeup &= ~(1 << hcd_portnum); |
1638 | 1569 | ||
1639 | if ((portsc & PORT_PLC) && (portsc & PORT_PLS_MASK) == XDEV_RESUME) { | 1570 | if ((portsc & PORT_PLC) && (portsc & PORT_PLS_MASK) == XDEV_RESUME) { |
1640 | xhci_dbg(xhci, "port resume event for port %d\n", port_id); | 1571 | xhci_dbg(xhci, "port resume event for port %d\n", port_id); |
@@ -1651,29 +1582,26 @@ static void handle_port_status(struct xhci_hcd *xhci, | |||
1651 | * so we can tell the difference between the end of | 1582 | * so we can tell the difference between the end of |
1652 | * device and host initiated resume. | 1583 | * device and host initiated resume. |
1653 | */ | 1584 | */ |
1654 | bus_state->port_remote_wakeup |= 1 << faked_port_index; | 1585 | bus_state->port_remote_wakeup |= 1 << hcd_portnum; |
1655 | xhci_test_and_clear_bit(xhci, port_array, | 1586 | xhci_test_and_clear_bit(xhci, port, PORT_PLC); |
1656 | faked_port_index, PORT_PLC); | 1587 | xhci_set_link_state(xhci, port, XDEV_U0); |
1657 | xhci_set_link_state(xhci, port_array, faked_port_index, | ||
1658 | XDEV_U0); | ||
1659 | /* Need to wait until the next link state change | 1588 | /* Need to wait until the next link state change |
1660 | * indicates the device is actually in U0. | 1589 | * indicates the device is actually in U0. |
1661 | */ | 1590 | */ |
1662 | bogus_port_status = true; | 1591 | bogus_port_status = true; |
1663 | goto cleanup; | 1592 | goto cleanup; |
1664 | } else if (!test_bit(faked_port_index, | 1593 | } else if (!test_bit(hcd_portnum, &bus_state->resuming_ports)) { |
1665 | &bus_state->resuming_ports)) { | ||
1666 | xhci_dbg(xhci, "resume HS port %d\n", port_id); | 1594 | xhci_dbg(xhci, "resume HS port %d\n", port_id); |
1667 | bus_state->resume_done[faked_port_index] = jiffies + | 1595 | bus_state->resume_done[hcd_portnum] = jiffies + |
1668 | msecs_to_jiffies(USB_RESUME_TIMEOUT); | 1596 | msecs_to_jiffies(USB_RESUME_TIMEOUT); |
1669 | set_bit(faked_port_index, &bus_state->resuming_ports); | 1597 | set_bit(hcd_portnum, &bus_state->resuming_ports); |
1670 | /* Do the rest in GetPortStatus after resume time delay. | 1598 | /* Do the rest in GetPortStatus after resume time delay. |
1671 | * Avoid polling roothub status before that so that a | 1599 | * Avoid polling roothub status before that so that a |
1672 | * usb device auto-resume latency around ~40ms. | 1600 | * usb device auto-resume latency around ~40ms. |
1673 | */ | 1601 | */ |
1674 | set_bit(HCD_FLAG_POLL_RH, &hcd->flags); | 1602 | set_bit(HCD_FLAG_POLL_RH, &hcd->flags); |
1675 | mod_timer(&hcd->rh_timer, | 1603 | mod_timer(&hcd->rh_timer, |
1676 | bus_state->resume_done[faked_port_index]); | 1604 | bus_state->resume_done[hcd_portnum]); |
1677 | bogus_port_status = true; | 1605 | bogus_port_status = true; |
1678 | } | 1606 | } |
1679 | } | 1607 | } |
@@ -1688,17 +1616,14 @@ static void handle_port_status(struct xhci_hcd *xhci, | |||
1688 | * so the roothub behavior is consistent with external | 1616 | * so the roothub behavior is consistent with external |
1689 | * USB 3.0 hub behavior. | 1617 | * USB 3.0 hub behavior. |
1690 | */ | 1618 | */ |
1691 | slot_id = xhci_find_slot_id_by_port(hcd, xhci, | 1619 | slot_id = xhci_find_slot_id_by_port(hcd, xhci, hcd_portnum + 1); |
1692 | faked_port_index + 1); | ||
1693 | if (slot_id && xhci->devs[slot_id]) | 1620 | if (slot_id && xhci->devs[slot_id]) |
1694 | xhci_ring_device(xhci, slot_id); | 1621 | xhci_ring_device(xhci, slot_id); |
1695 | if (bus_state->port_remote_wakeup & (1 << faked_port_index)) { | 1622 | if (bus_state->port_remote_wakeup & (1 << hcd_portnum)) { |
1696 | bus_state->port_remote_wakeup &= | 1623 | bus_state->port_remote_wakeup &= ~(1 << hcd_portnum); |
1697 | ~(1 << faked_port_index); | 1624 | xhci_test_and_clear_bit(xhci, port, PORT_PLC); |
1698 | xhci_test_and_clear_bit(xhci, port_array, | ||
1699 | faked_port_index, PORT_PLC); | ||
1700 | usb_wakeup_notification(hcd->self.root_hub, | 1625 | usb_wakeup_notification(hcd->self.root_hub, |
1701 | faked_port_index + 1); | 1626 | hcd_portnum + 1); |
1702 | bogus_port_status = true; | 1627 | bogus_port_status = true; |
1703 | goto cleanup; | 1628 | goto cleanup; |
1704 | } | 1629 | } |
@@ -1710,16 +1635,15 @@ static void handle_port_status(struct xhci_hcd *xhci, | |||
1710 | * out of the RExit state. | 1635 | * out of the RExit state. |
1711 | */ | 1636 | */ |
1712 | if (!DEV_SUPERSPEED_ANY(portsc) && | 1637 | if (!DEV_SUPERSPEED_ANY(portsc) && |
1713 | test_and_clear_bit(faked_port_index, | 1638 | test_and_clear_bit(hcd_portnum, |
1714 | &bus_state->rexit_ports)) { | 1639 | &bus_state->rexit_ports)) { |
1715 | complete(&bus_state->rexit_done[faked_port_index]); | 1640 | complete(&bus_state->rexit_done[hcd_portnum]); |
1716 | bogus_port_status = true; | 1641 | bogus_port_status = true; |
1717 | goto cleanup; | 1642 | goto cleanup; |
1718 | } | 1643 | } |
1719 | 1644 | ||
1720 | if (hcd->speed < HCD_USB3) | 1645 | if (hcd->speed < HCD_USB3) |
1721 | xhci_test_and_clear_bit(xhci, port_array, faked_port_index, | 1646 | xhci_test_and_clear_bit(xhci, port, PORT_PLC); |
1722 | PORT_PLC); | ||
1723 | 1647 | ||
1724 | cleanup: | 1648 | cleanup: |
1725 | /* Update event ring dequeue pointer before dropping the lock */ | 1649 | /* Update event ring dequeue pointer before dropping the lock */ |
diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c index 2c076ea80522..a8c1d073cba0 100644 --- a/drivers/usb/host/xhci-tegra.c +++ b/drivers/usb/host/xhci-tegra.c | |||
@@ -18,9 +18,11 @@ | |||
18 | #include <linux/phy/tegra/xusb.h> | 18 | #include <linux/phy/tegra/xusb.h> |
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/pm.h> | 20 | #include <linux/pm.h> |
21 | #include <linux/pm_runtime.h> | ||
21 | #include <linux/regulator/consumer.h> | 22 | #include <linux/regulator/consumer.h> |
22 | #include <linux/reset.h> | 23 | #include <linux/reset.h> |
23 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <soc/tegra/pmc.h> | ||
24 | 26 | ||
25 | #include "xhci.h" | 27 | #include "xhci.h" |
26 | 28 | ||
@@ -761,6 +763,49 @@ static void tegra_xusb_phy_disable(struct tegra_xusb *tegra) | |||
761 | } | 763 | } |
762 | } | 764 | } |
763 | 765 | ||
766 | static int tegra_xusb_runtime_suspend(struct device *dev) | ||
767 | { | ||
768 | struct tegra_xusb *tegra = dev_get_drvdata(dev); | ||
769 | |||
770 | tegra_xusb_phy_disable(tegra); | ||
771 | regulator_bulk_disable(tegra->soc->num_supplies, tegra->supplies); | ||
772 | tegra_xusb_clk_disable(tegra); | ||
773 | |||
774 | return 0; | ||
775 | } | ||
776 | |||
777 | static int tegra_xusb_runtime_resume(struct device *dev) | ||
778 | { | ||
779 | struct tegra_xusb *tegra = dev_get_drvdata(dev); | ||
780 | int err; | ||
781 | |||
782 | err = tegra_xusb_clk_enable(tegra); | ||
783 | if (err) { | ||
784 | dev_err(dev, "failed to enable clocks: %d\n", err); | ||
785 | return err; | ||
786 | } | ||
787 | |||
788 | err = regulator_bulk_enable(tegra->soc->num_supplies, tegra->supplies); | ||
789 | if (err) { | ||
790 | dev_err(dev, "failed to enable regulators: %d\n", err); | ||
791 | goto disable_clk; | ||
792 | } | ||
793 | |||
794 | err = tegra_xusb_phy_enable(tegra); | ||
795 | if (err < 0) { | ||
796 | dev_err(dev, "failed to enable PHYs: %d\n", err); | ||
797 | goto disable_regulator; | ||
798 | } | ||
799 | |||
800 | return 0; | ||
801 | |||
802 | disable_regulator: | ||
803 | regulator_bulk_disable(tegra->soc->num_supplies, tegra->supplies); | ||
804 | disable_clk: | ||
805 | tegra_xusb_clk_disable(tegra); | ||
806 | return err; | ||
807 | } | ||
808 | |||
764 | static int tegra_xusb_load_firmware(struct tegra_xusb *tegra) | 809 | static int tegra_xusb_load_firmware(struct tegra_xusb *tegra) |
765 | { | 810 | { |
766 | unsigned int code_tag_blocks, code_size_blocks, code_blocks; | 811 | unsigned int code_tag_blocks, code_size_blocks, code_blocks; |
@@ -930,20 +975,6 @@ static int tegra_xusb_probe(struct platform_device *pdev) | |||
930 | if (IS_ERR(tegra->padctl)) | 975 | if (IS_ERR(tegra->padctl)) |
931 | return PTR_ERR(tegra->padctl); | 976 | return PTR_ERR(tegra->padctl); |
932 | 977 | ||
933 | tegra->host_rst = devm_reset_control_get(&pdev->dev, "xusb_host"); | ||
934 | if (IS_ERR(tegra->host_rst)) { | ||
935 | err = PTR_ERR(tegra->host_rst); | ||
936 | dev_err(&pdev->dev, "failed to get xusb_host reset: %d\n", err); | ||
937 | goto put_padctl; | ||
938 | } | ||
939 | |||
940 | tegra->ss_rst = devm_reset_control_get(&pdev->dev, "xusb_ss"); | ||
941 | if (IS_ERR(tegra->ss_rst)) { | ||
942 | err = PTR_ERR(tegra->ss_rst); | ||
943 | dev_err(&pdev->dev, "failed to get xusb_ss reset: %d\n", err); | ||
944 | goto put_padctl; | ||
945 | } | ||
946 | |||
947 | tegra->host_clk = devm_clk_get(&pdev->dev, "xusb_host"); | 978 | tegra->host_clk = devm_clk_get(&pdev->dev, "xusb_host"); |
948 | if (IS_ERR(tegra->host_clk)) { | 979 | if (IS_ERR(tegra->host_clk)) { |
949 | err = PTR_ERR(tegra->host_clk); | 980 | err = PTR_ERR(tegra->host_clk); |
@@ -1007,11 +1038,48 @@ static int tegra_xusb_probe(struct platform_device *pdev) | |||
1007 | goto put_padctl; | 1038 | goto put_padctl; |
1008 | } | 1039 | } |
1009 | 1040 | ||
1041 | if (!pdev->dev.pm_domain) { | ||
1042 | tegra->host_rst = devm_reset_control_get(&pdev->dev, | ||
1043 | "xusb_host"); | ||
1044 | if (IS_ERR(tegra->host_rst)) { | ||
1045 | err = PTR_ERR(tegra->host_rst); | ||
1046 | dev_err(&pdev->dev, | ||
1047 | "failed to get xusb_host reset: %d\n", err); | ||
1048 | goto put_padctl; | ||
1049 | } | ||
1050 | |||
1051 | tegra->ss_rst = devm_reset_control_get(&pdev->dev, "xusb_ss"); | ||
1052 | if (IS_ERR(tegra->ss_rst)) { | ||
1053 | err = PTR_ERR(tegra->ss_rst); | ||
1054 | dev_err(&pdev->dev, "failed to get xusb_ss reset: %d\n", | ||
1055 | err); | ||
1056 | goto put_padctl; | ||
1057 | } | ||
1058 | |||
1059 | err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_XUSBA, | ||
1060 | tegra->ss_clk, | ||
1061 | tegra->ss_rst); | ||
1062 | if (err) { | ||
1063 | dev_err(&pdev->dev, | ||
1064 | "failed to enable XUSBA domain: %d\n", err); | ||
1065 | goto put_padctl; | ||
1066 | } | ||
1067 | |||
1068 | err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_XUSBC, | ||
1069 | tegra->host_clk, | ||
1070 | tegra->host_rst); | ||
1071 | if (err) { | ||
1072 | dev_err(&pdev->dev, | ||
1073 | "failed to enable XUSBC domain: %d\n", err); | ||
1074 | goto disable_xusba; | ||
1075 | } | ||
1076 | } | ||
1077 | |||
1010 | tegra->supplies = devm_kcalloc(&pdev->dev, tegra->soc->num_supplies, | 1078 | tegra->supplies = devm_kcalloc(&pdev->dev, tegra->soc->num_supplies, |
1011 | sizeof(*tegra->supplies), GFP_KERNEL); | 1079 | sizeof(*tegra->supplies), GFP_KERNEL); |
1012 | if (!tegra->supplies) { | 1080 | if (!tegra->supplies) { |
1013 | err = -ENOMEM; | 1081 | err = -ENOMEM; |
1014 | goto put_padctl; | 1082 | goto disable_xusbc; |
1015 | } | 1083 | } |
1016 | 1084 | ||
1017 | for (i = 0; i < tegra->soc->num_supplies; i++) | 1085 | for (i = 0; i < tegra->soc->num_supplies; i++) |
@@ -1021,7 +1089,7 @@ static int tegra_xusb_probe(struct platform_device *pdev) | |||
1021 | tegra->supplies); | 1089 | tegra->supplies); |
1022 | if (err) { | 1090 | if (err) { |
1023 | dev_err(&pdev->dev, "failed to get regulators: %d\n", err); | 1091 | dev_err(&pdev->dev, "failed to get regulators: %d\n", err); |
1024 | goto put_padctl; | 1092 | goto disable_xusbc; |
1025 | } | 1093 | } |
1026 | 1094 | ||
1027 | for (i = 0; i < tegra->soc->num_types; i++) | 1095 | for (i = 0; i < tegra->soc->num_types; i++) |
@@ -1031,7 +1099,7 @@ static int tegra_xusb_probe(struct platform_device *pdev) | |||
1031 | sizeof(*tegra->phys), GFP_KERNEL); | 1099 | sizeof(*tegra->phys), GFP_KERNEL); |
1032 | if (!tegra->phys) { | 1100 | if (!tegra->phys) { |
1033 | err = -ENOMEM; | 1101 | err = -ENOMEM; |
1034 | goto put_padctl; | 1102 | goto disable_xusbc; |
1035 | } | 1103 | } |
1036 | 1104 | ||
1037 | for (i = 0, k = 0; i < tegra->soc->num_types; i++) { | 1105 | for (i = 0, k = 0; i < tegra->soc->num_types; i++) { |
@@ -1047,29 +1115,35 @@ static int tegra_xusb_probe(struct platform_device *pdev) | |||
1047 | "failed to get PHY %s: %ld\n", prop, | 1115 | "failed to get PHY %s: %ld\n", prop, |
1048 | PTR_ERR(phy)); | 1116 | PTR_ERR(phy)); |
1049 | err = PTR_ERR(phy); | 1117 | err = PTR_ERR(phy); |
1050 | goto put_padctl; | 1118 | goto disable_xusbc; |
1051 | } | 1119 | } |
1052 | 1120 | ||
1053 | tegra->phys[k++] = phy; | 1121 | tegra->phys[k++] = phy; |
1054 | } | 1122 | } |
1055 | } | 1123 | } |
1056 | 1124 | ||
1057 | err = tegra_xusb_clk_enable(tegra); | 1125 | tegra->hcd = usb_create_hcd(&tegra_xhci_hc_driver, &pdev->dev, |
1058 | if (err) { | 1126 | dev_name(&pdev->dev)); |
1059 | dev_err(&pdev->dev, "failed to enable clocks: %d\n", err); | 1127 | if (!tegra->hcd) { |
1060 | goto put_padctl; | 1128 | err = -ENOMEM; |
1129 | goto disable_xusbc; | ||
1061 | } | 1130 | } |
1062 | 1131 | ||
1063 | err = regulator_bulk_enable(tegra->soc->num_supplies, tegra->supplies); | 1132 | /* |
1064 | if (err) { | 1133 | * This must happen after usb_create_hcd(), because usb_create_hcd() |
1065 | dev_err(&pdev->dev, "failed to enable regulators: %d\n", err); | 1134 | * will overwrite the drvdata of the device with the hcd it creates. |
1066 | goto disable_clk; | 1135 | */ |
1067 | } | 1136 | platform_set_drvdata(pdev, tegra); |
1137 | |||
1138 | pm_runtime_enable(&pdev->dev); | ||
1139 | if (pm_runtime_enabled(&pdev->dev)) | ||
1140 | err = pm_runtime_get_sync(&pdev->dev); | ||
1141 | else | ||
1142 | err = tegra_xusb_runtime_resume(&pdev->dev); | ||
1068 | 1143 | ||
1069 | err = tegra_xusb_phy_enable(tegra); | ||
1070 | if (err < 0) { | 1144 | if (err < 0) { |
1071 | dev_err(&pdev->dev, "failed to enable PHYs: %d\n", err); | 1145 | dev_err(&pdev->dev, "failed to enable device: %d\n", err); |
1072 | goto disable_regulator; | 1146 | goto disable_rpm; |
1073 | } | 1147 | } |
1074 | 1148 | ||
1075 | tegra_xusb_ipfs_config(tegra, regs); | 1149 | tegra_xusb_ipfs_config(tegra, regs); |
@@ -1077,22 +1151,9 @@ static int tegra_xusb_probe(struct platform_device *pdev) | |||
1077 | err = tegra_xusb_load_firmware(tegra); | 1151 | err = tegra_xusb_load_firmware(tegra); |
1078 | if (err < 0) { | 1152 | if (err < 0) { |
1079 | dev_err(&pdev->dev, "failed to load firmware: %d\n", err); | 1153 | dev_err(&pdev->dev, "failed to load firmware: %d\n", err); |
1080 | goto disable_phy; | 1154 | goto put_rpm; |
1081 | } | ||
1082 | |||
1083 | tegra->hcd = usb_create_hcd(&tegra_xhci_hc_driver, &pdev->dev, | ||
1084 | dev_name(&pdev->dev)); | ||
1085 | if (!tegra->hcd) { | ||
1086 | err = -ENOMEM; | ||
1087 | goto disable_phy; | ||
1088 | } | 1155 | } |
1089 | 1156 | ||
1090 | /* | ||
1091 | * This must happen after usb_create_hcd(), because usb_create_hcd() | ||
1092 | * will overwrite the drvdata of the device with the hcd it creates. | ||
1093 | */ | ||
1094 | platform_set_drvdata(pdev, tegra); | ||
1095 | |||
1096 | tegra->hcd->regs = tegra->regs; | 1157 | tegra->hcd->regs = tegra->regs; |
1097 | tegra->hcd->rsrc_start = regs->start; | 1158 | tegra->hcd->rsrc_start = regs->start; |
1098 | tegra->hcd->rsrc_len = resource_size(regs); | 1159 | tegra->hcd->rsrc_len = resource_size(regs); |
@@ -1100,7 +1161,7 @@ static int tegra_xusb_probe(struct platform_device *pdev) | |||
1100 | err = usb_add_hcd(tegra->hcd, tegra->xhci_irq, IRQF_SHARED); | 1161 | err = usb_add_hcd(tegra->hcd, tegra->xhci_irq, IRQF_SHARED); |
1101 | if (err < 0) { | 1162 | if (err < 0) { |
1102 | dev_err(&pdev->dev, "failed to add USB HCD: %d\n", err); | 1163 | dev_err(&pdev->dev, "failed to add USB HCD: %d\n", err); |
1103 | goto put_usb2; | 1164 | goto put_rpm; |
1104 | } | 1165 | } |
1105 | 1166 | ||
1106 | device_wakeup_enable(tegra->hcd->self.controller); | 1167 | device_wakeup_enable(tegra->hcd->self.controller); |
@@ -1155,14 +1216,18 @@ put_usb3: | |||
1155 | usb_put_hcd(xhci->shared_hcd); | 1216 | usb_put_hcd(xhci->shared_hcd); |
1156 | remove_usb2: | 1217 | remove_usb2: |
1157 | usb_remove_hcd(tegra->hcd); | 1218 | usb_remove_hcd(tegra->hcd); |
1158 | put_usb2: | 1219 | put_rpm: |
1220 | if (!pm_runtime_status_suspended(&pdev->dev)) | ||
1221 | tegra_xusb_runtime_suspend(&pdev->dev); | ||
1222 | disable_rpm: | ||
1223 | pm_runtime_disable(&pdev->dev); | ||
1159 | usb_put_hcd(tegra->hcd); | 1224 | usb_put_hcd(tegra->hcd); |
1160 | disable_phy: | 1225 | disable_xusbc: |
1161 | tegra_xusb_phy_disable(tegra); | 1226 | if (!&pdev->dev.pm_domain) |
1162 | disable_regulator: | 1227 | tegra_powergate_power_off(TEGRA_POWERGATE_XUSBC); |
1163 | regulator_bulk_disable(tegra->soc->num_supplies, tegra->supplies); | 1228 | disable_xusba: |
1164 | disable_clk: | 1229 | if (!&pdev->dev.pm_domain) |
1165 | tegra_xusb_clk_disable(tegra); | 1230 | tegra_powergate_power_off(TEGRA_POWERGATE_XUSBA); |
1166 | put_padctl: | 1231 | put_padctl: |
1167 | tegra_xusb_padctl_put(tegra->padctl); | 1232 | tegra_xusb_padctl_put(tegra->padctl); |
1168 | return err; | 1233 | return err; |
@@ -1181,9 +1246,8 @@ static int tegra_xusb_remove(struct platform_device *pdev) | |||
1181 | dma_free_coherent(&pdev->dev, tegra->fw.size, tegra->fw.virt, | 1246 | dma_free_coherent(&pdev->dev, tegra->fw.size, tegra->fw.virt, |
1182 | tegra->fw.phys); | 1247 | tegra->fw.phys); |
1183 | 1248 | ||
1184 | tegra_xusb_phy_disable(tegra); | 1249 | pm_runtime_put_sync(&pdev->dev); |
1185 | regulator_bulk_disable(tegra->soc->num_supplies, tegra->supplies); | 1250 | pm_runtime_disable(&pdev->dev); |
1186 | tegra_xusb_clk_disable(tegra); | ||
1187 | 1251 | ||
1188 | tegra_xusb_padctl_put(tegra->padctl); | 1252 | tegra_xusb_padctl_put(tegra->padctl); |
1189 | 1253 | ||
@@ -1211,6 +1275,8 @@ static int tegra_xusb_resume(struct device *dev) | |||
1211 | #endif | 1275 | #endif |
1212 | 1276 | ||
1213 | static const struct dev_pm_ops tegra_xusb_pm_ops = { | 1277 | static const struct dev_pm_ops tegra_xusb_pm_ops = { |
1278 | SET_RUNTIME_PM_OPS(tegra_xusb_runtime_suspend, | ||
1279 | tegra_xusb_runtime_resume, NULL) | ||
1214 | SET_SYSTEM_SLEEP_PM_OPS(tegra_xusb_suspend, tegra_xusb_resume) | 1280 | SET_SYSTEM_SLEEP_PM_OPS(tegra_xusb_suspend, tegra_xusb_resume) |
1215 | }; | 1281 | }; |
1216 | 1282 | ||
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 711da3306b14..8c8da2d657fa 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c | |||
@@ -33,8 +33,8 @@ static int link_quirk; | |||
33 | module_param(link_quirk, int, S_IRUGO | S_IWUSR); | 33 | module_param(link_quirk, int, S_IRUGO | S_IWUSR); |
34 | MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB"); | 34 | MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB"); |
35 | 35 | ||
36 | static unsigned int quirks; | 36 | static unsigned long long quirks; |
37 | module_param(quirks, uint, S_IRUGO); | 37 | module_param(quirks, ullong, S_IRUGO); |
38 | MODULE_PARM_DESC(quirks, "Bit flags for quirks to be enabled as default"); | 38 | MODULE_PARM_DESC(quirks, "Bit flags for quirks to be enabled as default"); |
39 | 39 | ||
40 | /* TODO: copied from ehci-hcd.c - can this be refactored? */ | 40 | /* TODO: copied from ehci-hcd.c - can this be refactored? */ |
@@ -209,6 +209,68 @@ int xhci_reset(struct xhci_hcd *xhci) | |||
209 | return ret; | 209 | return ret; |
210 | } | 210 | } |
211 | 211 | ||
212 | static void xhci_zero_64b_regs(struct xhci_hcd *xhci) | ||
213 | { | ||
214 | struct device *dev = xhci_to_hcd(xhci)->self.sysdev; | ||
215 | int err, i; | ||
216 | u64 val; | ||
217 | |||
218 | /* | ||
219 | * Some Renesas controllers get into a weird state if they are | ||
220 | * reset while programmed with 64bit addresses (they will preserve | ||
221 | * the top half of the address in internal, non visible | ||
222 | * registers). You end up with half the address coming from the | ||
223 | * kernel, and the other half coming from the firmware. Also, | ||
224 | * changing the programming leads to extra accesses even if the | ||
225 | * controller is supposed to be halted. The controller ends up with | ||
226 | * a fatal fault, and is then ripe for being properly reset. | ||
227 | * | ||
228 | * Special care is taken to only apply this if the device is behind | ||
229 | * an iommu. Doing anything when there is no iommu is definitely | ||
230 | * unsafe... | ||
231 | */ | ||
232 | if (!(xhci->quirks & XHCI_ZERO_64B_REGS) || !dev->iommu_group) | ||
233 | return; | ||
234 | |||
235 | xhci_info(xhci, "Zeroing 64bit base registers, expecting fault\n"); | ||
236 | |||
237 | /* Clear HSEIE so that faults do not get signaled */ | ||
238 | val = readl(&xhci->op_regs->command); | ||
239 | val &= ~CMD_HSEIE; | ||
240 | writel(val, &xhci->op_regs->command); | ||
241 | |||
242 | /* Clear HSE (aka FATAL) */ | ||
243 | val = readl(&xhci->op_regs->status); | ||
244 | val |= STS_FATAL; | ||
245 | writel(val, &xhci->op_regs->status); | ||
246 | |||
247 | /* Now zero the registers, and brace for impact */ | ||
248 | val = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr); | ||
249 | if (upper_32_bits(val)) | ||
250 | xhci_write_64(xhci, 0, &xhci->op_regs->dcbaa_ptr); | ||
251 | val = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); | ||
252 | if (upper_32_bits(val)) | ||
253 | xhci_write_64(xhci, 0, &xhci->op_regs->cmd_ring); | ||
254 | |||
255 | for (i = 0; i < HCS_MAX_INTRS(xhci->hcs_params1); i++) { | ||
256 | struct xhci_intr_reg __iomem *ir; | ||
257 | |||
258 | ir = &xhci->run_regs->ir_set[i]; | ||
259 | val = xhci_read_64(xhci, &ir->erst_base); | ||
260 | if (upper_32_bits(val)) | ||
261 | xhci_write_64(xhci, 0, &ir->erst_base); | ||
262 | val= xhci_read_64(xhci, &ir->erst_dequeue); | ||
263 | if (upper_32_bits(val)) | ||
264 | xhci_write_64(xhci, 0, &ir->erst_dequeue); | ||
265 | } | ||
266 | |||
267 | /* Wait for the fault to appear. It will be cleared on reset */ | ||
268 | err = xhci_handshake(&xhci->op_regs->status, | ||
269 | STS_FATAL, STS_FATAL, | ||
270 | XHCI_MAX_HALT_USEC); | ||
271 | if (!err) | ||
272 | xhci_info(xhci, "Fault detected\n"); | ||
273 | } | ||
212 | 274 | ||
213 | #ifdef CONFIG_USB_PCI | 275 | #ifdef CONFIG_USB_PCI |
214 | /* | 276 | /* |
@@ -400,13 +462,15 @@ static void compliance_mode_recovery(struct timer_list *t) | |||
400 | { | 462 | { |
401 | struct xhci_hcd *xhci; | 463 | struct xhci_hcd *xhci; |
402 | struct usb_hcd *hcd; | 464 | struct usb_hcd *hcd; |
465 | struct xhci_hub *rhub; | ||
403 | u32 temp; | 466 | u32 temp; |
404 | int i; | 467 | int i; |
405 | 468 | ||
406 | xhci = from_timer(xhci, t, comp_mode_recovery_timer); | 469 | xhci = from_timer(xhci, t, comp_mode_recovery_timer); |
470 | rhub = &xhci->usb3_rhub; | ||
407 | 471 | ||
408 | for (i = 0; i < xhci->num_usb3_ports; i++) { | 472 | for (i = 0; i < rhub->num_ports; i++) { |
409 | temp = readl(xhci->usb3_ports[i]); | 473 | temp = readl(rhub->ports[i]->addr); |
410 | if ((temp & PORT_PLS_MASK) == USB_SS_PORT_LS_COMP_MOD) { | 474 | if ((temp & PORT_PLS_MASK) == USB_SS_PORT_LS_COMP_MOD) { |
411 | /* | 475 | /* |
412 | * Compliance Mode Detected. Letting USB Core | 476 | * Compliance Mode Detected. Letting USB Core |
@@ -426,7 +490,7 @@ static void compliance_mode_recovery(struct timer_list *t) | |||
426 | } | 490 | } |
427 | } | 491 | } |
428 | 492 | ||
429 | if (xhci->port_status_u0 != ((1 << xhci->num_usb3_ports)-1)) | 493 | if (xhci->port_status_u0 != ((1 << rhub->num_ports) - 1)) |
430 | mod_timer(&xhci->comp_mode_recovery_timer, | 494 | mod_timer(&xhci->comp_mode_recovery_timer, |
431 | jiffies + msecs_to_jiffies(COMP_MODE_RCVRY_MSECS)); | 495 | jiffies + msecs_to_jiffies(COMP_MODE_RCVRY_MSECS)); |
432 | } | 496 | } |
@@ -483,7 +547,7 @@ static bool xhci_compliance_mode_recovery_timer_quirk_check(void) | |||
483 | 547 | ||
484 | static int xhci_all_ports_seen_u0(struct xhci_hcd *xhci) | 548 | static int xhci_all_ports_seen_u0(struct xhci_hcd *xhci) |
485 | { | 549 | { |
486 | return (xhci->port_status_u0 == ((1 << xhci->num_usb3_ports)-1)); | 550 | return (xhci->port_status_u0 == ((1 << xhci->usb3_rhub.num_ports) - 1)); |
487 | } | 551 | } |
488 | 552 | ||
489 | 553 | ||
@@ -812,33 +876,33 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci) | |||
812 | 876 | ||
813 | static void xhci_disable_port_wake_on_bits(struct xhci_hcd *xhci) | 877 | static void xhci_disable_port_wake_on_bits(struct xhci_hcd *xhci) |
814 | { | 878 | { |
879 | struct xhci_port **ports; | ||
815 | int port_index; | 880 | int port_index; |
816 | __le32 __iomem **port_array; | ||
817 | unsigned long flags; | 881 | unsigned long flags; |
818 | u32 t1, t2; | 882 | u32 t1, t2; |
819 | 883 | ||
820 | spin_lock_irqsave(&xhci->lock, flags); | 884 | spin_lock_irqsave(&xhci->lock, flags); |
821 | 885 | ||
822 | /* disable usb3 ports Wake bits */ | 886 | /* disable usb3 ports Wake bits */ |
823 | port_index = xhci->num_usb3_ports; | 887 | port_index = xhci->usb3_rhub.num_ports; |
824 | port_array = xhci->usb3_ports; | 888 | ports = xhci->usb3_rhub.ports; |
825 | while (port_index--) { | 889 | while (port_index--) { |
826 | t1 = readl(port_array[port_index]); | 890 | t1 = readl(ports[port_index]->addr); |
827 | t1 = xhci_port_state_to_neutral(t1); | 891 | t1 = xhci_port_state_to_neutral(t1); |
828 | t2 = t1 & ~PORT_WAKE_BITS; | 892 | t2 = t1 & ~PORT_WAKE_BITS; |
829 | if (t1 != t2) | 893 | if (t1 != t2) |
830 | writel(t2, port_array[port_index]); | 894 | writel(t2, ports[port_index]->addr); |
831 | } | 895 | } |
832 | 896 | ||
833 | /* disable usb2 ports Wake bits */ | 897 | /* disable usb2 ports Wake bits */ |
834 | port_index = xhci->num_usb2_ports; | 898 | port_index = xhci->usb2_rhub.num_ports; |
835 | port_array = xhci->usb2_ports; | 899 | ports = xhci->usb2_rhub.ports; |
836 | while (port_index--) { | 900 | while (port_index--) { |
837 | t1 = readl(port_array[port_index]); | 901 | t1 = readl(ports[port_index]->addr); |
838 | t1 = xhci_port_state_to_neutral(t1); | 902 | t1 = xhci_port_state_to_neutral(t1); |
839 | t2 = t1 & ~PORT_WAKE_BITS; | 903 | t2 = t1 & ~PORT_WAKE_BITS; |
840 | if (t1 != t2) | 904 | if (t1 != t2) |
841 | writel(t2, port_array[port_index]); | 905 | writel(t2, ports[port_index]->addr); |
842 | } | 906 | } |
843 | 907 | ||
844 | spin_unlock_irqrestore(&xhci->lock, flags); | 908 | spin_unlock_irqrestore(&xhci->lock, flags); |
@@ -1004,6 +1068,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) | |||
1004 | 1068 | ||
1005 | xhci_dbg(xhci, "Stop HCD\n"); | 1069 | xhci_dbg(xhci, "Stop HCD\n"); |
1006 | xhci_halt(xhci); | 1070 | xhci_halt(xhci); |
1071 | xhci_zero_64b_regs(xhci); | ||
1007 | xhci_reset(xhci); | 1072 | xhci_reset(xhci); |
1008 | spin_unlock_irq(&xhci->lock); | 1073 | spin_unlock_irq(&xhci->lock); |
1009 | xhci_cleanup_msix(xhci); | 1074 | xhci_cleanup_msix(xhci); |
@@ -3976,18 +4041,10 @@ static int xhci_enable_device(struct usb_hcd *hcd, struct usb_device *udev) | |||
3976 | */ | 4041 | */ |
3977 | int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1) | 4042 | int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1) |
3978 | { | 4043 | { |
3979 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 4044 | struct xhci_hub *rhub; |
3980 | __le32 __iomem *base_addr = &xhci->op_regs->port_status_base; | ||
3981 | __le32 __iomem *addr; | ||
3982 | int raw_port; | ||
3983 | 4045 | ||
3984 | if (hcd->speed < HCD_USB3) | 4046 | rhub = xhci_get_rhub(hcd); |
3985 | addr = xhci->usb2_ports[port1 - 1]; | 4047 | return rhub->ports[port1 - 1]->hw_portnum + 1; |
3986 | else | ||
3987 | addr = xhci->usb3_ports[port1 - 1]; | ||
3988 | |||
3989 | raw_port = (addr - base_addr)/NUM_PORT_REGS + 1; | ||
3990 | return raw_port; | ||
3991 | } | 4048 | } |
3992 | 4049 | ||
3993 | /* | 4050 | /* |
@@ -4120,7 +4177,7 @@ static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, | |||
4120 | struct usb_device *udev, int enable) | 4177 | struct usb_device *udev, int enable) |
4121 | { | 4178 | { |
4122 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 4179 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
4123 | __le32 __iomem **port_array; | 4180 | struct xhci_port **ports; |
4124 | __le32 __iomem *pm_addr, *hlpm_addr; | 4181 | __le32 __iomem *pm_addr, *hlpm_addr; |
4125 | u32 pm_val, hlpm_val, field; | 4182 | u32 pm_val, hlpm_val, field; |
4126 | unsigned int port_num; | 4183 | unsigned int port_num; |
@@ -4141,11 +4198,11 @@ static int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, | |||
4141 | 4198 | ||
4142 | spin_lock_irqsave(&xhci->lock, flags); | 4199 | spin_lock_irqsave(&xhci->lock, flags); |
4143 | 4200 | ||
4144 | port_array = xhci->usb2_ports; | 4201 | ports = xhci->usb2_rhub.ports; |
4145 | port_num = udev->portnum - 1; | 4202 | port_num = udev->portnum - 1; |
4146 | pm_addr = port_array[port_num] + PORTPMSC; | 4203 | pm_addr = ports[port_num]->addr + PORTPMSC; |
4147 | pm_val = readl(pm_addr); | 4204 | pm_val = readl(pm_addr); |
4148 | hlpm_addr = port_array[port_num] + PORTHLPMC; | 4205 | hlpm_addr = ports[port_num]->addr + PORTHLPMC; |
4149 | field = le32_to_cpu(udev->bos->ext_cap->bmAttributes); | 4206 | field = le32_to_cpu(udev->bos->ext_cap->bmAttributes); |
4150 | 4207 | ||
4151 | xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n", | 4208 | xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n", |
@@ -4858,6 +4915,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) | |||
4858 | 4915 | ||
4859 | if (usb_hcd_is_primary_hcd(hcd)) { | 4916 | if (usb_hcd_is_primary_hcd(hcd)) { |
4860 | xhci->main_hcd = hcd; | 4917 | xhci->main_hcd = hcd; |
4918 | xhci->usb2_rhub.hcd = hcd; | ||
4861 | /* Mark the first roothub as being USB 2.0. | 4919 | /* Mark the first roothub as being USB 2.0. |
4862 | * The xHCI driver will register the USB 3.0 roothub. | 4920 | * The xHCI driver will register the USB 3.0 roothub. |
4863 | */ | 4921 | */ |
@@ -4883,6 +4941,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) | |||
4883 | minor_rev, | 4941 | minor_rev, |
4884 | minor_rev ? "Enhanced" : ""); | 4942 | minor_rev ? "Enhanced" : ""); |
4885 | 4943 | ||
4944 | xhci->usb3_rhub.hcd = hcd; | ||
4886 | /* xHCI private pointer was set in xhci_pci_probe for the second | 4945 | /* xHCI private pointer was set in xhci_pci_probe for the second |
4887 | * registered roothub. | 4946 | * registered roothub. |
4888 | */ | 4947 | */ |
@@ -4921,6 +4980,8 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) | |||
4921 | if (retval) | 4980 | if (retval) |
4922 | return retval; | 4981 | return retval; |
4923 | 4982 | ||
4983 | xhci_zero_64b_regs(xhci); | ||
4984 | |||
4924 | xhci_dbg(xhci, "Resetting HCD\n"); | 4985 | xhci_dbg(xhci, "Resetting HCD\n"); |
4925 | /* Reset the internal HC memory state and registers. */ | 4986 | /* Reset the internal HC memory state and registers. */ |
4926 | retval = xhci_reset(xhci); | 4987 | retval = xhci_reset(xhci); |
@@ -4963,7 +5024,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) | |||
4963 | return retval; | 5024 | return retval; |
4964 | xhci_dbg(xhci, "Called HCD init\n"); | 5025 | xhci_dbg(xhci, "Called HCD init\n"); |
4965 | 5026 | ||
4966 | xhci_info(xhci, "hcc params 0x%08x hci version 0x%x quirks 0x%08x\n", | 5027 | xhci_info(xhci, "hcc params 0x%08x hci version 0x%x quirks 0x%016llx\n", |
4967 | xhci->hcc_params, xhci->hci_version, xhci->quirks); | 5028 | xhci->hcc_params, xhci->hci_version, xhci->quirks); |
4968 | 5029 | ||
4969 | return 0; | 5030 | return 0; |
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 6dfc4867dbcf..939e2f86b595 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h | |||
@@ -1683,13 +1683,23 @@ static inline unsigned int hcd_index(struct usb_hcd *hcd) | |||
1683 | else | 1683 | else |
1684 | return 1; | 1684 | return 1; |
1685 | } | 1685 | } |
1686 | struct xhci_port { | ||
1687 | __le32 __iomem *addr; | ||
1688 | int hw_portnum; | ||
1689 | int hcd_portnum; | ||
1690 | struct xhci_hub *rhub; | ||
1691 | }; | ||
1686 | 1692 | ||
1687 | struct xhci_hub { | 1693 | struct xhci_hub { |
1688 | u8 maj_rev; | 1694 | struct xhci_port **ports; |
1689 | u8 min_rev; | 1695 | unsigned int num_ports; |
1690 | u32 *psi; /* array of protocol speed ID entries */ | 1696 | struct usb_hcd *hcd; |
1691 | u8 psi_count; | 1697 | /* supported prococol extended capabiliy values */ |
1692 | u8 psi_uid_count; | 1698 | u8 maj_rev; |
1699 | u8 min_rev; | ||
1700 | u32 *psi; /* array of protocol speed ID entries */ | ||
1701 | u8 psi_count; | ||
1702 | u8 psi_uid_count; | ||
1693 | }; | 1703 | }; |
1694 | 1704 | ||
1695 | /* There is one xhci_hcd structure per controller */ | 1705 | /* There is one xhci_hcd structure per controller */ |
@@ -1787,12 +1797,12 @@ struct xhci_hcd { | |||
1787 | #define XHCI_STATE_DYING (1 << 0) | 1797 | #define XHCI_STATE_DYING (1 << 0) |
1788 | #define XHCI_STATE_HALTED (1 << 1) | 1798 | #define XHCI_STATE_HALTED (1 << 1) |
1789 | #define XHCI_STATE_REMOVING (1 << 2) | 1799 | #define XHCI_STATE_REMOVING (1 << 2) |
1790 | unsigned int quirks; | 1800 | unsigned long long quirks; |
1791 | #define XHCI_LINK_TRB_QUIRK (1 << 0) | 1801 | #define XHCI_LINK_TRB_QUIRK BIT_ULL(0) |
1792 | #define XHCI_RESET_EP_QUIRK (1 << 1) | 1802 | #define XHCI_RESET_EP_QUIRK BIT_ULL(1) |
1793 | #define XHCI_NEC_HOST (1 << 2) | 1803 | #define XHCI_NEC_HOST BIT_ULL(2) |
1794 | #define XHCI_AMD_PLL_FIX (1 << 3) | 1804 | #define XHCI_AMD_PLL_FIX BIT_ULL(3) |
1795 | #define XHCI_SPURIOUS_SUCCESS (1 << 4) | 1805 | #define XHCI_SPURIOUS_SUCCESS BIT_ULL(4) |
1796 | /* | 1806 | /* |
1797 | * Certain Intel host controllers have a limit to the number of endpoint | 1807 | * Certain Intel host controllers have a limit to the number of endpoint |
1798 | * contexts they can handle. Ideally, they would signal that they can't handle | 1808 | * contexts they can handle. Ideally, they would signal that they can't handle |
@@ -1802,50 +1812,44 @@ struct xhci_hcd { | |||
1802 | * commands, reset device commands, disable slot commands, and address device | 1812 | * commands, reset device commands, disable slot commands, and address device |
1803 | * commands. | 1813 | * commands. |
1804 | */ | 1814 | */ |
1805 | #define XHCI_EP_LIMIT_QUIRK (1 << 5) | 1815 | #define XHCI_EP_LIMIT_QUIRK BIT_ULL(5) |
1806 | #define XHCI_BROKEN_MSI (1 << 6) | 1816 | #define XHCI_BROKEN_MSI BIT_ULL(6) |
1807 | #define XHCI_RESET_ON_RESUME (1 << 7) | 1817 | #define XHCI_RESET_ON_RESUME BIT_ULL(7) |
1808 | #define XHCI_SW_BW_CHECKING (1 << 8) | 1818 | #define XHCI_SW_BW_CHECKING BIT_ULL(8) |
1809 | #define XHCI_AMD_0x96_HOST (1 << 9) | 1819 | #define XHCI_AMD_0x96_HOST BIT_ULL(9) |
1810 | #define XHCI_TRUST_TX_LENGTH (1 << 10) | 1820 | #define XHCI_TRUST_TX_LENGTH BIT_ULL(10) |
1811 | #define XHCI_LPM_SUPPORT (1 << 11) | 1821 | #define XHCI_LPM_SUPPORT BIT_ULL(11) |
1812 | #define XHCI_INTEL_HOST (1 << 12) | 1822 | #define XHCI_INTEL_HOST BIT_ULL(12) |
1813 | #define XHCI_SPURIOUS_REBOOT (1 << 13) | 1823 | #define XHCI_SPURIOUS_REBOOT BIT_ULL(13) |
1814 | #define XHCI_COMP_MODE_QUIRK (1 << 14) | 1824 | #define XHCI_COMP_MODE_QUIRK BIT_ULL(14) |
1815 | #define XHCI_AVOID_BEI (1 << 15) | 1825 | #define XHCI_AVOID_BEI BIT_ULL(15) |
1816 | #define XHCI_PLAT (1 << 16) | 1826 | #define XHCI_PLAT BIT_ULL(16) |
1817 | #define XHCI_SLOW_SUSPEND (1 << 17) | 1827 | #define XHCI_SLOW_SUSPEND BIT_ULL(17) |
1818 | #define XHCI_SPURIOUS_WAKEUP (1 << 18) | 1828 | #define XHCI_SPURIOUS_WAKEUP BIT_ULL(18) |
1819 | /* For controllers with a broken beyond repair streams implementation */ | 1829 | /* For controllers with a broken beyond repair streams implementation */ |
1820 | #define XHCI_BROKEN_STREAMS (1 << 19) | 1830 | #define XHCI_BROKEN_STREAMS BIT_ULL(19) |
1821 | #define XHCI_PME_STUCK_QUIRK (1 << 20) | 1831 | #define XHCI_PME_STUCK_QUIRK BIT_ULL(20) |
1822 | #define XHCI_MTK_HOST (1 << 21) | 1832 | #define XHCI_MTK_HOST BIT_ULL(21) |
1823 | #define XHCI_SSIC_PORT_UNUSED (1 << 22) | 1833 | #define XHCI_SSIC_PORT_UNUSED BIT_ULL(22) |
1824 | #define XHCI_NO_64BIT_SUPPORT (1 << 23) | 1834 | #define XHCI_NO_64BIT_SUPPORT BIT_ULL(23) |
1825 | #define XHCI_MISSING_CAS (1 << 24) | 1835 | #define XHCI_MISSING_CAS BIT_ULL(24) |
1826 | /* For controller with a broken Port Disable implementation */ | 1836 | /* For controller with a broken Port Disable implementation */ |
1827 | #define XHCI_BROKEN_PORT_PED (1 << 25) | 1837 | #define XHCI_BROKEN_PORT_PED BIT_ULL(25) |
1828 | #define XHCI_LIMIT_ENDPOINT_INTERVAL_7 (1 << 26) | 1838 | #define XHCI_LIMIT_ENDPOINT_INTERVAL_7 BIT_ULL(26) |
1829 | #define XHCI_U2_DISABLE_WAKE (1 << 27) | 1839 | #define XHCI_U2_DISABLE_WAKE BIT_ULL(27) |
1830 | #define XHCI_ASMEDIA_MODIFY_FLOWCONTROL (1 << 28) | 1840 | #define XHCI_ASMEDIA_MODIFY_FLOWCONTROL BIT_ULL(28) |
1831 | #define XHCI_HW_LPM_DISABLE (1 << 29) | 1841 | #define XHCI_HW_LPM_DISABLE BIT_ULL(29) |
1832 | #define XHCI_SUSPEND_DELAY (1 << 30) | 1842 | #define XHCI_SUSPEND_DELAY BIT_ULL(30) |
1833 | #define XHCI_INTEL_USB_ROLE_SW (1 << 31) | 1843 | #define XHCI_INTEL_USB_ROLE_SW BIT_ULL(31) |
1844 | #define XHCI_ZERO_64B_REGS BIT_ULL(32) | ||
1834 | 1845 | ||
1835 | unsigned int num_active_eps; | 1846 | unsigned int num_active_eps; |
1836 | unsigned int limit_active_eps; | 1847 | unsigned int limit_active_eps; |
1837 | /* There are two roothubs to keep track of bus suspend info for */ | 1848 | /* There are two roothubs to keep track of bus suspend info for */ |
1838 | struct xhci_bus_state bus_state[2]; | 1849 | struct xhci_bus_state bus_state[2]; |
1839 | /* Is each xHCI roothub port a USB 3.0, USB 2.0, or USB 1.1 port? */ | 1850 | struct xhci_port *hw_ports; |
1840 | u8 *port_array; | ||
1841 | /* Array of pointers to USB 3.0 PORTSC registers */ | ||
1842 | __le32 __iomem **usb3_ports; | ||
1843 | unsigned int num_usb3_ports; | ||
1844 | /* Array of pointers to USB 2.0 PORTSC registers */ | ||
1845 | __le32 __iomem **usb2_ports; | ||
1846 | struct xhci_hub usb2_rhub; | 1851 | struct xhci_hub usb2_rhub; |
1847 | struct xhci_hub usb3_rhub; | 1852 | struct xhci_hub usb3_rhub; |
1848 | unsigned int num_usb2_ports; | ||
1849 | /* support xHCI 0.96 spec USB2 software LPM */ | 1853 | /* support xHCI 0.96 spec USB2 software LPM */ |
1850 | unsigned sw_lpm_support:1; | 1854 | unsigned sw_lpm_support:1; |
1851 | /* support xHCI 1.0 spec USB2 hardware LPM */ | 1855 | /* support xHCI 1.0 spec USB2 hardware LPM */ |
@@ -2091,14 +2095,16 @@ void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring); | |||
2091 | unsigned int count_trbs(u64 addr, u64 len); | 2095 | unsigned int count_trbs(u64 addr, u64 len); |
2092 | 2096 | ||
2093 | /* xHCI roothub code */ | 2097 | /* xHCI roothub code */ |
2094 | void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array, | 2098 | void xhci_set_link_state(struct xhci_hcd *xhci, struct xhci_port *port, |
2095 | int port_id, u32 link_state); | 2099 | u32 link_state); |
2096 | void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array, | 2100 | void xhci_test_and_clear_bit(struct xhci_hcd *xhci, struct xhci_port *port, |
2097 | int port_id, u32 port_bit); | 2101 | u32 port_bit); |
2098 | int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, | 2102 | int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, |
2099 | char *buf, u16 wLength); | 2103 | char *buf, u16 wLength); |
2100 | int xhci_hub_status_data(struct usb_hcd *hcd, char *buf); | 2104 | int xhci_hub_status_data(struct usb_hcd *hcd, char *buf); |
2101 | int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1); | 2105 | int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1); |
2106 | struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd); | ||
2107 | |||
2102 | void xhci_hc_died(struct xhci_hcd *xhci); | 2108 | void xhci_hc_died(struct xhci_hcd *xhci); |
2103 | 2109 | ||
2104 | #ifdef CONFIG_PM | 2110 | #ifdef CONFIG_PM |
diff --git a/drivers/usb/isp1760/isp1760-core.c b/drivers/usb/isp1760/isp1760-core.c index 05d22589b5cc..55b94fd10331 100644 --- a/drivers/usb/isp1760/isp1760-core.c +++ b/drivers/usb/isp1760/isp1760-core.c | |||
@@ -31,7 +31,7 @@ static void isp1760_init_core(struct isp1760_device *isp) | |||
31 | /* Low-level chip reset */ | 31 | /* Low-level chip reset */ |
32 | if (isp->rst_gpio) { | 32 | if (isp->rst_gpio) { |
33 | gpiod_set_value_cansleep(isp->rst_gpio, 1); | 33 | gpiod_set_value_cansleep(isp->rst_gpio, 1); |
34 | mdelay(50); | 34 | msleep(50); |
35 | gpiod_set_value_cansleep(isp->rst_gpio, 0); | 35 | gpiod_set_value_cansleep(isp->rst_gpio, 0); |
36 | } | 36 | } |
37 | 37 | ||
diff --git a/drivers/usb/isp1760/isp1760-hcd.c b/drivers/usb/isp1760/isp1760-hcd.c index 42672d6ec525..1045521be293 100644 --- a/drivers/usb/isp1760/isp1760-hcd.c +++ b/drivers/usb/isp1760/isp1760-hcd.c | |||
@@ -2093,7 +2093,7 @@ static void isp1760_stop(struct usb_hcd *hcd) | |||
2093 | 2093 | ||
2094 | isp1760_hub_control(hcd, ClearPortFeature, USB_PORT_FEAT_POWER, 1, | 2094 | isp1760_hub_control(hcd, ClearPortFeature, USB_PORT_FEAT_POWER, 1, |
2095 | NULL, 0); | 2095 | NULL, 0); |
2096 | mdelay(20); | 2096 | msleep(20); |
2097 | 2097 | ||
2098 | spin_lock_irq(&priv->lock); | 2098 | spin_lock_irq(&priv->lock); |
2099 | ehci_reset(hcd); | 2099 | ehci_reset(hcd); |
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 3e65bdc2615c..f92c5df26320 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c | |||
@@ -2107,7 +2107,7 @@ static void sisusb_get_ramconfig(struct sisusb_usb_data *sisusb) | |||
2107 | bw = busSDR[(tmp8 & 0x03)]; | 2107 | bw = busSDR[(tmp8 & 0x03)]; |
2108 | break; | 2108 | break; |
2109 | case 2: | 2109 | case 2: |
2110 | ramtypetext1 = "asymmeric"; | 2110 | ramtypetext1 = "asymmetric"; |
2111 | sisusb->vramsize += sisusb->vramsize/2; | 2111 | sisusb->vramsize += sisusb->vramsize/2; |
2112 | bw = busDDRA[(tmp8 & 0x03)]; | 2112 | bw = busDDRA[(tmp8 & 0x03)]; |
2113 | break; | 2113 | break; |
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index 2761fad66b95..34e866ad4a81 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c | |||
@@ -1227,7 +1227,7 @@ static void mon_bin_vma_close(struct vm_area_struct *vma) | |||
1227 | /* | 1227 | /* |
1228 | * Map ring pages to user space. | 1228 | * Map ring pages to user space. |
1229 | */ | 1229 | */ |
1230 | static int mon_bin_vma_fault(struct vm_fault *vmf) | 1230 | static vm_fault_t mon_bin_vma_fault(struct vm_fault *vmf) |
1231 | { | 1231 | { |
1232 | struct mon_reader_bin *rp = vmf->vma->vm_private_data; | 1232 | struct mon_reader_bin *rp = vmf->vma->vm_private_data; |
1233 | unsigned long offset, chunk_idx; | 1233 | unsigned long offset, chunk_idx; |
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c index 984f7e12a6a5..bc5ecd5ff565 100644 --- a/drivers/usb/mon/mon_text.c +++ b/drivers/usb/mon/mon_text.c | |||
@@ -700,7 +700,6 @@ static const struct file_operations mon_fops_text_u = { | |||
700 | 700 | ||
701 | int mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus) | 701 | int mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus) |
702 | { | 702 | { |
703 | struct dentry *d; | ||
704 | enum { NAMESZ = 10 }; | 703 | enum { NAMESZ = 10 }; |
705 | char name[NAMESZ]; | 704 | char name[NAMESZ]; |
706 | int busnum = ubus? ubus->busnum: 0; | 705 | int busnum = ubus? ubus->busnum: 0; |
@@ -713,42 +712,32 @@ int mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus) | |||
713 | rc = snprintf(name, NAMESZ, "%dt", busnum); | 712 | rc = snprintf(name, NAMESZ, "%dt", busnum); |
714 | if (rc <= 0 || rc >= NAMESZ) | 713 | if (rc <= 0 || rc >= NAMESZ) |
715 | goto err_print_t; | 714 | goto err_print_t; |
716 | d = debugfs_create_file(name, 0600, mon_dir, mbus, | 715 | mbus->dent_t = debugfs_create_file(name, 0600, mon_dir, mbus, |
717 | &mon_fops_text_t); | 716 | &mon_fops_text_t); |
718 | if (d == NULL) | ||
719 | goto err_create_t; | ||
720 | mbus->dent_t = d; | ||
721 | } | 717 | } |
722 | 718 | ||
723 | rc = snprintf(name, NAMESZ, "%du", busnum); | 719 | rc = snprintf(name, NAMESZ, "%du", busnum); |
724 | if (rc <= 0 || rc >= NAMESZ) | 720 | if (rc <= 0 || rc >= NAMESZ) |
725 | goto err_print_u; | 721 | goto err_print_u; |
726 | d = debugfs_create_file(name, 0600, mon_dir, mbus, &mon_fops_text_u); | 722 | mbus->dent_u = debugfs_create_file(name, 0600, mon_dir, mbus, |
727 | if (d == NULL) | 723 | &mon_fops_text_u); |
728 | goto err_create_u; | ||
729 | mbus->dent_u = d; | ||
730 | 724 | ||
731 | rc = snprintf(name, NAMESZ, "%ds", busnum); | 725 | rc = snprintf(name, NAMESZ, "%ds", busnum); |
732 | if (rc <= 0 || rc >= NAMESZ) | 726 | if (rc <= 0 || rc >= NAMESZ) |
733 | goto err_print_s; | 727 | goto err_print_s; |
734 | d = debugfs_create_file(name, 0600, mon_dir, mbus, &mon_fops_stat); | 728 | mbus->dent_s = debugfs_create_file(name, 0600, mon_dir, mbus, |
735 | if (d == NULL) | 729 | &mon_fops_stat); |
736 | goto err_create_s; | ||
737 | mbus->dent_s = d; | ||
738 | 730 | ||
739 | return 1; | 731 | return 1; |
740 | 732 | ||
741 | err_create_s: | ||
742 | err_print_s: | 733 | err_print_s: |
743 | debugfs_remove(mbus->dent_u); | 734 | debugfs_remove(mbus->dent_u); |
744 | mbus->dent_u = NULL; | 735 | mbus->dent_u = NULL; |
745 | err_create_u: | ||
746 | err_print_u: | 736 | err_print_u: |
747 | if (ubus != NULL) { | 737 | if (ubus != NULL) { |
748 | debugfs_remove(mbus->dent_t); | 738 | debugfs_remove(mbus->dent_t); |
749 | mbus->dent_t = NULL; | 739 | mbus->dent_t = NULL; |
750 | } | 740 | } |
751 | err_create_t: | ||
752 | err_print_t: | 741 | err_print_t: |
753 | return 0; | 742 | return 0; |
754 | } | 743 | } |
@@ -756,8 +745,7 @@ err_print_t: | |||
756 | void mon_text_del(struct mon_bus *mbus) | 745 | void mon_text_del(struct mon_bus *mbus) |
757 | { | 746 | { |
758 | debugfs_remove(mbus->dent_u); | 747 | debugfs_remove(mbus->dent_u); |
759 | if (mbus->dent_t != NULL) | 748 | debugfs_remove(mbus->dent_t); |
760 | debugfs_remove(mbus->dent_t); | ||
761 | debugfs_remove(mbus->dent_s); | 749 | debugfs_remove(mbus->dent_s); |
762 | } | 750 | } |
763 | 751 | ||
@@ -775,18 +763,7 @@ static void mon_text_ctor(void *mem) | |||
775 | 763 | ||
776 | int __init mon_text_init(void) | 764 | int __init mon_text_init(void) |
777 | { | 765 | { |
778 | struct dentry *mondir; | 766 | mon_dir = debugfs_create_dir("usbmon", usb_debug_root); |
779 | |||
780 | mondir = debugfs_create_dir("usbmon", usb_debug_root); | ||
781 | if (IS_ERR(mondir)) { | ||
782 | /* debugfs not available, but we can use usbmon without it */ | ||
783 | return 0; | ||
784 | } | ||
785 | if (mondir == NULL) { | ||
786 | printk(KERN_NOTICE TAG ": unable to create usbmon directory\n"); | ||
787 | return -ENOMEM; | ||
788 | } | ||
789 | mon_dir = mondir; | ||
790 | return 0; | 767 | return 0; |
791 | } | 768 | } |
792 | 769 | ||
diff --git a/drivers/usb/mtu3/Kconfig b/drivers/usb/mtu3/Kconfig index 25cd61947bee..40bbf1f53337 100644 --- a/drivers/usb/mtu3/Kconfig +++ b/drivers/usb/mtu3/Kconfig | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | config USB_MTU3 | 3 | config USB_MTU3 |
4 | tristate "MediaTek USB3 Dual Role controller" | 4 | tristate "MediaTek USB3 Dual Role controller" |
5 | depends on EXTCON && (USB || USB_GADGET) && HAS_DMA | 5 | depends on USB || USB_GADGET |
6 | depends on ARCH_MEDIATEK || COMPILE_TEST | 6 | depends on ARCH_MEDIATEK || COMPILE_TEST |
7 | select USB_XHCI_MTK if USB_SUPPORT && USB_XHCI_HCD | 7 | select USB_XHCI_MTK if USB_SUPPORT && USB_XHCI_HCD |
8 | help | 8 | help |
@@ -40,6 +40,7 @@ config USB_MTU3_GADGET | |||
40 | config USB_MTU3_DUAL_ROLE | 40 | config USB_MTU3_DUAL_ROLE |
41 | bool "Dual Role mode" | 41 | bool "Dual Role mode" |
42 | depends on ((USB=y || USB=USB_MTU3) && (USB_GADGET=y || USB_GADGET=USB_MTU3)) | 42 | depends on ((USB=y || USB=USB_MTU3) && (USB_GADGET=y || USB_GADGET=USB_MTU3)) |
43 | depends on (EXTCON=y || EXTCON=USB_MTU3) | ||
43 | help | 44 | help |
44 | This is the default mode of working of MTU3 controller where | 45 | This is the default mode of working of MTU3 controller where |
45 | both host and gadget features are enabled. | 46 | both host and gadget features are enabled. |
diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h index 2cd00a24afd9..87823ac0d120 100644 --- a/drivers/usb/mtu3/mtu3.h +++ b/drivers/usb/mtu3/mtu3.h | |||
@@ -196,10 +196,12 @@ struct mtu3_gpd_ring { | |||
196 | * @vbus: vbus 5V used by host mode | 196 | * @vbus: vbus 5V used by host mode |
197 | * @edev: external connector used to detect vbus and iddig changes | 197 | * @edev: external connector used to detect vbus and iddig changes |
198 | * @vbus_nb: notifier for vbus detection | 198 | * @vbus_nb: notifier for vbus detection |
199 | * @vbus_nb: notifier for iddig(idpin) detection | 199 | * @vbus_work : work of vbus detection notifier, used to avoid sleep in |
200 | * @extcon_reg_dwork: delay work for extcon notifier register, waiting for | 200 | * notifier callback which is atomic context |
201 | * xHCI driver initialization, it's necessary for system bootup | 201 | * @vbus_event : event of vbus detecion notifier |
202 | * as device. | 202 | * @id_nb : notifier for iddig(idpin) detection |
203 | * @id_work : work of iddig detection notifier | ||
204 | * @id_event : event of iddig detecion notifier | ||
203 | * @is_u3_drd: whether port0 supports usb3.0 dual-role device or not | 205 | * @is_u3_drd: whether port0 supports usb3.0 dual-role device or not |
204 | * @manual_drd_enabled: it's true when supports dual-role device by debugfs | 206 | * @manual_drd_enabled: it's true when supports dual-role device by debugfs |
205 | * to switch host/device modes depending on user input. | 207 | * to switch host/device modes depending on user input. |
@@ -208,8 +210,11 @@ struct otg_switch_mtk { | |||
208 | struct regulator *vbus; | 210 | struct regulator *vbus; |
209 | struct extcon_dev *edev; | 211 | struct extcon_dev *edev; |
210 | struct notifier_block vbus_nb; | 212 | struct notifier_block vbus_nb; |
213 | struct work_struct vbus_work; | ||
214 | unsigned long vbus_event; | ||
211 | struct notifier_block id_nb; | 215 | struct notifier_block id_nb; |
212 | struct delayed_work extcon_reg_dwork; | 216 | struct work_struct id_work; |
217 | unsigned long id_event; | ||
213 | bool is_u3_drd; | 218 | bool is_u3_drd; |
214 | bool manual_drd_enabled; | 219 | bool manual_drd_enabled; |
215 | }; | 220 | }; |
diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c index b1b99a8f6a7a..eecfd0671362 100644 --- a/drivers/usb/mtu3/mtu3_core.c +++ b/drivers/usb/mtu3/mtu3_core.c | |||
@@ -176,7 +176,7 @@ static void mtu3_intr_enable(struct mtu3 *mtu) | |||
176 | mtu3_writel(mbase, U3D_LV1IESR, value); | 176 | mtu3_writel(mbase, U3D_LV1IESR, value); |
177 | 177 | ||
178 | /* Enable U2 common USB interrupts */ | 178 | /* Enable U2 common USB interrupts */ |
179 | value = SUSPEND_INTR | RESUME_INTR | RESET_INTR; | 179 | value = SUSPEND_INTR | RESUME_INTR | RESET_INTR | LPM_RESUME_INTR; |
180 | mtu3_writel(mbase, U3D_COMMON_USB_INTR_ENABLE, value); | 180 | mtu3_writel(mbase, U3D_COMMON_USB_INTR_ENABLE, value); |
181 | 181 | ||
182 | if (mtu->is_u3_ip) { | 182 | if (mtu->is_u3_ip) { |
@@ -195,6 +195,16 @@ static void mtu3_intr_enable(struct mtu3 *mtu) | |||
195 | mtu3_writel(mbase, U3D_DEV_LINK_INTR_ENABLE, SSUSB_DEV_SPEED_CHG_INTR); | 195 | mtu3_writel(mbase, U3D_DEV_LINK_INTR_ENABLE, SSUSB_DEV_SPEED_CHG_INTR); |
196 | } | 196 | } |
197 | 197 | ||
198 | /* reset: u2 - data toggle, u3 - SeqN, flow control status etc */ | ||
199 | static void mtu3_ep_reset(struct mtu3_ep *mep) | ||
200 | { | ||
201 | struct mtu3 *mtu = mep->mtu; | ||
202 | u32 rst_bit = EP_RST(mep->is_in, mep->epnum); | ||
203 | |||
204 | mtu3_setbits(mtu->mac_base, U3D_EP_RST, rst_bit); | ||
205 | mtu3_clrbits(mtu->mac_base, U3D_EP_RST, rst_bit); | ||
206 | } | ||
207 | |||
198 | /* set/clear the stall and toggle bits for non-ep0 */ | 208 | /* set/clear the stall and toggle bits for non-ep0 */ |
199 | void mtu3_ep_stall_set(struct mtu3_ep *mep, bool set) | 209 | void mtu3_ep_stall_set(struct mtu3_ep *mep, bool set) |
200 | { | 210 | { |
@@ -220,8 +230,7 @@ void mtu3_ep_stall_set(struct mtu3_ep *mep, bool set) | |||
220 | } | 230 | } |
221 | 231 | ||
222 | if (!set) { | 232 | if (!set) { |
223 | mtu3_setbits(mbase, U3D_EP_RST, EP_RST(mep->is_in, epnum)); | 233 | mtu3_ep_reset(mep); |
224 | mtu3_clrbits(mbase, U3D_EP_RST, EP_RST(mep->is_in, epnum)); | ||
225 | mep->flags &= ~MTU3_EP_STALL; | 234 | mep->flags &= ~MTU3_EP_STALL; |
226 | } else { | 235 | } else { |
227 | mep->flags |= MTU3_EP_STALL; | 236 | mep->flags |= MTU3_EP_STALL; |
@@ -400,6 +409,7 @@ void mtu3_deconfig_ep(struct mtu3 *mtu, struct mtu3_ep *mep) | |||
400 | mtu3_setbits(mbase, U3D_QIECR0, QMU_RX_DONE_INT(epnum)); | 409 | mtu3_setbits(mbase, U3D_QIECR0, QMU_RX_DONE_INT(epnum)); |
401 | } | 410 | } |
402 | 411 | ||
412 | mtu3_ep_reset(mep); | ||
403 | ep_fifo_free(mep); | 413 | ep_fifo_free(mep); |
404 | 414 | ||
405 | dev_dbg(mtu->dev, "%s: %s\n", __func__, mep->name); | 415 | dev_dbg(mtu->dev, "%s: %s\n", __func__, mep->name); |
@@ -658,8 +668,10 @@ static irqreturn_t mtu3_u3_ltssm_isr(struct mtu3 *mtu) | |||
658 | if (ltssm & (HOT_RST_INTR | WARM_RST_INTR)) | 668 | if (ltssm & (HOT_RST_INTR | WARM_RST_INTR)) |
659 | mtu3_gadget_reset(mtu); | 669 | mtu3_gadget_reset(mtu); |
660 | 670 | ||
661 | if (ltssm & VBUS_FALL_INTR) | 671 | if (ltssm & VBUS_FALL_INTR) { |
662 | mtu3_ss_func_set(mtu, false); | 672 | mtu3_ss_func_set(mtu, false); |
673 | mtu3_gadget_reset(mtu); | ||
674 | } | ||
663 | 675 | ||
664 | if (ltssm & VBUS_RISE_INTR) | 676 | if (ltssm & VBUS_RISE_INTR) |
665 | mtu3_ss_func_set(mtu, true); | 677 | mtu3_ss_func_set(mtu, true); |
@@ -692,6 +704,12 @@ static irqreturn_t mtu3_u2_common_isr(struct mtu3 *mtu) | |||
692 | if (u2comm & RESET_INTR) | 704 | if (u2comm & RESET_INTR) |
693 | mtu3_gadget_reset(mtu); | 705 | mtu3_gadget_reset(mtu); |
694 | 706 | ||
707 | if (u2comm & LPM_RESUME_INTR) { | ||
708 | if (!(mtu3_readl(mbase, U3D_POWER_MANAGEMENT) & LPM_HRWE)) | ||
709 | mtu3_setbits(mbase, U3D_USB20_MISC_CONTROL, | ||
710 | LPM_U3_ACK_EN); | ||
711 | } | ||
712 | |||
695 | return IRQ_HANDLED; | 713 | return IRQ_HANDLED; |
696 | } | 714 | } |
697 | 715 | ||
diff --git a/drivers/usb/mtu3/mtu3_dr.c b/drivers/usb/mtu3/mtu3_dr.c index db7562d99b95..ac60e9c8564e 100644 --- a/drivers/usb/mtu3/mtu3_dr.c +++ b/drivers/usb/mtu3/mtu3_dr.c | |||
@@ -174,16 +174,40 @@ static void ssusb_set_mailbox(struct otg_switch_mtk *otg_sx, | |||
174 | } | 174 | } |
175 | } | 175 | } |
176 | 176 | ||
177 | static int ssusb_id_notifier(struct notifier_block *nb, | 177 | static void ssusb_id_work(struct work_struct *work) |
178 | unsigned long event, void *ptr) | ||
179 | { | 178 | { |
180 | struct otg_switch_mtk *otg_sx = | 179 | struct otg_switch_mtk *otg_sx = |
181 | container_of(nb, struct otg_switch_mtk, id_nb); | 180 | container_of(work, struct otg_switch_mtk, id_work); |
182 | 181 | ||
183 | if (event) | 182 | if (otg_sx->id_event) |
184 | ssusb_set_mailbox(otg_sx, MTU3_ID_GROUND); | 183 | ssusb_set_mailbox(otg_sx, MTU3_ID_GROUND); |
185 | else | 184 | else |
186 | ssusb_set_mailbox(otg_sx, MTU3_ID_FLOAT); | 185 | ssusb_set_mailbox(otg_sx, MTU3_ID_FLOAT); |
186 | } | ||
187 | |||
188 | static void ssusb_vbus_work(struct work_struct *work) | ||
189 | { | ||
190 | struct otg_switch_mtk *otg_sx = | ||
191 | container_of(work, struct otg_switch_mtk, vbus_work); | ||
192 | |||
193 | if (otg_sx->vbus_event) | ||
194 | ssusb_set_mailbox(otg_sx, MTU3_VBUS_VALID); | ||
195 | else | ||
196 | ssusb_set_mailbox(otg_sx, MTU3_VBUS_OFF); | ||
197 | } | ||
198 | |||
199 | /* | ||
200 | * @ssusb_id_notifier is called in atomic context, but @ssusb_set_mailbox | ||
201 | * may sleep, so use work queue here | ||
202 | */ | ||
203 | static int ssusb_id_notifier(struct notifier_block *nb, | ||
204 | unsigned long event, void *ptr) | ||
205 | { | ||
206 | struct otg_switch_mtk *otg_sx = | ||
207 | container_of(nb, struct otg_switch_mtk, id_nb); | ||
208 | |||
209 | otg_sx->id_event = event; | ||
210 | schedule_work(&otg_sx->id_work); | ||
187 | 211 | ||
188 | return NOTIFY_DONE; | 212 | return NOTIFY_DONE; |
189 | } | 213 | } |
@@ -194,10 +218,8 @@ static int ssusb_vbus_notifier(struct notifier_block *nb, | |||
194 | struct otg_switch_mtk *otg_sx = | 218 | struct otg_switch_mtk *otg_sx = |
195 | container_of(nb, struct otg_switch_mtk, vbus_nb); | 219 | container_of(nb, struct otg_switch_mtk, vbus_nb); |
196 | 220 | ||
197 | if (event) | 221 | otg_sx->vbus_event = event; |
198 | ssusb_set_mailbox(otg_sx, MTU3_VBUS_VALID); | 222 | schedule_work(&otg_sx->vbus_work); |
199 | else | ||
200 | ssusb_set_mailbox(otg_sx, MTU3_VBUS_OFF); | ||
201 | 223 | ||
202 | return NOTIFY_DONE; | 224 | return NOTIFY_DONE; |
203 | } | 225 | } |
@@ -238,15 +260,6 @@ static int ssusb_extcon_register(struct otg_switch_mtk *otg_sx) | |||
238 | return 0; | 260 | return 0; |
239 | } | 261 | } |
240 | 262 | ||
241 | static void extcon_register_dwork(struct work_struct *work) | ||
242 | { | ||
243 | struct delayed_work *dwork = to_delayed_work(work); | ||
244 | struct otg_switch_mtk *otg_sx = | ||
245 | container_of(dwork, struct otg_switch_mtk, extcon_reg_dwork); | ||
246 | |||
247 | ssusb_extcon_register(otg_sx); | ||
248 | } | ||
249 | |||
250 | /* | 263 | /* |
251 | * We provide an interface via debugfs to switch between host and device modes | 264 | * We provide an interface via debugfs to switch between host and device modes |
252 | * depending on user input. | 265 | * depending on user input. |
@@ -365,10 +378,6 @@ static void ssusb_debugfs_init(struct ssusb_mtk *ssusb) | |||
365 | struct dentry *root; | 378 | struct dentry *root; |
366 | 379 | ||
367 | root = debugfs_create_dir(dev_name(ssusb->dev), usb_debug_root); | 380 | root = debugfs_create_dir(dev_name(ssusb->dev), usb_debug_root); |
368 | if (!root) { | ||
369 | dev_err(ssusb->dev, "create debugfs root failed\n"); | ||
370 | return; | ||
371 | } | ||
372 | ssusb->dbgfs_root = root; | 381 | ssusb->dbgfs_root = root; |
373 | 382 | ||
374 | debugfs_create_file("mode", 0644, root, ssusb, &ssusb_mode_fops); | 383 | debugfs_create_file("mode", 0644, root, ssusb, &ssusb_mode_fops); |
@@ -407,18 +416,13 @@ int ssusb_otg_switch_init(struct ssusb_mtk *ssusb) | |||
407 | { | 416 | { |
408 | struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; | 417 | struct otg_switch_mtk *otg_sx = &ssusb->otg_switch; |
409 | 418 | ||
410 | if (otg_sx->manual_drd_enabled) { | 419 | INIT_WORK(&otg_sx->id_work, ssusb_id_work); |
420 | INIT_WORK(&otg_sx->vbus_work, ssusb_vbus_work); | ||
421 | |||
422 | if (otg_sx->manual_drd_enabled) | ||
411 | ssusb_debugfs_init(ssusb); | 423 | ssusb_debugfs_init(ssusb); |
412 | } else { | 424 | else |
413 | INIT_DELAYED_WORK(&otg_sx->extcon_reg_dwork, | 425 | ssusb_extcon_register(otg_sx); |
414 | extcon_register_dwork); | ||
415 | |||
416 | /* | ||
417 | * It is enough to delay 1s for waiting for | ||
418 | * host initialization | ||
419 | */ | ||
420 | schedule_delayed_work(&otg_sx->extcon_reg_dwork, HZ); | ||
421 | } | ||
422 | 426 | ||
423 | return 0; | 427 | return 0; |
424 | } | 428 | } |
@@ -429,6 +433,7 @@ void ssusb_otg_switch_exit(struct ssusb_mtk *ssusb) | |||
429 | 433 | ||
430 | if (otg_sx->manual_drd_enabled) | 434 | if (otg_sx->manual_drd_enabled) |
431 | ssusb_debugfs_exit(ssusb); | 435 | ssusb_debugfs_exit(ssusb); |
432 | else | 436 | |
433 | cancel_delayed_work(&otg_sx->extcon_reg_dwork); | 437 | cancel_work_sync(&otg_sx->id_work); |
438 | cancel_work_sync(&otg_sx->vbus_work); | ||
434 | } | 439 | } |
diff --git a/drivers/usb/mtu3/mtu3_gadget.c b/drivers/usb/mtu3/mtu3_gadget.c index f05f10f5c171..5c60a8c5a0b5 100644 --- a/drivers/usb/mtu3/mtu3_gadget.c +++ b/drivers/usb/mtu3/mtu3_gadget.c | |||
@@ -660,14 +660,10 @@ int mtu3_gadget_setup(struct mtu3 *mtu) | |||
660 | mtu3_gadget_init_eps(mtu); | 660 | mtu3_gadget_init_eps(mtu); |
661 | 661 | ||
662 | ret = usb_add_gadget_udc(mtu->dev, &mtu->g); | 662 | ret = usb_add_gadget_udc(mtu->dev, &mtu->g); |
663 | if (ret) { | 663 | if (ret) |
664 | dev_err(mtu->dev, "failed to register udc\n"); | 664 | dev_err(mtu->dev, "failed to register udc\n"); |
665 | return ret; | ||
666 | } | ||
667 | 665 | ||
668 | usb_gadget_set_state(&mtu->g, USB_STATE_NOTATTACHED); | 666 | return ret; |
669 | |||
670 | return 0; | ||
671 | } | 667 | } |
672 | 668 | ||
673 | void mtu3_gadget_cleanup(struct mtu3 *mtu) | 669 | void mtu3_gadget_cleanup(struct mtu3 *mtu) |
@@ -723,4 +719,5 @@ void mtu3_gadget_reset(struct mtu3 *mtu) | |||
723 | mtu->u1_enable = 0; | 719 | mtu->u1_enable = 0; |
724 | mtu->u2_enable = 0; | 720 | mtu->u2_enable = 0; |
725 | mtu->delayed_status = false; | 721 | mtu->delayed_status = false; |
722 | mtu->test_mode = false; | ||
726 | } | 723 | } |
diff --git a/drivers/usb/mtu3/mtu3_gadget_ep0.c b/drivers/usb/mtu3/mtu3_gadget_ep0.c index ebdcf7a38c29..25216e79cd6e 100644 --- a/drivers/usb/mtu3/mtu3_gadget_ep0.c +++ b/drivers/usb/mtu3/mtu3_gadget_ep0.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * Author: Chunfeng.Yun <chunfeng.yun@mediatek.com> | 7 | * Author: Chunfeng.Yun <chunfeng.yun@mediatek.com> |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/iopoll.h> | ||
10 | #include <linux/usb/composite.h> | 11 | #include <linux/usb/composite.h> |
11 | 12 | ||
12 | #include "mtu3.h" | 13 | #include "mtu3.h" |
@@ -263,6 +264,7 @@ static int handle_test_mode(struct mtu3 *mtu, struct usb_ctrlrequest *setup) | |||
263 | { | 264 | { |
264 | void __iomem *mbase = mtu->mac_base; | 265 | void __iomem *mbase = mtu->mac_base; |
265 | int handled = 1; | 266 | int handled = 1; |
267 | u32 value; | ||
266 | 268 | ||
267 | switch (le16_to_cpu(setup->wIndex) >> 8) { | 269 | switch (le16_to_cpu(setup->wIndex) >> 8) { |
268 | case TEST_J: | 270 | case TEST_J: |
@@ -292,6 +294,14 @@ static int handle_test_mode(struct mtu3 *mtu, struct usb_ctrlrequest *setup) | |||
292 | if (mtu->test_mode_nr == TEST_PACKET_MODE) | 294 | if (mtu->test_mode_nr == TEST_PACKET_MODE) |
293 | ep0_load_test_packet(mtu); | 295 | ep0_load_test_packet(mtu); |
294 | 296 | ||
297 | /* send status before entering test mode. */ | ||
298 | value = mtu3_readl(mbase, U3D_EP0CSR) & EP0_W1C_BITS; | ||
299 | mtu3_writel(mbase, U3D_EP0CSR, value | EP0_SETUPPKTRDY | EP0_DATAEND); | ||
300 | |||
301 | /* wait for ACK status sent by host */ | ||
302 | readl_poll_timeout_atomic(mbase + U3D_EP0CSR, value, | ||
303 | !(value & EP0_DATAEND), 100, 5000); | ||
304 | |||
295 | mtu3_writel(mbase, U3D_USB2_TEST_MODE, mtu->test_mode_nr); | 305 | mtu3_writel(mbase, U3D_USB2_TEST_MODE, mtu->test_mode_nr); |
296 | 306 | ||
297 | mtu->ep0_state = MU3D_EP0_STATE_SETUP; | 307 | mtu->ep0_state = MU3D_EP0_STATE_SETUP; |
@@ -546,7 +556,7 @@ static void ep0_tx_state(struct mtu3 *mtu) | |||
546 | struct usb_request *req; | 556 | struct usb_request *req; |
547 | u32 csr; | 557 | u32 csr; |
548 | u8 *src; | 558 | u8 *src; |
549 | u8 count; | 559 | u32 count; |
550 | u32 maxp; | 560 | u32 maxp; |
551 | 561 | ||
552 | dev_dbg(mtu->dev, "%s\n", __func__); | 562 | dev_dbg(mtu->dev, "%s\n", __func__); |
diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c index 628d5ce356ca..46551f6d16fd 100644 --- a/drivers/usb/mtu3/mtu3_plat.c +++ b/drivers/usb/mtu3/mtu3_plat.c | |||
@@ -447,8 +447,7 @@ static int mtu3_remove(struct platform_device *pdev) | |||
447 | */ | 447 | */ |
448 | static int __maybe_unused mtu3_suspend(struct device *dev) | 448 | static int __maybe_unused mtu3_suspend(struct device *dev) |
449 | { | 449 | { |
450 | struct platform_device *pdev = to_platform_device(dev); | 450 | struct ssusb_mtk *ssusb = dev_get_drvdata(dev); |
451 | struct ssusb_mtk *ssusb = platform_get_drvdata(pdev); | ||
452 | 451 | ||
453 | dev_dbg(dev, "%s\n", __func__); | 452 | dev_dbg(dev, "%s\n", __func__); |
454 | 453 | ||
@@ -466,8 +465,7 @@ static int __maybe_unused mtu3_suspend(struct device *dev) | |||
466 | 465 | ||
467 | static int __maybe_unused mtu3_resume(struct device *dev) | 466 | static int __maybe_unused mtu3_resume(struct device *dev) |
468 | { | 467 | { |
469 | struct platform_device *pdev = to_platform_device(dev); | 468 | struct ssusb_mtk *ssusb = dev_get_drvdata(dev); |
470 | struct ssusb_mtk *ssusb = platform_get_drvdata(pdev); | ||
471 | int ret; | 469 | int ret; |
472 | 470 | ||
473 | dev_dbg(dev, "%s\n", __func__); | 471 | dev_dbg(dev, "%s\n", __func__); |
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c index 0ad664efda6b..660641ab1545 100644 --- a/drivers/usb/musb/am35x.c +++ b/drivers/usb/musb/am35x.c | |||
@@ -201,7 +201,6 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci) | |||
201 | struct device *dev = musb->controller; | 201 | struct device *dev = musb->controller; |
202 | struct musb_hdrc_platform_data *plat = dev_get_platdata(dev); | 202 | struct musb_hdrc_platform_data *plat = dev_get_platdata(dev); |
203 | struct omap_musb_board_data *data = plat->board_data; | 203 | struct omap_musb_board_data *data = plat->board_data; |
204 | struct usb_otg *otg = musb->xceiv->otg; | ||
205 | unsigned long flags; | 204 | unsigned long flags; |
206 | irqreturn_t ret = IRQ_NONE; | 205 | irqreturn_t ret = IRQ_NONE; |
207 | u32 epintr, usbintr; | 206 | u32 epintr, usbintr; |
@@ -264,14 +263,12 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci) | |||
264 | WARNING("VBUS error workaround (delay coming)\n"); | 263 | WARNING("VBUS error workaround (delay coming)\n"); |
265 | } else if (drvvbus) { | 264 | } else if (drvvbus) { |
266 | MUSB_HST_MODE(musb); | 265 | MUSB_HST_MODE(musb); |
267 | otg->default_a = 1; | ||
268 | musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; | 266 | musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; |
269 | portstate(musb->port1_status |= USB_PORT_STAT_POWER); | 267 | portstate(musb->port1_status |= USB_PORT_STAT_POWER); |
270 | del_timer(&musb->dev_timer); | 268 | del_timer(&musb->dev_timer); |
271 | } else { | 269 | } else { |
272 | musb->is_active = 0; | 270 | musb->is_active = 0; |
273 | MUSB_DEV_MODE(musb); | 271 | MUSB_DEV_MODE(musb); |
274 | otg->default_a = 0; | ||
275 | musb->xceiv->otg->state = OTG_STATE_B_IDLE; | 272 | musb->xceiv->otg->state = OTG_STATE_B_IDLE; |
276 | portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); | 273 | portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); |
277 | } | 274 | } |
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c index b8295ce7c4fe..1c023c0091c4 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c | |||
@@ -223,7 +223,6 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) | |||
223 | { | 223 | { |
224 | struct musb *musb = hci; | 224 | struct musb *musb = hci; |
225 | void __iomem *reg_base = musb->ctrl_base; | 225 | void __iomem *reg_base = musb->ctrl_base; |
226 | struct usb_otg *otg = musb->xceiv->otg; | ||
227 | unsigned long flags; | 226 | unsigned long flags; |
228 | irqreturn_t ret = IRQ_NONE; | 227 | irqreturn_t ret = IRQ_NONE; |
229 | u32 status; | 228 | u32 status; |
@@ -280,7 +279,6 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) | |||
280 | WARNING("VBUS error workaround (delay coming)\n"); | 279 | WARNING("VBUS error workaround (delay coming)\n"); |
281 | } else if (drvvbus) { | 280 | } else if (drvvbus) { |
282 | MUSB_HST_MODE(musb); | 281 | MUSB_HST_MODE(musb); |
283 | otg->default_a = 1; | ||
284 | musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; | 282 | musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; |
285 | portstate(musb->port1_status |= USB_PORT_STAT_POWER); | 283 | portstate(musb->port1_status |= USB_PORT_STAT_POWER); |
286 | del_timer(&musb->dev_timer); | 284 | del_timer(&musb->dev_timer); |
@@ -295,7 +293,6 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) | |||
295 | */ | 293 | */ |
296 | musb->is_active = 0; | 294 | musb->is_active = 0; |
297 | MUSB_DEV_MODE(musb); | 295 | MUSB_DEV_MODE(musb); |
298 | otg->default_a = 0; | ||
299 | musb->xceiv->otg->state = OTG_STATE_B_IDLE; | 296 | musb->xceiv->otg->state = OTG_STATE_B_IDLE; |
300 | portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); | 297 | portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); |
301 | } | 298 | } |
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 2ad39dcd2f4c..fb6bbd254ab7 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c | |||
@@ -311,14 +311,12 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci) | |||
311 | WARNING("VBUS error workaround (delay coming)\n"); | 311 | WARNING("VBUS error workaround (delay coming)\n"); |
312 | } else if (drvvbus) { | 312 | } else if (drvvbus) { |
313 | MUSB_HST_MODE(musb); | 313 | MUSB_HST_MODE(musb); |
314 | otg->default_a = 1; | ||
315 | musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; | 314 | musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; |
316 | portstate(musb->port1_status |= USB_PORT_STAT_POWER); | 315 | portstate(musb->port1_status |= USB_PORT_STAT_POWER); |
317 | del_timer(&musb->dev_timer); | 316 | del_timer(&musb->dev_timer); |
318 | } else { | 317 | } else { |
319 | musb->is_active = 0; | 318 | musb->is_active = 0; |
320 | MUSB_DEV_MODE(musb); | 319 | MUSB_DEV_MODE(musb); |
321 | otg->default_a = 0; | ||
322 | musb->xceiv->otg->state = OTG_STATE_B_IDLE; | 320 | musb->xceiv->otg->state = OTG_STATE_B_IDLE; |
323 | portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); | 321 | portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); |
324 | } | 322 | } |
@@ -425,6 +423,9 @@ unregister: | |||
425 | 423 | ||
426 | static int davinci_musb_exit(struct musb *musb) | 424 | static int davinci_musb_exit(struct musb *musb) |
427 | { | 425 | { |
426 | int maxdelay = 30; | ||
427 | u8 devctl, warn = 0; | ||
428 | |||
428 | del_timer_sync(&musb->dev_timer); | 429 | del_timer_sync(&musb->dev_timer); |
429 | 430 | ||
430 | /* force VBUS off */ | 431 | /* force VBUS off */ |
@@ -438,31 +439,27 @@ static int davinci_musb_exit(struct musb *musb) | |||
438 | 439 | ||
439 | davinci_musb_source_power(musb, 0 /*off*/, 1); | 440 | davinci_musb_source_power(musb, 0 /*off*/, 1); |
440 | 441 | ||
441 | /* delay, to avoid problems with module reload */ | 442 | /* |
442 | if (musb->xceiv->otg->default_a) { | 443 | * delay, to avoid problems with module reload. |
443 | int maxdelay = 30; | 444 | * if there's no peripheral connected, this can take a |
444 | u8 devctl, warn = 0; | 445 | * long time to fall, especially on EVM with huge C133. |
446 | */ | ||
447 | do { | ||
448 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | ||
449 | if (!(devctl & MUSB_DEVCTL_VBUS)) | ||
450 | break; | ||
451 | if ((devctl & MUSB_DEVCTL_VBUS) != warn) { | ||
452 | warn = devctl & MUSB_DEVCTL_VBUS; | ||
453 | dev_dbg(musb->controller, "VBUS %d\n", | ||
454 | warn >> MUSB_DEVCTL_VBUS_SHIFT); | ||
455 | } | ||
456 | msleep(1000); | ||
457 | maxdelay--; | ||
458 | } while (maxdelay > 0); | ||
445 | 459 | ||
446 | /* if there's no peripheral connected, this can take a | 460 | /* in OTG mode, another host might be connected */ |
447 | * long time to fall, especially on EVM with huge C133. | 461 | if (devctl & MUSB_DEVCTL_VBUS) |
448 | */ | 462 | dev_dbg(musb->controller, "VBUS off timeout (devctl %02x)\n", devctl); |
449 | do { | ||
450 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | ||
451 | if (!(devctl & MUSB_DEVCTL_VBUS)) | ||
452 | break; | ||
453 | if ((devctl & MUSB_DEVCTL_VBUS) != warn) { | ||
454 | warn = devctl & MUSB_DEVCTL_VBUS; | ||
455 | dev_dbg(musb->controller, "VBUS %d\n", | ||
456 | warn >> MUSB_DEVCTL_VBUS_SHIFT); | ||
457 | } | ||
458 | msleep(1000); | ||
459 | maxdelay--; | ||
460 | } while (maxdelay > 0); | ||
461 | |||
462 | /* in OTG mode, another host might be connected */ | ||
463 | if (devctl & MUSB_DEVCTL_VBUS) | ||
464 | dev_dbg(musb->controller, "VBUS off timeout (devctl %02x)\n", devctl); | ||
465 | } | ||
466 | 463 | ||
467 | phy_off(); | 464 | phy_off(); |
468 | 465 | ||
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index fb5e4523dc28..b7d56272f9d1 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c | |||
@@ -274,20 +274,6 @@ static void musb_default_writew(void __iomem *addr, unsigned offset, u16 data) | |||
274 | __raw_writew(data, addr + offset); | 274 | __raw_writew(data, addr + offset); |
275 | } | 275 | } |
276 | 276 | ||
277 | static u32 musb_default_readl(const void __iomem *addr, unsigned offset) | ||
278 | { | ||
279 | u32 data = __raw_readl(addr + offset); | ||
280 | |||
281 | trace_musb_readl(__builtin_return_address(0), addr, offset, data); | ||
282 | return data; | ||
283 | } | ||
284 | |||
285 | static void musb_default_writel(void __iomem *addr, unsigned offset, u32 data) | ||
286 | { | ||
287 | trace_musb_writel(__builtin_return_address(0), addr, offset, data); | ||
288 | __raw_writel(data, addr + offset); | ||
289 | } | ||
290 | |||
291 | /* | 277 | /* |
292 | * Load an endpoint's FIFO | 278 | * Load an endpoint's FIFO |
293 | */ | 279 | */ |
@@ -390,10 +376,20 @@ EXPORT_SYMBOL_GPL(musb_readw); | |||
390 | void (*musb_writew)(void __iomem *addr, unsigned offset, u16 data); | 376 | void (*musb_writew)(void __iomem *addr, unsigned offset, u16 data); |
391 | EXPORT_SYMBOL_GPL(musb_writew); | 377 | EXPORT_SYMBOL_GPL(musb_writew); |
392 | 378 | ||
393 | u32 (*musb_readl)(const void __iomem *addr, unsigned offset); | 379 | u32 musb_readl(const void __iomem *addr, unsigned offset) |
380 | { | ||
381 | u32 data = __raw_readl(addr + offset); | ||
382 | |||
383 | trace_musb_readl(__builtin_return_address(0), addr, offset, data); | ||
384 | return data; | ||
385 | } | ||
394 | EXPORT_SYMBOL_GPL(musb_readl); | 386 | EXPORT_SYMBOL_GPL(musb_readl); |
395 | 387 | ||
396 | void (*musb_writel)(void __iomem *addr, unsigned offset, u32 data); | 388 | void musb_writel(void __iomem *addr, unsigned offset, u32 data) |
389 | { | ||
390 | trace_musb_writel(__builtin_return_address(0), addr, offset, data); | ||
391 | __raw_writel(data, addr + offset); | ||
392 | } | ||
397 | EXPORT_SYMBOL_GPL(musb_writel); | 393 | EXPORT_SYMBOL_GPL(musb_writel); |
398 | 394 | ||
399 | #ifndef CONFIG_MUSB_PIO_ONLY | 395 | #ifndef CONFIG_MUSB_PIO_ONLY |
@@ -527,6 +523,383 @@ void musb_hnp_stop(struct musb *musb) | |||
527 | 523 | ||
528 | static void musb_recover_from_babble(struct musb *musb); | 524 | static void musb_recover_from_babble(struct musb *musb); |
529 | 525 | ||
526 | static void musb_handle_intr_resume(struct musb *musb, u8 devctl) | ||
527 | { | ||
528 | musb_dbg(musb, "RESUME (%s)", | ||
529 | usb_otg_state_string(musb->xceiv->otg->state)); | ||
530 | |||
531 | if (devctl & MUSB_DEVCTL_HM) { | ||
532 | switch (musb->xceiv->otg->state) { | ||
533 | case OTG_STATE_A_SUSPEND: | ||
534 | /* remote wakeup? */ | ||
535 | musb->port1_status |= | ||
536 | (USB_PORT_STAT_C_SUSPEND << 16) | ||
537 | | MUSB_PORT_STAT_RESUME; | ||
538 | musb->rh_timer = jiffies | ||
539 | + msecs_to_jiffies(USB_RESUME_TIMEOUT); | ||
540 | musb->xceiv->otg->state = OTG_STATE_A_HOST; | ||
541 | musb->is_active = 1; | ||
542 | musb_host_resume_root_hub(musb); | ||
543 | schedule_delayed_work(&musb->finish_resume_work, | ||
544 | msecs_to_jiffies(USB_RESUME_TIMEOUT)); | ||
545 | break; | ||
546 | case OTG_STATE_B_WAIT_ACON: | ||
547 | musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL; | ||
548 | musb->is_active = 1; | ||
549 | MUSB_DEV_MODE(musb); | ||
550 | break; | ||
551 | default: | ||
552 | WARNING("bogus %s RESUME (%s)\n", | ||
553 | "host", | ||
554 | usb_otg_state_string(musb->xceiv->otg->state)); | ||
555 | } | ||
556 | } else { | ||
557 | switch (musb->xceiv->otg->state) { | ||
558 | case OTG_STATE_A_SUSPEND: | ||
559 | /* possibly DISCONNECT is upcoming */ | ||
560 | musb->xceiv->otg->state = OTG_STATE_A_HOST; | ||
561 | musb_host_resume_root_hub(musb); | ||
562 | break; | ||
563 | case OTG_STATE_B_WAIT_ACON: | ||
564 | case OTG_STATE_B_PERIPHERAL: | ||
565 | /* disconnect while suspended? we may | ||
566 | * not get a disconnect irq... | ||
567 | */ | ||
568 | if ((devctl & MUSB_DEVCTL_VBUS) | ||
569 | != (3 << MUSB_DEVCTL_VBUS_SHIFT) | ||
570 | ) { | ||
571 | musb->int_usb |= MUSB_INTR_DISCONNECT; | ||
572 | musb->int_usb &= ~MUSB_INTR_SUSPEND; | ||
573 | break; | ||
574 | } | ||
575 | musb_g_resume(musb); | ||
576 | break; | ||
577 | case OTG_STATE_B_IDLE: | ||
578 | musb->int_usb &= ~MUSB_INTR_SUSPEND; | ||
579 | break; | ||
580 | default: | ||
581 | WARNING("bogus %s RESUME (%s)\n", | ||
582 | "peripheral", | ||
583 | usb_otg_state_string(musb->xceiv->otg->state)); | ||
584 | } | ||
585 | } | ||
586 | } | ||
587 | |||
588 | /* return IRQ_HANDLED to tell the caller to return immediately */ | ||
589 | static irqreturn_t musb_handle_intr_sessreq(struct musb *musb, u8 devctl) | ||
590 | { | ||
591 | void __iomem *mbase = musb->mregs; | ||
592 | |||
593 | if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS | ||
594 | && (devctl & MUSB_DEVCTL_BDEVICE)) { | ||
595 | musb_dbg(musb, "SessReq while on B state"); | ||
596 | return IRQ_HANDLED; | ||
597 | } | ||
598 | |||
599 | musb_dbg(musb, "SESSION_REQUEST (%s)", | ||
600 | usb_otg_state_string(musb->xceiv->otg->state)); | ||
601 | |||
602 | /* IRQ arrives from ID pin sense or (later, if VBUS power | ||
603 | * is removed) SRP. responses are time critical: | ||
604 | * - turn on VBUS (with silicon-specific mechanism) | ||
605 | * - go through A_WAIT_VRISE | ||
606 | * - ... to A_WAIT_BCON. | ||
607 | * a_wait_vrise_tmout triggers VBUS_ERROR transitions | ||
608 | */ | ||
609 | musb_writeb(mbase, MUSB_DEVCTL, MUSB_DEVCTL_SESSION); | ||
610 | musb->ep0_stage = MUSB_EP0_START; | ||
611 | musb->xceiv->otg->state = OTG_STATE_A_IDLE; | ||
612 | MUSB_HST_MODE(musb); | ||
613 | musb_platform_set_vbus(musb, 1); | ||
614 | |||
615 | return IRQ_NONE; | ||
616 | } | ||
617 | |||
618 | static void musb_handle_intr_vbuserr(struct musb *musb, u8 devctl) | ||
619 | { | ||
620 | int ignore = 0; | ||
621 | |||
622 | /* During connection as an A-Device, we may see a short | ||
623 | * current spikes causing voltage drop, because of cable | ||
624 | * and peripheral capacitance combined with vbus draw. | ||
625 | * (So: less common with truly self-powered devices, where | ||
626 | * vbus doesn't act like a power supply.) | ||
627 | * | ||
628 | * Such spikes are short; usually less than ~500 usec, max | ||
629 | * of ~2 msec. That is, they're not sustained overcurrent | ||
630 | * errors, though they're reported using VBUSERROR irqs. | ||
631 | * | ||
632 | * Workarounds: (a) hardware: use self powered devices. | ||
633 | * (b) software: ignore non-repeated VBUS errors. | ||
634 | * | ||
635 | * REVISIT: do delays from lots of DEBUG_KERNEL checks | ||
636 | * make trouble here, keeping VBUS < 4.4V ? | ||
637 | */ | ||
638 | switch (musb->xceiv->otg->state) { | ||
639 | case OTG_STATE_A_HOST: | ||
640 | /* recovery is dicey once we've gotten past the | ||
641 | * initial stages of enumeration, but if VBUS | ||
642 | * stayed ok at the other end of the link, and | ||
643 | * another reset is due (at least for high speed, | ||
644 | * to redo the chirp etc), it might work OK... | ||
645 | */ | ||
646 | case OTG_STATE_A_WAIT_BCON: | ||
647 | case OTG_STATE_A_WAIT_VRISE: | ||
648 | if (musb->vbuserr_retry) { | ||
649 | void __iomem *mbase = musb->mregs; | ||
650 | |||
651 | musb->vbuserr_retry--; | ||
652 | ignore = 1; | ||
653 | devctl |= MUSB_DEVCTL_SESSION; | ||
654 | musb_writeb(mbase, MUSB_DEVCTL, devctl); | ||
655 | } else { | ||
656 | musb->port1_status |= | ||
657 | USB_PORT_STAT_OVERCURRENT | ||
658 | | (USB_PORT_STAT_C_OVERCURRENT << 16); | ||
659 | } | ||
660 | break; | ||
661 | default: | ||
662 | break; | ||
663 | } | ||
664 | |||
665 | dev_printk(ignore ? KERN_DEBUG : KERN_ERR, musb->controller, | ||
666 | "VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n", | ||
667 | usb_otg_state_string(musb->xceiv->otg->state), | ||
668 | devctl, | ||
669 | ({ char *s; | ||
670 | switch (devctl & MUSB_DEVCTL_VBUS) { | ||
671 | case 0 << MUSB_DEVCTL_VBUS_SHIFT: | ||
672 | s = "<SessEnd"; break; | ||
673 | case 1 << MUSB_DEVCTL_VBUS_SHIFT: | ||
674 | s = "<AValid"; break; | ||
675 | case 2 << MUSB_DEVCTL_VBUS_SHIFT: | ||
676 | s = "<VBusValid"; break; | ||
677 | /* case 3 << MUSB_DEVCTL_VBUS_SHIFT: */ | ||
678 | default: | ||
679 | s = "VALID"; break; | ||
680 | } s; }), | ||
681 | VBUSERR_RETRY_COUNT - musb->vbuserr_retry, | ||
682 | musb->port1_status); | ||
683 | |||
684 | /* go through A_WAIT_VFALL then start a new session */ | ||
685 | if (!ignore) | ||
686 | musb_platform_set_vbus(musb, 0); | ||
687 | } | ||
688 | |||
689 | static void musb_handle_intr_suspend(struct musb *musb, u8 devctl) | ||
690 | { | ||
691 | musb_dbg(musb, "SUSPEND (%s) devctl %02x", | ||
692 | usb_otg_state_string(musb->xceiv->otg->state), devctl); | ||
693 | |||
694 | switch (musb->xceiv->otg->state) { | ||
695 | case OTG_STATE_A_PERIPHERAL: | ||
696 | /* We also come here if the cable is removed, since | ||
697 | * this silicon doesn't report ID-no-longer-grounded. | ||
698 | * | ||
699 | * We depend on T(a_wait_bcon) to shut us down, and | ||
700 | * hope users don't do anything dicey during this | ||
701 | * undesired detour through A_WAIT_BCON. | ||
702 | */ | ||
703 | musb_hnp_stop(musb); | ||
704 | musb_host_resume_root_hub(musb); | ||
705 | musb_root_disconnect(musb); | ||
706 | musb_platform_try_idle(musb, jiffies | ||
707 | + msecs_to_jiffies(musb->a_wait_bcon | ||
708 | ? : OTG_TIME_A_WAIT_BCON)); | ||
709 | |||
710 | break; | ||
711 | case OTG_STATE_B_IDLE: | ||
712 | if (!musb->is_active) | ||
713 | break; | ||
714 | /* fall through */ | ||
715 | case OTG_STATE_B_PERIPHERAL: | ||
716 | musb_g_suspend(musb); | ||
717 | musb->is_active = musb->g.b_hnp_enable; | ||
718 | if (musb->is_active) { | ||
719 | musb->xceiv->otg->state = OTG_STATE_B_WAIT_ACON; | ||
720 | musb_dbg(musb, "HNP: Setting timer for b_ase0_brst"); | ||
721 | mod_timer(&musb->otg_timer, jiffies | ||
722 | + msecs_to_jiffies( | ||
723 | OTG_TIME_B_ASE0_BRST)); | ||
724 | } | ||
725 | break; | ||
726 | case OTG_STATE_A_WAIT_BCON: | ||
727 | if (musb->a_wait_bcon != 0) | ||
728 | musb_platform_try_idle(musb, jiffies | ||
729 | + msecs_to_jiffies(musb->a_wait_bcon)); | ||
730 | break; | ||
731 | case OTG_STATE_A_HOST: | ||
732 | musb->xceiv->otg->state = OTG_STATE_A_SUSPEND; | ||
733 | musb->is_active = musb->hcd->self.b_hnp_enable; | ||
734 | break; | ||
735 | case OTG_STATE_B_HOST: | ||
736 | /* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */ | ||
737 | musb_dbg(musb, "REVISIT: SUSPEND as B_HOST"); | ||
738 | break; | ||
739 | default: | ||
740 | /* "should not happen" */ | ||
741 | musb->is_active = 0; | ||
742 | break; | ||
743 | } | ||
744 | } | ||
745 | |||
746 | static void musb_handle_intr_connect(struct musb *musb, u8 devctl, u8 int_usb) | ||
747 | { | ||
748 | struct usb_hcd *hcd = musb->hcd; | ||
749 | |||
750 | musb->is_active = 1; | ||
751 | musb->ep0_stage = MUSB_EP0_START; | ||
752 | |||
753 | musb->intrtxe = musb->epmask; | ||
754 | musb_writew(musb->mregs, MUSB_INTRTXE, musb->intrtxe); | ||
755 | musb->intrrxe = musb->epmask & 0xfffe; | ||
756 | musb_writew(musb->mregs, MUSB_INTRRXE, musb->intrrxe); | ||
757 | musb_writeb(musb->mregs, MUSB_INTRUSBE, 0xf7); | ||
758 | musb->port1_status &= ~(USB_PORT_STAT_LOW_SPEED | ||
759 | |USB_PORT_STAT_HIGH_SPEED | ||
760 | |USB_PORT_STAT_ENABLE | ||
761 | ); | ||
762 | musb->port1_status |= USB_PORT_STAT_CONNECTION | ||
763 | |(USB_PORT_STAT_C_CONNECTION << 16); | ||
764 | |||
765 | /* high vs full speed is just a guess until after reset */ | ||
766 | if (devctl & MUSB_DEVCTL_LSDEV) | ||
767 | musb->port1_status |= USB_PORT_STAT_LOW_SPEED; | ||
768 | |||
769 | /* indicate new connection to OTG machine */ | ||
770 | switch (musb->xceiv->otg->state) { | ||
771 | case OTG_STATE_B_PERIPHERAL: | ||
772 | if (int_usb & MUSB_INTR_SUSPEND) { | ||
773 | musb_dbg(musb, "HNP: SUSPEND+CONNECT, now b_host"); | ||
774 | int_usb &= ~MUSB_INTR_SUSPEND; | ||
775 | goto b_host; | ||
776 | } else | ||
777 | musb_dbg(musb, "CONNECT as b_peripheral???"); | ||
778 | break; | ||
779 | case OTG_STATE_B_WAIT_ACON: | ||
780 | musb_dbg(musb, "HNP: CONNECT, now b_host"); | ||
781 | b_host: | ||
782 | musb->xceiv->otg->state = OTG_STATE_B_HOST; | ||
783 | if (musb->hcd) | ||
784 | musb->hcd->self.is_b_host = 1; | ||
785 | del_timer(&musb->otg_timer); | ||
786 | break; | ||
787 | default: | ||
788 | if ((devctl & MUSB_DEVCTL_VBUS) | ||
789 | == (3 << MUSB_DEVCTL_VBUS_SHIFT)) { | ||
790 | musb->xceiv->otg->state = OTG_STATE_A_HOST; | ||
791 | if (hcd) | ||
792 | hcd->self.is_b_host = 0; | ||
793 | } | ||
794 | break; | ||
795 | } | ||
796 | |||
797 | musb_host_poke_root_hub(musb); | ||
798 | |||
799 | musb_dbg(musb, "CONNECT (%s) devctl %02x", | ||
800 | usb_otg_state_string(musb->xceiv->otg->state), devctl); | ||
801 | } | ||
802 | |||
803 | static void musb_handle_intr_disconnect(struct musb *musb, u8 devctl) | ||
804 | { | ||
805 | musb_dbg(musb, "DISCONNECT (%s) as %s, devctl %02x", | ||
806 | usb_otg_state_string(musb->xceiv->otg->state), | ||
807 | MUSB_MODE(musb), devctl); | ||
808 | |||
809 | switch (musb->xceiv->otg->state) { | ||
810 | case OTG_STATE_A_HOST: | ||
811 | case OTG_STATE_A_SUSPEND: | ||
812 | musb_host_resume_root_hub(musb); | ||
813 | musb_root_disconnect(musb); | ||
814 | if (musb->a_wait_bcon != 0) | ||
815 | musb_platform_try_idle(musb, jiffies | ||
816 | + msecs_to_jiffies(musb->a_wait_bcon)); | ||
817 | break; | ||
818 | case OTG_STATE_B_HOST: | ||
819 | /* REVISIT this behaves for "real disconnect" | ||
820 | * cases; make sure the other transitions from | ||
821 | * from B_HOST act right too. The B_HOST code | ||
822 | * in hnp_stop() is currently not used... | ||
823 | */ | ||
824 | musb_root_disconnect(musb); | ||
825 | if (musb->hcd) | ||
826 | musb->hcd->self.is_b_host = 0; | ||
827 | musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL; | ||
828 | MUSB_DEV_MODE(musb); | ||
829 | musb_g_disconnect(musb); | ||
830 | break; | ||
831 | case OTG_STATE_A_PERIPHERAL: | ||
832 | musb_hnp_stop(musb); | ||
833 | musb_root_disconnect(musb); | ||
834 | /* FALLTHROUGH */ | ||
835 | case OTG_STATE_B_WAIT_ACON: | ||
836 | /* FALLTHROUGH */ | ||
837 | case OTG_STATE_B_PERIPHERAL: | ||
838 | case OTG_STATE_B_IDLE: | ||
839 | musb_g_disconnect(musb); | ||
840 | break; | ||
841 | default: | ||
842 | WARNING("unhandled DISCONNECT transition (%s)\n", | ||
843 | usb_otg_state_string(musb->xceiv->otg->state)); | ||
844 | break; | ||
845 | } | ||
846 | } | ||
847 | |||
848 | /* | ||
849 | * mentor saves a bit: bus reset and babble share the same irq. | ||
850 | * only host sees babble; only peripheral sees bus reset. | ||
851 | */ | ||
852 | static void musb_handle_intr_reset(struct musb *musb) | ||
853 | { | ||
854 | if (is_host_active(musb)) { | ||
855 | /* | ||
856 | * When BABBLE happens what we can depends on which | ||
857 | * platform MUSB is running, because some platforms | ||
858 | * implemented proprietary means for 'recovering' from | ||
859 | * Babble conditions. One such platform is AM335x. In | ||
860 | * most cases, however, the only thing we can do is | ||
861 | * drop the session. | ||
862 | */ | ||
863 | dev_err(musb->controller, "Babble\n"); | ||
864 | musb_recover_from_babble(musb); | ||
865 | } else { | ||
866 | musb_dbg(musb, "BUS RESET as %s", | ||
867 | usb_otg_state_string(musb->xceiv->otg->state)); | ||
868 | switch (musb->xceiv->otg->state) { | ||
869 | case OTG_STATE_A_SUSPEND: | ||
870 | musb_g_reset(musb); | ||
871 | /* FALLTHROUGH */ | ||
872 | case OTG_STATE_A_WAIT_BCON: /* OPT TD.4.7-900ms */ | ||
873 | /* never use invalid T(a_wait_bcon) */ | ||
874 | musb_dbg(musb, "HNP: in %s, %d msec timeout", | ||
875 | usb_otg_state_string(musb->xceiv->otg->state), | ||
876 | TA_WAIT_BCON(musb)); | ||
877 | mod_timer(&musb->otg_timer, jiffies | ||
878 | + msecs_to_jiffies(TA_WAIT_BCON(musb))); | ||
879 | break; | ||
880 | case OTG_STATE_A_PERIPHERAL: | ||
881 | del_timer(&musb->otg_timer); | ||
882 | musb_g_reset(musb); | ||
883 | break; | ||
884 | case OTG_STATE_B_WAIT_ACON: | ||
885 | musb_dbg(musb, "HNP: RESET (%s), to b_peripheral", | ||
886 | usb_otg_state_string(musb->xceiv->otg->state)); | ||
887 | musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL; | ||
888 | musb_g_reset(musb); | ||
889 | break; | ||
890 | case OTG_STATE_B_IDLE: | ||
891 | musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL; | ||
892 | /* FALLTHROUGH */ | ||
893 | case OTG_STATE_B_PERIPHERAL: | ||
894 | musb_g_reset(musb); | ||
895 | break; | ||
896 | default: | ||
897 | musb_dbg(musb, "Unhandled BUS RESET as %s", | ||
898 | usb_otg_state_string(musb->xceiv->otg->state)); | ||
899 | } | ||
900 | } | ||
901 | } | ||
902 | |||
530 | /* | 903 | /* |
531 | * Interrupt Service Routine to record USB "global" interrupts. | 904 | * Interrupt Service Routine to record USB "global" interrupts. |
532 | * Since these do not happen often and signify things of | 905 | * Since these do not happen often and signify things of |
@@ -551,379 +924,40 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | |||
551 | * spurious RESUME irqs happen too, paired with SUSPEND. | 924 | * spurious RESUME irqs happen too, paired with SUSPEND. |
552 | */ | 925 | */ |
553 | if (int_usb & MUSB_INTR_RESUME) { | 926 | if (int_usb & MUSB_INTR_RESUME) { |
927 | musb_handle_intr_resume(musb, devctl); | ||
554 | handled = IRQ_HANDLED; | 928 | handled = IRQ_HANDLED; |
555 | musb_dbg(musb, "RESUME (%s)", | ||
556 | usb_otg_state_string(musb->xceiv->otg->state)); | ||
557 | |||
558 | if (devctl & MUSB_DEVCTL_HM) { | ||
559 | switch (musb->xceiv->otg->state) { | ||
560 | case OTG_STATE_A_SUSPEND: | ||
561 | /* remote wakeup? */ | ||
562 | musb->port1_status |= | ||
563 | (USB_PORT_STAT_C_SUSPEND << 16) | ||
564 | | MUSB_PORT_STAT_RESUME; | ||
565 | musb->rh_timer = jiffies | ||
566 | + msecs_to_jiffies(USB_RESUME_TIMEOUT); | ||
567 | musb->xceiv->otg->state = OTG_STATE_A_HOST; | ||
568 | musb->is_active = 1; | ||
569 | musb_host_resume_root_hub(musb); | ||
570 | schedule_delayed_work(&musb->finish_resume_work, | ||
571 | msecs_to_jiffies(USB_RESUME_TIMEOUT)); | ||
572 | break; | ||
573 | case OTG_STATE_B_WAIT_ACON: | ||
574 | musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL; | ||
575 | musb->is_active = 1; | ||
576 | MUSB_DEV_MODE(musb); | ||
577 | break; | ||
578 | default: | ||
579 | WARNING("bogus %s RESUME (%s)\n", | ||
580 | "host", | ||
581 | usb_otg_state_string(musb->xceiv->otg->state)); | ||
582 | } | ||
583 | } else { | ||
584 | switch (musb->xceiv->otg->state) { | ||
585 | case OTG_STATE_A_SUSPEND: | ||
586 | /* possibly DISCONNECT is upcoming */ | ||
587 | musb->xceiv->otg->state = OTG_STATE_A_HOST; | ||
588 | musb_host_resume_root_hub(musb); | ||
589 | break; | ||
590 | case OTG_STATE_B_WAIT_ACON: | ||
591 | case OTG_STATE_B_PERIPHERAL: | ||
592 | /* disconnect while suspended? we may | ||
593 | * not get a disconnect irq... | ||
594 | */ | ||
595 | if ((devctl & MUSB_DEVCTL_VBUS) | ||
596 | != (3 << MUSB_DEVCTL_VBUS_SHIFT) | ||
597 | ) { | ||
598 | musb->int_usb |= MUSB_INTR_DISCONNECT; | ||
599 | musb->int_usb &= ~MUSB_INTR_SUSPEND; | ||
600 | break; | ||
601 | } | ||
602 | musb_g_resume(musb); | ||
603 | break; | ||
604 | case OTG_STATE_B_IDLE: | ||
605 | musb->int_usb &= ~MUSB_INTR_SUSPEND; | ||
606 | break; | ||
607 | default: | ||
608 | WARNING("bogus %s RESUME (%s)\n", | ||
609 | "peripheral", | ||
610 | usb_otg_state_string(musb->xceiv->otg->state)); | ||
611 | } | ||
612 | } | ||
613 | } | 929 | } |
614 | 930 | ||
615 | /* see manual for the order of the tests */ | 931 | /* see manual for the order of the tests */ |
616 | if (int_usb & MUSB_INTR_SESSREQ) { | 932 | if (int_usb & MUSB_INTR_SESSREQ) { |
617 | void __iomem *mbase = musb->mregs; | 933 | if (musb_handle_intr_sessreq(musb, devctl)) |
618 | |||
619 | if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS | ||
620 | && (devctl & MUSB_DEVCTL_BDEVICE)) { | ||
621 | musb_dbg(musb, "SessReq while on B state"); | ||
622 | return IRQ_HANDLED; | 934 | return IRQ_HANDLED; |
623 | } | ||
624 | |||
625 | musb_dbg(musb, "SESSION_REQUEST (%s)", | ||
626 | usb_otg_state_string(musb->xceiv->otg->state)); | ||
627 | |||
628 | /* IRQ arrives from ID pin sense or (later, if VBUS power | ||
629 | * is removed) SRP. responses are time critical: | ||
630 | * - turn on VBUS (with silicon-specific mechanism) | ||
631 | * - go through A_WAIT_VRISE | ||
632 | * - ... to A_WAIT_BCON. | ||
633 | * a_wait_vrise_tmout triggers VBUS_ERROR transitions | ||
634 | */ | ||
635 | musb_writeb(mbase, MUSB_DEVCTL, MUSB_DEVCTL_SESSION); | ||
636 | musb->ep0_stage = MUSB_EP0_START; | ||
637 | musb->xceiv->otg->state = OTG_STATE_A_IDLE; | ||
638 | MUSB_HST_MODE(musb); | ||
639 | musb_platform_set_vbus(musb, 1); | ||
640 | |||
641 | handled = IRQ_HANDLED; | 935 | handled = IRQ_HANDLED; |
642 | } | 936 | } |
643 | 937 | ||
644 | if (int_usb & MUSB_INTR_VBUSERROR) { | 938 | if (int_usb & MUSB_INTR_VBUSERROR) { |
645 | int ignore = 0; | 939 | musb_handle_intr_vbuserr(musb, devctl); |
646 | |||
647 | /* During connection as an A-Device, we may see a short | ||
648 | * current spikes causing voltage drop, because of cable | ||
649 | * and peripheral capacitance combined with vbus draw. | ||
650 | * (So: less common with truly self-powered devices, where | ||
651 | * vbus doesn't act like a power supply.) | ||
652 | * | ||
653 | * Such spikes are short; usually less than ~500 usec, max | ||
654 | * of ~2 msec. That is, they're not sustained overcurrent | ||
655 | * errors, though they're reported using VBUSERROR irqs. | ||
656 | * | ||
657 | * Workarounds: (a) hardware: use self powered devices. | ||
658 | * (b) software: ignore non-repeated VBUS errors. | ||
659 | * | ||
660 | * REVISIT: do delays from lots of DEBUG_KERNEL checks | ||
661 | * make trouble here, keeping VBUS < 4.4V ? | ||
662 | */ | ||
663 | switch (musb->xceiv->otg->state) { | ||
664 | case OTG_STATE_A_HOST: | ||
665 | /* recovery is dicey once we've gotten past the | ||
666 | * initial stages of enumeration, but if VBUS | ||
667 | * stayed ok at the other end of the link, and | ||
668 | * another reset is due (at least for high speed, | ||
669 | * to redo the chirp etc), it might work OK... | ||
670 | */ | ||
671 | case OTG_STATE_A_WAIT_BCON: | ||
672 | case OTG_STATE_A_WAIT_VRISE: | ||
673 | if (musb->vbuserr_retry) { | ||
674 | void __iomem *mbase = musb->mregs; | ||
675 | |||
676 | musb->vbuserr_retry--; | ||
677 | ignore = 1; | ||
678 | devctl |= MUSB_DEVCTL_SESSION; | ||
679 | musb_writeb(mbase, MUSB_DEVCTL, devctl); | ||
680 | } else { | ||
681 | musb->port1_status |= | ||
682 | USB_PORT_STAT_OVERCURRENT | ||
683 | | (USB_PORT_STAT_C_OVERCURRENT << 16); | ||
684 | } | ||
685 | break; | ||
686 | default: | ||
687 | break; | ||
688 | } | ||
689 | |||
690 | dev_printk(ignore ? KERN_DEBUG : KERN_ERR, musb->controller, | ||
691 | "VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n", | ||
692 | usb_otg_state_string(musb->xceiv->otg->state), | ||
693 | devctl, | ||
694 | ({ char *s; | ||
695 | switch (devctl & MUSB_DEVCTL_VBUS) { | ||
696 | case 0 << MUSB_DEVCTL_VBUS_SHIFT: | ||
697 | s = "<SessEnd"; break; | ||
698 | case 1 << MUSB_DEVCTL_VBUS_SHIFT: | ||
699 | s = "<AValid"; break; | ||
700 | case 2 << MUSB_DEVCTL_VBUS_SHIFT: | ||
701 | s = "<VBusValid"; break; | ||
702 | /* case 3 << MUSB_DEVCTL_VBUS_SHIFT: */ | ||
703 | default: | ||
704 | s = "VALID"; break; | ||
705 | } s; }), | ||
706 | VBUSERR_RETRY_COUNT - musb->vbuserr_retry, | ||
707 | musb->port1_status); | ||
708 | |||
709 | /* go through A_WAIT_VFALL then start a new session */ | ||
710 | if (!ignore) | ||
711 | musb_platform_set_vbus(musb, 0); | ||
712 | handled = IRQ_HANDLED; | 940 | handled = IRQ_HANDLED; |
713 | } | 941 | } |
714 | 942 | ||
715 | if (int_usb & MUSB_INTR_SUSPEND) { | 943 | if (int_usb & MUSB_INTR_SUSPEND) { |
716 | musb_dbg(musb, "SUSPEND (%s) devctl %02x", | 944 | musb_handle_intr_suspend(musb, devctl); |
717 | usb_otg_state_string(musb->xceiv->otg->state), devctl); | ||
718 | handled = IRQ_HANDLED; | 945 | handled = IRQ_HANDLED; |
719 | |||
720 | switch (musb->xceiv->otg->state) { | ||
721 | case OTG_STATE_A_PERIPHERAL: | ||
722 | /* We also come here if the cable is removed, since | ||
723 | * this silicon doesn't report ID-no-longer-grounded. | ||
724 | * | ||
725 | * We depend on T(a_wait_bcon) to shut us down, and | ||
726 | * hope users don't do anything dicey during this | ||
727 | * undesired detour through A_WAIT_BCON. | ||
728 | */ | ||
729 | musb_hnp_stop(musb); | ||
730 | musb_host_resume_root_hub(musb); | ||
731 | musb_root_disconnect(musb); | ||
732 | musb_platform_try_idle(musb, jiffies | ||
733 | + msecs_to_jiffies(musb->a_wait_bcon | ||
734 | ? : OTG_TIME_A_WAIT_BCON)); | ||
735 | |||
736 | break; | ||
737 | case OTG_STATE_B_IDLE: | ||
738 | if (!musb->is_active) | ||
739 | break; | ||
740 | /* fall through */ | ||
741 | case OTG_STATE_B_PERIPHERAL: | ||
742 | musb_g_suspend(musb); | ||
743 | musb->is_active = musb->g.b_hnp_enable; | ||
744 | if (musb->is_active) { | ||
745 | musb->xceiv->otg->state = OTG_STATE_B_WAIT_ACON; | ||
746 | musb_dbg(musb, "HNP: Setting timer for b_ase0_brst"); | ||
747 | mod_timer(&musb->otg_timer, jiffies | ||
748 | + msecs_to_jiffies( | ||
749 | OTG_TIME_B_ASE0_BRST)); | ||
750 | } | ||
751 | break; | ||
752 | case OTG_STATE_A_WAIT_BCON: | ||
753 | if (musb->a_wait_bcon != 0) | ||
754 | musb_platform_try_idle(musb, jiffies | ||
755 | + msecs_to_jiffies(musb->a_wait_bcon)); | ||
756 | break; | ||
757 | case OTG_STATE_A_HOST: | ||
758 | musb->xceiv->otg->state = OTG_STATE_A_SUSPEND; | ||
759 | musb->is_active = musb->hcd->self.b_hnp_enable; | ||
760 | break; | ||
761 | case OTG_STATE_B_HOST: | ||
762 | /* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */ | ||
763 | musb_dbg(musb, "REVISIT: SUSPEND as B_HOST"); | ||
764 | break; | ||
765 | default: | ||
766 | /* "should not happen" */ | ||
767 | musb->is_active = 0; | ||
768 | break; | ||
769 | } | ||
770 | } | 946 | } |
771 | 947 | ||
772 | if (int_usb & MUSB_INTR_CONNECT) { | 948 | if (int_usb & MUSB_INTR_CONNECT) { |
773 | struct usb_hcd *hcd = musb->hcd; | 949 | musb_handle_intr_connect(musb, devctl, int_usb); |
774 | |||
775 | handled = IRQ_HANDLED; | 950 | handled = IRQ_HANDLED; |
776 | musb->is_active = 1; | ||
777 | |||
778 | musb->ep0_stage = MUSB_EP0_START; | ||
779 | |||
780 | musb->intrtxe = musb->epmask; | ||
781 | musb_writew(musb->mregs, MUSB_INTRTXE, musb->intrtxe); | ||
782 | musb->intrrxe = musb->epmask & 0xfffe; | ||
783 | musb_writew(musb->mregs, MUSB_INTRRXE, musb->intrrxe); | ||
784 | musb_writeb(musb->mregs, MUSB_INTRUSBE, 0xf7); | ||
785 | musb->port1_status &= ~(USB_PORT_STAT_LOW_SPEED | ||
786 | |USB_PORT_STAT_HIGH_SPEED | ||
787 | |USB_PORT_STAT_ENABLE | ||
788 | ); | ||
789 | musb->port1_status |= USB_PORT_STAT_CONNECTION | ||
790 | |(USB_PORT_STAT_C_CONNECTION << 16); | ||
791 | |||
792 | /* high vs full speed is just a guess until after reset */ | ||
793 | if (devctl & MUSB_DEVCTL_LSDEV) | ||
794 | musb->port1_status |= USB_PORT_STAT_LOW_SPEED; | ||
795 | |||
796 | /* indicate new connection to OTG machine */ | ||
797 | switch (musb->xceiv->otg->state) { | ||
798 | case OTG_STATE_B_PERIPHERAL: | ||
799 | if (int_usb & MUSB_INTR_SUSPEND) { | ||
800 | musb_dbg(musb, "HNP: SUSPEND+CONNECT, now b_host"); | ||
801 | int_usb &= ~MUSB_INTR_SUSPEND; | ||
802 | goto b_host; | ||
803 | } else | ||
804 | musb_dbg(musb, "CONNECT as b_peripheral???"); | ||
805 | break; | ||
806 | case OTG_STATE_B_WAIT_ACON: | ||
807 | musb_dbg(musb, "HNP: CONNECT, now b_host"); | ||
808 | b_host: | ||
809 | musb->xceiv->otg->state = OTG_STATE_B_HOST; | ||
810 | if (musb->hcd) | ||
811 | musb->hcd->self.is_b_host = 1; | ||
812 | del_timer(&musb->otg_timer); | ||
813 | break; | ||
814 | default: | ||
815 | if ((devctl & MUSB_DEVCTL_VBUS) | ||
816 | == (3 << MUSB_DEVCTL_VBUS_SHIFT)) { | ||
817 | musb->xceiv->otg->state = OTG_STATE_A_HOST; | ||
818 | if (hcd) | ||
819 | hcd->self.is_b_host = 0; | ||
820 | } | ||
821 | break; | ||
822 | } | ||
823 | |||
824 | musb_host_poke_root_hub(musb); | ||
825 | |||
826 | musb_dbg(musb, "CONNECT (%s) devctl %02x", | ||
827 | usb_otg_state_string(musb->xceiv->otg->state), devctl); | ||
828 | } | 951 | } |
829 | 952 | ||
830 | if (int_usb & MUSB_INTR_DISCONNECT) { | 953 | if (int_usb & MUSB_INTR_DISCONNECT) { |
831 | musb_dbg(musb, "DISCONNECT (%s) as %s, devctl %02x", | 954 | musb_handle_intr_disconnect(musb, devctl); |
832 | usb_otg_state_string(musb->xceiv->otg->state), | ||
833 | MUSB_MODE(musb), devctl); | ||
834 | handled = IRQ_HANDLED; | 955 | handled = IRQ_HANDLED; |
835 | |||
836 | switch (musb->xceiv->otg->state) { | ||
837 | case OTG_STATE_A_HOST: | ||
838 | case OTG_STATE_A_SUSPEND: | ||
839 | musb_host_resume_root_hub(musb); | ||
840 | musb_root_disconnect(musb); | ||
841 | if (musb->a_wait_bcon != 0) | ||
842 | musb_platform_try_idle(musb, jiffies | ||
843 | + msecs_to_jiffies(musb->a_wait_bcon)); | ||
844 | break; | ||
845 | case OTG_STATE_B_HOST: | ||
846 | /* REVISIT this behaves for "real disconnect" | ||
847 | * cases; make sure the other transitions from | ||
848 | * from B_HOST act right too. The B_HOST code | ||
849 | * in hnp_stop() is currently not used... | ||
850 | */ | ||
851 | musb_root_disconnect(musb); | ||
852 | if (musb->hcd) | ||
853 | musb->hcd->self.is_b_host = 0; | ||
854 | musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL; | ||
855 | MUSB_DEV_MODE(musb); | ||
856 | musb_g_disconnect(musb); | ||
857 | break; | ||
858 | case OTG_STATE_A_PERIPHERAL: | ||
859 | musb_hnp_stop(musb); | ||
860 | musb_root_disconnect(musb); | ||
861 | /* FALLTHROUGH */ | ||
862 | case OTG_STATE_B_WAIT_ACON: | ||
863 | /* FALLTHROUGH */ | ||
864 | case OTG_STATE_B_PERIPHERAL: | ||
865 | case OTG_STATE_B_IDLE: | ||
866 | musb_g_disconnect(musb); | ||
867 | break; | ||
868 | default: | ||
869 | WARNING("unhandled DISCONNECT transition (%s)\n", | ||
870 | usb_otg_state_string(musb->xceiv->otg->state)); | ||
871 | break; | ||
872 | } | ||
873 | } | 956 | } |
874 | 957 | ||
875 | /* mentor saves a bit: bus reset and babble share the same irq. | ||
876 | * only host sees babble; only peripheral sees bus reset. | ||
877 | */ | ||
878 | if (int_usb & MUSB_INTR_RESET) { | 958 | if (int_usb & MUSB_INTR_RESET) { |
959 | musb_handle_intr_reset(musb); | ||
879 | handled = IRQ_HANDLED; | 960 | handled = IRQ_HANDLED; |
880 | if (is_host_active(musb)) { | ||
881 | /* | ||
882 | * When BABBLE happens what we can depends on which | ||
883 | * platform MUSB is running, because some platforms | ||
884 | * implemented proprietary means for 'recovering' from | ||
885 | * Babble conditions. One such platform is AM335x. In | ||
886 | * most cases, however, the only thing we can do is | ||
887 | * drop the session. | ||
888 | */ | ||
889 | dev_err(musb->controller, "Babble\n"); | ||
890 | musb_recover_from_babble(musb); | ||
891 | } else { | ||
892 | musb_dbg(musb, "BUS RESET as %s", | ||
893 | usb_otg_state_string(musb->xceiv->otg->state)); | ||
894 | switch (musb->xceiv->otg->state) { | ||
895 | case OTG_STATE_A_SUSPEND: | ||
896 | musb_g_reset(musb); | ||
897 | /* FALLTHROUGH */ | ||
898 | case OTG_STATE_A_WAIT_BCON: /* OPT TD.4.7-900ms */ | ||
899 | /* never use invalid T(a_wait_bcon) */ | ||
900 | musb_dbg(musb, "HNP: in %s, %d msec timeout", | ||
901 | usb_otg_state_string(musb->xceiv->otg->state), | ||
902 | TA_WAIT_BCON(musb)); | ||
903 | mod_timer(&musb->otg_timer, jiffies | ||
904 | + msecs_to_jiffies(TA_WAIT_BCON(musb))); | ||
905 | break; | ||
906 | case OTG_STATE_A_PERIPHERAL: | ||
907 | del_timer(&musb->otg_timer); | ||
908 | musb_g_reset(musb); | ||
909 | break; | ||
910 | case OTG_STATE_B_WAIT_ACON: | ||
911 | musb_dbg(musb, "HNP: RESET (%s), to b_peripheral", | ||
912 | usb_otg_state_string(musb->xceiv->otg->state)); | ||
913 | musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL; | ||
914 | musb_g_reset(musb); | ||
915 | break; | ||
916 | case OTG_STATE_B_IDLE: | ||
917 | musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL; | ||
918 | /* FALLTHROUGH */ | ||
919 | case OTG_STATE_B_PERIPHERAL: | ||
920 | musb_g_reset(musb); | ||
921 | break; | ||
922 | default: | ||
923 | musb_dbg(musb, "Unhandled BUS RESET as %s", | ||
924 | usb_otg_state_string(musb->xceiv->otg->state)); | ||
925 | } | ||
926 | } | ||
927 | } | 961 | } |
928 | 962 | ||
929 | #if 0 | 963 | #if 0 |
@@ -1042,7 +1076,7 @@ void musb_start(struct musb *musb) | |||
1042 | * (b) vbus present/connect IRQ, peripheral mode; | 1076 | * (b) vbus present/connect IRQ, peripheral mode; |
1043 | * (c) peripheral initiates, using SRP | 1077 | * (c) peripheral initiates, using SRP |
1044 | */ | 1078 | */ |
1045 | if (musb->port_mode != MUSB_PORT_MODE_HOST && | 1079 | if (musb->port_mode != MUSB_HOST && |
1046 | musb->xceiv->otg->state != OTG_STATE_A_WAIT_BCON && | 1080 | musb->xceiv->otg->state != OTG_STATE_A_WAIT_BCON && |
1047 | (devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) { | 1081 | (devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) { |
1048 | musb->is_active = 1; | 1082 | musb->is_active = 1; |
@@ -1244,25 +1278,25 @@ fifo_setup(struct musb *musb, struct musb_hw_ep *hw_ep, | |||
1244 | /* REVISIT error check: be sure ep0 can both rx and tx ... */ | 1278 | /* REVISIT error check: be sure ep0 can both rx and tx ... */ |
1245 | switch (cfg->style) { | 1279 | switch (cfg->style) { |
1246 | case FIFO_TX: | 1280 | case FIFO_TX: |
1247 | musb_write_txfifosz(mbase, c_size); | 1281 | musb_writeb(mbase, MUSB_TXFIFOSZ, c_size); |
1248 | musb_write_txfifoadd(mbase, c_off); | 1282 | musb_writew(mbase, MUSB_TXFIFOADD, c_off); |
1249 | hw_ep->tx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB); | 1283 | hw_ep->tx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB); |
1250 | hw_ep->max_packet_sz_tx = maxpacket; | 1284 | hw_ep->max_packet_sz_tx = maxpacket; |
1251 | break; | 1285 | break; |
1252 | case FIFO_RX: | 1286 | case FIFO_RX: |
1253 | musb_write_rxfifosz(mbase, c_size); | 1287 | musb_writeb(mbase, MUSB_RXFIFOSZ, c_size); |
1254 | musb_write_rxfifoadd(mbase, c_off); | 1288 | musb_writew(mbase, MUSB_RXFIFOADD, c_off); |
1255 | hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB); | 1289 | hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB); |
1256 | hw_ep->max_packet_sz_rx = maxpacket; | 1290 | hw_ep->max_packet_sz_rx = maxpacket; |
1257 | break; | 1291 | break; |
1258 | case FIFO_RXTX: | 1292 | case FIFO_RXTX: |
1259 | musb_write_txfifosz(mbase, c_size); | 1293 | musb_writeb(mbase, MUSB_TXFIFOSZ, c_size); |
1260 | musb_write_txfifoadd(mbase, c_off); | 1294 | musb_writew(mbase, MUSB_TXFIFOADD, c_off); |
1261 | hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB); | 1295 | hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB); |
1262 | hw_ep->max_packet_sz_rx = maxpacket; | 1296 | hw_ep->max_packet_sz_rx = maxpacket; |
1263 | 1297 | ||
1264 | musb_write_rxfifosz(mbase, c_size); | 1298 | musb_writeb(mbase, MUSB_RXFIFOSZ, c_size); |
1265 | musb_write_rxfifoadd(mbase, c_off); | 1299 | musb_writew(mbase, MUSB_RXFIFOADD, c_off); |
1266 | hw_ep->tx_double_buffered = hw_ep->rx_double_buffered; | 1300 | hw_ep->tx_double_buffered = hw_ep->rx_double_buffered; |
1267 | hw_ep->max_packet_sz_tx = maxpacket; | 1301 | hw_ep->max_packet_sz_tx = maxpacket; |
1268 | 1302 | ||
@@ -1470,7 +1504,7 @@ static int musb_core_init(u16 musb_type, struct musb *musb) | |||
1470 | } | 1504 | } |
1471 | 1505 | ||
1472 | /* log release info */ | 1506 | /* log release info */ |
1473 | musb->hwvers = musb_read_hwvers(mbase); | 1507 | musb->hwvers = musb_readw(mbase, MUSB_HWVERS); |
1474 | pr_debug("%s: %sHDRC RTL version %d.%d%s\n", | 1508 | pr_debug("%s: %sHDRC RTL version %d.%d%s\n", |
1475 | musb_driver_name, type, MUSB_HWVERS_MAJOR(musb->hwvers), | 1509 | musb_driver_name, type, MUSB_HWVERS_MAJOR(musb->hwvers), |
1476 | MUSB_HWVERS_MINOR(musb->hwvers), | 1510 | MUSB_HWVERS_MINOR(musb->hwvers), |
@@ -1497,7 +1531,7 @@ static int musb_core_init(u16 musb_type, struct musb *musb) | |||
1497 | 1531 | ||
1498 | hw_ep->fifo = musb->io.fifo_offset(i) + mbase; | 1532 | hw_ep->fifo = musb->io.fifo_offset(i) + mbase; |
1499 | #if IS_ENABLED(CONFIG_USB_MUSB_TUSB6010) | 1533 | #if IS_ENABLED(CONFIG_USB_MUSB_TUSB6010) |
1500 | if (musb->io.quirks & MUSB_IN_TUSB) { | 1534 | if (musb->ops->quirks & MUSB_IN_TUSB) { |
1501 | hw_ep->fifo_async = musb->async + 0x400 + | 1535 | hw_ep->fifo_async = musb->async + 0x400 + |
1502 | musb->io.fifo_offset(i); | 1536 | musb->io.fifo_offset(i); |
1503 | hw_ep->fifo_sync = musb->sync + 0x400 + | 1537 | hw_ep->fifo_sync = musb->sync + 0x400 + |
@@ -2158,8 +2192,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) | |||
2158 | musb_writeb = musb_default_writeb; | 2192 | musb_writeb = musb_default_writeb; |
2159 | musb_readw = musb_default_readw; | 2193 | musb_readw = musb_default_readw; |
2160 | musb_writew = musb_default_writew; | 2194 | musb_writew = musb_default_writew; |
2161 | musb_readl = musb_default_readl; | ||
2162 | musb_writel = musb_default_writel; | ||
2163 | 2195 | ||
2164 | /* The musb_platform_init() call: | 2196 | /* The musb_platform_init() call: |
2165 | * - adjusts musb->mregs | 2197 | * - adjusts musb->mregs |
@@ -2182,11 +2214,9 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) | |||
2182 | goto fail2; | 2214 | goto fail2; |
2183 | } | 2215 | } |
2184 | 2216 | ||
2185 | if (musb->ops->quirks) | ||
2186 | musb->io.quirks = musb->ops->quirks; | ||
2187 | 2217 | ||
2188 | /* Most devices use indexed offset or flat offset */ | 2218 | /* Most devices use indexed offset or flat offset */ |
2189 | if (musb->io.quirks & MUSB_INDEXED_EP) { | 2219 | if (musb->ops->quirks & MUSB_INDEXED_EP) { |
2190 | musb->io.ep_offset = musb_indexed_ep_offset; | 2220 | musb->io.ep_offset = musb_indexed_ep_offset; |
2191 | musb->io.ep_select = musb_indexed_ep_select; | 2221 | musb->io.ep_select = musb_indexed_ep_select; |
2192 | } else { | 2222 | } else { |
@@ -2194,7 +2224,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) | |||
2194 | musb->io.ep_select = musb_flat_ep_select; | 2224 | musb->io.ep_select = musb_flat_ep_select; |
2195 | } | 2225 | } |
2196 | 2226 | ||
2197 | if (musb->io.quirks & MUSB_G_NO_SKB_RESERVE) | 2227 | if (musb->ops->quirks & MUSB_G_NO_SKB_RESERVE) |
2198 | musb->g.quirk_avoids_skb_reserve = 1; | 2228 | musb->g.quirk_avoids_skb_reserve = 1; |
2199 | 2229 | ||
2200 | /* At least tusb6010 has its own offsets */ | 2230 | /* At least tusb6010 has its own offsets */ |
@@ -2226,10 +2256,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) | |||
2226 | musb_readw = musb->ops->readw; | 2256 | musb_readw = musb->ops->readw; |
2227 | if (musb->ops->writew) | 2257 | if (musb->ops->writew) |
2228 | musb_writew = musb->ops->writew; | 2258 | musb_writew = musb->ops->writew; |
2229 | if (musb->ops->readl) | ||
2230 | musb_readl = musb->ops->readl; | ||
2231 | if (musb->ops->writel) | ||
2232 | musb_writel = musb->ops->writel; | ||
2233 | 2259 | ||
2234 | #ifndef CONFIG_MUSB_PIO_ONLY | 2260 | #ifndef CONFIG_MUSB_PIO_ONLY |
2235 | if (!musb->ops->dma_init || !musb->ops->dma_exit) { | 2261 | if (!musb->ops->dma_init || !musb->ops->dma_exit) { |
@@ -2321,33 +2347,28 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) | |||
2321 | 2347 | ||
2322 | /* program PHY to use external vBus if required */ | 2348 | /* program PHY to use external vBus if required */ |
2323 | if (plat->extvbus) { | 2349 | if (plat->extvbus) { |
2324 | u8 busctl = musb_read_ulpi_buscontrol(musb->mregs); | 2350 | u8 busctl = musb_readb(musb->mregs, MUSB_ULPI_BUSCONTROL); |
2325 | busctl |= MUSB_ULPI_USE_EXTVBUS; | 2351 | busctl |= MUSB_ULPI_USE_EXTVBUS; |
2326 | musb_write_ulpi_buscontrol(musb->mregs, busctl); | 2352 | musb_writeb(musb->mregs, MUSB_ULPI_BUSCONTROL, busctl); |
2327 | } | 2353 | } |
2328 | 2354 | ||
2329 | if (musb->xceiv->otg->default_a) { | 2355 | MUSB_DEV_MODE(musb); |
2330 | MUSB_HST_MODE(musb); | 2356 | musb->xceiv->otg->state = OTG_STATE_B_IDLE; |
2331 | musb->xceiv->otg->state = OTG_STATE_A_IDLE; | ||
2332 | } else { | ||
2333 | MUSB_DEV_MODE(musb); | ||
2334 | musb->xceiv->otg->state = OTG_STATE_B_IDLE; | ||
2335 | } | ||
2336 | 2357 | ||
2337 | switch (musb->port_mode) { | 2358 | switch (musb->port_mode) { |
2338 | case MUSB_PORT_MODE_HOST: | 2359 | case MUSB_HOST: |
2339 | status = musb_host_setup(musb, plat->power); | 2360 | status = musb_host_setup(musb, plat->power); |
2340 | if (status < 0) | 2361 | if (status < 0) |
2341 | goto fail3; | 2362 | goto fail3; |
2342 | status = musb_platform_set_mode(musb, MUSB_HOST); | 2363 | status = musb_platform_set_mode(musb, MUSB_HOST); |
2343 | break; | 2364 | break; |
2344 | case MUSB_PORT_MODE_GADGET: | 2365 | case MUSB_PERIPHERAL: |
2345 | status = musb_gadget_setup(musb); | 2366 | status = musb_gadget_setup(musb); |
2346 | if (status < 0) | 2367 | if (status < 0) |
2347 | goto fail3; | 2368 | goto fail3; |
2348 | status = musb_platform_set_mode(musb, MUSB_PERIPHERAL); | 2369 | status = musb_platform_set_mode(musb, MUSB_PERIPHERAL); |
2349 | break; | 2370 | break; |
2350 | case MUSB_PORT_MODE_DUAL_ROLE: | 2371 | case MUSB_OTG: |
2351 | status = musb_host_setup(musb, plat->power); | 2372 | status = musb_host_setup(musb, plat->power); |
2352 | if (status < 0) | 2373 | if (status < 0) |
2353 | goto fail3; | 2374 | goto fail3; |
@@ -2366,9 +2387,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) | |||
2366 | if (status < 0) | 2387 | if (status < 0) |
2367 | goto fail3; | 2388 | goto fail3; |
2368 | 2389 | ||
2369 | status = musb_init_debugfs(musb); | 2390 | musb_init_debugfs(musb); |
2370 | if (status < 0) | ||
2371 | goto fail4; | ||
2372 | 2391 | ||
2373 | status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group); | 2392 | status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group); |
2374 | if (status) | 2393 | if (status) |
@@ -2383,7 +2402,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) | |||
2383 | fail5: | 2402 | fail5: |
2384 | musb_exit_debugfs(musb); | 2403 | musb_exit_debugfs(musb); |
2385 | 2404 | ||
2386 | fail4: | ||
2387 | musb_gadget_cleanup(musb); | 2405 | musb_gadget_cleanup(musb); |
2388 | musb_host_cleanup(musb); | 2406 | musb_host_cleanup(musb); |
2389 | 2407 | ||
@@ -2492,7 +2510,7 @@ static void musb_save_context(struct musb *musb) | |||
2492 | 2510 | ||
2493 | musb->context.frame = musb_readw(musb_base, MUSB_FRAME); | 2511 | musb->context.frame = musb_readw(musb_base, MUSB_FRAME); |
2494 | musb->context.testmode = musb_readb(musb_base, MUSB_TESTMODE); | 2512 | musb->context.testmode = musb_readb(musb_base, MUSB_TESTMODE); |
2495 | musb->context.busctl = musb_read_ulpi_buscontrol(musb->mregs); | 2513 | musb->context.busctl = musb_readb(musb_base, MUSB_ULPI_BUSCONTROL); |
2496 | musb->context.power = musb_readb(musb_base, MUSB_POWER); | 2514 | musb->context.power = musb_readb(musb_base, MUSB_POWER); |
2497 | musb->context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE); | 2515 | musb->context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE); |
2498 | musb->context.index = musb_readb(musb_base, MUSB_INDEX); | 2516 | musb->context.index = musb_readb(musb_base, MUSB_INDEX); |
@@ -2521,13 +2539,13 @@ static void musb_save_context(struct musb *musb) | |||
2521 | 2539 | ||
2522 | if (musb->dyn_fifo) { | 2540 | if (musb->dyn_fifo) { |
2523 | musb->context.index_regs[i].txfifoadd = | 2541 | musb->context.index_regs[i].txfifoadd = |
2524 | musb_read_txfifoadd(musb_base); | 2542 | musb_readw(musb_base, MUSB_TXFIFOADD); |
2525 | musb->context.index_regs[i].rxfifoadd = | 2543 | musb->context.index_regs[i].rxfifoadd = |
2526 | musb_read_rxfifoadd(musb_base); | 2544 | musb_readw(musb_base, MUSB_RXFIFOADD); |
2527 | musb->context.index_regs[i].txfifosz = | 2545 | musb->context.index_regs[i].txfifosz = |
2528 | musb_read_txfifosz(musb_base); | 2546 | musb_readb(musb_base, MUSB_TXFIFOSZ); |
2529 | musb->context.index_regs[i].rxfifosz = | 2547 | musb->context.index_regs[i].rxfifosz = |
2530 | musb_read_rxfifosz(musb_base); | 2548 | musb_readb(musb_base, MUSB_RXFIFOSZ); |
2531 | } | 2549 | } |
2532 | 2550 | ||
2533 | musb->context.index_regs[i].txtype = | 2551 | musb->context.index_regs[i].txtype = |
@@ -2564,7 +2582,7 @@ static void musb_restore_context(struct musb *musb) | |||
2564 | 2582 | ||
2565 | musb_writew(musb_base, MUSB_FRAME, musb->context.frame); | 2583 | musb_writew(musb_base, MUSB_FRAME, musb->context.frame); |
2566 | musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode); | 2584 | musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode); |
2567 | musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl); | 2585 | musb_writeb(musb_base, MUSB_ULPI_BUSCONTROL, musb->context.busctl); |
2568 | 2586 | ||
2569 | /* Don't affect SUSPENDM/RESUME bits in POWER reg */ | 2587 | /* Don't affect SUSPENDM/RESUME bits in POWER reg */ |
2570 | power = musb_readb(musb_base, MUSB_POWER); | 2588 | power = musb_readb(musb_base, MUSB_POWER); |
@@ -2601,13 +2619,13 @@ static void musb_restore_context(struct musb *musb) | |||
2601 | musb->context.index_regs[i].rxcsr); | 2619 | musb->context.index_regs[i].rxcsr); |
2602 | 2620 | ||
2603 | if (musb->dyn_fifo) { | 2621 | if (musb->dyn_fifo) { |
2604 | musb_write_txfifosz(musb_base, | 2622 | musb_writeb(musb_base, MUSB_TXFIFOSZ, |
2605 | musb->context.index_regs[i].txfifosz); | 2623 | musb->context.index_regs[i].txfifosz); |
2606 | musb_write_rxfifosz(musb_base, | 2624 | musb_writeb(musb_base, MUSB_RXFIFOSZ, |
2607 | musb->context.index_regs[i].rxfifosz); | 2625 | musb->context.index_regs[i].rxfifosz); |
2608 | musb_write_txfifoadd(musb_base, | 2626 | musb_writew(musb_base, MUSB_TXFIFOADD, |
2609 | musb->context.index_regs[i].txfifoadd); | 2627 | musb->context.index_regs[i].txfifoadd); |
2610 | musb_write_rxfifoadd(musb_base, | 2628 | musb_writew(musb_base, MUSB_RXFIFOADD, |
2611 | musb->context.index_regs[i].rxfifoadd); | 2629 | musb->context.index_regs[i].rxfifoadd); |
2612 | } | 2630 | } |
2613 | 2631 | ||
@@ -2657,7 +2675,7 @@ static int musb_suspend(struct device *dev) | |||
2657 | ; | 2675 | ; |
2658 | musb->flush_irq_work = false; | 2676 | musb->flush_irq_work = false; |
2659 | 2677 | ||
2660 | if (!(musb->io.quirks & MUSB_PRESERVE_SESSION)) | 2678 | if (!(musb->ops->quirks & MUSB_PRESERVE_SESSION)) |
2661 | musb_writeb(musb->mregs, MUSB_DEVCTL, 0); | 2679 | musb_writeb(musb->mregs, MUSB_DEVCTL, 0); |
2662 | 2680 | ||
2663 | WARN_ON(!list_empty(&musb->pending_list)); | 2681 | WARN_ON(!list_empty(&musb->pending_list)); |
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 8a74cb2907f8..04203b7126d5 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h | |||
@@ -53,12 +53,6 @@ struct musb_ep; | |||
53 | #define is_peripheral_active(m) (!(m)->is_host) | 53 | #define is_peripheral_active(m) (!(m)->is_host) |
54 | #define is_host_active(m) ((m)->is_host) | 54 | #define is_host_active(m) ((m)->is_host) |
55 | 55 | ||
56 | enum { | ||
57 | MUSB_PORT_MODE_HOST = 1, | ||
58 | MUSB_PORT_MODE_GADGET, | ||
59 | MUSB_PORT_MODE_DUAL_ROLE, | ||
60 | }; | ||
61 | |||
62 | /****************************** CONSTANTS ********************************/ | 56 | /****************************** CONSTANTS ********************************/ |
63 | 57 | ||
64 | #ifndef MUSB_C_NUM_EPS | 58 | #ifndef MUSB_C_NUM_EPS |
@@ -127,8 +121,6 @@ struct musb_io; | |||
127 | * @writeb: write 8 bits | 121 | * @writeb: write 8 bits |
128 | * @readw: read 16 bits | 122 | * @readw: read 16 bits |
129 | * @writew: write 16 bits | 123 | * @writew: write 16 bits |
130 | * @readl: read 32 bits | ||
131 | * @writel: write 32 bits | ||
132 | * @read_fifo: reads the fifo | 124 | * @read_fifo: reads the fifo |
133 | * @write_fifo: writes to fifo | 125 | * @write_fifo: writes to fifo |
134 | * @dma_init: platform specific dma init function | 126 | * @dma_init: platform specific dma init function |
@@ -140,7 +132,6 @@ struct musb_io; | |||
140 | * @recover: platform-specific babble recovery | 132 | * @recover: platform-specific babble recovery |
141 | * @vbus_status: returns vbus status if possible | 133 | * @vbus_status: returns vbus status if possible |
142 | * @set_vbus: forces vbus status | 134 | * @set_vbus: forces vbus status |
143 | * @adjust_channel_params: pre check for standard dma channel_program func | ||
144 | * @pre_root_reset_end: called before the root usb port reset flag gets cleared | 135 | * @pre_root_reset_end: called before the root usb port reset flag gets cleared |
145 | * @post_root_reset_end: called after the root usb port reset flag gets cleared | 136 | * @post_root_reset_end: called after the root usb port reset flag gets cleared |
146 | * @phy_callback: optional callback function for the phy to call | 137 | * @phy_callback: optional callback function for the phy to call |
@@ -174,8 +165,6 @@ struct musb_platform_ops { | |||
174 | void (*writeb)(void __iomem *addr, unsigned offset, u8 data); | 165 | void (*writeb)(void __iomem *addr, unsigned offset, u8 data); |
175 | u16 (*readw)(const void __iomem *addr, unsigned offset); | 166 | u16 (*readw)(const void __iomem *addr, unsigned offset); |
176 | void (*writew)(void __iomem *addr, unsigned offset, u16 data); | 167 | void (*writew)(void __iomem *addr, unsigned offset, u16 data); |
177 | u32 (*readl)(const void __iomem *addr, unsigned offset); | ||
178 | void (*writel)(void __iomem *addr, unsigned offset, u32 data); | ||
179 | void (*read_fifo)(struct musb_hw_ep *hw_ep, u16 len, u8 *buf); | 168 | void (*read_fifo)(struct musb_hw_ep *hw_ep, u16 len, u8 *buf); |
180 | void (*write_fifo)(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf); | 169 | void (*write_fifo)(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf); |
181 | struct dma_controller * | 170 | struct dma_controller * |
@@ -188,9 +177,6 @@ struct musb_platform_ops { | |||
188 | int (*vbus_status)(struct musb *musb); | 177 | int (*vbus_status)(struct musb *musb); |
189 | void (*set_vbus)(struct musb *musb, int on); | 178 | void (*set_vbus)(struct musb *musb, int on); |
190 | 179 | ||
191 | int (*adjust_channel_params)(struct dma_channel *channel, | ||
192 | u16 packet_sz, u8 *mode, | ||
193 | dma_addr_t *dma_addr, u32 *len); | ||
194 | void (*pre_root_reset_end)(struct musb *musb); | 180 | void (*pre_root_reset_end)(struct musb *musb); |
195 | void (*post_root_reset_end)(struct musb *musb); | 181 | void (*post_root_reset_end)(struct musb *musb); |
196 | int (*phy_callback)(enum musb_vbus_id_status status); | 182 | int (*phy_callback)(enum musb_vbus_id_status status); |
@@ -359,7 +345,7 @@ struct musb { | |||
359 | 345 | ||
360 | u8 min_power; /* vbus for periph, in mA/2 */ | 346 | u8 min_power; /* vbus for periph, in mA/2 */ |
361 | 347 | ||
362 | int port_mode; /* MUSB_PORT_MODE_* */ | 348 | enum musb_mode port_mode; |
363 | bool session; | 349 | bool session; |
364 | unsigned long quirk_retries; | 350 | unsigned long quirk_retries; |
365 | bool is_host; | 351 | bool is_host; |
diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c index d0dd4f470bbe..7fbb8a307145 100644 --- a/drivers/usb/musb/musb_cppi41.c +++ b/drivers/usb/musb/musb_cppi41.c | |||
@@ -614,7 +614,7 @@ static int cppi41_dma_channel_abort(struct dma_channel *channel) | |||
614 | } | 614 | } |
615 | 615 | ||
616 | /* DA8xx Advisory 2.3.27: wait 250 ms before to start the teardown */ | 616 | /* DA8xx Advisory 2.3.27: wait 250 ms before to start the teardown */ |
617 | if (musb->io.quirks & MUSB_DA8XX) | 617 | if (musb->ops->quirks & MUSB_DA8XX) |
618 | mdelay(250); | 618 | mdelay(250); |
619 | 619 | ||
620 | tdbit = 1 << cppi41_channel->port_num; | 620 | tdbit = 1 << cppi41_channel->port_num; |
@@ -773,7 +773,7 @@ cppi41_dma_controller_create(struct musb *musb, void __iomem *base) | |||
773 | controller->controller.is_compatible = cppi41_is_compatible; | 773 | controller->controller.is_compatible = cppi41_is_compatible; |
774 | controller->controller.musb = musb; | 774 | controller->controller.musb = musb; |
775 | 775 | ||
776 | if (musb->io.quirks & MUSB_DA8XX) { | 776 | if (musb->ops->quirks & MUSB_DA8XX) { |
777 | controller->tdown_reg = DA8XX_USB_TEARDOWN; | 777 | controller->tdown_reg = DA8XX_USB_TEARDOWN; |
778 | controller->autoreq_reg = DA8XX_USB_AUTOREQ; | 778 | controller->autoreq_reg = DA8XX_USB_AUTOREQ; |
779 | controller->set_dma_mode = da8xx_set_dma_mode; | 779 | controller->set_dma_mode = da8xx_set_dma_mode; |
diff --git a/drivers/usb/musb/musb_debug.h b/drivers/usb/musb/musb_debug.h index 5e0f079dde21..c444a80fe1da 100644 --- a/drivers/usb/musb/musb_debug.h +++ b/drivers/usb/musb/musb_debug.h | |||
@@ -20,12 +20,11 @@ | |||
20 | void musb_dbg(struct musb *musb, const char *fmt, ...); | 20 | void musb_dbg(struct musb *musb, const char *fmt, ...); |
21 | 21 | ||
22 | #ifdef CONFIG_DEBUG_FS | 22 | #ifdef CONFIG_DEBUG_FS |
23 | int musb_init_debugfs(struct musb *musb); | 23 | void musb_init_debugfs(struct musb *musb); |
24 | void musb_exit_debugfs(struct musb *musb); | 24 | void musb_exit_debugfs(struct musb *musb); |
25 | #else | 25 | #else |
26 | static inline int musb_init_debugfs(struct musb *musb) | 26 | static inline void musb_init_debugfs(struct musb *musb) |
27 | { | 27 | { |
28 | return 0; | ||
29 | } | 28 | } |
30 | static inline void musb_exit_debugfs(struct musb *musb) | 29 | static inline void musb_exit_debugfs(struct musb *musb) |
31 | { | 30 | { |
diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c index e2050cac3eae..f42858e2b54c 100644 --- a/drivers/usb/musb/musb_debugfs.c +++ b/drivers/usb/musb/musb_debugfs.c | |||
@@ -321,48 +321,18 @@ static const struct file_operations musb_softconnect_fops = { | |||
321 | .release = single_release, | 321 | .release = single_release, |
322 | }; | 322 | }; |
323 | 323 | ||
324 | int musb_init_debugfs(struct musb *musb) | 324 | void musb_init_debugfs(struct musb *musb) |
325 | { | 325 | { |
326 | struct dentry *root; | 326 | struct dentry *root; |
327 | struct dentry *file; | ||
328 | int ret; | ||
329 | 327 | ||
330 | root = debugfs_create_dir(dev_name(musb->controller), NULL); | 328 | root = debugfs_create_dir(dev_name(musb->controller), NULL); |
331 | if (!root) { | ||
332 | ret = -ENOMEM; | ||
333 | goto err0; | ||
334 | } | ||
335 | |||
336 | file = debugfs_create_file("regdump", S_IRUGO, root, musb, | ||
337 | &musb_regdump_fops); | ||
338 | if (!file) { | ||
339 | ret = -ENOMEM; | ||
340 | goto err1; | ||
341 | } | ||
342 | |||
343 | file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, | ||
344 | root, musb, &musb_test_mode_fops); | ||
345 | if (!file) { | ||
346 | ret = -ENOMEM; | ||
347 | goto err1; | ||
348 | } | ||
349 | |||
350 | file = debugfs_create_file("softconnect", S_IRUGO | S_IWUSR, | ||
351 | root, musb, &musb_softconnect_fops); | ||
352 | if (!file) { | ||
353 | ret = -ENOMEM; | ||
354 | goto err1; | ||
355 | } | ||
356 | |||
357 | musb->debugfs_root = root; | 329 | musb->debugfs_root = root; |
358 | 330 | ||
359 | return 0; | 331 | debugfs_create_file("regdump", S_IRUGO, root, musb, &musb_regdump_fops); |
360 | 332 | debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root, musb, | |
361 | err1: | 333 | &musb_test_mode_fops); |
362 | debugfs_remove_recursive(root); | 334 | debugfs_create_file("softconnect", S_IRUGO | S_IWUSR, root, musb, |
363 | 335 | &musb_softconnect_fops); | |
364 | err0: | ||
365 | return ret; | ||
366 | } | 336 | } |
367 | 337 | ||
368 | void /* __init_or_exit */ musb_exit_debugfs(struct musb *musb) | 338 | void /* __init_or_exit */ musb_exit_debugfs(struct musb *musb) |
diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h index 0fc8cd0c2a5c..8f60271c0a9d 100644 --- a/drivers/usb/musb/musb_dma.h +++ b/drivers/usb/musb/musb_dma.h | |||
@@ -44,31 +44,31 @@ struct musb_hw_ep; | |||
44 | #endif | 44 | #endif |
45 | 45 | ||
46 | #ifdef CONFIG_USB_UX500_DMA | 46 | #ifdef CONFIG_USB_UX500_DMA |
47 | #define musb_dma_ux500(musb) (musb->io.quirks & MUSB_DMA_UX500) | 47 | #define musb_dma_ux500(musb) (musb->ops->quirks & MUSB_DMA_UX500) |
48 | #else | 48 | #else |
49 | #define musb_dma_ux500(musb) 0 | 49 | #define musb_dma_ux500(musb) 0 |
50 | #endif | 50 | #endif |
51 | 51 | ||
52 | #ifdef CONFIG_USB_TI_CPPI41_DMA | 52 | #ifdef CONFIG_USB_TI_CPPI41_DMA |
53 | #define musb_dma_cppi41(musb) (musb->io.quirks & MUSB_DMA_CPPI41) | 53 | #define musb_dma_cppi41(musb) (musb->ops->quirks & MUSB_DMA_CPPI41) |
54 | #else | 54 | #else |
55 | #define musb_dma_cppi41(musb) 0 | 55 | #define musb_dma_cppi41(musb) 0 |
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | #ifdef CONFIG_USB_TI_CPPI_DMA | 58 | #ifdef CONFIG_USB_TI_CPPI_DMA |
59 | #define musb_dma_cppi(musb) (musb->io.quirks & MUSB_DMA_CPPI) | 59 | #define musb_dma_cppi(musb) (musb->ops->quirks & MUSB_DMA_CPPI) |
60 | #else | 60 | #else |
61 | #define musb_dma_cppi(musb) 0 | 61 | #define musb_dma_cppi(musb) 0 |
62 | #endif | 62 | #endif |
63 | 63 | ||
64 | #ifdef CONFIG_USB_TUSB_OMAP_DMA | 64 | #ifdef CONFIG_USB_TUSB_OMAP_DMA |
65 | #define tusb_dma_omap(musb) (musb->io.quirks & MUSB_DMA_TUSB_OMAP) | 65 | #define tusb_dma_omap(musb) (musb->ops->quirks & MUSB_DMA_TUSB_OMAP) |
66 | #else | 66 | #else |
67 | #define tusb_dma_omap(musb) 0 | 67 | #define tusb_dma_omap(musb) 0 |
68 | #endif | 68 | #endif |
69 | 69 | ||
70 | #ifdef CONFIG_USB_INVENTRA_DMA | 70 | #ifdef CONFIG_USB_INVENTRA_DMA |
71 | #define musb_dma_inventra(musb) (musb->io.quirks & MUSB_DMA_INVENTRA) | 71 | #define musb_dma_inventra(musb) (musb->ops->quirks & MUSB_DMA_INVENTRA) |
72 | #else | 72 | #else |
73 | #define musb_dma_inventra(musb) 0 | 73 | #define musb_dma_inventra(musb) 0 |
74 | #endif | 74 | #endif |
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 6a60bc0490c5..fb871eabcc10 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c | |||
@@ -183,7 +183,7 @@ static void dsps_musb_enable(struct musb *musb) | |||
183 | musb_writel(reg_base, wrp->coreintr_set, coremask); | 183 | musb_writel(reg_base, wrp->coreintr_set, coremask); |
184 | /* start polling for ID change in dual-role idle mode */ | 184 | /* start polling for ID change in dual-role idle mode */ |
185 | if (musb->xceiv->otg->state == OTG_STATE_B_IDLE && | 185 | if (musb->xceiv->otg->state == OTG_STATE_B_IDLE && |
186 | musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE) | 186 | musb->port_mode == MUSB_OTG) |
187 | dsps_mod_timer(glue, -1); | 187 | dsps_mod_timer(glue, -1); |
188 | } | 188 | } |
189 | 189 | ||
@@ -231,7 +231,7 @@ static int dsps_check_status(struct musb *musb, void *unused) | |||
231 | break; | 231 | break; |
232 | case OTG_STATE_A_WAIT_BCON: | 232 | case OTG_STATE_A_WAIT_BCON: |
233 | /* keep VBUS on for host-only mode */ | 233 | /* keep VBUS on for host-only mode */ |
234 | if (musb->port_mode == MUSB_PORT_MODE_HOST) { | 234 | if (musb->port_mode == MUSB_HOST) { |
235 | dsps_mod_timer_optional(glue); | 235 | dsps_mod_timer_optional(glue); |
236 | break; | 236 | break; |
237 | } | 237 | } |
@@ -360,13 +360,11 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) | |||
360 | WARNING("VBUS error workaround (delay coming)\n"); | 360 | WARNING("VBUS error workaround (delay coming)\n"); |
361 | } else if (drvvbus) { | 361 | } else if (drvvbus) { |
362 | MUSB_HST_MODE(musb); | 362 | MUSB_HST_MODE(musb); |
363 | musb->xceiv->otg->default_a = 1; | ||
364 | musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; | 363 | musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; |
365 | dsps_mod_timer_optional(glue); | 364 | dsps_mod_timer_optional(glue); |
366 | } else { | 365 | } else { |
367 | musb->is_active = 0; | 366 | musb->is_active = 0; |
368 | MUSB_DEV_MODE(musb); | 367 | MUSB_DEV_MODE(musb); |
369 | musb->xceiv->otg->default_a = 0; | ||
370 | musb->xceiv->otg->state = OTG_STATE_B_IDLE; | 368 | musb->xceiv->otg->state = OTG_STATE_B_IDLE; |
371 | } | 369 | } |
372 | 370 | ||
@@ -401,24 +399,17 @@ out: | |||
401 | static int dsps_musb_dbg_init(struct musb *musb, struct dsps_glue *glue) | 399 | static int dsps_musb_dbg_init(struct musb *musb, struct dsps_glue *glue) |
402 | { | 400 | { |
403 | struct dentry *root; | 401 | struct dentry *root; |
404 | struct dentry *file; | ||
405 | char buf[128]; | 402 | char buf[128]; |
406 | 403 | ||
407 | sprintf(buf, "%s.dsps", dev_name(musb->controller)); | 404 | sprintf(buf, "%s.dsps", dev_name(musb->controller)); |
408 | root = debugfs_create_dir(buf, NULL); | 405 | root = debugfs_create_dir(buf, NULL); |
409 | if (!root) | ||
410 | return -ENOMEM; | ||
411 | glue->dbgfs_root = root; | 406 | glue->dbgfs_root = root; |
412 | 407 | ||
413 | glue->regset.regs = dsps_musb_regs; | 408 | glue->regset.regs = dsps_musb_regs; |
414 | glue->regset.nregs = ARRAY_SIZE(dsps_musb_regs); | 409 | glue->regset.nregs = ARRAY_SIZE(dsps_musb_regs); |
415 | glue->regset.base = musb->ctrl_base; | 410 | glue->regset.base = musb->ctrl_base; |
416 | 411 | ||
417 | file = debugfs_create_regset32("regdump", S_IRUGO, root, &glue->regset); | 412 | debugfs_create_regset32("regdump", S_IRUGO, root, &glue->regset); |
418 | if (!file) { | ||
419 | debugfs_remove_recursive(root); | ||
420 | return -ENOMEM; | ||
421 | } | ||
422 | return 0; | 413 | return 0; |
423 | } | 414 | } |
424 | 415 | ||
@@ -729,25 +720,6 @@ static int get_int_prop(struct device_node *dn, const char *s) | |||
729 | return val; | 720 | return val; |
730 | } | 721 | } |
731 | 722 | ||
732 | static int get_musb_port_mode(struct device *dev) | ||
733 | { | ||
734 | enum usb_dr_mode mode; | ||
735 | |||
736 | mode = usb_get_dr_mode(dev); | ||
737 | switch (mode) { | ||
738 | case USB_DR_MODE_HOST: | ||
739 | return MUSB_PORT_MODE_HOST; | ||
740 | |||
741 | case USB_DR_MODE_PERIPHERAL: | ||
742 | return MUSB_PORT_MODE_GADGET; | ||
743 | |||
744 | case USB_DR_MODE_UNKNOWN: | ||
745 | case USB_DR_MODE_OTG: | ||
746 | default: | ||
747 | return MUSB_PORT_MODE_DUAL_ROLE; | ||
748 | } | ||
749 | } | ||
750 | |||
751 | static int dsps_create_musb_pdev(struct dsps_glue *glue, | 723 | static int dsps_create_musb_pdev(struct dsps_glue *glue, |
752 | struct platform_device *parent) | 724 | struct platform_device *parent) |
753 | { | 725 | { |
@@ -786,6 +758,7 @@ static int dsps_create_musb_pdev(struct dsps_glue *glue, | |||
786 | musb->dev.parent = dev; | 758 | musb->dev.parent = dev; |
787 | musb->dev.dma_mask = &musb_dmamask; | 759 | musb->dev.dma_mask = &musb_dmamask; |
788 | musb->dev.coherent_dma_mask = musb_dmamask; | 760 | musb->dev.coherent_dma_mask = musb_dmamask; |
761 | device_set_of_node_from_dev(&musb->dev, &parent->dev); | ||
789 | 762 | ||
790 | glue->musb = musb; | 763 | glue->musb = musb; |
791 | 764 | ||
@@ -807,7 +780,7 @@ static int dsps_create_musb_pdev(struct dsps_glue *glue, | |||
807 | config->num_eps = get_int_prop(dn, "mentor,num-eps"); | 780 | config->num_eps = get_int_prop(dn, "mentor,num-eps"); |
808 | config->ram_bits = get_int_prop(dn, "mentor,ram-bits"); | 781 | config->ram_bits = get_int_prop(dn, "mentor,ram-bits"); |
809 | config->host_port_deassert_reset_at_resume = 1; | 782 | config->host_port_deassert_reset_at_resume = 1; |
810 | pdata.mode = get_musb_port_mode(dev); | 783 | pdata.mode = musb_get_mode(dev); |
811 | /* DT keeps this entry in mA, musb expects it as per USB spec */ | 784 | /* DT keeps this entry in mA, musb expects it as per USB spec */ |
812 | pdata.power = get_int_prop(dn, "mentor,power") / 2; | 785 | pdata.power = get_int_prop(dn, "mentor,power") / 2; |
813 | 786 | ||
@@ -1047,7 +1020,7 @@ static int dsps_resume(struct device *dev) | |||
1047 | musb_writel(mbase, wrp->tx_mode, glue->context.tx_mode); | 1020 | musb_writel(mbase, wrp->tx_mode, glue->context.tx_mode); |
1048 | musb_writel(mbase, wrp->rx_mode, glue->context.rx_mode); | 1021 | musb_writel(mbase, wrp->rx_mode, glue->context.rx_mode); |
1049 | if (musb->xceiv->otg->state == OTG_STATE_B_IDLE && | 1022 | if (musb->xceiv->otg->state == OTG_STATE_B_IDLE && |
1050 | musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE) | 1023 | musb->port_mode == MUSB_OTG) |
1051 | dsps_mod_timer(glue, -1); | 1024 | dsps_mod_timer(glue, -1); |
1052 | 1025 | ||
1053 | pm_runtime_put(dev); | 1026 | pm_runtime_put(dev); |
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 71c5835ea9cd..eae8b1b1b45b 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c | |||
@@ -1794,16 +1794,12 @@ int musb_gadget_setup(struct musb *musb) | |||
1794 | musb->g.speed = USB_SPEED_UNKNOWN; | 1794 | musb->g.speed = USB_SPEED_UNKNOWN; |
1795 | 1795 | ||
1796 | MUSB_DEV_MODE(musb); | 1796 | MUSB_DEV_MODE(musb); |
1797 | musb->xceiv->otg->default_a = 0; | ||
1798 | musb->xceiv->otg->state = OTG_STATE_B_IDLE; | 1797 | musb->xceiv->otg->state = OTG_STATE_B_IDLE; |
1799 | 1798 | ||
1800 | /* this "gadget" abstracts/virtualizes the controller */ | 1799 | /* this "gadget" abstracts/virtualizes the controller */ |
1801 | musb->g.name = musb_driver_name; | 1800 | musb->g.name = musb_driver_name; |
1802 | #if IS_ENABLED(CONFIG_USB_MUSB_DUAL_ROLE) | 1801 | /* don't support otg protocols */ |
1803 | musb->g.is_otg = 1; | ||
1804 | #elif IS_ENABLED(CONFIG_USB_MUSB_GADGET) | ||
1805 | musb->g.is_otg = 0; | 1802 | musb->g.is_otg = 0; |
1806 | #endif | ||
1807 | INIT_DELAYED_WORK(&musb->gadget_work, musb_gadget_work); | 1803 | INIT_DELAYED_WORK(&musb->gadget_work, musb_gadget_work); |
1808 | musb_g_init_endpoints(musb); | 1804 | musb_g_init_endpoints(musb); |
1809 | 1805 | ||
@@ -1823,7 +1819,7 @@ err: | |||
1823 | 1819 | ||
1824 | void musb_gadget_cleanup(struct musb *musb) | 1820 | void musb_gadget_cleanup(struct musb *musb) |
1825 | { | 1821 | { |
1826 | if (musb->port_mode == MUSB_PORT_MODE_HOST) | 1822 | if (musb->port_mode == MUSB_HOST) |
1827 | return; | 1823 | return; |
1828 | 1824 | ||
1829 | cancel_delayed_work_sync(&musb->gadget_work); | 1825 | cancel_delayed_work_sync(&musb->gadget_work); |
diff --git a/drivers/usb/musb/musb_gadget.h b/drivers/usb/musb/musb_gadget.h index 9c34aca06db6..d02663660813 100644 --- a/drivers/usb/musb/musb_gadget.h +++ b/drivers/usb/musb/musb_gadget.h | |||
@@ -60,10 +60,7 @@ struct musb_request { | |||
60 | enum buffer_map_state map_state; | 60 | enum buffer_map_state map_state; |
61 | }; | 61 | }; |
62 | 62 | ||
63 | static inline struct musb_request *to_musb_request(struct usb_request *req) | 63 | #define to_musb_request(r) container_of((r), struct musb_request, request) |
64 | { | ||
65 | return req ? container_of(req, struct musb_request, request) : NULL; | ||
66 | } | ||
67 | 64 | ||
68 | extern struct usb_request * | 65 | extern struct usb_request * |
69 | musb_alloc_request(struct usb_ep *ep, gfp_t gfp_flags); | 66 | musb_alloc_request(struct usb_ep *ep, gfp_t gfp_flags); |
@@ -99,10 +96,7 @@ struct musb_ep { | |||
99 | u8 hb_mult; | 96 | u8 hb_mult; |
100 | }; | 97 | }; |
101 | 98 | ||
102 | static inline struct musb_ep *to_musb_ep(struct usb_ep *ep) | 99 | #define to_musb_ep(ep) container_of((ep), struct musb_ep, end_point) |
103 | { | ||
104 | return ep ? container_of(ep, struct musb_ep, end_point) : NULL; | ||
105 | } | ||
106 | 100 | ||
107 | static inline struct musb_request *next_request(struct musb_ep *ep) | 101 | static inline struct musb_request *next_request(struct musb_ep *ep) |
108 | { | 102 | { |
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 15a42cee0a9c..8000c7c02f79 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c | |||
@@ -2735,7 +2735,7 @@ int musb_host_alloc(struct musb *musb) | |||
2735 | 2735 | ||
2736 | void musb_host_cleanup(struct musb *musb) | 2736 | void musb_host_cleanup(struct musb *musb) |
2737 | { | 2737 | { |
2738 | if (musb->port_mode == MUSB_PORT_MODE_GADGET) | 2738 | if (musb->port_mode == MUSB_PERIPHERAL) |
2739 | return; | 2739 | return; |
2740 | usb_remove_hcd(musb->hcd); | 2740 | usb_remove_hcd(musb->hcd); |
2741 | } | 2741 | } |
@@ -2750,13 +2750,13 @@ int musb_host_setup(struct musb *musb, int power_budget) | |||
2750 | int ret; | 2750 | int ret; |
2751 | struct usb_hcd *hcd = musb->hcd; | 2751 | struct usb_hcd *hcd = musb->hcd; |
2752 | 2752 | ||
2753 | if (musb->port_mode == MUSB_PORT_MODE_HOST) { | 2753 | if (musb->port_mode == MUSB_HOST) { |
2754 | MUSB_HST_MODE(musb); | 2754 | MUSB_HST_MODE(musb); |
2755 | musb->xceiv->otg->default_a = 1; | ||
2756 | musb->xceiv->otg->state = OTG_STATE_A_IDLE; | 2755 | musb->xceiv->otg->state = OTG_STATE_A_IDLE; |
2757 | } | 2756 | } |
2758 | otg_set_host(musb->xceiv->otg, &hcd->self); | 2757 | otg_set_host(musb->xceiv->otg, &hcd->self); |
2759 | hcd->self.otg_port = 1; | 2758 | /* don't support otg protocols */ |
2759 | hcd->self.otg_port = 0; | ||
2760 | musb->xceiv->otg->host = &hcd->self; | 2760 | musb->xceiv->otg->host = &hcd->self; |
2761 | hcd->power_budget = 2 * (power_budget ? : 250); | 2761 | hcd->power_budget = 2 * (power_budget ? : 250); |
2762 | hcd->skip_phy_initialization = 1; | 2762 | hcd->skip_phy_initialization = 1; |
diff --git a/drivers/usb/musb/musb_io.h b/drivers/usb/musb/musb_io.h index b7025b2e6e00..8058a58092cf 100644 --- a/drivers/usb/musb/musb_io.h +++ b/drivers/usb/musb/musb_io.h | |||
@@ -16,7 +16,6 @@ | |||
16 | 16 | ||
17 | /** | 17 | /** |
18 | * struct musb_io - IO functions for MUSB | 18 | * struct musb_io - IO functions for MUSB |
19 | * @quirks: platform specific flags | ||
20 | * @ep_offset: platform specific function to get end point offset | 19 | * @ep_offset: platform specific function to get end point offset |
21 | * @ep_select: platform specific function to select end point | 20 | * @ep_select: platform specific function to select end point |
22 | * @fifo_offset: platform specific function to get fifo offset | 21 | * @fifo_offset: platform specific function to get fifo offset |
@@ -25,7 +24,6 @@ | |||
25 | * @busctl_offset: platform specific function to get busctl offset | 24 | * @busctl_offset: platform specific function to get busctl offset |
26 | */ | 25 | */ |
27 | struct musb_io { | 26 | struct musb_io { |
28 | u32 quirks; | ||
29 | u32 (*ep_offset)(u8 epnum, u16 offset); | 27 | u32 (*ep_offset)(u8 epnum, u16 offset); |
30 | void (*ep_select)(void __iomem *mbase, u8 epnum); | 28 | void (*ep_select)(void __iomem *mbase, u8 epnum); |
31 | u32 (*fifo_offset)(u8 epnum); | 29 | u32 (*fifo_offset)(u8 epnum); |
@@ -39,7 +37,7 @@ extern u8 (*musb_readb)(const void __iomem *addr, unsigned offset); | |||
39 | extern void (*musb_writeb)(void __iomem *addr, unsigned offset, u8 data); | 37 | extern void (*musb_writeb)(void __iomem *addr, unsigned offset, u8 data); |
40 | extern u16 (*musb_readw)(const void __iomem *addr, unsigned offset); | 38 | extern u16 (*musb_readw)(const void __iomem *addr, unsigned offset); |
41 | extern void (*musb_writew)(void __iomem *addr, unsigned offset, u16 data); | 39 | extern void (*musb_writew)(void __iomem *addr, unsigned offset, u16 data); |
42 | extern u32 (*musb_readl)(const void __iomem *addr, unsigned offset); | 40 | extern u32 musb_readl(const void __iomem *addr, unsigned offset); |
43 | extern void (*musb_writel)(void __iomem *addr, unsigned offset, u32 data); | 41 | extern void musb_writel(void __iomem *addr, unsigned offset, u32 data); |
44 | 42 | ||
45 | #endif | 43 | #endif |
diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h index 88466622c89f..5cd7264fc2cb 100644 --- a/drivers/usb/musb/musb_regs.h +++ b/drivers/usb/musb/musb_regs.h | |||
@@ -273,67 +273,12 @@ | |||
273 | #define MUSB_RXHUBADDR 0x06 | 273 | #define MUSB_RXHUBADDR 0x06 |
274 | #define MUSB_RXHUBPORT 0x07 | 274 | #define MUSB_RXHUBPORT 0x07 |
275 | 275 | ||
276 | static inline void musb_write_txfifosz(void __iomem *mbase, u8 c_size) | ||
277 | { | ||
278 | musb_writeb(mbase, MUSB_TXFIFOSZ, c_size); | ||
279 | } | ||
280 | |||
281 | static inline void musb_write_txfifoadd(void __iomem *mbase, u16 c_off) | ||
282 | { | ||
283 | musb_writew(mbase, MUSB_TXFIFOADD, c_off); | ||
284 | } | ||
285 | |||
286 | static inline void musb_write_rxfifosz(void __iomem *mbase, u8 c_size) | ||
287 | { | ||
288 | musb_writeb(mbase, MUSB_RXFIFOSZ, c_size); | ||
289 | } | ||
290 | |||
291 | static inline void musb_write_rxfifoadd(void __iomem *mbase, u16 c_off) | ||
292 | { | ||
293 | musb_writew(mbase, MUSB_RXFIFOADD, c_off); | ||
294 | } | ||
295 | |||
296 | static inline void musb_write_ulpi_buscontrol(void __iomem *mbase, u8 val) | ||
297 | { | ||
298 | musb_writeb(mbase, MUSB_ULPI_BUSCONTROL, val); | ||
299 | } | ||
300 | |||
301 | static inline u8 musb_read_txfifosz(void __iomem *mbase) | ||
302 | { | ||
303 | return musb_readb(mbase, MUSB_TXFIFOSZ); | ||
304 | } | ||
305 | |||
306 | static inline u16 musb_read_txfifoadd(void __iomem *mbase) | ||
307 | { | ||
308 | return musb_readw(mbase, MUSB_TXFIFOADD); | ||
309 | } | ||
310 | |||
311 | static inline u8 musb_read_rxfifosz(void __iomem *mbase) | ||
312 | { | ||
313 | return musb_readb(mbase, MUSB_RXFIFOSZ); | ||
314 | } | ||
315 | |||
316 | static inline u16 musb_read_rxfifoadd(void __iomem *mbase) | ||
317 | { | ||
318 | return musb_readw(mbase, MUSB_RXFIFOADD); | ||
319 | } | ||
320 | |||
321 | static inline u8 musb_read_ulpi_buscontrol(void __iomem *mbase) | ||
322 | { | ||
323 | return musb_readb(mbase, MUSB_ULPI_BUSCONTROL); | ||
324 | } | ||
325 | |||
326 | static inline u8 musb_read_configdata(void __iomem *mbase) | 276 | static inline u8 musb_read_configdata(void __iomem *mbase) |
327 | { | 277 | { |
328 | musb_writeb(mbase, MUSB_INDEX, 0); | 278 | musb_writeb(mbase, MUSB_INDEX, 0); |
329 | return musb_readb(mbase, 0x10 + MUSB_CONFIGDATA); | 279 | return musb_readb(mbase, 0x10 + MUSB_CONFIGDATA); |
330 | } | 280 | } |
331 | 281 | ||
332 | static inline u16 musb_read_hwvers(void __iomem *mbase) | ||
333 | { | ||
334 | return musb_readw(mbase, MUSB_HWVERS); | ||
335 | } | ||
336 | |||
337 | static inline void musb_write_rxfunaddr(struct musb *musb, u8 epnum, | 282 | static inline void musb_write_rxfunaddr(struct musb *musb, u8 epnum, |
338 | u8 qh_addr_reg) | 283 | u8 qh_addr_reg) |
339 | { | 284 | { |
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index 2f8dd9826e94..a84ec27c4c12 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c | |||
@@ -254,7 +254,7 @@ static int musb_has_gadget(struct musb *musb) | |||
254 | #ifdef CONFIG_USB_MUSB_HOST | 254 | #ifdef CONFIG_USB_MUSB_HOST |
255 | return 1; | 255 | return 1; |
256 | #else | 256 | #else |
257 | return musb->port_mode == MUSB_PORT_MODE_HOST; | 257 | return musb->port_mode == MUSB_HOST; |
258 | #endif | 258 | #endif |
259 | } | 259 | } |
260 | 260 | ||
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index 4389fc3422bd..a688f7f87829 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c | |||
@@ -10,7 +10,71 @@ | |||
10 | #include <linux/platform_device.h> | 10 | #include <linux/platform_device.h> |
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include "musb_core.h" | 12 | #include "musb_core.h" |
13 | #include "musbhsdma.h" | 13 | |
14 | #define MUSB_HSDMA_BASE 0x200 | ||
15 | #define MUSB_HSDMA_INTR (MUSB_HSDMA_BASE + 0) | ||
16 | #define MUSB_HSDMA_CONTROL 0x4 | ||
17 | #define MUSB_HSDMA_ADDRESS 0x8 | ||
18 | #define MUSB_HSDMA_COUNT 0xc | ||
19 | |||
20 | #define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset) \ | ||
21 | (MUSB_HSDMA_BASE + (_bchannel << 4) + _offset) | ||
22 | |||
23 | #define musb_read_hsdma_addr(mbase, bchannel) \ | ||
24 | musb_readl(mbase, \ | ||
25 | MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS)) | ||
26 | |||
27 | #define musb_write_hsdma_addr(mbase, bchannel, addr) \ | ||
28 | musb_writel(mbase, \ | ||
29 | MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS), \ | ||
30 | addr) | ||
31 | |||
32 | #define musb_read_hsdma_count(mbase, bchannel) \ | ||
33 | musb_readl(mbase, \ | ||
34 | MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT)) | ||
35 | |||
36 | #define musb_write_hsdma_count(mbase, bchannel, len) \ | ||
37 | musb_writel(mbase, \ | ||
38 | MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT), \ | ||
39 | len) | ||
40 | /* control register (16-bit): */ | ||
41 | #define MUSB_HSDMA_ENABLE_SHIFT 0 | ||
42 | #define MUSB_HSDMA_TRANSMIT_SHIFT 1 | ||
43 | #define MUSB_HSDMA_MODE1_SHIFT 2 | ||
44 | #define MUSB_HSDMA_IRQENABLE_SHIFT 3 | ||
45 | #define MUSB_HSDMA_ENDPOINT_SHIFT 4 | ||
46 | #define MUSB_HSDMA_BUSERROR_SHIFT 8 | ||
47 | #define MUSB_HSDMA_BURSTMODE_SHIFT 9 | ||
48 | #define MUSB_HSDMA_BURSTMODE (3 << MUSB_HSDMA_BURSTMODE_SHIFT) | ||
49 | #define MUSB_HSDMA_BURSTMODE_UNSPEC 0 | ||
50 | #define MUSB_HSDMA_BURSTMODE_INCR4 1 | ||
51 | #define MUSB_HSDMA_BURSTMODE_INCR8 2 | ||
52 | #define MUSB_HSDMA_BURSTMODE_INCR16 3 | ||
53 | |||
54 | #define MUSB_HSDMA_CHANNELS 8 | ||
55 | |||
56 | struct musb_dma_controller; | ||
57 | |||
58 | struct musb_dma_channel { | ||
59 | struct dma_channel channel; | ||
60 | struct musb_dma_controller *controller; | ||
61 | u32 start_addr; | ||
62 | u32 len; | ||
63 | u16 max_packet_sz; | ||
64 | u8 idx; | ||
65 | u8 epnum; | ||
66 | u8 transmit; | ||
67 | }; | ||
68 | |||
69 | struct musb_dma_controller { | ||
70 | struct dma_controller controller; | ||
71 | struct musb_dma_channel channel[MUSB_HSDMA_CHANNELS]; | ||
72 | void *private_data; | ||
73 | void __iomem *base; | ||
74 | u8 channel_count; | ||
75 | u8 used_channels; | ||
76 | int irq; | ||
77 | }; | ||
14 | 78 | ||
15 | static void dma_channel_release(struct dma_channel *channel); | 79 | static void dma_channel_release(struct dma_channel *channel); |
16 | 80 | ||
@@ -135,14 +199,6 @@ static int dma_channel_program(struct dma_channel *channel, | |||
135 | BUG_ON(channel->status == MUSB_DMA_STATUS_UNKNOWN || | 199 | BUG_ON(channel->status == MUSB_DMA_STATUS_UNKNOWN || |
136 | channel->status == MUSB_DMA_STATUS_BUSY); | 200 | channel->status == MUSB_DMA_STATUS_BUSY); |
137 | 201 | ||
138 | /* Let targets check/tweak the arguments */ | ||
139 | if (musb->ops->adjust_channel_params) { | ||
140 | int ret = musb->ops->adjust_channel_params(channel, | ||
141 | packet_sz, &mode, &dma_addr, &len); | ||
142 | if (ret) | ||
143 | return ret; | ||
144 | } | ||
145 | |||
146 | /* | 202 | /* |
147 | * The DMA engine in RTL1.8 and above cannot handle | 203 | * The DMA engine in RTL1.8 and above cannot handle |
148 | * DMA addresses that are not aligned to a 4 byte boundary. | 204 | * DMA addresses that are not aligned to a 4 byte boundary. |
diff --git a/drivers/usb/musb/musbhsdma.h b/drivers/usb/musb/musbhsdma.h deleted file mode 100644 index 93665135aff1..000000000000 --- a/drivers/usb/musb/musbhsdma.h +++ /dev/null | |||
@@ -1,72 +0,0 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * MUSB OTG driver - support for Mentor's DMA controller | ||
4 | * | ||
5 | * Copyright 2005 Mentor Graphics Corporation | ||
6 | * Copyright (C) 2005-2007 by Texas Instruments | ||
7 | */ | ||
8 | |||
9 | #define MUSB_HSDMA_BASE 0x200 | ||
10 | #define MUSB_HSDMA_INTR (MUSB_HSDMA_BASE + 0) | ||
11 | #define MUSB_HSDMA_CONTROL 0x4 | ||
12 | #define MUSB_HSDMA_ADDRESS 0x8 | ||
13 | #define MUSB_HSDMA_COUNT 0xc | ||
14 | |||
15 | #define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset) \ | ||
16 | (MUSB_HSDMA_BASE + (_bchannel << 4) + _offset) | ||
17 | |||
18 | #define musb_read_hsdma_addr(mbase, bchannel) \ | ||
19 | musb_readl(mbase, \ | ||
20 | MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS)) | ||
21 | |||
22 | #define musb_write_hsdma_addr(mbase, bchannel, addr) \ | ||
23 | musb_writel(mbase, \ | ||
24 | MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS), \ | ||
25 | addr) | ||
26 | |||
27 | #define musb_read_hsdma_count(mbase, bchannel) \ | ||
28 | musb_readl(mbase, \ | ||
29 | MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT)) | ||
30 | |||
31 | #define musb_write_hsdma_count(mbase, bchannel, len) \ | ||
32 | musb_writel(mbase, \ | ||
33 | MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT), \ | ||
34 | len) | ||
35 | /* control register (16-bit): */ | ||
36 | #define MUSB_HSDMA_ENABLE_SHIFT 0 | ||
37 | #define MUSB_HSDMA_TRANSMIT_SHIFT 1 | ||
38 | #define MUSB_HSDMA_MODE1_SHIFT 2 | ||
39 | #define MUSB_HSDMA_IRQENABLE_SHIFT 3 | ||
40 | #define MUSB_HSDMA_ENDPOINT_SHIFT 4 | ||
41 | #define MUSB_HSDMA_BUSERROR_SHIFT 8 | ||
42 | #define MUSB_HSDMA_BURSTMODE_SHIFT 9 | ||
43 | #define MUSB_HSDMA_BURSTMODE (3 << MUSB_HSDMA_BURSTMODE_SHIFT) | ||
44 | #define MUSB_HSDMA_BURSTMODE_UNSPEC 0 | ||
45 | #define MUSB_HSDMA_BURSTMODE_INCR4 1 | ||
46 | #define MUSB_HSDMA_BURSTMODE_INCR8 2 | ||
47 | #define MUSB_HSDMA_BURSTMODE_INCR16 3 | ||
48 | |||
49 | #define MUSB_HSDMA_CHANNELS 8 | ||
50 | |||
51 | struct musb_dma_controller; | ||
52 | |||
53 | struct musb_dma_channel { | ||
54 | struct dma_channel channel; | ||
55 | struct musb_dma_controller *controller; | ||
56 | u32 start_addr; | ||
57 | u32 len; | ||
58 | u16 max_packet_sz; | ||
59 | u8 idx; | ||
60 | u8 epnum; | ||
61 | u8 transmit; | ||
62 | }; | ||
63 | |||
64 | struct musb_dma_controller { | ||
65 | struct dma_controller controller; | ||
66 | struct musb_dma_channel channel[MUSB_HSDMA_CHANNELS]; | ||
67 | void *private_data; | ||
68 | void __iomem *base; | ||
69 | u8 channel_count; | ||
70 | u8 used_channels; | ||
71 | int irq; | ||
72 | }; | ||
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 5d705930ef47..b1dd81fb5f55 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c | |||
@@ -77,7 +77,6 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on) | |||
77 | otg_set_vbus(otg, 1); | 77 | otg_set_vbus(otg, 1); |
78 | } else { | 78 | } else { |
79 | musb->is_active = 1; | 79 | musb->is_active = 1; |
80 | otg->default_a = 1; | ||
81 | musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; | 80 | musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; |
82 | devctl |= MUSB_DEVCTL_SESSION; | 81 | devctl |= MUSB_DEVCTL_SESSION; |
83 | MUSB_HST_MODE(musb); | 82 | MUSB_HST_MODE(musb); |
@@ -89,7 +88,6 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on) | |||
89 | * jumping right to B_IDLE... | 88 | * jumping right to B_IDLE... |
90 | */ | 89 | */ |
91 | 90 | ||
92 | otg->default_a = 0; | ||
93 | musb->xceiv->otg->state = OTG_STATE_B_IDLE; | 91 | musb->xceiv->otg->state = OTG_STATE_B_IDLE; |
94 | devctl &= ~MUSB_DEVCTL_SESSION; | 92 | devctl &= ~MUSB_DEVCTL_SESSION; |
95 | 93 | ||
@@ -148,14 +146,12 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) | |||
148 | struct musb_hdrc_platform_data *pdata = | 146 | struct musb_hdrc_platform_data *pdata = |
149 | dev_get_platdata(musb->controller); | 147 | dev_get_platdata(musb->controller); |
150 | struct omap_musb_board_data *data = pdata->board_data; | 148 | struct omap_musb_board_data *data = pdata->board_data; |
151 | struct usb_otg *otg = musb->xceiv->otg; | ||
152 | 149 | ||
153 | pm_runtime_get_sync(musb->controller); | 150 | pm_runtime_get_sync(musb->controller); |
154 | switch (glue->status) { | 151 | switch (glue->status) { |
155 | case MUSB_ID_GROUND: | 152 | case MUSB_ID_GROUND: |
156 | dev_dbg(musb->controller, "ID GND\n"); | 153 | dev_dbg(musb->controller, "ID GND\n"); |
157 | 154 | ||
158 | otg->default_a = true; | ||
159 | musb->xceiv->otg->state = OTG_STATE_A_IDLE; | 155 | musb->xceiv->otg->state = OTG_STATE_A_IDLE; |
160 | musb->xceiv->last_event = USB_EVENT_ID; | 156 | musb->xceiv->last_event = USB_EVENT_ID; |
161 | if (musb->gadget_driver) { | 157 | if (musb->gadget_driver) { |
@@ -168,7 +164,6 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) | |||
168 | case MUSB_VBUS_VALID: | 164 | case MUSB_VBUS_VALID: |
169 | dev_dbg(musb->controller, "VBUS Connect\n"); | 165 | dev_dbg(musb->controller, "VBUS Connect\n"); |
170 | 166 | ||
171 | otg->default_a = false; | ||
172 | musb->xceiv->otg->state = OTG_STATE_B_IDLE; | 167 | musb->xceiv->otg->state = OTG_STATE_B_IDLE; |
173 | musb->xceiv->last_event = USB_EVENT_VBUS; | 168 | musb->xceiv->last_event = USB_EVENT_VBUS; |
174 | omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE); | 169 | omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE); |
@@ -239,21 +234,15 @@ static int omap2430_musb_init(struct musb *musb) | |||
239 | * up through ULPI. TWL4030-family PMICs include one, | 234 | * up through ULPI. TWL4030-family PMICs include one, |
240 | * which needs a driver, drivers aren't always needed. | 235 | * which needs a driver, drivers aren't always needed. |
241 | */ | 236 | */ |
242 | if (dev->parent->of_node) { | 237 | musb->phy = devm_phy_get(dev->parent, "usb2-phy"); |
243 | musb->phy = devm_phy_get(dev->parent, "usb2-phy"); | 238 | |
244 | 239 | /* We can't totally remove musb->xceiv as of now because | |
245 | /* We can't totally remove musb->xceiv as of now because | 240 | * musb core uses xceiv.state and xceiv.otg. Once we have |
246 | * musb core uses xceiv.state and xceiv.otg. Once we have | 241 | * a separate state machine to handle otg, these can be moved |
247 | * a separate state machine to handle otg, these can be moved | 242 | * out of xceiv and then we can start using the generic PHY |
248 | * out of xceiv and then we can start using the generic PHY | 243 | * framework |
249 | * framework | 244 | */ |
250 | */ | 245 | musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent, "usb-phy", 0); |
251 | musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent, | ||
252 | "usb-phy", 0); | ||
253 | } else { | ||
254 | musb->xceiv = devm_usb_get_phy_dev(dev, 0); | ||
255 | musb->phy = devm_phy_get(dev, "usb"); | ||
256 | } | ||
257 | 246 | ||
258 | if (IS_ERR(musb->xceiv)) { | 247 | if (IS_ERR(musb->xceiv)) { |
259 | status = PTR_ERR(musb->xceiv); | 248 | status = PTR_ERR(musb->xceiv); |
@@ -391,8 +380,13 @@ static int omap2430_probe(struct platform_device *pdev) | |||
391 | struct omap2430_glue *glue; | 380 | struct omap2430_glue *glue; |
392 | struct device_node *np = pdev->dev.of_node; | 381 | struct device_node *np = pdev->dev.of_node; |
393 | struct musb_hdrc_config *config; | 382 | struct musb_hdrc_config *config; |
383 | struct device_node *control_node; | ||
384 | struct platform_device *control_pdev; | ||
394 | int ret = -ENOMEM, val; | 385 | int ret = -ENOMEM, val; |
395 | 386 | ||
387 | if (!np) | ||
388 | return -ENODEV; | ||
389 | |||
396 | glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL); | 390 | glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL); |
397 | if (!glue) | 391 | if (!glue) |
398 | goto err0; | 392 | goto err0; |
@@ -412,47 +406,43 @@ static int omap2430_probe(struct platform_device *pdev) | |||
412 | glue->status = MUSB_UNKNOWN; | 406 | glue->status = MUSB_UNKNOWN; |
413 | glue->control_otghs = ERR_PTR(-ENODEV); | 407 | glue->control_otghs = ERR_PTR(-ENODEV); |
414 | 408 | ||
415 | if (np) { | 409 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
416 | struct device_node *control_node; | 410 | if (!pdata) |
417 | struct platform_device *control_pdev; | 411 | goto err2; |
418 | 412 | ||
419 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | 413 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); |
420 | if (!pdata) | 414 | if (!data) |
421 | goto err2; | 415 | goto err2; |
422 | 416 | ||
423 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | 417 | config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL); |
424 | if (!data) | 418 | if (!config) |
425 | goto err2; | 419 | goto err2; |
426 | 420 | ||
427 | config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL); | 421 | of_property_read_u32(np, "mode", (u32 *)&pdata->mode); |
428 | if (!config) | 422 | of_property_read_u32(np, "interface-type", |
423 | (u32 *)&data->interface_type); | ||
424 | of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps); | ||
425 | of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits); | ||
426 | of_property_read_u32(np, "power", (u32 *)&pdata->power); | ||
427 | |||
428 | ret = of_property_read_u32(np, "multipoint", &val); | ||
429 | if (!ret && val) | ||
430 | config->multipoint = true; | ||
431 | |||
432 | pdata->board_data = data; | ||
433 | pdata->config = config; | ||
434 | |||
435 | control_node = of_parse_phandle(np, "ctrl-module", 0); | ||
436 | if (control_node) { | ||
437 | control_pdev = of_find_device_by_node(control_node); | ||
438 | if (!control_pdev) { | ||
439 | dev_err(&pdev->dev, "Failed to get control device\n"); | ||
440 | ret = -EINVAL; | ||
429 | goto err2; | 441 | goto err2; |
430 | |||
431 | of_property_read_u32(np, "mode", (u32 *)&pdata->mode); | ||
432 | of_property_read_u32(np, "interface-type", | ||
433 | (u32 *)&data->interface_type); | ||
434 | of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps); | ||
435 | of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits); | ||
436 | of_property_read_u32(np, "power", (u32 *)&pdata->power); | ||
437 | |||
438 | ret = of_property_read_u32(np, "multipoint", &val); | ||
439 | if (!ret && val) | ||
440 | config->multipoint = true; | ||
441 | |||
442 | pdata->board_data = data; | ||
443 | pdata->config = config; | ||
444 | |||
445 | control_node = of_parse_phandle(np, "ctrl-module", 0); | ||
446 | if (control_node) { | ||
447 | control_pdev = of_find_device_by_node(control_node); | ||
448 | if (!control_pdev) { | ||
449 | dev_err(&pdev->dev, "Failed to get control device\n"); | ||
450 | ret = -EINVAL; | ||
451 | goto err2; | ||
452 | } | ||
453 | glue->control_otghs = &control_pdev->dev; | ||
454 | } | 442 | } |
443 | glue->control_otghs = &control_pdev->dev; | ||
455 | } | 444 | } |
445 | |||
456 | pdata->platform_ops = &omap2430_ops; | 446 | pdata->platform_ops = &omap2430_ops; |
457 | 447 | ||
458 | platform_set_drvdata(pdev, glue); | 448 | platform_set_drvdata(pdev, glue); |
diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c index 2d201219ecff..832a41f9ee7d 100644 --- a/drivers/usb/musb/sunxi.c +++ b/drivers/usb/musb/sunxi.c | |||
@@ -105,13 +105,11 @@ static void sunxi_musb_work(struct work_struct *work) | |||
105 | devctl = readb(musb->mregs + SUNXI_MUSB_DEVCTL); | 105 | devctl = readb(musb->mregs + SUNXI_MUSB_DEVCTL); |
106 | if (test_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags)) { | 106 | if (test_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags)) { |
107 | set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags); | 107 | set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags); |
108 | musb->xceiv->otg->default_a = 1; | ||
109 | musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; | 108 | musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; |
110 | MUSB_HST_MODE(musb); | 109 | MUSB_HST_MODE(musb); |
111 | devctl |= MUSB_DEVCTL_SESSION; | 110 | devctl |= MUSB_DEVCTL_SESSION; |
112 | } else { | 111 | } else { |
113 | clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags); | 112 | clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags); |
114 | musb->xceiv->otg->default_a = 0; | ||
115 | musb->xceiv->otg->state = OTG_STATE_B_IDLE; | 113 | musb->xceiv->otg->state = OTG_STATE_B_IDLE; |
116 | MUSB_DEV_MODE(musb); | 114 | MUSB_DEV_MODE(musb); |
117 | devctl &= ~MUSB_DEVCTL_SESSION; | 115 | devctl &= ~MUSB_DEVCTL_SESSION; |
@@ -347,7 +345,7 @@ static int sunxi_musb_set_mode(struct musb *musb, u8 mode) | |||
347 | if (glue->phy_mode == new_mode) | 345 | if (glue->phy_mode == new_mode) |
348 | return 0; | 346 | return 0; |
349 | 347 | ||
350 | if (musb->port_mode != MUSB_PORT_MODE_DUAL_ROLE) { | 348 | if (musb->port_mode != MUSB_OTG) { |
351 | dev_err(musb->controller->parent, | 349 | dev_err(musb->controller->parent, |
352 | "Error changing modes is only supported in dual role mode\n"); | 350 | "Error changing modes is only supported in dual role mode\n"); |
353 | return -EINVAL; | 351 | return -EINVAL; |
@@ -651,10 +649,8 @@ static const struct musb_hdrc_config sunxi_musb_hdrc_config = { | |||
651 | .fifo_cfg_size = ARRAY_SIZE(sunxi_musb_mode_cfg), | 649 | .fifo_cfg_size = ARRAY_SIZE(sunxi_musb_mode_cfg), |
652 | .multipoint = true, | 650 | .multipoint = true, |
653 | .dyn_fifo = true, | 651 | .dyn_fifo = true, |
654 | .soft_con = true, | ||
655 | .num_eps = SUNXI_MUSB_MAX_EP_NUM, | 652 | .num_eps = SUNXI_MUSB_MAX_EP_NUM, |
656 | .ram_bits = SUNXI_MUSB_RAM_BITS, | 653 | .ram_bits = SUNXI_MUSB_RAM_BITS, |
657 | .dma = 0, | ||
658 | }; | 654 | }; |
659 | 655 | ||
660 | static struct musb_hdrc_config sunxi_musb_hdrc_config_h3 = { | 656 | static struct musb_hdrc_config sunxi_musb_hdrc_config_h3 = { |
@@ -662,10 +658,8 @@ static struct musb_hdrc_config sunxi_musb_hdrc_config_h3 = { | |||
662 | .fifo_cfg_size = ARRAY_SIZE(sunxi_musb_mode_cfg_h3), | 658 | .fifo_cfg_size = ARRAY_SIZE(sunxi_musb_mode_cfg_h3), |
663 | .multipoint = true, | 659 | .multipoint = true, |
664 | .dyn_fifo = true, | 660 | .dyn_fifo = true, |
665 | .soft_con = true, | ||
666 | .num_eps = SUNXI_MUSB_MAX_EP_NUM_H3, | 661 | .num_eps = SUNXI_MUSB_MAX_EP_NUM_H3, |
667 | .ram_bits = SUNXI_MUSB_RAM_BITS, | 662 | .ram_bits = SUNXI_MUSB_RAM_BITS, |
668 | .dma = 0, | ||
669 | }; | 663 | }; |
670 | 664 | ||
671 | 665 | ||
@@ -690,19 +684,19 @@ static int sunxi_musb_probe(struct platform_device *pdev) | |||
690 | switch (usb_get_dr_mode(&pdev->dev)) { | 684 | switch (usb_get_dr_mode(&pdev->dev)) { |
691 | #if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_HOST | 685 | #if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_HOST |
692 | case USB_DR_MODE_HOST: | 686 | case USB_DR_MODE_HOST: |
693 | pdata.mode = MUSB_PORT_MODE_HOST; | 687 | pdata.mode = MUSB_HOST; |
694 | glue->phy_mode = PHY_MODE_USB_HOST; | 688 | glue->phy_mode = PHY_MODE_USB_HOST; |
695 | break; | 689 | break; |
696 | #endif | 690 | #endif |
697 | #if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_GADGET | 691 | #if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_GADGET |
698 | case USB_DR_MODE_PERIPHERAL: | 692 | case USB_DR_MODE_PERIPHERAL: |
699 | pdata.mode = MUSB_PORT_MODE_GADGET; | 693 | pdata.mode = MUSB_PERIPHERAL; |
700 | glue->phy_mode = PHY_MODE_USB_DEVICE; | 694 | glue->phy_mode = PHY_MODE_USB_DEVICE; |
701 | break; | 695 | break; |
702 | #endif | 696 | #endif |
703 | #ifdef CONFIG_USB_MUSB_DUAL_ROLE | 697 | #ifdef CONFIG_USB_MUSB_DUAL_ROLE |
704 | case USB_DR_MODE_OTG: | 698 | case USB_DR_MODE_OTG: |
705 | pdata.mode = MUSB_PORT_MODE_DUAL_ROLE; | 699 | pdata.mode = MUSB_OTG; |
706 | glue->phy_mode = PHY_MODE_USB_OTG; | 700 | glue->phy_mode = PHY_MODE_USB_OTG; |
707 | break; | 701 | break; |
708 | #endif | 702 | #endif |
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c index 27b4a77a9e23..73538d1d0524 100644 --- a/drivers/usb/musb/ux500.c +++ b/drivers/usb/musb/ux500.c | |||
@@ -62,7 +62,6 @@ static void ux500_musb_set_vbus(struct musb *musb, int is_on) | |||
62 | 62 | ||
63 | } else { | 63 | } else { |
64 | musb->is_active = 1; | 64 | musb->is_active = 1; |
65 | musb->xceiv->otg->default_a = 1; | ||
66 | musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; | 65 | musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; |
67 | devctl |= MUSB_DEVCTL_SESSION; | 66 | devctl |= MUSB_DEVCTL_SESSION; |
68 | MUSB_HST_MODE(musb); | 67 | MUSB_HST_MODE(musb); |
@@ -73,7 +72,6 @@ static void ux500_musb_set_vbus(struct musb *musb, int is_on) | |||
73 | /* NOTE: we're skipping A_WAIT_VFALL -> A_IDLE and jumping | 72 | /* NOTE: we're skipping A_WAIT_VFALL -> A_IDLE and jumping |
74 | * right to B_IDLE... | 73 | * right to B_IDLE... |
75 | */ | 74 | */ |
76 | musb->xceiv->otg->default_a = 0; | ||
77 | devctl &= ~MUSB_DEVCTL_SESSION; | 75 | devctl &= ~MUSB_DEVCTL_SESSION; |
78 | MUSB_DEV_MODE(musb); | 76 | MUSB_DEV_MODE(musb); |
79 | } | 77 | } |
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 0f8ab981d572..d7312eed6088 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig | |||
@@ -159,6 +159,16 @@ config USB_MXS_PHY | |||
159 | 159 | ||
160 | MXS Phy is used by some of the i.MX SoCs, for example imx23/28/6x. | 160 | MXS Phy is used by some of the i.MX SoCs, for example imx23/28/6x. |
161 | 161 | ||
162 | config USB_TEGRA_PHY | ||
163 | tristate "NVIDIA Tegra USB PHY Driver" | ||
164 | depends on ARCH_TEGRA | ||
165 | select USB_COMMON | ||
166 | select USB_PHY | ||
167 | select USB_ULPI | ||
168 | help | ||
169 | This driver provides PHY support for the USB controllers found | ||
170 | on NVIDIA Tegra SoC's. | ||
171 | |||
162 | config USB_ULPI | 172 | config USB_ULPI |
163 | bool "Generic ULPI Transceiver Driver" | 173 | bool "Generic ULPI Transceiver Driver" |
164 | depends on ARM || ARM64 | 174 | depends on ARM || ARM64 |
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 25e579fb92b8..df1d99010079 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile | |||
@@ -16,7 +16,7 @@ obj-$(CONFIG_AM335X_CONTROL_USB) += phy-am335x-control.o | |||
16 | obj-$(CONFIG_AM335X_PHY_USB) += phy-am335x.o | 16 | obj-$(CONFIG_AM335X_PHY_USB) += phy-am335x.o |
17 | obj-$(CONFIG_OMAP_OTG) += phy-omap-otg.o | 17 | obj-$(CONFIG_OMAP_OTG) += phy-omap-otg.o |
18 | obj-$(CONFIG_TWL6030_USB) += phy-twl6030-usb.o | 18 | obj-$(CONFIG_TWL6030_USB) += phy-twl6030-usb.o |
19 | obj-$(CONFIG_USB_EHCI_TEGRA) += phy-tegra-usb.o | 19 | obj-$(CONFIG_USB_TEGRA_PHY) += phy-tegra-usb.o |
20 | obj-$(CONFIG_USB_GPIO_VBUS) += phy-gpio-vbus-usb.o | 20 | obj-$(CONFIG_USB_GPIO_VBUS) += phy-gpio-vbus-usb.o |
21 | obj-$(CONFIG_USB_ISP1301) += phy-isp1301.o | 21 | obj-$(CONFIG_USB_ISP1301) += phy-isp1301.o |
22 | obj-$(CONFIG_USB_MV_OTG) += phy-mv-usb.o | 22 | obj-$(CONFIG_USB_MV_OTG) += phy-mv-usb.o |
diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c index b36fa8b953d0..27bdb7222527 100644 --- a/drivers/usb/phy/phy-am335x.c +++ b/drivers/usb/phy/phy-am335x.c | |||
@@ -96,8 +96,7 @@ static int am335x_phy_remove(struct platform_device *pdev) | |||
96 | #ifdef CONFIG_PM_SLEEP | 96 | #ifdef CONFIG_PM_SLEEP |
97 | static int am335x_phy_suspend(struct device *dev) | 97 | static int am335x_phy_suspend(struct device *dev) |
98 | { | 98 | { |
99 | struct platform_device *pdev = to_platform_device(dev); | 99 | struct am335x_phy *am_phy = dev_get_drvdata(dev); |
100 | struct am335x_phy *am_phy = platform_get_drvdata(pdev); | ||
101 | 100 | ||
102 | /* | 101 | /* |
103 | * Enable phy wakeup only if dev->power.can_wakeup is true. | 102 | * Enable phy wakeup only if dev->power.can_wakeup is true. |
@@ -117,8 +116,7 @@ static int am335x_phy_suspend(struct device *dev) | |||
117 | 116 | ||
118 | static int am335x_phy_resume(struct device *dev) | 117 | static int am335x_phy_resume(struct device *dev) |
119 | { | 118 | { |
120 | struct platform_device *pdev = to_platform_device(dev); | 119 | struct am335x_phy *am_phy = dev_get_drvdata(dev); |
121 | struct am335x_phy *am_phy = platform_get_drvdata(pdev); | ||
122 | 120 | ||
123 | phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, am_phy->dr_mode, true); | 121 | phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, am_phy->dr_mode, true); |
124 | 122 | ||
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c index 0e8d23e51732..ea7ef1dc0b42 100644 --- a/drivers/usb/phy/phy-tegra-usb.c +++ b/drivers/usb/phy/phy-tegra-usb.c | |||
@@ -236,13 +236,83 @@ static void set_phcd(struct tegra_usb_phy *phy, bool enable) | |||
236 | 236 | ||
237 | static int utmip_pad_open(struct tegra_usb_phy *phy) | 237 | static int utmip_pad_open(struct tegra_usb_phy *phy) |
238 | { | 238 | { |
239 | int ret; | ||
240 | |||
239 | phy->pad_clk = devm_clk_get(phy->u_phy.dev, "utmi-pads"); | 241 | phy->pad_clk = devm_clk_get(phy->u_phy.dev, "utmi-pads"); |
240 | if (IS_ERR(phy->pad_clk)) { | 242 | if (IS_ERR(phy->pad_clk)) { |
241 | pr_err("%s: can't get utmip pad clock\n", __func__); | 243 | ret = PTR_ERR(phy->pad_clk); |
242 | return PTR_ERR(phy->pad_clk); | 244 | dev_err(phy->u_phy.dev, |
245 | "Failed to get UTMIP pad clock: %d\n", ret); | ||
246 | return ret; | ||
243 | } | 247 | } |
244 | 248 | ||
245 | return 0; | 249 | phy->pad_rst = devm_reset_control_get_optional_shared( |
250 | phy->u_phy.dev, "utmi-pads"); | ||
251 | if (IS_ERR(phy->pad_rst)) { | ||
252 | ret = PTR_ERR(phy->pad_rst); | ||
253 | dev_err(phy->u_phy.dev, | ||
254 | "Failed to get UTMI-pads reset: %d\n", ret); | ||
255 | return ret; | ||
256 | } | ||
257 | |||
258 | ret = clk_prepare_enable(phy->pad_clk); | ||
259 | if (ret) { | ||
260 | dev_err(phy->u_phy.dev, | ||
261 | "Failed to enable UTMI-pads clock: %d\n", ret); | ||
262 | return ret; | ||
263 | } | ||
264 | |||
265 | spin_lock(&utmip_pad_lock); | ||
266 | |||
267 | ret = reset_control_deassert(phy->pad_rst); | ||
268 | if (ret) { | ||
269 | dev_err(phy->u_phy.dev, | ||
270 | "Failed to initialize UTMI-pads reset: %d\n", ret); | ||
271 | goto unlock; | ||
272 | } | ||
273 | |||
274 | ret = reset_control_assert(phy->pad_rst); | ||
275 | if (ret) { | ||
276 | dev_err(phy->u_phy.dev, | ||
277 | "Failed to assert UTMI-pads reset: %d\n", ret); | ||
278 | goto unlock; | ||
279 | } | ||
280 | |||
281 | udelay(1); | ||
282 | |||
283 | ret = reset_control_deassert(phy->pad_rst); | ||
284 | if (ret) | ||
285 | dev_err(phy->u_phy.dev, | ||
286 | "Failed to deassert UTMI-pads reset: %d\n", ret); | ||
287 | unlock: | ||
288 | spin_unlock(&utmip_pad_lock); | ||
289 | |||
290 | clk_disable_unprepare(phy->pad_clk); | ||
291 | |||
292 | return ret; | ||
293 | } | ||
294 | |||
295 | static int utmip_pad_close(struct tegra_usb_phy *phy) | ||
296 | { | ||
297 | int ret; | ||
298 | |||
299 | ret = clk_prepare_enable(phy->pad_clk); | ||
300 | if (ret) { | ||
301 | dev_err(phy->u_phy.dev, | ||
302 | "Failed to enable UTMI-pads clock: %d\n", ret); | ||
303 | return ret; | ||
304 | } | ||
305 | |||
306 | ret = reset_control_assert(phy->pad_rst); | ||
307 | if (ret) | ||
308 | dev_err(phy->u_phy.dev, | ||
309 | "Failed to assert UTMI-pads reset: %d\n", ret); | ||
310 | |||
311 | udelay(1); | ||
312 | |||
313 | clk_disable_unprepare(phy->pad_clk); | ||
314 | |||
315 | return ret; | ||
246 | } | 316 | } |
247 | 317 | ||
248 | static void utmip_pad_power_on(struct tegra_usb_phy *phy) | 318 | static void utmip_pad_power_on(struct tegra_usb_phy *phy) |
@@ -282,7 +352,7 @@ static int utmip_pad_power_off(struct tegra_usb_phy *phy) | |||
282 | void __iomem *base = phy->pad_regs; | 352 | void __iomem *base = phy->pad_regs; |
283 | 353 | ||
284 | if (!utmip_pad_count) { | 354 | if (!utmip_pad_count) { |
285 | pr_err("%s: utmip pad already powered off\n", __func__); | 355 | dev_err(phy->u_phy.dev, "UTMIP pad already powered off\n"); |
286 | return -EINVAL; | 356 | return -EINVAL; |
287 | } | 357 | } |
288 | 358 | ||
@@ -338,7 +408,8 @@ static void utmi_phy_clk_disable(struct tegra_usb_phy *phy) | |||
338 | set_phcd(phy, true); | 408 | set_phcd(phy, true); |
339 | 409 | ||
340 | if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0) | 410 | if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0) |
341 | pr_err("%s: timeout waiting for phy to stabilize\n", __func__); | 411 | dev_err(phy->u_phy.dev, |
412 | "Timeout waiting for PHY to stabilize on disable\n"); | ||
342 | } | 413 | } |
343 | 414 | ||
344 | static void utmi_phy_clk_enable(struct tegra_usb_phy *phy) | 415 | static void utmi_phy_clk_enable(struct tegra_usb_phy *phy) |
@@ -370,7 +441,8 @@ static void utmi_phy_clk_enable(struct tegra_usb_phy *phy) | |||
370 | 441 | ||
371 | if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, | 442 | if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, |
372 | USB_PHY_CLK_VALID)) | 443 | USB_PHY_CLK_VALID)) |
373 | pr_err("%s: timeout waiting for phy to stabilize\n", __func__); | 444 | dev_err(phy->u_phy.dev, |
445 | "Timeout waiting for PHY to stabilize on enable\n"); | ||
374 | } | 446 | } |
375 | 447 | ||
376 | static int utmi_phy_power_on(struct tegra_usb_phy *phy) | 448 | static int utmi_phy_power_on(struct tegra_usb_phy *phy) |
@@ -617,15 +689,15 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy) | |||
617 | 689 | ||
618 | ret = gpio_direction_output(phy->reset_gpio, 0); | 690 | ret = gpio_direction_output(phy->reset_gpio, 0); |
619 | if (ret < 0) { | 691 | if (ret < 0) { |
620 | dev_err(phy->u_phy.dev, "gpio %d not set to 0\n", | 692 | dev_err(phy->u_phy.dev, "GPIO %d not set to 0: %d\n", |
621 | phy->reset_gpio); | 693 | phy->reset_gpio, ret); |
622 | return ret; | 694 | return ret; |
623 | } | 695 | } |
624 | msleep(5); | 696 | msleep(5); |
625 | ret = gpio_direction_output(phy->reset_gpio, 1); | 697 | ret = gpio_direction_output(phy->reset_gpio, 1); |
626 | if (ret < 0) { | 698 | if (ret < 0) { |
627 | dev_err(phy->u_phy.dev, "gpio %d not set to 1\n", | 699 | dev_err(phy->u_phy.dev, "GPIO %d not set to 1: %d\n", |
628 | phy->reset_gpio); | 700 | phy->reset_gpio, ret); |
629 | return ret; | 701 | return ret; |
630 | } | 702 | } |
631 | 703 | ||
@@ -661,13 +733,13 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy) | |||
661 | /* Fix VbusInvalid due to floating VBUS */ | 733 | /* Fix VbusInvalid due to floating VBUS */ |
662 | ret = usb_phy_io_write(phy->ulpi, 0x40, 0x08); | 734 | ret = usb_phy_io_write(phy->ulpi, 0x40, 0x08); |
663 | if (ret) { | 735 | if (ret) { |
664 | pr_err("%s: ulpi write failed\n", __func__); | 736 | dev_err(phy->u_phy.dev, "ULPI write failed: %d\n", ret); |
665 | return ret; | 737 | return ret; |
666 | } | 738 | } |
667 | 739 | ||
668 | ret = usb_phy_io_write(phy->ulpi, 0x80, 0x0B); | 740 | ret = usb_phy_io_write(phy->ulpi, 0x80, 0x0B); |
669 | if (ret) { | 741 | if (ret) { |
670 | pr_err("%s: ulpi write failed\n", __func__); | 742 | dev_err(phy->u_phy.dev, "ULPI write failed: %d\n", ret); |
671 | return ret; | 743 | return ret; |
672 | } | 744 | } |
673 | 745 | ||
@@ -694,6 +766,9 @@ static void tegra_usb_phy_close(struct tegra_usb_phy *phy) | |||
694 | if (!IS_ERR(phy->vbus)) | 766 | if (!IS_ERR(phy->vbus)) |
695 | regulator_disable(phy->vbus); | 767 | regulator_disable(phy->vbus); |
696 | 768 | ||
769 | if (!phy->is_ulpi_phy) | ||
770 | utmip_pad_close(phy); | ||
771 | |||
697 | clk_disable_unprepare(phy->pll_u); | 772 | clk_disable_unprepare(phy->pll_u); |
698 | } | 773 | } |
699 | 774 | ||
@@ -728,28 +803,30 @@ static int ulpi_open(struct tegra_usb_phy *phy) | |||
728 | 803 | ||
729 | phy->clk = devm_clk_get(phy->u_phy.dev, "ulpi-link"); | 804 | phy->clk = devm_clk_get(phy->u_phy.dev, "ulpi-link"); |
730 | if (IS_ERR(phy->clk)) { | 805 | if (IS_ERR(phy->clk)) { |
731 | pr_err("%s: can't get ulpi clock\n", __func__); | 806 | err = PTR_ERR(phy->clk); |
732 | return PTR_ERR(phy->clk); | 807 | dev_err(phy->u_phy.dev, "Failed to get ULPI clock: %d\n", err); |
808 | return err; | ||
733 | } | 809 | } |
734 | 810 | ||
735 | err = devm_gpio_request(phy->u_phy.dev, phy->reset_gpio, | 811 | err = devm_gpio_request(phy->u_phy.dev, phy->reset_gpio, |
736 | "ulpi_phy_reset_b"); | 812 | "ulpi_phy_reset_b"); |
737 | if (err < 0) { | 813 | if (err < 0) { |
738 | dev_err(phy->u_phy.dev, "request failed for gpio: %d\n", | 814 | dev_err(phy->u_phy.dev, "Request failed for GPIO %d: %d\n", |
739 | phy->reset_gpio); | 815 | phy->reset_gpio, err); |
740 | return err; | 816 | return err; |
741 | } | 817 | } |
742 | 818 | ||
743 | err = gpio_direction_output(phy->reset_gpio, 0); | 819 | err = gpio_direction_output(phy->reset_gpio, 0); |
744 | if (err < 0) { | 820 | if (err < 0) { |
745 | dev_err(phy->u_phy.dev, "gpio %d direction not set to output\n", | 821 | dev_err(phy->u_phy.dev, |
746 | phy->reset_gpio); | 822 | "GPIO %d direction not set to output: %d\n", |
823 | phy->reset_gpio, err); | ||
747 | return err; | 824 | return err; |
748 | } | 825 | } |
749 | 826 | ||
750 | phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0); | 827 | phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0); |
751 | if (!phy->ulpi) { | 828 | if (!phy->ulpi) { |
752 | dev_err(phy->u_phy.dev, "otg_ulpi_create returned NULL\n"); | 829 | dev_err(phy->u_phy.dev, "Failed to create ULPI OTG\n"); |
753 | err = -ENOMEM; | 830 | err = -ENOMEM; |
754 | return err; | 831 | return err; |
755 | } | 832 | } |
@@ -766,8 +843,10 @@ static int tegra_usb_phy_init(struct tegra_usb_phy *phy) | |||
766 | 843 | ||
767 | phy->pll_u = devm_clk_get(phy->u_phy.dev, "pll_u"); | 844 | phy->pll_u = devm_clk_get(phy->u_phy.dev, "pll_u"); |
768 | if (IS_ERR(phy->pll_u)) { | 845 | if (IS_ERR(phy->pll_u)) { |
769 | pr_err("Can't get pll_u clock\n"); | 846 | err = PTR_ERR(phy->pll_u); |
770 | return PTR_ERR(phy->pll_u); | 847 | dev_err(phy->u_phy.dev, |
848 | "Failed to get pll_u clock: %d\n", err); | ||
849 | return err; | ||
771 | } | 850 | } |
772 | 851 | ||
773 | err = clk_prepare_enable(phy->pll_u); | 852 | err = clk_prepare_enable(phy->pll_u); |
@@ -782,7 +861,8 @@ static int tegra_usb_phy_init(struct tegra_usb_phy *phy) | |||
782 | } | 861 | } |
783 | } | 862 | } |
784 | if (!phy->freq) { | 863 | if (!phy->freq) { |
785 | pr_err("invalid pll_u parent rate %ld\n", parent_rate); | 864 | dev_err(phy->u_phy.dev, "Invalid pll_u parent rate %ld\n", |
865 | parent_rate); | ||
786 | err = -EINVAL; | 866 | err = -EINVAL; |
787 | goto fail; | 867 | goto fail; |
788 | } | 868 | } |
@@ -791,7 +871,7 @@ static int tegra_usb_phy_init(struct tegra_usb_phy *phy) | |||
791 | err = regulator_enable(phy->vbus); | 871 | err = regulator_enable(phy->vbus); |
792 | if (err) { | 872 | if (err) { |
793 | dev_err(phy->u_phy.dev, | 873 | dev_err(phy->u_phy.dev, |
794 | "failed to enable usb vbus regulator: %d\n", | 874 | "Failed to enable USB VBUS regulator: %d\n", |
795 | err); | 875 | err); |
796 | goto fail; | 876 | goto fail; |
797 | } | 877 | } |
@@ -855,7 +935,8 @@ static int read_utmi_param(struct platform_device *pdev, const char *param, | |||
855 | int err = of_property_read_u32(pdev->dev.of_node, param, &value); | 935 | int err = of_property_read_u32(pdev->dev.of_node, param, &value); |
856 | *dest = (u8)value; | 936 | *dest = (u8)value; |
857 | if (err < 0) | 937 | if (err < 0) |
858 | dev_err(&pdev->dev, "Failed to read USB UTMI parameter %s: %d\n", | 938 | dev_err(&pdev->dev, |
939 | "Failed to read USB UTMI parameter %s: %d\n", | ||
859 | param, err); | 940 | param, err); |
860 | return err; | 941 | return err; |
861 | } | 942 | } |
@@ -871,14 +952,14 @@ static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy, | |||
871 | 952 | ||
872 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 953 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
873 | if (!res) { | 954 | if (!res) { |
874 | dev_err(&pdev->dev, "Failed to get UTMI Pad regs\n"); | 955 | dev_err(&pdev->dev, "Failed to get UTMI pad regs\n"); |
875 | return -ENXIO; | 956 | return -ENXIO; |
876 | } | 957 | } |
877 | 958 | ||
878 | tegra_phy->pad_regs = devm_ioremap(&pdev->dev, res->start, | 959 | tegra_phy->pad_regs = devm_ioremap(&pdev->dev, res->start, |
879 | resource_size(res)); | 960 | resource_size(res)); |
880 | if (!tegra_phy->pad_regs) { | 961 | if (!tegra_phy->pad_regs) { |
881 | dev_err(&pdev->dev, "Failed to remap UTMI Pad regs\n"); | 962 | dev_err(&pdev->dev, "Failed to remap UTMI pad regs\n"); |
882 | return -ENOMEM; | 963 | return -ENOMEM; |
883 | } | 964 | } |
884 | 965 | ||
@@ -1020,15 +1101,16 @@ static int tegra_usb_phy_probe(struct platform_device *pdev) | |||
1020 | tegra_phy->reset_gpio = | 1101 | tegra_phy->reset_gpio = |
1021 | of_get_named_gpio(np, "nvidia,phy-reset-gpio", 0); | 1102 | of_get_named_gpio(np, "nvidia,phy-reset-gpio", 0); |
1022 | if (!gpio_is_valid(tegra_phy->reset_gpio)) { | 1103 | if (!gpio_is_valid(tegra_phy->reset_gpio)) { |
1023 | dev_err(&pdev->dev, "invalid gpio: %d\n", | 1104 | dev_err(&pdev->dev, |
1024 | tegra_phy->reset_gpio); | 1105 | "Invalid GPIO: %d\n", tegra_phy->reset_gpio); |
1025 | return tegra_phy->reset_gpio; | 1106 | return tegra_phy->reset_gpio; |
1026 | } | 1107 | } |
1027 | tegra_phy->config = NULL; | 1108 | tegra_phy->config = NULL; |
1028 | break; | 1109 | break; |
1029 | 1110 | ||
1030 | default: | 1111 | default: |
1031 | dev_err(&pdev->dev, "phy_type is invalid or unsupported\n"); | 1112 | dev_err(&pdev->dev, "phy_type %u is invalid or unsupported\n", |
1113 | phy_type); | ||
1032 | return -EINVAL; | 1114 | return -EINVAL; |
1033 | } | 1115 | } |
1034 | 1116 | ||
diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c index bceb2c9988dd..0277f62739a2 100644 --- a/drivers/usb/phy/phy.c +++ b/drivers/usb/phy/phy.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #define DEFAULT_ACA_CUR_MAX 5000 | 27 | #define DEFAULT_ACA_CUR_MAX 5000 |
28 | 28 | ||
29 | static LIST_HEAD(phy_list); | 29 | static LIST_HEAD(phy_list); |
30 | static LIST_HEAD(phy_bind_list); | ||
31 | static DEFINE_SPINLOCK(phy_lock); | 30 | static DEFINE_SPINLOCK(phy_lock); |
32 | 31 | ||
33 | struct phy_devm { | 32 | struct phy_devm { |
@@ -50,24 +49,6 @@ static struct usb_phy *__usb_find_phy(struct list_head *list, | |||
50 | return ERR_PTR(-ENODEV); | 49 | return ERR_PTR(-ENODEV); |
51 | } | 50 | } |
52 | 51 | ||
53 | static struct usb_phy *__usb_find_phy_dev(struct device *dev, | ||
54 | struct list_head *list, u8 index) | ||
55 | { | ||
56 | struct usb_phy_bind *phy_bind = NULL; | ||
57 | |||
58 | list_for_each_entry(phy_bind, list, list) { | ||
59 | if (!(strcmp(phy_bind->dev_name, dev_name(dev))) && | ||
60 | phy_bind->index == index) { | ||
61 | if (phy_bind->phy) | ||
62 | return phy_bind->phy; | ||
63 | else | ||
64 | return ERR_PTR(-EPROBE_DEFER); | ||
65 | } | ||
66 | } | ||
67 | |||
68 | return ERR_PTR(-ENODEV); | ||
69 | } | ||
70 | |||
71 | static struct usb_phy *__of_usb_find_phy(struct device_node *node) | 52 | static struct usb_phy *__of_usb_find_phy(struct device_node *node) |
72 | { | 53 | { |
73 | struct usb_phy *phy; | 54 | struct usb_phy *phy; |
@@ -585,72 +566,6 @@ struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev, | |||
585 | EXPORT_SYMBOL_GPL(devm_usb_get_phy_by_phandle); | 566 | EXPORT_SYMBOL_GPL(devm_usb_get_phy_by_phandle); |
586 | 567 | ||
587 | /** | 568 | /** |
588 | * usb_get_phy_dev - find the USB PHY | ||
589 | * @dev - device that requests this phy | ||
590 | * @index - the index of the phy | ||
591 | * | ||
592 | * Returns the phy driver, after getting a refcount to it; or | ||
593 | * -ENODEV if there is no such phy. The caller is responsible for | ||
594 | * calling usb_put_phy() to release that count. | ||
595 | * | ||
596 | * For use by USB host and peripheral drivers. | ||
597 | */ | ||
598 | struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index) | ||
599 | { | ||
600 | struct usb_phy *phy = NULL; | ||
601 | unsigned long flags; | ||
602 | |||
603 | spin_lock_irqsave(&phy_lock, flags); | ||
604 | |||
605 | phy = __usb_find_phy_dev(dev, &phy_bind_list, index); | ||
606 | if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) { | ||
607 | dev_dbg(dev, "unable to find transceiver\n"); | ||
608 | if (!IS_ERR(phy)) | ||
609 | phy = ERR_PTR(-ENODEV); | ||
610 | |||
611 | goto err0; | ||
612 | } | ||
613 | |||
614 | get_device(phy->dev); | ||
615 | |||
616 | err0: | ||
617 | spin_unlock_irqrestore(&phy_lock, flags); | ||
618 | |||
619 | return phy; | ||
620 | } | ||
621 | EXPORT_SYMBOL_GPL(usb_get_phy_dev); | ||
622 | |||
623 | /** | ||
624 | * devm_usb_get_phy_dev - find the USB PHY using device ptr and index | ||
625 | * @dev - device that requests this phy | ||
626 | * @index - the index of the phy | ||
627 | * | ||
628 | * Gets the phy using usb_get_phy_dev(), and associates a device with it using | ||
629 | * devres. On driver detach, release function is invoked on the devres data, | ||
630 | * then, devres data is freed. | ||
631 | * | ||
632 | * For use by USB host and peripheral drivers. | ||
633 | */ | ||
634 | struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index) | ||
635 | { | ||
636 | struct usb_phy **ptr, *phy; | ||
637 | |||
638 | ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL); | ||
639 | if (!ptr) | ||
640 | return NULL; | ||
641 | |||
642 | phy = usb_get_phy_dev(dev, index); | ||
643 | if (!IS_ERR(phy)) { | ||
644 | *ptr = phy; | ||
645 | devres_add(dev, ptr); | ||
646 | } else | ||
647 | devres_free(ptr); | ||
648 | |||
649 | return phy; | ||
650 | } | ||
651 | EXPORT_SYMBOL_GPL(devm_usb_get_phy_dev); | ||
652 | |||
653 | /** | ||
654 | * devm_usb_put_phy - release the USB PHY | 569 | * devm_usb_put_phy - release the USB PHY |
655 | * @dev - device that wants to release this phy | 570 | * @dev - device that wants to release this phy |
656 | * @phy - the phy returned by devm_usb_get_phy() | 571 | * @phy - the phy returned by devm_usb_get_phy() |
@@ -745,7 +660,6 @@ EXPORT_SYMBOL_GPL(usb_add_phy); | |||
745 | */ | 660 | */ |
746 | int usb_add_phy_dev(struct usb_phy *x) | 661 | int usb_add_phy_dev(struct usb_phy *x) |
747 | { | 662 | { |
748 | struct usb_phy_bind *phy_bind; | ||
749 | unsigned long flags; | 663 | unsigned long flags; |
750 | int ret; | 664 | int ret; |
751 | 665 | ||
@@ -762,13 +676,9 @@ int usb_add_phy_dev(struct usb_phy *x) | |||
762 | ATOMIC_INIT_NOTIFIER_HEAD(&x->notifier); | 676 | ATOMIC_INIT_NOTIFIER_HEAD(&x->notifier); |
763 | 677 | ||
764 | spin_lock_irqsave(&phy_lock, flags); | 678 | spin_lock_irqsave(&phy_lock, flags); |
765 | list_for_each_entry(phy_bind, &phy_bind_list, list) | ||
766 | if (!(strcmp(phy_bind->phy_dev_name, dev_name(x->dev)))) | ||
767 | phy_bind->phy = x; | ||
768 | |||
769 | list_add_tail(&x->head, &phy_list); | 679 | list_add_tail(&x->head, &phy_list); |
770 | |||
771 | spin_unlock_irqrestore(&phy_lock, flags); | 680 | spin_unlock_irqrestore(&phy_lock, flags); |
681 | |||
772 | return 0; | 682 | return 0; |
773 | } | 683 | } |
774 | EXPORT_SYMBOL_GPL(usb_add_phy_dev); | 684 | EXPORT_SYMBOL_GPL(usb_add_phy_dev); |
@@ -782,54 +692,15 @@ EXPORT_SYMBOL_GPL(usb_add_phy_dev); | |||
782 | void usb_remove_phy(struct usb_phy *x) | 692 | void usb_remove_phy(struct usb_phy *x) |
783 | { | 693 | { |
784 | unsigned long flags; | 694 | unsigned long flags; |
785 | struct usb_phy_bind *phy_bind; | ||
786 | 695 | ||
787 | spin_lock_irqsave(&phy_lock, flags); | 696 | spin_lock_irqsave(&phy_lock, flags); |
788 | if (x) { | 697 | if (x) |
789 | list_for_each_entry(phy_bind, &phy_bind_list, list) | ||
790 | if (phy_bind->phy == x) | ||
791 | phy_bind->phy = NULL; | ||
792 | list_del(&x->head); | 698 | list_del(&x->head); |
793 | } | ||
794 | spin_unlock_irqrestore(&phy_lock, flags); | 699 | spin_unlock_irqrestore(&phy_lock, flags); |
795 | } | 700 | } |
796 | EXPORT_SYMBOL_GPL(usb_remove_phy); | 701 | EXPORT_SYMBOL_GPL(usb_remove_phy); |
797 | 702 | ||
798 | /** | 703 | /** |
799 | * usb_bind_phy - bind the phy and the controller that uses the phy | ||
800 | * @dev_name: the device name of the device that will bind to the phy | ||
801 | * @index: index to specify the port number | ||
802 | * @phy_dev_name: the device name of the phy | ||
803 | * | ||
804 | * Fills the phy_bind structure with the dev_name and phy_dev_name. This will | ||
805 | * be used when the phy driver registers the phy and when the controller | ||
806 | * requests this phy. | ||
807 | * | ||
808 | * To be used by platform specific initialization code. | ||
809 | */ | ||
810 | int usb_bind_phy(const char *dev_name, u8 index, | ||
811 | const char *phy_dev_name) | ||
812 | { | ||
813 | struct usb_phy_bind *phy_bind; | ||
814 | unsigned long flags; | ||
815 | |||
816 | phy_bind = kzalloc(sizeof(*phy_bind), GFP_KERNEL); | ||
817 | if (!phy_bind) | ||
818 | return -ENOMEM; | ||
819 | |||
820 | phy_bind->dev_name = dev_name; | ||
821 | phy_bind->phy_dev_name = phy_dev_name; | ||
822 | phy_bind->index = index; | ||
823 | |||
824 | spin_lock_irqsave(&phy_lock, flags); | ||
825 | list_add_tail(&phy_bind->list, &phy_bind_list); | ||
826 | spin_unlock_irqrestore(&phy_lock, flags); | ||
827 | |||
828 | return 0; | ||
829 | } | ||
830 | EXPORT_SYMBOL_GPL(usb_bind_phy); | ||
831 | |||
832 | /** | ||
833 | * usb_phy_set_event - set event to phy event | 704 | * usb_phy_set_event - set event to phy event |
834 | * @x: the phy returned by usb_get_phy(); | 705 | * @x: the phy returned by usb_get_phy(); |
835 | * | 706 | * |
diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h index f619afeae2b8..6137f7942c05 100644 --- a/drivers/usb/renesas_usbhs/common.h +++ b/drivers/usb/renesas_usbhs/common.h | |||
@@ -276,7 +276,6 @@ struct usbhs_priv { | |||
276 | */ | 276 | */ |
277 | struct usbhs_fifo_info fifo_info; | 277 | struct usbhs_fifo_info fifo_info; |
278 | 278 | ||
279 | struct usb_phy *usb_phy; | ||
280 | struct phy *phy; | 279 | struct phy *phy; |
281 | }; | 280 | }; |
282 | 281 | ||
diff --git a/drivers/usb/renesas_usbhs/rcar2.c b/drivers/usb/renesas_usbhs/rcar2.c index 85a0e0933917..0027092b1118 100644 --- a/drivers/usb/renesas_usbhs/rcar2.c +++ b/drivers/usb/renesas_usbhs/rcar2.c | |||
@@ -8,7 +8,6 @@ | |||
8 | #include <linux/gpio.h> | 8 | #include <linux/gpio.h> |
9 | #include <linux/of_gpio.h> | 9 | #include <linux/of_gpio.h> |
10 | #include <linux/phy/phy.h> | 10 | #include <linux/phy/phy.h> |
11 | #include <linux/usb/phy.h> | ||
12 | #include "common.h" | 11 | #include "common.h" |
13 | #include "rcar2.h" | 12 | #include "rcar2.h" |
14 | 13 | ||
@@ -26,16 +25,6 @@ static int usbhs_rcar2_hardware_init(struct platform_device *pdev) | |||
26 | return 0; | 25 | return 0; |
27 | } | 26 | } |
28 | 27 | ||
29 | if (IS_ENABLED(CONFIG_USB_PHY)) { | ||
30 | struct usb_phy *usb_phy = usb_get_phy_dev(&pdev->dev, 0); | ||
31 | |||
32 | if (IS_ERR(usb_phy)) | ||
33 | return PTR_ERR(usb_phy); | ||
34 | |||
35 | priv->usb_phy = usb_phy; | ||
36 | return 0; | ||
37 | } | ||
38 | |||
39 | return -ENXIO; | 28 | return -ENXIO; |
40 | } | 29 | } |
41 | 30 | ||
@@ -48,11 +37,6 @@ static int usbhs_rcar2_hardware_exit(struct platform_device *pdev) | |||
48 | priv->phy = NULL; | 37 | priv->phy = NULL; |
49 | } | 38 | } |
50 | 39 | ||
51 | if (priv->usb_phy) { | ||
52 | usb_put_phy(priv->usb_phy); | ||
53 | priv->usb_phy = NULL; | ||
54 | } | ||
55 | |||
56 | return 0; | 40 | return 0; |
57 | } | 41 | } |
58 | 42 | ||
@@ -75,19 +59,6 @@ static int usbhs_rcar2_power_ctrl(struct platform_device *pdev, | |||
75 | } | 59 | } |
76 | } | 60 | } |
77 | 61 | ||
78 | if (priv->usb_phy) { | ||
79 | if (enable) { | ||
80 | retval = usb_phy_init(priv->usb_phy); | ||
81 | |||
82 | if (!retval) | ||
83 | retval = usb_phy_set_suspend(priv->usb_phy, 0); | ||
84 | } else { | ||
85 | usb_phy_set_suspend(priv->usb_phy, 1); | ||
86 | usb_phy_shutdown(priv->usb_phy); | ||
87 | retval = 0; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | return retval; | 62 | return retval; |
92 | } | 63 | } |
93 | 64 | ||
diff --git a/drivers/usb/roles/intel-xhci-usb-role-switch.c b/drivers/usb/roles/intel-xhci-usb-role-switch.c index de72eedb762e..1fb3dd0f1dfa 100644 --- a/drivers/usb/roles/intel-xhci-usb-role-switch.c +++ b/drivers/usb/roles/intel-xhci-usb-role-switch.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/pm_runtime.h> | ||
21 | #include <linux/usb/role.h> | 22 | #include <linux/usb/role.h> |
22 | 23 | ||
23 | /* register definition */ | 24 | /* register definition */ |
@@ -38,20 +39,6 @@ struct intel_xhci_usb_data { | |||
38 | void __iomem *base; | 39 | void __iomem *base; |
39 | }; | 40 | }; |
40 | 41 | ||
41 | struct intel_xhci_acpi_match { | ||
42 | const char *hid; | ||
43 | int hrv; | ||
44 | }; | ||
45 | |||
46 | /* | ||
47 | * ACPI IDs for PMICs which do not support separate data and power role | ||
48 | * detection (USB ACA detection for micro USB OTG), we allow userspace to | ||
49 | * change the role manually on these. | ||
50 | */ | ||
51 | static const struct intel_xhci_acpi_match allow_userspace_ctrl_ids[] = { | ||
52 | { "INT33F4", 3 }, /* X-Powers AXP288 PMIC */ | ||
53 | }; | ||
54 | |||
55 | static int intel_xhci_usb_set_role(struct device *dev, enum usb_role role) | 42 | static int intel_xhci_usb_set_role(struct device *dev, enum usb_role role) |
56 | { | 43 | { |
57 | struct intel_xhci_usb_data *data = dev_get_drvdata(dev); | 44 | struct intel_xhci_usb_data *data = dev_get_drvdata(dev); |
@@ -70,6 +57,8 @@ static int intel_xhci_usb_set_role(struct device *dev, enum usb_role role) | |||
70 | return -EIO; | 57 | return -EIO; |
71 | } | 58 | } |
72 | 59 | ||
60 | pm_runtime_get_sync(dev); | ||
61 | |||
73 | /* Set idpin value as requested */ | 62 | /* Set idpin value as requested */ |
74 | val = readl(data->base + DUAL_ROLE_CFG0); | 63 | val = readl(data->base + DUAL_ROLE_CFG0); |
75 | switch (role) { | 64 | switch (role) { |
@@ -98,13 +87,17 @@ static int intel_xhci_usb_set_role(struct device *dev, enum usb_role role) | |||
98 | /* Polling on CFG1 register to confirm mode switch.*/ | 87 | /* Polling on CFG1 register to confirm mode switch.*/ |
99 | do { | 88 | do { |
100 | val = readl(data->base + DUAL_ROLE_CFG1); | 89 | val = readl(data->base + DUAL_ROLE_CFG1); |
101 | if (!!(val & HOST_MODE) == (role == USB_ROLE_HOST)) | 90 | if (!!(val & HOST_MODE) == (role == USB_ROLE_HOST)) { |
91 | pm_runtime_put(dev); | ||
102 | return 0; | 92 | return 0; |
93 | } | ||
103 | 94 | ||
104 | /* Interval for polling is set to about 5 - 10 ms */ | 95 | /* Interval for polling is set to about 5 - 10 ms */ |
105 | usleep_range(5000, 10000); | 96 | usleep_range(5000, 10000); |
106 | } while (time_before(jiffies, timeout)); | 97 | } while (time_before(jiffies, timeout)); |
107 | 98 | ||
99 | pm_runtime_put(dev); | ||
100 | |||
108 | dev_warn(dev, "Timeout waiting for role-switch\n"); | 101 | dev_warn(dev, "Timeout waiting for role-switch\n"); |
109 | return -ETIMEDOUT; | 102 | return -ETIMEDOUT; |
110 | } | 103 | } |
@@ -115,7 +108,9 @@ static enum usb_role intel_xhci_usb_get_role(struct device *dev) | |||
115 | enum usb_role role; | 108 | enum usb_role role; |
116 | u32 val; | 109 | u32 val; |
117 | 110 | ||
111 | pm_runtime_get_sync(dev); | ||
118 | val = readl(data->base + DUAL_ROLE_CFG0); | 112 | val = readl(data->base + DUAL_ROLE_CFG0); |
113 | pm_runtime_put(dev); | ||
119 | 114 | ||
120 | if (!(val & SW_IDPIN)) | 115 | if (!(val & SW_IDPIN)) |
121 | role = USB_ROLE_HOST; | 116 | role = USB_ROLE_HOST; |
@@ -127,9 +122,10 @@ static enum usb_role intel_xhci_usb_get_role(struct device *dev) | |||
127 | return role; | 122 | return role; |
128 | } | 123 | } |
129 | 124 | ||
130 | static struct usb_role_switch_desc sw_desc = { | 125 | static const struct usb_role_switch_desc sw_desc = { |
131 | .set = intel_xhci_usb_set_role, | 126 | .set = intel_xhci_usb_set_role, |
132 | .get = intel_xhci_usb_get_role, | 127 | .get = intel_xhci_usb_get_role, |
128 | .allow_userspace_control = true, | ||
133 | }; | 129 | }; |
134 | 130 | ||
135 | static int intel_xhci_usb_probe(struct platform_device *pdev) | 131 | static int intel_xhci_usb_probe(struct platform_device *pdev) |
@@ -137,28 +133,27 @@ static int intel_xhci_usb_probe(struct platform_device *pdev) | |||
137 | struct device *dev = &pdev->dev; | 133 | struct device *dev = &pdev->dev; |
138 | struct intel_xhci_usb_data *data; | 134 | struct intel_xhci_usb_data *data; |
139 | struct resource *res; | 135 | struct resource *res; |
140 | int i; | ||
141 | 136 | ||
142 | data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); | 137 | data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); |
143 | if (!data) | 138 | if (!data) |
144 | return -ENOMEM; | 139 | return -ENOMEM; |
145 | 140 | ||
146 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 141 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
142 | if (!res) | ||
143 | return -EINVAL; | ||
147 | data->base = devm_ioremap_nocache(dev, res->start, resource_size(res)); | 144 | data->base = devm_ioremap_nocache(dev, res->start, resource_size(res)); |
148 | if (!data->base) | 145 | if (!data->base) |
149 | return -ENOMEM; | 146 | return -ENOMEM; |
150 | 147 | ||
151 | for (i = 0; i < ARRAY_SIZE(allow_userspace_ctrl_ids); i++) | ||
152 | if (acpi_dev_present(allow_userspace_ctrl_ids[i].hid, "1", | ||
153 | allow_userspace_ctrl_ids[i].hrv)) | ||
154 | sw_desc.allow_userspace_control = true; | ||
155 | |||
156 | platform_set_drvdata(pdev, data); | 148 | platform_set_drvdata(pdev, data); |
157 | 149 | ||
158 | data->role_sw = usb_role_switch_register(dev, &sw_desc); | 150 | data->role_sw = usb_role_switch_register(dev, &sw_desc); |
159 | if (IS_ERR(data->role_sw)) | 151 | if (IS_ERR(data->role_sw)) |
160 | return PTR_ERR(data->role_sw); | 152 | return PTR_ERR(data->role_sw); |
161 | 153 | ||
154 | pm_runtime_set_active(dev); | ||
155 | pm_runtime_enable(dev); | ||
156 | |||
162 | return 0; | 157 | return 0; |
163 | } | 158 | } |
164 | 159 | ||
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index 9e265eb92611..eb0195cf37dd 100644 --- a/drivers/usb/serial/bus.c +++ b/drivers/usb/serial/bus.c | |||
@@ -60,7 +60,8 @@ static int usb_serial_device_probe(struct device *dev) | |||
60 | } | 60 | } |
61 | 61 | ||
62 | minor = port->minor; | 62 | minor = port->minor; |
63 | tty_dev = tty_register_device(usb_serial_tty_driver, minor, dev); | 63 | tty_dev = tty_port_register_device(&port->port, usb_serial_tty_driver, |
64 | minor, dev); | ||
64 | if (IS_ERR(tty_dev)) { | 65 | if (IS_ERR(tty_dev)) { |
65 | retval = PTR_ERR(tty_dev); | 66 | retval = PTR_ERR(tty_dev); |
66 | goto err_port_remove; | 67 | goto err_port_remove; |
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 7ea221d42dba..b5cef322826f 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -54,15 +54,14 @@ struct ftdi_private { | |||
54 | int custom_divisor; /* custom_divisor kludge, this is for | 54 | int custom_divisor; /* custom_divisor kludge, this is for |
55 | baud_base (different from what goes to the | 55 | baud_base (different from what goes to the |
56 | chip!) */ | 56 | chip!) */ |
57 | __u16 last_set_data_urb_value ; | 57 | u16 last_set_data_value; /* the last data state set - needed for doing |
58 | /* the last data state set - needed for doing | 58 | * a break |
59 | * a break | 59 | */ |
60 | */ | ||
61 | int flags; /* some ASYNC_xxxx flags are supported */ | 60 | int flags; /* some ASYNC_xxxx flags are supported */ |
62 | unsigned long last_dtr_rts; /* saved modem control outputs */ | 61 | unsigned long last_dtr_rts; /* saved modem control outputs */ |
63 | char prev_status; /* Used for TIOCMIWAIT */ | 62 | char prev_status; /* Used for TIOCMIWAIT */ |
64 | char transmit_empty; /* If transmitter is empty or not */ | 63 | char transmit_empty; /* If transmitter is empty or not */ |
65 | __u16 interface; /* FT2232C, FT2232H or FT4232H port interface | 64 | u16 interface; /* FT2232C, FT2232H or FT4232H port interface |
66 | (0 for FT232/245) */ | 65 | (0 for FT232/245) */ |
67 | 66 | ||
68 | speed_t force_baud; /* if non-zero, force the baud rate to | 67 | speed_t force_baud; /* if non-zero, force the baud rate to |
@@ -1063,10 +1062,10 @@ static int ftdi_get_modem_status(struct usb_serial_port *port, | |||
1063 | 1062 | ||
1064 | static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base); | 1063 | static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base); |
1065 | static unsigned short int ftdi_232am_baud_to_divisor(int baud); | 1064 | static unsigned short int ftdi_232am_baud_to_divisor(int baud); |
1066 | static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base); | 1065 | static u32 ftdi_232bm_baud_base_to_divisor(int baud, int base); |
1067 | static __u32 ftdi_232bm_baud_to_divisor(int baud); | 1066 | static u32 ftdi_232bm_baud_to_divisor(int baud); |
1068 | static __u32 ftdi_2232h_baud_base_to_divisor(int baud, int base); | 1067 | static u32 ftdi_2232h_baud_base_to_divisor(int baud, int base); |
1069 | static __u32 ftdi_2232h_baud_to_divisor(int baud); | 1068 | static u32 ftdi_2232h_baud_to_divisor(int baud); |
1070 | 1069 | ||
1071 | static struct usb_serial_driver ftdi_sio_device = { | 1070 | static struct usb_serial_driver ftdi_sio_device = { |
1072 | .driver = { | 1071 | .driver = { |
@@ -1136,14 +1135,14 @@ static unsigned short int ftdi_232am_baud_to_divisor(int baud) | |||
1136 | return ftdi_232am_baud_base_to_divisor(baud, 48000000); | 1135 | return ftdi_232am_baud_base_to_divisor(baud, 48000000); |
1137 | } | 1136 | } |
1138 | 1137 | ||
1139 | static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base) | 1138 | static u32 ftdi_232bm_baud_base_to_divisor(int baud, int base) |
1140 | { | 1139 | { |
1141 | static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; | 1140 | static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; |
1142 | __u32 divisor; | 1141 | u32 divisor; |
1143 | /* divisor shifted 3 bits to the left */ | 1142 | /* divisor shifted 3 bits to the left */ |
1144 | int divisor3 = base / 2 / baud; | 1143 | int divisor3 = base / 2 / baud; |
1145 | divisor = divisor3 >> 3; | 1144 | divisor = divisor3 >> 3; |
1146 | divisor |= (__u32)divfrac[divisor3 & 0x7] << 14; | 1145 | divisor |= (u32)divfrac[divisor3 & 0x7] << 14; |
1147 | /* Deal with special cases for highest baud rates. */ | 1146 | /* Deal with special cases for highest baud rates. */ |
1148 | if (divisor == 1) | 1147 | if (divisor == 1) |
1149 | divisor = 0; | 1148 | divisor = 0; |
@@ -1152,22 +1151,22 @@ static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base) | |||
1152 | return divisor; | 1151 | return divisor; |
1153 | } | 1152 | } |
1154 | 1153 | ||
1155 | static __u32 ftdi_232bm_baud_to_divisor(int baud) | 1154 | static u32 ftdi_232bm_baud_to_divisor(int baud) |
1156 | { | 1155 | { |
1157 | return ftdi_232bm_baud_base_to_divisor(baud, 48000000); | 1156 | return ftdi_232bm_baud_base_to_divisor(baud, 48000000); |
1158 | } | 1157 | } |
1159 | 1158 | ||
1160 | static __u32 ftdi_2232h_baud_base_to_divisor(int baud, int base) | 1159 | static u32 ftdi_2232h_baud_base_to_divisor(int baud, int base) |
1161 | { | 1160 | { |
1162 | static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; | 1161 | static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; |
1163 | __u32 divisor; | 1162 | u32 divisor; |
1164 | int divisor3; | 1163 | int divisor3; |
1165 | 1164 | ||
1166 | /* hi-speed baud rate is 10-bit sampling instead of 16-bit */ | 1165 | /* hi-speed baud rate is 10-bit sampling instead of 16-bit */ |
1167 | divisor3 = base * 8 / (baud * 10); | 1166 | divisor3 = base * 8 / (baud * 10); |
1168 | 1167 | ||
1169 | divisor = divisor3 >> 3; | 1168 | divisor = divisor3 >> 3; |
1170 | divisor |= (__u32)divfrac[divisor3 & 0x7] << 14; | 1169 | divisor |= (u32)divfrac[divisor3 & 0x7] << 14; |
1171 | /* Deal with special cases for highest baud rates. */ | 1170 | /* Deal with special cases for highest baud rates. */ |
1172 | if (divisor == 1) | 1171 | if (divisor == 1) |
1173 | divisor = 0; | 1172 | divisor = 0; |
@@ -1182,7 +1181,7 @@ static __u32 ftdi_2232h_baud_base_to_divisor(int baud, int base) | |||
1182 | return divisor; | 1181 | return divisor; |
1183 | } | 1182 | } |
1184 | 1183 | ||
1185 | static __u32 ftdi_2232h_baud_to_divisor(int baud) | 1184 | static u32 ftdi_2232h_baud_to_divisor(int baud) |
1186 | { | 1185 | { |
1187 | return ftdi_2232h_baud_base_to_divisor(baud, 120000000); | 1186 | return ftdi_2232h_baud_base_to_divisor(baud, 120000000); |
1188 | } | 1187 | } |
@@ -1195,7 +1194,7 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, | |||
1195 | { | 1194 | { |
1196 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1195 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1197 | struct device *dev = &port->dev; | 1196 | struct device *dev = &port->dev; |
1198 | unsigned urb_value; | 1197 | unsigned value; |
1199 | int rv; | 1198 | int rv; |
1200 | 1199 | ||
1201 | if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) { | 1200 | if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) { |
@@ -1204,20 +1203,20 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, | |||
1204 | } | 1203 | } |
1205 | 1204 | ||
1206 | clear &= ~set; /* 'set' takes precedence over 'clear' */ | 1205 | clear &= ~set; /* 'set' takes precedence over 'clear' */ |
1207 | urb_value = 0; | 1206 | value = 0; |
1208 | if (clear & TIOCM_DTR) | 1207 | if (clear & TIOCM_DTR) |
1209 | urb_value |= FTDI_SIO_SET_DTR_LOW; | 1208 | value |= FTDI_SIO_SET_DTR_LOW; |
1210 | if (clear & TIOCM_RTS) | 1209 | if (clear & TIOCM_RTS) |
1211 | urb_value |= FTDI_SIO_SET_RTS_LOW; | 1210 | value |= FTDI_SIO_SET_RTS_LOW; |
1212 | if (set & TIOCM_DTR) | 1211 | if (set & TIOCM_DTR) |
1213 | urb_value |= FTDI_SIO_SET_DTR_HIGH; | 1212 | value |= FTDI_SIO_SET_DTR_HIGH; |
1214 | if (set & TIOCM_RTS) | 1213 | if (set & TIOCM_RTS) |
1215 | urb_value |= FTDI_SIO_SET_RTS_HIGH; | 1214 | value |= FTDI_SIO_SET_RTS_HIGH; |
1216 | rv = usb_control_msg(port->serial->dev, | 1215 | rv = usb_control_msg(port->serial->dev, |
1217 | usb_sndctrlpipe(port->serial->dev, 0), | 1216 | usb_sndctrlpipe(port->serial->dev, 0), |
1218 | FTDI_SIO_SET_MODEM_CTRL_REQUEST, | 1217 | FTDI_SIO_SET_MODEM_CTRL_REQUEST, |
1219 | FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, | 1218 | FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, |
1220 | urb_value, priv->interface, | 1219 | value, priv->interface, |
1221 | NULL, 0, WDR_TIMEOUT); | 1220 | NULL, 0, WDR_TIMEOUT); |
1222 | if (rv < 0) { | 1221 | if (rv < 0) { |
1223 | dev_dbg(dev, "%s Error from MODEM_CTRL urb: DTR %s, RTS %s\n", | 1222 | dev_dbg(dev, "%s Error from MODEM_CTRL urb: DTR %s, RTS %s\n", |
@@ -1236,12 +1235,12 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, | |||
1236 | } | 1235 | } |
1237 | 1236 | ||
1238 | 1237 | ||
1239 | static __u32 get_ftdi_divisor(struct tty_struct *tty, | 1238 | static u32 get_ftdi_divisor(struct tty_struct *tty, |
1240 | struct usb_serial_port *port) | 1239 | struct usb_serial_port *port) |
1241 | { | 1240 | { |
1242 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1241 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1243 | struct device *dev = &port->dev; | 1242 | struct device *dev = &port->dev; |
1244 | __u32 div_value = 0; | 1243 | u32 div_value = 0; |
1245 | int div_okay = 1; | 1244 | int div_okay = 1; |
1246 | int baud; | 1245 | int baud; |
1247 | 1246 | ||
@@ -1299,7 +1298,7 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty, | |||
1299 | case FT232RL: /* FT232RL chip */ | 1298 | case FT232RL: /* FT232RL chip */ |
1300 | case FTX: /* FT-X series */ | 1299 | case FTX: /* FT-X series */ |
1301 | if (baud <= 3000000) { | 1300 | if (baud <= 3000000) { |
1302 | __u16 product_id = le16_to_cpu( | 1301 | u16 product_id = le16_to_cpu( |
1303 | port->serial->dev->descriptor.idProduct); | 1302 | port->serial->dev->descriptor.idProduct); |
1304 | if (((product_id == FTDI_NDI_HUC_PID) || | 1303 | if (((product_id == FTDI_NDI_HUC_PID) || |
1305 | (product_id == FTDI_NDI_SPECTRA_SCU_PID) || | 1304 | (product_id == FTDI_NDI_SPECTRA_SCU_PID) || |
@@ -1346,26 +1345,26 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty, | |||
1346 | static int change_speed(struct tty_struct *tty, struct usb_serial_port *port) | 1345 | static int change_speed(struct tty_struct *tty, struct usb_serial_port *port) |
1347 | { | 1346 | { |
1348 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1347 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1349 | __u16 urb_value; | 1348 | u16 value; |
1350 | __u16 urb_index; | 1349 | u16 index; |
1351 | __u32 urb_index_value; | 1350 | u32 index_value; |
1352 | int rv; | 1351 | int rv; |
1353 | 1352 | ||
1354 | urb_index_value = get_ftdi_divisor(tty, port); | 1353 | index_value = get_ftdi_divisor(tty, port); |
1355 | urb_value = (__u16)urb_index_value; | 1354 | value = (u16)index_value; |
1356 | urb_index = (__u16)(urb_index_value >> 16); | 1355 | index = (u16)(index_value >> 16); |
1357 | if ((priv->chip_type == FT2232C) || (priv->chip_type == FT2232H) || | 1356 | if ((priv->chip_type == FT2232C) || (priv->chip_type == FT2232H) || |
1358 | (priv->chip_type == FT4232H) || (priv->chip_type == FT232H)) { | 1357 | (priv->chip_type == FT4232H) || (priv->chip_type == FT232H)) { |
1359 | /* Probably the BM type needs the MSB of the encoded fractional | 1358 | /* Probably the BM type needs the MSB of the encoded fractional |
1360 | * divider also moved like for the chips above. Any infos? */ | 1359 | * divider also moved like for the chips above. Any infos? */ |
1361 | urb_index = (__u16)((urb_index << 8) | priv->interface); | 1360 | index = (u16)((index << 8) | priv->interface); |
1362 | } | 1361 | } |
1363 | 1362 | ||
1364 | rv = usb_control_msg(port->serial->dev, | 1363 | rv = usb_control_msg(port->serial->dev, |
1365 | usb_sndctrlpipe(port->serial->dev, 0), | 1364 | usb_sndctrlpipe(port->serial->dev, 0), |
1366 | FTDI_SIO_SET_BAUDRATE_REQUEST, | 1365 | FTDI_SIO_SET_BAUDRATE_REQUEST, |
1367 | FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, | 1366 | FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, |
1368 | urb_value, urb_index, | 1367 | value, index, |
1369 | NULL, 0, WDR_SHORT_TIMEOUT); | 1368 | NULL, 0, WDR_SHORT_TIMEOUT); |
1370 | return rv; | 1369 | return rv; |
1371 | } | 1370 | } |
@@ -2140,29 +2139,29 @@ static void ftdi_break_ctl(struct tty_struct *tty, int break_state) | |||
2140 | { | 2139 | { |
2141 | struct usb_serial_port *port = tty->driver_data; | 2140 | struct usb_serial_port *port = tty->driver_data; |
2142 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 2141 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
2143 | __u16 urb_value; | 2142 | u16 value; |
2144 | 2143 | ||
2145 | /* break_state = -1 to turn on break, and 0 to turn off break */ | 2144 | /* break_state = -1 to turn on break, and 0 to turn off break */ |
2146 | /* see drivers/char/tty_io.c to see it used */ | 2145 | /* see drivers/char/tty_io.c to see it used */ |
2147 | /* last_set_data_urb_value NEVER has the break bit set in it */ | 2146 | /* last_set_data_value NEVER has the break bit set in it */ |
2148 | 2147 | ||
2149 | if (break_state) | 2148 | if (break_state) |
2150 | urb_value = priv->last_set_data_urb_value | FTDI_SIO_SET_BREAK; | 2149 | value = priv->last_set_data_value | FTDI_SIO_SET_BREAK; |
2151 | else | 2150 | else |
2152 | urb_value = priv->last_set_data_urb_value; | 2151 | value = priv->last_set_data_value; |
2153 | 2152 | ||
2154 | if (usb_control_msg(port->serial->dev, | 2153 | if (usb_control_msg(port->serial->dev, |
2155 | usb_sndctrlpipe(port->serial->dev, 0), | 2154 | usb_sndctrlpipe(port->serial->dev, 0), |
2156 | FTDI_SIO_SET_DATA_REQUEST, | 2155 | FTDI_SIO_SET_DATA_REQUEST, |
2157 | FTDI_SIO_SET_DATA_REQUEST_TYPE, | 2156 | FTDI_SIO_SET_DATA_REQUEST_TYPE, |
2158 | urb_value , priv->interface, | 2157 | value , priv->interface, |
2159 | NULL, 0, WDR_TIMEOUT) < 0) { | 2158 | NULL, 0, WDR_TIMEOUT) < 0) { |
2160 | dev_err(&port->dev, "%s FAILED to enable/disable break state (state was %d)\n", | 2159 | dev_err(&port->dev, "%s FAILED to enable/disable break state (state was %d)\n", |
2161 | __func__, break_state); | 2160 | __func__, break_state); |
2162 | } | 2161 | } |
2163 | 2162 | ||
2164 | dev_dbg(&port->dev, "%s break state is %d - urb is %d\n", __func__, | 2163 | dev_dbg(&port->dev, "%s break state is %d - urb is %d\n", __func__, |
2165 | break_state, urb_value); | 2164 | break_state, value); |
2166 | 2165 | ||
2167 | } | 2166 | } |
2168 | 2167 | ||
@@ -2192,12 +2191,8 @@ static void ftdi_set_termios(struct tty_struct *tty, | |||
2192 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 2191 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
2193 | struct ktermios *termios = &tty->termios; | 2192 | struct ktermios *termios = &tty->termios; |
2194 | unsigned int cflag = termios->c_cflag; | 2193 | unsigned int cflag = termios->c_cflag; |
2195 | __u16 urb_value; /* will hold the new flags */ | 2194 | u16 value, index; |
2196 | 2195 | int ret; | |
2197 | /* Added for xon/xoff support */ | ||
2198 | unsigned int iflag = termios->c_iflag; | ||
2199 | unsigned char vstop; | ||
2200 | unsigned char vstart; | ||
2201 | 2196 | ||
2202 | /* Force baud rate if this device requires it, unless it is set to | 2197 | /* Force baud rate if this device requires it, unless it is set to |
2203 | B0. */ | 2198 | B0. */ |
@@ -2258,44 +2253,44 @@ static void ftdi_set_termios(struct tty_struct *tty, | |||
2258 | no_skip: | 2253 | no_skip: |
2259 | /* Set number of data bits, parity, stop bits */ | 2254 | /* Set number of data bits, parity, stop bits */ |
2260 | 2255 | ||
2261 | urb_value = 0; | 2256 | value = 0; |
2262 | urb_value |= (cflag & CSTOPB ? FTDI_SIO_SET_DATA_STOP_BITS_2 : | 2257 | value |= (cflag & CSTOPB ? FTDI_SIO_SET_DATA_STOP_BITS_2 : |
2263 | FTDI_SIO_SET_DATA_STOP_BITS_1); | 2258 | FTDI_SIO_SET_DATA_STOP_BITS_1); |
2264 | if (cflag & PARENB) { | 2259 | if (cflag & PARENB) { |
2265 | if (cflag & CMSPAR) | 2260 | if (cflag & CMSPAR) |
2266 | urb_value |= cflag & PARODD ? | 2261 | value |= cflag & PARODD ? |
2267 | FTDI_SIO_SET_DATA_PARITY_MARK : | 2262 | FTDI_SIO_SET_DATA_PARITY_MARK : |
2268 | FTDI_SIO_SET_DATA_PARITY_SPACE; | 2263 | FTDI_SIO_SET_DATA_PARITY_SPACE; |
2269 | else | 2264 | else |
2270 | urb_value |= cflag & PARODD ? | 2265 | value |= cflag & PARODD ? |
2271 | FTDI_SIO_SET_DATA_PARITY_ODD : | 2266 | FTDI_SIO_SET_DATA_PARITY_ODD : |
2272 | FTDI_SIO_SET_DATA_PARITY_EVEN; | 2267 | FTDI_SIO_SET_DATA_PARITY_EVEN; |
2273 | } else { | 2268 | } else { |
2274 | urb_value |= FTDI_SIO_SET_DATA_PARITY_NONE; | 2269 | value |= FTDI_SIO_SET_DATA_PARITY_NONE; |
2275 | } | 2270 | } |
2276 | switch (cflag & CSIZE) { | 2271 | switch (cflag & CSIZE) { |
2277 | case CS5: | 2272 | case CS5: |
2278 | dev_dbg(ddev, "Setting CS5 quirk\n"); | 2273 | dev_dbg(ddev, "Setting CS5 quirk\n"); |
2279 | break; | 2274 | break; |
2280 | case CS7: | 2275 | case CS7: |
2281 | urb_value |= 7; | 2276 | value |= 7; |
2282 | dev_dbg(ddev, "Setting CS7\n"); | 2277 | dev_dbg(ddev, "Setting CS7\n"); |
2283 | break; | 2278 | break; |
2284 | default: | 2279 | default: |
2285 | case CS8: | 2280 | case CS8: |
2286 | urb_value |= 8; | 2281 | value |= 8; |
2287 | dev_dbg(ddev, "Setting CS8\n"); | 2282 | dev_dbg(ddev, "Setting CS8\n"); |
2288 | break; | 2283 | break; |
2289 | } | 2284 | } |
2290 | 2285 | ||
2291 | /* This is needed by the break command since it uses the same command | 2286 | /* This is needed by the break command since it uses the same command |
2292 | - but is or'ed with this value */ | 2287 | - but is or'ed with this value */ |
2293 | priv->last_set_data_urb_value = urb_value; | 2288 | priv->last_set_data_value = value; |
2294 | 2289 | ||
2295 | if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 2290 | if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
2296 | FTDI_SIO_SET_DATA_REQUEST, | 2291 | FTDI_SIO_SET_DATA_REQUEST, |
2297 | FTDI_SIO_SET_DATA_REQUEST_TYPE, | 2292 | FTDI_SIO_SET_DATA_REQUEST_TYPE, |
2298 | urb_value , priv->interface, | 2293 | value , priv->interface, |
2299 | NULL, 0, WDR_SHORT_TIMEOUT) < 0) { | 2294 | NULL, 0, WDR_SHORT_TIMEOUT) < 0) { |
2300 | dev_err(ddev, "%s FAILED to set databits/stopbits/parity\n", | 2295 | dev_err(ddev, "%s FAILED to set databits/stopbits/parity\n", |
2301 | __func__); | 2296 | __func__); |
@@ -2326,65 +2321,30 @@ no_data_parity_stop_changes: | |||
2326 | set_mctrl(port, TIOCM_DTR | TIOCM_RTS); | 2321 | set_mctrl(port, TIOCM_DTR | TIOCM_RTS); |
2327 | } | 2322 | } |
2328 | 2323 | ||
2329 | /* Set flow control */ | ||
2330 | /* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */ | ||
2331 | no_c_cflag_changes: | 2324 | no_c_cflag_changes: |
2332 | if (cflag & CRTSCTS) { | 2325 | /* Set hardware-assisted flow control */ |
2333 | dev_dbg(ddev, "%s Setting to CRTSCTS flow control\n", __func__); | 2326 | value = 0; |
2334 | if (usb_control_msg(dev, | 2327 | |
2335 | usb_sndctrlpipe(dev, 0), | 2328 | if (C_CRTSCTS(tty)) { |
2336 | FTDI_SIO_SET_FLOW_CTRL_REQUEST, | 2329 | dev_dbg(&port->dev, "enabling rts/cts flow control\n"); |
2337 | FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, | 2330 | index = FTDI_SIO_RTS_CTS_HS; |
2338 | 0 , (FTDI_SIO_RTS_CTS_HS | priv->interface), | 2331 | } else if (I_IXON(tty)) { |
2339 | NULL, 0, WDR_TIMEOUT) < 0) { | 2332 | dev_dbg(&port->dev, "enabling xon/xoff flow control\n"); |
2340 | dev_err(ddev, "urb failed to set to rts/cts flow control\n"); | 2333 | index = FTDI_SIO_XON_XOFF_HS; |
2341 | } | 2334 | value = STOP_CHAR(tty) << 8 | START_CHAR(tty); |
2342 | } else { | 2335 | } else { |
2343 | /* | 2336 | dev_dbg(&port->dev, "disabling flow control\n"); |
2344 | * Xon/Xoff code | 2337 | index = FTDI_SIO_DISABLE_FLOW_CTRL; |
2345 | * | ||
2346 | * Check the IXOFF status in the iflag component of the | ||
2347 | * termios structure. If IXOFF is not set, the pre-xon/xoff | ||
2348 | * code is executed. | ||
2349 | */ | ||
2350 | if (iflag & IXOFF) { | ||
2351 | dev_dbg(ddev, "%s request to enable xonxoff iflag=%04x\n", | ||
2352 | __func__, iflag); | ||
2353 | /* Try to enable the XON/XOFF on the ftdi_sio | ||
2354 | * Set the vstart and vstop -- could have been done up | ||
2355 | * above where a lot of other dereferencing is done but | ||
2356 | * that would be very inefficient as vstart and vstop | ||
2357 | * are not always needed. | ||
2358 | */ | ||
2359 | vstart = termios->c_cc[VSTART]; | ||
2360 | vstop = termios->c_cc[VSTOP]; | ||
2361 | urb_value = (vstop << 8) | (vstart); | ||
2362 | |||
2363 | if (usb_control_msg(dev, | ||
2364 | usb_sndctrlpipe(dev, 0), | ||
2365 | FTDI_SIO_SET_FLOW_CTRL_REQUEST, | ||
2366 | FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, | ||
2367 | urb_value , (FTDI_SIO_XON_XOFF_HS | ||
2368 | | priv->interface), | ||
2369 | NULL, 0, WDR_TIMEOUT) < 0) { | ||
2370 | dev_err(&port->dev, "urb failed to set to " | ||
2371 | "xon/xoff flow control\n"); | ||
2372 | } | ||
2373 | } else { | ||
2374 | /* else clause to only run if cflag ! CRTSCTS and iflag | ||
2375 | * ! XOFF. CHECKME Assuming XON/XOFF handled by tty | ||
2376 | * stack - not by device */ | ||
2377 | dev_dbg(ddev, "%s Turning off hardware flow control\n", __func__); | ||
2378 | if (usb_control_msg(dev, | ||
2379 | usb_sndctrlpipe(dev, 0), | ||
2380 | FTDI_SIO_SET_FLOW_CTRL_REQUEST, | ||
2381 | FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, | ||
2382 | 0, priv->interface, | ||
2383 | NULL, 0, WDR_TIMEOUT) < 0) { | ||
2384 | dev_err(ddev, "urb failed to clear flow control\n"); | ||
2385 | } | ||
2386 | } | ||
2387 | } | 2338 | } |
2339 | |||
2340 | index |= priv->interface; | ||
2341 | |||
2342 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
2343 | FTDI_SIO_SET_FLOW_CTRL_REQUEST, | ||
2344 | FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, | ||
2345 | value, index, NULL, 0, WDR_TIMEOUT); | ||
2346 | if (ret < 0) | ||
2347 | dev_err(&port->dev, "failed to set flow control: %d\n", ret); | ||
2388 | } | 2348 | } |
2389 | 2349 | ||
2390 | /* | 2350 | /* |
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 2058852a87fa..664e61f16b6a 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
@@ -1916,7 +1916,8 @@ static const struct usb_device_id option_ids[] = { | |||
1916 | { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d01, 0xff) }, /* D-Link DWM-156 (variant) */ | 1916 | { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d01, 0xff) }, /* D-Link DWM-156 (variant) */ |
1917 | { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d02, 0xff) }, | 1917 | { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d02, 0xff) }, |
1918 | { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d03, 0xff) }, | 1918 | { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d03, 0xff) }, |
1919 | { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d04, 0xff) }, /* D-Link DWM-158 */ | 1919 | { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d04, 0xff), /* D-Link DWM-158 */ |
1920 | .driver_info = RSVD(4) | RSVD(5) }, | ||
1920 | { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d0e, 0xff) }, /* D-Link DWM-157 C1 */ | 1921 | { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d0e, 0xff) }, /* D-Link DWM-157 C1 */ |
1921 | { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e19, 0xff), /* D-Link DWM-221 B1 */ | 1922 | { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e19, 0xff), /* D-Link DWM-221 B1 */ |
1922 | .driver_info = RSVD(4) }, | 1923 | .driver_info = RSVD(4) }, |
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 46dd09da2434..5d1a1931967e 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -533,6 +533,17 @@ static int pl2303_set_line_request(struct usb_serial_port *port, | |||
533 | return 0; | 533 | return 0; |
534 | } | 534 | } |
535 | 535 | ||
536 | static bool pl2303_termios_change(const struct ktermios *a, const struct ktermios *b) | ||
537 | { | ||
538 | bool ixon_change; | ||
539 | |||
540 | ixon_change = ((a->c_iflag ^ b->c_iflag) & (IXON | IXANY)) || | ||
541 | a->c_cc[VSTART] != b->c_cc[VSTART] || | ||
542 | a->c_cc[VSTOP] != b->c_cc[VSTOP]; | ||
543 | |||
544 | return tty_termios_hw_change(a, b) || ixon_change; | ||
545 | } | ||
546 | |||
536 | static void pl2303_set_termios(struct tty_struct *tty, | 547 | static void pl2303_set_termios(struct tty_struct *tty, |
537 | struct usb_serial_port *port, struct ktermios *old_termios) | 548 | struct usb_serial_port *port, struct ktermios *old_termios) |
538 | { | 549 | { |
@@ -544,7 +555,7 @@ static void pl2303_set_termios(struct tty_struct *tty, | |||
544 | int ret; | 555 | int ret; |
545 | u8 control; | 556 | u8 control; |
546 | 557 | ||
547 | if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios)) | 558 | if (old_termios && !pl2303_termios_change(&tty->termios, old_termios)) |
548 | return; | 559 | return; |
549 | 560 | ||
550 | buf = kzalloc(7, GFP_KERNEL); | 561 | buf = kzalloc(7, GFP_KERNEL); |
@@ -662,6 +673,9 @@ static void pl2303_set_termios(struct tty_struct *tty, | |||
662 | pl2303_vendor_write(serial, 0x0, 0x41); | 673 | pl2303_vendor_write(serial, 0x0, 0x41); |
663 | else | 674 | else |
664 | pl2303_vendor_write(serial, 0x0, 0x61); | 675 | pl2303_vendor_write(serial, 0x0, 0x61); |
676 | } else if (I_IXON(tty) && !I_IXANY(tty) && START_CHAR(tty) == 0x11 && | ||
677 | STOP_CHAR(tty) == 0x13) { | ||
678 | pl2303_vendor_write(serial, 0x0, 0xc0); | ||
665 | } else { | 679 | } else { |
666 | pl2303_vendor_write(serial, 0x0, 0x0); | 680 | pl2303_vendor_write(serial, 0x0, 0x0); |
667 | } | 681 | } |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 268ffa6b51d2..f7aaa7f079e1 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -192,7 +192,7 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty) | |||
192 | if (retval) | 192 | if (retval) |
193 | goto error_get_interface; | 193 | goto error_get_interface; |
194 | 194 | ||
195 | retval = tty_port_install(&port->port, driver, tty); | 195 | retval = tty_standard_install(driver, tty); |
196 | if (retval) | 196 | if (retval) |
197 | goto error_init_termios; | 197 | goto error_init_termios; |
198 | 198 | ||
diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c index ec4d92c92762..4f542df37a44 100644 --- a/drivers/usb/storage/freecom.c +++ b/drivers/usb/storage/freecom.c | |||
@@ -464,7 +464,7 @@ static int init_freecom(struct us_data *us) | |||
464 | usb_stor_dbg(us, "result from activate reset is %d\n", result); | 464 | usb_stor_dbg(us, "result from activate reset is %d\n", result); |
465 | 465 | ||
466 | /* wait 250ms */ | 466 | /* wait 250ms */ |
467 | mdelay(250); | 467 | msleep(250); |
468 | 468 | ||
469 | /* clear reset */ | 469 | /* clear reset */ |
470 | result = usb_stor_control_msg(us, us->send_ctrl_pipe, | 470 | result = usb_stor_control_msg(us, us->send_ctrl_pipe, |
@@ -472,7 +472,7 @@ static int init_freecom(struct us_data *us) | |||
472 | usb_stor_dbg(us, "result from clear reset is %d\n", result); | 472 | usb_stor_dbg(us, "result from clear reset is %d\n", result); |
473 | 473 | ||
474 | /* wait 3 seconds */ | 474 | /* wait 3 seconds */ |
475 | mdelay(3 * 1000); | 475 | msleep(3 * 1000); |
476 | 476 | ||
477 | return USB_STOR_TRANSPORT_GOOD; | 477 | return USB_STOR_TRANSPORT_GOOD; |
478 | } | 478 | } |
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 6034c39b67d1..9e9de5452860 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c | |||
@@ -836,6 +836,12 @@ static int uas_slave_configure(struct scsi_device *sdev) | |||
836 | if (devinfo->flags & US_FL_BROKEN_FUA) | 836 | if (devinfo->flags & US_FL_BROKEN_FUA) |
837 | sdev->broken_fua = 1; | 837 | sdev->broken_fua = 1; |
838 | 838 | ||
839 | /* UAS also needs to support FL_ALWAYS_SYNC */ | ||
840 | if (devinfo->flags & US_FL_ALWAYS_SYNC) { | ||
841 | sdev->skip_ms_page_3f = 1; | ||
842 | sdev->skip_ms_page_8 = 1; | ||
843 | sdev->wce_default_on = 1; | ||
844 | } | ||
839 | scsi_change_queue_depth(sdev, devinfo->qdepth - 2); | 845 | scsi_change_queue_depth(sdev, devinfo->qdepth - 2); |
840 | return 0; | 846 | return 0; |
841 | } | 847 | } |
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 747d3a9596d9..22fcfccf453a 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h | |||
@@ -2321,6 +2321,15 @@ UNUSUAL_DEV( 0x4146, 0xba01, 0x0100, 0x0100, | |||
2321 | "Micro Mini 1GB", | 2321 | "Micro Mini 1GB", |
2322 | USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), | 2322 | USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), |
2323 | 2323 | ||
2324 | /* "G-DRIVE" external HDD hangs on write without these. | ||
2325 | * Patch submitted by Alexander Kappner <agk@godking.net> | ||
2326 | */ | ||
2327 | UNUSUAL_DEV(0x4971, 0x8024, 0x0000, 0x9999, | ||
2328 | "SimpleTech", | ||
2329 | "External HDD", | ||
2330 | USB_SC_DEVICE, USB_PR_DEVICE, NULL, | ||
2331 | US_FL_ALWAYS_SYNC), | ||
2332 | |||
2324 | /* | 2333 | /* |
2325 | * Nick Bowler <nbowler@elliptictech.com> | 2334 | * Nick Bowler <nbowler@elliptictech.com> |
2326 | * SCSI stack spams (otherwise harmless) error messages. | 2335 | * SCSI stack spams (otherwise harmless) error messages. |
diff --git a/drivers/usb/storage/unusual_uas.h b/drivers/usb/storage/unusual_uas.h index 38434d88954a..d0bdebd87ce3 100644 --- a/drivers/usb/storage/unusual_uas.h +++ b/drivers/usb/storage/unusual_uas.h | |||
@@ -107,3 +107,12 @@ UNUSUAL_DEV(0x4971, 0x8017, 0x0000, 0x9999, | |||
107 | "External HDD", | 107 | "External HDD", |
108 | USB_SC_DEVICE, USB_PR_DEVICE, NULL, | 108 | USB_SC_DEVICE, USB_PR_DEVICE, NULL, |
109 | US_FL_NO_REPORT_OPCODES), | 109 | US_FL_NO_REPORT_OPCODES), |
110 | |||
111 | /* "G-DRIVE" external HDD hangs on write without these. | ||
112 | * Patch submitted by Alexander Kappner <agk@godking.net> | ||
113 | */ | ||
114 | UNUSUAL_DEV(0x4971, 0x8024, 0x0000, 0x9999, | ||
115 | "SimpleTech", | ||
116 | "External HDD", | ||
117 | USB_SC_DEVICE, USB_PR_DEVICE, NULL, | ||
118 | US_FL_ALWAYS_SYNC), | ||
diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig index 030f88cb0c3f..2c8eab11a493 100644 --- a/drivers/usb/typec/Kconfig +++ b/drivers/usb/typec/Kconfig | |||
@@ -49,6 +49,7 @@ config TYPEC_TCPM | |||
49 | tristate "USB Type-C Port Controller Manager" | 49 | tristate "USB Type-C Port Controller Manager" |
50 | depends on USB | 50 | depends on USB |
51 | select USB_ROLE_SWITCH | 51 | select USB_ROLE_SWITCH |
52 | select POWER_SUPPLY | ||
52 | help | 53 | help |
53 | The Type-C Port Controller Manager provides a USB PD and USB Type-C | 54 | The Type-C Port Controller Manager provides a USB PD and USB Type-C |
54 | state machine for use with Type-C Port Controllers. | 55 | state machine for use with Type-C Port Controllers. |
diff --git a/drivers/usb/typec/fusb302/Kconfig b/drivers/usb/typec/fusb302/Kconfig index 48a4f2fcee03..fce099ff39fe 100644 --- a/drivers/usb/typec/fusb302/Kconfig +++ b/drivers/usb/typec/fusb302/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config TYPEC_FUSB302 | 1 | config TYPEC_FUSB302 |
2 | tristate "Fairchild FUSB302 Type-C chip driver" | 2 | tristate "Fairchild FUSB302 Type-C chip driver" |
3 | depends on I2C && POWER_SUPPLY | 3 | depends on I2C |
4 | help | 4 | help |
5 | The Fairchild FUSB302 Type-C chip driver that works with | 5 | The Fairchild FUSB302 Type-C chip driver that works with |
6 | Type-C Port Controller Manager to provide USB PD and USB | 6 | Type-C Port Controller Manager to provide USB PD and USB |
diff --git a/drivers/usb/typec/fusb302/fusb302.c b/drivers/usb/typec/fusb302/fusb302.c index 703617129067..1e68da10bf17 100644 --- a/drivers/usb/typec/fusb302/fusb302.c +++ b/drivers/usb/typec/fusb302/fusb302.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/of_device.h> | 18 | #include <linux/of_device.h> |
19 | #include <linux/of_gpio.h> | 19 | #include <linux/of_gpio.h> |
20 | #include <linux/pinctrl/consumer.h> | 20 | #include <linux/pinctrl/consumer.h> |
21 | #include <linux/power_supply.h> | ||
22 | #include <linux/proc_fs.h> | 21 | #include <linux/proc_fs.h> |
23 | #include <linux/regulator/consumer.h> | 22 | #include <linux/regulator/consumer.h> |
24 | #include <linux/sched/clock.h> | 23 | #include <linux/sched/clock.h> |
@@ -99,11 +98,6 @@ struct fusb302_chip { | |||
99 | /* lock for sharing chip states */ | 98 | /* lock for sharing chip states */ |
100 | struct mutex lock; | 99 | struct mutex lock; |
101 | 100 | ||
102 | /* psy + psy status */ | ||
103 | struct power_supply *psy; | ||
104 | u32 current_limit; | ||
105 | u32 supply_voltage; | ||
106 | |||
107 | /* chip status */ | 101 | /* chip status */ |
108 | enum toggling_mode toggling_mode; | 102 | enum toggling_mode toggling_mode; |
109 | enum src_current_status src_current_status; | 103 | enum src_current_status src_current_status; |
@@ -120,6 +114,7 @@ struct fusb302_chip { | |||
120 | enum typec_cc_polarity cc_polarity; | 114 | enum typec_cc_polarity cc_polarity; |
121 | enum typec_cc_status cc1; | 115 | enum typec_cc_status cc1; |
122 | enum typec_cc_status cc2; | 116 | enum typec_cc_status cc2; |
117 | u32 snk_pdo[PDO_MAX_OBJECTS]; | ||
123 | 118 | ||
124 | #ifdef CONFIG_DEBUG_FS | 119 | #ifdef CONFIG_DEBUG_FS |
125 | struct dentry *dentry; | 120 | struct dentry *dentry; |
@@ -220,32 +215,28 @@ DEFINE_SHOW_ATTRIBUTE(fusb302_debug); | |||
220 | 215 | ||
221 | static struct dentry *rootdir; | 216 | static struct dentry *rootdir; |
222 | 217 | ||
223 | static int fusb302_debugfs_init(struct fusb302_chip *chip) | 218 | static void fusb302_debugfs_init(struct fusb302_chip *chip) |
224 | { | 219 | { |
225 | mutex_init(&chip->logbuffer_lock); | 220 | mutex_init(&chip->logbuffer_lock); |
226 | if (!rootdir) { | 221 | if (!rootdir) |
227 | rootdir = debugfs_create_dir("fusb302", NULL); | 222 | rootdir = debugfs_create_dir("fusb302", NULL); |
228 | if (!rootdir) | ||
229 | return -ENOMEM; | ||
230 | } | ||
231 | 223 | ||
232 | chip->dentry = debugfs_create_file(dev_name(chip->dev), | 224 | chip->dentry = debugfs_create_file(dev_name(chip->dev), |
233 | S_IFREG | 0444, rootdir, | 225 | S_IFREG | 0444, rootdir, |
234 | chip, &fusb302_debug_fops); | 226 | chip, &fusb302_debug_fops); |
235 | |||
236 | return 0; | ||
237 | } | 227 | } |
238 | 228 | ||
239 | static void fusb302_debugfs_exit(struct fusb302_chip *chip) | 229 | static void fusb302_debugfs_exit(struct fusb302_chip *chip) |
240 | { | 230 | { |
241 | debugfs_remove(chip->dentry); | 231 | debugfs_remove(chip->dentry); |
232 | debugfs_remove(rootdir); | ||
242 | } | 233 | } |
243 | 234 | ||
244 | #else | 235 | #else |
245 | 236 | ||
246 | static void fusb302_log(const struct fusb302_chip *chip, | 237 | static void fusb302_log(const struct fusb302_chip *chip, |
247 | const char *fmt, ...) { } | 238 | const char *fmt, ...) { } |
248 | static int fusb302_debugfs_init(const struct fusb302_chip *chip) { return 0; } | 239 | static void fusb302_debugfs_init(const struct fusb302_chip *chip) { } |
249 | static void fusb302_debugfs_exit(const struct fusb302_chip *chip) { } | 240 | static void fusb302_debugfs_exit(const struct fusb302_chip *chip) { } |
250 | 241 | ||
251 | #endif | 242 | #endif |
@@ -861,13 +852,11 @@ static int tcpm_set_vbus(struct tcpc_dev *dev, bool on, bool charge) | |||
861 | chip->vbus_on = on; | 852 | chip->vbus_on = on; |
862 | fusb302_log(chip, "vbus := %s", on ? "On" : "Off"); | 853 | fusb302_log(chip, "vbus := %s", on ? "On" : "Off"); |
863 | } | 854 | } |
864 | if (chip->charge_on == charge) { | 855 | if (chip->charge_on == charge) |
865 | fusb302_log(chip, "charge is already %s", | 856 | fusb302_log(chip, "charge is already %s", |
866 | charge ? "On" : "Off"); | 857 | charge ? "On" : "Off"); |
867 | } else { | 858 | else |
868 | chip->charge_on = charge; | 859 | chip->charge_on = charge; |
869 | power_supply_changed(chip->psy); | ||
870 | } | ||
871 | 860 | ||
872 | done: | 861 | done: |
873 | mutex_unlock(&chip->lock); | 862 | mutex_unlock(&chip->lock); |
@@ -883,11 +872,6 @@ static int tcpm_set_current_limit(struct tcpc_dev *dev, u32 max_ma, u32 mv) | |||
883 | fusb302_log(chip, "current limit: %d ma, %d mv (not implemented)", | 872 | fusb302_log(chip, "current limit: %d ma, %d mv (not implemented)", |
884 | max_ma, mv); | 873 | max_ma, mv); |
885 | 874 | ||
886 | chip->supply_voltage = mv; | ||
887 | chip->current_limit = max_ma; | ||
888 | |||
889 | power_supply_changed(chip->psy); | ||
890 | |||
891 | return 0; | 875 | return 0; |
892 | } | 876 | } |
893 | 877 | ||
@@ -1212,11 +1196,6 @@ static const u32 snk_pdo[] = { | |||
1212 | static const struct tcpc_config fusb302_tcpc_config = { | 1196 | static const struct tcpc_config fusb302_tcpc_config = { |
1213 | .src_pdo = src_pdo, | 1197 | .src_pdo = src_pdo, |
1214 | .nr_src_pdo = ARRAY_SIZE(src_pdo), | 1198 | .nr_src_pdo = ARRAY_SIZE(src_pdo), |
1215 | .snk_pdo = snk_pdo, | ||
1216 | .nr_snk_pdo = ARRAY_SIZE(snk_pdo), | ||
1217 | .max_snk_mv = 5000, | ||
1218 | .max_snk_ma = 3000, | ||
1219 | .max_snk_mw = 15000, | ||
1220 | .operating_snk_mw = 2500, | 1199 | .operating_snk_mw = 2500, |
1221 | .type = TYPEC_PORT_DRP, | 1200 | .type = TYPEC_PORT_DRP, |
1222 | .data = TYPEC_PORT_DRD, | 1201 | .data = TYPEC_PORT_DRD, |
@@ -1686,43 +1665,6 @@ done: | |||
1686 | return IRQ_HANDLED; | 1665 | return IRQ_HANDLED; |
1687 | } | 1666 | } |
1688 | 1667 | ||
1689 | static int fusb302_psy_get_property(struct power_supply *psy, | ||
1690 | enum power_supply_property psp, | ||
1691 | union power_supply_propval *val) | ||
1692 | { | ||
1693 | struct fusb302_chip *chip = power_supply_get_drvdata(psy); | ||
1694 | |||
1695 | switch (psp) { | ||
1696 | case POWER_SUPPLY_PROP_ONLINE: | ||
1697 | val->intval = chip->charge_on; | ||
1698 | break; | ||
1699 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
1700 | val->intval = chip->supply_voltage * 1000; /* mV -> µV */ | ||
1701 | break; | ||
1702 | case POWER_SUPPLY_PROP_CURRENT_MAX: | ||
1703 | val->intval = chip->current_limit * 1000; /* mA -> µA */ | ||
1704 | break; | ||
1705 | default: | ||
1706 | return -ENODATA; | ||
1707 | } | ||
1708 | |||
1709 | return 0; | ||
1710 | } | ||
1711 | |||
1712 | static enum power_supply_property fusb302_psy_properties[] = { | ||
1713 | POWER_SUPPLY_PROP_ONLINE, | ||
1714 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
1715 | POWER_SUPPLY_PROP_CURRENT_MAX, | ||
1716 | }; | ||
1717 | |||
1718 | static const struct power_supply_desc fusb302_psy_desc = { | ||
1719 | .name = "fusb302-typec-source", | ||
1720 | .type = POWER_SUPPLY_TYPE_USB_TYPE_C, | ||
1721 | .properties = fusb302_psy_properties, | ||
1722 | .num_properties = ARRAY_SIZE(fusb302_psy_properties), | ||
1723 | .get_property = fusb302_psy_get_property, | ||
1724 | }; | ||
1725 | |||
1726 | static int init_gpio(struct fusb302_chip *chip) | 1668 | static int init_gpio(struct fusb302_chip *chip) |
1727 | { | 1669 | { |
1728 | struct device_node *node; | 1670 | struct device_node *node; |
@@ -1756,13 +1698,35 @@ static int init_gpio(struct fusb302_chip *chip) | |||
1756 | return 0; | 1698 | return 0; |
1757 | } | 1699 | } |
1758 | 1700 | ||
1701 | static int fusb302_composite_snk_pdo_array(struct fusb302_chip *chip) | ||
1702 | { | ||
1703 | struct device *dev = chip->dev; | ||
1704 | u32 max_uv, max_ua; | ||
1705 | |||
1706 | chip->snk_pdo[0] = PDO_FIXED(5000, 400, PDO_FIXED_FLAGS); | ||
1707 | |||
1708 | /* | ||
1709 | * As max_snk_ma/mv/mw is not needed for tcpc_config, | ||
1710 | * those settings should be passed in via sink PDO, so | ||
1711 | * "fcs, max-sink-*" properties will be deprecated, to | ||
1712 | * perserve compatibility with existing users of them, | ||
1713 | * we read those properties to convert them to be a var | ||
1714 | * PDO. | ||
1715 | */ | ||
1716 | if (device_property_read_u32(dev, "fcs,max-sink-microvolt", &max_uv) || | ||
1717 | device_property_read_u32(dev, "fcs,max-sink-microamp", &max_ua)) | ||
1718 | return 1; | ||
1719 | |||
1720 | chip->snk_pdo[1] = PDO_VAR(5000, max_uv / 1000, max_ua / 1000); | ||
1721 | return 2; | ||
1722 | } | ||
1723 | |||
1759 | static int fusb302_probe(struct i2c_client *client, | 1724 | static int fusb302_probe(struct i2c_client *client, |
1760 | const struct i2c_device_id *id) | 1725 | const struct i2c_device_id *id) |
1761 | { | 1726 | { |
1762 | struct fusb302_chip *chip; | 1727 | struct fusb302_chip *chip; |
1763 | struct i2c_adapter *adapter; | 1728 | struct i2c_adapter *adapter; |
1764 | struct device *dev = &client->dev; | 1729 | struct device *dev = &client->dev; |
1765 | struct power_supply_config cfg = {}; | ||
1766 | const char *name; | 1730 | const char *name; |
1767 | int ret = 0; | 1731 | int ret = 0; |
1768 | u32 v; | 1732 | u32 v; |
@@ -1784,18 +1748,13 @@ static int fusb302_probe(struct i2c_client *client, | |||
1784 | chip->tcpc_dev.config = &chip->tcpc_config; | 1748 | chip->tcpc_dev.config = &chip->tcpc_config; |
1785 | mutex_init(&chip->lock); | 1749 | mutex_init(&chip->lock); |
1786 | 1750 | ||
1787 | if (!device_property_read_u32(dev, "fcs,max-sink-microvolt", &v)) | ||
1788 | chip->tcpc_config.max_snk_mv = v / 1000; | ||
1789 | |||
1790 | if (!device_property_read_u32(dev, "fcs,max-sink-microamp", &v)) | ||
1791 | chip->tcpc_config.max_snk_ma = v / 1000; | ||
1792 | |||
1793 | if (!device_property_read_u32(dev, "fcs,max-sink-microwatt", &v)) | ||
1794 | chip->tcpc_config.max_snk_mw = v / 1000; | ||
1795 | |||
1796 | if (!device_property_read_u32(dev, "fcs,operating-sink-microwatt", &v)) | 1751 | if (!device_property_read_u32(dev, "fcs,operating-sink-microwatt", &v)) |
1797 | chip->tcpc_config.operating_snk_mw = v / 1000; | 1752 | chip->tcpc_config.operating_snk_mw = v / 1000; |
1798 | 1753 | ||
1754 | /* Composite sink PDO */ | ||
1755 | chip->tcpc_config.nr_snk_pdo = fusb302_composite_snk_pdo_array(chip); | ||
1756 | chip->tcpc_config.snk_pdo = chip->snk_pdo; | ||
1757 | |||
1799 | /* | 1758 | /* |
1800 | * Devicetree platforms should get extcon via phandle (not yet | 1759 | * Devicetree platforms should get extcon via phandle (not yet |
1801 | * supported). On ACPI platforms, we get the name from a device prop. | 1760 | * supported). On ACPI platforms, we get the name from a device prop. |
@@ -1809,17 +1768,7 @@ static int fusb302_probe(struct i2c_client *client, | |||
1809 | return -EPROBE_DEFER; | 1768 | return -EPROBE_DEFER; |
1810 | } | 1769 | } |
1811 | 1770 | ||
1812 | cfg.drv_data = chip; | 1771 | fusb302_debugfs_init(chip); |
1813 | chip->psy = devm_power_supply_register(dev, &fusb302_psy_desc, &cfg); | ||
1814 | if (IS_ERR(chip->psy)) { | ||
1815 | ret = PTR_ERR(chip->psy); | ||
1816 | dev_err(chip->dev, "Error registering power-supply: %d\n", ret); | ||
1817 | return ret; | ||
1818 | } | ||
1819 | |||
1820 | ret = fusb302_debugfs_init(chip); | ||
1821 | if (ret < 0) | ||
1822 | return ret; | ||
1823 | 1772 | ||
1824 | chip->wq = create_singlethread_workqueue(dev_name(chip->dev)); | 1773 | chip->wq = create_singlethread_workqueue(dev_name(chip->dev)); |
1825 | if (!chip->wq) { | 1774 | if (!chip->wq) { |
diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c index f89093bd7185..9d8330e9c431 100644 --- a/drivers/usb/typec/mux.c +++ b/drivers/usb/typec/mux.c | |||
@@ -178,7 +178,7 @@ EXPORT_SYMBOL_GPL(typec_mux_register); | |||
178 | 178 | ||
179 | /** | 179 | /** |
180 | * typec_mux_unregister - Unregister Multiplexer Switch | 180 | * typec_mux_unregister - Unregister Multiplexer Switch |
181 | * @sw: USB Type-C Connector Multiplexer/DeMultiplexer | 181 | * @mux: USB Type-C Connector Multiplexer/DeMultiplexer |
182 | * | 182 | * |
183 | * Unregister mux that was registered with typec_mux_register(). | 183 | * Unregister mux that was registered with typec_mux_register(). |
184 | */ | 184 | */ |
diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index ded49e3bf2b0..8a201dd53d36 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c | |||
@@ -12,13 +12,17 @@ | |||
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/mutex.h> | 14 | #include <linux/mutex.h> |
15 | #include <linux/power_supply.h> | ||
15 | #include <linux/proc_fs.h> | 16 | #include <linux/proc_fs.h> |
17 | #include <linux/property.h> | ||
16 | #include <linux/sched/clock.h> | 18 | #include <linux/sched/clock.h> |
17 | #include <linux/seq_file.h> | 19 | #include <linux/seq_file.h> |
18 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
19 | #include <linux/spinlock.h> | 21 | #include <linux/spinlock.h> |
20 | #include <linux/usb/pd.h> | 22 | #include <linux/usb/pd.h> |
23 | #include <linux/usb/pd_ado.h> | ||
21 | #include <linux/usb/pd_bdo.h> | 24 | #include <linux/usb/pd_bdo.h> |
25 | #include <linux/usb/pd_ext_sdb.h> | ||
22 | #include <linux/usb/pd_vdo.h> | 26 | #include <linux/usb/pd_vdo.h> |
23 | #include <linux/usb/role.h> | 27 | #include <linux/usb/role.h> |
24 | #include <linux/usb/tcpm.h> | 28 | #include <linux/usb/tcpm.h> |
@@ -48,6 +52,7 @@ | |||
48 | S(SNK_DISCOVERY_DEBOUNCE_DONE), \ | 52 | S(SNK_DISCOVERY_DEBOUNCE_DONE), \ |
49 | S(SNK_WAIT_CAPABILITIES), \ | 53 | S(SNK_WAIT_CAPABILITIES), \ |
50 | S(SNK_NEGOTIATE_CAPABILITIES), \ | 54 | S(SNK_NEGOTIATE_CAPABILITIES), \ |
55 | S(SNK_NEGOTIATE_PPS_CAPABILITIES), \ | ||
51 | S(SNK_TRANSITION_SINK), \ | 56 | S(SNK_TRANSITION_SINK), \ |
52 | S(SNK_TRANSITION_SINK_VBUS), \ | 57 | S(SNK_TRANSITION_SINK_VBUS), \ |
53 | S(SNK_READY), \ | 58 | S(SNK_READY), \ |
@@ -112,6 +117,11 @@ | |||
112 | S(SNK_TRYWAIT_VBUS), \ | 117 | S(SNK_TRYWAIT_VBUS), \ |
113 | S(BIST_RX), \ | 118 | S(BIST_RX), \ |
114 | \ | 119 | \ |
120 | S(GET_STATUS_SEND), \ | ||
121 | S(GET_STATUS_SEND_TIMEOUT), \ | ||
122 | S(GET_PPS_STATUS_SEND), \ | ||
123 | S(GET_PPS_STATUS_SEND_TIMEOUT), \ | ||
124 | \ | ||
115 | S(ERROR_RECOVERY), \ | 125 | S(ERROR_RECOVERY), \ |
116 | S(PORT_RESET), \ | 126 | S(PORT_RESET), \ |
117 | S(PORT_RESET_WAIT_OFF) | 127 | S(PORT_RESET_WAIT_OFF) |
@@ -142,6 +152,7 @@ enum pd_msg_request { | |||
142 | PD_MSG_NONE = 0, | 152 | PD_MSG_NONE = 0, |
143 | PD_MSG_CTRL_REJECT, | 153 | PD_MSG_CTRL_REJECT, |
144 | PD_MSG_CTRL_WAIT, | 154 | PD_MSG_CTRL_WAIT, |
155 | PD_MSG_CTRL_NOT_SUPP, | ||
145 | PD_MSG_DATA_SINK_CAP, | 156 | PD_MSG_DATA_SINK_CAP, |
146 | PD_MSG_DATA_SOURCE_CAP, | 157 | PD_MSG_DATA_SOURCE_CAP, |
147 | }; | 158 | }; |
@@ -167,6 +178,16 @@ struct pd_mode_data { | |||
167 | struct typec_altmode_desc altmode_desc[SVID_DISCOVERY_MAX]; | 178 | struct typec_altmode_desc altmode_desc[SVID_DISCOVERY_MAX]; |
168 | }; | 179 | }; |
169 | 180 | ||
181 | struct pd_pps_data { | ||
182 | u32 min_volt; | ||
183 | u32 max_volt; | ||
184 | u32 max_curr; | ||
185 | u32 out_volt; | ||
186 | u32 op_curr; | ||
187 | bool supported; | ||
188 | bool active; | ||
189 | }; | ||
190 | |||
170 | struct tcpm_port { | 191 | struct tcpm_port { |
171 | struct device *dev; | 192 | struct device *dev; |
172 | 193 | ||
@@ -235,6 +256,7 @@ struct tcpm_port { | |||
235 | struct completion swap_complete; | 256 | struct completion swap_complete; |
236 | int swap_status; | 257 | int swap_status; |
237 | 258 | ||
259 | unsigned int negotiated_rev; | ||
238 | unsigned int message_id; | 260 | unsigned int message_id; |
239 | unsigned int caps_count; | 261 | unsigned int caps_count; |
240 | unsigned int hard_reset_count; | 262 | unsigned int hard_reset_count; |
@@ -257,15 +279,18 @@ struct tcpm_port { | |||
257 | u32 snk_vdo[VDO_MAX_OBJECTS]; | 279 | u32 snk_vdo[VDO_MAX_OBJECTS]; |
258 | unsigned int nr_snk_vdo; | 280 | unsigned int nr_snk_vdo; |
259 | 281 | ||
260 | unsigned int max_snk_mv; | ||
261 | unsigned int max_snk_ma; | ||
262 | unsigned int max_snk_mw; | ||
263 | unsigned int operating_snk_mw; | 282 | unsigned int operating_snk_mw; |
283 | bool update_sink_caps; | ||
264 | 284 | ||
265 | /* Requested current / voltage */ | 285 | /* Requested current / voltage */ |
266 | u32 current_limit; | 286 | u32 current_limit; |
267 | u32 supply_voltage; | 287 | u32 supply_voltage; |
268 | 288 | ||
289 | /* Used to export TA voltage and current */ | ||
290 | struct power_supply *psy; | ||
291 | struct power_supply_desc psy_desc; | ||
292 | enum power_supply_usb_type usb_type; | ||
293 | |||
269 | u32 bist_request; | 294 | u32 bist_request; |
270 | 295 | ||
271 | /* PD state for Vendor Defined Messages */ | 296 | /* PD state for Vendor Defined Messages */ |
@@ -277,8 +302,13 @@ struct tcpm_port { | |||
277 | /* VDO to retry if UFP responder replied busy */ | 302 | /* VDO to retry if UFP responder replied busy */ |
278 | u32 vdo_retry; | 303 | u32 vdo_retry; |
279 | 304 | ||
280 | /* Alternate mode data */ | 305 | /* PPS */ |
306 | struct pd_pps_data pps_data; | ||
307 | struct completion pps_complete; | ||
308 | bool pps_pending; | ||
309 | int pps_status; | ||
281 | 310 | ||
311 | /* Alternate mode data */ | ||
282 | struct pd_mode_data mode_data; | 312 | struct pd_mode_data mode_data; |
283 | struct typec_altmode *partner_altmode[SVID_DISCOVERY_MAX]; | 313 | struct typec_altmode *partner_altmode[SVID_DISCOVERY_MAX]; |
284 | struct typec_altmode *port_altmode[SVID_DISCOVERY_MAX]; | 314 | struct typec_altmode *port_altmode[SVID_DISCOVERY_MAX]; |
@@ -496,6 +526,16 @@ static void tcpm_log_source_caps(struct tcpm_port *port) | |||
496 | pdo_max_voltage(pdo), | 526 | pdo_max_voltage(pdo), |
497 | pdo_max_power(pdo)); | 527 | pdo_max_power(pdo)); |
498 | break; | 528 | break; |
529 | case PDO_TYPE_APDO: | ||
530 | if (pdo_apdo_type(pdo) == APDO_TYPE_PPS) | ||
531 | scnprintf(msg, sizeof(msg), | ||
532 | "%u-%u mV, %u mA", | ||
533 | pdo_pps_apdo_min_voltage(pdo), | ||
534 | pdo_pps_apdo_max_voltage(pdo), | ||
535 | pdo_pps_apdo_max_current(pdo)); | ||
536 | else | ||
537 | strcpy(msg, "undefined APDO"); | ||
538 | break; | ||
499 | default: | 539 | default: |
500 | strcpy(msg, "undefined"); | 540 | strcpy(msg, "undefined"); |
501 | break; | 541 | break; |
@@ -526,21 +566,16 @@ DEFINE_SHOW_ATTRIBUTE(tcpm_debug); | |||
526 | 566 | ||
527 | static struct dentry *rootdir; | 567 | static struct dentry *rootdir; |
528 | 568 | ||
529 | static int tcpm_debugfs_init(struct tcpm_port *port) | 569 | static void tcpm_debugfs_init(struct tcpm_port *port) |
530 | { | 570 | { |
531 | mutex_init(&port->logbuffer_lock); | 571 | mutex_init(&port->logbuffer_lock); |
532 | /* /sys/kernel/debug/tcpm/usbcX */ | 572 | /* /sys/kernel/debug/tcpm/usbcX */ |
533 | if (!rootdir) { | 573 | if (!rootdir) |
534 | rootdir = debugfs_create_dir("tcpm", NULL); | 574 | rootdir = debugfs_create_dir("tcpm", NULL); |
535 | if (!rootdir) | ||
536 | return -ENOMEM; | ||
537 | } | ||
538 | 575 | ||
539 | port->dentry = debugfs_create_file(dev_name(port->dev), | 576 | port->dentry = debugfs_create_file(dev_name(port->dev), |
540 | S_IFREG | 0444, rootdir, | 577 | S_IFREG | 0444, rootdir, |
541 | port, &tcpm_debug_fops); | 578 | port, &tcpm_debug_fops); |
542 | |||
543 | return 0; | ||
544 | } | 579 | } |
545 | 580 | ||
546 | static void tcpm_debugfs_exit(struct tcpm_port *port) | 581 | static void tcpm_debugfs_exit(struct tcpm_port *port) |
@@ -555,7 +590,7 @@ static void tcpm_log(const struct tcpm_port *port, const char *fmt, ...) { } | |||
555 | __printf(2, 3) | 590 | __printf(2, 3) |
556 | static void tcpm_log_force(struct tcpm_port *port, const char *fmt, ...) { } | 591 | static void tcpm_log_force(struct tcpm_port *port, const char *fmt, ...) { } |
557 | static void tcpm_log_source_caps(struct tcpm_port *port) { } | 592 | static void tcpm_log_source_caps(struct tcpm_port *port) { } |
558 | static int tcpm_debugfs_init(const struct tcpm_port *port) { return 0; } | 593 | static void tcpm_debugfs_init(const struct tcpm_port *port) { } |
559 | static void tcpm_debugfs_exit(const struct tcpm_port *port) { } | 594 | static void tcpm_debugfs_exit(const struct tcpm_port *port) { } |
560 | 595 | ||
561 | #endif | 596 | #endif |
@@ -793,11 +828,13 @@ static int tcpm_pd_send_source_caps(struct tcpm_port *port) | |||
793 | msg.header = PD_HEADER_LE(PD_CTRL_REJECT, | 828 | msg.header = PD_HEADER_LE(PD_CTRL_REJECT, |
794 | port->pwr_role, | 829 | port->pwr_role, |
795 | port->data_role, | 830 | port->data_role, |
831 | port->negotiated_rev, | ||
796 | port->message_id, 0); | 832 | port->message_id, 0); |
797 | } else { | 833 | } else { |
798 | msg.header = PD_HEADER_LE(PD_DATA_SOURCE_CAP, | 834 | msg.header = PD_HEADER_LE(PD_DATA_SOURCE_CAP, |
799 | port->pwr_role, | 835 | port->pwr_role, |
800 | port->data_role, | 836 | port->data_role, |
837 | port->negotiated_rev, | ||
801 | port->message_id, | 838 | port->message_id, |
802 | port->nr_src_pdo); | 839 | port->nr_src_pdo); |
803 | } | 840 | } |
@@ -818,11 +855,13 @@ static int tcpm_pd_send_sink_caps(struct tcpm_port *port) | |||
818 | msg.header = PD_HEADER_LE(PD_CTRL_REJECT, | 855 | msg.header = PD_HEADER_LE(PD_CTRL_REJECT, |
819 | port->pwr_role, | 856 | port->pwr_role, |
820 | port->data_role, | 857 | port->data_role, |
858 | port->negotiated_rev, | ||
821 | port->message_id, 0); | 859 | port->message_id, 0); |
822 | } else { | 860 | } else { |
823 | msg.header = PD_HEADER_LE(PD_DATA_SINK_CAP, | 861 | msg.header = PD_HEADER_LE(PD_DATA_SINK_CAP, |
824 | port->pwr_role, | 862 | port->pwr_role, |
825 | port->data_role, | 863 | port->data_role, |
864 | port->negotiated_rev, | ||
826 | port->message_id, | 865 | port->message_id, |
827 | port->nr_snk_pdo); | 866 | port->nr_snk_pdo); |
828 | } | 867 | } |
@@ -1189,6 +1228,7 @@ static void vdm_run_state_machine(struct tcpm_port *port) | |||
1189 | msg.header = PD_HEADER_LE(PD_DATA_VENDOR_DEF, | 1228 | msg.header = PD_HEADER_LE(PD_DATA_VENDOR_DEF, |
1190 | port->pwr_role, | 1229 | port->pwr_role, |
1191 | port->data_role, | 1230 | port->data_role, |
1231 | port->negotiated_rev, | ||
1192 | port->message_id, port->vdo_count); | 1232 | port->message_id, port->vdo_count); |
1193 | for (i = 0; i < port->vdo_count; i++) | 1233 | for (i = 0; i < port->vdo_count; i++) |
1194 | msg.payload[i] = cpu_to_le32(port->vdo_data[i]); | 1234 | msg.payload[i] = cpu_to_le32(port->vdo_data[i]); |
@@ -1260,6 +1300,8 @@ enum pdo_err { | |||
1260 | PDO_ERR_FIXED_NOT_SORTED, | 1300 | PDO_ERR_FIXED_NOT_SORTED, |
1261 | PDO_ERR_VARIABLE_BATT_NOT_SORTED, | 1301 | PDO_ERR_VARIABLE_BATT_NOT_SORTED, |
1262 | PDO_ERR_DUPE_PDO, | 1302 | PDO_ERR_DUPE_PDO, |
1303 | PDO_ERR_PPS_APDO_NOT_SORTED, | ||
1304 | PDO_ERR_DUPE_PPS_APDO, | ||
1263 | }; | 1305 | }; |
1264 | 1306 | ||
1265 | static const char * const pdo_err_msg[] = { | 1307 | static const char * const pdo_err_msg[] = { |
@@ -1275,6 +1317,10 @@ static const char * const pdo_err_msg[] = { | |||
1275 | " err: Variable/Battery supply pdos should be in increasing order of their minimum voltage", | 1317 | " err: Variable/Battery supply pdos should be in increasing order of their minimum voltage", |
1276 | [PDO_ERR_DUPE_PDO] = | 1318 | [PDO_ERR_DUPE_PDO] = |
1277 | " err: Variable/Batt supply pdos cannot have same min/max voltage", | 1319 | " err: Variable/Batt supply pdos cannot have same min/max voltage", |
1320 | [PDO_ERR_PPS_APDO_NOT_SORTED] = | ||
1321 | " err: Programmable power supply apdos should be in increasing order of their maximum voltage", | ||
1322 | [PDO_ERR_DUPE_PPS_APDO] = | ||
1323 | " err: Programmable power supply apdos cannot have same min/max voltage and max current", | ||
1278 | }; | 1324 | }; |
1279 | 1325 | ||
1280 | static enum pdo_err tcpm_caps_err(struct tcpm_port *port, const u32 *pdo, | 1326 | static enum pdo_err tcpm_caps_err(struct tcpm_port *port, const u32 *pdo, |
@@ -1324,6 +1370,26 @@ static enum pdo_err tcpm_caps_err(struct tcpm_port *port, const u32 *pdo, | |||
1324 | pdo_min_voltage(pdo[i - 1]))) | 1370 | pdo_min_voltage(pdo[i - 1]))) |
1325 | return PDO_ERR_DUPE_PDO; | 1371 | return PDO_ERR_DUPE_PDO; |
1326 | break; | 1372 | break; |
1373 | /* | ||
1374 | * The Programmable Power Supply APDOs, if present, | ||
1375 | * shall be sent in Maximum Voltage order; | ||
1376 | * lowest to highest. | ||
1377 | */ | ||
1378 | case PDO_TYPE_APDO: | ||
1379 | if (pdo_apdo_type(pdo[i]) != APDO_TYPE_PPS) | ||
1380 | break; | ||
1381 | |||
1382 | if (pdo_pps_apdo_max_current(pdo[i]) < | ||
1383 | pdo_pps_apdo_max_current(pdo[i - 1])) | ||
1384 | return PDO_ERR_PPS_APDO_NOT_SORTED; | ||
1385 | else if (pdo_pps_apdo_min_voltage(pdo[i]) == | ||
1386 | pdo_pps_apdo_min_voltage(pdo[i - 1]) && | ||
1387 | pdo_pps_apdo_max_voltage(pdo[i]) == | ||
1388 | pdo_pps_apdo_max_voltage(pdo[i - 1]) && | ||
1389 | pdo_pps_apdo_max_current(pdo[i]) == | ||
1390 | pdo_pps_apdo_max_current(pdo[i - 1])) | ||
1391 | return PDO_ERR_DUPE_PPS_APDO; | ||
1392 | break; | ||
1327 | default: | 1393 | default: |
1328 | tcpm_log_force(port, " Unknown pdo type"); | 1394 | tcpm_log_force(port, " Unknown pdo type"); |
1329 | } | 1395 | } |
@@ -1349,11 +1415,48 @@ static int tcpm_validate_caps(struct tcpm_port *port, const u32 *pdo, | |||
1349 | /* | 1415 | /* |
1350 | * PD (data, control) command handling functions | 1416 | * PD (data, control) command handling functions |
1351 | */ | 1417 | */ |
1418 | static inline enum tcpm_state ready_state(struct tcpm_port *port) | ||
1419 | { | ||
1420 | if (port->pwr_role == TYPEC_SOURCE) | ||
1421 | return SRC_READY; | ||
1422 | else | ||
1423 | return SNK_READY; | ||
1424 | } | ||
1425 | |||
1426 | static int tcpm_pd_send_control(struct tcpm_port *port, | ||
1427 | enum pd_ctrl_msg_type type); | ||
1428 | |||
1429 | static void tcpm_handle_alert(struct tcpm_port *port, const __le32 *payload, | ||
1430 | int cnt) | ||
1431 | { | ||
1432 | u32 p0 = le32_to_cpu(payload[0]); | ||
1433 | unsigned int type = usb_pd_ado_type(p0); | ||
1434 | |||
1435 | if (!type) { | ||
1436 | tcpm_log(port, "Alert message received with no type"); | ||
1437 | return; | ||
1438 | } | ||
1439 | |||
1440 | /* Just handling non-battery alerts for now */ | ||
1441 | if (!(type & USB_PD_ADO_TYPE_BATT_STATUS_CHANGE)) { | ||
1442 | switch (port->state) { | ||
1443 | case SRC_READY: | ||
1444 | case SNK_READY: | ||
1445 | tcpm_set_state(port, GET_STATUS_SEND, 0); | ||
1446 | break; | ||
1447 | default: | ||
1448 | tcpm_queue_message(port, PD_MSG_CTRL_WAIT); | ||
1449 | break; | ||
1450 | } | ||
1451 | } | ||
1452 | } | ||
1453 | |||
1352 | static void tcpm_pd_data_request(struct tcpm_port *port, | 1454 | static void tcpm_pd_data_request(struct tcpm_port *port, |
1353 | const struct pd_message *msg) | 1455 | const struct pd_message *msg) |
1354 | { | 1456 | { |
1355 | enum pd_data_msg_type type = pd_header_type_le(msg->header); | 1457 | enum pd_data_msg_type type = pd_header_type_le(msg->header); |
1356 | unsigned int cnt = pd_header_cnt_le(msg->header); | 1458 | unsigned int cnt = pd_header_cnt_le(msg->header); |
1459 | unsigned int rev = pd_header_rev_le(msg->header); | ||
1357 | unsigned int i; | 1460 | unsigned int i; |
1358 | 1461 | ||
1359 | switch (type) { | 1462 | switch (type) { |
@@ -1372,6 +1475,17 @@ static void tcpm_pd_data_request(struct tcpm_port *port, | |||
1372 | port->nr_source_caps); | 1475 | port->nr_source_caps); |
1373 | 1476 | ||
1374 | /* | 1477 | /* |
1478 | * Adjust revision in subsequent message headers, as required, | ||
1479 | * to comply with 6.2.1.1.5 of the USB PD 3.0 spec. We don't | ||
1480 | * support Rev 1.0 so just do nothing in that scenario. | ||
1481 | */ | ||
1482 | if (rev == PD_REV10) | ||
1483 | break; | ||
1484 | |||
1485 | if (rev < PD_MAX_REV) | ||
1486 | port->negotiated_rev = rev; | ||
1487 | |||
1488 | /* | ||
1375 | * This message may be received even if VBUS is not | 1489 | * This message may be received even if VBUS is not |
1376 | * present. This is quite unexpected; see USB PD | 1490 | * present. This is quite unexpected; see USB PD |
1377 | * specification, sections 8.3.3.6.3.1 and 8.3.3.6.3.2. | 1491 | * specification, sections 8.3.3.6.3.1 and 8.3.3.6.3.2. |
@@ -1392,6 +1506,20 @@ static void tcpm_pd_data_request(struct tcpm_port *port, | |||
1392 | tcpm_queue_message(port, PD_MSG_CTRL_REJECT); | 1506 | tcpm_queue_message(port, PD_MSG_CTRL_REJECT); |
1393 | break; | 1507 | break; |
1394 | } | 1508 | } |
1509 | |||
1510 | /* | ||
1511 | * Adjust revision in subsequent message headers, as required, | ||
1512 | * to comply with 6.2.1.1.5 of the USB PD 3.0 spec. We don't | ||
1513 | * support Rev 1.0 so just reject in that scenario. | ||
1514 | */ | ||
1515 | if (rev == PD_REV10) { | ||
1516 | tcpm_queue_message(port, PD_MSG_CTRL_REJECT); | ||
1517 | break; | ||
1518 | } | ||
1519 | |||
1520 | if (rev < PD_MAX_REV) | ||
1521 | port->negotiated_rev = rev; | ||
1522 | |||
1395 | port->sink_request = le32_to_cpu(msg->payload[0]); | 1523 | port->sink_request = le32_to_cpu(msg->payload[0]); |
1396 | tcpm_set_state(port, SRC_NEGOTIATE_CAPABILITIES, 0); | 1524 | tcpm_set_state(port, SRC_NEGOTIATE_CAPABILITIES, 0); |
1397 | break; | 1525 | break; |
@@ -1410,12 +1538,29 @@ static void tcpm_pd_data_request(struct tcpm_port *port, | |||
1410 | tcpm_set_state(port, BIST_RX, 0); | 1538 | tcpm_set_state(port, BIST_RX, 0); |
1411 | } | 1539 | } |
1412 | break; | 1540 | break; |
1541 | case PD_DATA_ALERT: | ||
1542 | tcpm_handle_alert(port, msg->payload, cnt); | ||
1543 | break; | ||
1544 | case PD_DATA_BATT_STATUS: | ||
1545 | case PD_DATA_GET_COUNTRY_INFO: | ||
1546 | /* Currently unsupported */ | ||
1547 | tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP); | ||
1548 | break; | ||
1413 | default: | 1549 | default: |
1414 | tcpm_log(port, "Unhandled data message type %#x", type); | 1550 | tcpm_log(port, "Unhandled data message type %#x", type); |
1415 | break; | 1551 | break; |
1416 | } | 1552 | } |
1417 | } | 1553 | } |
1418 | 1554 | ||
1555 | static void tcpm_pps_complete(struct tcpm_port *port, int result) | ||
1556 | { | ||
1557 | if (port->pps_pending) { | ||
1558 | port->pps_status = result; | ||
1559 | port->pps_pending = false; | ||
1560 | complete(&port->pps_complete); | ||
1561 | } | ||
1562 | } | ||
1563 | |||
1419 | static void tcpm_pd_ctrl_request(struct tcpm_port *port, | 1564 | static void tcpm_pd_ctrl_request(struct tcpm_port *port, |
1420 | const struct pd_message *msg) | 1565 | const struct pd_message *msg) |
1421 | { | 1566 | { |
@@ -1483,6 +1628,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, | |||
1483 | break; | 1628 | break; |
1484 | case PD_CTRL_REJECT: | 1629 | case PD_CTRL_REJECT: |
1485 | case PD_CTRL_WAIT: | 1630 | case PD_CTRL_WAIT: |
1631 | case PD_CTRL_NOT_SUPP: | ||
1486 | switch (port->state) { | 1632 | switch (port->state) { |
1487 | case SNK_NEGOTIATE_CAPABILITIES: | 1633 | case SNK_NEGOTIATE_CAPABILITIES: |
1488 | /* USB PD specification, Figure 8-43 */ | 1634 | /* USB PD specification, Figure 8-43 */ |
@@ -1492,6 +1638,14 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, | |||
1492 | next_state = SNK_WAIT_CAPABILITIES; | 1638 | next_state = SNK_WAIT_CAPABILITIES; |
1493 | tcpm_set_state(port, next_state, 0); | 1639 | tcpm_set_state(port, next_state, 0); |
1494 | break; | 1640 | break; |
1641 | case SNK_NEGOTIATE_PPS_CAPABILITIES: | ||
1642 | /* Revert data back from any requested PPS updates */ | ||
1643 | port->pps_data.out_volt = port->supply_voltage; | ||
1644 | port->pps_data.op_curr = port->current_limit; | ||
1645 | port->pps_status = (type == PD_CTRL_WAIT ? | ||
1646 | -EAGAIN : -EOPNOTSUPP); | ||
1647 | tcpm_set_state(port, SNK_READY, 0); | ||
1648 | break; | ||
1495 | case DR_SWAP_SEND: | 1649 | case DR_SWAP_SEND: |
1496 | port->swap_status = (type == PD_CTRL_WAIT ? | 1650 | port->swap_status = (type == PD_CTRL_WAIT ? |
1497 | -EAGAIN : -EOPNOTSUPP); | 1651 | -EAGAIN : -EOPNOTSUPP); |
@@ -1514,6 +1668,13 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, | |||
1514 | case PD_CTRL_ACCEPT: | 1668 | case PD_CTRL_ACCEPT: |
1515 | switch (port->state) { | 1669 | switch (port->state) { |
1516 | case SNK_NEGOTIATE_CAPABILITIES: | 1670 | case SNK_NEGOTIATE_CAPABILITIES: |
1671 | port->pps_data.active = false; | ||
1672 | tcpm_set_state(port, SNK_TRANSITION_SINK, 0); | ||
1673 | break; | ||
1674 | case SNK_NEGOTIATE_PPS_CAPABILITIES: | ||
1675 | port->pps_data.active = true; | ||
1676 | port->supply_voltage = port->pps_data.out_volt; | ||
1677 | port->current_limit = port->pps_data.op_curr; | ||
1517 | tcpm_set_state(port, SNK_TRANSITION_SINK, 0); | 1678 | tcpm_set_state(port, SNK_TRANSITION_SINK, 0); |
1518 | break; | 1679 | break; |
1519 | case SOFT_RESET_SEND: | 1680 | case SOFT_RESET_SEND: |
@@ -1587,12 +1748,75 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, | |||
1587 | break; | 1748 | break; |
1588 | } | 1749 | } |
1589 | break; | 1750 | break; |
1751 | case PD_CTRL_GET_SOURCE_CAP_EXT: | ||
1752 | case PD_CTRL_GET_STATUS: | ||
1753 | case PD_CTRL_FR_SWAP: | ||
1754 | case PD_CTRL_GET_PPS_STATUS: | ||
1755 | case PD_CTRL_GET_COUNTRY_CODES: | ||
1756 | /* Currently not supported */ | ||
1757 | tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP); | ||
1758 | break; | ||
1590 | default: | 1759 | default: |
1591 | tcpm_log(port, "Unhandled ctrl message type %#x", type); | 1760 | tcpm_log(port, "Unhandled ctrl message type %#x", type); |
1592 | break; | 1761 | break; |
1593 | } | 1762 | } |
1594 | } | 1763 | } |
1595 | 1764 | ||
1765 | static void tcpm_pd_ext_msg_request(struct tcpm_port *port, | ||
1766 | const struct pd_message *msg) | ||
1767 | { | ||
1768 | enum pd_ext_msg_type type = pd_header_type_le(msg->header); | ||
1769 | unsigned int data_size = pd_ext_header_data_size_le(msg->ext_msg.header); | ||
1770 | |||
1771 | if (!(msg->ext_msg.header & PD_EXT_HDR_CHUNKED)) { | ||
1772 | tcpm_log(port, "Unchunked extended messages unsupported"); | ||
1773 | return; | ||
1774 | } | ||
1775 | |||
1776 | if (data_size > PD_EXT_MAX_CHUNK_DATA) { | ||
1777 | tcpm_log(port, "Chunk handling not yet supported"); | ||
1778 | return; | ||
1779 | } | ||
1780 | |||
1781 | switch (type) { | ||
1782 | case PD_EXT_STATUS: | ||
1783 | /* | ||
1784 | * If PPS related events raised then get PPS status to clear | ||
1785 | * (see USB PD 3.0 Spec, 6.5.2.4) | ||
1786 | */ | ||
1787 | if (msg->ext_msg.data[USB_PD_EXT_SDB_EVENT_FLAGS] & | ||
1788 | USB_PD_EXT_SDB_PPS_EVENTS) | ||
1789 | tcpm_set_state(port, GET_PPS_STATUS_SEND, 0); | ||
1790 | else | ||
1791 | tcpm_set_state(port, ready_state(port), 0); | ||
1792 | break; | ||
1793 | case PD_EXT_PPS_STATUS: | ||
1794 | /* | ||
1795 | * For now the PPS status message is used to clear events | ||
1796 | * and nothing more. | ||
1797 | */ | ||
1798 | tcpm_set_state(port, ready_state(port), 0); | ||
1799 | break; | ||
1800 | case PD_EXT_SOURCE_CAP_EXT: | ||
1801 | case PD_EXT_GET_BATT_CAP: | ||
1802 | case PD_EXT_GET_BATT_STATUS: | ||
1803 | case PD_EXT_BATT_CAP: | ||
1804 | case PD_EXT_GET_MANUFACTURER_INFO: | ||
1805 | case PD_EXT_MANUFACTURER_INFO: | ||
1806 | case PD_EXT_SECURITY_REQUEST: | ||
1807 | case PD_EXT_SECURITY_RESPONSE: | ||
1808 | case PD_EXT_FW_UPDATE_REQUEST: | ||
1809 | case PD_EXT_FW_UPDATE_RESPONSE: | ||
1810 | case PD_EXT_COUNTRY_INFO: | ||
1811 | case PD_EXT_COUNTRY_CODES: | ||
1812 | tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP); | ||
1813 | break; | ||
1814 | default: | ||
1815 | tcpm_log(port, "Unhandled extended message type %#x", type); | ||
1816 | break; | ||
1817 | } | ||
1818 | } | ||
1819 | |||
1596 | static void tcpm_pd_rx_handler(struct work_struct *work) | 1820 | static void tcpm_pd_rx_handler(struct work_struct *work) |
1597 | { | 1821 | { |
1598 | struct pd_rx_event *event = container_of(work, | 1822 | struct pd_rx_event *event = container_of(work, |
@@ -1633,7 +1857,9 @@ static void tcpm_pd_rx_handler(struct work_struct *work) | |||
1633 | "Data role mismatch, initiating error recovery"); | 1857 | "Data role mismatch, initiating error recovery"); |
1634 | tcpm_set_state(port, ERROR_RECOVERY, 0); | 1858 | tcpm_set_state(port, ERROR_RECOVERY, 0); |
1635 | } else { | 1859 | } else { |
1636 | if (cnt) | 1860 | if (msg->header & PD_HEADER_EXT_HDR) |
1861 | tcpm_pd_ext_msg_request(port, msg); | ||
1862 | else if (cnt) | ||
1637 | tcpm_pd_data_request(port, msg); | 1863 | tcpm_pd_data_request(port, msg); |
1638 | else | 1864 | else |
1639 | tcpm_pd_ctrl_request(port, msg); | 1865 | tcpm_pd_ctrl_request(port, msg); |
@@ -1668,6 +1894,7 @@ static int tcpm_pd_send_control(struct tcpm_port *port, | |||
1668 | memset(&msg, 0, sizeof(msg)); | 1894 | memset(&msg, 0, sizeof(msg)); |
1669 | msg.header = PD_HEADER_LE(type, port->pwr_role, | 1895 | msg.header = PD_HEADER_LE(type, port->pwr_role, |
1670 | port->data_role, | 1896 | port->data_role, |
1897 | port->negotiated_rev, | ||
1671 | port->message_id, 0); | 1898 | port->message_id, 0); |
1672 | 1899 | ||
1673 | return tcpm_pd_transmit(port, TCPC_TX_SOP, &msg); | 1900 | return tcpm_pd_transmit(port, TCPC_TX_SOP, &msg); |
@@ -1693,6 +1920,9 @@ static bool tcpm_send_queued_message(struct tcpm_port *port) | |||
1693 | case PD_MSG_CTRL_REJECT: | 1920 | case PD_MSG_CTRL_REJECT: |
1694 | tcpm_pd_send_control(port, PD_CTRL_REJECT); | 1921 | tcpm_pd_send_control(port, PD_CTRL_REJECT); |
1695 | break; | 1922 | break; |
1923 | case PD_MSG_CTRL_NOT_SUPP: | ||
1924 | tcpm_pd_send_control(port, PD_CTRL_NOT_SUPP); | ||
1925 | break; | ||
1696 | case PD_MSG_DATA_SINK_CAP: | 1926 | case PD_MSG_DATA_SINK_CAP: |
1697 | tcpm_pd_send_sink_caps(port); | 1927 | tcpm_pd_send_sink_caps(port); |
1698 | break; | 1928 | break; |
@@ -1772,84 +2002,254 @@ static int tcpm_pd_check_request(struct tcpm_port *port) | |||
1772 | return 0; | 2002 | return 0; |
1773 | } | 2003 | } |
1774 | 2004 | ||
1775 | static int tcpm_pd_select_pdo(struct tcpm_port *port) | 2005 | #define min_power(x, y) min(pdo_max_power(x), pdo_max_power(y)) |
2006 | #define min_current(x, y) min(pdo_max_current(x), pdo_max_current(y)) | ||
2007 | |||
2008 | static int tcpm_pd_select_pdo(struct tcpm_port *port, int *sink_pdo, | ||
2009 | int *src_pdo) | ||
1776 | { | 2010 | { |
1777 | unsigned int i, max_mw = 0, max_mv = 0; | 2011 | unsigned int i, j, max_src_mv = 0, min_src_mv = 0, max_mw = 0, |
2012 | max_mv = 0, src_mw = 0, src_ma = 0, max_snk_mv = 0, | ||
2013 | min_snk_mv = 0; | ||
1778 | int ret = -EINVAL; | 2014 | int ret = -EINVAL; |
1779 | 2015 | ||
2016 | port->pps_data.supported = false; | ||
2017 | port->usb_type = POWER_SUPPLY_USB_TYPE_PD; | ||
2018 | |||
1780 | /* | 2019 | /* |
1781 | * Select the source PDO providing the most power while staying within | 2020 | * Select the source PDO providing the most power which has a |
1782 | * the board's voltage limits. Prefer PDO providing exp | 2021 | * matchig sink cap. |
1783 | */ | 2022 | */ |
1784 | for (i = 0; i < port->nr_source_caps; i++) { | 2023 | for (i = 0; i < port->nr_source_caps; i++) { |
1785 | u32 pdo = port->source_caps[i]; | 2024 | u32 pdo = port->source_caps[i]; |
1786 | enum pd_pdo_type type = pdo_type(pdo); | 2025 | enum pd_pdo_type type = pdo_type(pdo); |
1787 | unsigned int mv, ma, mw; | ||
1788 | 2026 | ||
1789 | if (type == PDO_TYPE_FIXED) | 2027 | switch (type) { |
1790 | mv = pdo_fixed_voltage(pdo); | 2028 | case PDO_TYPE_FIXED: |
1791 | else | 2029 | max_src_mv = pdo_fixed_voltage(pdo); |
1792 | mv = pdo_min_voltage(pdo); | 2030 | min_src_mv = max_src_mv; |
2031 | break; | ||
2032 | case PDO_TYPE_BATT: | ||
2033 | case PDO_TYPE_VAR: | ||
2034 | max_src_mv = pdo_max_voltage(pdo); | ||
2035 | min_src_mv = pdo_min_voltage(pdo); | ||
2036 | break; | ||
2037 | case PDO_TYPE_APDO: | ||
2038 | if (pdo_apdo_type(pdo) == APDO_TYPE_PPS) { | ||
2039 | port->pps_data.supported = true; | ||
2040 | port->usb_type = | ||
2041 | POWER_SUPPLY_USB_TYPE_PD_PPS; | ||
2042 | } | ||
2043 | continue; | ||
2044 | default: | ||
2045 | tcpm_log(port, "Invalid source PDO type, ignoring"); | ||
2046 | continue; | ||
2047 | } | ||
1793 | 2048 | ||
1794 | if (type == PDO_TYPE_BATT) { | 2049 | switch (type) { |
1795 | mw = pdo_max_power(pdo); | 2050 | case PDO_TYPE_FIXED: |
1796 | } else { | 2051 | case PDO_TYPE_VAR: |
1797 | ma = min(pdo_max_current(pdo), | 2052 | src_ma = pdo_max_current(pdo); |
1798 | port->max_snk_ma); | 2053 | src_mw = src_ma * min_src_mv / 1000; |
1799 | mw = ma * mv / 1000; | 2054 | break; |
2055 | case PDO_TYPE_BATT: | ||
2056 | src_mw = pdo_max_power(pdo); | ||
2057 | break; | ||
2058 | case PDO_TYPE_APDO: | ||
2059 | continue; | ||
2060 | default: | ||
2061 | tcpm_log(port, "Invalid source PDO type, ignoring"); | ||
2062 | continue; | ||
1800 | } | 2063 | } |
1801 | 2064 | ||
1802 | /* Perfer higher voltages if available */ | 2065 | for (j = 0; j < port->nr_snk_pdo; j++) { |
1803 | if ((mw > max_mw || (mw == max_mw && mv > max_mv)) && | 2066 | pdo = port->snk_pdo[j]; |
1804 | mv <= port->max_snk_mv) { | 2067 | |
1805 | ret = i; | 2068 | switch (pdo_type(pdo)) { |
1806 | max_mw = mw; | 2069 | case PDO_TYPE_FIXED: |
1807 | max_mv = mv; | 2070 | max_snk_mv = pdo_fixed_voltage(pdo); |
2071 | min_snk_mv = max_snk_mv; | ||
2072 | break; | ||
2073 | case PDO_TYPE_BATT: | ||
2074 | case PDO_TYPE_VAR: | ||
2075 | max_snk_mv = pdo_max_voltage(pdo); | ||
2076 | min_snk_mv = pdo_min_voltage(pdo); | ||
2077 | break; | ||
2078 | case PDO_TYPE_APDO: | ||
2079 | continue; | ||
2080 | default: | ||
2081 | tcpm_log(port, "Invalid sink PDO type, ignoring"); | ||
2082 | continue; | ||
2083 | } | ||
2084 | |||
2085 | if (max_src_mv <= max_snk_mv && | ||
2086 | min_src_mv >= min_snk_mv) { | ||
2087 | /* Prefer higher voltages if available */ | ||
2088 | if ((src_mw == max_mw && min_src_mv > max_mv) || | ||
2089 | src_mw > max_mw) { | ||
2090 | *src_pdo = i; | ||
2091 | *sink_pdo = j; | ||
2092 | max_mw = src_mw; | ||
2093 | max_mv = min_src_mv; | ||
2094 | ret = 0; | ||
2095 | } | ||
2096 | } | ||
1808 | } | 2097 | } |
1809 | } | 2098 | } |
1810 | 2099 | ||
1811 | return ret; | 2100 | return ret; |
1812 | } | 2101 | } |
1813 | 2102 | ||
2103 | #define min_pps_apdo_current(x, y) \ | ||
2104 | min(pdo_pps_apdo_max_current(x), pdo_pps_apdo_max_current(y)) | ||
2105 | |||
2106 | static unsigned int tcpm_pd_select_pps_apdo(struct tcpm_port *port) | ||
2107 | { | ||
2108 | unsigned int i, j, max_mw = 0, max_mv = 0; | ||
2109 | unsigned int min_src_mv, max_src_mv, src_ma, src_mw; | ||
2110 | unsigned int min_snk_mv, max_snk_mv, snk_ma; | ||
2111 | u32 pdo; | ||
2112 | unsigned int src_pdo = 0, snk_pdo = 0; | ||
2113 | |||
2114 | /* | ||
2115 | * Select the source PPS APDO providing the most power while staying | ||
2116 | * within the board's limits. We skip the first PDO as this is always | ||
2117 | * 5V 3A. | ||
2118 | */ | ||
2119 | for (i = 1; i < port->nr_source_caps; ++i) { | ||
2120 | pdo = port->source_caps[i]; | ||
2121 | |||
2122 | switch (pdo_type(pdo)) { | ||
2123 | case PDO_TYPE_APDO: | ||
2124 | if (pdo_apdo_type(pdo) != APDO_TYPE_PPS) { | ||
2125 | tcpm_log(port, "Not PPS APDO (source), ignoring"); | ||
2126 | continue; | ||
2127 | } | ||
2128 | |||
2129 | min_src_mv = pdo_pps_apdo_min_voltage(pdo); | ||
2130 | max_src_mv = pdo_pps_apdo_max_voltage(pdo); | ||
2131 | src_ma = pdo_pps_apdo_max_current(pdo); | ||
2132 | src_mw = (src_ma * max_src_mv) / 1000; | ||
2133 | |||
2134 | /* | ||
2135 | * Now search through the sink PDOs to find a matching | ||
2136 | * PPS APDO. Again skip the first sink PDO as this will | ||
2137 | * always be 5V 3A. | ||
2138 | */ | ||
2139 | for (j = i; j < port->nr_snk_pdo; j++) { | ||
2140 | pdo = port->snk_pdo[j]; | ||
2141 | |||
2142 | switch (pdo_type(pdo)) { | ||
2143 | case PDO_TYPE_APDO: | ||
2144 | if (pdo_apdo_type(pdo) != APDO_TYPE_PPS) { | ||
2145 | tcpm_log(port, | ||
2146 | "Not PPS APDO (sink), ignoring"); | ||
2147 | continue; | ||
2148 | } | ||
2149 | |||
2150 | min_snk_mv = | ||
2151 | pdo_pps_apdo_min_voltage(pdo); | ||
2152 | max_snk_mv = | ||
2153 | pdo_pps_apdo_max_voltage(pdo); | ||
2154 | snk_ma = | ||
2155 | pdo_pps_apdo_max_current(pdo); | ||
2156 | break; | ||
2157 | default: | ||
2158 | tcpm_log(port, | ||
2159 | "Not APDO type (sink), ignoring"); | ||
2160 | continue; | ||
2161 | } | ||
2162 | |||
2163 | if (max_src_mv <= max_snk_mv && | ||
2164 | min_src_mv >= min_snk_mv) { | ||
2165 | /* Prefer higher voltages if available */ | ||
2166 | if ((src_mw == max_mw && | ||
2167 | min_src_mv > max_mv) || | ||
2168 | src_mw > max_mw) { | ||
2169 | src_pdo = i; | ||
2170 | snk_pdo = j; | ||
2171 | max_mw = src_mw; | ||
2172 | max_mv = max_src_mv; | ||
2173 | } | ||
2174 | } | ||
2175 | } | ||
2176 | |||
2177 | break; | ||
2178 | default: | ||
2179 | tcpm_log(port, "Not APDO type (source), ignoring"); | ||
2180 | continue; | ||
2181 | } | ||
2182 | } | ||
2183 | |||
2184 | if (src_pdo) { | ||
2185 | pdo = port->source_caps[src_pdo]; | ||
2186 | |||
2187 | port->pps_data.min_volt = pdo_pps_apdo_min_voltage(pdo); | ||
2188 | port->pps_data.max_volt = pdo_pps_apdo_max_voltage(pdo); | ||
2189 | port->pps_data.max_curr = | ||
2190 | min_pps_apdo_current(pdo, port->snk_pdo[snk_pdo]); | ||
2191 | port->pps_data.out_volt = | ||
2192 | min(pdo_pps_apdo_max_voltage(pdo), port->pps_data.out_volt); | ||
2193 | port->pps_data.op_curr = | ||
2194 | min(port->pps_data.max_curr, port->pps_data.op_curr); | ||
2195 | } | ||
2196 | |||
2197 | return src_pdo; | ||
2198 | } | ||
2199 | |||
1814 | static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo) | 2200 | static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo) |
1815 | { | 2201 | { |
1816 | unsigned int mv, ma, mw, flags; | 2202 | unsigned int mv, ma, mw, flags; |
1817 | unsigned int max_ma, max_mw; | 2203 | unsigned int max_ma, max_mw; |
1818 | enum pd_pdo_type type; | 2204 | enum pd_pdo_type type; |
1819 | int index; | 2205 | u32 pdo, matching_snk_pdo; |
1820 | u32 pdo; | 2206 | int src_pdo_index = 0; |
2207 | int snk_pdo_index = 0; | ||
2208 | int ret; | ||
1821 | 2209 | ||
1822 | index = tcpm_pd_select_pdo(port); | 2210 | ret = tcpm_pd_select_pdo(port, &snk_pdo_index, &src_pdo_index); |
1823 | if (index < 0) | 2211 | if (ret < 0) |
1824 | return -EINVAL; | 2212 | return ret; |
1825 | pdo = port->source_caps[index]; | 2213 | |
2214 | pdo = port->source_caps[src_pdo_index]; | ||
2215 | matching_snk_pdo = port->snk_pdo[snk_pdo_index]; | ||
1826 | type = pdo_type(pdo); | 2216 | type = pdo_type(pdo); |
1827 | 2217 | ||
1828 | if (type == PDO_TYPE_FIXED) | 2218 | switch (type) { |
2219 | case PDO_TYPE_FIXED: | ||
1829 | mv = pdo_fixed_voltage(pdo); | 2220 | mv = pdo_fixed_voltage(pdo); |
1830 | else | 2221 | break; |
2222 | case PDO_TYPE_BATT: | ||
2223 | case PDO_TYPE_VAR: | ||
1831 | mv = pdo_min_voltage(pdo); | 2224 | mv = pdo_min_voltage(pdo); |
2225 | break; | ||
2226 | default: | ||
2227 | tcpm_log(port, "Invalid PDO selected!"); | ||
2228 | return -EINVAL; | ||
2229 | } | ||
1832 | 2230 | ||
1833 | /* Select maximum available current within the board's power limit */ | 2231 | /* Select maximum available current within the sink pdo's limit */ |
1834 | if (type == PDO_TYPE_BATT) { | 2232 | if (type == PDO_TYPE_BATT) { |
1835 | mw = pdo_max_power(pdo); | 2233 | mw = min_power(pdo, matching_snk_pdo); |
1836 | ma = 1000 * min(mw, port->max_snk_mw) / mv; | 2234 | ma = 1000 * mw / mv; |
1837 | } else { | 2235 | } else { |
1838 | ma = min(pdo_max_current(pdo), | 2236 | ma = min_current(pdo, matching_snk_pdo); |
1839 | 1000 * port->max_snk_mw / mv); | 2237 | mw = ma * mv / 1000; |
1840 | } | 2238 | } |
1841 | ma = min(ma, port->max_snk_ma); | ||
1842 | 2239 | ||
1843 | flags = RDO_USB_COMM | RDO_NO_SUSPEND; | 2240 | flags = RDO_USB_COMM | RDO_NO_SUSPEND; |
1844 | 2241 | ||
1845 | /* Set mismatch bit if offered power is less than operating power */ | 2242 | /* Set mismatch bit if offered power is less than operating power */ |
1846 | mw = ma * mv / 1000; | ||
1847 | max_ma = ma; | 2243 | max_ma = ma; |
1848 | max_mw = mw; | 2244 | max_mw = mw; |
1849 | if (mw < port->operating_snk_mw) { | 2245 | if (mw < port->operating_snk_mw) { |
1850 | flags |= RDO_CAP_MISMATCH; | 2246 | flags |= RDO_CAP_MISMATCH; |
1851 | max_mw = port->operating_snk_mw; | 2247 | if (type == PDO_TYPE_BATT && |
1852 | max_ma = max_mw * 1000 / mv; | 2248 | (pdo_max_power(matching_snk_pdo) > pdo_max_power(pdo))) |
2249 | max_mw = pdo_max_power(matching_snk_pdo); | ||
2250 | else if (pdo_max_current(matching_snk_pdo) > | ||
2251 | pdo_max_current(pdo)) | ||
2252 | max_ma = pdo_max_current(matching_snk_pdo); | ||
1853 | } | 2253 | } |
1854 | 2254 | ||
1855 | tcpm_log(port, "cc=%d cc1=%d cc2=%d vbus=%d vconn=%s polarity=%d", | 2255 | tcpm_log(port, "cc=%d cc1=%d cc2=%d vbus=%d vconn=%s polarity=%d", |
@@ -1858,16 +2258,16 @@ static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo) | |||
1858 | port->polarity); | 2258 | port->polarity); |
1859 | 2259 | ||
1860 | if (type == PDO_TYPE_BATT) { | 2260 | if (type == PDO_TYPE_BATT) { |
1861 | *rdo = RDO_BATT(index + 1, mw, max_mw, flags); | 2261 | *rdo = RDO_BATT(src_pdo_index + 1, mw, max_mw, flags); |
1862 | 2262 | ||
1863 | tcpm_log(port, "Requesting PDO %d: %u mV, %u mW%s", | 2263 | tcpm_log(port, "Requesting PDO %d: %u mV, %u mW%s", |
1864 | index, mv, mw, | 2264 | src_pdo_index, mv, mw, |
1865 | flags & RDO_CAP_MISMATCH ? " [mismatch]" : ""); | 2265 | flags & RDO_CAP_MISMATCH ? " [mismatch]" : ""); |
1866 | } else { | 2266 | } else { |
1867 | *rdo = RDO_FIXED(index + 1, ma, max_ma, flags); | 2267 | *rdo = RDO_FIXED(src_pdo_index + 1, ma, max_ma, flags); |
1868 | 2268 | ||
1869 | tcpm_log(port, "Requesting PDO %d: %u mV, %u mA%s", | 2269 | tcpm_log(port, "Requesting PDO %d: %u mV, %u mA%s", |
1870 | index, mv, ma, | 2270 | src_pdo_index, mv, ma, |
1871 | flags & RDO_CAP_MISMATCH ? " [mismatch]" : ""); | 2271 | flags & RDO_CAP_MISMATCH ? " [mismatch]" : ""); |
1872 | } | 2272 | } |
1873 | 2273 | ||
@@ -1891,6 +2291,105 @@ static int tcpm_pd_send_request(struct tcpm_port *port) | |||
1891 | msg.header = PD_HEADER_LE(PD_DATA_REQUEST, | 2291 | msg.header = PD_HEADER_LE(PD_DATA_REQUEST, |
1892 | port->pwr_role, | 2292 | port->pwr_role, |
1893 | port->data_role, | 2293 | port->data_role, |
2294 | port->negotiated_rev, | ||
2295 | port->message_id, 1); | ||
2296 | msg.payload[0] = cpu_to_le32(rdo); | ||
2297 | |||
2298 | return tcpm_pd_transmit(port, TCPC_TX_SOP, &msg); | ||
2299 | } | ||
2300 | |||
2301 | static int tcpm_pd_build_pps_request(struct tcpm_port *port, u32 *rdo) | ||
2302 | { | ||
2303 | unsigned int out_mv, op_ma, op_mw, min_mv, max_mv, max_ma, flags; | ||
2304 | enum pd_pdo_type type; | ||
2305 | unsigned int src_pdo_index; | ||
2306 | u32 pdo; | ||
2307 | |||
2308 | src_pdo_index = tcpm_pd_select_pps_apdo(port); | ||
2309 | if (!src_pdo_index) | ||
2310 | return -EOPNOTSUPP; | ||
2311 | |||
2312 | pdo = port->source_caps[src_pdo_index]; | ||
2313 | type = pdo_type(pdo); | ||
2314 | |||
2315 | switch (type) { | ||
2316 | case PDO_TYPE_APDO: | ||
2317 | if (pdo_apdo_type(pdo) != APDO_TYPE_PPS) { | ||
2318 | tcpm_log(port, "Invalid APDO selected!"); | ||
2319 | return -EINVAL; | ||
2320 | } | ||
2321 | min_mv = port->pps_data.min_volt; | ||
2322 | max_mv = port->pps_data.max_volt; | ||
2323 | max_ma = port->pps_data.max_curr; | ||
2324 | out_mv = port->pps_data.out_volt; | ||
2325 | op_ma = port->pps_data.op_curr; | ||
2326 | break; | ||
2327 | default: | ||
2328 | tcpm_log(port, "Invalid PDO selected!"); | ||
2329 | return -EINVAL; | ||
2330 | } | ||
2331 | |||
2332 | flags = RDO_USB_COMM | RDO_NO_SUSPEND; | ||
2333 | |||
2334 | op_mw = (op_ma * out_mv) / 1000; | ||
2335 | if (op_mw < port->operating_snk_mw) { | ||
2336 | /* | ||
2337 | * Try raising current to meet power needs. If that's not enough | ||
2338 | * then try upping the voltage. If that's still not enough | ||
2339 | * then we've obviously chosen a PPS APDO which really isn't | ||
2340 | * suitable so abandon ship. | ||
2341 | */ | ||
2342 | op_ma = (port->operating_snk_mw * 1000) / out_mv; | ||
2343 | if ((port->operating_snk_mw * 1000) % out_mv) | ||
2344 | ++op_ma; | ||
2345 | op_ma += RDO_PROG_CURR_MA_STEP - (op_ma % RDO_PROG_CURR_MA_STEP); | ||
2346 | |||
2347 | if (op_ma > max_ma) { | ||
2348 | op_ma = max_ma; | ||
2349 | out_mv = (port->operating_snk_mw * 1000) / op_ma; | ||
2350 | if ((port->operating_snk_mw * 1000) % op_ma) | ||
2351 | ++out_mv; | ||
2352 | out_mv += RDO_PROG_VOLT_MV_STEP - | ||
2353 | (out_mv % RDO_PROG_VOLT_MV_STEP); | ||
2354 | |||
2355 | if (out_mv > max_mv) { | ||
2356 | tcpm_log(port, "Invalid PPS APDO selected!"); | ||
2357 | return -EINVAL; | ||
2358 | } | ||
2359 | } | ||
2360 | } | ||
2361 | |||
2362 | tcpm_log(port, "cc=%d cc1=%d cc2=%d vbus=%d vconn=%s polarity=%d", | ||
2363 | port->cc_req, port->cc1, port->cc2, port->vbus_source, | ||
2364 | port->vconn_role == TYPEC_SOURCE ? "source" : "sink", | ||
2365 | port->polarity); | ||
2366 | |||
2367 | *rdo = RDO_PROG(src_pdo_index + 1, out_mv, op_ma, flags); | ||
2368 | |||
2369 | tcpm_log(port, "Requesting APDO %d: %u mV, %u mA", | ||
2370 | src_pdo_index, out_mv, op_ma); | ||
2371 | |||
2372 | port->pps_data.op_curr = op_ma; | ||
2373 | port->pps_data.out_volt = out_mv; | ||
2374 | |||
2375 | return 0; | ||
2376 | } | ||
2377 | |||
2378 | static int tcpm_pd_send_pps_request(struct tcpm_port *port) | ||
2379 | { | ||
2380 | struct pd_message msg; | ||
2381 | int ret; | ||
2382 | u32 rdo; | ||
2383 | |||
2384 | ret = tcpm_pd_build_pps_request(port, &rdo); | ||
2385 | if (ret < 0) | ||
2386 | return ret; | ||
2387 | |||
2388 | memset(&msg, 0, sizeof(msg)); | ||
2389 | msg.header = PD_HEADER_LE(PD_DATA_REQUEST, | ||
2390 | port->pwr_role, | ||
2391 | port->data_role, | ||
2392 | port->negotiated_rev, | ||
1894 | port->message_id, 1); | 2393 | port->message_id, 1); |
1895 | msg.payload[0] = cpu_to_le32(rdo); | 2394 | msg.payload[0] = cpu_to_le32(rdo); |
1896 | 2395 | ||
@@ -2077,6 +2576,7 @@ static void tcpm_reset_port(struct tcpm_port *port) | |||
2077 | tcpm_typec_disconnect(port); | 2576 | tcpm_typec_disconnect(port); |
2078 | port->attached = false; | 2577 | port->attached = false; |
2079 | port->pd_capable = false; | 2578 | port->pd_capable = false; |
2579 | port->pps_data.supported = false; | ||
2080 | 2580 | ||
2081 | /* | 2581 | /* |
2082 | * First Rx ID should be 0; set this to a sentinel of -1 so that | 2582 | * First Rx ID should be 0; set this to a sentinel of -1 so that |
@@ -2094,6 +2594,11 @@ static void tcpm_reset_port(struct tcpm_port *port) | |||
2094 | tcpm_set_attached_state(port, false); | 2594 | tcpm_set_attached_state(port, false); |
2095 | port->try_src_count = 0; | 2595 | port->try_src_count = 0; |
2096 | port->try_snk_count = 0; | 2596 | port->try_snk_count = 0; |
2597 | port->supply_voltage = 0; | ||
2598 | port->current_limit = 0; | ||
2599 | port->usb_type = POWER_SUPPLY_USB_TYPE_C; | ||
2600 | |||
2601 | power_supply_changed(port->psy); | ||
2097 | } | 2602 | } |
2098 | 2603 | ||
2099 | static void tcpm_detach(struct tcpm_port *port) | 2604 | static void tcpm_detach(struct tcpm_port *port) |
@@ -2181,14 +2686,6 @@ static inline enum tcpm_state hard_reset_state(struct tcpm_port *port) | |||
2181 | return SNK_UNATTACHED; | 2686 | return SNK_UNATTACHED; |
2182 | } | 2687 | } |
2183 | 2688 | ||
2184 | static inline enum tcpm_state ready_state(struct tcpm_port *port) | ||
2185 | { | ||
2186 | if (port->pwr_role == TYPEC_SOURCE) | ||
2187 | return SRC_READY; | ||
2188 | else | ||
2189 | return SNK_READY; | ||
2190 | } | ||
2191 | |||
2192 | static inline enum tcpm_state unattached_state(struct tcpm_port *port) | 2689 | static inline enum tcpm_state unattached_state(struct tcpm_port *port) |
2193 | { | 2690 | { |
2194 | if (port->port_type == TYPEC_PORT_DRP) { | 2691 | if (port->port_type == TYPEC_PORT_DRP) { |
@@ -2338,6 +2835,7 @@ static void run_state_machine(struct tcpm_port *port) | |||
2338 | typec_set_pwr_opmode(port->typec_port, opmode); | 2835 | typec_set_pwr_opmode(port->typec_port, opmode); |
2339 | port->pwr_opmode = TYPEC_PWR_MODE_USB; | 2836 | port->pwr_opmode = TYPEC_PWR_MODE_USB; |
2340 | port->caps_count = 0; | 2837 | port->caps_count = 0; |
2838 | port->negotiated_rev = PD_MAX_REV; | ||
2341 | port->message_id = 0; | 2839 | port->message_id = 0; |
2342 | port->rx_msgid = -1; | 2840 | port->rx_msgid = -1; |
2343 | port->explicit_contract = false; | 2841 | port->explicit_contract = false; |
@@ -2398,6 +2896,7 @@ static void run_state_machine(struct tcpm_port *port) | |||
2398 | 2896 | ||
2399 | tcpm_swap_complete(port, 0); | 2897 | tcpm_swap_complete(port, 0); |
2400 | tcpm_typec_connect(port); | 2898 | tcpm_typec_connect(port); |
2899 | |||
2401 | tcpm_check_send_discover(port); | 2900 | tcpm_check_send_discover(port); |
2402 | /* | 2901 | /* |
2403 | * 6.3.5 | 2902 | * 6.3.5 |
@@ -2421,6 +2920,7 @@ static void run_state_machine(struct tcpm_port *port) | |||
2421 | case SNK_UNATTACHED: | 2920 | case SNK_UNATTACHED: |
2422 | if (!port->non_pd_role_swap) | 2921 | if (!port->non_pd_role_swap) |
2423 | tcpm_swap_complete(port, -ENOTCONN); | 2922 | tcpm_swap_complete(port, -ENOTCONN); |
2923 | tcpm_pps_complete(port, -ENOTCONN); | ||
2424 | tcpm_snk_detach(port); | 2924 | tcpm_snk_detach(port); |
2425 | if (tcpm_start_drp_toggling(port)) { | 2925 | if (tcpm_start_drp_toggling(port)) { |
2426 | tcpm_set_state(port, DRP_TOGGLING, 0); | 2926 | tcpm_set_state(port, DRP_TOGGLING, 0); |
@@ -2510,6 +3010,7 @@ static void run_state_machine(struct tcpm_port *port) | |||
2510 | port->cc2 : port->cc1); | 3010 | port->cc2 : port->cc1); |
2511 | typec_set_pwr_opmode(port->typec_port, opmode); | 3011 | typec_set_pwr_opmode(port->typec_port, opmode); |
2512 | port->pwr_opmode = TYPEC_PWR_MODE_USB; | 3012 | port->pwr_opmode = TYPEC_PWR_MODE_USB; |
3013 | port->negotiated_rev = PD_MAX_REV; | ||
2513 | port->message_id = 0; | 3014 | port->message_id = 0; |
2514 | port->rx_msgid = -1; | 3015 | port->rx_msgid = -1; |
2515 | port->explicit_contract = false; | 3016 | port->explicit_contract = false; |
@@ -2580,6 +3081,24 @@ static void run_state_machine(struct tcpm_port *port) | |||
2580 | PD_T_SENDER_RESPONSE); | 3081 | PD_T_SENDER_RESPONSE); |
2581 | } | 3082 | } |
2582 | break; | 3083 | break; |
3084 | case SNK_NEGOTIATE_PPS_CAPABILITIES: | ||
3085 | ret = tcpm_pd_send_pps_request(port); | ||
3086 | if (ret < 0) { | ||
3087 | port->pps_status = ret; | ||
3088 | /* | ||
3089 | * If this was called due to updates to sink | ||
3090 | * capabilities, and pps is no longer valid, we should | ||
3091 | * safely fall back to a standard PDO. | ||
3092 | */ | ||
3093 | if (port->update_sink_caps) | ||
3094 | tcpm_set_state(port, SNK_NEGOTIATE_CAPABILITIES, 0); | ||
3095 | else | ||
3096 | tcpm_set_state(port, SNK_READY, 0); | ||
3097 | } else { | ||
3098 | tcpm_set_state_cond(port, hard_reset_state(port), | ||
3099 | PD_T_SENDER_RESPONSE); | ||
3100 | } | ||
3101 | break; | ||
2583 | case SNK_TRANSITION_SINK: | 3102 | case SNK_TRANSITION_SINK: |
2584 | case SNK_TRANSITION_SINK_VBUS: | 3103 | case SNK_TRANSITION_SINK_VBUS: |
2585 | tcpm_set_state(port, hard_reset_state(port), | 3104 | tcpm_set_state(port, hard_reset_state(port), |
@@ -2587,6 +3106,7 @@ static void run_state_machine(struct tcpm_port *port) | |||
2587 | break; | 3106 | break; |
2588 | case SNK_READY: | 3107 | case SNK_READY: |
2589 | port->try_snk_count = 0; | 3108 | port->try_snk_count = 0; |
3109 | port->update_sink_caps = false; | ||
2590 | if (port->explicit_contract) { | 3110 | if (port->explicit_contract) { |
2591 | typec_set_pwr_opmode(port->typec_port, | 3111 | typec_set_pwr_opmode(port->typec_port, |
2592 | TYPEC_PWR_MODE_PD); | 3112 | TYPEC_PWR_MODE_PD); |
@@ -2596,6 +3116,10 @@ static void run_state_machine(struct tcpm_port *port) | |||
2596 | tcpm_swap_complete(port, 0); | 3116 | tcpm_swap_complete(port, 0); |
2597 | tcpm_typec_connect(port); | 3117 | tcpm_typec_connect(port); |
2598 | tcpm_check_send_discover(port); | 3118 | tcpm_check_send_discover(port); |
3119 | tcpm_pps_complete(port, port->pps_status); | ||
3120 | |||
3121 | power_supply_changed(port->psy); | ||
3122 | |||
2599 | break; | 3123 | break; |
2600 | 3124 | ||
2601 | /* Accessory states */ | 3125 | /* Accessory states */ |
@@ -2642,6 +3166,7 @@ static void run_state_machine(struct tcpm_port *port) | |||
2642 | tcpm_set_state(port, SRC_UNATTACHED, PD_T_PS_SOURCE_ON); | 3166 | tcpm_set_state(port, SRC_UNATTACHED, PD_T_PS_SOURCE_ON); |
2643 | break; | 3167 | break; |
2644 | case SNK_HARD_RESET_SINK_OFF: | 3168 | case SNK_HARD_RESET_SINK_OFF: |
3169 | memset(&port->pps_data, 0, sizeof(port->pps_data)); | ||
2645 | tcpm_set_vconn(port, false); | 3170 | tcpm_set_vconn(port, false); |
2646 | tcpm_set_charge(port, false); | 3171 | tcpm_set_charge(port, false); |
2647 | tcpm_set_roles(port, false, TYPEC_SINK, TYPEC_DEVICE); | 3172 | tcpm_set_roles(port, false, TYPEC_SINK, TYPEC_DEVICE); |
@@ -2860,8 +3385,25 @@ static void run_state_machine(struct tcpm_port *port) | |||
2860 | /* Always switch to unattached state */ | 3385 | /* Always switch to unattached state */ |
2861 | tcpm_set_state(port, unattached_state(port), 0); | 3386 | tcpm_set_state(port, unattached_state(port), 0); |
2862 | break; | 3387 | break; |
3388 | case GET_STATUS_SEND: | ||
3389 | tcpm_pd_send_control(port, PD_CTRL_GET_STATUS); | ||
3390 | tcpm_set_state(port, GET_STATUS_SEND_TIMEOUT, | ||
3391 | PD_T_SENDER_RESPONSE); | ||
3392 | break; | ||
3393 | case GET_STATUS_SEND_TIMEOUT: | ||
3394 | tcpm_set_state(port, ready_state(port), 0); | ||
3395 | break; | ||
3396 | case GET_PPS_STATUS_SEND: | ||
3397 | tcpm_pd_send_control(port, PD_CTRL_GET_PPS_STATUS); | ||
3398 | tcpm_set_state(port, GET_PPS_STATUS_SEND_TIMEOUT, | ||
3399 | PD_T_SENDER_RESPONSE); | ||
3400 | break; | ||
3401 | case GET_PPS_STATUS_SEND_TIMEOUT: | ||
3402 | tcpm_set_state(port, ready_state(port), 0); | ||
3403 | break; | ||
2863 | case ERROR_RECOVERY: | 3404 | case ERROR_RECOVERY: |
2864 | tcpm_swap_complete(port, -EPROTO); | 3405 | tcpm_swap_complete(port, -EPROTO); |
3406 | tcpm_pps_complete(port, -EPROTO); | ||
2865 | tcpm_set_state(port, PORT_RESET, 0); | 3407 | tcpm_set_state(port, PORT_RESET, 0); |
2866 | break; | 3408 | break; |
2867 | case PORT_RESET: | 3409 | case PORT_RESET: |
@@ -3444,6 +3986,162 @@ static int tcpm_try_role(const struct typec_capability *cap, int role) | |||
3444 | return ret; | 3986 | return ret; |
3445 | } | 3987 | } |
3446 | 3988 | ||
3989 | static int tcpm_pps_set_op_curr(struct tcpm_port *port, u16 op_curr) | ||
3990 | { | ||
3991 | unsigned int target_mw; | ||
3992 | int ret; | ||
3993 | |||
3994 | mutex_lock(&port->swap_lock); | ||
3995 | mutex_lock(&port->lock); | ||
3996 | |||
3997 | if (!port->pps_data.active) { | ||
3998 | ret = -EOPNOTSUPP; | ||
3999 | goto port_unlock; | ||
4000 | } | ||
4001 | |||
4002 | if (port->state != SNK_READY) { | ||
4003 | ret = -EAGAIN; | ||
4004 | goto port_unlock; | ||
4005 | } | ||
4006 | |||
4007 | if (op_curr > port->pps_data.max_curr) { | ||
4008 | ret = -EINVAL; | ||
4009 | goto port_unlock; | ||
4010 | } | ||
4011 | |||
4012 | target_mw = (op_curr * port->pps_data.out_volt) / 1000; | ||
4013 | if (target_mw < port->operating_snk_mw) { | ||
4014 | ret = -EINVAL; | ||
4015 | goto port_unlock; | ||
4016 | } | ||
4017 | |||
4018 | reinit_completion(&port->pps_complete); | ||
4019 | port->pps_data.op_curr = op_curr; | ||
4020 | port->pps_status = 0; | ||
4021 | port->pps_pending = true; | ||
4022 | tcpm_set_state(port, SNK_NEGOTIATE_PPS_CAPABILITIES, 0); | ||
4023 | mutex_unlock(&port->lock); | ||
4024 | |||
4025 | if (!wait_for_completion_timeout(&port->pps_complete, | ||
4026 | msecs_to_jiffies(PD_PPS_CTRL_TIMEOUT))) | ||
4027 | ret = -ETIMEDOUT; | ||
4028 | else | ||
4029 | ret = port->pps_status; | ||
4030 | |||
4031 | goto swap_unlock; | ||
4032 | |||
4033 | port_unlock: | ||
4034 | mutex_unlock(&port->lock); | ||
4035 | swap_unlock: | ||
4036 | mutex_unlock(&port->swap_lock); | ||
4037 | |||
4038 | return ret; | ||
4039 | } | ||
4040 | |||
4041 | static int tcpm_pps_set_out_volt(struct tcpm_port *port, u16 out_volt) | ||
4042 | { | ||
4043 | unsigned int target_mw; | ||
4044 | int ret; | ||
4045 | |||
4046 | mutex_lock(&port->swap_lock); | ||
4047 | mutex_lock(&port->lock); | ||
4048 | |||
4049 | if (!port->pps_data.active) { | ||
4050 | ret = -EOPNOTSUPP; | ||
4051 | goto port_unlock; | ||
4052 | } | ||
4053 | |||
4054 | if (port->state != SNK_READY) { | ||
4055 | ret = -EAGAIN; | ||
4056 | goto port_unlock; | ||
4057 | } | ||
4058 | |||
4059 | if (out_volt < port->pps_data.min_volt || | ||
4060 | out_volt > port->pps_data.max_volt) { | ||
4061 | ret = -EINVAL; | ||
4062 | goto port_unlock; | ||
4063 | } | ||
4064 | |||
4065 | target_mw = (port->pps_data.op_curr * out_volt) / 1000; | ||
4066 | if (target_mw < port->operating_snk_mw) { | ||
4067 | ret = -EINVAL; | ||
4068 | goto port_unlock; | ||
4069 | } | ||
4070 | |||
4071 | reinit_completion(&port->pps_complete); | ||
4072 | port->pps_data.out_volt = out_volt; | ||
4073 | port->pps_status = 0; | ||
4074 | port->pps_pending = true; | ||
4075 | tcpm_set_state(port, SNK_NEGOTIATE_PPS_CAPABILITIES, 0); | ||
4076 | mutex_unlock(&port->lock); | ||
4077 | |||
4078 | if (!wait_for_completion_timeout(&port->pps_complete, | ||
4079 | msecs_to_jiffies(PD_PPS_CTRL_TIMEOUT))) | ||
4080 | ret = -ETIMEDOUT; | ||
4081 | else | ||
4082 | ret = port->pps_status; | ||
4083 | |||
4084 | goto swap_unlock; | ||
4085 | |||
4086 | port_unlock: | ||
4087 | mutex_unlock(&port->lock); | ||
4088 | swap_unlock: | ||
4089 | mutex_unlock(&port->swap_lock); | ||
4090 | |||
4091 | return ret; | ||
4092 | } | ||
4093 | |||
4094 | static int tcpm_pps_activate(struct tcpm_port *port, bool activate) | ||
4095 | { | ||
4096 | int ret = 0; | ||
4097 | |||
4098 | mutex_lock(&port->swap_lock); | ||
4099 | mutex_lock(&port->lock); | ||
4100 | |||
4101 | if (!port->pps_data.supported) { | ||
4102 | ret = -EOPNOTSUPP; | ||
4103 | goto port_unlock; | ||
4104 | } | ||
4105 | |||
4106 | /* Trying to deactivate PPS when already deactivated so just bail */ | ||
4107 | if (!port->pps_data.active && !activate) | ||
4108 | goto port_unlock; | ||
4109 | |||
4110 | if (port->state != SNK_READY) { | ||
4111 | ret = -EAGAIN; | ||
4112 | goto port_unlock; | ||
4113 | } | ||
4114 | |||
4115 | reinit_completion(&port->pps_complete); | ||
4116 | port->pps_status = 0; | ||
4117 | port->pps_pending = true; | ||
4118 | |||
4119 | /* Trigger PPS request or move back to standard PDO contract */ | ||
4120 | if (activate) { | ||
4121 | port->pps_data.out_volt = port->supply_voltage; | ||
4122 | port->pps_data.op_curr = port->current_limit; | ||
4123 | tcpm_set_state(port, SNK_NEGOTIATE_PPS_CAPABILITIES, 0); | ||
4124 | } else { | ||
4125 | tcpm_set_state(port, SNK_NEGOTIATE_CAPABILITIES, 0); | ||
4126 | } | ||
4127 | mutex_unlock(&port->lock); | ||
4128 | |||
4129 | if (!wait_for_completion_timeout(&port->pps_complete, | ||
4130 | msecs_to_jiffies(PD_PPS_CTRL_TIMEOUT))) | ||
4131 | ret = -ETIMEDOUT; | ||
4132 | else | ||
4133 | ret = port->pps_status; | ||
4134 | |||
4135 | goto swap_unlock; | ||
4136 | |||
4137 | port_unlock: | ||
4138 | mutex_unlock(&port->lock); | ||
4139 | swap_unlock: | ||
4140 | mutex_unlock(&port->swap_lock); | ||
4141 | |||
4142 | return ret; | ||
4143 | } | ||
4144 | |||
3447 | static void tcpm_init(struct tcpm_port *port) | 4145 | static void tcpm_init(struct tcpm_port *port) |
3448 | { | 4146 | { |
3449 | enum typec_cc_status cc1, cc2; | 4147 | enum typec_cc_status cc1, cc2; |
@@ -3569,9 +4267,6 @@ EXPORT_SYMBOL_GPL(tcpm_update_source_capabilities); | |||
3569 | 4267 | ||
3570 | int tcpm_update_sink_capabilities(struct tcpm_port *port, const u32 *pdo, | 4268 | int tcpm_update_sink_capabilities(struct tcpm_port *port, const u32 *pdo, |
3571 | unsigned int nr_pdo, | 4269 | unsigned int nr_pdo, |
3572 | unsigned int max_snk_mv, | ||
3573 | unsigned int max_snk_ma, | ||
3574 | unsigned int max_snk_mw, | ||
3575 | unsigned int operating_snk_mw) | 4270 | unsigned int operating_snk_mw) |
3576 | { | 4271 | { |
3577 | if (tcpm_validate_caps(port, pdo, nr_pdo)) | 4272 | if (tcpm_validate_caps(port, pdo, nr_pdo)) |
@@ -3579,17 +4274,19 @@ int tcpm_update_sink_capabilities(struct tcpm_port *port, const u32 *pdo, | |||
3579 | 4274 | ||
3580 | mutex_lock(&port->lock); | 4275 | mutex_lock(&port->lock); |
3581 | port->nr_snk_pdo = tcpm_copy_pdos(port->snk_pdo, pdo, nr_pdo); | 4276 | port->nr_snk_pdo = tcpm_copy_pdos(port->snk_pdo, pdo, nr_pdo); |
3582 | port->max_snk_mv = max_snk_mv; | ||
3583 | port->max_snk_ma = max_snk_ma; | ||
3584 | port->max_snk_mw = max_snk_mw; | ||
3585 | port->operating_snk_mw = operating_snk_mw; | 4277 | port->operating_snk_mw = operating_snk_mw; |
4278 | port->update_sink_caps = true; | ||
3586 | 4279 | ||
3587 | switch (port->state) { | 4280 | switch (port->state) { |
3588 | case SNK_NEGOTIATE_CAPABILITIES: | 4281 | case SNK_NEGOTIATE_CAPABILITIES: |
4282 | case SNK_NEGOTIATE_PPS_CAPABILITIES: | ||
3589 | case SNK_READY: | 4283 | case SNK_READY: |
3590 | case SNK_TRANSITION_SINK: | 4284 | case SNK_TRANSITION_SINK: |
3591 | case SNK_TRANSITION_SINK_VBUS: | 4285 | case SNK_TRANSITION_SINK_VBUS: |
3592 | tcpm_set_state(port, SNK_NEGOTIATE_CAPABILITIES, 0); | 4286 | if (port->pps_data.active) |
4287 | tcpm_set_state(port, SNK_NEGOTIATE_PPS_CAPABILITIES, 0); | ||
4288 | else | ||
4289 | tcpm_set_state(port, SNK_NEGOTIATE_CAPABILITIES, 0); | ||
3593 | break; | 4290 | break; |
3594 | default: | 4291 | default: |
3595 | break; | 4292 | break; |
@@ -3599,6 +4296,231 @@ int tcpm_update_sink_capabilities(struct tcpm_port *port, const u32 *pdo, | |||
3599 | } | 4296 | } |
3600 | EXPORT_SYMBOL_GPL(tcpm_update_sink_capabilities); | 4297 | EXPORT_SYMBOL_GPL(tcpm_update_sink_capabilities); |
3601 | 4298 | ||
4299 | /* Power Supply access to expose source power information */ | ||
4300 | enum tcpm_psy_online_states { | ||
4301 | TCPM_PSY_OFFLINE = 0, | ||
4302 | TCPM_PSY_FIXED_ONLINE, | ||
4303 | TCPM_PSY_PROG_ONLINE, | ||
4304 | }; | ||
4305 | |||
4306 | static enum power_supply_property tcpm_psy_props[] = { | ||
4307 | POWER_SUPPLY_PROP_USB_TYPE, | ||
4308 | POWER_SUPPLY_PROP_ONLINE, | ||
4309 | POWER_SUPPLY_PROP_VOLTAGE_MIN, | ||
4310 | POWER_SUPPLY_PROP_VOLTAGE_MAX, | ||
4311 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
4312 | POWER_SUPPLY_PROP_CURRENT_MAX, | ||
4313 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
4314 | }; | ||
4315 | |||
4316 | static int tcpm_psy_get_online(struct tcpm_port *port, | ||
4317 | union power_supply_propval *val) | ||
4318 | { | ||
4319 | if (port->vbus_charge) { | ||
4320 | if (port->pps_data.active) | ||
4321 | val->intval = TCPM_PSY_PROG_ONLINE; | ||
4322 | else | ||
4323 | val->intval = TCPM_PSY_FIXED_ONLINE; | ||
4324 | } else { | ||
4325 | val->intval = TCPM_PSY_OFFLINE; | ||
4326 | } | ||
4327 | |||
4328 | return 0; | ||
4329 | } | ||
4330 | |||
4331 | static int tcpm_psy_get_voltage_min(struct tcpm_port *port, | ||
4332 | union power_supply_propval *val) | ||
4333 | { | ||
4334 | if (port->pps_data.active) | ||
4335 | val->intval = port->pps_data.min_volt * 1000; | ||
4336 | else | ||
4337 | val->intval = port->supply_voltage * 1000; | ||
4338 | |||
4339 | return 0; | ||
4340 | } | ||
4341 | |||
4342 | static int tcpm_psy_get_voltage_max(struct tcpm_port *port, | ||
4343 | union power_supply_propval *val) | ||
4344 | { | ||
4345 | if (port->pps_data.active) | ||
4346 | val->intval = port->pps_data.max_volt * 1000; | ||
4347 | else | ||
4348 | val->intval = port->supply_voltage * 1000; | ||
4349 | |||
4350 | return 0; | ||
4351 | } | ||
4352 | |||
4353 | static int tcpm_psy_get_voltage_now(struct tcpm_port *port, | ||
4354 | union power_supply_propval *val) | ||
4355 | { | ||
4356 | val->intval = port->supply_voltage * 1000; | ||
4357 | |||
4358 | return 0; | ||
4359 | } | ||
4360 | |||
4361 | static int tcpm_psy_get_current_max(struct tcpm_port *port, | ||
4362 | union power_supply_propval *val) | ||
4363 | { | ||
4364 | if (port->pps_data.active) | ||
4365 | val->intval = port->pps_data.max_curr * 1000; | ||
4366 | else | ||
4367 | val->intval = port->current_limit * 1000; | ||
4368 | |||
4369 | return 0; | ||
4370 | } | ||
4371 | |||
4372 | static int tcpm_psy_get_current_now(struct tcpm_port *port, | ||
4373 | union power_supply_propval *val) | ||
4374 | { | ||
4375 | val->intval = port->current_limit * 1000; | ||
4376 | |||
4377 | return 0; | ||
4378 | } | ||
4379 | |||
4380 | static int tcpm_psy_get_prop(struct power_supply *psy, | ||
4381 | enum power_supply_property psp, | ||
4382 | union power_supply_propval *val) | ||
4383 | { | ||
4384 | struct tcpm_port *port = power_supply_get_drvdata(psy); | ||
4385 | int ret = 0; | ||
4386 | |||
4387 | switch (psp) { | ||
4388 | case POWER_SUPPLY_PROP_USB_TYPE: | ||
4389 | val->intval = port->usb_type; | ||
4390 | break; | ||
4391 | case POWER_SUPPLY_PROP_ONLINE: | ||
4392 | ret = tcpm_psy_get_online(port, val); | ||
4393 | break; | ||
4394 | case POWER_SUPPLY_PROP_VOLTAGE_MIN: | ||
4395 | ret = tcpm_psy_get_voltage_min(port, val); | ||
4396 | break; | ||
4397 | case POWER_SUPPLY_PROP_VOLTAGE_MAX: | ||
4398 | ret = tcpm_psy_get_voltage_max(port, val); | ||
4399 | break; | ||
4400 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
4401 | ret = tcpm_psy_get_voltage_now(port, val); | ||
4402 | break; | ||
4403 | case POWER_SUPPLY_PROP_CURRENT_MAX: | ||
4404 | ret = tcpm_psy_get_current_max(port, val); | ||
4405 | break; | ||
4406 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
4407 | ret = tcpm_psy_get_current_now(port, val); | ||
4408 | break; | ||
4409 | default: | ||
4410 | ret = -EINVAL; | ||
4411 | break; | ||
4412 | } | ||
4413 | |||
4414 | return ret; | ||
4415 | } | ||
4416 | |||
4417 | static int tcpm_psy_set_online(struct tcpm_port *port, | ||
4418 | const union power_supply_propval *val) | ||
4419 | { | ||
4420 | int ret; | ||
4421 | |||
4422 | switch (val->intval) { | ||
4423 | case TCPM_PSY_FIXED_ONLINE: | ||
4424 | ret = tcpm_pps_activate(port, false); | ||
4425 | break; | ||
4426 | case TCPM_PSY_PROG_ONLINE: | ||
4427 | ret = tcpm_pps_activate(port, true); | ||
4428 | break; | ||
4429 | default: | ||
4430 | ret = -EINVAL; | ||
4431 | break; | ||
4432 | } | ||
4433 | |||
4434 | return ret; | ||
4435 | } | ||
4436 | |||
4437 | static int tcpm_psy_set_prop(struct power_supply *psy, | ||
4438 | enum power_supply_property psp, | ||
4439 | const union power_supply_propval *val) | ||
4440 | { | ||
4441 | struct tcpm_port *port = power_supply_get_drvdata(psy); | ||
4442 | int ret; | ||
4443 | |||
4444 | switch (psp) { | ||
4445 | case POWER_SUPPLY_PROP_ONLINE: | ||
4446 | ret = tcpm_psy_set_online(port, val); | ||
4447 | break; | ||
4448 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
4449 | if (val->intval < port->pps_data.min_volt * 1000 || | ||
4450 | val->intval > port->pps_data.max_volt * 1000) | ||
4451 | ret = -EINVAL; | ||
4452 | else | ||
4453 | ret = tcpm_pps_set_out_volt(port, val->intval / 1000); | ||
4454 | break; | ||
4455 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
4456 | if (val->intval > port->pps_data.max_curr * 1000) | ||
4457 | ret = -EINVAL; | ||
4458 | else | ||
4459 | ret = tcpm_pps_set_op_curr(port, val->intval / 1000); | ||
4460 | break; | ||
4461 | default: | ||
4462 | ret = -EINVAL; | ||
4463 | break; | ||
4464 | } | ||
4465 | |||
4466 | return ret; | ||
4467 | } | ||
4468 | |||
4469 | static int tcpm_psy_prop_writeable(struct power_supply *psy, | ||
4470 | enum power_supply_property psp) | ||
4471 | { | ||
4472 | switch (psp) { | ||
4473 | case POWER_SUPPLY_PROP_ONLINE: | ||
4474 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
4475 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
4476 | return 1; | ||
4477 | default: | ||
4478 | return 0; | ||
4479 | } | ||
4480 | } | ||
4481 | |||
4482 | static enum power_supply_usb_type tcpm_psy_usb_types[] = { | ||
4483 | POWER_SUPPLY_USB_TYPE_C, | ||
4484 | POWER_SUPPLY_USB_TYPE_PD, | ||
4485 | POWER_SUPPLY_USB_TYPE_PD_PPS, | ||
4486 | }; | ||
4487 | |||
4488 | static const char *tcpm_psy_name_prefix = "tcpm-source-psy-"; | ||
4489 | |||
4490 | static int devm_tcpm_psy_register(struct tcpm_port *port) | ||
4491 | { | ||
4492 | struct power_supply_config psy_cfg = {}; | ||
4493 | const char *port_dev_name = dev_name(port->dev); | ||
4494 | size_t psy_name_len = strlen(tcpm_psy_name_prefix) + | ||
4495 | strlen(port_dev_name) + 1; | ||
4496 | char *psy_name; | ||
4497 | |||
4498 | psy_cfg.drv_data = port; | ||
4499 | psy_cfg.fwnode = dev_fwnode(port->dev); | ||
4500 | psy_name = devm_kzalloc(port->dev, psy_name_len, GFP_KERNEL); | ||
4501 | if (!psy_name) | ||
4502 | return -ENOMEM; | ||
4503 | |||
4504 | snprintf(psy_name, psy_name_len, "%s%s", tcpm_psy_name_prefix, | ||
4505 | port_dev_name); | ||
4506 | port->psy_desc.name = psy_name; | ||
4507 | port->psy_desc.type = POWER_SUPPLY_TYPE_USB, | ||
4508 | port->psy_desc.usb_types = tcpm_psy_usb_types; | ||
4509 | port->psy_desc.num_usb_types = ARRAY_SIZE(tcpm_psy_usb_types); | ||
4510 | port->psy_desc.properties = tcpm_psy_props, | ||
4511 | port->psy_desc.num_properties = ARRAY_SIZE(tcpm_psy_props), | ||
4512 | port->psy_desc.get_property = tcpm_psy_get_prop, | ||
4513 | port->psy_desc.set_property = tcpm_psy_set_prop, | ||
4514 | port->psy_desc.property_is_writeable = tcpm_psy_prop_writeable, | ||
4515 | |||
4516 | port->usb_type = POWER_SUPPLY_USB_TYPE_C; | ||
4517 | |||
4518 | port->psy = devm_power_supply_register(port->dev, &port->psy_desc, | ||
4519 | &psy_cfg); | ||
4520 | |||
4521 | return PTR_ERR_OR_ZERO(port->psy); | ||
4522 | } | ||
4523 | |||
3602 | struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) | 4524 | struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) |
3603 | { | 4525 | { |
3604 | struct tcpm_port *port; | 4526 | struct tcpm_port *port; |
@@ -3631,6 +4553,7 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) | |||
3631 | 4553 | ||
3632 | init_completion(&port->tx_complete); | 4554 | init_completion(&port->tx_complete); |
3633 | init_completion(&port->swap_complete); | 4555 | init_completion(&port->swap_complete); |
4556 | init_completion(&port->pps_complete); | ||
3634 | tcpm_debugfs_init(port); | 4557 | tcpm_debugfs_init(port); |
3635 | 4558 | ||
3636 | if (tcpm_validate_caps(port, tcpc->config->src_pdo, | 4559 | if (tcpm_validate_caps(port, tcpc->config->src_pdo, |
@@ -3647,9 +4570,6 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) | |||
3647 | port->nr_snk_vdo = tcpm_copy_vdos(port->snk_vdo, tcpc->config->snk_vdo, | 4570 | port->nr_snk_vdo = tcpm_copy_vdos(port->snk_vdo, tcpc->config->snk_vdo, |
3648 | tcpc->config->nr_snk_vdo); | 4571 | tcpc->config->nr_snk_vdo); |
3649 | 4572 | ||
3650 | port->max_snk_mv = tcpc->config->max_snk_mv; | ||
3651 | port->max_snk_ma = tcpc->config->max_snk_ma; | ||
3652 | port->max_snk_mw = tcpc->config->max_snk_mw; | ||
3653 | port->operating_snk_mw = tcpc->config->operating_snk_mw; | 4573 | port->operating_snk_mw = tcpc->config->operating_snk_mw; |
3654 | if (!tcpc->config->try_role_hw) | 4574 | if (!tcpc->config->try_role_hw) |
3655 | port->try_role = tcpc->config->default_role; | 4575 | port->try_role = tcpc->config->default_role; |
@@ -3660,7 +4580,7 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) | |||
3660 | port->typec_caps.type = tcpc->config->type; | 4580 | port->typec_caps.type = tcpc->config->type; |
3661 | port->typec_caps.data = tcpc->config->data; | 4581 | port->typec_caps.data = tcpc->config->data; |
3662 | port->typec_caps.revision = 0x0120; /* Type-C spec release 1.2 */ | 4582 | port->typec_caps.revision = 0x0120; /* Type-C spec release 1.2 */ |
3663 | port->typec_caps.pd_revision = 0x0200; /* USB-PD spec release 2.0 */ | 4583 | port->typec_caps.pd_revision = 0x0300; /* USB-PD spec release 3.0 */ |
3664 | port->typec_caps.dr_set = tcpm_dr_set; | 4584 | port->typec_caps.dr_set = tcpm_dr_set; |
3665 | port->typec_caps.pr_set = tcpm_pr_set; | 4585 | port->typec_caps.pr_set = tcpm_pr_set; |
3666 | port->typec_caps.vconn_set = tcpm_vconn_set; | 4586 | port->typec_caps.vconn_set = tcpm_vconn_set; |
@@ -3676,6 +4596,10 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) | |||
3676 | goto out_destroy_wq; | 4596 | goto out_destroy_wq; |
3677 | } | 4597 | } |
3678 | 4598 | ||
4599 | err = devm_tcpm_psy_register(port); | ||
4600 | if (err) | ||
4601 | goto out_destroy_wq; | ||
4602 | |||
3679 | port->typec_port = typec_register_port(port->dev, &port->typec_caps); | 4603 | port->typec_port = typec_register_port(port->dev, &port->typec_caps); |
3680 | if (IS_ERR(port->typec_port)) { | 4604 | if (IS_ERR(port->typec_port)) { |
3681 | err = PTR_ERR(port->typec_port); | 4605 | err = PTR_ERR(port->typec_port); |
diff --git a/drivers/usb/typec/typec_wcove.c b/drivers/usb/typec/typec_wcove.c index 19cca7f1b2c5..423208e19383 100644 --- a/drivers/usb/typec/typec_wcove.c +++ b/drivers/usb/typec/typec_wcove.c | |||
@@ -202,6 +202,10 @@ static int wcove_init(struct tcpc_dev *tcpc) | |||
202 | struct wcove_typec *wcove = tcpc_to_wcove(tcpc); | 202 | struct wcove_typec *wcove = tcpc_to_wcove(tcpc); |
203 | int ret; | 203 | int ret; |
204 | 204 | ||
205 | ret = regmap_write(wcove->regmap, USBC_CONTROL1, 0); | ||
206 | if (ret) | ||
207 | return ret; | ||
208 | |||
205 | /* Unmask everything */ | 209 | /* Unmask everything */ |
206 | ret = regmap_write(wcove->regmap, USBC_IRQMASK1, 0); | 210 | ret = regmap_write(wcove->regmap, USBC_IRQMASK1, 0); |
207 | if (ret) | 211 | if (ret) |
@@ -285,8 +289,30 @@ static int wcove_get_cc(struct tcpc_dev *tcpc, enum typec_cc_status *cc1, | |||
285 | 289 | ||
286 | static int wcove_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc) | 290 | static int wcove_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc) |
287 | { | 291 | { |
288 | /* XXX: Relying on the HW FSM to configure things correctly for now */ | 292 | struct wcove_typec *wcove = tcpc_to_wcove(tcpc); |
289 | return 0; | 293 | unsigned int ctrl; |
294 | |||
295 | switch (cc) { | ||
296 | case TYPEC_CC_RD: | ||
297 | ctrl = USBC_CONTROL1_MODE_SNK; | ||
298 | break; | ||
299 | case TYPEC_CC_RP_DEF: | ||
300 | ctrl = USBC_CONTROL1_CURSRC_UA_80 | USBC_CONTROL1_MODE_SRC; | ||
301 | break; | ||
302 | case TYPEC_CC_RP_1_5: | ||
303 | ctrl = USBC_CONTROL1_CURSRC_UA_180 | USBC_CONTROL1_MODE_SRC; | ||
304 | break; | ||
305 | case TYPEC_CC_RP_3_0: | ||
306 | ctrl = USBC_CONTROL1_CURSRC_UA_330 | USBC_CONTROL1_MODE_SRC; | ||
307 | break; | ||
308 | case TYPEC_CC_OPEN: | ||
309 | ctrl = 0; | ||
310 | break; | ||
311 | default: | ||
312 | return -EINVAL; | ||
313 | } | ||
314 | |||
315 | return regmap_write(wcove->regmap, USBC_CONTROL1, ctrl); | ||
290 | } | 316 | } |
291 | 317 | ||
292 | static int wcove_set_polarity(struct tcpc_dev *tcpc, enum typec_cc_polarity pol) | 318 | static int wcove_set_polarity(struct tcpc_dev *tcpc, enum typec_cc_polarity pol) |
@@ -558,6 +584,7 @@ static const u32 src_pdo[] = { | |||
558 | static const u32 snk_pdo[] = { | 584 | static const u32 snk_pdo[] = { |
559 | PDO_FIXED(5000, 500, PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP | | 585 | PDO_FIXED(5000, 500, PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP | |
560 | PDO_FIXED_USB_COMM), | 586 | PDO_FIXED_USB_COMM), |
587 | PDO_VAR(5000, 12000, 3000), | ||
561 | }; | 588 | }; |
562 | 589 | ||
563 | static struct tcpc_config wcove_typec_config = { | 590 | static struct tcpc_config wcove_typec_config = { |
@@ -566,9 +593,6 @@ static struct tcpc_config wcove_typec_config = { | |||
566 | .snk_pdo = snk_pdo, | 593 | .snk_pdo = snk_pdo, |
567 | .nr_snk_pdo = ARRAY_SIZE(snk_pdo), | 594 | .nr_snk_pdo = ARRAY_SIZE(snk_pdo), |
568 | 595 | ||
569 | .max_snk_mv = 12000, | ||
570 | .max_snk_ma = 3000, | ||
571 | .max_snk_mw = 36000, | ||
572 | .operating_snk_mw = 15000, | 596 | .operating_snk_mw = 15000, |
573 | 597 | ||
574 | .type = TYPEC_PORT_DRP, | 598 | .type = TYPEC_PORT_DRP, |
diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c index 48808388ec33..be37aec250c2 100644 --- a/drivers/usb/usbip/vhci_sysfs.c +++ b/drivers/usb/usbip/vhci_sysfs.c | |||
@@ -10,6 +10,9 @@ | |||
10 | #include <linux/platform_device.h> | 10 | #include <linux/platform_device.h> |
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | 12 | ||
13 | /* Hardening for Spectre-v1 */ | ||
14 | #include <linux/nospec.h> | ||
15 | |||
13 | #include "usbip_common.h" | 16 | #include "usbip_common.h" |
14 | #include "vhci.h" | 17 | #include "vhci.h" |
15 | 18 | ||
@@ -205,16 +208,20 @@ static int vhci_port_disconnect(struct vhci_hcd *vhci_hcd, __u32 rhport) | |||
205 | return 0; | 208 | return 0; |
206 | } | 209 | } |
207 | 210 | ||
208 | static int valid_port(__u32 pdev_nr, __u32 rhport) | 211 | static int valid_port(__u32 *pdev_nr, __u32 *rhport) |
209 | { | 212 | { |
210 | if (pdev_nr >= vhci_num_controllers) { | 213 | if (*pdev_nr >= vhci_num_controllers) { |
211 | pr_err("pdev %u\n", pdev_nr); | 214 | pr_err("pdev %u\n", *pdev_nr); |
212 | return 0; | 215 | return 0; |
213 | } | 216 | } |
214 | if (rhport >= VHCI_HC_PORTS) { | 217 | *pdev_nr = array_index_nospec(*pdev_nr, vhci_num_controllers); |
215 | pr_err("rhport %u\n", rhport); | 218 | |
219 | if (*rhport >= VHCI_HC_PORTS) { | ||
220 | pr_err("rhport %u\n", *rhport); | ||
216 | return 0; | 221 | return 0; |
217 | } | 222 | } |
223 | *rhport = array_index_nospec(*rhport, VHCI_HC_PORTS); | ||
224 | |||
218 | return 1; | 225 | return 1; |
219 | } | 226 | } |
220 | 227 | ||
@@ -232,7 +239,7 @@ static ssize_t detach_store(struct device *dev, struct device_attribute *attr, | |||
232 | pdev_nr = port_to_pdev_nr(port); | 239 | pdev_nr = port_to_pdev_nr(port); |
233 | rhport = port_to_rhport(port); | 240 | rhport = port_to_rhport(port); |
234 | 241 | ||
235 | if (!valid_port(pdev_nr, rhport)) | 242 | if (!valid_port(&pdev_nr, &rhport)) |
236 | return -EINVAL; | 243 | return -EINVAL; |
237 | 244 | ||
238 | hcd = platform_get_drvdata(vhcis[pdev_nr].pdev); | 245 | hcd = platform_get_drvdata(vhcis[pdev_nr].pdev); |
@@ -258,7 +265,8 @@ static ssize_t detach_store(struct device *dev, struct device_attribute *attr, | |||
258 | } | 265 | } |
259 | static DEVICE_ATTR_WO(detach); | 266 | static DEVICE_ATTR_WO(detach); |
260 | 267 | ||
261 | static int valid_args(__u32 pdev_nr, __u32 rhport, enum usb_device_speed speed) | 268 | static int valid_args(__u32 *pdev_nr, __u32 *rhport, |
269 | enum usb_device_speed speed) | ||
262 | { | 270 | { |
263 | if (!valid_port(pdev_nr, rhport)) { | 271 | if (!valid_port(pdev_nr, rhport)) { |
264 | return 0; | 272 | return 0; |
@@ -322,7 +330,7 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, | |||
322 | sockfd, devid, speed); | 330 | sockfd, devid, speed); |
323 | 331 | ||
324 | /* check received parameters */ | 332 | /* check received parameters */ |
325 | if (!valid_args(pdev_nr, rhport, speed)) | 333 | if (!valid_args(&pdev_nr, &rhport, speed)) |
326 | return -EINVAL; | 334 | return -EINVAL; |
327 | 335 | ||
328 | hcd = platform_get_drvdata(vhcis[pdev_nr].pdev); | 336 | hcd = platform_get_drvdata(vhcis[pdev_nr].pdev); |
diff --git a/include/dt-bindings/phy/phy-qcom-qusb2.h b/include/dt-bindings/phy/phy-qcom-qusb2.h new file mode 100644 index 000000000000..5c5e4d800cac --- /dev/null +++ b/include/dt-bindings/phy/phy-qcom-qusb2.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | /* | ||
3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | ||
4 | */ | ||
5 | |||
6 | #ifndef _DT_BINDINGS_QCOM_PHY_QUSB2_H_ | ||
7 | #define _DT_BINDINGS_QCOM_PHY_QUSB2_H_ | ||
8 | |||
9 | /* PHY HSTX TRIM bit values (24mA to 15mA) */ | ||
10 | #define QUSB2_V2_HSTX_TRIM_24_0_MA 0x0 | ||
11 | #define QUSB2_V2_HSTX_TRIM_23_4_MA 0x1 | ||
12 | #define QUSB2_V2_HSTX_TRIM_22_8_MA 0x2 | ||
13 | #define QUSB2_V2_HSTX_TRIM_22_2_MA 0x3 | ||
14 | #define QUSB2_V2_HSTX_TRIM_21_6_MA 0x4 | ||
15 | #define QUSB2_V2_HSTX_TRIM_21_0_MA 0x5 | ||
16 | #define QUSB2_V2_HSTX_TRIM_20_4_MA 0x6 | ||
17 | #define QUSB2_V2_HSTX_TRIM_19_8_MA 0x7 | ||
18 | #define QUSB2_V2_HSTX_TRIM_19_2_MA 0x8 | ||
19 | #define QUSB2_V2_HSTX_TRIM_18_6_MA 0x9 | ||
20 | #define QUSB2_V2_HSTX_TRIM_18_0_MA 0xa | ||
21 | #define QUSB2_V2_HSTX_TRIM_17_4_MA 0xb | ||
22 | #define QUSB2_V2_HSTX_TRIM_16_8_MA 0xc | ||
23 | #define QUSB2_V2_HSTX_TRIM_16_2_MA 0xd | ||
24 | #define QUSB2_V2_HSTX_TRIM_15_6_MA 0xe | ||
25 | #define QUSB2_V2_HSTX_TRIM_15_0_MA 0xf | ||
26 | |||
27 | /* PHY PREEMPHASIS bit values */ | ||
28 | #define QUSB2_V2_PREEMPHASIS_NONE 0 | ||
29 | #define QUSB2_V2_PREEMPHASIS_5_PERCENT 1 | ||
30 | #define QUSB2_V2_PREEMPHASIS_10_PERCENT 2 | ||
31 | #define QUSB2_V2_PREEMPHASIS_15_PERCENT 3 | ||
32 | |||
33 | /* PHY PREEMPHASIS-WIDTH bit values */ | ||
34 | #define QUSB2_V2_PREEMPHASIS_WIDTH_FULL_BIT 0 | ||
35 | #define QUSB2_V2_PREEMPHASIS_WIDTH_HALF_BIT 1 | ||
36 | |||
37 | #endif | ||
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index f0139b460a72..b21c4bd96b84 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h | |||
@@ -145,6 +145,7 @@ enum power_supply_property { | |||
145 | POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, | 145 | POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, |
146 | POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, | 146 | POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, |
147 | POWER_SUPPLY_PROP_TYPE, /* use power_supply.type instead */ | 147 | POWER_SUPPLY_PROP_TYPE, /* use power_supply.type instead */ |
148 | POWER_SUPPLY_PROP_USB_TYPE, | ||
148 | POWER_SUPPLY_PROP_SCOPE, | 149 | POWER_SUPPLY_PROP_SCOPE, |
149 | POWER_SUPPLY_PROP_PRECHARGE_CURRENT, | 150 | POWER_SUPPLY_PROP_PRECHARGE_CURRENT, |
150 | POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, | 151 | POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, |
@@ -170,6 +171,19 @@ enum power_supply_type { | |||
170 | POWER_SUPPLY_TYPE_APPLE_BRICK_ID, /* Apple Charging Method */ | 171 | POWER_SUPPLY_TYPE_APPLE_BRICK_ID, /* Apple Charging Method */ |
171 | }; | 172 | }; |
172 | 173 | ||
174 | enum power_supply_usb_type { | ||
175 | POWER_SUPPLY_USB_TYPE_UNKNOWN = 0, | ||
176 | POWER_SUPPLY_USB_TYPE_SDP, /* Standard Downstream Port */ | ||
177 | POWER_SUPPLY_USB_TYPE_DCP, /* Dedicated Charging Port */ | ||
178 | POWER_SUPPLY_USB_TYPE_CDP, /* Charging Downstream Port */ | ||
179 | POWER_SUPPLY_USB_TYPE_ACA, /* Accessory Charger Adapters */ | ||
180 | POWER_SUPPLY_USB_TYPE_C, /* Type C Port */ | ||
181 | POWER_SUPPLY_USB_TYPE_PD, /* Power Delivery Port */ | ||
182 | POWER_SUPPLY_USB_TYPE_PD_DRP, /* PD Dual Role Port */ | ||
183 | POWER_SUPPLY_USB_TYPE_PD_PPS, /* PD Programmable Power Supply */ | ||
184 | POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID, /* Apple Charging Method */ | ||
185 | }; | ||
186 | |||
173 | enum power_supply_notifier_events { | 187 | enum power_supply_notifier_events { |
174 | PSY_EVENT_PROP_CHANGED, | 188 | PSY_EVENT_PROP_CHANGED, |
175 | }; | 189 | }; |
@@ -185,6 +199,8 @@ struct power_supply; | |||
185 | /* Run-time specific power supply configuration */ | 199 | /* Run-time specific power supply configuration */ |
186 | struct power_supply_config { | 200 | struct power_supply_config { |
187 | struct device_node *of_node; | 201 | struct device_node *of_node; |
202 | struct fwnode_handle *fwnode; | ||
203 | |||
188 | /* Driver private data */ | 204 | /* Driver private data */ |
189 | void *drv_data; | 205 | void *drv_data; |
190 | 206 | ||
@@ -196,6 +212,8 @@ struct power_supply_config { | |||
196 | struct power_supply_desc { | 212 | struct power_supply_desc { |
197 | const char *name; | 213 | const char *name; |
198 | enum power_supply_type type; | 214 | enum power_supply_type type; |
215 | enum power_supply_usb_type *usb_types; | ||
216 | size_t num_usb_types; | ||
199 | enum power_supply_property *properties; | 217 | enum power_supply_property *properties; |
200 | size_t num_properties; | 218 | size_t num_properties; |
201 | 219 | ||
diff --git a/include/linux/tty.h b/include/linux/tty.h index 9bd7d37adbfa..c56e3978b00f 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
@@ -528,7 +528,7 @@ static inline speed_t tty_get_baud_rate(struct tty_struct *tty) | |||
528 | } | 528 | } |
529 | 529 | ||
530 | extern void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old); | 530 | extern void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old); |
531 | extern int tty_termios_hw_change(struct ktermios *a, struct ktermios *b); | 531 | extern int tty_termios_hw_change(const struct ktermios *a, const struct ktermios *b); |
532 | extern int tty_set_termios(struct tty_struct *tty, struct ktermios *kt); | 532 | extern int tty_set_termios(struct tty_struct *tty, struct ktermios *kt); |
533 | 533 | ||
534 | extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *); | 534 | extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *); |
diff --git a/include/linux/usb.h b/include/linux/usb.h index 0173597e59aa..4cdd515a4385 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h | |||
@@ -490,6 +490,16 @@ enum usb_port_connect_type { | |||
490 | }; | 490 | }; |
491 | 491 | ||
492 | /* | 492 | /* |
493 | * USB port quirks. | ||
494 | */ | ||
495 | |||
496 | /* For the given port, prefer the old (faster) enumeration scheme. */ | ||
497 | #define USB_PORT_QUIRK_OLD_SCHEME BIT(0) | ||
498 | |||
499 | /* Decrease TRSTRCY to 10ms during device enumeration. */ | ||
500 | #define USB_PORT_QUIRK_FAST_ENUM BIT(1) | ||
501 | |||
502 | /* | ||
493 | * USB 2.0 Link Power Management (LPM) parameters. | 503 | * USB 2.0 Link Power Management (LPM) parameters. |
494 | */ | 504 | */ |
495 | struct usb2_lpm_parameters { | 505 | struct usb2_lpm_parameters { |
@@ -551,6 +561,8 @@ struct usb3_lpm_parameters { | |||
551 | * @route: tree topology hex string for use with xHCI | 561 | * @route: tree topology hex string for use with xHCI |
552 | * @state: device state: configured, not attached, etc. | 562 | * @state: device state: configured, not attached, etc. |
553 | * @speed: device speed: high/full/low (or error) | 563 | * @speed: device speed: high/full/low (or error) |
564 | * @rx_lanes: number of rx lanes in use, USB 3.2 adds dual-lane support | ||
565 | * @tx_lanes: number of tx lanes in use, USB 3.2 adds dual-lane support | ||
554 | * @tt: Transaction Translator info; used with low/full speed dev, highspeed hub | 566 | * @tt: Transaction Translator info; used with low/full speed dev, highspeed hub |
555 | * @ttport: device port on that tt hub | 567 | * @ttport: device port on that tt hub |
556 | * @toggle: one bit for each endpoint, with ([0] = IN, [1] = OUT) endpoints | 568 | * @toggle: one bit for each endpoint, with ([0] = IN, [1] = OUT) endpoints |
@@ -624,6 +636,8 @@ struct usb_device { | |||
624 | u32 route; | 636 | u32 route; |
625 | enum usb_device_state state; | 637 | enum usb_device_state state; |
626 | enum usb_device_speed speed; | 638 | enum usb_device_speed speed; |
639 | unsigned int rx_lanes; | ||
640 | unsigned int tx_lanes; | ||
627 | 641 | ||
628 | struct usb_tt *tt; | 642 | struct usb_tt *tt; |
629 | int ttport; | 643 | int ttport; |
diff --git a/include/linux/usb/atmel_usba_udc.h b/include/linux/usb/atmel_usba_udc.h deleted file mode 100644 index 9bb00df3b53f..000000000000 --- a/include/linux/usb/atmel_usba_udc.h +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | /* | ||
3 | * Platform data definitions for Atmel USBA gadget driver. | ||
4 | */ | ||
5 | #ifndef __LINUX_USB_USBA_H | ||
6 | #define __LINUX_USB_USBA_H | ||
7 | |||
8 | struct usba_ep_data { | ||
9 | char *name; | ||
10 | int index; | ||
11 | int fifo_size; | ||
12 | int nr_banks; | ||
13 | int can_dma; | ||
14 | int can_isoc; | ||
15 | }; | ||
16 | |||
17 | struct usba_platform_data { | ||
18 | int vbus_pin; | ||
19 | int vbus_pin_inverted; | ||
20 | int num_ep; | ||
21 | struct usba_ep_data ep[0]; | ||
22 | }; | ||
23 | |||
24 | #endif /* __LINUX_USB_USBA_H */ | ||
diff --git a/include/linux/usb/audio-v2.h b/include/linux/usb/audio-v2.h index aaafecf073ff..49699255cfd3 100644 --- a/include/linux/usb/audio-v2.h +++ b/include/linux/usb/audio-v2.h | |||
@@ -94,7 +94,7 @@ struct uac_clock_selector_descriptor { | |||
94 | __u8 bClockID; | 94 | __u8 bClockID; |
95 | __u8 bNrInPins; | 95 | __u8 bNrInPins; |
96 | __u8 baCSourceID[]; | 96 | __u8 baCSourceID[]; |
97 | /* bmControls, bAssocTerminal and iClockSource omitted */ | 97 | /* bmControls and iClockSource omitted */ |
98 | } __attribute__((packed)); | 98 | } __attribute__((packed)); |
99 | 99 | ||
100 | /* 4.7.2.3 Clock Multiplier Descriptor */ | 100 | /* 4.7.2.3 Clock Multiplier Descriptor */ |
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 847f423ad9b3..e5cd84a0f84a 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h | |||
@@ -763,7 +763,7 @@ struct usb_gadget_string_container { | |||
763 | }; | 763 | }; |
764 | 764 | ||
765 | /* put descriptor for string with that id into buf (buflen >= 256) */ | 765 | /* put descriptor for string with that id into buf (buflen >= 256) */ |
766 | int usb_gadget_get_string(struct usb_gadget_strings *table, int id, u8 *buf); | 766 | int usb_gadget_get_string(const struct usb_gadget_strings *table, int id, u8 *buf); |
767 | 767 | ||
768 | /*-------------------------------------------------------------------------*/ | 768 | /*-------------------------------------------------------------------------*/ |
769 | 769 | ||
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index aef50cb2ed1b..34a6ded6f319 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h | |||
@@ -150,7 +150,6 @@ struct usb_hcd { | |||
150 | unsigned rh_pollable:1; /* may we poll the root hub? */ | 150 | unsigned rh_pollable:1; /* may we poll the root hub? */ |
151 | unsigned msix_enabled:1; /* driver has MSI-X enabled? */ | 151 | unsigned msix_enabled:1; /* driver has MSI-X enabled? */ |
152 | unsigned msi_enabled:1; /* driver has MSI enabled? */ | 152 | unsigned msi_enabled:1; /* driver has MSI enabled? */ |
153 | unsigned remove_phy:1; /* auto-remove USB phy */ | ||
154 | /* | 153 | /* |
155 | * do not manage the PHY state in the HCD core, instead let the driver | 154 | * do not manage the PHY state in the HCD core, instead let the driver |
156 | * handle this (for example if the PHY can only be turned on after a | 155 | * handle this (for example if the PHY can only be turned on after a |
@@ -261,6 +260,7 @@ struct hc_driver { | |||
261 | #define HCD_USB25 0x0030 /* Wireless USB 1.0 (USB 2.5)*/ | 260 | #define HCD_USB25 0x0030 /* Wireless USB 1.0 (USB 2.5)*/ |
262 | #define HCD_USB3 0x0040 /* USB 3.0 */ | 261 | #define HCD_USB3 0x0040 /* USB 3.0 */ |
263 | #define HCD_USB31 0x0050 /* USB 3.1 */ | 262 | #define HCD_USB31 0x0050 /* USB 3.1 */ |
263 | #define HCD_USB32 0x0060 /* USB 3.2 */ | ||
264 | #define HCD_MASK 0x0070 | 264 | #define HCD_MASK 0x0070 |
265 | #define HCD_BH 0x0100 /* URB complete in BH context */ | 265 | #define HCD_BH 0x0100 /* URB complete in BH context */ |
266 | 266 | ||
diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h index 9eb908a98033..fc6c77918481 100644 --- a/include/linux/usb/musb.h +++ b/include/linux/usb/musb.h | |||
@@ -67,28 +67,13 @@ struct musb_hdrc_config { | |||
67 | /* MUSB configuration-specific details */ | 67 | /* MUSB configuration-specific details */ |
68 | unsigned multipoint:1; /* multipoint device */ | 68 | unsigned multipoint:1; /* multipoint device */ |
69 | unsigned dyn_fifo:1 __deprecated; /* supports dynamic fifo sizing */ | 69 | unsigned dyn_fifo:1 __deprecated; /* supports dynamic fifo sizing */ |
70 | unsigned soft_con:1 __deprecated; /* soft connect required */ | ||
71 | unsigned utm_16:1 __deprecated; /* utm data witdh is 16 bits */ | ||
72 | unsigned big_endian:1; /* true if CPU uses big-endian */ | ||
73 | unsigned mult_bulk_tx:1; /* Tx ep required for multbulk pkts */ | ||
74 | unsigned mult_bulk_rx:1; /* Rx ep required for multbulk pkts */ | ||
75 | unsigned high_iso_tx:1; /* Tx ep required for HB iso */ | ||
76 | unsigned high_iso_rx:1; /* Rx ep required for HD iso */ | ||
77 | unsigned dma:1 __deprecated; /* supports DMA */ | ||
78 | unsigned vendor_req:1 __deprecated; /* vendor registers required */ | ||
79 | 70 | ||
80 | /* need to explicitly de-assert the port reset after resume? */ | 71 | /* need to explicitly de-assert the port reset after resume? */ |
81 | unsigned host_port_deassert_reset_at_resume:1; | 72 | unsigned host_port_deassert_reset_at_resume:1; |
82 | 73 | ||
83 | u8 num_eps; /* number of endpoints _with_ ep0 */ | 74 | u8 num_eps; /* number of endpoints _with_ ep0 */ |
84 | u8 dma_channels __deprecated; /* number of dma channels */ | ||
85 | u8 dyn_fifo_size; /* dynamic size in bytes */ | ||
86 | u8 vendor_ctrl __deprecated; /* vendor control reg width */ | ||
87 | u8 vendor_stat __deprecated; /* vendor status reg witdh */ | ||
88 | u8 dma_req_chan __deprecated; /* bitmask for required dma channels */ | ||
89 | u8 ram_bits; /* ram address size */ | 75 | u8 ram_bits; /* ram address size */ |
90 | 76 | ||
91 | struct musb_hdrc_eps_bits *eps_bits __deprecated; | ||
92 | u32 maximum_speed; | 77 | u32 maximum_speed; |
93 | }; | 78 | }; |
94 | 79 | ||
diff --git a/include/linux/usb/pd.h b/include/linux/usb/pd.h index ff359bdfdc7b..09b570feb297 100644 --- a/include/linux/usb/pd.h +++ b/include/linux/usb/pd.h | |||
@@ -103,8 +103,8 @@ enum pd_ext_msg_type { | |||
103 | (((cnt) & PD_HEADER_CNT_MASK) << PD_HEADER_CNT_SHIFT) | \ | 103 | (((cnt) & PD_HEADER_CNT_MASK) << PD_HEADER_CNT_SHIFT) | \ |
104 | ((ext_hdr) ? PD_HEADER_EXT_HDR : 0)) | 104 | ((ext_hdr) ? PD_HEADER_EXT_HDR : 0)) |
105 | 105 | ||
106 | #define PD_HEADER_LE(type, pwr, data, id, cnt) \ | 106 | #define PD_HEADER_LE(type, pwr, data, rev, id, cnt) \ |
107 | cpu_to_le16(PD_HEADER((type), (pwr), (data), PD_REV20, (id), (cnt), (0))) | 107 | cpu_to_le16(PD_HEADER((type), (pwr), (data), (rev), (id), (cnt), (0))) |
108 | 108 | ||
109 | static inline unsigned int pd_header_cnt(u16 header) | 109 | static inline unsigned int pd_header_cnt(u16 header) |
110 | { | 110 | { |
diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h index b7a2625947f5..e4de6bc1f69b 100644 --- a/include/linux/usb/phy.h +++ b/include/linux/usb/phy.h | |||
@@ -157,22 +157,6 @@ struct usb_phy { | |||
157 | enum usb_charger_type (*charger_detect)(struct usb_phy *x); | 157 | enum usb_charger_type (*charger_detect)(struct usb_phy *x); |
158 | }; | 158 | }; |
159 | 159 | ||
160 | /** | ||
161 | * struct usb_phy_bind - represent the binding for the phy | ||
162 | * @dev_name: the device name of the device that will bind to the phy | ||
163 | * @phy_dev_name: the device name of the phy | ||
164 | * @index: used if a single controller uses multiple phys | ||
165 | * @phy: reference to the phy | ||
166 | * @list: to maintain a linked list of the binding information | ||
167 | */ | ||
168 | struct usb_phy_bind { | ||
169 | const char *dev_name; | ||
170 | const char *phy_dev_name; | ||
171 | u8 index; | ||
172 | struct usb_phy *phy; | ||
173 | struct list_head list; | ||
174 | }; | ||
175 | |||
176 | /* for board-specific init logic */ | 160 | /* for board-specific init logic */ |
177 | extern int usb_add_phy(struct usb_phy *, enum usb_phy_type type); | 161 | extern int usb_add_phy(struct usb_phy *, enum usb_phy_type type); |
178 | extern int usb_add_phy_dev(struct usb_phy *); | 162 | extern int usb_add_phy_dev(struct usb_phy *); |
@@ -234,16 +218,12 @@ usb_phy_vbus_off(struct usb_phy *x) | |||
234 | extern struct usb_phy *usb_get_phy(enum usb_phy_type type); | 218 | extern struct usb_phy *usb_get_phy(enum usb_phy_type type); |
235 | extern struct usb_phy *devm_usb_get_phy(struct device *dev, | 219 | extern struct usb_phy *devm_usb_get_phy(struct device *dev, |
236 | enum usb_phy_type type); | 220 | enum usb_phy_type type); |
237 | extern struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index); | ||
238 | extern struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index); | ||
239 | extern struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev, | 221 | extern struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev, |
240 | const char *phandle, u8 index); | 222 | const char *phandle, u8 index); |
241 | extern struct usb_phy *devm_usb_get_phy_by_node(struct device *dev, | 223 | extern struct usb_phy *devm_usb_get_phy_by_node(struct device *dev, |
242 | struct device_node *node, struct notifier_block *nb); | 224 | struct device_node *node, struct notifier_block *nb); |
243 | extern void usb_put_phy(struct usb_phy *); | 225 | extern void usb_put_phy(struct usb_phy *); |
244 | extern void devm_usb_put_phy(struct device *dev, struct usb_phy *x); | 226 | extern void devm_usb_put_phy(struct device *dev, struct usb_phy *x); |
245 | extern int usb_bind_phy(const char *dev_name, u8 index, | ||
246 | const char *phy_dev_name); | ||
247 | extern void usb_phy_set_event(struct usb_phy *x, unsigned long event); | 227 | extern void usb_phy_set_event(struct usb_phy *x, unsigned long event); |
248 | extern void usb_phy_set_charger_current(struct usb_phy *usb_phy, | 228 | extern void usb_phy_set_charger_current(struct usb_phy *usb_phy, |
249 | unsigned int mA); | 229 | unsigned int mA); |
@@ -263,16 +243,6 @@ static inline struct usb_phy *devm_usb_get_phy(struct device *dev, | |||
263 | return ERR_PTR(-ENXIO); | 243 | return ERR_PTR(-ENXIO); |
264 | } | 244 | } |
265 | 245 | ||
266 | static inline struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index) | ||
267 | { | ||
268 | return ERR_PTR(-ENXIO); | ||
269 | } | ||
270 | |||
271 | static inline struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index) | ||
272 | { | ||
273 | return ERR_PTR(-ENXIO); | ||
274 | } | ||
275 | |||
276 | static inline struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev, | 246 | static inline struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev, |
277 | const char *phandle, u8 index) | 247 | const char *phandle, u8 index) |
278 | { | 248 | { |
@@ -293,12 +263,6 @@ static inline void devm_usb_put_phy(struct device *dev, struct usb_phy *x) | |||
293 | { | 263 | { |
294 | } | 264 | } |
295 | 265 | ||
296 | static inline int usb_bind_phy(const char *dev_name, u8 index, | ||
297 | const char *phy_dev_name) | ||
298 | { | ||
299 | return -EOPNOTSUPP; | ||
300 | } | ||
301 | |||
302 | static inline void usb_phy_set_event(struct usb_phy *x, unsigned long event) | 266 | static inline void usb_phy_set_event(struct usb_phy *x, unsigned long event) |
303 | { | 267 | { |
304 | } | 268 | } |
diff --git a/include/linux/usb/tcpm.h b/include/linux/usb/tcpm.h index f0d839daeaea..b231b9314240 100644 --- a/include/linux/usb/tcpm.h +++ b/include/linux/usb/tcpm.h | |||
@@ -36,6 +36,7 @@ enum typec_cc_polarity { | |||
36 | /* Time to wait for TCPC to complete transmit */ | 36 | /* Time to wait for TCPC to complete transmit */ |
37 | #define PD_T_TCPC_TX_TIMEOUT 100 /* in ms */ | 37 | #define PD_T_TCPC_TX_TIMEOUT 100 /* in ms */ |
38 | #define PD_ROLE_SWAP_TIMEOUT (MSEC_PER_SEC * 10) | 38 | #define PD_ROLE_SWAP_TIMEOUT (MSEC_PER_SEC * 10) |
39 | #define PD_PPS_CTRL_TIMEOUT (MSEC_PER_SEC * 10) | ||
39 | 40 | ||
40 | enum tcpm_transmit_status { | 41 | enum tcpm_transmit_status { |
41 | TCPC_TX_SUCCESS = 0, | 42 | TCPC_TX_SUCCESS = 0, |
@@ -62,9 +63,6 @@ enum tcpm_transmit_type { | |||
62 | * @snk_pdo: PDO parameters sent to partner as response to | 63 | * @snk_pdo: PDO parameters sent to partner as response to |
63 | * PD_CTRL_GET_SINK_CAP message | 64 | * PD_CTRL_GET_SINK_CAP message |
64 | * @nr_snk_pdo: Number of entries in @snk_pdo | 65 | * @nr_snk_pdo: Number of entries in @snk_pdo |
65 | * @max_snk_mv: Maximum acceptable sink voltage in mV | ||
66 | * @max_snk_ma: Maximum sink current in mA | ||
67 | * @max_snk_mw: Maximum required sink power in mW | ||
68 | * @operating_snk_mw: | 66 | * @operating_snk_mw: |
69 | * Required operating sink power in mW | 67 | * Required operating sink power in mW |
70 | * @type: Port type (TYPEC_PORT_DFP, TYPEC_PORT_UFP, or | 68 | * @type: Port type (TYPEC_PORT_DFP, TYPEC_PORT_UFP, or |
@@ -85,9 +83,6 @@ struct tcpc_config { | |||
85 | const u32 *snk_vdo; | 83 | const u32 *snk_vdo; |
86 | unsigned int nr_snk_vdo; | 84 | unsigned int nr_snk_vdo; |
87 | 85 | ||
88 | unsigned int max_snk_mv; | ||
89 | unsigned int max_snk_ma; | ||
90 | unsigned int max_snk_mw; | ||
91 | unsigned int operating_snk_mw; | 86 | unsigned int operating_snk_mw; |
92 | 87 | ||
93 | enum typec_port_type type; | 88 | enum typec_port_type type; |
@@ -174,9 +169,6 @@ int tcpm_update_source_capabilities(struct tcpm_port *port, const u32 *pdo, | |||
174 | unsigned int nr_pdo); | 169 | unsigned int nr_pdo); |
175 | int tcpm_update_sink_capabilities(struct tcpm_port *port, const u32 *pdo, | 170 | int tcpm_update_sink_capabilities(struct tcpm_port *port, const u32 *pdo, |
176 | unsigned int nr_pdo, | 171 | unsigned int nr_pdo, |
177 | unsigned int max_snk_mv, | ||
178 | unsigned int max_snk_ma, | ||
179 | unsigned int max_snk_mw, | ||
180 | unsigned int operating_snk_mw); | 172 | unsigned int operating_snk_mw); |
181 | 173 | ||
182 | void tcpm_vbus_change(struct tcpm_port *port); | 174 | void tcpm_vbus_change(struct tcpm_port *port); |
diff --git a/include/linux/usb/tegra_usb_phy.h b/include/linux/usb/tegra_usb_phy.h index d641ea1660b7..0c5c3ea8b2d7 100644 --- a/include/linux/usb/tegra_usb_phy.h +++ b/include/linux/usb/tegra_usb_phy.h | |||
@@ -17,6 +17,7 @@ | |||
17 | #define __TEGRA_USB_PHY_H | 17 | #define __TEGRA_USB_PHY_H |
18 | 18 | ||
19 | #include <linux/clk.h> | 19 | #include <linux/clk.h> |
20 | #include <linux/reset.h> | ||
20 | #include <linux/usb/otg.h> | 21 | #include <linux/usb/otg.h> |
21 | 22 | ||
22 | /* | 23 | /* |
@@ -76,6 +77,7 @@ struct tegra_usb_phy { | |||
76 | bool is_legacy_phy; | 77 | bool is_legacy_phy; |
77 | bool is_ulpi_phy; | 78 | bool is_ulpi_phy; |
78 | int reset_gpio; | 79 | int reset_gpio; |
80 | struct reset_control *pad_rst; | ||
79 | }; | 81 | }; |
80 | 82 | ||
81 | void tegra_usb_phy_preresume(struct usb_phy *phy); | 83 | void tegra_usb_phy_preresume(struct usb_phy *phy); |
diff --git a/include/uapi/linux/usb/ch11.h b/include/uapi/linux/usb/ch11.h index 29c120c88747..fb0cd24c392c 100644 --- a/include/uapi/linux/usb/ch11.h +++ b/include/uapi/linux/usb/ch11.h | |||
@@ -197,6 +197,11 @@ struct usb_port_status { | |||
197 | #define USB_EXT_PORT_STAT_RX_LANES 0x00000f00 | 197 | #define USB_EXT_PORT_STAT_RX_LANES 0x00000f00 |
198 | #define USB_EXT_PORT_STAT_TX_LANES 0x0000f000 | 198 | #define USB_EXT_PORT_STAT_TX_LANES 0x0000f000 |
199 | 199 | ||
200 | #define USB_EXT_PORT_RX_LANES(p) \ | ||
201 | (((p) & USB_EXT_PORT_STAT_RX_LANES) >> 8) | ||
202 | #define USB_EXT_PORT_TX_LANES(p) \ | ||
203 | (((p) & USB_EXT_PORT_STAT_TX_LANES) >> 12) | ||
204 | |||
200 | /* | 205 | /* |
201 | * wHubCharacteristics (masks) | 206 | * wHubCharacteristics (masks) |
202 | * See USB 2.0 spec Table 11-13, offset 3 | 207 | * See USB 2.0 spec Table 11-13, offset 3 |
diff --git a/tools/testing/selftests/drivers/usb/usbip/usbip_test.sh b/tools/testing/selftests/drivers/usb/usbip/usbip_test.sh new file mode 100755 index 000000000000..1893d0f59ad7 --- /dev/null +++ b/tools/testing/selftests/drivers/usb/usbip/usbip_test.sh | |||
@@ -0,0 +1,198 @@ | |||
1 | #!/bin/bash | ||
2 | # SPDX-License-Identifier: GPL-2.0 | ||
3 | |||
4 | # Kselftest framework requirement - SKIP code is 4. | ||
5 | ksft_skip=4 | ||
6 | |||
7 | usage() { echo "usbip_test.sh -b <busid> -p <usbip tools path>"; exit 1; } | ||
8 | |||
9 | while getopts "h:b:p:" arg; do | ||
10 | case "${arg}" in | ||
11 | h) | ||
12 | usage | ||
13 | ;; | ||
14 | b) | ||
15 | busid=${OPTARG} | ||
16 | ;; | ||
17 | p) | ||
18 | tools_path=${OPTARG} | ||
19 | ;; | ||
20 | *) | ||
21 | usage | ||
22 | ;; | ||
23 | esac | ||
24 | done | ||
25 | shift $((OPTIND-1)) | ||
26 | |||
27 | if [ -z "${busid}" ]; then | ||
28 | usage | ||
29 | fi | ||
30 | |||
31 | echo "Running USB over IP Testing on $busid"; | ||
32 | |||
33 | test_end_msg="End of USB over IP Testing on $busid" | ||
34 | |||
35 | if [ $UID != 0 ]; then | ||
36 | echo "Please run usbip_test as root [SKIP]" | ||
37 | echo $test_end_msg | ||
38 | exit $ksft_skip | ||
39 | fi | ||
40 | |||
41 | echo "Load usbip_host module" | ||
42 | if ! /sbin/modprobe -q -n usbip_host; then | ||
43 | echo "usbip_test: module usbip_host is not found [SKIP]" | ||
44 | echo $test_end_msg | ||
45 | exit $ksft_skip | ||
46 | fi | ||
47 | |||
48 | if /sbin/modprobe -q usbip_host; then | ||
49 | /sbin/modprobe -q -r test_bitmap | ||
50 | echo "usbip_test: module usbip_host is loaded [OK]" | ||
51 | else | ||
52 | echo "usbip_test: module usbip_host failed to load [FAIL]" | ||
53 | echo $test_end_msg | ||
54 | exit 1 | ||
55 | fi | ||
56 | |||
57 | echo "Load vhci_hcd module" | ||
58 | if /sbin/modprobe -q vhci_hcd; then | ||
59 | /sbin/modprobe -q -r test_bitmap | ||
60 | echo "usbip_test: module vhci_hcd is loaded [OK]" | ||
61 | else | ||
62 | echo "usbip_test: module vhci_hcd failed to load [FAIL]" | ||
63 | echo $test_end_msg | ||
64 | exit 1 | ||
65 | fi | ||
66 | echo "==============================================================" | ||
67 | |||
68 | cd $tools_path; | ||
69 | |||
70 | if [ ! -f src/usbip ]; then | ||
71 | echo "Please build usbip tools" | ||
72 | echo $test_end_msg | ||
73 | exit $ksft_skip | ||
74 | fi | ||
75 | |||
76 | echo "Expect to see export-able devices"; | ||
77 | src/usbip list -l; | ||
78 | echo "==============================================================" | ||
79 | |||
80 | echo "Run lsusb to see all usb devices" | ||
81 | lsusb -t; | ||
82 | echo "==============================================================" | ||
83 | |||
84 | src/usbipd -D; | ||
85 | |||
86 | echo "Get exported devices from localhost - expect to see none"; | ||
87 | src/usbip list -r localhost; | ||
88 | echo "==============================================================" | ||
89 | |||
90 | echo "bind devices"; | ||
91 | src/usbip bind -b $busid; | ||
92 | echo "==============================================================" | ||
93 | |||
94 | echo "Run lsusb - bound devices should be under usbip_host control" | ||
95 | lsusb -t; | ||
96 | echo "==============================================================" | ||
97 | |||
98 | echo "bind devices - expect already bound messages" | ||
99 | src/usbip bind -b $busid; | ||
100 | echo "==============================================================" | ||
101 | |||
102 | echo "Get exported devices from localhost - expect to see exported devices"; | ||
103 | src/usbip list -r localhost; | ||
104 | echo "==============================================================" | ||
105 | |||
106 | echo "unbind devices"; | ||
107 | src/usbip unbind -b $busid; | ||
108 | echo "==============================================================" | ||
109 | |||
110 | echo "Run lsusb - bound devices should be rebound to original drivers" | ||
111 | lsusb -t; | ||
112 | echo "==============================================================" | ||
113 | |||
114 | echo "unbind devices - expect no devices bound message"; | ||
115 | src/usbip unbind -b $busid; | ||
116 | echo "==============================================================" | ||
117 | |||
118 | echo "Get exported devices from localhost - expect to see none"; | ||
119 | src/usbip list -r localhost; | ||
120 | echo "==============================================================" | ||
121 | |||
122 | echo "List imported devices - expect to see none"; | ||
123 | src/usbip port; | ||
124 | echo "==============================================================" | ||
125 | |||
126 | echo "Import devices from localhost - should fail with no devices" | ||
127 | src/usbip attach -r localhost -b $busid; | ||
128 | echo "==============================================================" | ||
129 | |||
130 | echo "bind devices"; | ||
131 | src/usbip bind -b $busid; | ||
132 | echo "==============================================================" | ||
133 | |||
134 | echo "List imported devices - expect to see exported devices"; | ||
135 | src/usbip list -r localhost; | ||
136 | echo "==============================================================" | ||
137 | |||
138 | echo "List imported devices - expect to see none"; | ||
139 | src/usbip port; | ||
140 | echo "==============================================================" | ||
141 | |||
142 | echo "Import devices from localhost - should work" | ||
143 | src/usbip attach -r localhost -b $busid; | ||
144 | echo "==============================================================" | ||
145 | |||
146 | echo "List imported devices - expect to see imported devices"; | ||
147 | src/usbip port; | ||
148 | echo "==============================================================" | ||
149 | |||
150 | echo "Import devices from localhost - expect already imported messages" | ||
151 | src/usbip attach -r localhost -b $busid; | ||
152 | echo "==============================================================" | ||
153 | |||
154 | echo "Un-import devices"; | ||
155 | src/usbip detach -p 00; | ||
156 | src/usbip detach -p 01; | ||
157 | echo "==============================================================" | ||
158 | |||
159 | echo "List imported devices - expect to see none"; | ||
160 | src/usbip port; | ||
161 | echo "==============================================================" | ||
162 | |||
163 | echo "Un-import devices - expect no devices to detach messages"; | ||
164 | src/usbip detach -p 00; | ||
165 | src/usbip detach -p 01; | ||
166 | echo "==============================================================" | ||
167 | |||
168 | echo "Detach invalid port tests - expect invalid port error message"; | ||
169 | src/usbip detach -p 100; | ||
170 | echo "==============================================================" | ||
171 | |||
172 | echo "Expect to see export-able devices"; | ||
173 | src/usbip list -l; | ||
174 | echo "==============================================================" | ||
175 | |||
176 | echo "Remove usbip_host module"; | ||
177 | rmmod usbip_host; | ||
178 | |||
179 | echo "Run lsusb - bound devices should be rebound to original drivers" | ||
180 | lsusb -t; | ||
181 | echo "==============================================================" | ||
182 | |||
183 | echo "Run bind without usbip_host - expect fail" | ||
184 | src/usbip bind -b $busid; | ||
185 | echo "==============================================================" | ||
186 | |||
187 | echo "Run lsusb - devices that failed to bind aren't bound to any driver" | ||
188 | lsusb -t; | ||
189 | echo "==============================================================" | ||
190 | |||
191 | echo "modprobe usbip_host - does it work?" | ||
192 | /sbin/modprobe usbip_host | ||
193 | echo "Should see -busid- is not in match_busid table... skip! dmesg" | ||
194 | echo "==============================================================" | ||
195 | dmesg | grep "is not in match_busid table" | ||
196 | echo "==============================================================" | ||
197 | |||
198 | echo $test_end_msg | ||
diff --git a/tools/usb/usbip/libsrc/vhci_driver.c b/tools/usb/usbip/libsrc/vhci_driver.c index c9c81614a66a..4204359c9fee 100644 --- a/tools/usb/usbip/libsrc/vhci_driver.c +++ b/tools/usb/usbip/libsrc/vhci_driver.c | |||
@@ -135,11 +135,11 @@ static int refresh_imported_device_list(void) | |||
135 | return 0; | 135 | return 0; |
136 | } | 136 | } |
137 | 137 | ||
138 | static int get_nports(void) | 138 | static int get_nports(struct udev_device *hc_device) |
139 | { | 139 | { |
140 | const char *attr_nports; | 140 | const char *attr_nports; |
141 | 141 | ||
142 | attr_nports = udev_device_get_sysattr_value(vhci_driver->hc_device, "nports"); | 142 | attr_nports = udev_device_get_sysattr_value(hc_device, "nports"); |
143 | if (!attr_nports) { | 143 | if (!attr_nports) { |
144 | err("udev_device_get_sysattr_value nports failed"); | 144 | err("udev_device_get_sysattr_value nports failed"); |
145 | return -1; | 145 | return -1; |
@@ -242,35 +242,41 @@ static int read_record(int rhport, char *host, unsigned long host_len, | |||
242 | 242 | ||
243 | int usbip_vhci_driver_open(void) | 243 | int usbip_vhci_driver_open(void) |
244 | { | 244 | { |
245 | int nports; | ||
246 | struct udev_device *hc_device; | ||
247 | |||
245 | udev_context = udev_new(); | 248 | udev_context = udev_new(); |
246 | if (!udev_context) { | 249 | if (!udev_context) { |
247 | err("udev_new failed"); | 250 | err("udev_new failed"); |
248 | return -1; | 251 | return -1; |
249 | } | 252 | } |
250 | 253 | ||
251 | vhci_driver = calloc(1, sizeof(struct usbip_vhci_driver)); | ||
252 | |||
253 | /* will be freed in usbip_driver_close() */ | 254 | /* will be freed in usbip_driver_close() */ |
254 | vhci_driver->hc_device = | 255 | hc_device = |
255 | udev_device_new_from_subsystem_sysname(udev_context, | 256 | udev_device_new_from_subsystem_sysname(udev_context, |
256 | USBIP_VHCI_BUS_TYPE, | 257 | USBIP_VHCI_BUS_TYPE, |
257 | USBIP_VHCI_DEVICE_NAME); | 258 | USBIP_VHCI_DEVICE_NAME); |
258 | if (!vhci_driver->hc_device) { | 259 | if (!hc_device) { |
259 | err("udev_device_new_from_subsystem_sysname failed"); | 260 | err("udev_device_new_from_subsystem_sysname failed"); |
260 | goto err; | 261 | goto err; |
261 | } | 262 | } |
262 | 263 | ||
263 | vhci_driver->nports = get_nports(); | 264 | nports = get_nports(hc_device); |
264 | dbg("available ports: %d", vhci_driver->nports); | 265 | if (nports <= 0) { |
265 | |||
266 | if (vhci_driver->nports <= 0) { | ||
267 | err("no available ports"); | 266 | err("no available ports"); |
268 | goto err; | 267 | goto err; |
269 | } else if (vhci_driver->nports > MAXNPORT) { | 268 | } |
270 | err("port number exceeds %d", MAXNPORT); | 269 | dbg("available ports: %d", nports); |
270 | |||
271 | vhci_driver = calloc(1, sizeof(struct usbip_vhci_driver) + | ||
272 | nports * sizeof(struct usbip_imported_device)); | ||
273 | if (!vhci_driver) { | ||
274 | err("vhci_driver allocation failed"); | ||
271 | goto err; | 275 | goto err; |
272 | } | 276 | } |
273 | 277 | ||
278 | vhci_driver->nports = nports; | ||
279 | vhci_driver->hc_device = hc_device; | ||
274 | vhci_driver->ncontrollers = get_ncontrollers(); | 280 | vhci_driver->ncontrollers = get_ncontrollers(); |
275 | dbg("available controllers: %d", vhci_driver->ncontrollers); | 281 | dbg("available controllers: %d", vhci_driver->ncontrollers); |
276 | 282 | ||
@@ -285,7 +291,7 @@ int usbip_vhci_driver_open(void) | |||
285 | return 0; | 291 | return 0; |
286 | 292 | ||
287 | err: | 293 | err: |
288 | udev_device_unref(vhci_driver->hc_device); | 294 | udev_device_unref(hc_device); |
289 | 295 | ||
290 | if (vhci_driver) | 296 | if (vhci_driver) |
291 | free(vhci_driver); | 297 | free(vhci_driver); |
diff --git a/tools/usb/usbip/libsrc/vhci_driver.h b/tools/usb/usbip/libsrc/vhci_driver.h index 418b404d5121..6c9aca216705 100644 --- a/tools/usb/usbip/libsrc/vhci_driver.h +++ b/tools/usb/usbip/libsrc/vhci_driver.h | |||
@@ -13,7 +13,6 @@ | |||
13 | 13 | ||
14 | #define USBIP_VHCI_BUS_TYPE "platform" | 14 | #define USBIP_VHCI_BUS_TYPE "platform" |
15 | #define USBIP_VHCI_DEVICE_NAME "vhci_hcd.0" | 15 | #define USBIP_VHCI_DEVICE_NAME "vhci_hcd.0" |
16 | #define MAXNPORT 128 | ||
17 | 16 | ||
18 | enum hub_speed { | 17 | enum hub_speed { |
19 | HUB_SPEED_HIGH = 0, | 18 | HUB_SPEED_HIGH = 0, |
@@ -41,7 +40,7 @@ struct usbip_vhci_driver { | |||
41 | 40 | ||
42 | int ncontrollers; | 41 | int ncontrollers; |
43 | int nports; | 42 | int nports; |
44 | struct usbip_imported_device idev[MAXNPORT]; | 43 | struct usbip_imported_device idev[]; |
45 | }; | 44 | }; |
46 | 45 | ||
47 | 46 | ||
diff --git a/tools/usb/usbip/src/usbip_detach.c b/tools/usb/usbip/src/usbip_detach.c index 9db9d21bb2ec..777f7286a0c5 100644 --- a/tools/usb/usbip/src/usbip_detach.c +++ b/tools/usb/usbip/src/usbip_detach.c | |||
@@ -43,9 +43,12 @@ void usbip_detach_usage(void) | |||
43 | 43 | ||
44 | static int detach_port(char *port) | 44 | static int detach_port(char *port) |
45 | { | 45 | { |
46 | int ret; | 46 | int ret = 0; |
47 | uint8_t portnum; | 47 | uint8_t portnum; |
48 | char path[PATH_MAX+1]; | 48 | char path[PATH_MAX+1]; |
49 | int i; | ||
50 | struct usbip_imported_device *idev; | ||
51 | int found = 0; | ||
49 | 52 | ||
50 | unsigned int port_len = strlen(port); | 53 | unsigned int port_len = strlen(port); |
51 | 54 | ||
@@ -55,27 +58,48 @@ static int detach_port(char *port) | |||
55 | return -1; | 58 | return -1; |
56 | } | 59 | } |
57 | 60 | ||
58 | /* check max port */ | ||
59 | |||
60 | portnum = atoi(port); | 61 | portnum = atoi(port); |
61 | 62 | ||
62 | /* remove the port state file */ | 63 | ret = usbip_vhci_driver_open(); |
64 | if (ret < 0) { | ||
65 | err("open vhci_driver"); | ||
66 | return -1; | ||
67 | } | ||
68 | |||
69 | /* check for invalid port */ | ||
70 | for (i = 0; i < vhci_driver->nports; i++) { | ||
71 | idev = &vhci_driver->idev[i]; | ||
72 | |||
73 | if (idev->port == portnum) { | ||
74 | found = 1; | ||
75 | if (idev->status != VDEV_ST_NULL) | ||
76 | break; | ||
77 | info("Port %d is already detached!\n", idev->port); | ||
78 | goto call_driver_close; | ||
79 | } | ||
80 | } | ||
63 | 81 | ||
82 | if (!found) { | ||
83 | err("Invalid port %s > maxports %d", | ||
84 | port, vhci_driver->nports); | ||
85 | goto call_driver_close; | ||
86 | } | ||
87 | |||
88 | /* remove the port state file */ | ||
64 | snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", portnum); | 89 | snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", portnum); |
65 | 90 | ||
66 | remove(path); | 91 | remove(path); |
67 | rmdir(VHCI_STATE_PATH); | 92 | rmdir(VHCI_STATE_PATH); |
68 | 93 | ||
69 | ret = usbip_vhci_driver_open(); | 94 | ret = usbip_vhci_detach_device(portnum); |
70 | if (ret < 0) { | 95 | if (ret < 0) { |
71 | err("open vhci_driver"); | 96 | ret = -1; |
72 | return -1; | 97 | err("Port %d detach request failed!\n", portnum); |
98 | goto call_driver_close; | ||
73 | } | 99 | } |
100 | info("Port %d is now detached!\n", portnum); | ||
74 | 101 | ||
75 | ret = usbip_vhci_detach_device(portnum); | 102 | call_driver_close: |
76 | if (ret < 0) | ||
77 | return -1; | ||
78 | |||
79 | usbip_vhci_driver_close(); | 103 | usbip_vhci_driver_close(); |
80 | 104 | ||
81 | return ret; | 105 | return ret; |