/** * debug.c - DesignWare USB3 DRD Controller Debug/Trace Support * * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com * * Author: Felipe Balbi * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 of * the License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "debug.h" #include static unsigned int ep_addr_rxdbg_mask = 1; module_param(ep_addr_rxdbg_mask, uint, 0644); static unsigned int ep_addr_txdbg_mask = 1; module_param(ep_addr_txdbg_mask, uint, 0644); void dwc3_trace(void (*trace)(struct va_format *), const char *fmt, ...) { struct va_format vaf; va_list args; va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; trace(&vaf); va_end(args); } static int allow_dbg_print(u8 ep_num) { int dir, num; /* allow bus wide events */ if (ep_num == 0xff) return 1; dir = ep_num & 0x1; num = ep_num >> 1; num = 1 << num; if (dir && (num & ep_addr_txdbg_mask)) return 1; if (!dir && (num & ep_addr_rxdbg_mask)) return 1; return 0; } /** * dwc3_dbg_print: prints the common part of the event * @addr: endpoint address * @name: event name * @status: status * @extra: extra information * @dwc3: pointer to struct dwc3 */ void dwc3_dbg_print(struct dwc3 *dwc, u8 ep_num, const char *name, int status, const char *extra) { if (!allow_dbg_print(ep_num)) return; if (name == NULL) return; ipc_log_string(dwc->dwc_ipc_log_ctxt, "%02X %-25.25s %4i ?\t%s", ep_num, name, status, extra); } /** * dwc3_dbg_done: prints a DONE event * @addr: endpoint address * @td: transfer descriptor * @status: status * @dwc3: pointer to struct dwc3 */ void dwc3_dbg_done(struct dwc3 *dwc, u8 ep_num, const u32 count, int status) { if (!allow_dbg_print(ep_num)) return; ipc_log_string(dwc->dwc_ipc_log_ctxt, "%02X %-25.25s %4i ?\t%d", ep_num, "DONE", status, count); } /** * dwc3_dbg_event: prints a generic event * @addr: endpoint address * @name: event name * @status: status */ void dwc3_dbg_event(struct dwc3 *dwc, u8 ep_num, const char *name, int status) { if (!allow_dbg_print(ep_num)) return; if (name != NULL) dwc3_dbg_print(dwc, ep_num, name, status, ""); } /* * dwc3_dbg_queue: prints a QUEUE event * @addr: endpoint address * @req: USB request * @status: status */ void dwc3_dbg_queue(struct dwc3 *dwc, u8 ep_num, const struct usb_request *req, int status) { if (!allow_dbg_print(ep_num)) return; if (req != NULL) { ipc_log_string(dwc->dwc_ipc_log_ctxt, "%02X %-25.25s %4i ?\t%d %d", ep_num, "QUEUE", status, !req->no_interrupt, req->length); } } /** * dwc3_dbg_setup: prints a SETUP event * @addr: endpoint address * @req: setup request */ void dwc3_dbg_setup(struct dwc3 *dwc, u8 ep_num, const struct usb_ctrlrequest *req) { if (!allow_dbg_print(ep_num)) return; if (req != NULL) { ipc_log_string(dwc->dwc_ipc_log_ctxt, "%02X %-25.25s ?\t%02X %02X %04X %04X %d", ep_num, "SETUP", req->bRequestType, req->bRequest, le16_to_cpu(req->wValue), le16_to_cpu(req->wIndex), le16_to_cpu(req->wLength)); } } /** * dwc3_dbg_print_reg: prints a reg value * @name: reg name * @reg: reg value to be printed */ void dwc3_dbg_print_reg(struct dwc3 *dwc, const char *name, int reg) { if (name == NULL) return; ipc_log_string(dwc->dwc_ipc_log_ctxt, "%s = 0x%08x", name, reg); }