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