1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Cadence CDNSP DRD Driver. 4 * 5 * Copyright (C) 2020 Cadence. 6 * 7 * Author: Pawel Laszczak <pawell@cadence.com> 8 * 9 */ 10 #ifndef __LINUX_CDNSP_DEBUG 11 #define __LINUX_CDNSP_DEBUG 12 13 static inline const char *cdnsp_trb_comp_code_string(u8 status) 14 { 15 switch (status) { 16 case COMP_INVALID: 17 return "Invalid"; 18 case COMP_SUCCESS: 19 return "Success"; 20 case COMP_DATA_BUFFER_ERROR: 21 return "Data Buffer Error"; 22 case COMP_BABBLE_DETECTED_ERROR: 23 return "Babble Detected"; 24 case COMP_TRB_ERROR: 25 return "TRB Error"; 26 case COMP_RESOURCE_ERROR: 27 return "Resource Error"; 28 case COMP_NO_SLOTS_AVAILABLE_ERROR: 29 return "No Slots Available Error"; 30 case COMP_INVALID_STREAM_TYPE_ERROR: 31 return "Invalid Stream Type Error"; 32 case COMP_SLOT_NOT_ENABLED_ERROR: 33 return "Slot Not Enabled Error"; 34 case COMP_ENDPOINT_NOT_ENABLED_ERROR: 35 return "Endpoint Not Enabled Error"; 36 case COMP_SHORT_PACKET: 37 return "Short Packet"; 38 case COMP_RING_UNDERRUN: 39 return "Ring Underrun"; 40 case COMP_RING_OVERRUN: 41 return "Ring Overrun"; 42 case COMP_VF_EVENT_RING_FULL_ERROR: 43 return "VF Event Ring Full Error"; 44 case COMP_PARAMETER_ERROR: 45 return "Parameter Error"; 46 case COMP_CONTEXT_STATE_ERROR: 47 return "Context State Error"; 48 case COMP_EVENT_RING_FULL_ERROR: 49 return "Event Ring Full Error"; 50 case COMP_INCOMPATIBLE_DEVICE_ERROR: 51 return "Incompatible Device Error"; 52 case COMP_MISSED_SERVICE_ERROR: 53 return "Missed Service Error"; 54 case COMP_COMMAND_RING_STOPPED: 55 return "Command Ring Stopped"; 56 case COMP_COMMAND_ABORTED: 57 return "Command Aborted"; 58 case COMP_STOPPED: 59 return "Stopped"; 60 case COMP_STOPPED_LENGTH_INVALID: 61 return "Stopped - Length Invalid"; 62 case COMP_STOPPED_SHORT_PACKET: 63 return "Stopped - Short Packet"; 64 case COMP_MAX_EXIT_LATENCY_TOO_LARGE_ERROR: 65 return "Max Exit Latency Too Large Error"; 66 case COMP_ISOCH_BUFFER_OVERRUN: 67 return "Isoch Buffer Overrun"; 68 case COMP_EVENT_LOST_ERROR: 69 return "Event Lost Error"; 70 case COMP_UNDEFINED_ERROR: 71 return "Undefined Error"; 72 case COMP_INVALID_STREAM_ID_ERROR: 73 return "Invalid Stream ID Error"; 74 default: 75 return "Unknown!!"; 76 } 77 } 78 79 static inline const char *cdnsp_trb_type_string(u8 type) 80 { 81 switch (type) { 82 case TRB_NORMAL: 83 return "Normal"; 84 case TRB_SETUP: 85 return "Setup Stage"; 86 case TRB_DATA: 87 return "Data Stage"; 88 case TRB_STATUS: 89 return "Status Stage"; 90 case TRB_ISOC: 91 return "Isoch"; 92 case TRB_LINK: 93 return "Link"; 94 case TRB_EVENT_DATA: 95 return "Event Data"; 96 case TRB_TR_NOOP: 97 return "No-Op"; 98 case TRB_ENABLE_SLOT: 99 return "Enable Slot Command"; 100 case TRB_DISABLE_SLOT: 101 return "Disable Slot Command"; 102 case TRB_ADDR_DEV: 103 return "Address Device Command"; 104 case TRB_CONFIG_EP: 105 return "Configure Endpoint Command"; 106 case TRB_EVAL_CONTEXT: 107 return "Evaluate Context Command"; 108 case TRB_RESET_EP: 109 return "Reset Endpoint Command"; 110 case TRB_STOP_RING: 111 return "Stop Ring Command"; 112 case TRB_SET_DEQ: 113 return "Set TR Dequeue Pointer Command"; 114 case TRB_RESET_DEV: 115 return "Reset Device Command"; 116 case TRB_FORCE_HEADER: 117 return "Force Header Command"; 118 case TRB_CMD_NOOP: 119 return "No-Op Command"; 120 case TRB_TRANSFER: 121 return "Transfer Event"; 122 case TRB_COMPLETION: 123 return "Command Completion Event"; 124 case TRB_PORT_STATUS: 125 return "Port Status Change Event"; 126 case TRB_HC_EVENT: 127 return "Device Controller Event"; 128 case TRB_MFINDEX_WRAP: 129 return "MFINDEX Wrap Event"; 130 case TRB_ENDPOINT_NRDY: 131 return "Endpoint Not ready"; 132 case TRB_HALT_ENDPOINT: 133 return "Halt Endpoint"; 134 case TRB_FLUSH_ENDPOINT: 135 return "FLush Endpoint"; 136 default: 137 return "UNKNOWN"; 138 } 139 } 140 141 static inline const char *cdnsp_ring_type_string(enum cdnsp_ring_type type) 142 { 143 switch (type) { 144 case TYPE_CTRL: 145 return "CTRL"; 146 case TYPE_ISOC: 147 return "ISOC"; 148 case TYPE_BULK: 149 return "BULK"; 150 case TYPE_INTR: 151 return "INTR"; 152 case TYPE_STREAM: 153 return "STREAM"; 154 case TYPE_COMMAND: 155 return "CMD"; 156 case TYPE_EVENT: 157 return "EVENT"; 158 } 159 160 return "UNKNOWN"; 161 } 162 163 static inline char *cdnsp_slot_state_string(u32 state) 164 { 165 switch (state) { 166 case SLOT_STATE_ENABLED: 167 return "enabled/disabled"; 168 case SLOT_STATE_DEFAULT: 169 return "default"; 170 case SLOT_STATE_ADDRESSED: 171 return "addressed"; 172 case SLOT_STATE_CONFIGURED: 173 return "configured"; 174 default: 175 return "reserved"; 176 } 177 } 178 179 static inline const char *cdnsp_decode_trb(char *str, size_t size, u32 field0, 180 u32 field1, u32 field2, u32 field3) 181 { 182 int ep_id = TRB_TO_EP_INDEX(field3) - 1; 183 int type = TRB_FIELD_TO_TYPE(field3); 184 unsigned int ep_num; 185 int ret = 0; 186 u32 temp; 187 188 ep_num = DIV_ROUND_UP(ep_id, 2); 189 190 switch (type) { 191 case TRB_LINK: 192 ret += snprintf(str, size, 193 "LINK %08x%08x intr %ld type '%s' flags %c:%c:%c:%c", 194 field1, field0, GET_INTR_TARGET(field2), 195 cdnsp_trb_type_string(type), 196 field3 & TRB_IOC ? 'I' : 'i', 197 field3 & TRB_CHAIN ? 'C' : 'c', 198 field3 & TRB_TC ? 'T' : 't', 199 field3 & TRB_CYCLE ? 'C' : 'c'); 200 break; 201 case TRB_TRANSFER: 202 case TRB_COMPLETION: 203 case TRB_PORT_STATUS: 204 case TRB_HC_EVENT: 205 ret += snprintf(str, size, 206 "ep%d%s(%d) type '%s' TRB %08x%08x status '%s'" 207 " len %ld slot %ld flags %c:%c", 208 ep_num, ep_id % 2 ? "out" : "in", 209 TRB_TO_EP_INDEX(field3), 210 cdnsp_trb_type_string(type), field1, field0, 211 cdnsp_trb_comp_code_string(GET_COMP_CODE(field2)), 212 EVENT_TRB_LEN(field2), TRB_TO_SLOT_ID(field3), 213 field3 & EVENT_DATA ? 'E' : 'e', 214 field3 & TRB_CYCLE ? 'C' : 'c'); 215 break; 216 case TRB_MFINDEX_WRAP: 217 ret += snprintf(str, size, "%s: flags %c", 218 cdnsp_trb_type_string(type), 219 field3 & TRB_CYCLE ? 'C' : 'c'); 220 break; 221 case TRB_SETUP: 222 ret += snprintf(str, size, 223 "type '%s' bRequestType %02x bRequest %02x " 224 "wValue %02x%02x wIndex %02x%02x wLength %d " 225 "length %ld TD size %ld intr %ld Setup ID %ld " 226 "flags %c:%c:%c", 227 cdnsp_trb_type_string(type), 228 field0 & 0xff, 229 (field0 & 0xff00) >> 8, 230 (field0 & 0xff000000) >> 24, 231 (field0 & 0xff0000) >> 16, 232 (field1 & 0xff00) >> 8, 233 field1 & 0xff, 234 (field1 & 0xff000000) >> 16 | 235 (field1 & 0xff0000) >> 16, 236 TRB_LEN(field2), GET_TD_SIZE(field2), 237 GET_INTR_TARGET(field2), 238 TRB_SETUPID_TO_TYPE(field3), 239 field3 & TRB_IDT ? 'D' : 'd', 240 field3 & TRB_IOC ? 'I' : 'i', 241 field3 & TRB_CYCLE ? 'C' : 'c'); 242 break; 243 case TRB_DATA: 244 ret += snprintf(str, size, 245 "type '%s' Buffer %08x%08x length %ld TD size %ld " 246 "intr %ld flags %c:%c:%c:%c:%c:%c:%c", 247 cdnsp_trb_type_string(type), 248 field1, field0, TRB_LEN(field2), 249 GET_TD_SIZE(field2), 250 GET_INTR_TARGET(field2), 251 field3 & TRB_IDT ? 'D' : 'i', 252 field3 & TRB_IOC ? 'I' : 'i', 253 field3 & TRB_CHAIN ? 'C' : 'c', 254 field3 & TRB_NO_SNOOP ? 'S' : 's', 255 field3 & TRB_ISP ? 'I' : 'i', 256 field3 & TRB_ENT ? 'E' : 'e', 257 field3 & TRB_CYCLE ? 'C' : 'c'); 258 break; 259 case TRB_STATUS: 260 ret += snprintf(str, size, 261 "Buffer %08x%08x length %ld TD size %ld intr" 262 "%ld type '%s' flags %c:%c:%c:%c", 263 field1, field0, TRB_LEN(field2), 264 GET_TD_SIZE(field2), 265 GET_INTR_TARGET(field2), 266 cdnsp_trb_type_string(type), 267 field3 & TRB_IOC ? 'I' : 'i', 268 field3 & TRB_CHAIN ? 'C' : 'c', 269 field3 & TRB_ENT ? 'E' : 'e', 270 field3 & TRB_CYCLE ? 'C' : 'c'); 271 break; 272 case TRB_NORMAL: 273 case TRB_ISOC: 274 case TRB_EVENT_DATA: 275 case TRB_TR_NOOP: 276 ret += snprintf(str, size, 277 "type '%s' Buffer %08x%08x length %ld " 278 "TD size %ld intr %ld " 279 "flags %c:%c:%c:%c:%c:%c:%c:%c:%c", 280 cdnsp_trb_type_string(type), 281 field1, field0, TRB_LEN(field2), 282 GET_TD_SIZE(field2), 283 GET_INTR_TARGET(field2), 284 field3 & TRB_BEI ? 'B' : 'b', 285 field3 & TRB_IDT ? 'T' : 't', 286 field3 & TRB_IOC ? 'I' : 'i', 287 field3 & TRB_CHAIN ? 'C' : 'c', 288 field3 & TRB_NO_SNOOP ? 'S' : 's', 289 field3 & TRB_ISP ? 'I' : 'i', 290 field3 & TRB_ENT ? 'E' : 'e', 291 field3 & TRB_CYCLE ? 'C' : 'c', 292 !(field3 & TRB_EVENT_INVALIDATE) ? 'V' : 'v'); 293 break; 294 case TRB_CMD_NOOP: 295 case TRB_ENABLE_SLOT: 296 ret += snprintf(str, size, "%s: flags %c", 297 cdnsp_trb_type_string(type), 298 field3 & TRB_CYCLE ? 'C' : 'c'); 299 break; 300 case TRB_DISABLE_SLOT: 301 ret += snprintf(str, size, "%s: slot %ld flags %c", 302 cdnsp_trb_type_string(type), 303 TRB_TO_SLOT_ID(field3), 304 field3 & TRB_CYCLE ? 'C' : 'c'); 305 break; 306 case TRB_ADDR_DEV: 307 ret += snprintf(str, size, 308 "%s: ctx %08x%08x slot %ld flags %c:%c", 309 cdnsp_trb_type_string(type), field1, field0, 310 TRB_TO_SLOT_ID(field3), 311 field3 & TRB_BSR ? 'B' : 'b', 312 field3 & TRB_CYCLE ? 'C' : 'c'); 313 break; 314 case TRB_CONFIG_EP: 315 ret += snprintf(str, size, 316 "%s: ctx %08x%08x slot %ld flags %c:%c", 317 cdnsp_trb_type_string(type), field1, field0, 318 TRB_TO_SLOT_ID(field3), 319 field3 & TRB_DC ? 'D' : 'd', 320 field3 & TRB_CYCLE ? 'C' : 'c'); 321 break; 322 case TRB_EVAL_CONTEXT: 323 ret += snprintf(str, size, 324 "%s: ctx %08x%08x slot %ld flags %c", 325 cdnsp_trb_type_string(type), field1, field0, 326 TRB_TO_SLOT_ID(field3), 327 field3 & TRB_CYCLE ? 'C' : 'c'); 328 break; 329 case TRB_RESET_EP: 330 case TRB_HALT_ENDPOINT: 331 case TRB_FLUSH_ENDPOINT: 332 ret += snprintf(str, size, 333 "%s: ep%d%s(%d) ctx %08x%08x slot %ld flags %c", 334 cdnsp_trb_type_string(type), 335 ep_num, ep_id % 2 ? "out" : "in", 336 TRB_TO_EP_INDEX(field3), field1, field0, 337 TRB_TO_SLOT_ID(field3), 338 field3 & TRB_CYCLE ? 'C' : 'c'); 339 break; 340 case TRB_STOP_RING: 341 ret += snprintf(str, size, 342 "%s: ep%d%s(%d) slot %ld sp %d flags %c", 343 cdnsp_trb_type_string(type), 344 ep_num, ep_id % 2 ? "out" : "in", 345 TRB_TO_EP_INDEX(field3), 346 TRB_TO_SLOT_ID(field3), 347 TRB_TO_SUSPEND_PORT(field3), 348 field3 & TRB_CYCLE ? 'C' : 'c'); 349 break; 350 case TRB_SET_DEQ: 351 ret += snprintf(str, size, 352 "%s: ep%d%s(%d) deq %08x%08x stream %ld slot %ld flags %c", 353 cdnsp_trb_type_string(type), 354 ep_num, ep_id % 2 ? "out" : "in", 355 TRB_TO_EP_INDEX(field3), field1, field0, 356 TRB_TO_STREAM_ID(field2), 357 TRB_TO_SLOT_ID(field3), 358 field3 & TRB_CYCLE ? 'C' : 'c'); 359 break; 360 case TRB_RESET_DEV: 361 ret += snprintf(str, size, "%s: slot %ld flags %c", 362 cdnsp_trb_type_string(type), 363 TRB_TO_SLOT_ID(field3), 364 field3 & TRB_CYCLE ? 'C' : 'c'); 365 break; 366 case TRB_ENDPOINT_NRDY: 367 temp = TRB_TO_HOST_STREAM(field2); 368 369 ret += snprintf(str, size, 370 "%s: ep%d%s(%d) H_SID %x%s%s D_SID %lx flags %c:%c", 371 cdnsp_trb_type_string(type), 372 ep_num, ep_id % 2 ? "out" : "in", 373 TRB_TO_EP_INDEX(field3), temp, 374 temp == STREAM_PRIME_ACK ? "(PRIME)" : "", 375 temp == STREAM_REJECTED ? "(REJECTED)" : "", 376 TRB_TO_DEV_STREAM(field0), 377 field3 & TRB_STAT ? 'S' : 's', 378 field3 & TRB_CYCLE ? 'C' : 'c'); 379 break; 380 default: 381 ret += snprintf(str, size, 382 "type '%s' -> raw %08x %08x %08x %08x", 383 cdnsp_trb_type_string(type), 384 field0, field1, field2, field3); 385 } 386 387 return str; 388 } 389 390 static inline const char *cdnsp_decode_slot_context(u32 info, u32 info2, 391 u32 int_target, u32 state) 392 { 393 static char str[1024]; 394 int ret = 0; 395 u32 speed; 396 char *s; 397 398 speed = info & DEV_SPEED; 399 400 switch (speed) { 401 case SLOT_SPEED_FS: 402 s = "full-speed"; 403 break; 404 case SLOT_SPEED_HS: 405 s = "high-speed"; 406 break; 407 case SLOT_SPEED_SS: 408 s = "super-speed"; 409 break; 410 case SLOT_SPEED_SSP: 411 s = "super-speed plus"; 412 break; 413 default: 414 s = "UNKNOWN speed"; 415 } 416 417 ret = sprintf(str, "%s Ctx Entries %d", 418 s, (info & LAST_CTX_MASK) >> 27); 419 420 ret += sprintf(str + ret, " [Intr %ld] Addr %ld State %s", 421 GET_INTR_TARGET(int_target), state & DEV_ADDR_MASK, 422 cdnsp_slot_state_string(GET_SLOT_STATE(state))); 423 424 return str; 425 } 426 427 static inline const char *cdnsp_portsc_link_state_string(u32 portsc) 428 { 429 switch (portsc & PORT_PLS_MASK) { 430 case XDEV_U0: 431 return "U0"; 432 case XDEV_U1: 433 return "U1"; 434 case XDEV_U2: 435 return "U2"; 436 case XDEV_U3: 437 return "U3"; 438 case XDEV_DISABLED: 439 return "Disabled"; 440 case XDEV_RXDETECT: 441 return "RxDetect"; 442 case XDEV_INACTIVE: 443 return "Inactive"; 444 case XDEV_POLLING: 445 return "Polling"; 446 case XDEV_RECOVERY: 447 return "Recovery"; 448 case XDEV_HOT_RESET: 449 return "Hot Reset"; 450 case XDEV_COMP_MODE: 451 return "Compliance mode"; 452 case XDEV_TEST_MODE: 453 return "Test mode"; 454 case XDEV_RESUME: 455 return "Resume"; 456 default: 457 break; 458 } 459 460 return "Unknown"; 461 } 462 463 static inline const char *cdnsp_decode_portsc(char *str, size_t size, 464 u32 portsc) 465 { 466 int ret; 467 468 ret = snprintf(str, size, "%s %s %s Link:%s PortSpeed:%d ", 469 portsc & PORT_POWER ? "Powered" : "Powered-off", 470 portsc & PORT_CONNECT ? "Connected" : "Not-connected", 471 portsc & PORT_PED ? "Enabled" : "Disabled", 472 cdnsp_portsc_link_state_string(portsc), 473 DEV_PORT_SPEED(portsc)); 474 475 if (portsc & PORT_RESET) 476 ret += snprintf(str + ret, size - ret, "In-Reset "); 477 478 ret += snprintf(str + ret, size - ret, "Change: "); 479 if (portsc & PORT_CSC) 480 ret += snprintf(str + ret, size - ret, "CSC "); 481 if (portsc & PORT_WRC) 482 ret += snprintf(str + ret, size - ret, "WRC "); 483 if (portsc & PORT_RC) 484 ret += snprintf(str + ret, size - ret, "PRC "); 485 if (portsc & PORT_PLC) 486 ret += snprintf(str + ret, size - ret, "PLC "); 487 if (portsc & PORT_CEC) 488 ret += snprintf(str + ret, size - ret, "CEC "); 489 ret += snprintf(str + ret, size - ret, "Wake: "); 490 if (portsc & PORT_WKCONN_E) 491 ret += snprintf(str + ret, size - ret, "WCE "); 492 if (portsc & PORT_WKDISC_E) 493 ret += snprintf(str + ret, size - ret, "WDE "); 494 495 return str; 496 } 497 498 static inline const char *cdnsp_ep_state_string(u8 state) 499 { 500 switch (state) { 501 case EP_STATE_DISABLED: 502 return "disabled"; 503 case EP_STATE_RUNNING: 504 return "running"; 505 case EP_STATE_HALTED: 506 return "halted"; 507 case EP_STATE_STOPPED: 508 return "stopped"; 509 case EP_STATE_ERROR: 510 return "error"; 511 default: 512 return "INVALID"; 513 } 514 } 515 516 static inline const char *cdnsp_ep_type_string(u8 type) 517 { 518 switch (type) { 519 case ISOC_OUT_EP: 520 return "Isoc OUT"; 521 case BULK_OUT_EP: 522 return "Bulk OUT"; 523 case INT_OUT_EP: 524 return "Int OUT"; 525 case CTRL_EP: 526 return "Ctrl"; 527 case ISOC_IN_EP: 528 return "Isoc IN"; 529 case BULK_IN_EP: 530 return "Bulk IN"; 531 case INT_IN_EP: 532 return "Int IN"; 533 default: 534 return "INVALID"; 535 } 536 } 537 538 static inline const char *cdnsp_decode_ep_context(char *str, size_t size, 539 u32 info, u32 info2, 540 u64 deq, u32 tx_info) 541 { 542 u8 max_pstr, ep_state, interval, ep_type, burst, cerr, mult; 543 bool lsa, hid; 544 u16 maxp, avg; 545 u32 esit; 546 int ret; 547 548 esit = CTX_TO_MAX_ESIT_PAYLOAD_HI(info) << 16 | 549 CTX_TO_MAX_ESIT_PAYLOAD_LO(tx_info); 550 551 ep_state = info & EP_STATE_MASK; 552 max_pstr = CTX_TO_EP_MAXPSTREAMS(info); 553 interval = CTX_TO_EP_INTERVAL(info); 554 mult = CTX_TO_EP_MULT(info) + 1; 555 lsa = !!(info & EP_HAS_LSA); 556 557 cerr = (info2 & (3 << 1)) >> 1; 558 ep_type = CTX_TO_EP_TYPE(info2); 559 hid = !!(info2 & (1 << 7)); 560 burst = CTX_TO_MAX_BURST(info2); 561 maxp = MAX_PACKET_DECODED(info2); 562 563 avg = EP_AVG_TRB_LENGTH(tx_info); 564 565 ret = snprintf(str, size, "State %s mult %d max P. Streams %d %s", 566 cdnsp_ep_state_string(ep_state), mult, 567 max_pstr, lsa ? "LSA " : ""); 568 569 ret += snprintf(str + ret, size - ret, 570 "interval %d us max ESIT payload %d CErr %d ", 571 (1 << interval) * 125, esit, cerr); 572 573 ret += snprintf(str + ret, size - ret, 574 "Type %s %sburst %d maxp %d deq %016llx ", 575 cdnsp_ep_type_string(ep_type), hid ? "HID" : "", 576 burst, maxp, deq); 577 578 ret += snprintf(str + ret, size - ret, "avg trb len %d", avg); 579 580 return str; 581 } 582 583 #endif /*__LINUX_CDNSP_DEBUG*/ 584