204 lines
5.4 KiB
C
204 lines
5.4 KiB
C
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||
|
/*
|
||
|
* Cadence USBHS-DEV Driver.
|
||
|
* Debug header file.
|
||
|
*
|
||
|
* Copyright (C) 2023 Cadence.
|
||
|
*
|
||
|
* Author: Pawel Laszczak <pawell@cadence.com>
|
||
|
*/
|
||
|
|
||
|
#ifndef __LINUX_CDNS2_DEBUG
|
||
|
#define __LINUX_CDNS2_DEBUG
|
||
|
|
||
|
static inline const char *cdns2_decode_usb_irq(char *str, size_t size,
|
||
|
u8 usb_irq, u8 ext_irq)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
ret = scnprintf(str, size, "usbirq: 0x%02x - ", usb_irq);
|
||
|
|
||
|
if (usb_irq & USBIRQ_SOF)
|
||
|
ret += scnprintf(str + ret, size - ret, "SOF ");
|
||
|
if (usb_irq & USBIRQ_SUTOK)
|
||
|
ret += scnprintf(str + ret, size - ret, "SUTOK ");
|
||
|
if (usb_irq & USBIRQ_SUDAV)
|
||
|
ret += scnprintf(str + ret, size - ret, "SETUP ");
|
||
|
if (usb_irq & USBIRQ_SUSPEND)
|
||
|
ret += scnprintf(str + ret, size - ret, "Suspend ");
|
||
|
if (usb_irq & USBIRQ_URESET)
|
||
|
ret += scnprintf(str + ret, size - ret, "Reset ");
|
||
|
if (usb_irq & USBIRQ_HSPEED)
|
||
|
ret += scnprintf(str + ret, size - ret, "HS ");
|
||
|
if (usb_irq & USBIRQ_LPM)
|
||
|
ret += scnprintf(str + ret, size - ret, "LPM ");
|
||
|
|
||
|
ret += scnprintf(str + ret, size - ret, ", EXT: 0x%02x - ", ext_irq);
|
||
|
|
||
|
if (ext_irq & EXTIRQ_WAKEUP)
|
||
|
ret += scnprintf(str + ret, size - ret, "Wakeup ");
|
||
|
if (ext_irq & EXTIRQ_VBUSFAULT_FALL)
|
||
|
ret += scnprintf(str + ret, size - ret, "VBUS_FALL ");
|
||
|
if (ext_irq & EXTIRQ_VBUSFAULT_RISE)
|
||
|
ret += scnprintf(str + ret, size - ret, "VBUS_RISE ");
|
||
|
|
||
|
if (ret == size - 1)
|
||
|
pr_info("CDNS2: buffer may be truncated.\n");
|
||
|
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
static inline const char *cdns2_decode_dma_irq(char *str, size_t size,
|
||
|
u32 ep_ists, u32 ep_sts,
|
||
|
const char *ep_name)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
ret = scnprintf(str, size, "ISTS: %08x, %s: %08x ",
|
||
|
ep_ists, ep_name, ep_sts);
|
||
|
|
||
|
if (ep_sts & DMA_EP_STS_IOC)
|
||
|
ret += scnprintf(str + ret, size - ret, "IOC ");
|
||
|
if (ep_sts & DMA_EP_STS_ISP)
|
||
|
ret += scnprintf(str + ret, size - ret, "ISP ");
|
||
|
if (ep_sts & DMA_EP_STS_DESCMIS)
|
||
|
ret += scnprintf(str + ret, size - ret, "DESCMIS ");
|
||
|
if (ep_sts & DMA_EP_STS_TRBERR)
|
||
|
ret += scnprintf(str + ret, size - ret, "TRBERR ");
|
||
|
if (ep_sts & DMA_EP_STS_OUTSMM)
|
||
|
ret += scnprintf(str + ret, size - ret, "OUTSMM ");
|
||
|
if (ep_sts & DMA_EP_STS_ISOERR)
|
||
|
ret += scnprintf(str + ret, size - ret, "ISOERR ");
|
||
|
if (ep_sts & DMA_EP_STS_DBUSY)
|
||
|
ret += scnprintf(str + ret, size - ret, "DBUSY ");
|
||
|
if (DMA_EP_STS_CCS(ep_sts))
|
||
|
ret += scnprintf(str + ret, size - ret, "CCS ");
|
||
|
|
||
|
if (ret == size - 1)
|
||
|
pr_info("CDNS2: buffer may be truncated.\n");
|
||
|
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
static inline const char *cdns2_decode_epx_irq(char *str, size_t size,
|
||
|
char *ep_name, u32 ep_ists,
|
||
|
u32 ep_sts)
|
||
|
{
|
||
|
return cdns2_decode_dma_irq(str, size, ep_ists, ep_sts, ep_name);
|
||
|
}
|
||
|
|
||
|
static inline const char *cdns2_decode_ep0_irq(char *str, size_t size,
|
||
|
u32 ep_ists, u32 ep_sts,
|
||
|
int dir)
|
||
|
{
|
||
|
return cdns2_decode_dma_irq(str, size, ep_ists, ep_sts,
|
||
|
dir ? "ep0IN" : "ep0OUT");
|
||
|
}
|
||
|
|
||
|
static inline const char *cdns2_raw_ring(struct cdns2_endpoint *pep,
|
||
|
struct cdns2_trb *trbs,
|
||
|
char *str, size_t size)
|
||
|
{
|
||
|
struct cdns2_ring *ring = &pep->ring;
|
||
|
struct cdns2_trb *trb;
|
||
|
dma_addr_t dma;
|
||
|
int ret;
|
||
|
int i;
|
||
|
|
||
|
ret = scnprintf(str, size, "\n\t\tTR for %s:", pep->name);
|
||
|
|
||
|
trb = &trbs[ring->dequeue];
|
||
|
dma = cdns2_trb_virt_to_dma(pep, trb);
|
||
|
ret += scnprintf(str + ret, size - ret,
|
||
|
"\n\t\tRing deq index: %d, trb: V=%p, P=0x%pad\n",
|
||
|
ring->dequeue, trb, &dma);
|
||
|
|
||
|
trb = &trbs[ring->enqueue];
|
||
|
dma = cdns2_trb_virt_to_dma(pep, trb);
|
||
|
ret += scnprintf(str + ret, size - ret,
|
||
|
"\t\tRing enq index: %d, trb: V=%p, P=0x%pad\n",
|
||
|
ring->enqueue, trb, &dma);
|
||
|
|
||
|
ret += scnprintf(str + ret, size - ret,
|
||
|
"\t\tfree trbs: %d, CCS=%d, PCS=%d\n",
|
||
|
ring->free_trbs, ring->ccs, ring->pcs);
|
||
|
|
||
|
if (TRBS_PER_SEGMENT > 40) {
|
||
|
ret += scnprintf(str + ret, size - ret,
|
||
|
"\t\tTransfer ring %d too big\n", TRBS_PER_SEGMENT);
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
dma = ring->dma;
|
||
|
for (i = 0; i < TRBS_PER_SEGMENT; ++i) {
|
||
|
trb = &trbs[i];
|
||
|
ret += scnprintf(str + ret, size - ret,
|
||
|
"\t\t@%pad %08x %08x %08x\n", &dma,
|
||
|
le32_to_cpu(trb->buffer),
|
||
|
le32_to_cpu(trb->length),
|
||
|
le32_to_cpu(trb->control));
|
||
|
dma += sizeof(*trb);
|
||
|
}
|
||
|
|
||
|
if (ret == size - 1)
|
||
|
pr_info("CDNS2: buffer may be truncated.\n");
|
||
|
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
static inline const char *cdns2_trb_type_string(u8 type)
|
||
|
{
|
||
|
switch (type) {
|
||
|
case TRB_NORMAL:
|
||
|
return "Normal";
|
||
|
case TRB_LINK:
|
||
|
return "Link";
|
||
|
default:
|
||
|
return "UNKNOWN";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static inline const char *cdns2_decode_trb(char *str, size_t size, u32 flags,
|
||
|
u32 length, u32 buffer)
|
||
|
{
|
||
|
int type = TRB_FIELD_TO_TYPE(flags);
|
||
|
int ret;
|
||
|
|
||
|
switch (type) {
|
||
|
case TRB_LINK:
|
||
|
ret = scnprintf(str, size,
|
||
|
"LINK %08x type '%s' flags %c:%c:%c%c:%c",
|
||
|
buffer, cdns2_trb_type_string(type),
|
||
|
flags & TRB_CYCLE ? 'C' : 'c',
|
||
|
flags & TRB_TOGGLE ? 'T' : 't',
|
||
|
flags & TRB_CHAIN ? 'C' : 'c',
|
||
|
flags & TRB_CHAIN ? 'H' : 'h',
|
||
|
flags & TRB_IOC ? 'I' : 'i');
|
||
|
break;
|
||
|
case TRB_NORMAL:
|
||
|
ret = scnprintf(str, size,
|
||
|
"type: '%s', Buffer: %08x, length: %ld, burst len: %ld, "
|
||
|
"flags %c:%c:%c%c:%c",
|
||
|
cdns2_trb_type_string(type),
|
||
|
buffer, TRB_LEN(length),
|
||
|
TRB_FIELD_TO_BURST(length),
|
||
|
flags & TRB_CYCLE ? 'C' : 'c',
|
||
|
flags & TRB_ISP ? 'I' : 'i',
|
||
|
flags & TRB_CHAIN ? 'C' : 'c',
|
||
|
flags & TRB_CHAIN ? 'H' : 'h',
|
||
|
flags & TRB_IOC ? 'I' : 'i');
|
||
|
break;
|
||
|
default:
|
||
|
ret = scnprintf(str, size, "type '%s' -> raw %08x %08x %08x",
|
||
|
cdns2_trb_type_string(type),
|
||
|
buffer, length, flags);
|
||
|
}
|
||
|
|
||
|
if (ret == size - 1)
|
||
|
pr_info("CDNS2: buffer may be truncated.\n");
|
||
|
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
#endif /*__LINUX_CDNS2_DEBUG*/
|