1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Cadence USBHS-DEV Driver. 4 * Debug header file. 5 * 6 * Copyright (C) 2023 Cadence. 7 * 8 * Author: Pawel Laszczak <pawell@cadence.com> 9 */ 10 11 #ifndef __LINUX_CDNS2_DEBUG 12 #define __LINUX_CDNS2_DEBUG 13 14 static inline const char *cdns2_decode_usb_irq(char *str, size_t size, 15 u8 usb_irq, u8 ext_irq) 16 { 17 int ret; 18 19 ret = scnprintf(str, size, "usbirq: 0x%02x - ", usb_irq); 20 21 if (usb_irq & USBIRQ_SOF) 22 ret += scnprintf(str + ret, size - ret, "SOF "); 23 if (usb_irq & USBIRQ_SUTOK) 24 ret += scnprintf(str + ret, size - ret, "SUTOK "); 25 if (usb_irq & USBIRQ_SUDAV) 26 ret += scnprintf(str + ret, size - ret, "SETUP "); 27 if (usb_irq & USBIRQ_SUSPEND) 28 ret += scnprintf(str + ret, size - ret, "Suspend "); 29 if (usb_irq & USBIRQ_URESET) 30 ret += scnprintf(str + ret, size - ret, "Reset "); 31 if (usb_irq & USBIRQ_HSPEED) 32 ret += scnprintf(str + ret, size - ret, "HS "); 33 if (usb_irq & USBIRQ_LPM) 34 ret += scnprintf(str + ret, size - ret, "LPM "); 35 36 ret += scnprintf(str + ret, size - ret, ", EXT: 0x%02x - ", ext_irq); 37 38 if (ext_irq & EXTIRQ_WAKEUP) 39 ret += scnprintf(str + ret, size - ret, "Wakeup "); 40 if (ext_irq & EXTIRQ_VBUSFAULT_FALL) 41 ret += scnprintf(str + ret, size - ret, "VBUS_FALL "); 42 if (ext_irq & EXTIRQ_VBUSFAULT_RISE) 43 ret += scnprintf(str + ret, size - ret, "VBUS_RISE "); 44 45 if (ret == size - 1) 46 pr_info("CDNS2: buffer may be truncated.\n"); 47 48 return str; 49 } 50 51 static inline const char *cdns2_decode_dma_irq(char *str, size_t size, 52 u32 ep_ists, u32 ep_sts, 53 const char *ep_name) 54 { 55 int ret; 56 57 ret = scnprintf(str, size, "ISTS: %08x, %s: %08x ", 58 ep_ists, ep_name, ep_sts); 59 60 if (ep_sts & DMA_EP_STS_IOC) 61 ret += scnprintf(str + ret, size - ret, "IOC "); 62 if (ep_sts & DMA_EP_STS_ISP) 63 ret += scnprintf(str + ret, size - ret, "ISP "); 64 if (ep_sts & DMA_EP_STS_DESCMIS) 65 ret += scnprintf(str + ret, size - ret, "DESCMIS "); 66 if (ep_sts & DMA_EP_STS_TRBERR) 67 ret += scnprintf(str + ret, size - ret, "TRBERR "); 68 if (ep_sts & DMA_EP_STS_OUTSMM) 69 ret += scnprintf(str + ret, size - ret, "OUTSMM "); 70 if (ep_sts & DMA_EP_STS_ISOERR) 71 ret += scnprintf(str + ret, size - ret, "ISOERR "); 72 if (ep_sts & DMA_EP_STS_DBUSY) 73 ret += scnprintf(str + ret, size - ret, "DBUSY "); 74 if (DMA_EP_STS_CCS(ep_sts)) 75 ret += scnprintf(str + ret, size - ret, "CCS "); 76 77 if (ret == size - 1) 78 pr_info("CDNS2: buffer may be truncated.\n"); 79 80 return str; 81 } 82 83 static inline const char *cdns2_decode_epx_irq(char *str, size_t size, 84 char *ep_name, u32 ep_ists, 85 u32 ep_sts) 86 { 87 return cdns2_decode_dma_irq(str, size, ep_ists, ep_sts, ep_name); 88 } 89 90 static inline const char *cdns2_decode_ep0_irq(char *str, size_t size, 91 u32 ep_ists, u32 ep_sts, 92 int dir) 93 { 94 return cdns2_decode_dma_irq(str, size, ep_ists, ep_sts, 95 dir ? "ep0IN" : "ep0OUT"); 96 } 97 98 static inline const char *cdns2_raw_ring(struct cdns2_endpoint *pep, 99 struct cdns2_trb *trbs, 100 char *str, size_t size) 101 { 102 struct cdns2_ring *ring = &pep->ring; 103 struct cdns2_trb *trb; 104 dma_addr_t dma; 105 int ret; 106 int i; 107 108 ret = scnprintf(str, size, "\n\t\tTR for %s:", pep->name); 109 110 trb = &trbs[ring->dequeue]; 111 dma = cdns2_trb_virt_to_dma(pep, trb); 112 ret += scnprintf(str + ret, size - ret, 113 "\n\t\tRing deq index: %d, trb: V=%p, P=0x%pad\n", 114 ring->dequeue, trb, &dma); 115 116 trb = &trbs[ring->enqueue]; 117 dma = cdns2_trb_virt_to_dma(pep, trb); 118 ret += scnprintf(str + ret, size - ret, 119 "\t\tRing enq index: %d, trb: V=%p, P=0x%pad\n", 120 ring->enqueue, trb, &dma); 121 122 ret += scnprintf(str + ret, size - ret, 123 "\t\tfree trbs: %d, CCS=%d, PCS=%d\n", 124 ring->free_trbs, ring->ccs, ring->pcs); 125 126 if (TRBS_PER_SEGMENT > 40) { 127 ret += scnprintf(str + ret, size - ret, 128 "\t\tTransfer ring %d too big\n", TRBS_PER_SEGMENT); 129 return str; 130 } 131 132 dma = ring->dma; 133 for (i = 0; i < TRBS_PER_SEGMENT; ++i) { 134 trb = &trbs[i]; 135 ret += scnprintf(str + ret, size - ret, 136 "\t\t@%pad %08x %08x %08x\n", &dma, 137 le32_to_cpu(trb->buffer), 138 le32_to_cpu(trb->length), 139 le32_to_cpu(trb->control)); 140 dma += sizeof(*trb); 141 } 142 143 if (ret == size - 1) 144 pr_info("CDNS2: buffer may be truncated.\n"); 145 146 return str; 147 } 148 149 static inline const char *cdns2_trb_type_string(u8 type) 150 { 151 switch (type) { 152 case TRB_NORMAL: 153 return "Normal"; 154 case TRB_LINK: 155 return "Link"; 156 default: 157 return "UNKNOWN"; 158 } 159 } 160 161 static inline const char *cdns2_decode_trb(char *str, size_t size, u32 flags, 162 u32 length, u32 buffer) 163 { 164 int type = TRB_FIELD_TO_TYPE(flags); 165 int ret; 166 167 switch (type) { 168 case TRB_LINK: 169 ret = scnprintf(str, size, 170 "LINK %08x type '%s' flags %c:%c:%c%c:%c", 171 buffer, cdns2_trb_type_string(type), 172 flags & TRB_CYCLE ? 'C' : 'c', 173 flags & TRB_TOGGLE ? 'T' : 't', 174 flags & TRB_CHAIN ? 'C' : 'c', 175 flags & TRB_CHAIN ? 'H' : 'h', 176 flags & TRB_IOC ? 'I' : 'i'); 177 break; 178 case TRB_NORMAL: 179 ret = scnprintf(str, size, 180 "type: '%s', Buffer: %08x, length: %ld, burst len: %ld, " 181 "flags %c:%c:%c%c:%c", 182 cdns2_trb_type_string(type), 183 buffer, TRB_LEN(length), 184 TRB_FIELD_TO_BURST(length), 185 flags & TRB_CYCLE ? 'C' : 'c', 186 flags & TRB_ISP ? 'I' : 'i', 187 flags & TRB_CHAIN ? 'C' : 'c', 188 flags & TRB_CHAIN ? 'H' : 'h', 189 flags & TRB_IOC ? 'I' : 'i'); 190 break; 191 default: 192 ret = scnprintf(str, size, "type '%s' -> raw %08x %08x %08x", 193 cdns2_trb_type_string(type), 194 buffer, length, flags); 195 } 196 197 if (ret == size - 1) 198 pr_info("CDNS2: buffer may be truncated.\n"); 199 200 return str; 201 } 202 203 #endif /*__LINUX_CDNS2_DEBUG*/ 204