/* SPDX-License-Identifier: GPL-2.0 */ /* * Cadence USBHS-DEV Driver. * Debug header file. * * Copyright (C) 2023 Cadence. * * Author: Pawel Laszczak */ #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*/