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 
cdns2_decode_usb_irq(char * str,size_t size,u8 usb_irq,u8 ext_irq)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 
cdns2_decode_dma_irq(char * str,size_t size,u32 ep_ists,u32 ep_sts,const char * ep_name)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 
cdns2_decode_epx_irq(char * str,size_t size,char * ep_name,u32 ep_ists,u32 ep_sts)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 
cdns2_decode_ep0_irq(char * str,size_t size,u32 ep_ists,u32 ep_sts,int dir)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 
cdns2_raw_ring(struct cdns2_endpoint * pep,struct cdns2_trb * trbs,char * str,size_t size)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 
cdns2_trb_type_string(u8 type)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 
cdns2_decode_trb(char * str,size_t size,u32 flags,u32 length,u32 buffer)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