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; 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 if (ret >= size) 388 pr_info("CDNSP: buffer overflowed.\n"); 389 390 return str; 391 } 392 393 static inline const char *cdnsp_decode_slot_context(u32 info, u32 info2, 394 u32 int_target, u32 state) 395 { 396 static char str[1024]; 397 int ret = 0; 398 u32 speed; 399 char *s; 400 401 speed = info & DEV_SPEED; 402 403 switch (speed) { 404 case SLOT_SPEED_FS: 405 s = "full-speed"; 406 break; 407 case SLOT_SPEED_HS: 408 s = "high-speed"; 409 break; 410 case SLOT_SPEED_SS: 411 s = "super-speed"; 412 break; 413 case SLOT_SPEED_SSP: 414 s = "super-speed plus"; 415 break; 416 default: 417 s = "UNKNOWN speed"; 418 } 419 420 ret = sprintf(str, "%s Ctx Entries %d", 421 s, (info & LAST_CTX_MASK) >> 27); 422 423 ret += sprintf(str + ret, " [Intr %ld] Addr %ld State %s", 424 GET_INTR_TARGET(int_target), state & DEV_ADDR_MASK, 425 cdnsp_slot_state_string(GET_SLOT_STATE(state))); 426 427 return str; 428 } 429 430 static inline const char *cdnsp_portsc_link_state_string(u32 portsc) 431 { 432 switch (portsc & PORT_PLS_MASK) { 433 case XDEV_U0: 434 return "U0"; 435 case XDEV_U1: 436 return "U1"; 437 case XDEV_U2: 438 return "U2"; 439 case XDEV_U3: 440 return "U3"; 441 case XDEV_DISABLED: 442 return "Disabled"; 443 case XDEV_RXDETECT: 444 return "RxDetect"; 445 case XDEV_INACTIVE: 446 return "Inactive"; 447 case XDEV_POLLING: 448 return "Polling"; 449 case XDEV_RECOVERY: 450 return "Recovery"; 451 case XDEV_HOT_RESET: 452 return "Hot Reset"; 453 case XDEV_COMP_MODE: 454 return "Compliance mode"; 455 case XDEV_TEST_MODE: 456 return "Test mode"; 457 case XDEV_RESUME: 458 return "Resume"; 459 default: 460 break; 461 } 462 463 return "Unknown"; 464 } 465 466 static inline const char *cdnsp_decode_portsc(char *str, size_t size, 467 u32 portsc) 468 { 469 int ret; 470 471 ret = snprintf(str, size, "%s %s %s Link:%s PortSpeed:%d ", 472 portsc & PORT_POWER ? "Powered" : "Powered-off", 473 portsc & PORT_CONNECT ? "Connected" : "Not-connected", 474 portsc & PORT_PED ? "Enabled" : "Disabled", 475 cdnsp_portsc_link_state_string(portsc), 476 DEV_PORT_SPEED(portsc)); 477 478 if (portsc & PORT_RESET) 479 ret += snprintf(str + ret, size - ret, "In-Reset "); 480 481 ret += snprintf(str + ret, size - ret, "Change: "); 482 if (portsc & PORT_CSC) 483 ret += snprintf(str + ret, size - ret, "CSC "); 484 if (portsc & PORT_WRC) 485 ret += snprintf(str + ret, size - ret, "WRC "); 486 if (portsc & PORT_RC) 487 ret += snprintf(str + ret, size - ret, "PRC "); 488 if (portsc & PORT_PLC) 489 ret += snprintf(str + ret, size - ret, "PLC "); 490 if (portsc & PORT_CEC) 491 ret += snprintf(str + ret, size - ret, "CEC "); 492 ret += snprintf(str + ret, size - ret, "Wake: "); 493 if (portsc & PORT_WKCONN_E) 494 ret += snprintf(str + ret, size - ret, "WCE "); 495 if (portsc & PORT_WKDISC_E) 496 ret += snprintf(str + ret, size - ret, "WDE "); 497 498 return str; 499 } 500 501 static inline const char *cdnsp_ep_state_string(u8 state) 502 { 503 switch (state) { 504 case EP_STATE_DISABLED: 505 return "disabled"; 506 case EP_STATE_RUNNING: 507 return "running"; 508 case EP_STATE_HALTED: 509 return "halted"; 510 case EP_STATE_STOPPED: 511 return "stopped"; 512 case EP_STATE_ERROR: 513 return "error"; 514 default: 515 return "INVALID"; 516 } 517 } 518 519 static inline const char *cdnsp_ep_type_string(u8 type) 520 { 521 switch (type) { 522 case ISOC_OUT_EP: 523 return "Isoc OUT"; 524 case BULK_OUT_EP: 525 return "Bulk OUT"; 526 case INT_OUT_EP: 527 return "Int OUT"; 528 case CTRL_EP: 529 return "Ctrl"; 530 case ISOC_IN_EP: 531 return "Isoc IN"; 532 case BULK_IN_EP: 533 return "Bulk IN"; 534 case INT_IN_EP: 535 return "Int IN"; 536 default: 537 return "INVALID"; 538 } 539 } 540 541 static inline const char *cdnsp_decode_ep_context(char *str, size_t size, 542 u32 info, u32 info2, 543 u64 deq, u32 tx_info) 544 { 545 u8 max_pstr, ep_state, interval, ep_type, burst, cerr, mult; 546 bool lsa, hid; 547 u16 maxp, avg; 548 u32 esit; 549 int ret; 550 551 esit = CTX_TO_MAX_ESIT_PAYLOAD_HI(info) << 16 | 552 CTX_TO_MAX_ESIT_PAYLOAD_LO(tx_info); 553 554 ep_state = info & EP_STATE_MASK; 555 max_pstr = CTX_TO_EP_MAXPSTREAMS(info); 556 interval = CTX_TO_EP_INTERVAL(info); 557 mult = CTX_TO_EP_MULT(info) + 1; 558 lsa = !!(info & EP_HAS_LSA); 559 560 cerr = (info2 & (3 << 1)) >> 1; 561 ep_type = CTX_TO_EP_TYPE(info2); 562 hid = !!(info2 & (1 << 7)); 563 burst = CTX_TO_MAX_BURST(info2); 564 maxp = MAX_PACKET_DECODED(info2); 565 566 avg = EP_AVG_TRB_LENGTH(tx_info); 567 568 ret = snprintf(str, size, "State %s mult %d max P. Streams %d %s", 569 cdnsp_ep_state_string(ep_state), mult, 570 max_pstr, lsa ? "LSA " : ""); 571 572 ret += snprintf(str + ret, size - ret, 573 "interval %d us max ESIT payload %d CErr %d ", 574 (1 << interval) * 125, esit, cerr); 575 576 ret += snprintf(str + ret, size - ret, 577 "Type %s %sburst %d maxp %d deq %016llx ", 578 cdnsp_ep_type_string(ep_type), hid ? "HID" : "", 579 burst, maxp, deq); 580 581 ret += snprintf(str + ret, size - ret, "avg trb len %d", avg); 582 583 return str; 584 } 585 586 #endif /*__LINUX_CDNSP_DEBUG*/ 587