summaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/Kconfig8
-rw-r--r--drivers/usb/host/Makefile5
-rw-r--r--drivers/usb/host/ehci-omap.c3
-rw-r--r--drivers/usb/host/ehci-sysfs.c12
-rw-r--r--drivers/usb/host/fotg210-hcd.c14
-rw-r--r--drivers/usb/host/ohci-da8xx.c2
-rw-r--r--drivers/usb/host/uhci-hcd.c3
-rw-r--r--drivers/usb/host/uhci-hcd.h3
-rw-r--r--drivers/usb/host/uhci-platform.c23
-rw-r--r--drivers/usb/host/uhci-q.c3
-rw-r--r--drivers/usb/host/whci/asl.c2
-rw-r--r--drivers/usb/host/xhci-dbg.c261
-rw-r--r--drivers/usb/host/xhci-dbgcap.c996
-rw-r--r--drivers/usb/host/xhci-dbgcap.h229
-rw-r--r--drivers/usb/host/xhci-dbgtty.c497
-rw-r--r--drivers/usb/host/xhci-hub.c8
-rw-r--r--drivers/usb/host/xhci-mem.c132
-rw-r--r--drivers/usb/host/xhci-mtk.c186
-rw-r--r--drivers/usb/host/xhci-mtk.h6
-rw-r--r--drivers/usb/host/xhci-pci.c3
-rw-r--r--drivers/usb/host/xhci-plat.c5
-rw-r--r--drivers/usb/host/xhci-ring.c14
-rw-r--r--drivers/usb/host/xhci-trace.h69
-rw-r--r--drivers/usb/host/xhci.c48
-rw-r--r--drivers/usb/host/xhci.h30
25 files changed, 2050 insertions, 512 deletions
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index b80a94e632af..6150bed7cfa8 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -27,6 +27,14 @@ config USB_XHCI_HCD
module will be called xhci-hcd.
if USB_XHCI_HCD
+config USB_XHCI_DBGCAP
+ bool "xHCI support for debug capability"
+ depends on TTY
+ ---help---
+ Say 'Y' to enable the support for the xHCI debug capability. Make
+ sure that your xHCI host supports the extended debug capability and
+ you want a TTY serial device based on the xHCI debug capability
+ before enabling this option. If unsure, say 'N'.
config USB_XHCI_PCI
tristate
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 32b036e2ffef..4ede4ce12366 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -14,6 +14,11 @@ fhci-$(CONFIG_FHCI_DEBUG) += fhci-dbg.o
xhci-hcd-y := xhci.o xhci-mem.o
xhci-hcd-y += xhci-ring.o xhci-hub.o xhci-dbg.o
xhci-hcd-y += xhci-trace.o
+
+ifneq ($(CONFIG_USB_XHCI_DBGCAP), )
+ xhci-hcd-y += xhci-dbgcap.o xhci-dbgtty.o
+endif
+
ifneq ($(CONFIG_USB_XHCI_MTK), )
xhci-hcd-y += xhci-mtk-sch.o
endif
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 854b146a457d..8d8bafc70c1f 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -167,7 +167,8 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
continue;
ret = PTR_ERR(phy);
- dev_err(dev, "Can't get PHY device for port %d: %d\n",
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "Can't get PHY for port %d: %d\n",
i, ret);
goto err_phy;
}
diff --git a/drivers/usb/host/ehci-sysfs.c b/drivers/usb/host/ehci-sysfs.c
index 71fb61dd4a87..8f75cb7b197c 100644
--- a/drivers/usb/host/ehci-sysfs.c
+++ b/drivers/usb/host/ehci-sysfs.c
@@ -7,7 +7,7 @@
/* Display the ports dedicated to the companion controller */
-static ssize_t show_companion(struct device *dev,
+static ssize_t companion_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
@@ -34,7 +34,7 @@ static ssize_t show_companion(struct device *dev,
* Syntax is "[-]portnum", where a leading '-' sign means
* return control of the port to the EHCI controller.
*/
-static ssize_t store_companion(struct device *dev,
+static ssize_t companion_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
@@ -59,13 +59,13 @@ static ssize_t store_companion(struct device *dev,
set_owner(ehci, portnum, new_owner);
return count;
}
-static DEVICE_ATTR(companion, 0644, show_companion, store_companion);
+static DEVICE_ATTR_RW(companion);
/*
* Display / Set uframe_periodic_max
*/
-static ssize_t show_uframe_periodic_max(struct device *dev,
+static ssize_t uframe_periodic_max_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
@@ -78,7 +78,7 @@ static ssize_t show_uframe_periodic_max(struct device *dev,
}
-static ssize_t store_uframe_periodic_max(struct device *dev,
+static ssize_t uframe_periodic_max_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
@@ -143,7 +143,7 @@ out_unlock:
spin_unlock_irqrestore (&ehci->lock, flags);
return ret;
}
-static DEVICE_ATTR(uframe_periodic_max, 0644, show_uframe_periodic_max, store_uframe_periodic_max);
+static DEVICE_ATTR_RW(uframe_periodic_max);
static inline int create_sysfs_files(struct ehci_hcd *ehci)
diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c
index 62fc955085a1..d8abf401918a 100644
--- a/drivers/usb/host/fotg210-hcd.c
+++ b/drivers/usb/host/fotg210-hcd.c
@@ -1865,11 +1865,9 @@ static struct fotg210_qh *fotg210_qh_alloc(struct fotg210_hcd *fotg210,
qh = kzalloc(sizeof(*qh), GFP_ATOMIC);
if (!qh)
goto done;
- qh->hw = (struct fotg210_qh_hw *)
- dma_pool_alloc(fotg210->qh_pool, flags, &dma);
+ qh->hw = dma_pool_zalloc(fotg210->qh_pool, flags, &dma);
if (!qh->hw)
goto fail;
- memset(qh->hw, 0, sizeof(*qh->hw));
qh->qh_dma = dma;
INIT_LIST_HEAD(&qh->qtd_list);
@@ -4121,7 +4119,7 @@ static int itd_urb_transaction(struct fotg210_iso_stream *stream,
} else {
alloc_itd:
spin_unlock_irqrestore(&fotg210->lock, flags);
- itd = dma_pool_alloc(fotg210->itd_pool, mem_flags,
+ itd = dma_pool_zalloc(fotg210->itd_pool, mem_flags,
&itd_dma);
spin_lock_irqsave(&fotg210->lock, flags);
if (!itd) {
@@ -4131,7 +4129,6 @@ alloc_itd:
}
}
- memset(itd, 0, sizeof(*itd));
itd->itd_dma = itd_dma;
list_add(&itd->itd_list, &sched->td_list);
}
@@ -4696,7 +4693,7 @@ static void scan_isoc(struct fotg210_hcd *fotg210)
/* Display / Set uframe_periodic_max
*/
-static ssize_t show_uframe_periodic_max(struct device *dev,
+static ssize_t uframe_periodic_max_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct fotg210_hcd *fotg210;
@@ -4708,7 +4705,7 @@ static ssize_t show_uframe_periodic_max(struct device *dev,
}
-static ssize_t store_uframe_periodic_max(struct device *dev,
+static ssize_t uframe_periodic_max_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct fotg210_hcd *fotg210;
@@ -4775,8 +4772,7 @@ out_unlock:
return ret;
}
-static DEVICE_ATTR(uframe_periodic_max, 0644, show_uframe_periodic_max,
- store_uframe_periodic_max);
+static DEVICE_ATTR_RW(uframe_periodic_max);
static inline int create_sysfs_files(struct fotg210_hcd *fotg210)
{
diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
index 0c507a0cfe1f..a55cbba40a5a 100644
--- a/drivers/usb/host/ohci-da8xx.c
+++ b/drivers/usb/host/ohci-da8xx.c
@@ -413,7 +413,7 @@ static int ohci_da8xx_probe(struct platform_device *pdev)
da8xx_ohci = to_da8xx_ohci(hcd);
da8xx_ohci->hcd = hcd;
- da8xx_ohci->usb11_clk = devm_clk_get(&pdev->dev, "usb11");
+ da8xx_ohci->usb11_clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(da8xx_ohci->usb11_clk)) {
error = PTR_ERR(da8xx_ohci->usb11_clk);
if (error != -EPROBE_DEFER)
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index f5c90217777a..f9c3947577fc 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -600,7 +600,7 @@ static int uhci_start(struct usb_hcd *hcd)
uhci->dentry = dentry;
#endif
- uhci->frame = dma_alloc_coherent(uhci_dev(uhci),
+ uhci->frame = dma_zalloc_coherent(uhci_dev(uhci),
UHCI_NUMFRAMES * sizeof(*uhci->frame),
&uhci->frame_dma_handle, GFP_KERNEL);
if (!uhci->frame) {
@@ -608,7 +608,6 @@ static int uhci_start(struct usb_hcd *hcd)
"unable to allocate consistent memory for frame list\n");
goto err_alloc_frame;
}
- memset(uhci->frame, 0, UHCI_NUMFRAMES * sizeof(*uhci->frame));
uhci->frame_cpu = kcalloc(UHCI_NUMFRAMES, sizeof(*uhci->frame_cpu),
GFP_KERNEL);
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index f1cc47292a59..7f9f33c8c232 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -4,6 +4,7 @@
#include <linux/list.h>
#include <linux/usb.h>
+#include <linux/clk.h>
#define usb_packetid(pipe) (usb_pipein(pipe) ? USB_PID_IN : USB_PID_OUT)
#define PIPE_DEVEP_MASK 0x0007ff00
@@ -447,6 +448,8 @@ struct uhci_hcd {
int total_load; /* Sum of array values */
short load[MAX_PHASE]; /* Periodic allocations */
+ struct clk *clk; /* (optional) clock source */
+
/* Reset host controller */
void (*reset_hc) (struct uhci_hcd *uhci);
int (*check_and_reset_hc) (struct uhci_hcd *uhci);
diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c
index 6cb16d4b2257..89700e26fb29 100644
--- a/drivers/usb/host/uhci-platform.c
+++ b/drivers/usb/host/uhci-platform.c
@@ -89,6 +89,8 @@ static int uhci_hcd_platform_probe(struct platform_device *pdev)
if (!hcd)
return -ENOMEM;
+ uhci = hcd_to_uhci(hcd);
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
hcd->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(hcd->regs)) {
@@ -98,8 +100,6 @@ static int uhci_hcd_platform_probe(struct platform_device *pdev)
hcd->rsrc_start = res->start;
hcd->rsrc_len = resource_size(res);
- uhci = hcd_to_uhci(hcd);
-
uhci->regs = hcd->regs;
/* Grab some things from the device-tree */
@@ -119,13 +119,28 @@ static int uhci_hcd_platform_probe(struct platform_device *pdev)
"Enabled Aspeed implementation workarounds\n");
}
}
+
+ /* Get and enable clock if any specified */
+ uhci->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(uhci->clk)) {
+ ret = PTR_ERR(uhci->clk);
+ goto err_rmr;
+ }
+ ret = clk_prepare_enable(uhci->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "Error couldn't enable clock (%d)\n", ret);
+ goto err_rmr;
+ }
+
ret = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_SHARED);
if (ret)
- goto err_rmr;
+ goto err_clk;
device_wakeup_enable(hcd->self.controller);
return 0;
+err_clk:
+ clk_disable_unprepare(uhci->clk);
err_rmr:
usb_put_hcd(hcd);
@@ -135,7 +150,9 @@ err_rmr:
static int uhci_hcd_platform_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ clk_disable_unprepare(uhci->clk);
usb_remove_hcd(hcd);
usb_put_hcd(hcd);
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index d40438238938..35fcb826152c 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -73,8 +73,7 @@ static void uhci_add_fsbr(struct uhci_hcd *uhci, struct urb *urb)
{
struct urb_priv *urbp = urb->hcpriv;
- if (!(urb->transfer_flags & URB_NO_FSBR))
- urbp->fsbr = 1;
+ urbp->fsbr = 1;
}
static void uhci_urbp_wants_fsbr(struct uhci_hcd *uhci, struct urb_priv *urbp)
diff --git a/drivers/usb/host/whci/asl.c b/drivers/usb/host/whci/asl.c
index c5ac9efb076a..276fb34c8efd 100644
--- a/drivers/usb/host/whci/asl.c
+++ b/drivers/usb/host/whci/asl.c
@@ -90,9 +90,7 @@ static uint32_t process_qset(struct whc *whc, struct whc_qset *qset)
while (qset->ntds) {
struct whc_qtd *td;
- int t;
- t = qset->td_start;
td = &qset->qtd[qset->td_start];
status = le32_to_cpu(td->status);
diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c
index 584d7b9a3683..386abf26641d 100644
--- a/drivers/usb/host/xhci-dbg.c
+++ b/drivers/usb/host/xhci-dbg.c
@@ -10,267 +10,6 @@
#include "xhci.h"
-#define XHCI_INIT_VALUE 0x0
-
-/* Add verbose debugging later, just print everything for now */
-
-void xhci_dbg_regs(struct xhci_hcd *xhci)
-{
- u32 temp;
-
- xhci_dbg(xhci, "// xHCI capability registers at %p:\n",
- xhci->cap_regs);
- temp = readl(&xhci->cap_regs->hc_capbase);
- xhci_dbg(xhci, "// @%p = 0x%x (CAPLENGTH AND HCIVERSION)\n",
- &xhci->cap_regs->hc_capbase, temp);
- xhci_dbg(xhci, "// CAPLENGTH: 0x%x\n",
- (unsigned int) HC_LENGTH(temp));
- xhci_dbg(xhci, "// HCIVERSION: 0x%x\n",
- (unsigned int) HC_VERSION(temp));
-
- xhci_dbg(xhci, "// xHCI operational registers at %p:\n", xhci->op_regs);
-
- temp = readl(&xhci->cap_regs->run_regs_off);
- xhci_dbg(xhci, "// @%p = 0x%x RTSOFF\n",
- &xhci->cap_regs->run_regs_off,
- (unsigned int) temp & RTSOFF_MASK);
- xhci_dbg(xhci, "// xHCI runtime registers at %p:\n", xhci->run_regs);
-
- temp = readl(&xhci->cap_regs->db_off);
- xhci_dbg(xhci, "// @%p = 0x%x DBOFF\n", &xhci->cap_regs->db_off, temp);
- xhci_dbg(xhci, "// Doorbell array at %p:\n", xhci->dba);
-}
-
-static void xhci_print_cap_regs(struct xhci_hcd *xhci)
-{
- u32 temp;
- u32 hci_version;
-
- xhci_dbg(xhci, "xHCI capability registers at %p:\n", xhci->cap_regs);
-
- temp = readl(&xhci->cap_regs->hc_capbase);
- hci_version = HC_VERSION(temp);
- xhci_dbg(xhci, "CAPLENGTH AND HCIVERSION 0x%x:\n",
- (unsigned int) temp);
- xhci_dbg(xhci, "CAPLENGTH: 0x%x\n",
- (unsigned int) HC_LENGTH(temp));
- xhci_dbg(xhci, "HCIVERSION: 0x%x\n", hci_version);
-
- temp = readl(&xhci->cap_regs->hcs_params1);
- xhci_dbg(xhci, "HCSPARAMS 1: 0x%x\n",
- (unsigned int) temp);
- xhci_dbg(xhci, " Max device slots: %u\n",
- (unsigned int) HCS_MAX_SLOTS(temp));
- xhci_dbg(xhci, " Max interrupters: %u\n",
- (unsigned int) HCS_MAX_INTRS(temp));
- xhci_dbg(xhci, " Max ports: %u\n",
- (unsigned int) HCS_MAX_PORTS(temp));
-
- temp = readl(&xhci->cap_regs->hcs_params2);
- xhci_dbg(xhci, "HCSPARAMS 2: 0x%x\n",
- (unsigned int) temp);
- xhci_dbg(xhci, " Isoc scheduling threshold: %u\n",
- (unsigned int) HCS_IST(temp));
- xhci_dbg(xhci, " Maximum allowed segments in event ring: %u\n",
- (unsigned int) HCS_ERST_MAX(temp));
-
- temp = readl(&xhci->cap_regs->hcs_params3);
- xhci_dbg(xhci, "HCSPARAMS 3 0x%x:\n",
- (unsigned int) temp);
- xhci_dbg(xhci, " Worst case U1 device exit latency: %u\n",
- (unsigned int) HCS_U1_LATENCY(temp));
- xhci_dbg(xhci, " Worst case U2 device exit latency: %u\n",
- (unsigned int) HCS_U2_LATENCY(temp));
-
- temp = readl(&xhci->cap_regs->hcc_params);
- xhci_dbg(xhci, "HCC PARAMS 0x%x:\n", (unsigned int) temp);
- xhci_dbg(xhci, " HC generates %s bit addresses\n",
- HCC_64BIT_ADDR(temp) ? "64" : "32");
- xhci_dbg(xhci, " HC %s Contiguous Frame ID Capability\n",
- HCC_CFC(temp) ? "has" : "hasn't");
- xhci_dbg(xhci, " HC %s generate Stopped - Short Package event\n",
- HCC_SPC(temp) ? "can" : "can't");
- /* FIXME */
- xhci_dbg(xhci, " FIXME: more HCCPARAMS debugging\n");
-
- temp = readl(&xhci->cap_regs->run_regs_off);
- xhci_dbg(xhci, "RTSOFF 0x%x:\n", temp & RTSOFF_MASK);
-
- /* xhci 1.1 controllers have the HCCPARAMS2 register */
- if (hci_version > 0x100) {
- temp = readl(&xhci->cap_regs->hcc_params2);
- xhci_dbg(xhci, "HCC PARAMS2 0x%x:\n", (unsigned int) temp);
- xhci_dbg(xhci, " HC %s Force save context capability",
- HCC2_FSC(temp) ? "supports" : "doesn't support");
- xhci_dbg(xhci, " HC %s Large ESIT Payload Capability",
- HCC2_LEC(temp) ? "supports" : "doesn't support");
- xhci_dbg(xhci, " HC %s Extended TBC capability",
- HCC2_ETC(temp) ? "supports" : "doesn't support");
- }
-}
-
-static void xhci_print_command_reg(struct xhci_hcd *xhci)
-{
- u32 temp;
-
- temp = readl(&xhci->op_regs->command);
- xhci_dbg(xhci, "USBCMD 0x%x:\n", temp);
- xhci_dbg(xhci, " HC is %s\n",
- (temp & CMD_RUN) ? "running" : "being stopped");
- xhci_dbg(xhci, " HC has %sfinished hard reset\n",
- (temp & CMD_RESET) ? "not " : "");
- xhci_dbg(xhci, " Event Interrupts %s\n",
- (temp & CMD_EIE) ? "enabled " : "disabled");
- xhci_dbg(xhci, " Host System Error Interrupts %s\n",
- (temp & CMD_HSEIE) ? "enabled " : "disabled");
- xhci_dbg(xhci, " HC has %sfinished light reset\n",
- (temp & CMD_LRESET) ? "not " : "");
-}
-
-static void xhci_print_status(struct xhci_hcd *xhci)
-{
- u32 temp;
-
- temp = readl(&xhci->op_regs->status);
- xhci_dbg(xhci, "USBSTS 0x%x:\n", temp);
- xhci_dbg(xhci, " Event ring is %sempty\n",
- (temp & STS_EINT) ? "not " : "");
- xhci_dbg(xhci, " %sHost System Error\n",
- (temp & STS_FATAL) ? "WARNING: " : "No ");
- xhci_dbg(xhci, " HC is %s\n",
- (temp & STS_HALT) ? "halted" : "running");
-}
-
-static void xhci_print_op_regs(struct xhci_hcd *xhci)
-{
- xhci_dbg(xhci, "xHCI operational registers at %p:\n", xhci->op_regs);
- xhci_print_command_reg(xhci);
- xhci_print_status(xhci);
-}
-
-static void xhci_print_ports(struct xhci_hcd *xhci)
-{
- __le32 __iomem *addr;
- int i, j;
- int ports;
- char *names[NUM_PORT_REGS] = {
- "status",
- "power",
- "link",
- "reserved",
- };
-
- ports = HCS_MAX_PORTS(xhci->hcs_params1);
- addr = &xhci->op_regs->port_status_base;
- for (i = 0; i < ports; i++) {
- for (j = 0; j < NUM_PORT_REGS; j++) {
- xhci_dbg(xhci, "%p port %s reg = 0x%x\n",
- addr, names[j],
- (unsigned int) readl(addr));
- addr++;
- }
- }
-}
-
-void xhci_print_ir_set(struct xhci_hcd *xhci, int set_num)
-{
- struct xhci_intr_reg __iomem *ir_set = &xhci->run_regs->ir_set[set_num];
- void __iomem *addr;
- u32 temp;
- u64 temp_64;
-
- addr = &ir_set->irq_pending;
- temp = readl(addr);
- if (temp == XHCI_INIT_VALUE)
- return;
-
- xhci_dbg(xhci, " %p: ir_set[%i]\n", ir_set, set_num);
-
- xhci_dbg(xhci, " %p: ir_set.pending = 0x%x\n", addr,
- (unsigned int)temp);
-
- addr = &ir_set->irq_control;
- temp = readl(addr);
- xhci_dbg(xhci, " %p: ir_set.control = 0x%x\n", addr,
- (unsigned int)temp);
-
- addr = &ir_set->erst_size;
- temp = readl(addr);
- xhci_dbg(xhci, " %p: ir_set.erst_size = 0x%x\n", addr,
- (unsigned int)temp);
-
- addr = &ir_set->rsvd;
- temp = readl(addr);
- if (temp != XHCI_INIT_VALUE)
- xhci_dbg(xhci, " WARN: %p: ir_set.rsvd = 0x%x\n",
- addr, (unsigned int)temp);
-
- addr = &ir_set->erst_base;
- temp_64 = xhci_read_64(xhci, addr);
- xhci_dbg(xhci, " %p: ir_set.erst_base = @%08llx\n",
- addr, temp_64);
-
- addr = &ir_set->erst_dequeue;
- temp_64 = xhci_read_64(xhci, addr);
- xhci_dbg(xhci, " %p: ir_set.erst_dequeue = @%08llx\n",
- addr, temp_64);
-}
-
-void xhci_print_run_regs(struct xhci_hcd *xhci)
-{
- u32 temp;
- int i;
-
- xhci_dbg(xhci, "xHCI runtime registers at %p:\n", xhci->run_regs);
- temp = readl(&xhci->run_regs->microframe_index);
- xhci_dbg(xhci, " %p: Microframe index = 0x%x\n",
- &xhci->run_regs->microframe_index,
- (unsigned int) temp);
- for (i = 0; i < 7; i++) {
- temp = readl(&xhci->run_regs->rsvd[i]);
- if (temp != XHCI_INIT_VALUE)
- xhci_dbg(xhci, " WARN: %p: Rsvd[%i] = 0x%x\n",
- &xhci->run_regs->rsvd[i],
- i, (unsigned int) temp);
- }
-}
-
-void xhci_print_registers(struct xhci_hcd *xhci)
-{
- xhci_print_cap_regs(xhci);
- xhci_print_op_regs(xhci);
- xhci_print_ports(xhci);
-}
-
-void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst)
-{
- u64 addr = erst->erst_dma_addr;
- int i;
- struct xhci_erst_entry *entry;
-
- for (i = 0; i < erst->num_entries; i++) {
- entry = &erst->entries[i];
- xhci_dbg(xhci, "@%016llx %08x %08x %08x %08x\n",
- addr,
- lower_32_bits(le64_to_cpu(entry->seg_addr)),
- upper_32_bits(le64_to_cpu(entry->seg_addr)),
- le32_to_cpu(entry->seg_size),
- le32_to_cpu(entry->rsvd));
- addr += sizeof(*entry);
- }
-}
-
-void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci)
-{
- u64 val;
-
- val = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
- xhci_dbg(xhci, "// xHC command ring deq ptr low bits + flags = @%08x\n",
- lower_32_bits(val));
- xhci_dbg(xhci, "// xHC command ring deq ptr high bits = @%08x\n",
- upper_32_bits(val));
-}
-
char *xhci_get_slot_state(struct xhci_hcd *xhci,
struct xhci_container_ctx *ctx)
{
diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c
new file mode 100644
index 000000000000..a1ab8acf39ba
--- /dev/null
+++ b/drivers/usb/host/xhci-dbgcap.c
@@ -0,0 +1,996 @@
+/**
+ * xhci-dbgcap.c - xHCI debug capability support
+ *
+ * Copyright (C) 2017 Intel Corporation
+ *
+ * Author: Lu Baolu <baolu.lu@linux.intel.com>
+ */
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/nls.h>
+
+#include "xhci.h"
+#include "xhci-trace.h"
+#include "xhci-dbgcap.h"
+
+static inline void *
+dbc_dma_alloc_coherent(struct xhci_hcd *xhci, size_t size,
+ dma_addr_t *dma_handle, gfp_t flags)
+{
+ void *vaddr;
+
+ vaddr = dma_alloc_coherent(xhci_to_hcd(xhci)->self.sysdev,
+ size, dma_handle, flags);
+ memset(vaddr, 0, size);
+ return vaddr;
+}
+
+static inline void
+dbc_dma_free_coherent(struct xhci_hcd *xhci, size_t size,
+ void *cpu_addr, dma_addr_t dma_handle)
+{
+ if (cpu_addr)
+ dma_free_coherent(xhci_to_hcd(xhci)->self.sysdev,
+ size, cpu_addr, dma_handle);
+}
+
+static u32 xhci_dbc_populate_strings(struct dbc_str_descs *strings)
+{
+ struct usb_string_descriptor *s_desc;
+ u32 string_length;
+
+ /* Serial string: */
+ s_desc = (struct usb_string_descriptor *)strings->serial;
+ utf8s_to_utf16s(DBC_STRING_SERIAL, strlen(DBC_STRING_SERIAL),
+ UTF16_LITTLE_ENDIAN, (wchar_t *)s_desc->wData,
+ DBC_MAX_STRING_LENGTH);
+
+ s_desc->bLength = (strlen(DBC_STRING_SERIAL) + 1) * 2;
+ s_desc->bDescriptorType = USB_DT_STRING;
+ string_length = s_desc->bLength;
+ string_length <<= 8;
+
+ /* Product string: */
+ s_desc = (struct usb_string_descriptor *)strings->product;
+ utf8s_to_utf16s(DBC_STRING_PRODUCT, strlen(DBC_STRING_PRODUCT),
+ UTF16_LITTLE_ENDIAN, (wchar_t *)s_desc->wData,
+ DBC_MAX_STRING_LENGTH);
+
+ s_desc->bLength = (strlen(DBC_STRING_PRODUCT) + 1) * 2;
+ s_desc->bDescriptorType = USB_DT_STRING;
+ string_length += s_desc->bLength;
+ string_length <<= 8;
+
+ /* Manufacture string: */
+ s_desc = (struct usb_string_descriptor *)strings->manufacturer;
+ utf8s_to_utf16s(DBC_STRING_MANUFACTURER,
+ strlen(DBC_STRING_MANUFACTURER),
+ UTF16_LITTLE_ENDIAN, (wchar_t *)s_desc->wData,
+ DBC_MAX_STRING_LENGTH);
+
+ s_desc->bLength = (strlen(DBC_STRING_MANUFACTURER) + 1) * 2;
+ s_desc->bDescriptorType = USB_DT_STRING;
+ string_length += s_desc->bLength;
+ string_length <<= 8;
+
+ /* String0: */
+ strings->string0[0] = 4;
+ strings->string0[1] = USB_DT_STRING;
+ strings->string0[2] = 0x09;
+ strings->string0[3] = 0x04;
+ string_length += 4;
+
+ return string_length;
+}
+
+static void xhci_dbc_init_contexts(struct xhci_hcd *xhci, u32 string_length)
+{
+ struct xhci_dbc *dbc;
+ struct dbc_info_context *info;
+ struct xhci_ep_ctx *ep_ctx;
+ u32 dev_info;
+ dma_addr_t deq, dma;
+ unsigned int max_burst;
+
+ dbc = xhci->dbc;
+ if (!dbc)
+ return;
+
+ /* Populate info Context: */
+ info = (struct dbc_info_context *)dbc->ctx->bytes;
+ dma = dbc->string_dma;
+ info->string0 = cpu_to_le64(dma);
+ info->manufacturer = cpu_to_le64(dma + DBC_MAX_STRING_LENGTH);
+ info->product = cpu_to_le64(dma + DBC_MAX_STRING_LENGTH * 2);
+ info->serial = cpu_to_le64(dma + DBC_MAX_STRING_LENGTH * 3);
+ info->length = cpu_to_le32(string_length);
+
+ /* Populate bulk out endpoint context: */
+ ep_ctx = dbc_bulkout_ctx(dbc);
+ max_burst = DBC_CTRL_MAXBURST(readl(&dbc->regs->control));
+ deq = dbc_bulkout_enq(dbc);
+ ep_ctx->ep_info = 0;
+ ep_ctx->ep_info2 = dbc_epctx_info2(BULK_OUT_EP, 1024, max_burst);
+ ep_ctx->deq = cpu_to_le64(deq | dbc->ring_out->cycle_state);
+
+ /* Populate bulk in endpoint context: */
+ ep_ctx = dbc_bulkin_ctx(dbc);
+ deq = dbc_bulkin_enq(dbc);
+ ep_ctx->ep_info = 0;
+ ep_ctx->ep_info2 = dbc_epctx_info2(BULK_IN_EP, 1024, max_burst);
+ ep_ctx->deq = cpu_to_le64(deq | dbc->ring_in->cycle_state);
+
+ /* Set DbC context and info registers: */
+ xhci_write_64(xhci, dbc->ctx->dma, &dbc->regs->dccp);
+
+ dev_info = cpu_to_le32((DBC_VENDOR_ID << 16) | DBC_PROTOCOL);
+ writel(dev_info, &dbc->regs->devinfo1);
+
+ dev_info = cpu_to_le32((DBC_DEVICE_REV << 16) | DBC_PRODUCT_ID);
+ writel(dev_info, &dbc->regs->devinfo2);
+}
+
+static void xhci_dbc_giveback(struct dbc_request *req, int status)
+ __releases(&dbc->lock)
+ __acquires(&dbc->lock)
+{
+ struct dbc_ep *dep = req->dep;
+ struct xhci_dbc *dbc = dep->dbc;
+ struct xhci_hcd *xhci = dbc->xhci;
+ struct device *dev = xhci_to_hcd(dbc->xhci)->self.sysdev;
+
+ list_del_init(&req->list_pending);
+ req->trb_dma = 0;
+ req->trb = NULL;
+
+ if (req->status == -EINPROGRESS)
+ req->status = status;
+
+ trace_xhci_dbc_giveback_request(req);
+
+ dma_unmap_single(dev,
+ req->dma,
+ req->length,
+ dbc_ep_dma_direction(dep));
+
+ /* Give back the transfer request: */
+ spin_unlock(&dbc->lock);
+ req->complete(xhci, req);
+ spin_lock(&dbc->lock);
+}
+
+static void xhci_dbc_flush_single_request(struct dbc_request *req)
+{
+ union xhci_trb *trb = req->trb;
+
+ trb->generic.field[0] = 0;
+ trb->generic.field[1] = 0;
+ trb->generic.field[2] = 0;
+ trb->generic.field[3] &= cpu_to_le32(TRB_CYCLE);
+ trb->generic.field[3] |= cpu_to_le32(TRB_TYPE(TRB_TR_NOOP));
+
+ xhci_dbc_giveback(req, -ESHUTDOWN);
+}
+
+static void xhci_dbc_flush_endpoint_requests(struct dbc_ep *dep)
+{
+ struct dbc_request *req, *tmp;
+
+ list_for_each_entry_safe(req, tmp, &dep->list_pending, list_pending)
+ xhci_dbc_flush_single_request(req);
+}
+
+static void xhci_dbc_flush_reqests(struct xhci_dbc *dbc)
+{
+ xhci_dbc_flush_endpoint_requests(&dbc->eps[BULK_OUT]);
+ xhci_dbc_flush_endpoint_requests(&dbc->eps[BULK_IN]);
+}
+
+struct dbc_request *
+dbc_alloc_request(struct dbc_ep *dep, gfp_t gfp_flags)
+{
+ struct dbc_request *req;
+
+ req = kzalloc(sizeof(*req), gfp_flags);
+ if (!req)
+ return NULL;
+
+ req->dep = dep;
+ INIT_LIST_HEAD(&req->list_pending);
+ INIT_LIST_HEAD(&req->list_pool);
+ req->direction = dep->direction;
+
+ trace_xhci_dbc_alloc_request(req);
+
+ return req;
+}
+
+void
+dbc_free_request(struct dbc_ep *dep, struct dbc_request *req)
+{
+ trace_xhci_dbc_free_request(req);
+
+ kfree(req);
+}
+
+static void
+xhci_dbc_queue_trb(struct xhci_ring *ring, u32 field1,
+ u32 field2, u32 field3, u32 field4)
+{
+ union xhci_trb *trb, *next;
+
+ trb = ring->enqueue;
+ trb->generic.field[0] = cpu_to_le32(field1);
+ trb->generic.field[1] = cpu_to_le32(field2);
+ trb->generic.field[2] = cpu_to_le32(field3);
+ trb->generic.field[3] = cpu_to_le32(field4);
+
+ trace_xhci_dbc_gadget_ep_queue(ring, &trb->generic);
+
+ ring->num_trbs_free--;
+ next = ++(ring->enqueue);
+ if (TRB_TYPE_LINK_LE32(next->link.control)) {
+ next->link.control ^= cpu_to_le32(TRB_CYCLE);
+ ring->enqueue = ring->enq_seg->trbs;
+ ring->cycle_state ^= 1;
+ }
+}
+
+static int xhci_dbc_queue_bulk_tx(struct dbc_ep *dep,
+ struct dbc_request *req)
+{
+ u64 addr;
+ union xhci_trb *trb;
+ unsigned int num_trbs;
+ struct xhci_dbc *dbc = dep->dbc;
+ struct xhci_ring *ring = dep->ring;
+ u32 length, control, cycle;
+
+ num_trbs = count_trbs(req->dma, req->length);
+ WARN_ON(num_trbs != 1);
+ if (ring->num_trbs_free < num_trbs)
+ return -EBUSY;
+
+ addr = req->dma;
+ trb = ring->enqueue;
+ cycle = ring->cycle_state;
+ length = TRB_LEN(req->length);
+ control = TRB_TYPE(TRB_NORMAL) | TRB_IOC;
+
+ if (cycle)
+ control &= cpu_to_le32(~TRB_CYCLE);
+ else
+ control |= cpu_to_le32(TRB_CYCLE);
+
+ req->trb = ring->enqueue;
+ req->trb_dma = xhci_trb_virt_to_dma(ring->enq_seg, ring->enqueue);
+ xhci_dbc_queue_trb(ring,
+ lower_32_bits(addr),
+ upper_32_bits(addr),
+ length, control);
+
+ /*
+ * Add a barrier between writes of trb fields and flipping
+ * the cycle bit:
+ */
+ wmb();
+
+ if (cycle)
+ trb->generic.field[3] |= cpu_to_le32(TRB_CYCLE);
+ else
+ trb->generic.field[3] &= cpu_to_le32(~TRB_CYCLE);
+
+ writel(DBC_DOOR_BELL_TARGET(dep->direction), &dbc->regs->doorbell);
+
+ return 0;
+}
+
+static int
+dbc_ep_do_queue(struct dbc_ep *dep, struct dbc_request *req)
+{
+ int ret;
+ struct device *dev;
+ struct xhci_dbc *dbc = dep->dbc;
+ struct xhci_hcd *xhci = dbc->xhci;
+
+ dev = xhci_to_hcd(xhci)->self.sysdev;
+
+ if (!req->length || !req->buf)
+ return -EINVAL;
+
+ req->actual = 0;
+ req->status = -EINPROGRESS;
+
+ req->dma = dma_map_single(dev,
+ req->buf,
+ req->length,
+ dbc_ep_dma_direction(dep));
+ if (dma_mapping_error(dev, req->dma)) {
+ xhci_err(xhci, "failed to map buffer\n");
+ return -EFAULT;
+ }
+
+ ret = xhci_dbc_queue_bulk_tx(dep, req);
+ if (ret) {
+ xhci_err(xhci, "failed to queue trbs\n");
+ dma_unmap_single(dev,
+ req->dma,
+ req->length,
+ dbc_ep_dma_direction(dep));
+ return -EFAULT;
+ }
+
+ list_add_tail(&req->list_pending, &dep->list_pending);
+
+ return 0;
+}
+