xref: /linux/drivers/usb/dwc3/debug.h (revision 5fd54ace4721fc5ce2bb5aef6318fcf17f421460)
1 // SPDX-License-Identifier: GPL-2.0
2 /**
3  * debug.h - DesignWare USB3 DRD Controller Debug Header
4  *
5  * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
6  *
7  * Authors: Felipe Balbi <balbi@ti.com>,
8  *	    Sebastian Andrzej Siewior <bigeasy@linutronix.de>
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2  of
12  * the License as published by the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  */
19 
20 #ifndef __DWC3_DEBUG_H
21 #define __DWC3_DEBUG_H
22 
23 #include "core.h"
24 
25 /**
26  * dwc3_gadget_ep_cmd_string - returns endpoint command string
27  * @cmd: command code
28  */
29 static inline const char *
30 dwc3_gadget_ep_cmd_string(u8 cmd)
31 {
32 	switch (cmd) {
33 	case DWC3_DEPCMD_DEPSTARTCFG:
34 		return "Start New Configuration";
35 	case DWC3_DEPCMD_ENDTRANSFER:
36 		return "End Transfer";
37 	case DWC3_DEPCMD_UPDATETRANSFER:
38 		return "Update Transfer";
39 	case DWC3_DEPCMD_STARTTRANSFER:
40 		return "Start Transfer";
41 	case DWC3_DEPCMD_CLEARSTALL:
42 		return "Clear Stall";
43 	case DWC3_DEPCMD_SETSTALL:
44 		return "Set Stall";
45 	case DWC3_DEPCMD_GETEPSTATE:
46 		return "Get Endpoint State";
47 	case DWC3_DEPCMD_SETTRANSFRESOURCE:
48 		return "Set Endpoint Transfer Resource";
49 	case DWC3_DEPCMD_SETEPCONFIG:
50 		return "Set Endpoint Configuration";
51 	default:
52 		return "UNKNOWN command";
53 	}
54 }
55 
56 /**
57  * dwc3_gadget_generic_cmd_string - returns generic command string
58  * @cmd: command code
59  */
60 static inline const char *
61 dwc3_gadget_generic_cmd_string(u8 cmd)
62 {
63 	switch (cmd) {
64 	case DWC3_DGCMD_SET_LMP:
65 		return "Set LMP";
66 	case DWC3_DGCMD_SET_PERIODIC_PAR:
67 		return "Set Periodic Parameters";
68 	case DWC3_DGCMD_XMIT_FUNCTION:
69 		return "Transmit Function Wake Device Notification";
70 	case DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO:
71 		return "Set Scratchpad Buffer Array Address Lo";
72 	case DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI:
73 		return "Set Scratchpad Buffer Array Address Hi";
74 	case DWC3_DGCMD_SELECTED_FIFO_FLUSH:
75 		return "Selected FIFO Flush";
76 	case DWC3_DGCMD_ALL_FIFO_FLUSH:
77 		return "All FIFO Flush";
78 	case DWC3_DGCMD_SET_ENDPOINT_NRDY:
79 		return "Set Endpoint NRDY";
80 	case DWC3_DGCMD_RUN_SOC_BUS_LOOPBACK:
81 		return "Run SoC Bus Loopback Test";
82 	default:
83 		return "UNKNOWN";
84 	}
85 }
86 
87 /**
88  * dwc3_gadget_link_string - returns link name
89  * @link_state: link state code
90  */
91 static inline const char *
92 dwc3_gadget_link_string(enum dwc3_link_state link_state)
93 {
94 	switch (link_state) {
95 	case DWC3_LINK_STATE_U0:
96 		return "U0";
97 	case DWC3_LINK_STATE_U1:
98 		return "U1";
99 	case DWC3_LINK_STATE_U2:
100 		return "U2";
101 	case DWC3_LINK_STATE_U3:
102 		return "U3";
103 	case DWC3_LINK_STATE_SS_DIS:
104 		return "SS.Disabled";
105 	case DWC3_LINK_STATE_RX_DET:
106 		return "RX.Detect";
107 	case DWC3_LINK_STATE_SS_INACT:
108 		return "SS.Inactive";
109 	case DWC3_LINK_STATE_POLL:
110 		return "Polling";
111 	case DWC3_LINK_STATE_RECOV:
112 		return "Recovery";
113 	case DWC3_LINK_STATE_HRESET:
114 		return "Hot Reset";
115 	case DWC3_LINK_STATE_CMPLY:
116 		return "Compliance";
117 	case DWC3_LINK_STATE_LPBK:
118 		return "Loopback";
119 	case DWC3_LINK_STATE_RESET:
120 		return "Reset";
121 	case DWC3_LINK_STATE_RESUME:
122 		return "Resume";
123 	default:
124 		return "UNKNOWN link state\n";
125 	}
126 }
127 
128 /**
129  * dwc3_trb_type_string - returns TRB type as a string
130  * @type: the type of the TRB
131  */
132 static inline const char *dwc3_trb_type_string(unsigned int type)
133 {
134 	switch (type) {
135 	case DWC3_TRBCTL_NORMAL:
136 		return "normal";
137 	case DWC3_TRBCTL_CONTROL_SETUP:
138 		return "setup";
139 	case DWC3_TRBCTL_CONTROL_STATUS2:
140 		return "status2";
141 	case DWC3_TRBCTL_CONTROL_STATUS3:
142 		return "status3";
143 	case DWC3_TRBCTL_CONTROL_DATA:
144 		return "data";
145 	case DWC3_TRBCTL_ISOCHRONOUS_FIRST:
146 		return "isoc-first";
147 	case DWC3_TRBCTL_ISOCHRONOUS:
148 		return "isoc";
149 	case DWC3_TRBCTL_LINK_TRB:
150 		return "link";
151 	default:
152 		return "UNKNOWN";
153 	}
154 }
155 
156 static inline const char *dwc3_ep0_state_string(enum dwc3_ep0_state state)
157 {
158 	switch (state) {
159 	case EP0_UNCONNECTED:
160 		return "Unconnected";
161 	case EP0_SETUP_PHASE:
162 		return "Setup Phase";
163 	case EP0_DATA_PHASE:
164 		return "Data Phase";
165 	case EP0_STATUS_PHASE:
166 		return "Status Phase";
167 	default:
168 		return "UNKNOWN";
169 	}
170 }
171 
172 /**
173  * dwc3_gadget_event_string - returns event name
174  * @event: the event code
175  */
176 static inline const char *
177 dwc3_gadget_event_string(char *str, const struct dwc3_event_devt *event)
178 {
179 	enum dwc3_link_state state = event->event_info & DWC3_LINK_STATE_MASK;
180 
181 	switch (event->type) {
182 	case DWC3_DEVICE_EVENT_DISCONNECT:
183 		sprintf(str, "Disconnect: [%s]",
184 				dwc3_gadget_link_string(state));
185 		break;
186 	case DWC3_DEVICE_EVENT_RESET:
187 		sprintf(str, "Reset [%s]", dwc3_gadget_link_string(state));
188 		break;
189 	case DWC3_DEVICE_EVENT_CONNECT_DONE:
190 		sprintf(str, "Connection Done [%s]",
191 				dwc3_gadget_link_string(state));
192 		break;
193 	case DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE:
194 		sprintf(str, "Link Change [%s]",
195 				dwc3_gadget_link_string(state));
196 		break;
197 	case DWC3_DEVICE_EVENT_WAKEUP:
198 		sprintf(str, "WakeUp [%s]", dwc3_gadget_link_string(state));
199 		break;
200 	case DWC3_DEVICE_EVENT_EOPF:
201 		sprintf(str, "End-Of-Frame [%s]",
202 				dwc3_gadget_link_string(state));
203 		break;
204 	case DWC3_DEVICE_EVENT_SOF:
205 		sprintf(str, "Start-Of-Frame [%s]",
206 				dwc3_gadget_link_string(state));
207 		break;
208 	case DWC3_DEVICE_EVENT_ERRATIC_ERROR:
209 		sprintf(str, "Erratic Error [%s]",
210 				dwc3_gadget_link_string(state));
211 		break;
212 	case DWC3_DEVICE_EVENT_CMD_CMPL:
213 		sprintf(str, "Command Complete [%s]",
214 				dwc3_gadget_link_string(state));
215 		break;
216 	case DWC3_DEVICE_EVENT_OVERFLOW:
217 		sprintf(str, "Overflow [%s]", dwc3_gadget_link_string(state));
218 		break;
219 	default:
220 		sprintf(str, "UNKNOWN");
221 	}
222 
223 	return str;
224 }
225 
226 static inline void dwc3_decode_get_status(__u8 t, __u16 i, __u16 l, char *str)
227 {
228 	switch (t & USB_RECIP_MASK) {
229 	case USB_RECIP_INTERFACE:
230 		sprintf(str, "Get Interface Status(Intf = %d, Length = %d)",
231 			i, l);
232 		break;
233 	case USB_RECIP_ENDPOINT:
234 		sprintf(str, "Get Endpoint Status(ep%d%s)",
235 			i & ~USB_DIR_IN,
236 			i & USB_DIR_IN ? "in" : "out");
237 		break;
238 	}
239 }
240 
241 static inline void dwc3_decode_set_clear_feature(__u8 t, __u8 b, __u16 v,
242 						 __u16 i, char *str)
243 {
244 	switch (t & USB_RECIP_MASK) {
245 	case USB_RECIP_DEVICE:
246 		sprintf(str, "%s Device Feature(%s%s)",
247 			b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set",
248 			({char *s;
249 				switch (v) {
250 				case USB_DEVICE_SELF_POWERED:
251 					s = "Self Powered";
252 					break;
253 				case USB_DEVICE_REMOTE_WAKEUP:
254 					s = "Remote Wakeup";
255 					break;
256 				case USB_DEVICE_TEST_MODE:
257 					s = "Test Mode";
258 					break;
259 				default:
260 					s = "UNKNOWN";
261 				} s; }),
262 			v == USB_DEVICE_TEST_MODE ?
263 			({ char *s;
264 				switch (i) {
265 				case TEST_J:
266 					s = ": TEST_J";
267 					break;
268 				case TEST_K:
269 					s = ": TEST_K";
270 					break;
271 				case TEST_SE0_NAK:
272 					s = ": TEST_SE0_NAK";
273 					break;
274 				case TEST_PACKET:
275 					s = ": TEST_PACKET";
276 					break;
277 				case TEST_FORCE_EN:
278 					s = ": TEST_FORCE_EN";
279 					break;
280 				default:
281 					s = ": UNKNOWN";
282 				} s; }) : "");
283 		break;
284 	case USB_RECIP_INTERFACE:
285 		sprintf(str, "%s Interface Feature(%s)",
286 			b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set",
287 			v == USB_INTRF_FUNC_SUSPEND ?
288 			"Function Suspend" : "UNKNOWN");
289 		break;
290 	case USB_RECIP_ENDPOINT:
291 		sprintf(str, "%s Endpoint Feature(%s ep%d%s)",
292 			b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set",
293 			v == USB_ENDPOINT_HALT ? "Halt" : "UNKNOWN",
294 			i & ~USB_DIR_IN,
295 			i & USB_DIR_IN ? "in" : "out");
296 		break;
297 	}
298 }
299 
300 static inline void dwc3_decode_set_address(__u16 v, char *str)
301 {
302 	sprintf(str, "Set Address(Addr = %02x)", v);
303 }
304 
305 static inline void dwc3_decode_get_set_descriptor(__u8 t, __u8 b, __u16 v,
306 						  __u16 i, __u16 l, char *str)
307 {
308 	sprintf(str, "%s %s Descriptor(Index = %d, Length = %d)",
309 		b == USB_REQ_GET_DESCRIPTOR ? "Get" : "Set",
310 		({ char *s;
311 			switch (v >> 8) {
312 			case USB_DT_DEVICE:
313 				s = "Device";
314 				break;
315 			case USB_DT_CONFIG:
316 				s = "Configuration";
317 				break;
318 			case USB_DT_STRING:
319 				s = "String";
320 				break;
321 			case USB_DT_INTERFACE:
322 				s = "Interface";
323 				break;
324 			case USB_DT_ENDPOINT:
325 				s = "Endpoint";
326 				break;
327 			case USB_DT_DEVICE_QUALIFIER:
328 				s = "Device Qualifier";
329 				break;
330 			case USB_DT_OTHER_SPEED_CONFIG:
331 				s = "Other Speed Config";
332 				break;
333 			case USB_DT_INTERFACE_POWER:
334 				s = "Interface Power";
335 				break;
336 			case USB_DT_OTG:
337 				s = "OTG";
338 				break;
339 			case USB_DT_DEBUG:
340 				s = "Debug";
341 				break;
342 			case USB_DT_INTERFACE_ASSOCIATION:
343 				s = "Interface Association";
344 				break;
345 			case USB_DT_BOS:
346 				s = "BOS";
347 				break;
348 			case USB_DT_DEVICE_CAPABILITY:
349 				s = "Device Capability";
350 				break;
351 			case USB_DT_PIPE_USAGE:
352 				s = "Pipe Usage";
353 				break;
354 			case USB_DT_SS_ENDPOINT_COMP:
355 				s = "SS Endpoint Companion";
356 				break;
357 			case USB_DT_SSP_ISOC_ENDPOINT_COMP:
358 				s = "SSP Isochronous Endpoint Companion";
359 				break;
360 			default:
361 				s = "UNKNOWN";
362 				break;
363 			} s; }), v & 0xff, l);
364 }
365 
366 
367 static inline void dwc3_decode_get_configuration(__u16 l, char *str)
368 {
369 	sprintf(str, "Get Configuration(Length = %d)", l);
370 }
371 
372 static inline void dwc3_decode_set_configuration(__u8 v, char *str)
373 {
374 	sprintf(str, "Set Configuration(Config = %d)", v);
375 }
376 
377 static inline void dwc3_decode_get_intf(__u16 i, __u16 l, char *str)
378 {
379 	sprintf(str, "Get Interface(Intf = %d, Length = %d)", i, l);
380 }
381 
382 static inline void dwc3_decode_set_intf(__u8 v, __u16 i, char *str)
383 {
384 	sprintf(str, "Set Interface(Intf = %d, Alt.Setting = %d)", i, v);
385 }
386 
387 static inline void dwc3_decode_synch_frame(__u16 i, __u16 l, char *str)
388 {
389 	sprintf(str, "Synch Frame(Endpoint = %d, Length = %d)", i, l);
390 }
391 
392 static inline void dwc3_decode_set_sel(__u16 l, char *str)
393 {
394 	sprintf(str, "Set SEL(Length = %d)", l);
395 }
396 
397 static inline void dwc3_decode_set_isoch_delay(__u8 v, char *str)
398 {
399 	sprintf(str, "Set Isochronous Delay(Delay = %d ns)", v);
400 }
401 
402 /**
403  * dwc3_decode_ctrl - returns a string represetion of ctrl request
404  */
405 static inline const char *dwc3_decode_ctrl(char *str, __u8 bRequestType,
406 		__u8 bRequest, __u16 wValue, __u16 wIndex, __u16 wLength)
407 {
408 	switch (bRequest) {
409 	case USB_REQ_GET_STATUS:
410 		dwc3_decode_get_status(bRequestType, wIndex, wLength, str);
411 		break;
412 	case USB_REQ_CLEAR_FEATURE:
413 	case USB_REQ_SET_FEATURE:
414 		dwc3_decode_set_clear_feature(bRequestType, bRequest, wValue,
415 					      wIndex, str);
416 		break;
417 	case USB_REQ_SET_ADDRESS:
418 		dwc3_decode_set_address(wValue, str);
419 		break;
420 	case USB_REQ_GET_DESCRIPTOR:
421 	case USB_REQ_SET_DESCRIPTOR:
422 		dwc3_decode_get_set_descriptor(bRequestType, bRequest, wValue,
423 					       wIndex, wLength, str);
424 		break;
425 	case USB_REQ_GET_CONFIGURATION:
426 		dwc3_decode_get_configuration(wLength, str);
427 		break;
428 	case USB_REQ_SET_CONFIGURATION:
429 		dwc3_decode_set_configuration(wValue, str);
430 		break;
431 	case USB_REQ_GET_INTERFACE:
432 		dwc3_decode_get_intf(wIndex, wLength, str);
433 		break;
434 	case USB_REQ_SET_INTERFACE:
435 		dwc3_decode_set_intf(wValue, wIndex, str);
436 		break;
437 	case USB_REQ_SYNCH_FRAME:
438 		dwc3_decode_synch_frame(wIndex, wLength, str);
439 		break;
440 	case USB_REQ_SET_SEL:
441 		dwc3_decode_set_sel(wLength, str);
442 		break;
443 	case USB_REQ_SET_ISOCH_DELAY:
444 		dwc3_decode_set_isoch_delay(wValue, str);
445 		break;
446 	default:
447 		sprintf(str, "%02x %02x %02x %02x %02x %02x %02x %02x",
448 			bRequestType, bRequest,
449 			cpu_to_le16(wValue) & 0xff,
450 			cpu_to_le16(wValue) >> 8,
451 			cpu_to_le16(wIndex) & 0xff,
452 			cpu_to_le16(wIndex) >> 8,
453 			cpu_to_le16(wLength) & 0xff,
454 			cpu_to_le16(wLength) >> 8);
455 	}
456 
457 	return str;
458 }
459 
460 /**
461  * dwc3_ep_event_string - returns event name
462  * @event: then event code
463  */
464 static inline const char *
465 dwc3_ep_event_string(char *str, const struct dwc3_event_depevt *event,
466 		     u32 ep0state)
467 {
468 	u8 epnum = event->endpoint_number;
469 	size_t len;
470 	int status;
471 	int ret;
472 
473 	ret = sprintf(str, "ep%d%s: ", epnum >> 1,
474 			(epnum & 1) ? "in" : "out");
475 	if (ret < 0)
476 		return "UNKNOWN";
477 
478 	switch (event->endpoint_event) {
479 	case DWC3_DEPEVT_XFERCOMPLETE:
480 		strcat(str, "Transfer Complete");
481 		len = strlen(str);
482 
483 		if (epnum <= 1)
484 			sprintf(str + len, " [%s]", dwc3_ep0_state_string(ep0state));
485 		break;
486 	case DWC3_DEPEVT_XFERINPROGRESS:
487 		strcat(str, "Transfer In-Progress");
488 		break;
489 	case DWC3_DEPEVT_XFERNOTREADY:
490 		strcat(str, "Transfer Not Ready");
491 		status = event->status & DEPEVT_STATUS_TRANSFER_ACTIVE;
492 		strcat(str, status ? " (Active)" : " (Not Active)");
493 
494 		/* Control Endpoints */
495 		if (epnum <= 1) {
496 			int phase = DEPEVT_STATUS_CONTROL_PHASE(event->status);
497 
498 			switch (phase) {
499 			case DEPEVT_STATUS_CONTROL_DATA:
500 				strcat(str, " [Data Phase]");
501 				break;
502 			case DEPEVT_STATUS_CONTROL_STATUS:
503 				strcat(str, " [Status Phase]");
504 			}
505 		}
506 		break;
507 	case DWC3_DEPEVT_RXTXFIFOEVT:
508 		strcat(str, "FIFO");
509 		break;
510 	case DWC3_DEPEVT_STREAMEVT:
511 		status = event->status;
512 
513 		switch (status) {
514 		case DEPEVT_STREAMEVT_FOUND:
515 			sprintf(str + ret, " Stream %d Found",
516 					event->parameters);
517 			break;
518 		case DEPEVT_STREAMEVT_NOTFOUND:
519 		default:
520 			strcat(str, " Stream Not Found");
521 			break;
522 		}
523 
524 		break;
525 	case DWC3_DEPEVT_EPCMDCMPLT:
526 		strcat(str, "Endpoint Command Complete");
527 		break;
528 	default:
529 		sprintf(str, "UNKNOWN");
530 	}
531 
532 	return str;
533 }
534 
535 /**
536  * dwc3_gadget_event_type_string - return event name
537  * @event: the event code
538  */
539 static inline const char *dwc3_gadget_event_type_string(u8 event)
540 {
541 	switch (event) {
542 	case DWC3_DEVICE_EVENT_DISCONNECT:
543 		return "Disconnect";
544 	case DWC3_DEVICE_EVENT_RESET:
545 		return "Reset";
546 	case DWC3_DEVICE_EVENT_CONNECT_DONE:
547 		return "Connect Done";
548 	case DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE:
549 		return "Link Status Change";
550 	case DWC3_DEVICE_EVENT_WAKEUP:
551 		return "Wake-Up";
552 	case DWC3_DEVICE_EVENT_HIBER_REQ:
553 		return "Hibernation";
554 	case DWC3_DEVICE_EVENT_EOPF:
555 		return "End of Periodic Frame";
556 	case DWC3_DEVICE_EVENT_SOF:
557 		return "Start of Frame";
558 	case DWC3_DEVICE_EVENT_ERRATIC_ERROR:
559 		return "Erratic Error";
560 	case DWC3_DEVICE_EVENT_CMD_CMPL:
561 		return "Command Complete";
562 	case DWC3_DEVICE_EVENT_OVERFLOW:
563 		return "Overflow";
564 	default:
565 		return "UNKNOWN";
566 	}
567 }
568 
569 static inline const char *dwc3_decode_event(char *str, u32 event, u32 ep0state)
570 {
571 	const union dwc3_event evt = (union dwc3_event) event;
572 
573 	if (evt.type.is_devspec)
574 		return dwc3_gadget_event_string(str, &evt.devt);
575 	else
576 		return dwc3_ep_event_string(str, &evt.depevt, ep0state);
577 }
578 
579 static inline const char *dwc3_ep_cmd_status_string(int status)
580 {
581 	switch (status) {
582 	case -ETIMEDOUT:
583 		return "Timed Out";
584 	case 0:
585 		return "Successful";
586 	case DEPEVT_TRANSFER_NO_RESOURCE:
587 		return "No Resource";
588 	case DEPEVT_TRANSFER_BUS_EXPIRY:
589 		return "Bus Expiry";
590 	default:
591 		return "UNKNOWN";
592 	}
593 }
594 
595 static inline const char *dwc3_gadget_generic_cmd_status_string(int status)
596 {
597 	switch (status) {
598 	case -ETIMEDOUT:
599 		return "Timed Out";
600 	case 0:
601 		return "Successful";
602 	case 1:
603 		return "Error";
604 	default:
605 		return "UNKNOWN";
606 	}
607 }
608 
609 
610 #ifdef CONFIG_DEBUG_FS
611 extern void dwc3_debugfs_init(struct dwc3 *);
612 extern void dwc3_debugfs_exit(struct dwc3 *);
613 #else
614 static inline void dwc3_debugfs_init(struct dwc3 *d)
615 {  }
616 static inline void dwc3_debugfs_exit(struct dwc3 *d)
617 {  }
618 #endif
619 #endif /* __DWC3_DEBUG_H */
620