162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Cadence USBHS-DEV Driver.
462306a36Sopenharmony_ci * Debug header file.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (C) 2023 Cadence.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Author: Pawel Laszczak <pawell@cadence.com>
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#ifndef __LINUX_CDNS2_DEBUG
1262306a36Sopenharmony_ci#define __LINUX_CDNS2_DEBUG
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_cistatic inline const char *cdns2_decode_usb_irq(char *str, size_t size,
1562306a36Sopenharmony_ci					       u8 usb_irq, u8 ext_irq)
1662306a36Sopenharmony_ci{
1762306a36Sopenharmony_ci	int ret;
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci	ret = snprintf(str, size, "usbirq: 0x%02x - ", usb_irq);
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci	if (usb_irq & USBIRQ_SOF)
2262306a36Sopenharmony_ci		ret += snprintf(str + ret, size - ret, "SOF ");
2362306a36Sopenharmony_ci	if (usb_irq & USBIRQ_SUTOK)
2462306a36Sopenharmony_ci		ret += snprintf(str + ret, size - ret, "SUTOK ");
2562306a36Sopenharmony_ci	if (usb_irq & USBIRQ_SUDAV)
2662306a36Sopenharmony_ci		ret += snprintf(str + ret, size - ret, "SETUP ");
2762306a36Sopenharmony_ci	if (usb_irq & USBIRQ_SUSPEND)
2862306a36Sopenharmony_ci		ret += snprintf(str + ret, size - ret, "Suspend ");
2962306a36Sopenharmony_ci	if (usb_irq & USBIRQ_URESET)
3062306a36Sopenharmony_ci		ret += snprintf(str + ret, size - ret, "Reset ");
3162306a36Sopenharmony_ci	if (usb_irq & USBIRQ_HSPEED)
3262306a36Sopenharmony_ci		ret += snprintf(str + ret, size - ret, "HS ");
3362306a36Sopenharmony_ci	if (usb_irq & USBIRQ_LPM)
3462306a36Sopenharmony_ci		ret += snprintf(str + ret, size - ret, "LPM ");
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	ret += snprintf(str + ret, size - ret, ", EXT: 0x%02x - ", ext_irq);
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	if (ext_irq & EXTIRQ_WAKEUP)
3962306a36Sopenharmony_ci		ret += snprintf(str + ret, size - ret, "Wakeup ");
4062306a36Sopenharmony_ci	if (ext_irq & EXTIRQ_VBUSFAULT_FALL)
4162306a36Sopenharmony_ci		ret += snprintf(str + ret, size - ret, "VBUS_FALL ");
4262306a36Sopenharmony_ci	if (ext_irq & EXTIRQ_VBUSFAULT_RISE)
4362306a36Sopenharmony_ci		ret += snprintf(str + ret, size - ret, "VBUS_RISE ");
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	if (ret >= size)
4662306a36Sopenharmony_ci		pr_info("CDNS2: buffer overflowed.\n");
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	return str;
4962306a36Sopenharmony_ci}
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_cistatic inline const char *cdns2_decode_dma_irq(char *str, size_t size,
5262306a36Sopenharmony_ci					       u32 ep_ists, u32 ep_sts,
5362306a36Sopenharmony_ci					       const char *ep_name)
5462306a36Sopenharmony_ci{
5562306a36Sopenharmony_ci	int ret;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	ret = snprintf(str, size, "ISTS: %08x, %s: %08x ",
5862306a36Sopenharmony_ci		       ep_ists, ep_name, ep_sts);
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	if (ep_sts & DMA_EP_STS_IOC)
6162306a36Sopenharmony_ci		ret += snprintf(str + ret, size - ret, "IOC ");
6262306a36Sopenharmony_ci	if (ep_sts & DMA_EP_STS_ISP)
6362306a36Sopenharmony_ci		ret += snprintf(str + ret, size - ret, "ISP ");
6462306a36Sopenharmony_ci	if (ep_sts & DMA_EP_STS_DESCMIS)
6562306a36Sopenharmony_ci		ret += snprintf(str + ret, size - ret, "DESCMIS ");
6662306a36Sopenharmony_ci	if (ep_sts & DMA_EP_STS_TRBERR)
6762306a36Sopenharmony_ci		ret += snprintf(str + ret, size - ret, "TRBERR ");
6862306a36Sopenharmony_ci	if (ep_sts & DMA_EP_STS_OUTSMM)
6962306a36Sopenharmony_ci		ret += snprintf(str + ret, size - ret, "OUTSMM ");
7062306a36Sopenharmony_ci	if (ep_sts & DMA_EP_STS_ISOERR)
7162306a36Sopenharmony_ci		ret += snprintf(str + ret, size - ret, "ISOERR ");
7262306a36Sopenharmony_ci	if (ep_sts & DMA_EP_STS_DBUSY)
7362306a36Sopenharmony_ci		ret += snprintf(str + ret, size - ret, "DBUSY ");
7462306a36Sopenharmony_ci	if (DMA_EP_STS_CCS(ep_sts))
7562306a36Sopenharmony_ci		ret += snprintf(str + ret, size - ret, "CCS ");
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	if (ret >= size)
7862306a36Sopenharmony_ci		pr_info("CDNS2: buffer overflowed.\n");
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	return str;
8162306a36Sopenharmony_ci}
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_cistatic inline const char *cdns2_decode_epx_irq(char *str, size_t size,
8462306a36Sopenharmony_ci					       char *ep_name, u32 ep_ists,
8562306a36Sopenharmony_ci					       u32 ep_sts)
8662306a36Sopenharmony_ci{
8762306a36Sopenharmony_ci	return cdns2_decode_dma_irq(str, size, ep_ists, ep_sts, ep_name);
8862306a36Sopenharmony_ci}
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_cistatic inline const char *cdns2_decode_ep0_irq(char *str, size_t size,
9162306a36Sopenharmony_ci					       u32 ep_ists, u32 ep_sts,
9262306a36Sopenharmony_ci					       int dir)
9362306a36Sopenharmony_ci{
9462306a36Sopenharmony_ci	return cdns2_decode_dma_irq(str, size, ep_ists, ep_sts,
9562306a36Sopenharmony_ci				    dir ? "ep0IN" : "ep0OUT");
9662306a36Sopenharmony_ci}
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistatic inline const char *cdns2_raw_ring(struct cdns2_endpoint *pep,
9962306a36Sopenharmony_ci					 struct cdns2_trb *trbs,
10062306a36Sopenharmony_ci					 char *str, size_t size)
10162306a36Sopenharmony_ci{
10262306a36Sopenharmony_ci	struct cdns2_ring *ring = &pep->ring;
10362306a36Sopenharmony_ci	struct cdns2_trb *trb;
10462306a36Sopenharmony_ci	dma_addr_t dma;
10562306a36Sopenharmony_ci	int ret;
10662306a36Sopenharmony_ci	int i;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	ret = snprintf(str, size, "\n\t\tTR for %s:", pep->name);
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	trb = &trbs[ring->dequeue];
11162306a36Sopenharmony_ci	dma = cdns2_trb_virt_to_dma(pep, trb);
11262306a36Sopenharmony_ci	ret += snprintf(str + ret, size - ret,
11362306a36Sopenharmony_ci			"\n\t\tRing deq index: %d, trb: V=%p, P=0x%pad\n",
11462306a36Sopenharmony_ci			ring->dequeue, trb, &dma);
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	trb = &trbs[ring->enqueue];
11762306a36Sopenharmony_ci	dma = cdns2_trb_virt_to_dma(pep, trb);
11862306a36Sopenharmony_ci	ret += snprintf(str + ret, size - ret,
11962306a36Sopenharmony_ci			"\t\tRing enq index: %d, trb: V=%p, P=0x%pad\n",
12062306a36Sopenharmony_ci			ring->enqueue, trb, &dma);
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	ret += snprintf(str + ret, size - ret,
12362306a36Sopenharmony_ci			"\t\tfree trbs: %d, CCS=%d, PCS=%d\n",
12462306a36Sopenharmony_ci			ring->free_trbs, ring->ccs, ring->pcs);
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	if (TRBS_PER_SEGMENT > 40) {
12762306a36Sopenharmony_ci		ret += snprintf(str + ret, size - ret,
12862306a36Sopenharmony_ci				"\t\tTransfer ring %d too big\n", TRBS_PER_SEGMENT);
12962306a36Sopenharmony_ci		return str;
13062306a36Sopenharmony_ci	}
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	dma = ring->dma;
13362306a36Sopenharmony_ci	for (i = 0; i < TRBS_PER_SEGMENT; ++i) {
13462306a36Sopenharmony_ci		trb = &trbs[i];
13562306a36Sopenharmony_ci		ret += snprintf(str + ret, size - ret,
13662306a36Sopenharmony_ci				"\t\t@%pad %08x %08x %08x\n", &dma,
13762306a36Sopenharmony_ci				le32_to_cpu(trb->buffer),
13862306a36Sopenharmony_ci				le32_to_cpu(trb->length),
13962306a36Sopenharmony_ci				le32_to_cpu(trb->control));
14062306a36Sopenharmony_ci		dma += sizeof(*trb);
14162306a36Sopenharmony_ci	}
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	if (ret >= size)
14462306a36Sopenharmony_ci		pr_info("CDNS2: buffer overflowed.\n");
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	return str;
14762306a36Sopenharmony_ci}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_cistatic inline const char *cdns2_trb_type_string(u8 type)
15062306a36Sopenharmony_ci{
15162306a36Sopenharmony_ci	switch (type) {
15262306a36Sopenharmony_ci	case TRB_NORMAL:
15362306a36Sopenharmony_ci		return "Normal";
15462306a36Sopenharmony_ci	case TRB_LINK:
15562306a36Sopenharmony_ci		return "Link";
15662306a36Sopenharmony_ci	default:
15762306a36Sopenharmony_ci		return "UNKNOWN";
15862306a36Sopenharmony_ci	}
15962306a36Sopenharmony_ci}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_cistatic inline const char *cdns2_decode_trb(char *str, size_t size, u32 flags,
16262306a36Sopenharmony_ci					   u32 length, u32 buffer)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	int type = TRB_FIELD_TO_TYPE(flags);
16562306a36Sopenharmony_ci	int ret;
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	switch (type) {
16862306a36Sopenharmony_ci	case TRB_LINK:
16962306a36Sopenharmony_ci		ret = snprintf(str, size,
17062306a36Sopenharmony_ci			       "LINK %08x type '%s' flags %c:%c:%c%c:%c",
17162306a36Sopenharmony_ci			       buffer, cdns2_trb_type_string(type),
17262306a36Sopenharmony_ci			       flags & TRB_CYCLE ? 'C' : 'c',
17362306a36Sopenharmony_ci			       flags & TRB_TOGGLE ? 'T' : 't',
17462306a36Sopenharmony_ci			       flags & TRB_CHAIN ? 'C' : 'c',
17562306a36Sopenharmony_ci			       flags & TRB_CHAIN ? 'H' : 'h',
17662306a36Sopenharmony_ci			       flags & TRB_IOC ? 'I' : 'i');
17762306a36Sopenharmony_ci		break;
17862306a36Sopenharmony_ci	case TRB_NORMAL:
17962306a36Sopenharmony_ci		ret = snprintf(str, size,
18062306a36Sopenharmony_ci			       "type: '%s', Buffer: %08x, length: %ld, burst len: %ld, "
18162306a36Sopenharmony_ci			       "flags %c:%c:%c%c:%c",
18262306a36Sopenharmony_ci			       cdns2_trb_type_string(type),
18362306a36Sopenharmony_ci			       buffer, TRB_LEN(length),
18462306a36Sopenharmony_ci			       TRB_FIELD_TO_BURST(length),
18562306a36Sopenharmony_ci			       flags & TRB_CYCLE ? 'C' : 'c',
18662306a36Sopenharmony_ci			       flags & TRB_ISP ? 'I' : 'i',
18762306a36Sopenharmony_ci			       flags & TRB_CHAIN ? 'C' : 'c',
18862306a36Sopenharmony_ci			       flags & TRB_CHAIN ? 'H' : 'h',
18962306a36Sopenharmony_ci			       flags & TRB_IOC ? 'I' : 'i');
19062306a36Sopenharmony_ci		break;
19162306a36Sopenharmony_ci	default:
19262306a36Sopenharmony_ci		ret = snprintf(str, size, "type '%s' -> raw %08x %08x %08x",
19362306a36Sopenharmony_ci			       cdns2_trb_type_string(type),
19462306a36Sopenharmony_ci			       buffer, length, flags);
19562306a36Sopenharmony_ci	}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	if (ret >= size)
19862306a36Sopenharmony_ci		pr_info("CDNS2: buffer overflowed.\n");
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	return str;
20162306a36Sopenharmony_ci}
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci#endif /*__LINUX_CDNS2_DEBUG*/
204