Merge branch 'origin' into for-linus
Conflicts: MAINTAINERS
This commit is contained in:
@@ -113,6 +113,12 @@ config USB_EHCI_HCD_PPC_OF
|
||||
Enables support for the USB controller present on the PowerPC
|
||||
OpenFirmware platform bus.
|
||||
|
||||
config USB_W90X900_EHCI
|
||||
bool "W90X900(W90P910) EHCI support"
|
||||
depends on USB_EHCI_HCD && ARCH_W90X900
|
||||
---help---
|
||||
Enables support for the W90X900 USB controller
|
||||
|
||||
config USB_OXU210HP_HCD
|
||||
tristate "OXU210HP HCD support"
|
||||
depends on USB
|
||||
@@ -153,6 +159,18 @@ config USB_ISP1760_HCD
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called isp1760.
|
||||
|
||||
config USB_ISP1362_HCD
|
||||
tristate "ISP1362 HCD support"
|
||||
depends on USB
|
||||
default N
|
||||
---help---
|
||||
Supports the Philips ISP1362 chip as a host controller
|
||||
|
||||
This driver does not support isochronous transfers.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called isp1362-hcd.
|
||||
|
||||
config USB_OHCI_HCD
|
||||
tristate "OHCI HCD support"
|
||||
depends on USB && USB_ARCH_HAS_OHCI
|
||||
@@ -336,13 +354,6 @@ config USB_R8A66597_HCD
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called r8a66597-hcd.
|
||||
|
||||
config SUPERH_ON_CHIP_R8A66597
|
||||
boolean "Enable SuperH on-chip R8A66597 USB"
|
||||
depends on USB_R8A66597_HCD && (CPU_SUBTYPE_SH7366 || CPU_SUBTYPE_SH7723 || CPU_SUBTYPE_SH7724)
|
||||
help
|
||||
This driver enables support for the on-chip R8A66597 in the
|
||||
SH7366, SH7723 and SH7724 processors.
|
||||
|
||||
config USB_WHCI_HCD
|
||||
tristate "Wireless USB Host Controller Interface (WHCI) driver (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
|
@@ -21,6 +21,7 @@ obj-$(CONFIG_PCI) += pci-quirks.o
|
||||
obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
|
||||
obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
|
||||
obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
|
||||
obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o
|
||||
obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o
|
||||
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o
|
||||
obj-$(CONFIG_USB_FHCI_HCD) += fhci.o
|
||||
|
230
drivers/usb/host/ehci-atmel.c
Normal file
230
drivers/usb/host/ehci-atmel.c
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Driver for EHCI UHP on Atmel chips
|
||||
*
|
||||
* Copyright (C) 2009 Atmel Corporation,
|
||||
* Nicolas Ferre <nicolas.ferre@atmel.com>
|
||||
*
|
||||
* Based on various ehci-*.c drivers
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file COPYING in the main directory of this archive for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
/* interface and function clocks */
|
||||
static struct clk *iclk, *fclk;
|
||||
static int clocked;
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static void atmel_start_clock(void)
|
||||
{
|
||||
clk_enable(iclk);
|
||||
clk_enable(fclk);
|
||||
clocked = 1;
|
||||
}
|
||||
|
||||
static void atmel_stop_clock(void)
|
||||
{
|
||||
clk_disable(fclk);
|
||||
clk_disable(iclk);
|
||||
clocked = 0;
|
||||
}
|
||||
|
||||
static void atmel_start_ehci(struct platform_device *pdev)
|
||||
{
|
||||
dev_dbg(&pdev->dev, "start\n");
|
||||
atmel_start_clock();
|
||||
}
|
||||
|
||||
static void atmel_stop_ehci(struct platform_device *pdev)
|
||||
{
|
||||
dev_dbg(&pdev->dev, "stop\n");
|
||||
atmel_stop_clock();
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static int ehci_atmel_setup(struct usb_hcd *hcd)
|
||||
{
|
||||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
int retval = 0;
|
||||
|
||||
/* registers start at offset 0x0 */
|
||||
ehci->caps = hcd->regs;
|
||||
ehci->regs = hcd->regs +
|
||||
HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
|
||||
dbg_hcs_params(ehci, "reset");
|
||||
dbg_hcc_params(ehci, "reset");
|
||||
|
||||
/* cache this readonly data; minimize chip reads */
|
||||
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
|
||||
|
||||
retval = ehci_halt(ehci);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
/* data structure init */
|
||||
retval = ehci_init(hcd);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
ehci->sbrn = 0x20;
|
||||
|
||||
ehci_reset(ehci);
|
||||
ehci_port_power(ehci, 0);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static const struct hc_driver ehci_atmel_hc_driver = {
|
||||
.description = hcd_name,
|
||||
.product_desc = "Atmel EHCI UHP HS",
|
||||
.hcd_priv_size = sizeof(struct ehci_hcd),
|
||||
|
||||
/* generic hardware linkage */
|
||||
.irq = ehci_irq,
|
||||
.flags = HCD_MEMORY | HCD_USB2,
|
||||
|
||||
/* basic lifecycle operations */
|
||||
.reset = ehci_atmel_setup,
|
||||
.start = ehci_run,
|
||||
.stop = ehci_stop,
|
||||
.shutdown = ehci_shutdown,
|
||||
|
||||
/* managing i/o requests and associated device resources */
|
||||
.urb_enqueue = ehci_urb_enqueue,
|
||||
.urb_dequeue = ehci_urb_dequeue,
|
||||
.endpoint_disable = ehci_endpoint_disable,
|
||||
|
||||
/* scheduling support */
|
||||
.get_frame_number = ehci_get_frame,
|
||||
|
||||
/* root hub support */
|
||||
.hub_status_data = ehci_hub_status_data,
|
||||
.hub_control = ehci_hub_control,
|
||||
.bus_suspend = ehci_bus_suspend,
|
||||
.bus_resume = ehci_bus_resume,
|
||||
.relinquish_port = ehci_relinquish_port,
|
||||
.port_handed_over = ehci_port_handed_over,
|
||||
};
|
||||
|
||||
static int __init ehci_atmel_drv_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct usb_hcd *hcd;
|
||||
const struct hc_driver *driver = &ehci_atmel_hc_driver;
|
||||
struct resource *res;
|
||||
int irq;
|
||||
int retval;
|
||||
|
||||
if (usb_disabled())
|
||||
return -ENODEV;
|
||||
|
||||
pr_debug("Initializing Atmel-SoC USB Host Controller\n");
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq <= 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"Found HC with no IRQ. Check %s setup!\n",
|
||||
dev_name(&pdev->dev));
|
||||
retval = -ENODEV;
|
||||
goto fail_create_hcd;
|
||||
}
|
||||
|
||||
hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
|
||||
if (!hcd) {
|
||||
retval = -ENOMEM;
|
||||
goto fail_create_hcd;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev,
|
||||
"Found HC with no register addr. Check %s setup!\n",
|
||||
dev_name(&pdev->dev));
|
||||
retval = -ENODEV;
|
||||
goto fail_request_resource;
|
||||
}
|
||||
hcd->rsrc_start = res->start;
|
||||
hcd->rsrc_len = res->end - res->start + 1;
|
||||
|
||||
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
|
||||
driver->description)) {
|
||||
dev_dbg(&pdev->dev, "controller already in use\n");
|
||||
retval = -EBUSY;
|
||||
goto fail_request_resource;
|
||||
}
|
||||
|
||||
hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
|
||||
if (hcd->regs == NULL) {
|
||||
dev_dbg(&pdev->dev, "error mapping memory\n");
|
||||
retval = -EFAULT;
|
||||
goto fail_ioremap;
|
||||
}
|
||||
|
||||
iclk = clk_get(&pdev->dev, "ehci_clk");
|
||||
if (IS_ERR(iclk)) {
|
||||
dev_err(&pdev->dev, "Error getting interface clock\n");
|
||||
retval = -ENOENT;
|
||||
goto fail_get_iclk;
|
||||
}
|
||||
fclk = clk_get(&pdev->dev, "uhpck");
|
||||
if (IS_ERR(fclk)) {
|
||||
dev_err(&pdev->dev, "Error getting function clock\n");
|
||||
retval = -ENOENT;
|
||||
goto fail_get_fclk;
|
||||
}
|
||||
|
||||
atmel_start_ehci(pdev);
|
||||
|
||||
retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
|
||||
if (retval)
|
||||
goto fail_add_hcd;
|
||||
|
||||
return retval;
|
||||
|
||||
fail_add_hcd:
|
||||
atmel_stop_ehci(pdev);
|
||||
clk_put(fclk);
|
||||
fail_get_fclk:
|
||||
clk_put(iclk);
|
||||
fail_get_iclk:
|
||||
iounmap(hcd->regs);
|
||||
fail_ioremap:
|
||||
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
fail_request_resource:
|
||||
usb_put_hcd(hcd);
|
||||
fail_create_hcd:
|
||||
dev_err(&pdev->dev, "init %s fail, %d\n",
|
||||
dev_name(&pdev->dev), retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int __exit ehci_atmel_drv_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct usb_hcd *hcd = platform_get_drvdata(pdev);
|
||||
|
||||
ehci_shutdown(hcd);
|
||||
usb_remove_hcd(hcd);
|
||||
iounmap(hcd->regs);
|
||||
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
usb_put_hcd(hcd);
|
||||
|
||||
atmel_stop_ehci(pdev);
|
||||
clk_put(fclk);
|
||||
clk_put(iclk);
|
||||
fclk = iclk = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver ehci_atmel_driver = {
|
||||
.probe = ehci_atmel_drv_probe,
|
||||
.remove = __exit_p(ehci_atmel_drv_remove),
|
||||
.shutdown = usb_hcd_platform_shutdown,
|
||||
.driver.name = "atmel-ehci",
|
||||
};
|
@@ -199,10 +199,9 @@ static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int ehci_hcd_au1xxx_drv_suspend(struct platform_device *pdev,
|
||||
pm_message_t message)
|
||||
static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
|
||||
{
|
||||
struct usb_hcd *hcd = platform_get_drvdata(pdev);
|
||||
struct usb_hcd *hcd = dev_get_drvdata(dev);
|
||||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
unsigned long flags;
|
||||
int rc;
|
||||
@@ -229,12 +228,6 @@ static int ehci_hcd_au1xxx_drv_suspend(struct platform_device *pdev,
|
||||
ehci_writel(ehci, 0, &ehci->regs->intr_enable);
|
||||
(void)ehci_readl(ehci, &ehci->regs->intr_enable);
|
||||
|
||||
/* make sure snapshot being resumed re-enumerates everything */
|
||||
if (message.event == PM_EVENT_PRETHAW) {
|
||||
ehci_halt(ehci);
|
||||
ehci_reset(ehci);
|
||||
}
|
||||
|
||||
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
|
||||
|
||||
au1xxx_stop_ehc();
|
||||
@@ -248,10 +241,9 @@ bail:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static int ehci_hcd_au1xxx_drv_resume(struct platform_device *pdev)
|
||||
static int ehci_hcd_au1xxx_drv_resume(struct device *dev)
|
||||
{
|
||||
struct usb_hcd *hcd = platform_get_drvdata(pdev);
|
||||
struct usb_hcd *hcd = dev_get_drvdata(dev);
|
||||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
|
||||
au1xxx_start_ehc();
|
||||
@@ -305,20 +297,25 @@ static int ehci_hcd_au1xxx_drv_resume(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dev_pm_ops au1xxx_ehci_pmops = {
|
||||
.suspend = ehci_hcd_au1xxx_drv_suspend,
|
||||
.resume = ehci_hcd_au1xxx_drv_resume,
|
||||
};
|
||||
|
||||
#define AU1XXX_EHCI_PMOPS &au1xxx_ehci_pmops
|
||||
|
||||
#else
|
||||
#define ehci_hcd_au1xxx_drv_suspend NULL
|
||||
#define ehci_hcd_au1xxx_drv_resume NULL
|
||||
#define AU1XXX_EHCI_PMOPS NULL
|
||||
#endif
|
||||
|
||||
static struct platform_driver ehci_hcd_au1xxx_driver = {
|
||||
.probe = ehci_hcd_au1xxx_drv_probe,
|
||||
.remove = ehci_hcd_au1xxx_drv_remove,
|
||||
.shutdown = usb_hcd_platform_shutdown,
|
||||
.suspend = ehci_hcd_au1xxx_drv_suspend,
|
||||
.resume = ehci_hcd_au1xxx_drv_resume,
|
||||
.driver = {
|
||||
.name = "au1xxx-ehci",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = AU1XXX_EHCI_PMOPS,
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -134,10 +134,11 @@ dbg_qtd (const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd)
|
||||
static void __maybe_unused
|
||||
dbg_qh (const char *label, struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||
{
|
||||
struct ehci_qh_hw *hw = qh->hw;
|
||||
|
||||
ehci_dbg (ehci, "%s qh %p n%08x info %x %x qtd %x\n", label,
|
||||
qh, qh->hw_next, qh->hw_info1, qh->hw_info2,
|
||||
qh->hw_current);
|
||||
dbg_qtd ("overlay", ehci, (struct ehci_qtd *) &qh->hw_qtd_next);
|
||||
qh, hw->hw_next, hw->hw_info1, hw->hw_info2, hw->hw_current);
|
||||
dbg_qtd("overlay", ehci, (struct ehci_qtd *) &hw->hw_qtd_next);
|
||||
}
|
||||
|
||||
static void __maybe_unused
|
||||
@@ -400,31 +401,32 @@ static void qh_lines (
|
||||
char *next = *nextp;
|
||||
char mark;
|
||||
__le32 list_end = EHCI_LIST_END(ehci);
|
||||
struct ehci_qh_hw *hw = qh->hw;
|
||||
|
||||
if (qh->hw_qtd_next == list_end) /* NEC does this */
|
||||
if (hw->hw_qtd_next == list_end) /* NEC does this */
|
||||
mark = '@';
|
||||
else
|
||||
mark = token_mark(ehci, qh->hw_token);
|
||||
mark = token_mark(ehci, hw->hw_token);
|
||||
if (mark == '/') { /* qh_alt_next controls qh advance? */
|
||||
if ((qh->hw_alt_next & QTD_MASK(ehci))
|
||||
== ehci->async->hw_alt_next)
|
||||
if ((hw->hw_alt_next & QTD_MASK(ehci))
|
||||
== ehci->async->hw->hw_alt_next)
|
||||
mark = '#'; /* blocked */
|
||||
else if (qh->hw_alt_next == list_end)
|
||||
else if (hw->hw_alt_next == list_end)
|
||||
mark = '.'; /* use hw_qtd_next */
|
||||
/* else alt_next points to some other qtd */
|
||||
}
|
||||
scratch = hc32_to_cpup(ehci, &qh->hw_info1);
|
||||
hw_curr = (mark == '*') ? hc32_to_cpup(ehci, &qh->hw_current) : 0;
|
||||
scratch = hc32_to_cpup(ehci, &hw->hw_info1);
|
||||
hw_curr = (mark == '*') ? hc32_to_cpup(ehci, &hw->hw_current) : 0;
|
||||
temp = scnprintf (next, size,
|
||||
"qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)",
|
||||
qh, scratch & 0x007f,
|
||||
speed_char (scratch),
|
||||
(scratch >> 8) & 0x000f,
|
||||
scratch, hc32_to_cpup(ehci, &qh->hw_info2),
|
||||
hc32_to_cpup(ehci, &qh->hw_token), mark,
|
||||
(cpu_to_hc32(ehci, QTD_TOGGLE) & qh->hw_token)
|
||||
scratch, hc32_to_cpup(ehci, &hw->hw_info2),
|
||||
hc32_to_cpup(ehci, &hw->hw_token), mark,
|
||||
(cpu_to_hc32(ehci, QTD_TOGGLE) & hw->hw_token)
|
||||
? "data1" : "data0",
|
||||
(hc32_to_cpup(ehci, &qh->hw_alt_next) >> 1) & 0x0f);
|
||||
(hc32_to_cpup(ehci, &hw->hw_alt_next) >> 1) & 0x0f);
|
||||
size -= temp;
|
||||
next += temp;
|
||||
|
||||
@@ -435,10 +437,10 @@ static void qh_lines (
|
||||
mark = ' ';
|
||||
if (hw_curr == td->qtd_dma)
|
||||
mark = '*';
|
||||
else if (qh->hw_qtd_next == cpu_to_hc32(ehci, td->qtd_dma))
|
||||
else if (hw->hw_qtd_next == cpu_to_hc32(ehci, td->qtd_dma))
|
||||
mark = '+';
|
||||
else if (QTD_LENGTH (scratch)) {
|
||||
if (td->hw_alt_next == ehci->async->hw_alt_next)
|
||||
if (td->hw_alt_next == ehci->async->hw->hw_alt_next)
|
||||
mark = '#';
|
||||
else if (td->hw_alt_next != list_end)
|
||||
mark = '/';
|
||||
@@ -550,12 +552,15 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
|
||||
next += temp;
|
||||
|
||||
do {
|
||||
struct ehci_qh_hw *hw;
|
||||
|
||||
switch (hc32_to_cpu(ehci, tag)) {
|
||||
case Q_TYPE_QH:
|
||||
hw = p.qh->hw;
|
||||
temp = scnprintf (next, size, " qh%d-%04x/%p",
|
||||
p.qh->period,
|
||||
hc32_to_cpup(ehci,
|
||||
&p.qh->hw_info2)
|
||||
&hw->hw_info2)
|
||||
/* uframe masks */
|
||||
& (QH_CMASK | QH_SMASK),
|
||||
p.qh);
|
||||
@@ -576,7 +581,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
|
||||
/* show more info the first time around */
|
||||
if (temp == seen_count) {
|
||||
u32 scratch = hc32_to_cpup(ehci,
|
||||
&p.qh->hw_info1);
|
||||
&hw->hw_info1);
|
||||
struct ehci_qtd *qtd;
|
||||
char *type = "";
|
||||
|
||||
@@ -609,7 +614,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
|
||||
} else
|
||||
temp = 0;
|
||||
if (p.qh) {
|
||||
tag = Q_NEXT_TYPE(ehci, p.qh->hw_next);
|
||||
tag = Q_NEXT_TYPE(ehci, hw->hw_next);
|
||||
p = p.qh->qh_next;
|
||||
}
|
||||
break;
|
||||
@@ -879,8 +884,7 @@ static int debug_close(struct inode *inode, struct file *file)
|
||||
struct debug_buffer *buf = file->private_data;
|
||||
|
||||
if (buf) {
|
||||
if (buf->output_buf)
|
||||
vfree(buf->output_buf);
|
||||
vfree(buf->output_buf);
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
|
@@ -30,7 +30,6 @@
|
||||
#include <linux/timer.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
@@ -127,6 +126,8 @@ timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action)
|
||||
|
||||
switch (action) {
|
||||
case TIMER_IO_WATCHDOG:
|
||||
if (!ehci->need_io_watchdog)
|
||||
return;
|
||||
t = EHCI_IO_JIFFIES;
|
||||
break;
|
||||
case TIMER_ASYNC_OFF:
|
||||
@@ -239,6 +240,11 @@ static int ehci_reset (struct ehci_hcd *ehci)
|
||||
int retval;
|
||||
u32 command = ehci_readl(ehci, &ehci->regs->command);
|
||||
|
||||
/* If the EHCI debug controller is active, special care must be
|
||||
* taken before and after a host controller reset */
|
||||
if (ehci->debug && !dbgp_reset_prep())
|
||||
ehci->debug = NULL;
|
||||
|
||||
command |= CMD_RESET;
|
||||
dbg_cmd (ehci, "reset", command);
|
||||
ehci_writel(ehci, command, &ehci->regs->command);
|
||||
@@ -247,12 +253,21 @@ static int ehci_reset (struct ehci_hcd *ehci)
|
||||
retval = handshake (ehci, &ehci->regs->command,
|
||||
CMD_RESET, 0, 250 * 1000);
|
||||
|
||||
if (ehci->has_hostpc) {
|
||||
ehci_writel(ehci, USBMODE_EX_HC | USBMODE_EX_VBPS,
|
||||
(u32 __iomem *)(((u8 *)ehci->regs) + USBMODE_EX));
|
||||
ehci_writel(ehci, TXFIFO_DEFAULT,
|
||||
(u32 __iomem *)(((u8 *)ehci->regs) + TXFILLTUNING));
|
||||
}
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
if (ehci_is_TDI(ehci))
|
||||
tdi_reset (ehci);
|
||||
|
||||
if (ehci->debug)
|
||||
dbgp_external_startup();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -505,9 +520,14 @@ static int ehci_init(struct usb_hcd *hcd)
|
||||
u32 temp;
|
||||
int retval;
|
||||
u32 hcc_params;
|
||||
struct ehci_qh_hw *hw;
|
||||
|
||||
spin_lock_init(&ehci->lock);
|
||||
|
||||
/*
|
||||
* keep io watchdog by default, those good HCDs could turn off it later
|
||||
*/
|
||||
ehci->need_io_watchdog = 1;
|
||||
init_timer(&ehci->watchdog);
|
||||
ehci->watchdog.function = ehci_watchdog;
|
||||
ehci->watchdog.data = (unsigned long) ehci;
|
||||
@@ -544,12 +564,13 @@ static int ehci_init(struct usb_hcd *hcd)
|
||||
* from automatically advancing to the next td after short reads.
|
||||
*/
|
||||
ehci->async->qh_next.qh = NULL;
|
||||
ehci->async->hw_next = QH_NEXT(ehci, ehci->async->qh_dma);
|
||||
ehci->async->hw_info1 = cpu_to_hc32(ehci, QH_HEAD);
|
||||
ehci->async->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT);
|
||||
ehci->async->hw_qtd_next = EHCI_LIST_END(ehci);
|
||||
hw = ehci->async->hw;
|
||||
hw->hw_next = QH_NEXT(ehci, ehci->async->qh_dma);
|
||||
hw->hw_info1 = cpu_to_hc32(ehci, QH_HEAD);
|
||||
hw->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT);
|
||||
hw->hw_qtd_next = EHCI_LIST_END(ehci);
|
||||
ehci->async->qh_state = QH_STATE_LINKED;
|
||||
ehci->async->hw_alt_next = QTD_NEXT(ehci, ehci->async->dummy->qtd_dma);
|
||||
hw->hw_alt_next = QTD_NEXT(ehci, ehci->async->dummy->qtd_dma);
|
||||
|
||||
/* clear interrupt enables, set irq latency */
|
||||
if (log2_irq_thresh < 0 || log2_irq_thresh > 6)
|
||||
@@ -850,12 +871,18 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||
if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state) && ehci->reclaim)
|
||||
end_unlink_async(ehci);
|
||||
|
||||
/* if it's not linked then there's nothing to do */
|
||||
if (qh->qh_state != QH_STATE_LINKED)
|
||||
;
|
||||
/* If the QH isn't linked then there's nothing we can do
|
||||
* unless we were called during a giveback, in which case
|
||||
* qh_completions() has to deal with it.
|
||||
*/
|
||||
if (qh->qh_state != QH_STATE_LINKED) {
|
||||
if (qh->qh_state == QH_STATE_COMPLETING)
|
||||
qh->needs_rescan = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* defer till later if busy */
|
||||
else if (ehci->reclaim) {
|
||||
if (ehci->reclaim) {
|
||||
struct ehci_qh *last;
|
||||
|
||||
for (last = ehci->reclaim;
|
||||
@@ -915,8 +942,9 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
|
||||
break;
|
||||
switch (qh->qh_state) {
|
||||
case QH_STATE_LINKED:
|
||||
case QH_STATE_COMPLETING:
|
||||
intr_deschedule (ehci, qh);
|
||||
/* FALL THROUGH */
|
||||
break;
|
||||
case QH_STATE_IDLE:
|
||||
qh_completions (ehci, qh);
|
||||
break;
|
||||
@@ -925,23 +953,6 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
|
||||
qh, qh->qh_state);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* reschedule QH iff another request is queued */
|
||||
if (!list_empty (&qh->qtd_list)
|
||||
&& HC_IS_RUNNING (hcd->state)) {
|
||||
rc = qh_schedule(ehci, qh);
|
||||
|
||||
/* An error here likely indicates handshake failure
|
||||
* or no space left in the schedule. Neither fault
|
||||
* should happen often ...
|
||||
*
|
||||
* FIXME kill the now-dysfunctional queued urbs
|
||||
*/
|
||||
if (rc != 0)
|
||||
ehci_err(ehci,
|
||||
"can't reschedule qh %p, err %d",
|
||||
qh, rc);
|
||||
}
|
||||
break;
|
||||
|
||||
case PIPE_ISOCHRONOUS:
|
||||
@@ -979,7 +990,7 @@ rescan:
|
||||
/* endpoints can be iso streams. for now, we don't
|
||||
* accelerate iso completions ... so spin a while.
|
||||
*/
|
||||
if (qh->hw_info1 == 0) {
|
||||
if (qh->hw->hw_info1 == 0) {
|
||||
ehci_vdbg (ehci, "iso delay\n");
|
||||
goto idle_timeout;
|
||||
}
|
||||
@@ -988,6 +999,7 @@ rescan:
|
||||
qh->qh_state = QH_STATE_IDLE;
|
||||
switch (qh->qh_state) {
|
||||
case QH_STATE_LINKED:
|
||||
case QH_STATE_COMPLETING:
|
||||
for (tmp = ehci->async->qh_next.qh;
|
||||
tmp && tmp != qh;
|
||||
tmp = tmp->qh_next.qh)
|
||||
@@ -1052,18 +1064,17 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
|
||||
usb_settoggle(qh->dev, epnum, is_out, 0);
|
||||
if (!list_empty(&qh->qtd_list)) {
|
||||
WARN_ONCE(1, "clear_halt for a busy endpoint\n");
|
||||
} else if (qh->qh_state == QH_STATE_LINKED) {
|
||||
} else if (qh->qh_state == QH_STATE_LINKED ||
|
||||
qh->qh_state == QH_STATE_COMPLETING) {
|
||||
|
||||
/* The toggle value in the QH can't be updated
|
||||
* while the QH is active. Unlink it now;
|
||||
* re-linking will call qh_refresh().
|
||||
*/
|
||||
if (eptype == USB_ENDPOINT_XFER_BULK) {
|
||||
if (eptype == USB_ENDPOINT_XFER_BULK)
|
||||
unlink_async(ehci, qh);
|
||||
} else {
|
||||
else
|
||||
intr_deschedule(ehci, qh);
|
||||
(void) qh_schedule(ehci, qh);
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&ehci->lock, flags);
|
||||
@@ -1117,6 +1128,16 @@ MODULE_LICENSE ("GPL");
|
||||
#define PLATFORM_DRIVER ixp4xx_ehci_driver
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_W90X900_EHCI
|
||||
#include "ehci-w90x900.c"
|
||||
#define PLATFORM_DRIVER ehci_hcd_w90x900_driver
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_AT91
|
||||
#include "ehci-atmel.c"
|
||||
#define PLATFORM_DRIVER ehci_atmel_driver
|
||||
#endif
|
||||
|
||||
#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
|
||||
!defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER)
|
||||
#error "missing bus glue for ehci-hcd"
|
||||
|
@@ -111,6 +111,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
|
||||
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
|
||||
int port;
|
||||
int mask;
|
||||
u32 __iomem *hostpc_reg = NULL;
|
||||
|
||||
ehci_dbg(ehci, "suspend root hub\n");
|
||||
|
||||
@@ -142,6 +143,9 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
|
||||
u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
|
||||
u32 t2 = t1;
|
||||
|
||||
if (ehci->has_hostpc)
|
||||
hostpc_reg = (u32 __iomem *)((u8 *)ehci->regs
|
||||
+ HOSTPC0 + 4 * (port & 0xff));
|
||||
/* keep track of which ports we suspend */
|
||||
if (t1 & PORT_OWNER)
|
||||
set_bit(port, &ehci->owned_ports);
|
||||
@@ -151,15 +155,37 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
|
||||
}
|
||||
|
||||
/* enable remote wakeup on all ports */
|
||||
if (hcd->self.root_hub->do_remote_wakeup)
|
||||
t2 |= PORT_WAKE_BITS;
|
||||
else
|
||||
if (hcd->self.root_hub->do_remote_wakeup) {
|
||||
/* only enable appropriate wake bits, otherwise the
|
||||
* hardware can not go phy low power mode. If a race
|
||||
* condition happens here(connection change during bits
|
||||
* set), the port change detection will finally fix it.
|
||||
*/
|
||||
if (t1 & PORT_CONNECT) {
|
||||
t2 |= PORT_WKOC_E | PORT_WKDISC_E;
|
||||
t2 &= ~PORT_WKCONN_E;
|
||||
} else {
|
||||
t2 |= PORT_WKOC_E | PORT_WKCONN_E;
|
||||
t2 &= ~PORT_WKDISC_E;
|
||||
}
|
||||
} else
|
||||
t2 &= ~PORT_WAKE_BITS;
|
||||
|
||||
if (t1 != t2) {
|
||||
ehci_vdbg (ehci, "port %d, %08x -> %08x\n",
|
||||
port + 1, t1, t2);
|
||||
ehci_writel(ehci, t2, reg);
|
||||
if (hostpc_reg) {
|
||||
u32 t3;
|
||||
|
||||
msleep(5);/* 5ms for HCD enter low pwr mode */
|
||||
t3 = ehci_readl(ehci, hostpc_reg);
|
||||
ehci_writel(ehci, t3 | HOSTPC_PHCD, hostpc_reg);
|
||||
t3 = ehci_readl(ehci, hostpc_reg);
|
||||
ehci_dbg(ehci, "Port%d phy low pwr mode %s\n",
|
||||
port, (t3 & HOSTPC_PHCD) ?
|
||||
"succeeded" : "failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,6 +209,11 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
|
||||
|
||||
ehci->next_statechange = jiffies + msecs_to_jiffies(10);
|
||||
spin_unlock_irq (&ehci->lock);
|
||||
|
||||
/* ehci_work() may have re-enabled the watchdog timer, which we do not
|
||||
* want, and so we must delete any pending watchdog timer events.
|
||||
*/
|
||||
del_timer_sync(&ehci->watchdog);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -204,6 +235,13 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
|
||||
return -ESHUTDOWN;
|
||||
}
|
||||
|
||||
if (unlikely(ehci->debug)) {
|
||||
if (ehci->debug && !dbgp_reset_prep())
|
||||
ehci->debug = NULL;
|
||||
else
|
||||
dbgp_external_startup();
|
||||
}
|
||||
|
||||
/* Ideally and we've got a real resume here, and no port's power
|
||||
* was lost. (For PCI, that means Vaux was maintained.) But we
|
||||
* could instead be restoring a swsusp snapshot -- so that BIOS was
|
||||
@@ -563,7 +601,8 @@ static int ehci_hub_control (
|
||||
int ports = HCS_N_PORTS (ehci->hcs_params);
|
||||
u32 __iomem *status_reg = &ehci->regs->port_status[
|
||||
(wIndex & 0xff) - 1];
|
||||
u32 temp, status;
|
||||
u32 __iomem *hostpc_reg = NULL;
|
||||
u32 temp, temp1, status;
|
||||
unsigned long flags;
|
||||
int retval = 0;
|
||||
unsigned selector;
|
||||
@@ -575,6 +614,9 @@ static int ehci_hub_control (
|
||||
* power, "this is the one", etc. EHCI spec supports this.
|
||||
*/
|
||||
|
||||
if (ehci->has_hostpc)
|
||||
hostpc_reg = (u32 __iomem *)((u8 *)ehci->regs
|
||||
+ HOSTPC0 + 4 * ((wIndex & 0xff) - 1));
|
||||
spin_lock_irqsave (&ehci->lock, flags);
|
||||
switch (typeReq) {
|
||||
case ClearHubFeature:
|
||||
@@ -773,7 +815,11 @@ static int ehci_hub_control (
|
||||
if (temp & PORT_CONNECT) {
|
||||
status |= 1 << USB_PORT_FEAT_CONNECTION;
|
||||
// status may be from integrated TT
|
||||
status |= ehci_port_speed(ehci, temp);
|
||||
if (ehci->has_hostpc) {
|
||||
temp1 = ehci_readl(ehci, hostpc_reg);
|
||||
status |= ehci_port_speed(ehci, temp1);
|
||||
} else
|
||||
status |= ehci_port_speed(ehci, temp);
|
||||
}
|
||||
if (temp & PORT_PE)
|
||||
status |= 1 << USB_PORT_FEAT_ENABLE;
|
||||
@@ -816,6 +862,15 @@ static int ehci_hub_control (
|
||||
case SetPortFeature:
|
||||
selector = wIndex >> 8;
|
||||
wIndex &= 0xff;
|
||||
if (unlikely(ehci->debug)) {
|
||||
/* If the debug port is active any port
|
||||
* feature requests should get denied */
|
||||
if (wIndex == HCS_DEBUG_PORT(ehci->hcs_params) &&
|
||||
(readl(&ehci->debug->control) & DBGP_ENABLED)) {
|
||||
retval = -ENODEV;
|
||||
goto error_exit;
|
||||
}
|
||||
}
|
||||
if (!wIndex || wIndex > ports)
|
||||
goto error;
|
||||
wIndex--;
|
||||
@@ -832,6 +887,24 @@ static int ehci_hub_control (
|
||||
|| (temp & PORT_RESET) != 0)
|
||||
goto error;
|
||||
ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
|
||||
/* After above check the port must be connected.
|
||||
* Set appropriate bit thus could put phy into low power
|
||||
* mode if we have hostpc feature
|
||||
*/
|
||||
if (hostpc_reg) {
|
||||
temp &= ~PORT_WKCONN_E;
|
||||
temp |= (PORT_WKDISC_E | PORT_WKOC_E);
|
||||
ehci_writel(ehci, temp | PORT_SUSPEND,
|
||||
status_reg);
|
||||
msleep(5);/* 5ms for HCD enter low pwr mode */
|
||||
temp1 = ehci_readl(ehci, hostpc_reg);
|
||||
ehci_writel(ehci, temp1 | HOSTPC_PHCD,
|
||||
hostpc_reg);
|
||||
temp1 = ehci_readl(ehci, hostpc_reg);
|
||||
ehci_dbg(ehci, "Port%d phy low pwr mode %s\n",
|
||||
wIndex, (temp1 & HOSTPC_PHCD) ?
|
||||
"succeeded" : "failed");
|
||||
}
|
||||
set_bit(wIndex, &ehci->suspended_ports);
|
||||
break;
|
||||
case USB_PORT_FEAT_POWER:
|
||||
@@ -894,6 +967,7 @@ error:
|
||||
/* "stall" on error */
|
||||
retval = -EPIPE;
|
||||
}
|
||||
error_exit:
|
||||
spin_unlock_irqrestore (&ehci->lock, flags);
|
||||
return retval;
|
||||
}
|
||||
|
@@ -75,7 +75,8 @@ static void qh_destroy(struct ehci_qh *qh)
|
||||
}
|
||||
if (qh->dummy)
|
||||
ehci_qtd_free (ehci, qh->dummy);
|
||||
dma_pool_free (ehci->qh_pool, qh, qh->qh_dma);
|
||||
dma_pool_free(ehci->qh_pool, qh->hw, qh->qh_dma);
|
||||
kfree(qh);
|
||||
}
|
||||
|
||||
static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags)
|
||||
@@ -83,12 +84,14 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags)
|
||||
struct ehci_qh *qh;
|
||||
dma_addr_t dma;
|
||||
|
||||
qh = (struct ehci_qh *)
|
||||
dma_pool_alloc (ehci->qh_pool, flags, &dma);
|
||||
qh = kzalloc(sizeof *qh, GFP_ATOMIC);
|
||||
if (!qh)
|
||||
return qh;
|
||||
|
||||
memset (qh, 0, sizeof *qh);
|
||||
goto done;
|
||||
qh->hw = (struct ehci_qh_hw *)
|
||||
dma_pool_alloc(ehci->qh_pool, flags, &dma);
|
||||
if (!qh->hw)
|
||||
goto fail;
|
||||
memset(qh->hw, 0, sizeof *qh->hw);
|
||||
qh->refcount = 1;
|
||||
qh->ehci = ehci;
|
||||
qh->qh_dma = dma;
|
||||
@@ -99,10 +102,15 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags)
|
||||
qh->dummy = ehci_qtd_alloc (ehci, flags);
|
||||
if (qh->dummy == NULL) {
|
||||
ehci_dbg (ehci, "no dummy td\n");
|
||||
dma_pool_free (ehci->qh_pool, qh, qh->qh_dma);
|
||||
qh = NULL;
|
||||
goto fail1;
|
||||
}
|
||||
done:
|
||||
return qh;
|
||||
fail1:
|
||||
dma_pool_free(ehci->qh_pool, qh->hw, qh->qh_dma);
|
||||
fail:
|
||||
kfree(qh);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* to share a qh (cpu threads, or hc) */
|
||||
@@ -180,7 +188,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
|
||||
/* QHs for control/bulk/intr transfers */
|
||||
ehci->qh_pool = dma_pool_create ("ehci_qh",
|
||||
ehci_to_hcd(ehci)->self.controller,
|
||||
sizeof (struct ehci_qh),
|
||||
sizeof(struct ehci_qh_hw),
|
||||
32 /* byte alignment (for hw parts) */,
|
||||
4096 /* can't cross 4K */);
|
||||
if (!ehci->qh_pool) {
|
||||
|
@@ -27,28 +27,8 @@
|
||||
/* called after powerup, by probe or system-pm "wakeup" */
|
||||
static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev)
|
||||
{
|
||||
u32 temp;
|
||||
int retval;
|
||||
|
||||
/* optional debug port, normally in the first BAR */
|
||||
temp = pci_find_capability(pdev, 0x0a);
|
||||
if (temp) {
|
||||
pci_read_config_dword(pdev, temp, &temp);
|
||||
temp >>= 16;
|
||||
if ((temp & (3 << 13)) == (1 << 13)) {
|
||||
temp &= 0x1fff;
|
||||
ehci->debug = ehci_to_hcd(ehci)->regs + temp;
|
||||
temp = ehci_readl(ehci, &ehci->debug->control);
|
||||
ehci_info(ehci, "debug port %d%s\n",
|
||||
HCS_DEBUG_PORT(ehci->hcs_params),
|
||||
(temp & DBGP_ENABLED)
|
||||
? " IN USE"
|
||||
: "");
|
||||
if (!(temp & DBGP_ENABLED))
|
||||
ehci->debug = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* we expect static quirk code to handle the "extended capabilities"
|
||||
* (currently just BIOS handoff) allowed starting with EHCI 0.96
|
||||
*/
|
||||
@@ -129,6 +109,9 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
|
||||
return retval;
|
||||
|
||||
switch (pdev->vendor) {
|
||||
case PCI_VENDOR_ID_INTEL:
|
||||
ehci->need_io_watchdog = 0;
|
||||
break;
|
||||
case PCI_VENDOR_ID_TDI:
|
||||
if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
|
||||
hcd->has_tt = 1;
|
||||
@@ -192,6 +175,25 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
|
||||
break;
|
||||
}
|
||||
|
||||
/* optional debug port, normally in the first BAR */
|
||||
temp = pci_find_capability(pdev, 0x0a);
|
||||
if (temp) {
|
||||
pci_read_config_dword(pdev, temp, &temp);
|
||||
temp >>= 16;
|
||||
if ((temp & (3 << 13)) == (1 << 13)) {
|
||||
temp &= 0x1fff;
|
||||
ehci->debug = ehci_to_hcd(ehci)->regs + temp;
|
||||
temp = ehci_readl(ehci, &ehci->debug->control);
|
||||
ehci_info(ehci, "debug port %d%s\n",
|
||||
HCS_DEBUG_PORT(ehci->hcs_params),
|
||||
(temp & DBGP_ENABLED)
|
||||
? " IN USE"
|
||||
: "");
|
||||
if (!(temp & DBGP_ENABLED))
|
||||
ehci->debug = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ehci_reset(ehci);
|
||||
|
||||
/* at least the Genesys GL880S needs fixup here */
|
||||
@@ -242,7 +244,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
|
||||
* System suspend currently expects to be able to suspend the entire
|
||||
* device tree, device-at-a-time. If we failed selective suspend
|
||||
* reports, system suspend would fail; so the root hub code must claim
|
||||
* success. That's lying to usbcore, and it matters for for runtime
|
||||
* success. That's lying to usbcore, and it matters for runtime
|
||||
* PM scenarios with selective suspend and remote wakeup...
|
||||
*/
|
||||
if (ehci->no_selective_suspend && device_can_wakeup(&pdev->dev))
|
||||
|
@@ -87,31 +87,33 @@ qtd_fill(struct ehci_hcd *ehci, struct ehci_qtd *qtd, dma_addr_t buf,
|
||||
static inline void
|
||||
qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
|
||||
{
|
||||
struct ehci_qh_hw *hw = qh->hw;
|
||||
|
||||
/* writes to an active overlay are unsafe */
|
||||
BUG_ON(qh->qh_state != QH_STATE_IDLE);
|
||||
|
||||
qh->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma);
|
||||
qh->hw_alt_next = EHCI_LIST_END(ehci);
|
||||
hw->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma);
|
||||
hw->hw_alt_next = EHCI_LIST_END(ehci);
|
||||
|
||||
/* Except for control endpoints, we make hardware maintain data
|
||||
* toggle (like OHCI) ... here (re)initialize the toggle in the QH,
|
||||
* and set the pseudo-toggle in udev. Only usb_clear_halt() will
|
||||
* ever clear it.
|
||||
*/
|
||||
if (!(qh->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) {
|
||||
if (!(hw->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) {
|
||||
unsigned is_out, epnum;
|
||||
|
||||
is_out = !(qtd->hw_token & cpu_to_hc32(ehci, 1 << 8));
|
||||
epnum = (hc32_to_cpup(ehci, &qh->hw_info1) >> 8) & 0x0f;
|
||||
epnum = (hc32_to_cpup(ehci, &hw->hw_info1) >> 8) & 0x0f;
|
||||
if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) {
|
||||
qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
|
||||
hw->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
|
||||
usb_settoggle (qh->dev, epnum, is_out, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* HC must see latest qtd and qh data before we clear ACTIVE+HALT */
|
||||
wmb ();
|
||||
qh->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING);
|
||||
hw->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING);
|
||||
}
|
||||
|
||||
/* if it weren't for a common silicon quirk (writing the dummy into the qh
|
||||
@@ -129,7 +131,7 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||
qtd = list_entry (qh->qtd_list.next,
|
||||
struct ehci_qtd, qtd_list);
|
||||
/* first qtd may already be partially processed */
|
||||
if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw_current)
|
||||
if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current)
|
||||
qtd = NULL;
|
||||
}
|
||||
|
||||
@@ -260,7 +262,7 @@ __acquires(ehci->lock)
|
||||
struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv;
|
||||
|
||||
/* S-mask in a QH means it's an interrupt urb */
|
||||
if ((qh->hw_info2 & cpu_to_hc32(ehci, QH_SMASK)) != 0) {
|
||||
if ((qh->hw->hw_info2 & cpu_to_hc32(ehci, QH_SMASK)) != 0) {
|
||||
|
||||
/* ... update hc-wide periodic stats (for usbfs) */
|
||||
ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
|
||||
@@ -297,7 +299,6 @@ __acquires(ehci->lock)
|
||||
static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh);
|
||||
static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh);
|
||||
|
||||
static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh);
|
||||
static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh);
|
||||
|
||||
/*
|
||||
@@ -308,13 +309,14 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh);
|
||||
static unsigned
|
||||
qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||
{
|
||||
struct ehci_qtd *last = NULL, *end = qh->dummy;
|
||||
struct ehci_qtd *last, *end = qh->dummy;
|
||||
struct list_head *entry, *tmp;
|
||||
int last_status = -EINPROGRESS;
|
||||
int last_status;
|
||||
int stopped;
|
||||
unsigned count = 0;
|
||||
u8 state;
|
||||
__le32 halt = HALT_BIT(ehci);
|
||||
const __le32 halt = HALT_BIT(ehci);
|
||||
struct ehci_qh_hw *hw = qh->hw;
|
||||
|
||||
if (unlikely (list_empty (&qh->qtd_list)))
|
||||
return count;
|
||||
@@ -324,11 +326,20 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||
* they add urbs to this qh's queue or mark them for unlinking.
|
||||
*
|
||||
* NOTE: unlinking expects to be done in queue order.
|
||||
*
|
||||
* It's a bug for qh->qh_state to be anything other than
|
||||
* QH_STATE_IDLE, unless our caller is scan_async() or
|
||||
* scan_periodic().
|
||||
*/
|
||||
state = qh->qh_state;
|
||||
qh->qh_state = QH_STATE_COMPLETING;
|
||||
stopped = (state == QH_STATE_IDLE);
|
||||
|
||||
rescan:
|
||||
last = NULL;
|
||||
last_status = -EINPROGRESS;
|
||||
qh->needs_rescan = 0;
|
||||
|
||||
/* remove de-activated QTDs from front of queue.
|
||||
* after faults (including short reads), cleanup this urb
|
||||
* then let the queue advance.
|
||||
@@ -392,7 +403,8 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||
qtd->hw_token = cpu_to_hc32(ehci,
|
||||
token);
|
||||
wmb();
|
||||
qh->hw_token = cpu_to_hc32(ehci, token);
|
||||
hw->hw_token = cpu_to_hc32(ehci,
|
||||
token);
|
||||
goto retry_xacterr;
|
||||
}
|
||||
stopped = 1;
|
||||
@@ -435,8 +447,8 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||
/* qh unlinked; token in overlay may be most current */
|
||||
if (state == QH_STATE_IDLE
|
||||
&& cpu_to_hc32(ehci, qtd->qtd_dma)
|
||||
== qh->hw_current) {
|
||||
token = hc32_to_cpu(ehci, qh->hw_token);
|
||||
== hw->hw_current) {
|
||||
token = hc32_to_cpu(ehci, hw->hw_token);
|
||||
|
||||
/* An unlink may leave an incomplete
|
||||
* async transaction in the TT buffer.
|
||||
@@ -449,9 +461,9 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||
* patch the qh later and so that completions can't
|
||||
* activate it while we "know" it's stopped.
|
||||
*/
|
||||
if ((halt & qh->hw_token) == 0) {
|
||||
if ((halt & hw->hw_token) == 0) {
|
||||
halt:
|
||||
qh->hw_token |= halt;
|
||||
hw->hw_token |= halt;
|
||||
wmb ();
|
||||
}
|
||||
}
|
||||
@@ -503,6 +515,21 @@ halt:
|
||||
ehci_qtd_free (ehci, last);
|
||||
}
|
||||
|
||||
/* Do we need to rescan for URBs dequeued during a giveback? */
|
||||
if (unlikely(qh->needs_rescan)) {
|
||||
/* If the QH is already unlinked, do the rescan now. */
|
||||
if (state == QH_STATE_IDLE)
|
||||
goto rescan;
|
||||
|
||||
/* Otherwise we have to wait until the QH is fully unlinked.
|
||||
* Our caller will start an unlink if qh->needs_rescan is
|
||||
* set. But if an unlink has already started, nothing needs
|
||||
* to be done.
|
||||
*/
|
||||
if (state != QH_STATE_LINKED)
|
||||
qh->needs_rescan = 0;
|
||||
}
|
||||
|
||||
/* restore original state; caller must unlink or relink */
|
||||
qh->qh_state = state;
|
||||
|
||||
@@ -510,7 +537,7 @@ halt:
|
||||
* it after fault cleanup, or recovering from silicon wrongly
|
||||
* overlaying the dummy qtd (which reduces DMA chatter).
|
||||
*/
|
||||
if (stopped != 0 || qh->hw_qtd_next == EHCI_LIST_END(ehci)) {
|
||||
if (stopped != 0 || hw->hw_qtd_next == EHCI_LIST_END(ehci)) {
|
||||
switch (state) {
|
||||
case QH_STATE_IDLE:
|
||||
qh_refresh(ehci, qh);
|
||||
@@ -527,12 +554,9 @@ halt:
|
||||
* That should be rare for interrupt transfers,
|
||||
* except maybe high bandwidth ...
|
||||
*/
|
||||
if ((cpu_to_hc32(ehci, QH_SMASK)
|
||||
& qh->hw_info2) != 0) {
|
||||
intr_deschedule (ehci, qh);
|
||||
(void) qh_schedule (ehci, qh);
|
||||
} else
|
||||
unlink_async (ehci, qh);
|
||||
|
||||
/* Tell the caller to start an unlink */
|
||||
qh->needs_rescan = 1;
|
||||
break;
|
||||
/* otherwise, unlink already started */
|
||||
}
|
||||
@@ -649,7 +673,7 @@ qh_urb_transaction (
|
||||
* (this will usually be overridden later.)
|
||||
*/
|
||||
if (is_input)
|
||||
qtd->hw_alt_next = ehci->async->hw_alt_next;
|
||||
qtd->hw_alt_next = ehci->async->hw->hw_alt_next;
|
||||
|
||||
/* qh makes control packets use qtd toggle; maybe switch it */
|
||||
if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0)
|
||||
@@ -744,6 +768,7 @@ qh_make (
|
||||
int is_input, type;
|
||||
int maxp = 0;
|
||||
struct usb_tt *tt = urb->dev->tt;
|
||||
struct ehci_qh_hw *hw;
|
||||
|
||||
if (!qh)
|
||||
return qh;
|
||||
@@ -890,8 +915,9 @@ done:
|
||||
|
||||
/* init as live, toggle clear, advance to dummy */
|
||||
qh->qh_state = QH_STATE_IDLE;
|
||||
qh->hw_info1 = cpu_to_hc32(ehci, info1);
|
||||
qh->hw_info2 = cpu_to_hc32(ehci, info2);
|
||||
hw = qh->hw;
|
||||
hw->hw_info1 = cpu_to_hc32(ehci, info1);
|
||||
hw->hw_info2 = cpu_to_hc32(ehci, info2);
|
||||
usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1);
|
||||
qh_refresh (ehci, qh);
|
||||
return qh;
|
||||
@@ -910,6 +936,8 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||
if (unlikely(qh->clearing_tt))
|
||||
return;
|
||||
|
||||
WARN_ON(qh->qh_state != QH_STATE_IDLE);
|
||||
|
||||
/* (re)start the async schedule? */
|
||||
head = ehci->async;
|
||||
timer_action_done (ehci, TIMER_ASYNC_OFF);
|
||||
@@ -928,16 +956,15 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||
}
|
||||
|
||||
/* clear halt and/or toggle; and maybe recover from silicon quirk */
|
||||
if (qh->qh_state == QH_STATE_IDLE)
|
||||
qh_refresh (ehci, qh);
|
||||
qh_refresh(ehci, qh);
|
||||
|
||||
/* splice right after start */
|
||||
qh->qh_next = head->qh_next;
|
||||
qh->hw_next = head->hw_next;
|
||||
qh->hw->hw_next = head->hw->hw_next;
|
||||
wmb ();
|
||||
|
||||
head->qh_next.qh = qh;
|
||||
head->hw_next = dma;
|
||||
head->hw->hw_next = dma;
|
||||
|
||||
qh_get(qh);
|
||||
qh->xacterrs = 0;
|
||||
@@ -984,7 +1011,7 @@ static struct ehci_qh *qh_append_tds (
|
||||
|
||||
/* usb_reset_device() briefly reverts to address 0 */
|
||||
if (usb_pipedevice (urb->pipe) == 0)
|
||||
qh->hw_info1 &= ~qh_addr_mask;
|
||||
qh->hw->hw_info1 &= ~qh_addr_mask;
|
||||
}
|
||||
|
||||
/* just one way to queue requests: swap with the dummy qtd.
|
||||
@@ -1169,7 +1196,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||
while (prev->qh_next.qh != qh)
|
||||
prev = prev->qh_next.qh;
|
||||
|
||||
prev->hw_next = qh->hw_next;
|
||||
prev->hw->hw_next = qh->hw->hw_next;
|
||||
prev->qh_next = qh->qh_next;
|
||||
wmb ();
|
||||
|
||||
@@ -1214,6 +1241,8 @@ rescan:
|
||||
qh = qh_get (qh);
|
||||
qh->stamp = ehci->stamp;
|
||||
temp = qh_completions (ehci, qh);
|
||||
if (qh->needs_rescan)
|
||||
unlink_async(ehci, qh);
|
||||
qh_put (qh);
|
||||
if (temp != 0) {
|
||||
goto rescan;
|
||||
|
@@ -60,6 +60,20 @@ periodic_next_shadow(struct ehci_hcd *ehci, union ehci_shadow *periodic,
|
||||
}
|
||||
}
|
||||
|
||||
static __hc32 *
|
||||
shadow_next_periodic(struct ehci_hcd *ehci, union ehci_shadow *periodic,
|
||||
__hc32 tag)
|
||||
{
|
||||
switch (hc32_to_cpu(ehci, tag)) {
|
||||
/* our ehci_shadow.qh is actually software part */
|
||||
case Q_TYPE_QH:
|
||||
return &periodic->qh->hw->hw_next;
|
||||
/* others are hw parts */
|
||||
default:
|
||||
return periodic->hw_next;
|
||||
}
|
||||
}
|
||||
|
||||
/* caller must hold ehci->lock */
|
||||
static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
|
||||
{
|
||||
@@ -71,7 +85,8 @@ static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
|
||||
while (here.ptr && here.ptr != ptr) {
|
||||
prev_p = periodic_next_shadow(ehci, prev_p,
|
||||
Q_NEXT_TYPE(ehci, *hw_p));
|
||||
hw_p = here.hw_next;
|
||||
hw_p = shadow_next_periodic(ehci, &here,
|
||||
Q_NEXT_TYPE(ehci, *hw_p));
|
||||
here = *prev_p;
|
||||
}
|
||||
/* an interrupt entry (at list end) could have been shared */
|
||||
@@ -83,7 +98,7 @@ static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
|
||||
*/
|
||||
*prev_p = *periodic_next_shadow(ehci, &here,
|
||||
Q_NEXT_TYPE(ehci, *hw_p));
|
||||
*hw_p = *here.hw_next;
|
||||
*hw_p = *shadow_next_periodic(ehci, &here, Q_NEXT_TYPE(ehci, *hw_p));
|
||||
}
|
||||
|
||||
/* how many of the uframe's 125 usecs are allocated? */
|
||||
@@ -93,18 +108,20 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
|
||||
__hc32 *hw_p = &ehci->periodic [frame];
|
||||
union ehci_shadow *q = &ehci->pshadow [frame];
|
||||
unsigned usecs = 0;
|
||||
struct ehci_qh_hw *hw;
|
||||
|
||||
while (q->ptr) {
|
||||
switch (hc32_to_cpu(ehci, Q_NEXT_TYPE(ehci, *hw_p))) {
|
||||
case Q_TYPE_QH:
|
||||
hw = q->qh->hw;
|
||||
/* is it in the S-mask? */
|
||||
if (q->qh->hw_info2 & cpu_to_hc32(ehci, 1 << uframe))
|
||||
if (hw->hw_info2 & cpu_to_hc32(ehci, 1 << uframe))
|
||||
usecs += q->qh->usecs;
|
||||
/* ... or C-mask? */
|
||||
if (q->qh->hw_info2 & cpu_to_hc32(ehci,
|
||||
if (hw->hw_info2 & cpu_to_hc32(ehci,
|
||||
1 << (8 + uframe)))
|
||||
usecs += q->qh->c_usecs;
|
||||
hw_p = &q->qh->hw_next;
|
||||
hw_p = &hw->hw_next;
|
||||
q = &q->qh->qh_next;
|
||||
break;
|
||||
// case Q_TYPE_FSTN:
|
||||
@@ -237,10 +254,10 @@ periodic_tt_usecs (
|
||||
continue;
|
||||
case Q_TYPE_QH:
|
||||
if (same_tt(dev, q->qh->dev)) {
|
||||
uf = tt_start_uframe(ehci, q->qh->hw_info2);
|
||||
uf = tt_start_uframe(ehci, q->qh->hw->hw_info2);
|
||||
tt_usecs[uf] += q->qh->tt_usecs;
|
||||
}
|
||||
hw_p = &q->qh->hw_next;
|
||||
hw_p = &q->qh->hw->hw_next;
|
||||
q = &q->qh->qh_next;
|
||||
continue;
|
||||
case Q_TYPE_SITD:
|
||||
@@ -375,6 +392,7 @@ static int tt_no_collision (
|
||||
for (; frame < ehci->periodic_size; frame += period) {
|
||||
union ehci_shadow here;
|
||||
__hc32 type;
|
||||
struct ehci_qh_hw *hw;
|
||||
|
||||
here = ehci->pshadow [frame];
|
||||
type = Q_NEXT_TYPE(ehci, ehci->periodic [frame]);
|
||||
@@ -385,17 +403,18 @@ static int tt_no_collision (
|
||||
here = here.itd->itd_next;
|
||||
continue;
|
||||
case Q_TYPE_QH:
|
||||
hw = here.qh->hw;
|
||||
if (same_tt (dev, here.qh->dev)) {
|
||||
u32 mask;
|
||||
|
||||
mask = hc32_to_cpu(ehci,
|
||||
here.qh->hw_info2);
|
||||
hw->hw_info2);
|
||||
/* "knows" no gap is needed */
|
||||
mask |= mask >> 8;
|
||||
if (mask & uf_mask)
|
||||
break;
|
||||
}
|
||||
type = Q_NEXT_TYPE(ehci, here.qh->hw_next);
|
||||
type = Q_NEXT_TYPE(ehci, hw->hw_next);
|
||||
here = here.qh->qh_next;
|
||||
continue;
|
||||
case Q_TYPE_SITD:
|
||||
@@ -498,7 +517,8 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||
|
||||
dev_dbg (&qh->dev->dev,
|
||||
"link qh%d-%04x/%p start %d [%d/%d us]\n",
|
||||
period, hc32_to_cpup(ehci, &qh->hw_info2) & (QH_CMASK | QH_SMASK),
|
||||
period, hc32_to_cpup(ehci, &qh->hw->hw_info2)
|
||||
& (QH_CMASK | QH_SMASK),
|
||||
qh, qh->start, qh->usecs, qh->c_usecs);
|
||||
|
||||
/* high bandwidth, or otherwise every microframe */
|
||||
@@ -517,7 +537,7 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||
if (type == cpu_to_hc32(ehci, Q_TYPE_QH))
|
||||
break;
|
||||
prev = periodic_next_shadow(ehci, prev, type);
|
||||
hw_p = &here.qh->hw_next;
|
||||
hw_p = shadow_next_periodic(ehci, &here, type);
|
||||
here = *prev;
|
||||
}
|
||||
|
||||
@@ -528,14 +548,14 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||
if (qh->period > here.qh->period)
|
||||
break;
|
||||
prev = &here.qh->qh_next;
|
||||
hw_p = &here.qh->hw_next;
|
||||
hw_p = &here.qh->hw->hw_next;
|
||||
here = *prev;
|
||||
}
|
||||
/* link in this qh, unless some earlier pass did that */
|
||||
if (qh != here.qh) {
|
||||
qh->qh_next = here;
|
||||
if (here.qh)
|
||||
qh->hw_next = *hw_p;
|
||||
qh->hw->hw_next = *hw_p;
|
||||
wmb ();
|
||||
prev->qh = qh;
|
||||
*hw_p = QH_NEXT (ehci, qh->qh_dma);
|
||||
@@ -581,7 +601,7 @@ static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||
dev_dbg (&qh->dev->dev,
|
||||
"unlink qh%d-%04x/%p start %d [%d/%d us]\n",
|
||||
qh->period,
|
||||
hc32_to_cpup(ehci, &qh->hw_info2) & (QH_CMASK | QH_SMASK),
|
||||
hc32_to_cpup(ehci, &qh->hw->hw_info2) & (QH_CMASK | QH_SMASK),
|
||||
qh, qh->start, qh->usecs, qh->c_usecs);
|
||||
|
||||
/* qh->qh_next still "live" to HC */
|
||||
@@ -595,7 +615,19 @@ static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||
|
||||
static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||
{
|
||||
unsigned wait;
|
||||
unsigned wait;
|
||||
struct ehci_qh_hw *hw = qh->hw;
|
||||
int rc;
|
||||
|
||||
/* If the QH isn't linked then there's nothing we can do
|
||||
* unless we were called during a giveback, in which case
|
||||
* qh_completions() has to deal with it.
|
||||
*/
|
||||
if (qh->qh_state != QH_STATE_LINKED) {
|
||||
if (qh->qh_state == QH_STATE_COMPLETING)
|
||||
qh->needs_rescan = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
qh_unlink_periodic (ehci, qh);
|
||||
|
||||
@@ -606,15 +638,33 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||
*/
|
||||
if (list_empty (&qh->qtd_list)
|
||||
|| (cpu_to_hc32(ehci, QH_CMASK)
|
||||
& qh->hw_info2) != 0)
|
||||
& hw->hw_info2) != 0)
|
||||
wait = 2;
|
||||
else
|
||||
wait = 55; /* worst case: 3 * 1024 */
|
||||
|
||||
udelay (wait);
|
||||
qh->qh_state = QH_STATE_IDLE;
|
||||
qh->hw_next = EHCI_LIST_END(ehci);
|
||||
hw->hw_next = EHCI_LIST_END(ehci);
|
||||
wmb ();
|
||||
|
||||
qh_completions(ehci, qh);
|
||||
|
||||
/* reschedule QH iff another request is queued */
|
||||
if (!list_empty(&qh->qtd_list) &&
|
||||
HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
|
||||
rc = qh_schedule(ehci, qh);
|
||||
|
||||
/* An error here likely indicates handshake failure
|
||||
* or no space left in the schedule. Neither fault
|
||||
* should happen often ...
|
||||
*
|
||||
* FIXME kill the now-dysfunctional queued urbs
|
||||
*/
|
||||
if (rc != 0)
|
||||
ehci_err(ehci, "can't reschedule qh %p, err %d\n",
|
||||
qh, rc);
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@@ -739,14 +789,15 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||
unsigned uframe;
|
||||
__hc32 c_mask;
|
||||
unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */
|
||||
struct ehci_qh_hw *hw = qh->hw;
|
||||
|
||||
qh_refresh(ehci, qh);
|
||||
qh->hw_next = EHCI_LIST_END(ehci);
|
||||
hw->hw_next = EHCI_LIST_END(ehci);
|
||||
frame = qh->start;
|
||||
|
||||
/* reuse the previous schedule slots, if we can */
|
||||
if (frame < qh->period) {
|
||||
uframe = ffs(hc32_to_cpup(ehci, &qh->hw_info2) & QH_SMASK);
|
||||
uframe = ffs(hc32_to_cpup(ehci, &hw->hw_info2) & QH_SMASK);
|
||||
status = check_intr_schedule (ehci, frame, --uframe,
|
||||
qh, &c_mask);
|
||||
} else {
|
||||
@@ -784,11 +835,11 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||
qh->start = frame;
|
||||
|
||||
/* reset S-frame and (maybe) C-frame masks */
|
||||
qh->hw_info2 &= cpu_to_hc32(ehci, ~(QH_CMASK | QH_SMASK));
|
||||
qh->hw_info2 |= qh->period
|
||||
hw->hw_info2 &= cpu_to_hc32(ehci, ~(QH_CMASK | QH_SMASK));
|
||||
hw->hw_info2 |= qh->period
|
||||
? cpu_to_hc32(ehci, 1 << uframe)
|
||||
: cpu_to_hc32(ehci, QH_SMASK);
|
||||
qh->hw_info2 |= c_mask;
|
||||
hw->hw_info2 |= c_mask;
|
||||
} else
|
||||
ehci_dbg (ehci, "reused qh %p schedule\n", qh);
|
||||
|
||||
@@ -2188,10 +2239,11 @@ restart:
|
||||
case Q_TYPE_QH:
|
||||
/* handle any completions */
|
||||
temp.qh = qh_get (q.qh);
|
||||
type = Q_NEXT_TYPE(ehci, q.qh->hw_next);
|
||||
type = Q_NEXT_TYPE(ehci, q.qh->hw->hw_next);
|
||||
q = q.qh->qh_next;
|
||||
modified = qh_completions (ehci, temp.qh);
|
||||
if (unlikely (list_empty (&temp.qh->qtd_list)))
|
||||
if (unlikely(list_empty(&temp.qh->qtd_list) ||
|
||||
temp.qh->needs_rescan))
|
||||
intr_deschedule (ehci, temp.qh);
|
||||
qh_put (temp.qh);
|
||||
break;
|
||||
|
181
drivers/usb/host/ehci-w90x900.c
Normal file
181
drivers/usb/host/ehci-w90x900.c
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* linux/driver/usb/host/ehci-w90x900.c
|
||||
*
|
||||
* Copyright (c) 2008 Nuvoton technology corporation.
|
||||
*
|
||||
* Wan ZongShun <mcuos.com@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation;version 2 of the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
/*ebable phy0 and phy1 for w90p910*/
|
||||
#define ENPHY (0x01<<8)
|
||||
#define PHY0_CTR (0xA4)
|
||||
#define PHY1_CTR (0xA8)
|
||||
|
||||
static int __devinit usb_w90x900_probe(const struct hc_driver *driver,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
struct usb_hcd *hcd;
|
||||
struct ehci_hcd *ehci;
|
||||
struct resource *res;
|
||||
int retval = 0, irq;
|
||||
unsigned long val;
|
||||
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
retval = -ENXIO;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
hcd = usb_create_hcd(driver, &pdev->dev, "w90x900 EHCI");
|
||||
if (!hcd) {
|
||||
retval = -ENOMEM;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
hcd->rsrc_start = res->start;
|
||||
hcd->rsrc_len = res->end - res->start + 1;
|
||||
|
||||
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
|
||||
retval = -EBUSY;
|
||||
goto err2;
|
||||
}
|
||||
|
||||
hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
|
||||
if (hcd->regs == NULL) {
|
||||
retval = -EFAULT;
|
||||
goto err3;
|
||||
}
|
||||
|
||||
ehci = hcd_to_ehci(hcd);
|
||||
ehci->caps = hcd->regs;
|
||||
ehci->regs = hcd->regs +
|
||||
HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
|
||||
|
||||
/* enable PHY 0,1,the regs only apply to w90p910
|
||||
* 0xA4,0xA8 were offsets of PHY0 and PHY1 controller of
|
||||
* w90p910 IC relative to ehci->regs.
|
||||
*/
|
||||
val = __raw_readl(ehci->regs+PHY0_CTR);
|
||||
val |= ENPHY;
|
||||
__raw_writel(val, ehci->regs+PHY0_CTR);
|
||||
|
||||
val = __raw_readl(ehci->regs+PHY1_CTR);
|
||||
val |= ENPHY;
|
||||
__raw_writel(val, ehci->regs+PHY1_CTR);
|
||||
|
||||
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
|
||||
ehci->sbrn = 0x20;
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
goto err4;
|
||||
|
||||
retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
|
||||
if (retval != 0)
|
||||
goto err4;
|
||||
|
||||
ehci_writel(ehci, 1, &ehci->regs->configured_flag);
|
||||
|
||||
return retval;
|
||||
err4:
|
||||
iounmap(hcd->regs);
|
||||
err3:
|
||||
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
err2:
|
||||
usb_put_hcd(hcd);
|
||||
err1:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static
|
||||
void usb_w90x900_remove(struct usb_hcd *hcd, struct platform_device *pdev)
|
||||
{
|
||||
usb_remove_hcd(hcd);
|
||||
iounmap(hcd->regs);
|
||||
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
usb_put_hcd(hcd);
|
||||
}
|
||||
|
||||
static const struct hc_driver ehci_w90x900_hc_driver = {
|
||||
.description = hcd_name,
|
||||
.product_desc = "Nuvoton w90x900 EHCI Host Controller",
|
||||
.hcd_priv_size = sizeof(struct ehci_hcd),
|
||||
|
||||
/*
|
||||
* generic hardware linkage
|
||||
*/
|
||||
.irq = ehci_irq,
|
||||
.flags = HCD_USB2|HCD_MEMORY,
|
||||
|
||||
/*
|
||||
* basic lifecycle operations
|
||||
*/
|
||||
.reset = ehci_init,
|
||||
.start = ehci_run,
|
||||
|
||||
.stop = ehci_stop,
|
||||
.shutdown = ehci_shutdown,
|
||||
|
||||
/*
|
||||
* managing i/o requests and associated device resources
|
||||
*/
|
||||
.urb_enqueue = ehci_urb_enqueue,
|
||||
.urb_dequeue = ehci_urb_dequeue,
|
||||
.endpoint_disable = ehci_endpoint_disable,
|
||||
|
||||
/*
|
||||
* scheduling support
|
||||
*/
|
||||
.get_frame_number = ehci_get_frame,
|
||||
|
||||
/*
|
||||
* root hub support
|
||||
*/
|
||||
.hub_status_data = ehci_hub_status_data,
|
||||
.hub_control = ehci_hub_control,
|
||||
#ifdef CONFIG_PM
|
||||
.bus_suspend = ehci_bus_suspend,
|
||||
.bus_resume = ehci_bus_resume,
|
||||
#endif
|
||||
.relinquish_port = ehci_relinquish_port,
|
||||
.port_handed_over = ehci_port_handed_over,
|
||||
};
|
||||
|
||||
static int __devinit ehci_w90x900_probe(struct platform_device *pdev)
|
||||
{
|
||||
if (usb_disabled())
|
||||
return -ENODEV;
|
||||
|
||||
return usb_w90x900_probe(&ehci_w90x900_hc_driver, pdev);
|
||||
}
|
||||
|
||||
static int __devexit ehci_w90x900_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct usb_hcd *hcd = platform_get_drvdata(pdev);
|
||||
|
||||
usb_w90x900_remove(hcd, pdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver ehci_hcd_w90x900_driver = {
|
||||
.probe = ehci_w90x900_probe,
|
||||
.remove = __devexit_p(ehci_w90x900_remove),
|
||||
.driver = {
|
||||
.name = "w90x900-ehci",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
|
||||
MODULE_DESCRIPTION("w90p910 usb ehci driver!");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:w90p910-ehci");
|
@@ -37,7 +37,7 @@ typedef __u16 __bitwise __hc16;
|
||||
#define __hc16 __le16
|
||||
#endif
|
||||
|
||||
/* statistics can be kept for for tuning/monitoring */
|
||||
/* statistics can be kept for tuning/monitoring */
|
||||
struct ehci_stats {
|
||||
/* irq usage */
|
||||
unsigned long normal;
|
||||
@@ -126,6 +126,7 @@ struct ehci_hcd { /* one per controller */
|
||||
unsigned big_endian_mmio:1;
|
||||
unsigned big_endian_desc:1;
|
||||
unsigned has_amcc_usb23:1;
|
||||
unsigned need_io_watchdog:1;
|
||||
|
||||
/* required for usb32 quirk */
|
||||
#define OHCI_CTRL_HCFS (3 << 6)
|
||||
@@ -135,6 +136,7 @@ struct ehci_hcd { /* one per controller */
|
||||
#define OHCI_HCCTRL_OFFSET 0x4
|
||||
#define OHCI_HCCTRL_LEN 0x4
|
||||
__hc32 *ohci_hcctrl_reg;
|
||||
unsigned has_hostpc:1;
|
||||
|
||||
u8 sbrn; /* packed release number */
|
||||
|
||||
@@ -298,8 +300,8 @@ union ehci_shadow {
|
||||
* These appear in both the async and (for interrupt) periodic schedules.
|
||||
*/
|
||||
|
||||
struct ehci_qh {
|
||||
/* first part defined by EHCI spec */
|
||||
/* first part defined by EHCI spec */
|
||||
struct ehci_qh_hw {
|
||||
__hc32 hw_next; /* see EHCI 3.6.1 */
|
||||
__hc32 hw_info1; /* see EHCI 3.6.2 */
|
||||
#define QH_HEAD 0x00008000
|
||||
@@ -317,7 +319,10 @@ struct ehci_qh {
|
||||
__hc32 hw_token;
|
||||
__hc32 hw_buf [5];
|
||||
__hc32 hw_buf_hi [5];
|
||||
} __attribute__ ((aligned(32)));
|
||||
|
||||
struct ehci_qh {
|
||||
struct ehci_qh_hw *hw;
|
||||
/* the rest is HCD-private */
|
||||
dma_addr_t qh_dma; /* address of qh */
|
||||
union ehci_shadow qh_next; /* ptr to qh; or periodic */
|
||||
@@ -336,6 +341,7 @@ struct ehci_qh {
|
||||
u32 refcount;
|
||||
unsigned stamp;
|
||||
|
||||
u8 needs_rescan; /* Dequeue during giveback */
|
||||
u8 qh_state;
|
||||
#define QH_STATE_LINKED 1 /* HC sees this */
|
||||
#define QH_STATE_UNLINK 2 /* HC may still see this */
|
||||
@@ -357,7 +363,7 @@ struct ehci_qh {
|
||||
|
||||
struct usb_device *dev; /* access to TT */
|
||||
unsigned clearing_tt:1; /* Clear-TT-Buf in progress */
|
||||
} __attribute__ ((aligned (32)));
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
@@ -544,7 +550,7 @@ static inline unsigned int
|
||||
ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
|
||||
{
|
||||
if (ehci_is_TDI(ehci)) {
|
||||
switch ((portsc>>26)&3) {
|
||||
switch ((portsc >> (ehci->has_hostpc ? 25 : 26)) & 3) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
|
2909
drivers/usb/host/isp1362-hcd.c
Normal file
2909
drivers/usb/host/isp1362-hcd.c
Normal file
Diff onderdrukt omdat het te groot bestand
Laad Diff
1079
drivers/usb/host/isp1362.h
Normal file
1079
drivers/usb/host/isp1362.h
Normal file
Diff onderdrukt omdat het te groot bestand
Laad Diff
@@ -386,6 +386,10 @@ static int isp1760_hc_setup(struct usb_hcd *hcd)
|
||||
hwmode |= HW_DACK_POL_HIGH;
|
||||
if (priv->devflags & ISP1760_FLAG_DREQ_POL_HIGH)
|
||||
hwmode |= HW_DREQ_POL_HIGH;
|
||||
if (priv->devflags & ISP1760_FLAG_INTR_POL_HIGH)
|
||||
hwmode |= HW_INTR_HIGH_ACT;
|
||||
if (priv->devflags & ISP1760_FLAG_INTR_EDGE_TRIG)
|
||||
hwmode |= HW_INTR_EDGE_TRIG;
|
||||
|
||||
/*
|
||||
* We have to set this first in case we're in 16-bit mode.
|
||||
|
@@ -142,6 +142,8 @@ typedef void (packet_enqueue)(struct usb_hcd *hcd, struct isp1760_qh *qh,
|
||||
#define ISP1760_FLAG_DACK_POL_HIGH 0x00000010 /* DACK active high */
|
||||
#define ISP1760_FLAG_DREQ_POL_HIGH 0x00000020 /* DREQ active high */
|
||||
#define ISP1760_FLAG_ISP1761 0x00000040 /* Chip is ISP1761 */
|
||||
#define ISP1760_FLAG_INTR_POL_HIGH 0x00000080 /* Interrupt polarity active high */
|
||||
#define ISP1760_FLAG_INTR_EDGE_TRIG 0x00000100 /* Interrupt edge triggered */
|
||||
|
||||
/* chip memory management */
|
||||
struct memory_chunk {
|
||||
|
@@ -3,6 +3,7 @@
|
||||
* Currently there is support for
|
||||
* - OpenFirmware
|
||||
* - PCI
|
||||
* - PDEV (generic platform device centralized driver model)
|
||||
*
|
||||
* (c) 2007 Sebastian Siewior <bigeasy@linutronix.de>
|
||||
*
|
||||
@@ -11,6 +12,7 @@
|
||||
#include <linux/usb.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/usb/isp1760.h>
|
||||
|
||||
#include "../core/hcd.h"
|
||||
#include "isp1760-hcd.h"
|
||||
@@ -308,6 +310,8 @@ static int __devinit isp1760_plat_probe(struct platform_device *pdev)
|
||||
struct resource *mem_res;
|
||||
struct resource *irq_res;
|
||||
resource_size_t mem_size;
|
||||
struct isp1760_platform_data *priv = pdev->dev.platform_data;
|
||||
unsigned int devflags = 0;
|
||||
unsigned long irqflags = IRQF_SHARED | IRQF_DISABLED;
|
||||
|
||||
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
@@ -330,8 +334,23 @@ static int __devinit isp1760_plat_probe(struct platform_device *pdev)
|
||||
}
|
||||
irqflags |= irq_res->flags & IRQF_TRIGGER_MASK;
|
||||
|
||||
if (priv) {
|
||||
if (priv->is_isp1761)
|
||||
devflags |= ISP1760_FLAG_ISP1761;
|
||||
if (priv->bus_width_16)
|
||||
devflags |= ISP1760_FLAG_BUS_WIDTH_16;
|
||||
if (priv->port1_otg)
|
||||
devflags |= ISP1760_FLAG_OTG_EN;
|
||||
if (priv->analog_oc)
|
||||
devflags |= ISP1760_FLAG_ANALOG_OC;
|
||||
if (priv->dack_polarity_high)
|
||||
devflags |= ISP1760_FLAG_DACK_POL_HIGH;
|
||||
if (priv->dreq_polarity_high)
|
||||
devflags |= ISP1760_FLAG_DREQ_POL_HIGH;
|
||||
}
|
||||
|
||||
hcd = isp1760_register(mem_res->start, mem_size, irq_res->start,
|
||||
irqflags, &pdev->dev, dev_name(&pdev->dev), 0);
|
||||
irqflags, &pdev->dev, dev_name(&pdev->dev), devflags);
|
||||
if (IS_ERR(hcd)) {
|
||||
pr_warning("isp1760: Failed to register the HCD device\n");
|
||||
ret = -ENODEV;
|
||||
|
@@ -148,7 +148,7 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
|
||||
at91_start_hc(pdev);
|
||||
ohci_hcd_init(hcd_to_ohci(hcd));
|
||||
|
||||
retval = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_DISABLED);
|
||||
retval = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_SHARED);
|
||||
if (retval == 0)
|
||||
return retval;
|
||||
|
||||
|
@@ -248,10 +248,9 @@ static int ohci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int ohci_hcd_au1xxx_drv_suspend(struct platform_device *pdev,
|
||||
pm_message_t message)
|
||||
static int ohci_hcd_au1xxx_drv_suspend(struct device *dev)
|
||||
{
|
||||
struct usb_hcd *hcd = platform_get_drvdata(pdev);
|
||||
struct usb_hcd *hcd = dev_get_drvdata(dev);
|
||||
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
|
||||
unsigned long flags;
|
||||
int rc;
|
||||
@@ -274,10 +273,6 @@ static int ohci_hcd_au1xxx_drv_suspend(struct platform_device *pdev,
|
||||
ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
|
||||
(void)ohci_readl(ohci, &ohci->regs->intrdisable);
|
||||
|
||||
/* make sure snapshot being resumed re-enumerates everything */
|
||||
if (message.event == PM_EVENT_PRETHAW)
|
||||
ohci_usb_reset(ohci);
|
||||
|
||||
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
|
||||
|
||||
au1xxx_stop_ohc();
|
||||
@@ -287,9 +282,9 @@ bail:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ohci_hcd_au1xxx_drv_resume(struct platform_device *pdev)
|
||||
static int ohci_hcd_au1xxx_drv_resume(struct device *dev)
|
||||
{
|
||||
struct usb_hcd *hcd = platform_get_drvdata(pdev);
|
||||
struct usb_hcd *hcd = dev_get_drvdata(dev);
|
||||
|
||||
au1xxx_start_ohc();
|
||||
|
||||
@@ -298,20 +293,26 @@ static int ohci_hcd_au1xxx_drv_resume(struct platform_device *pdev)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dev_pm_ops au1xxx_ohci_pmops = {
|
||||
.suspend = ohci_hcd_au1xxx_drv_suspend,
|
||||
.resume = ohci_hcd_au1xxx_drv_resume,
|
||||
};
|
||||
|
||||
#define AU1XXX_OHCI_PMOPS &au1xxx_ohci_pmops
|
||||
|
||||
#else
|
||||
#define ohci_hcd_au1xxx_drv_suspend NULL
|
||||
#define ohci_hcd_au1xxx_drv_resume NULL
|
||||
#define AU1XXX_OHCI_PMOPS NULL
|
||||
#endif
|
||||
|
||||
static struct platform_driver ohci_hcd_au1xxx_driver = {
|
||||
.probe = ohci_hcd_au1xxx_drv_probe,
|
||||
.remove = ohci_hcd_au1xxx_drv_remove,
|
||||
.shutdown = usb_hcd_platform_shutdown,
|
||||
.suspend = ohci_hcd_au1xxx_drv_suspend,
|
||||
.resume = ohci_hcd_au1xxx_drv_resume,
|
||||
.driver = {
|
||||
.name = "au1xxx-ohci",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = AU1XXX_OHCI_PMOPS,
|
||||
},
|
||||
};
|
||||
|
||||
|
@@ -188,7 +188,6 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct usb_hcd *hcd = platform_get_drvdata(pdev);
|
||||
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
|
||||
int status;
|
||||
|
||||
if (time_before(jiffies, ohci->next_statechange))
|
||||
msleep(5);
|
||||
|
@@ -34,7 +34,6 @@
|
||||
#include <linux/usb/otg.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/dmapool.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
|
@@ -177,9 +177,13 @@ static inline void pxa27x_setup_hc(struct pxa27x_ohci *ohci,
|
||||
|
||||
if (inf->flags & NO_OC_PROTECTION)
|
||||
uhcrhda |= UHCRHDA_NOCP;
|
||||
else
|
||||
uhcrhda &= ~UHCRHDA_NOCP;
|
||||
|
||||
if (inf->flags & OC_MODE_PERPORT)
|
||||
uhcrhda |= UHCRHDA_OCPM;
|
||||
else
|
||||
uhcrhda &= ~UHCRHDA_OCPM;
|
||||
|
||||
if (inf->power_on_delay) {
|
||||
uhcrhda &= ~UHCRHDA_POTPGT(0xff);
|
||||
|
@@ -418,7 +418,7 @@ static struct ed *ed_get (
|
||||
is_out = !(ep->desc.bEndpointAddress & USB_DIR_IN);
|
||||
|
||||
/* FIXME usbcore changes dev->devnum before SET_ADDRESS
|
||||
* suceeds ... otherwise we wouldn't need "pipe".
|
||||
* succeeds ... otherwise we wouldn't need "pipe".
|
||||
*/
|
||||
info = usb_pipedevice (pipe);
|
||||
ed->type = usb_pipetype(pipe);
|
||||
|
@@ -33,7 +33,6 @@
|
||||
#include <linux/timer.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
@@ -475,4 +475,4 @@ static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
|
||||
else if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI)
|
||||
quirk_usb_handoff_xhci(pdev);
|
||||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);
|
||||
|
@@ -91,43 +91,43 @@ static int r8a66597_clock_enable(struct r8a66597 *r8a66597)
|
||||
u16 tmp;
|
||||
int i = 0;
|
||||
|
||||
#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
|
||||
#if defined(CONFIG_HAVE_CLK)
|
||||
clk_enable(r8a66597->clk);
|
||||
if (r8a66597->pdata->on_chip) {
|
||||
#ifdef CONFIG_HAVE_CLK
|
||||
clk_enable(r8a66597->clk);
|
||||
#endif
|
||||
do {
|
||||
r8a66597_write(r8a66597, SCKE, SYSCFG0);
|
||||
tmp = r8a66597_read(r8a66597, SYSCFG0);
|
||||
if (i++ > 1000) {
|
||||
printk(KERN_ERR "r8a66597: register access fail.\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
} while ((tmp & SCKE) != SCKE);
|
||||
r8a66597_write(r8a66597, 0x04, 0x02);
|
||||
#else
|
||||
do {
|
||||
r8a66597_write(r8a66597, USBE, SYSCFG0);
|
||||
tmp = r8a66597_read(r8a66597, SYSCFG0);
|
||||
if (i++ > 1000) {
|
||||
printk(KERN_ERR "r8a66597: register access fail.\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
} while ((tmp & USBE) != USBE);
|
||||
r8a66597_bclr(r8a66597, USBE, SYSCFG0);
|
||||
r8a66597_mdfy(r8a66597, get_xtal_from_pdata(r8a66597->pdata), XTAL,
|
||||
SYSCFG0);
|
||||
do {
|
||||
r8a66597_write(r8a66597, SCKE, SYSCFG0);
|
||||
tmp = r8a66597_read(r8a66597, SYSCFG0);
|
||||
if (i++ > 1000) {
|
||||
printk(KERN_ERR "r8a66597: reg access fail.\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
} while ((tmp & SCKE) != SCKE);
|
||||
r8a66597_write(r8a66597, 0x04, 0x02);
|
||||
} else {
|
||||
do {
|
||||
r8a66597_write(r8a66597, USBE, SYSCFG0);
|
||||
tmp = r8a66597_read(r8a66597, SYSCFG0);
|
||||
if (i++ > 1000) {
|
||||
printk(KERN_ERR "r8a66597: reg access fail.\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
} while ((tmp & USBE) != USBE);
|
||||
r8a66597_bclr(r8a66597, USBE, SYSCFG0);
|
||||
r8a66597_mdfy(r8a66597, get_xtal_from_pdata(r8a66597->pdata),
|
||||
XTAL, SYSCFG0);
|
||||
|
||||
i = 0;
|
||||
r8a66597_bset(r8a66597, XCKE, SYSCFG0);
|
||||
do {
|
||||
msleep(1);
|
||||
tmp = r8a66597_read(r8a66597, SYSCFG0);
|
||||
if (i++ > 500) {
|
||||
printk(KERN_ERR "r8a66597: register access fail.\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
} while ((tmp & SCKE) != SCKE);
|
||||
#endif /* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */
|
||||
i = 0;
|
||||
r8a66597_bset(r8a66597, XCKE, SYSCFG0);
|
||||
do {
|
||||
msleep(1);
|
||||
tmp = r8a66597_read(r8a66597, SYSCFG0);
|
||||
if (i++ > 500) {
|
||||
printk(KERN_ERR "r8a66597: reg access fail.\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
} while ((tmp & SCKE) != SCKE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -136,15 +136,16 @@ static void r8a66597_clock_disable(struct r8a66597 *r8a66597)
|
||||
{
|
||||
r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
|
||||
udelay(1);
|
||||
#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
|
||||
#if defined(CONFIG_HAVE_CLK)
|
||||
clk_disable(r8a66597->clk);
|
||||
#endif
|
||||
#else
|
||||
r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
|
||||
r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
|
||||
r8a66597_bclr(r8a66597, USBE, SYSCFG0);
|
||||
|
||||
if (r8a66597->pdata->on_chip) {
|
||||
#ifdef CONFIG_HAVE_CLK
|
||||
clk_disable(r8a66597->clk);
|
||||
#endif
|
||||
} else {
|
||||
r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
|
||||
r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
|
||||
r8a66597_bclr(r8a66597, USBE, SYSCFG0);
|
||||
}
|
||||
}
|
||||
|
||||
static void r8a66597_enable_port(struct r8a66597 *r8a66597, int port)
|
||||
@@ -205,7 +206,7 @@ static int enable_controller(struct r8a66597 *r8a66597)
|
||||
|
||||
r8a66597_bset(r8a66597, SIGNE | SACKE, INTENB1);
|
||||
|
||||
for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
|
||||
for (port = 0; port < r8a66597->max_root_hub; port++)
|
||||
r8a66597_enable_port(r8a66597, port);
|
||||
|
||||
return 0;
|
||||
@@ -218,7 +219,7 @@ static void disable_controller(struct r8a66597 *r8a66597)
|
||||
r8a66597_write(r8a66597, 0, INTENB0);
|
||||
r8a66597_write(r8a66597, 0, INTSTS0);
|
||||
|
||||
for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
|
||||
for (port = 0; port < r8a66597->max_root_hub; port++)
|
||||
r8a66597_disable_port(r8a66597, port);
|
||||
|
||||
r8a66597_clock_disable(r8a66597);
|
||||
@@ -249,11 +250,12 @@ static int is_hub_limit(char *devpath)
|
||||
return ((strlen(devpath) >= 4) ? 1 : 0);
|
||||
}
|
||||
|
||||
static void get_port_number(char *devpath, u16 *root_port, u16 *hub_port)
|
||||
static void get_port_number(struct r8a66597 *r8a66597,
|
||||
char *devpath, u16 *root_port, u16 *hub_port)
|
||||
{
|
||||
if (root_port) {
|
||||
*root_port = (devpath[0] & 0x0F) - 1;
|
||||
if (*root_port >= R8A66597_MAX_ROOT_HUB)
|
||||
if (*root_port >= r8a66597->max_root_hub)
|
||||
printk(KERN_ERR "r8a66597: Illegal root port number.\n");
|
||||
}
|
||||
if (hub_port)
|
||||
@@ -355,7 +357,8 @@ static int make_r8a66597_device(struct r8a66597 *r8a66597,
|
||||
INIT_LIST_HEAD(&dev->device_list);
|
||||
list_add_tail(&dev->device_list, &r8a66597->child_device);
|
||||
|
||||
get_port_number(urb->dev->devpath, &dev->root_port, &dev->hub_port);
|
||||
get_port_number(r8a66597, urb->dev->devpath,
|
||||
&dev->root_port, &dev->hub_port);
|
||||
if (!is_child_device(urb->dev->devpath))
|
||||
r8a66597->root_hub[dev->root_port].dev = dev;
|
||||
|
||||
@@ -420,7 +423,7 @@ static void free_usb_address(struct r8a66597 *r8a66597,
|
||||
list_del(&dev->device_list);
|
||||
kfree(dev);
|
||||
|
||||
for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
|
||||
for (port = 0; port < r8a66597->max_root_hub; port++) {
|
||||
if (r8a66597->root_hub[port].dev == dev) {
|
||||
r8a66597->root_hub[port].dev = NULL;
|
||||
break;
|
||||
@@ -495,10 +498,20 @@ static void r8a66597_pipe_toggle(struct r8a66597 *r8a66597,
|
||||
r8a66597_bset(r8a66597, SQCLR, pipe->pipectr);
|
||||
}
|
||||
|
||||
static inline unsigned short mbw_value(struct r8a66597 *r8a66597)
|
||||
{
|
||||
if (r8a66597->pdata->on_chip)
|
||||
return MBW_32;
|
||||
else
|
||||
return MBW_16;
|
||||
}
|
||||
|
||||
/* this function must be called with interrupt disabled */
|
||||
static inline void cfifo_change(struct r8a66597 *r8a66597, u16 pipenum)
|
||||
{
|
||||
r8a66597_mdfy(r8a66597, MBW | pipenum, MBW | CURPIPE, CFIFOSEL);
|
||||
unsigned short mbw = mbw_value(r8a66597);
|
||||
|
||||
r8a66597_mdfy(r8a66597, mbw | pipenum, mbw | CURPIPE, CFIFOSEL);
|
||||
r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, pipenum);
|
||||
}
|
||||
|
||||
@@ -506,11 +519,13 @@ static inline void cfifo_change(struct r8a66597 *r8a66597, u16 pipenum)
|
||||
static inline void fifo_change_from_pipe(struct r8a66597 *r8a66597,
|
||||
struct r8a66597_pipe *pipe)
|
||||
{
|
||||
cfifo_change(r8a66597, 0);
|
||||
r8a66597_mdfy(r8a66597, MBW | 0, MBW | CURPIPE, D0FIFOSEL);
|
||||
r8a66597_mdfy(r8a66597, MBW | 0, MBW | CURPIPE, D1FIFOSEL);
|
||||
unsigned short mbw = mbw_value(r8a66597);
|
||||
|
||||
r8a66597_mdfy(r8a66597, MBW | pipe->info.pipenum, MBW | CURPIPE,
|
||||
cfifo_change(r8a66597, 0);
|
||||
r8a66597_mdfy(r8a66597, mbw | 0, mbw | CURPIPE, D0FIFOSEL);
|
||||
r8a66597_mdfy(r8a66597, mbw | 0, mbw | CURPIPE, D1FIFOSEL);
|
||||
|
||||
r8a66597_mdfy(r8a66597, mbw | pipe->info.pipenum, mbw | CURPIPE,
|
||||
pipe->fifosel);
|
||||
r8a66597_reg_wait(r8a66597, pipe->fifosel, CURPIPE, pipe->info.pipenum);
|
||||
}
|
||||
@@ -742,9 +757,13 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
|
||||
struct r8a66597_pipe *pipe,
|
||||
struct urb *urb)
|
||||
{
|
||||
#if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
|
||||
int i;
|
||||
struct r8a66597_pipe_info *info = &pipe->info;
|
||||
unsigned short mbw = mbw_value(r8a66597);
|
||||
|
||||
/* pipe dma is only for external controlles */
|
||||
if (r8a66597->pdata->on_chip)
|
||||
return;
|
||||
|
||||
if ((pipe->info.pipenum != 0) && (info->type != R8A66597_INT)) {
|
||||
for (i = 0; i < R8A66597_MAX_DMA_CHANNEL; i++) {
|
||||
@@ -763,8 +782,8 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
|
||||
set_pipe_reg_addr(pipe, i);
|
||||
|
||||
cfifo_change(r8a66597, 0);
|
||||
r8a66597_mdfy(r8a66597, MBW | pipe->info.pipenum,
|
||||
MBW | CURPIPE, pipe->fifosel);
|
||||
r8a66597_mdfy(r8a66597, mbw | pipe->info.pipenum,
|
||||
mbw | CURPIPE, pipe->fifosel);
|
||||
|
||||
r8a66597_reg_wait(r8a66597, pipe->fifosel, CURPIPE,
|
||||
pipe->info.pipenum);
|
||||
@@ -772,7 +791,6 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */
|
||||
}
|
||||
|
||||
/* this function must be called with interrupt disabled */
|
||||
@@ -1769,7 +1787,7 @@ static void r8a66597_timer(unsigned long _r8a66597)
|
||||
|
||||
spin_lock_irqsave(&r8a66597->lock, flags);
|
||||
|
||||
for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
|
||||
for (port = 0; port < r8a66597->max_root_hub; port++)
|
||||
r8a66597_root_hub_control(r8a66597, port);
|
||||
|
||||
spin_unlock_irqrestore(&r8a66597->lock, flags);
|
||||
@@ -1807,7 +1825,7 @@ static void set_address_zero(struct r8a66597 *r8a66597, struct urb *urb)
|
||||
u16 root_port, hub_port;
|
||||
|
||||
if (usb_address == 0) {
|
||||
get_port_number(urb->dev->devpath,
|
||||
get_port_number(r8a66597, urb->dev->devpath,
|
||||
&root_port, &hub_port);
|
||||
set_devadd_reg(r8a66597, 0,
|
||||
get_r8a66597_usb_speed(urb->dev->speed),
|
||||
@@ -2082,7 +2100,7 @@ static int r8a66597_hub_status_data(struct usb_hcd *hcd, char *buf)
|
||||
|
||||
*buf = 0; /* initialize (no change) */
|
||||
|
||||
for (i = 0; i < R8A66597_MAX_ROOT_HUB; i++) {
|
||||
for (i = 0; i < r8a66597->max_root_hub; i++) {
|
||||
if (r8a66597->root_hub[i].port & 0xffff0000)
|
||||
*buf |= 1 << (i + 1);
|
||||
}
|
||||
@@ -2097,11 +2115,11 @@ static void r8a66597_hub_descriptor(struct r8a66597 *r8a66597,
|
||||
{
|
||||
desc->bDescriptorType = 0x29;
|
||||
desc->bHubContrCurrent = 0;
|
||||
desc->bNbrPorts = R8A66597_MAX_ROOT_HUB;
|
||||
desc->bNbrPorts = r8a66597->max_root_hub;
|
||||
desc->bDescLength = 9;
|
||||
desc->bPwrOn2PwrGood = 0;
|
||||
desc->wHubCharacteristics = cpu_to_le16(0x0011);
|
||||
desc->bitmap[0] = ((1 << R8A66597_MAX_ROOT_HUB) - 1) << 1;
|
||||
desc->bitmap[0] = ((1 << r8a66597->max_root_hub) - 1) << 1;
|
||||
desc->bitmap[1] = ~0;
|
||||
}
|
||||
|
||||
@@ -2129,7 +2147,7 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
||||
}
|
||||
break;
|
||||
case ClearPortFeature:
|
||||
if (wIndex > R8A66597_MAX_ROOT_HUB)
|
||||
if (wIndex > r8a66597->max_root_hub)
|
||||
goto error;
|
||||
if (wLength != 0)
|
||||
goto error;
|
||||
@@ -2162,12 +2180,12 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
||||
*buf = 0x00;
|
||||
break;
|
||||
case GetPortStatus:
|
||||
if (wIndex > R8A66597_MAX_ROOT_HUB)
|
||||
if (wIndex > r8a66597->max_root_hub)
|
||||
goto error;
|
||||
*(__le32 *)buf = cpu_to_le32(rh->port);
|
||||
break;
|
||||
case SetPortFeature:
|
||||
if (wIndex > R8A66597_MAX_ROOT_HUB)
|
||||
if (wIndex > r8a66597->max_root_hub)
|
||||
goto error;
|
||||
if (wLength != 0)
|
||||
goto error;
|
||||
@@ -2216,7 +2234,7 @@ static int r8a66597_bus_suspend(struct usb_hcd *hcd)
|
||||
|
||||
dbg("%s", __func__);
|
||||
|
||||
for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
|
||||
for (port = 0; port < r8a66597->max_root_hub; port++) {
|
||||
struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
|
||||
unsigned long dvstctr_reg = get_dvstctr_reg(port);
|
||||
|
||||
@@ -2247,7 +2265,7 @@ static int r8a66597_bus_resume(struct usb_hcd *hcd)
|
||||
|
||||
dbg("%s", __func__);
|
||||
|
||||
for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
|
||||
for (port = 0; port < r8a66597->max_root_hub; port++) {
|
||||
struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
|
||||
unsigned long dvstctr_reg = get_dvstctr_reg(port);
|
||||
|
||||
@@ -2305,16 +2323,16 @@ static struct hc_driver r8a66597_hc_driver = {
|
||||
};
|
||||
|
||||
#if defined(CONFIG_PM)
|
||||
static int r8a66597_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
static int r8a66597_suspend(struct device *dev)
|
||||
{
|
||||
struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev);
|
||||
struct r8a66597 *r8a66597 = dev_get_drvdata(dev);
|
||||
int port;
|
||||
|
||||
dbg("%s", __func__);
|
||||
|
||||
disable_controller(r8a66597);
|
||||
|
||||
for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
|
||||
for (port = 0; port < r8a66597->max_root_hub; port++) {
|
||||
struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
|
||||
|
||||
rh->port = 0x00000000;
|
||||
@@ -2323,9 +2341,9 @@ static int r8a66597_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int r8a66597_resume(struct platform_device *pdev)
|
||||
static int r8a66597_resume(struct device *dev)
|
||||
{
|
||||
struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev);
|
||||
struct r8a66597 *r8a66597 = dev_get_drvdata(dev);
|
||||
struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597);
|
||||
|
||||
dbg("%s", __func__);
|
||||
@@ -2335,9 +2353,17 @@ static int r8a66597_resume(struct platform_device *pdev)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dev_pm_ops r8a66597_dev_pm_ops = {
|
||||
.suspend = r8a66597_suspend,
|
||||
.resume = r8a66597_resume,
|
||||
.poweroff = r8a66597_suspend,
|
||||
.restore = r8a66597_resume,
|
||||
};
|
||||
|
||||
#define R8A66597_DEV_PM_OPS (&r8a66597_dev_pm_ops)
|
||||
#else /* if defined(CONFIG_PM) */
|
||||
#define r8a66597_suspend NULL
|
||||
#define r8a66597_resume NULL
|
||||
#define R8A66597_DEV_PM_OPS NULL
|
||||
#endif
|
||||
|
||||
static int __init_or_module r8a66597_remove(struct platform_device *pdev)
|
||||
@@ -2348,8 +2374,9 @@ static int __init_or_module r8a66597_remove(struct platform_device *pdev)
|
||||
del_timer_sync(&r8a66597->rh_timer);
|
||||
usb_remove_hcd(hcd);
|
||||
iounmap((void *)r8a66597->reg);
|
||||
#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK)
|
||||
clk_put(r8a66597->clk);
|
||||
#ifdef CONFIG_HAVE_CLK
|
||||
if (r8a66597->pdata->on_chip)
|
||||
clk_put(r8a66597->clk);
|
||||
#endif
|
||||
usb_put_hcd(hcd);
|
||||
return 0;
|
||||
@@ -2357,7 +2384,7 @@ static int __init_or_module r8a66597_remove(struct platform_device *pdev)
|
||||
|
||||
static int __devinit r8a66597_probe(struct platform_device *pdev)
|
||||
{
|
||||
#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK)
|
||||
#ifdef CONFIG_HAVE_CLK
|
||||
char clk_name[8];
|
||||
#endif
|
||||
struct resource *res = NULL, *ires;
|
||||
@@ -2419,15 +2446,20 @@ static int __devinit r8a66597_probe(struct platform_device *pdev)
|
||||
r8a66597->pdata = pdev->dev.platform_data;
|
||||
r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;
|
||||
|
||||
#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK)
|
||||
snprintf(clk_name, sizeof(clk_name), "usb%d", pdev->id);
|
||||
r8a66597->clk = clk_get(&pdev->dev, clk_name);
|
||||
if (IS_ERR(r8a66597->clk)) {
|
||||
dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
|
||||
ret = PTR_ERR(r8a66597->clk);
|
||||
goto clean_up2;
|
||||
}
|
||||
if (r8a66597->pdata->on_chip) {
|
||||
#ifdef CONFIG_HAVE_CLK
|
||||
snprintf(clk_name, sizeof(clk_name), "usb%d", pdev->id);
|
||||
r8a66597->clk = clk_get(&pdev->dev, clk_name);
|
||||
if (IS_ERR(r8a66597->clk)) {
|
||||
dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
|
||||
clk_name);
|
||||
ret = PTR_ERR(r8a66597->clk);
|
||||
goto clean_up2;
|
||||
}
|
||||
#endif
|
||||
r8a66597->max_root_hub = 1;
|
||||
} else
|
||||
r8a66597->max_root_hub = 2;
|
||||
|
||||
spin_lock_init(&r8a66597->lock);
|
||||
init_timer(&r8a66597->rh_timer);
|
||||
@@ -2457,8 +2489,9 @@ static int __devinit r8a66597_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
|
||||
clean_up3:
|
||||
#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK)
|
||||
clk_put(r8a66597->clk);
|
||||
#ifdef CONFIG_HAVE_CLK
|
||||
if (r8a66597->pdata->on_chip)
|
||||
clk_put(r8a66597->clk);
|
||||
clean_up2:
|
||||
#endif
|
||||
usb_put_hcd(hcd);
|
||||
@@ -2473,11 +2506,10 @@ clean_up:
|
||||
static struct platform_driver r8a66597_driver = {
|
||||
.probe = r8a66597_probe,
|
||||
.remove = r8a66597_remove,
|
||||
.suspend = r8a66597_suspend,
|
||||
.resume = r8a66597_resume,
|
||||
.driver = {
|
||||
.name = (char *) hcd_name,
|
||||
.owner = THIS_MODULE,
|
||||
.pm = R8A66597_DEV_PM_OPS,
|
||||
},
|
||||
};
|
||||
|
||||
|
@@ -26,390 +26,16 @@
|
||||
#ifndef __R8A66597_H__
|
||||
#define __R8A66597_H__
|
||||
|
||||
#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK)
|
||||
#ifdef CONFIG_HAVE_CLK
|
||||
#include <linux/clk.h>
|
||||
#endif
|
||||
|
||||
#include <linux/usb/r8a66597.h>
|
||||
|
||||
#define SYSCFG0 0x00
|
||||
#define SYSCFG1 0x02
|
||||
#define SYSSTS0 0x04
|
||||
#define SYSSTS1 0x06
|
||||
#define DVSTCTR0 0x08
|
||||
#define DVSTCTR1 0x0A
|
||||
#define TESTMODE 0x0C
|
||||
#define PINCFG 0x0E
|
||||
#define DMA0CFG 0x10
|
||||
#define DMA1CFG 0x12
|
||||
#define CFIFO 0x14
|
||||
#define D0FIFO 0x18
|
||||
#define D1FIFO 0x1C
|
||||
#define CFIFOSEL 0x20
|
||||
#define CFIFOCTR 0x22
|
||||
#define CFIFOSIE 0x24
|
||||
#define D0FIFOSEL 0x28
|
||||
#define D0FIFOCTR 0x2A
|
||||
#define D1FIFOSEL 0x2C
|
||||
#define D1FIFOCTR 0x2E
|
||||
#define INTENB0 0x30
|
||||
#define INTENB1 0x32
|
||||
#define INTENB2 0x34
|
||||
#define BRDYENB 0x36
|
||||
#define NRDYENB 0x38
|
||||
#define BEMPENB 0x3A
|
||||
#define SOFCFG 0x3C
|
||||
#define INTSTS0 0x40
|
||||
#define INTSTS1 0x42
|
||||
#define INTSTS2 0x44
|
||||
#define BRDYSTS 0x46
|
||||
#define NRDYSTS 0x48
|
||||
#define BEMPSTS 0x4A
|
||||
#define FRMNUM 0x4C
|
||||
#define UFRMNUM 0x4E
|
||||
#define USBADDR 0x50
|
||||
#define USBREQ 0x54
|
||||
#define USBVAL 0x56
|
||||
#define USBINDX 0x58
|
||||
#define USBLENG 0x5A
|
||||
#define DCPCFG 0x5C
|
||||
#define DCPMAXP 0x5E
|
||||
#define DCPCTR 0x60
|
||||
#define PIPESEL 0x64
|
||||
#define PIPECFG 0x68
|
||||
#define PIPEBUF 0x6A
|
||||
#define PIPEMAXP 0x6C
|
||||
#define PIPEPERI 0x6E
|
||||
#define PIPE1CTR 0x70
|
||||
#define PIPE2CTR 0x72
|
||||
#define PIPE3CTR 0x74
|
||||
#define PIPE4CTR 0x76
|
||||
#define PIPE5CTR 0x78
|
||||
#define PIPE6CTR 0x7A
|
||||
#define PIPE7CTR 0x7C
|
||||
#define PIPE8CTR 0x7E
|
||||
#define PIPE9CTR 0x80
|
||||
#define PIPE1TRE 0x90
|
||||
#define PIPE1TRN 0x92
|
||||
#define PIPE2TRE 0x94
|
||||
#define PIPE2TRN 0x96
|
||||
#define PIPE3TRE 0x98
|
||||
#define PIPE3TRN 0x9A
|
||||
#define PIPE4TRE 0x9C
|
||||
#define PIPE4TRN 0x9E
|
||||
#define PIPE5TRE 0xA0
|
||||
#define PIPE5TRN 0xA2
|
||||
#define DEVADD0 0xD0
|
||||
#define DEVADD1 0xD2
|
||||
#define DEVADD2 0xD4
|
||||
#define DEVADD3 0xD6
|
||||
#define DEVADD4 0xD8
|
||||
#define DEVADD5 0xDA
|
||||
#define DEVADD6 0xDC
|
||||
#define DEVADD7 0xDE
|
||||
#define DEVADD8 0xE0
|
||||
#define DEVADD9 0xE2
|
||||
#define DEVADDA 0xE4
|
||||
|
||||
/* System Configuration Control Register */
|
||||
#define XTAL 0xC000 /* b15-14: Crystal selection */
|
||||
#define XTAL48 0x8000 /* 48MHz */
|
||||
#define XTAL24 0x4000 /* 24MHz */
|
||||
#define XTAL12 0x0000 /* 12MHz */
|
||||
#define XCKE 0x2000 /* b13: External clock enable */
|
||||
#define PLLC 0x0800 /* b11: PLL control */
|
||||
#define SCKE 0x0400 /* b10: USB clock enable */
|
||||
#define PCSDIS 0x0200 /* b9: not CS wakeup */
|
||||
#define LPSME 0x0100 /* b8: Low power sleep mode */
|
||||
#define HSE 0x0080 /* b7: Hi-speed enable */
|
||||
#define DCFM 0x0040 /* b6: Controller function select */
|
||||
#define DRPD 0x0020 /* b5: D+/- pull down control */
|
||||
#define DPRPU 0x0010 /* b4: D+ pull up control */
|
||||
#define USBE 0x0001 /* b0: USB module operation enable */
|
||||
|
||||
/* System Configuration Status Register */
|
||||
#define OVCBIT 0x8000 /* b15-14: Over-current bit */
|
||||
#define OVCMON 0xC000 /* b15-14: Over-current monitor */
|
||||
#define SOFEA 0x0020 /* b5: SOF monitor */
|
||||
#define IDMON 0x0004 /* b3: ID-pin monitor */
|
||||
#define LNST 0x0003 /* b1-0: D+, D- line status */
|
||||
#define SE1 0x0003 /* SE1 */
|
||||
#define FS_KSTS 0x0002 /* Full-Speed K State */
|
||||
#define FS_JSTS 0x0001 /* Full-Speed J State */
|
||||
#define LS_JSTS 0x0002 /* Low-Speed J State */
|
||||
#define LS_KSTS 0x0001 /* Low-Speed K State */
|
||||
#define SE0 0x0000 /* SE0 */
|
||||
|
||||
/* Device State Control Register */
|
||||
#define EXTLP0 0x0400 /* b10: External port */
|
||||
#define VBOUT 0x0200 /* b9: VBUS output */
|
||||
#define WKUP 0x0100 /* b8: Remote wakeup */
|
||||
#define RWUPE 0x0080 /* b7: Remote wakeup sense */
|
||||
#define USBRST 0x0040 /* b6: USB reset enable */
|
||||
#define RESUME 0x0020 /* b5: Resume enable */
|
||||
#define UACT 0x0010 /* b4: USB bus enable */
|
||||
#define RHST 0x0007 /* b1-0: Reset handshake status */
|
||||
#define HSPROC 0x0004 /* HS handshake is processing */
|
||||
#define HSMODE 0x0003 /* Hi-Speed mode */
|
||||
#define FSMODE 0x0002 /* Full-Speed mode */
|
||||
#define LSMODE 0x0001 /* Low-Speed mode */
|
||||
#define UNDECID 0x0000 /* Undecided */
|
||||
|
||||
/* Test Mode Register */
|
||||
#define UTST 0x000F /* b3-0: Test select */
|
||||
#define H_TST_PACKET 0x000C /* HOST TEST Packet */
|
||||
#define H_TST_SE0_NAK 0x000B /* HOST TEST SE0 NAK */
|
||||
#define H_TST_K 0x000A /* HOST TEST K */
|
||||
#define H_TST_J 0x0009 /* HOST TEST J */
|
||||
#define H_TST_NORMAL 0x0000 /* HOST Normal Mode */
|
||||
#define P_TST_PACKET 0x0004 /* PERI TEST Packet */
|
||||
#define P_TST_SE0_NAK 0x0003 /* PERI TEST SE0 NAK */
|
||||
#define P_TST_K 0x0002 /* PERI TEST K */
|
||||
#define P_TST_J 0x0001 /* PERI TEST J */
|
||||
#define P_TST_NORMAL 0x0000 /* PERI Normal Mode */
|
||||
|
||||
/* Data Pin Configuration Register */
|
||||
#define LDRV 0x8000 /* b15: Drive Current Adjust */
|
||||
#define VIF1 0x0000 /* VIF = 1.8V */
|
||||
#define VIF3 0x8000 /* VIF = 3.3V */
|
||||
#define INTA 0x0001 /* b1: USB INT-pin active */
|
||||
|
||||
/* DMAx Pin Configuration Register */
|
||||
#define DREQA 0x4000 /* b14: Dreq active select */
|
||||
#define BURST 0x2000 /* b13: Burst mode */
|
||||
#define DACKA 0x0400 /* b10: Dack active select */
|
||||
#define DFORM 0x0380 /* b9-7: DMA mode select */
|
||||
#define CPU_ADR_RD_WR 0x0000 /* Address + RD/WR mode (CPU bus) */
|
||||
#define CPU_DACK_RD_WR 0x0100 /* DACK + RD/WR mode (CPU bus) */
|
||||
#define CPU_DACK_ONLY 0x0180 /* DACK only mode (CPU bus) */
|
||||
#define SPLIT_DACK_ONLY 0x0200 /* DACK only mode (SPLIT bus) */
|
||||
#define DENDA 0x0040 /* b6: Dend active select */
|
||||
#define PKTM 0x0020 /* b5: Packet mode */
|
||||
#define DENDE 0x0010 /* b4: Dend enable */
|
||||
#define OBUS 0x0004 /* b2: OUTbus mode */
|
||||
|
||||
/* CFIFO/DxFIFO Port Select Register */
|
||||
#define RCNT 0x8000 /* b15: Read count mode */
|
||||
#define REW 0x4000 /* b14: Buffer rewind */
|
||||
#define DCLRM 0x2000 /* b13: DMA buffer clear mode */
|
||||
#define DREQE 0x1000 /* b12: DREQ output enable */
|
||||
#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
|
||||
#define MBW 0x0800
|
||||
#else
|
||||
#define MBW 0x0400 /* b10: Maximum bit width for FIFO access */
|
||||
#endif
|
||||
#define MBW_8 0x0000 /* 8bit */
|
||||
#define MBW_16 0x0400 /* 16bit */
|
||||
#define BIGEND 0x0100 /* b8: Big endian mode */
|
||||
#define BYTE_LITTLE 0x0000 /* little dendian */
|
||||
#define BYTE_BIG 0x0100 /* big endifan */
|
||||
#define ISEL 0x0020 /* b5: DCP FIFO port direction select */
|
||||
#define CURPIPE 0x000F /* b2-0: PIPE select */
|
||||
|
||||
/* CFIFO/DxFIFO Port Control Register */
|
||||
#define BVAL 0x8000 /* b15: Buffer valid flag */
|
||||
#define BCLR 0x4000 /* b14: Buffer clear */
|
||||
#define FRDY 0x2000 /* b13: FIFO ready */
|
||||
#define DTLN 0x0FFF /* b11-0: FIFO received data length */
|
||||
|
||||
/* Interrupt Enable Register 0 */
|
||||
#define VBSE 0x8000 /* b15: VBUS interrupt */
|
||||
#define RSME 0x4000 /* b14: Resume interrupt */
|
||||
#define SOFE 0x2000 /* b13: Frame update interrupt */
|
||||
#define DVSE 0x1000 /* b12: Device state transition interrupt */
|
||||
#define CTRE 0x0800 /* b11: Control transfer stage transition interrupt */
|
||||
#define BEMPE 0x0400 /* b10: Buffer empty interrupt */
|
||||
#define NRDYE 0x0200 /* b9: Buffer not ready interrupt */
|
||||
#define BRDYE 0x0100 /* b8: Buffer ready interrupt */
|
||||
|
||||
/* Interrupt Enable Register 1 */
|
||||
#define OVRCRE 0x8000 /* b15: Over-current interrupt */
|
||||
#define BCHGE 0x4000 /* b14: USB us chenge interrupt */
|
||||
#define DTCHE 0x1000 /* b12: Detach sense interrupt */
|
||||
#define ATTCHE 0x0800 /* b11: Attach sense interrupt */
|
||||
#define EOFERRE 0x0040 /* b6: EOF error interrupt */
|
||||
#define SIGNE 0x0020 /* b5: SETUP IGNORE interrupt */
|
||||
#define SACKE 0x0010 /* b4: SETUP ACK interrupt */
|
||||
|
||||
/* BRDY Interrupt Enable/Status Register */
|
||||
#define BRDY9 0x0200 /* b9: PIPE9 */
|
||||
#define BRDY8 0x0100 /* b8: PIPE8 */
|
||||
#define BRDY7 0x0080 /* b7: PIPE7 */
|
||||
#define BRDY6 0x0040 /* b6: PIPE6 */
|
||||
#define BRDY5 0x0020 /* b5: PIPE5 */
|
||||
#define BRDY4 0x0010 /* b4: PIPE4 */
|
||||
#define BRDY3 0x0008 /* b3: PIPE3 */
|
||||
#define BRDY2 0x0004 /* b2: PIPE2 */
|
||||
#define BRDY1 0x0002 /* b1: PIPE1 */
|
||||
#define BRDY0 0x0001 /* b1: PIPE0 */
|
||||
|
||||
/* NRDY Interrupt Enable/Status Register */
|
||||
#define NRDY9 0x0200 /* b9: PIPE9 */
|
||||
#define NRDY8 0x0100 /* b8: PIPE8 */
|
||||
#define NRDY7 0x0080 /* b7: PIPE7 */
|
||||
#define NRDY6 0x0040 /* b6: PIPE6 */
|
||||
#define NRDY5 0x0020 /* b5: PIPE5 */
|
||||
#define NRDY4 0x0010 /* b4: PIPE4 */
|
||||
#define NRDY3 0x0008 /* b3: PIPE3 */
|
||||
#define NRDY2 0x0004 /* b2: PIPE2 */
|
||||
#define NRDY1 0x0002 /* b1: PIPE1 */
|
||||
#define NRDY0 0x0001 /* b1: PIPE0 */
|
||||
|
||||
/* BEMP Interrupt Enable/Status Register */
|
||||
#define BEMP9 0x0200 /* b9: PIPE9 */
|
||||
#define BEMP8 0x0100 /* b8: PIPE8 */
|
||||
#define BEMP7 0x0080 /* b7: PIPE7 */
|
||||
#define BEMP6 0x0040 /* b6: PIPE6 */
|
||||
#define BEMP5 0x0020 /* b5: PIPE5 */
|
||||
#define BEMP4 0x0010 /* b4: PIPE4 */
|
||||
#define BEMP3 0x0008 /* b3: PIPE3 */
|
||||
#define BEMP2 0x0004 /* b2: PIPE2 */
|
||||
#define BEMP1 0x0002 /* b1: PIPE1 */
|
||||
#define BEMP0 0x0001 /* b0: PIPE0 */
|
||||
|
||||
/* SOF Pin Configuration Register */
|
||||
#define TRNENSEL 0x0100 /* b8: Select transaction enable period */
|
||||
#define BRDYM 0x0040 /* b6: BRDY clear timing */
|
||||
#define INTL 0x0020 /* b5: Interrupt sense select */
|
||||
#define EDGESTS 0x0010 /* b4: */
|
||||
#define SOFMODE 0x000C /* b3-2: SOF pin select */
|
||||
#define SOF_125US 0x0008 /* SOF OUT 125us Frame Signal */
|
||||
#define SOF_1MS 0x0004 /* SOF OUT 1ms Frame Signal */
|
||||
#define SOF_DISABLE 0x0000 /* SOF OUT Disable */
|
||||
|
||||
/* Interrupt Status Register 0 */
|
||||
#define VBINT 0x8000 /* b15: VBUS interrupt */
|
||||
#define RESM 0x4000 /* b14: Resume interrupt */
|
||||
#define SOFR 0x2000 /* b13: SOF frame update interrupt */
|
||||
#define DVST 0x1000 /* b12: Device state transition interrupt */
|
||||
#define CTRT 0x0800 /* b11: Control transfer stage transition interrupt */
|
||||
#define BEMP 0x0400 /* b10: Buffer empty interrupt */
|
||||
#define NRDY 0x0200 /* b9: Buffer not ready interrupt */
|
||||
#define BRDY 0x0100 /* b8: Buffer ready interrupt */
|
||||
#define VBSTS 0x0080 /* b7: VBUS input port */
|
||||
#define DVSQ 0x0070 /* b6-4: Device state */
|
||||
#define DS_SPD_CNFG 0x0070 /* Suspend Configured */
|
||||
#define DS_SPD_ADDR 0x0060 /* Suspend Address */
|
||||
#define DS_SPD_DFLT 0x0050 /* Suspend Default */
|
||||
#define DS_SPD_POWR 0x0040 /* Suspend Powered */
|
||||
#define DS_SUSP 0x0040 /* Suspend */
|
||||
#define DS_CNFG 0x0030 /* Configured */
|
||||
#define DS_ADDS 0x0020 /* Address */
|
||||
#define DS_DFLT 0x0010 /* Default */
|
||||
#define DS_POWR 0x0000 /* Powered */
|
||||
#define DVSQS 0x0030 /* b5-4: Device state */
|
||||
#define VALID 0x0008 /* b3: Setup packet detected flag */
|
||||
#define CTSQ 0x0007 /* b2-0: Control transfer stage */
|
||||
#define CS_SQER 0x0006 /* Sequence error */
|
||||
#define CS_WRND 0x0005 /* Control write nodata status stage */
|
||||
#define CS_WRSS 0x0004 /* Control write status stage */
|
||||
#define CS_WRDS 0x0003 /* Control write data stage */
|
||||
#define CS_RDSS 0x0002 /* Control read status stage */
|
||||
#define CS_RDDS 0x0001 /* Control read data stage */
|
||||
#define CS_IDST 0x0000 /* Idle or setup stage */
|
||||
|
||||
/* Interrupt Status Register 1 */
|
||||
#define OVRCR 0x8000 /* b15: Over-current interrupt */
|
||||
#define BCHG 0x4000 /* b14: USB bus chenge interrupt */
|
||||
#define DTCH 0x1000 /* b12: Detach sense interrupt */
|
||||
#define ATTCH 0x0800 /* b11: Attach sense interrupt */
|
||||
#define EOFERR 0x0040 /* b6: EOF-error interrupt */
|
||||
#define SIGN 0x0020 /* b5: Setup ignore interrupt */
|
||||
#define SACK 0x0010 /* b4: Setup acknowledge interrupt */
|
||||
|
||||
/* Frame Number Register */
|
||||
#define OVRN 0x8000 /* b15: Overrun error */
|
||||
#define CRCE 0x4000 /* b14: Received data error */
|
||||
#define FRNM 0x07FF /* b10-0: Frame number */
|
||||
|
||||
/* Micro Frame Number Register */
|
||||
#define UFRNM 0x0007 /* b2-0: Micro frame number */
|
||||
|
||||
/* Default Control Pipe Maxpacket Size Register */
|
||||
/* Pipe Maxpacket Size Register */
|
||||
#define DEVSEL 0xF000 /* b15-14: Device address select */
|
||||
#define MAXP 0x007F /* b6-0: Maxpacket size of default control pipe */
|
||||
|
||||
/* Default Control Pipe Control Register */
|
||||
#define BSTS 0x8000 /* b15: Buffer status */
|
||||
#define SUREQ 0x4000 /* b14: Send USB request */
|
||||
#define CSCLR 0x2000 /* b13: complete-split status clear */
|
||||
#define CSSTS 0x1000 /* b12: complete-split status */
|
||||
#define SUREQCLR 0x0800 /* b11: stop setup request */
|
||||
#define SQCLR 0x0100 /* b8: Sequence toggle bit clear */
|
||||
#define SQSET 0x0080 /* b7: Sequence toggle bit set */
|
||||
#define SQMON 0x0040 /* b6: Sequence toggle bit monitor */
|
||||
#define PBUSY 0x0020 /* b5: pipe busy */
|
||||
#define PINGE 0x0010 /* b4: ping enable */
|
||||
#define CCPL 0x0004 /* b2: Enable control transfer complete */
|
||||
#define PID 0x0003 /* b1-0: Response PID */
|
||||
#define PID_STALL11 0x0003 /* STALL */
|
||||
#define PID_STALL 0x0002 /* STALL */
|
||||
#define PID_BUF 0x0001 /* BUF */
|
||||
#define PID_NAK 0x0000 /* NAK */
|
||||
|
||||
/* Pipe Window Select Register */
|
||||
#define PIPENM 0x0007 /* b2-0: Pipe select */
|
||||
|
||||
/* Pipe Configuration Register */
|
||||
#define R8A66597_TYP 0xC000 /* b15-14: Transfer type */
|
||||
#define R8A66597_ISO 0xC000 /* Isochronous */
|
||||
#define R8A66597_INT 0x8000 /* Interrupt */
|
||||
#define R8A66597_BULK 0x4000 /* Bulk */
|
||||
#define R8A66597_BFRE 0x0400 /* b10: Buffer ready interrupt mode select */
|
||||
#define R8A66597_DBLB 0x0200 /* b9: Double buffer mode select */
|
||||
#define R8A66597_CNTMD 0x0100 /* b8: Continuous transfer mode select */
|
||||
#define R8A66597_SHTNAK 0x0080 /* b7: Transfer end NAK */
|
||||
#define R8A66597_DIR 0x0010 /* b4: Transfer direction select */
|
||||
#define R8A66597_EPNUM 0x000F /* b3-0: Eendpoint number select */
|
||||
|
||||
/* Pipe Buffer Configuration Register */
|
||||
#define BUFSIZE 0x7C00 /* b14-10: Pipe buffer size */
|
||||
#define BUFNMB 0x007F /* b6-0: Pipe buffer number */
|
||||
#define PIPE0BUF 256
|
||||
#define PIPExBUF 64
|
||||
|
||||
/* Pipe Maxpacket Size Register */
|
||||
#define MXPS 0x07FF /* b10-0: Maxpacket size */
|
||||
|
||||
/* Pipe Cycle Configuration Register */
|
||||
#define IFIS 0x1000 /* b12: Isochronous in-buffer flush mode select */
|
||||
#define IITV 0x0007 /* b2-0: Isochronous interval */
|
||||
|
||||
/* Pipex Control Register */
|
||||
#define BSTS 0x8000 /* b15: Buffer status */
|
||||
#define INBUFM 0x4000 /* b14: IN buffer monitor (Only for PIPE1 to 5) */
|
||||
#define CSCLR 0x2000 /* b13: complete-split status clear */
|
||||
#define CSSTS 0x1000 /* b12: complete-split status */
|
||||
#define ATREPM 0x0400 /* b10: Auto repeat mode */
|
||||
#define ACLRM 0x0200 /* b9: Out buffer auto clear mode */
|
||||
#define SQCLR 0x0100 /* b8: Sequence toggle bit clear */
|
||||
#define SQSET 0x0080 /* b7: Sequence toggle bit set */
|
||||
#define SQMON 0x0040 /* b6: Sequence toggle bit monitor */
|
||||
#define PBUSY 0x0020 /* b5: pipe busy */
|
||||
#define PID 0x0003 /* b1-0: Response PID */
|
||||
|
||||
/* PIPExTRE */
|
||||
#define TRENB 0x0200 /* b9: Transaction counter enable */
|
||||
#define TRCLR 0x0100 /* b8: Transaction counter clear */
|
||||
|
||||
/* PIPExTRN */
|
||||
#define TRNCNT 0xFFFF /* b15-0: Transaction counter */
|
||||
|
||||
/* DEVADDx */
|
||||
#define UPPHUB 0x7800
|
||||
#define HUBPORT 0x0700
|
||||
#define USBSPD 0x00C0
|
||||
#define RTPORT 0x0001
|
||||
|
||||
#define R8A66597_MAX_NUM_PIPE 10
|
||||
#define R8A66597_BUF_BSIZE 8
|
||||
#define R8A66597_MAX_DEVICE 10
|
||||
#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
|
||||
#define R8A66597_MAX_ROOT_HUB 1
|
||||
#else
|
||||
#define R8A66597_MAX_ROOT_HUB 2
|
||||
#endif
|
||||
#define R8A66597_MAX_SAMPLING 5
|
||||
#define R8A66597_RH_POLL_TIME 10
|
||||
#define R8A66597_MAX_DMA_CHANNEL 2
|
||||
@@ -487,7 +113,7 @@ struct r8a66597_root_hub {
|
||||
struct r8a66597 {
|
||||
spinlock_t lock;
|
||||
unsigned long reg;
|
||||
#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK)
|
||||
#ifdef CONFIG_HAVE_CLK
|
||||
struct clk *clk;
|
||||
#endif
|
||||
struct r8a66597_platdata *pdata;
|
||||
@@ -504,6 +130,7 @@ struct r8a66597 {
|
||||
unsigned short interval_map;
|
||||
unsigned char pipe_cnt[R8A66597_MAX_NUM_PIPE];
|
||||
unsigned char dma_map;
|
||||
unsigned int max_root_hub;
|
||||
|
||||
struct list_head child_device;
|
||||
unsigned long child_connect_map[4];
|
||||
@@ -550,21 +177,22 @@ static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
|
||||
unsigned long offset, u16 *buf,
|
||||
int len)
|
||||
{
|
||||
#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
|
||||
unsigned long fifoaddr = r8a66597->reg + offset;
|
||||
unsigned long count;
|
||||
|
||||
count = len / 4;
|
||||
insl(fifoaddr, buf, count);
|
||||
if (r8a66597->pdata->on_chip) {
|
||||
count = len / 4;
|
||||
insl(fifoaddr, buf, count);
|
||||
|
||||
if (len & 0x00000003) {
|
||||
unsigned long tmp = inl(fifoaddr);
|
||||
memcpy((unsigned char *)buf + count * 4, &tmp, len & 0x03);
|
||||
if (len & 0x00000003) {
|
||||
unsigned long tmp = inl(fifoaddr);
|
||||
memcpy((unsigned char *)buf + count * 4, &tmp,
|
||||
len & 0x03);
|
||||
}
|
||||
} else {
|
||||
len = (len + 1) / 2;
|
||||
insw(fifoaddr, buf, len);
|
||||
}
|
||||
#else
|
||||
len = (len + 1) / 2;
|
||||
insw(r8a66597->reg + offset, buf, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
|
||||
@@ -578,33 +206,33 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
|
||||
int len)
|
||||
{
|
||||
unsigned long fifoaddr = r8a66597->reg + offset;
|
||||
#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
|
||||
unsigned long count;
|
||||
unsigned char *pb;
|
||||
int i;
|
||||
|
||||
count = len / 4;
|
||||
outsl(fifoaddr, buf, count);
|
||||
if (r8a66597->pdata->on_chip) {
|
||||
count = len / 4;
|
||||
outsl(fifoaddr, buf, count);
|
||||
|
||||
if (len & 0x00000003) {
|
||||
pb = (unsigned char *)buf + count * 4;
|
||||
for (i = 0; i < (len & 0x00000003); i++) {
|
||||
if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)
|
||||
outb(pb[i], fifoaddr + i);
|
||||
else
|
||||
outb(pb[i], fifoaddr + 3 - i);
|
||||
if (len & 0x00000003) {
|
||||
pb = (unsigned char *)buf + count * 4;
|
||||
for (i = 0; i < (len & 0x00000003); i++) {
|
||||
if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)
|
||||
outb(pb[i], fifoaddr + i);
|
||||
else
|
||||
outb(pb[i], fifoaddr + 3 - i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int odd = len & 0x0001;
|
||||
|
||||
len = len / 2;
|
||||
outsw(fifoaddr, buf, len);
|
||||
if (unlikely(odd)) {
|
||||
buf = &buf[len];
|
||||
outb((unsigned char)*buf, fifoaddr);
|
||||
}
|
||||
}
|
||||
#else
|
||||
int odd = len & 0x0001;
|
||||
|
||||
len = len / 2;
|
||||
outsw(fifoaddr, buf, len);
|
||||
if (unlikely(odd)) {
|
||||
buf = &buf[len];
|
||||
outb((unsigned char)*buf, fifoaddr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
|
||||
|
@@ -719,8 +719,12 @@ retry:
|
||||
/* port status seems weird until after reset, so
|
||||
* force the reset and make khubd clean up later.
|
||||
*/
|
||||
sl811->port1 |= (1 << USB_PORT_FEAT_C_CONNECTION)
|
||||
| (1 << USB_PORT_FEAT_CONNECTION);
|
||||
if (sl811->stat_insrmv & 1)
|
||||
sl811->port1 |= 1 << USB_PORT_FEAT_CONNECTION;
|
||||
else
|
||||
sl811->port1 &= ~(1 << USB_PORT_FEAT_CONNECTION);
|
||||
|
||||
sl811->port1 |= 1 << USB_PORT_FEAT_C_CONNECTION;
|
||||
|
||||
} else if (irqstat & SL11H_INTMASK_RD) {
|
||||
if (sl811->port1 & (1 << USB_PORT_FEAT_SUSPEND)) {
|
||||
|
@@ -1422,7 +1422,6 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd,
|
||||
goto err_submit_failed;
|
||||
|
||||
/* Add this URB to the QH */
|
||||
urbp->qh = qh;
|
||||
list_add_tail(&urbp->node, &qh->queue);
|
||||
|
||||
/* If the new URB is the first and only one on this QH then either
|
||||
|
@@ -227,11 +227,21 @@ void scan_async_work(struct work_struct *work)
|
||||
/*
|
||||
* Now that the ASL is updated, complete the removal of any
|
||||
* removed qsets.
|
||||
*
|
||||
* If the qset was to be reset, do so and reinsert it into the
|
||||
* ASL if it has pending transfers.
|
||||
*/
|
||||
spin_lock_irq(&whc->lock);
|
||||
|
||||
list_for_each_entry_safe(qset, t, &whc->async_removed_list, list_node) {
|
||||
qset_remove_complete(whc, qset);
|
||||
if (qset->reset) {
|
||||
qset_reset(whc, qset);
|
||||
if (!list_empty(&qset->stds)) {
|
||||
asl_qset_insert_begin(whc, qset);
|
||||
queue_work(whc->workqueue, &whc->async_work);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irq(&whc->lock);
|
||||
@@ -267,7 +277,7 @@ int asl_urb_enqueue(struct whc *whc, struct urb *urb, gfp_t mem_flags)
|
||||
else
|
||||
err = qset_add_urb(whc, qset, urb, GFP_ATOMIC);
|
||||
if (!err) {
|
||||
if (!qset->in_sw_list)
|
||||
if (!qset->in_sw_list && !qset->remove)
|
||||
asl_qset_insert_begin(whc, qset);
|
||||
} else
|
||||
usb_hcd_unlink_urb_from_ep(&whc->wusbhc.usb_hcd, urb);
|
||||
|
@@ -192,19 +192,23 @@ static void whc_endpoint_reset(struct usb_hcd *usb_hcd,
|
||||
struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd);
|
||||
struct whc *whc = wusbhc_to_whc(wusbhc);
|
||||
struct whc_qset *qset;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&whc->lock, flags);
|
||||
|
||||
qset = ep->hcpriv;
|
||||
if (qset) {
|
||||
qset->remove = 1;
|
||||
qset->reset = 1;
|
||||
|
||||
if (usb_endpoint_xfer_bulk(&ep->desc)
|
||||
|| usb_endpoint_xfer_control(&ep->desc))
|
||||
queue_work(whc->workqueue, &whc->async_work);
|
||||
else
|
||||
queue_work(whc->workqueue, &whc->periodic_work);
|
||||
|
||||
qset_reset(whc, qset);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&whc->lock, flags);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -255,11 +255,21 @@ void scan_periodic_work(struct work_struct *work)
|
||||
/*
|
||||
* Now that the PZL is updated, complete the removal of any
|
||||
* removed qsets.
|
||||
*
|
||||
* If the qset was to be reset, do so and reinsert it into the
|
||||
* PZL if it has pending transfers.
|
||||
*/
|
||||
spin_lock_irq(&whc->lock);
|
||||
|
||||
list_for_each_entry_safe(qset, t, &whc->periodic_removed_list, list_node) {
|
||||
qset_remove_complete(whc, qset);
|
||||
if (qset->reset) {
|
||||
qset_reset(whc, qset);
|
||||
if (!list_empty(&qset->stds)) {
|
||||
qset_insert_in_sw_list(whc, qset);
|
||||
queue_work(whc->workqueue, &whc->periodic_work);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irq(&whc->lock);
|
||||
@@ -295,7 +305,7 @@ int pzl_urb_enqueue(struct whc *whc, struct urb *urb, gfp_t mem_flags)
|
||||
else
|
||||
err = qset_add_urb(whc, qset, urb, GFP_ATOMIC);
|
||||
if (!err) {
|
||||
if (!qset->in_sw_list)
|
||||
if (!qset->in_sw_list && !qset->remove)
|
||||
qset_insert_in_sw_list(whc, qset);
|
||||
} else
|
||||
usb_hcd_unlink_urb_from_ep(&whc->wusbhc.usb_hcd, urb);
|
||||
|
@@ -103,7 +103,6 @@ static void qset_fill_qh(struct whc_qset *qset, struct urb *urb)
|
||||
void qset_clear(struct whc *whc, struct whc_qset *qset)
|
||||
{
|
||||
qset->td_start = qset->td_end = qset->ntds = 0;
|
||||
qset->remove = 0;
|
||||
|
||||
qset->qh.link = cpu_to_le32(QH_LINK_NTDS(8) | QH_LINK_T);
|
||||
qset->qh.status = qset->qh.status & QH_STATUS_SEQ_MASK;
|
||||
@@ -125,7 +124,7 @@ void qset_clear(struct whc *whc, struct whc_qset *qset)
|
||||
*/
|
||||
void qset_reset(struct whc *whc, struct whc_qset *qset)
|
||||
{
|
||||
wait_for_completion(&qset->remove_complete);
|
||||
qset->reset = 0;
|
||||
|
||||
qset->qh.status &= ~QH_STATUS_SEQ_MASK;
|
||||
qset->qh.cur_window = cpu_to_le32((1 << qset->max_burst) - 1);
|
||||
@@ -156,6 +155,7 @@ struct whc_qset *get_qset(struct whc *whc, struct urb *urb,
|
||||
|
||||
void qset_remove_complete(struct whc *whc, struct whc_qset *qset)
|
||||
{
|
||||
qset->remove = 0;
|
||||
list_del_init(&qset->list_node);
|
||||
complete(&qset->remove_complete);
|
||||
}
|
||||
|
@@ -264,6 +264,7 @@ struct whc_qset {
|
||||
unsigned in_sw_list:1;
|
||||
unsigned in_hw_list:1;
|
||||
unsigned remove:1;
|
||||
unsigned reset:1;
|
||||
struct urb *pause_after_urb;
|
||||
struct completion remove_complete;
|
||||
int max_burst;
|
||||
|
@@ -413,7 +413,8 @@ void xhci_dbg_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx)
|
||||
int i;
|
||||
|
||||
struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx);
|
||||
dma_addr_t dma = ctx->dma + ((unsigned long)slot_ctx - (unsigned long)ctx);
|
||||
dma_addr_t dma = ctx->dma +
|
||||
((unsigned long)slot_ctx - (unsigned long)ctx->bytes);
|
||||
int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params);
|
||||
|
||||
xhci_dbg(xhci, "Slot Context:\n");
|
||||
@@ -459,7 +460,7 @@ void xhci_dbg_ep_ctx(struct xhci_hcd *xhci,
|
||||
for (i = 0; i < last_ep_ctx; ++i) {
|
||||
struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, ctx, i);
|
||||
dma_addr_t dma = ctx->dma +
|
||||
((unsigned long)ep_ctx - (unsigned long)ctx);
|
||||
((unsigned long)ep_ctx - (unsigned long)ctx->bytes);
|
||||
|
||||
xhci_dbg(xhci, "Endpoint %02d Context:\n", i);
|
||||
xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info\n",
|
||||
|
@@ -22,12 +22,18 @@
|
||||
|
||||
#include <linux/irq.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
||||
#include "xhci.h"
|
||||
|
||||
#define DRIVER_AUTHOR "Sarah Sharp"
|
||||
#define DRIVER_DESC "'eXtensible' Host Controller (xHC) Driver"
|
||||
|
||||
/* Some 0.95 hardware can't handle the chain bit on a Link TRB being cleared */
|
||||
static int link_quirk;
|
||||
module_param(link_quirk, int, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB");
|
||||
|
||||
/* TODO: copied from ehci-hcd.c - can this be refactored? */
|
||||
/*
|
||||
* handshake - spin reading hc until handshake completes or fails
|
||||
@@ -214,6 +220,12 @@ int xhci_init(struct usb_hcd *hcd)
|
||||
|
||||
xhci_dbg(xhci, "xhci_init\n");
|
||||
spin_lock_init(&xhci->lock);
|
||||
if (link_quirk) {
|
||||
xhci_dbg(xhci, "QUIRK: Not clearing Link TRB chain bits.\n");
|
||||
xhci->quirks |= XHCI_LINK_TRB_QUIRK;
|
||||
} else {
|
||||
xhci_dbg(xhci, "xHCI doesn't need link TRB QUIRK\n");
|
||||
}
|
||||
retval = xhci_mem_init(xhci, GFP_KERNEL);
|
||||
xhci_dbg(xhci, "Finished xhci_init\n");
|
||||
|
||||
@@ -339,13 +351,14 @@ void xhci_event_ring_work(unsigned long arg)
|
||||
xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring);
|
||||
xhci_dbg_cmd_ptrs(xhci);
|
||||
for (i = 0; i < MAX_HC_SLOTS; ++i) {
|
||||
if (xhci->devs[i]) {
|
||||
for (j = 0; j < 31; ++j) {
|
||||
if (xhci->devs[i]->ep_rings[j]) {
|
||||
xhci_dbg(xhci, "Dev %d endpoint ring %d:\n", i, j);
|
||||
xhci_debug_segment(xhci, xhci->devs[i]->ep_rings[j]->deq_seg);
|
||||
}
|
||||
}
|
||||
if (!xhci->devs[i])
|
||||
continue;
|
||||
for (j = 0; j < 31; ++j) {
|
||||
struct xhci_ring *ring = xhci->devs[i]->eps[j].ring;
|
||||
if (!ring)
|
||||
continue;
|
||||
xhci_dbg(xhci, "Dev %d endpoint ring %d:\n", i, j);
|
||||
xhci_debug_segment(xhci, ring->deq_seg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -555,13 +568,22 @@ unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc)
|
||||
return 1 << (xhci_get_endpoint_index(desc) + 1);
|
||||
}
|
||||
|
||||
/* Find the flag for this endpoint (for use in the control context). Use the
|
||||
* endpoint index to create a bitmask. The slot context is bit 0, endpoint 0 is
|
||||
* bit 1, etc.
|
||||
*/
|
||||
unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index)
|
||||
{
|
||||
return 1 << (ep_index + 1);
|
||||
}
|
||||
|
||||
/* Compute the last valid endpoint context index. Basically, this is the
|
||||
* endpoint index plus one. For slot contexts with more than valid endpoint,
|
||||
* we find the most significant bit set in the added contexts flags.
|
||||
* e.g. ep 1 IN (with epnum 0x81) => added_ctxs = 0b1000
|
||||
* fls(0b1000) = 4, but the endpoint context index is 3, so subtract one.
|
||||
*/
|
||||
static inline unsigned int xhci_last_valid_endpoint(u32 added_ctxs)
|
||||
unsigned int xhci_last_valid_endpoint(u32 added_ctxs)
|
||||
{
|
||||
return fls(added_ctxs) - 1;
|
||||
}
|
||||
@@ -589,6 +611,71 @@ int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int xhci_configure_endpoint(struct xhci_hcd *xhci,
|
||||
struct usb_device *udev, struct xhci_command *command,
|
||||
bool ctx_change, bool must_succeed);
|
||||
|
||||
/*
|
||||
* Full speed devices may have a max packet size greater than 8 bytes, but the
|
||||
* USB core doesn't know that until it reads the first 8 bytes of the
|
||||
* descriptor. If the usb_device's max packet size changes after that point,
|
||||
* we need to issue an evaluate context command and wait on it.
|
||||
*/
|
||||
static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
|
||||
unsigned int ep_index, struct urb *urb)
|
||||
{
|
||||
struct xhci_container_ctx *in_ctx;
|
||||
struct xhci_container_ctx *out_ctx;
|
||||
struct xhci_input_control_ctx *ctrl_ctx;
|
||||
struct xhci_ep_ctx *ep_ctx;
|
||||
int max_packet_size;
|
||||
int hw_max_packet_size;
|
||||
int ret = 0;
|
||||
|
||||
out_ctx = xhci->devs[slot_id]->out_ctx;
|
||||
ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
|
||||
hw_max_packet_size = MAX_PACKET_DECODED(ep_ctx->ep_info2);
|
||||
max_packet_size = urb->dev->ep0.desc.wMaxPacketSize;
|
||||
if (hw_max_packet_size != max_packet_size) {
|
||||
xhci_dbg(xhci, "Max Packet Size for ep 0 changed.\n");
|
||||
xhci_dbg(xhci, "Max packet size in usb_device = %d\n",
|
||||
max_packet_size);
|
||||
xhci_dbg(xhci, "Max packet size in xHCI HW = %d\n",
|
||||
hw_max_packet_size);
|
||||
xhci_dbg(xhci, "Issuing evaluate context command.\n");
|
||||
|
||||
/* Set up the modified control endpoint 0 */
|
||||
xhci_endpoint_copy(xhci, xhci->devs[slot_id]->in_ctx,
|
||||
xhci->devs[slot_id]->out_ctx, ep_index);
|
||||
in_ctx = xhci->devs[slot_id]->in_ctx;
|
||||
ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index);
|
||||
ep_ctx->ep_info2 &= ~MAX_PACKET_MASK;
|
||||
ep_ctx->ep_info2 |= MAX_PACKET(max_packet_size);
|
||||
|
||||
/* Set up the input context flags for the command */
|
||||
/* FIXME: This won't work if a non-default control endpoint
|
||||
* changes max packet sizes.
|
||||
*/
|
||||
ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
|
||||
ctrl_ctx->add_flags = EP0_FLAG;
|
||||
ctrl_ctx->drop_flags = 0;
|
||||
|
||||
xhci_dbg(xhci, "Slot %d input context\n", slot_id);
|
||||
xhci_dbg_ctx(xhci, in_ctx, ep_index);
|
||||
xhci_dbg(xhci, "Slot %d output context\n", slot_id);
|
||||
xhci_dbg_ctx(xhci, out_ctx, ep_index);
|
||||
|
||||
ret = xhci_configure_endpoint(xhci, urb->dev, NULL,
|
||||
true, false);
|
||||
|
||||
/* Clean up the input context for later use by bandwidth
|
||||
* functions.
|
||||
*/
|
||||
ctrl_ctx->add_flags = SLOT_FLAG;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* non-error returns are a promise to giveback() the urb later
|
||||
* we drop ownership so next owner (or urb unlink) can get it
|
||||
@@ -600,13 +687,13 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
|
||||
int ret = 0;
|
||||
unsigned int slot_id, ep_index;
|
||||
|
||||
|
||||
if (!urb || xhci_check_args(hcd, urb->dev, urb->ep, true, __func__) <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
slot_id = urb->dev->slot_id;
|
||||
ep_index = xhci_get_endpoint_index(&urb->ep->desc);
|
||||
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
if (!xhci->devs || !xhci->devs[slot_id]) {
|
||||
if (!in_interrupt())
|
||||
dev_warn(&urb->dev->dev, "WARN: urb submitted for dev with no Slot ID\n");
|
||||
@@ -619,19 +706,38 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
|
||||
ret = -ESHUTDOWN;
|
||||
goto exit;
|
||||
}
|
||||
if (usb_endpoint_xfer_control(&urb->ep->desc))
|
||||
if (usb_endpoint_xfer_control(&urb->ep->desc)) {
|
||||
/* Check to see if the max packet size for the default control
|
||||
* endpoint changed during FS device enumeration
|
||||
*/
|
||||
if (urb->dev->speed == USB_SPEED_FULL) {
|
||||
ret = xhci_check_maxpacket(xhci, slot_id,
|
||||
ep_index, urb);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* We have a spinlock and interrupts disabled, so we must pass
|
||||
* atomic context to this function, which may allocate memory.
|
||||
*/
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
ret = xhci_queue_ctrl_tx(xhci, GFP_ATOMIC, urb,
|
||||
slot_id, ep_index);
|
||||
else if (usb_endpoint_xfer_bulk(&urb->ep->desc))
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
} else if (usb_endpoint_xfer_bulk(&urb->ep->desc)) {
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb,
|
||||
slot_id, ep_index);
|
||||
else
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
} else if (usb_endpoint_xfer_int(&urb->ep->desc)) {
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
ret = xhci_queue_intr_tx(xhci, GFP_ATOMIC, urb,
|
||||
slot_id, ep_index);
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
exit:
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -674,6 +780,7 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
|
||||
struct xhci_td *td;
|
||||
unsigned int ep_index;
|
||||
struct xhci_ring *ep_ring;
|
||||
struct xhci_virt_ep *ep;
|
||||
|
||||
xhci = hcd_to_xhci(hcd);
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
@@ -686,17 +793,18 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
|
||||
xhci_dbg(xhci, "Event ring:\n");
|
||||
xhci_debug_ring(xhci, xhci->event_ring);
|
||||
ep_index = xhci_get_endpoint_index(&urb->ep->desc);
|
||||
ep_ring = xhci->devs[urb->dev->slot_id]->ep_rings[ep_index];
|
||||
ep = &xhci->devs[urb->dev->slot_id]->eps[ep_index];
|
||||
ep_ring = ep->ring;
|
||||
xhci_dbg(xhci, "Endpoint ring:\n");
|
||||
xhci_debug_ring(xhci, ep_ring);
|
||||
td = (struct xhci_td *) urb->hcpriv;
|
||||
|
||||
ep_ring->cancels_pending++;
|
||||
list_add_tail(&td->cancelled_td_list, &ep_ring->cancelled_td_list);
|
||||
ep->cancels_pending++;
|
||||
list_add_tail(&td->cancelled_td_list, &ep->cancelled_td_list);
|
||||
/* Queue a stop endpoint command, but only if this is
|
||||
* the first cancellation to be handled.
|
||||
*/
|
||||
if (ep_ring->cancels_pending == 1) {
|
||||
if (ep->cancels_pending == 1) {
|
||||
xhci_queue_stop_endpoint(xhci, urb->dev->slot_id, ep_index);
|
||||
xhci_ring_cmd_db(xhci);
|
||||
}
|
||||
@@ -930,6 +1038,141 @@ static void xhci_zero_in_ctx(struct xhci_hcd *xhci, struct xhci_virt_device *vir
|
||||
}
|
||||
}
|
||||
|
||||
static int xhci_configure_endpoint_result(struct xhci_hcd *xhci,
|
||||
struct usb_device *udev, int *cmd_status)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (*cmd_status) {
|
||||
case COMP_ENOMEM:
|
||||
dev_warn(&udev->dev, "Not enough host controller resources "
|
||||
"for new device state.\n");
|
||||
ret = -ENOMEM;
|
||||
/* FIXME: can we allocate more resources for the HC? */
|
||||
break;
|
||||
case COMP_BW_ERR:
|
||||
dev_warn(&udev->dev, "Not enough bandwidth "
|
||||
"for new device state.\n");
|
||||
ret = -ENOSPC;
|
||||
/* FIXME: can we go back to the old state? */
|
||||
break;
|
||||
case COMP_TRB_ERR:
|
||||
/* the HCD set up something wrong */
|
||||
dev_warn(&udev->dev, "ERROR: Endpoint drop flag = 0, "
|
||||
"add flag = 1, "
|
||||
"and endpoint is not disabled.\n");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
case COMP_SUCCESS:
|
||||
dev_dbg(&udev->dev, "Successful Endpoint Configure command\n");
|
||||
ret = 0;
|
||||
break;
|
||||
default:
|
||||
xhci_err(xhci, "ERROR: unexpected command completion "
|
||||
"code 0x%x.\n", *cmd_status);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int xhci_evaluate_context_result(struct xhci_hcd *xhci,
|
||||
struct usb_device *udev, int *cmd_status)
|
||||
{
|
||||
int ret;
|
||||
struct xhci_virt_device *virt_dev = xhci->devs[udev->slot_id];
|
||||
|
||||
switch (*cmd_status) {
|
||||
case COMP_EINVAL:
|
||||
dev_warn(&udev->dev, "WARN: xHCI driver setup invalid evaluate "
|
||||
"context command.\n");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
case COMP_EBADSLT:
|
||||
dev_warn(&udev->dev, "WARN: slot not enabled for"
|
||||
"evaluate context command.\n");
|
||||
case COMP_CTX_STATE:
|
||||
dev_warn(&udev->dev, "WARN: invalid context state for "
|
||||
"evaluate context command.\n");
|
||||
xhci_dbg_ctx(xhci, virt_dev->out_ctx, 1);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
case COMP_SUCCESS:
|
||||
dev_dbg(&udev->dev, "Successful evaluate context command\n");
|
||||
ret = 0;
|
||||
break;
|
||||
default:
|
||||
xhci_err(xhci, "ERROR: unexpected command completion "
|
||||
"code 0x%x.\n", *cmd_status);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Issue a configure endpoint command or evaluate context command
|
||||
* and wait for it to finish.
|
||||
*/
|
||||
static int xhci_configure_endpoint(struct xhci_hcd *xhci,
|
||||
struct usb_device *udev,
|
||||
struct xhci_command *command,
|
||||
bool ctx_change, bool must_succeed)
|
||||
{
|
||||
int ret;
|
||||
int timeleft;
|
||||
unsigned long flags;
|
||||
struct xhci_container_ctx *in_ctx;
|
||||
struct completion *cmd_completion;
|
||||
int *cmd_status;
|
||||
struct xhci_virt_device *virt_dev;
|
||||
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
virt_dev = xhci->devs[udev->slot_id];
|
||||
if (command) {
|
||||
in_ctx = command->in_ctx;
|
||||
cmd_completion = command->completion;
|
||||
cmd_status = &command->status;
|
||||
command->command_trb = xhci->cmd_ring->enqueue;
|
||||
list_add_tail(&command->cmd_list, &virt_dev->cmd_list);
|
||||
} else {
|
||||
in_ctx = virt_dev->in_ctx;
|
||||
cmd_completion = &virt_dev->cmd_completion;
|
||||
cmd_status = &virt_dev->cmd_status;
|
||||
}
|
||||
|
||||
if (!ctx_change)
|
||||
ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma,
|
||||
udev->slot_id, must_succeed);
|
||||
else
|
||||
ret = xhci_queue_evaluate_context(xhci, in_ctx->dma,
|
||||
udev->slot_id);
|
||||
if (ret < 0) {
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
xhci_dbg(xhci, "FIXME allocate a new ring segment\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
xhci_ring_cmd_db(xhci);
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
|
||||
/* Wait for the configure endpoint command to complete */
|
||||
timeleft = wait_for_completion_interruptible_timeout(
|
||||
cmd_completion,
|
||||
USB_CTRL_SET_TIMEOUT);
|
||||
if (timeleft <= 0) {
|
||||
xhci_warn(xhci, "%s while waiting for %s command\n",
|
||||
timeleft == 0 ? "Timeout" : "Signal",
|
||||
ctx_change == 0 ?
|
||||
"configure endpoint" :
|
||||
"evaluate context");
|
||||
/* FIXME cancel the configure endpoint command */
|
||||
return -ETIME;
|
||||
}
|
||||
|
||||
if (!ctx_change)
|
||||
return xhci_configure_endpoint_result(xhci, udev, cmd_status);
|
||||
return xhci_evaluate_context_result(xhci, udev, cmd_status);
|
||||
}
|
||||
|
||||
/* Called after one or more calls to xhci_add_endpoint() or
|
||||
* xhci_drop_endpoint(). If this call fails, the USB core is expected
|
||||
* to call xhci_reset_bandwidth().
|
||||
@@ -944,8 +1187,6 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
|
||||
{
|
||||
int i;
|
||||
int ret = 0;
|
||||
int timeleft;
|
||||
unsigned long flags;
|
||||
struct xhci_hcd *xhci;
|
||||
struct xhci_virt_device *virt_dev;
|
||||
struct xhci_input_control_ctx *ctrl_ctx;
|
||||
@@ -975,56 +1216,8 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
|
||||
xhci_dbg_ctx(xhci, virt_dev->in_ctx,
|
||||
LAST_CTX_TO_EP_NUM(slot_ctx->dev_info));
|
||||
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
ret = xhci_queue_configure_endpoint(xhci, virt_dev->in_ctx->dma,
|
||||
udev->slot_id);
|
||||
if (ret < 0) {
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
xhci_dbg(xhci, "FIXME allocate a new ring segment\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
xhci_ring_cmd_db(xhci);
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
|
||||
/* Wait for the configure endpoint command to complete */
|
||||
timeleft = wait_for_completion_interruptible_timeout(
|
||||
&virt_dev->cmd_completion,
|
||||
USB_CTRL_SET_TIMEOUT);
|
||||
if (timeleft <= 0) {
|
||||
xhci_warn(xhci, "%s while waiting for configure endpoint command\n",
|
||||
timeleft == 0 ? "Timeout" : "Signal");
|
||||
/* FIXME cancel the configure endpoint command */
|
||||
return -ETIME;
|
||||
}
|
||||
|
||||
switch (virt_dev->cmd_status) {
|
||||
case COMP_ENOMEM:
|
||||
dev_warn(&udev->dev, "Not enough host controller resources "
|
||||
"for new device state.\n");
|
||||
ret = -ENOMEM;
|
||||
/* FIXME: can we allocate more resources for the HC? */
|
||||
break;
|
||||
case COMP_BW_ERR:
|
||||
dev_warn(&udev->dev, "Not enough bandwidth "
|
||||
"for new device state.\n");
|
||||
ret = -ENOSPC;
|
||||
/* FIXME: can we go back to the old state? */
|
||||
break;
|
||||
case COMP_TRB_ERR:
|
||||
/* the HCD set up something wrong */
|
||||
dev_warn(&udev->dev, "ERROR: Endpoint drop flag = 0, add flag = 1, "
|
||||
"and endpoint is not disabled.\n");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
case COMP_SUCCESS:
|
||||
dev_dbg(&udev->dev, "Successful Endpoint Configure command\n");
|
||||
break;
|
||||
default:
|
||||
xhci_err(xhci, "ERROR: unexpected command completion "
|
||||
"code 0x%x.\n", virt_dev->cmd_status);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
ret = xhci_configure_endpoint(xhci, udev, NULL,
|
||||
false, false);
|
||||
if (ret) {
|
||||
/* Callee should call reset_bandwidth() */
|
||||
return ret;
|
||||
@@ -1037,10 +1230,10 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
|
||||
xhci_zero_in_ctx(xhci, virt_dev);
|
||||
/* Free any old rings */
|
||||
for (i = 1; i < 31; ++i) {
|
||||
if (virt_dev->new_ep_rings[i]) {
|
||||
xhci_ring_free(xhci, virt_dev->ep_rings[i]);
|
||||
virt_dev->ep_rings[i] = virt_dev->new_ep_rings[i];
|
||||
virt_dev->new_ep_rings[i] = NULL;
|
||||
if (virt_dev->eps[i].new_ring) {
|
||||
xhci_ring_free(xhci, virt_dev->eps[i].ring);
|
||||
virt_dev->eps[i].ring = virt_dev->eps[i].new_ring;
|
||||
virt_dev->eps[i].new_ring = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1067,14 +1260,93 @@ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
|
||||
virt_dev = xhci->devs[udev->slot_id];
|
||||
/* Free any rings allocated for added endpoints */
|
||||
for (i = 0; i < 31; ++i) {
|
||||
if (virt_dev->new_ep_rings[i]) {
|
||||
xhci_ring_free(xhci, virt_dev->new_ep_rings[i]);
|
||||
virt_dev->new_ep_rings[i] = NULL;
|
||||
if (virt_dev->eps[i].new_ring) {
|
||||
xhci_ring_free(xhci, virt_dev->eps[i].new_ring);
|
||||
virt_dev->eps[i].new_ring = NULL;
|
||||
}
|
||||
}
|
||||
xhci_zero_in_ctx(xhci, virt_dev);
|
||||
}
|
||||
|
||||
static void xhci_setup_input_ctx_for_config_ep(struct xhci_hcd *xhci,
|
||||
struct xhci_container_ctx *in_ctx,
|
||||
struct xhci_container_ctx *out_ctx,
|
||||
u32 add_flags, u32 drop_flags)
|
||||
{
|
||||
struct xhci_input_control_ctx *ctrl_ctx;
|
||||
ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
|
||||
ctrl_ctx->add_flags = add_flags;
|
||||
ctrl_ctx->drop_flags = drop_flags;
|
||||
xhci_slot_copy(xhci, in_ctx, out_ctx);
|
||||
ctrl_ctx->add_flags |= SLOT_FLAG;
|
||||
|
||||
xhci_dbg(xhci, "Input Context:\n");
|
||||
xhci_dbg_ctx(xhci, in_ctx, xhci_last_valid_endpoint(add_flags));
|
||||
}
|
||||
|
||||
void xhci_setup_input_ctx_for_quirk(struct xhci_hcd *xhci,
|
||||
unsigned int slot_id, unsigned int ep_index,
|
||||
struct xhci_dequeue_state *deq_state)
|
||||
{
|
||||
struct xhci_container_ctx *in_ctx;
|
||||
struct xhci_ep_ctx *ep_ctx;
|
||||
u32 added_ctxs;
|
||||
dma_addr_t addr;
|
||||
|
||||
xhci_endpoint_copy(xhci, xhci->devs[slot_id]->in_ctx,
|
||||
xhci->devs[slot_id]->out_ctx, ep_index);
|
||||
in_ctx = xhci->devs[slot_id]->in_ctx;
|
||||
ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index);
|
||||
addr = xhci_trb_virt_to_dma(deq_state->new_deq_seg,
|
||||
deq_state->new_deq_ptr);
|
||||
if (addr == 0) {
|
||||
xhci_warn(xhci, "WARN Cannot submit config ep after "
|
||||
"reset ep command\n");
|
||||
xhci_warn(xhci, "WARN deq seg = %p, deq ptr = %p\n",
|
||||
deq_state->new_deq_seg,
|
||||
deq_state->new_deq_ptr);
|
||||
return;
|
||||
}
|
||||
ep_ctx->deq = addr | deq_state->new_cycle_state;
|
||||
|
||||
added_ctxs = xhci_get_endpoint_flag_from_index(ep_index);
|
||||
xhci_setup_input_ctx_for_config_ep(xhci, xhci->devs[slot_id]->in_ctx,
|
||||
xhci->devs[slot_id]->out_ctx, added_ctxs, added_ctxs);
|
||||
}
|
||||
|
||||
void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
|
||||
struct usb_device *udev, unsigned int ep_index)
|
||||
{
|
||||
struct xhci_dequeue_state deq_state;
|
||||
struct xhci_virt_ep *ep;
|
||||
|
||||
xhci_dbg(xhci, "Cleaning up stalled endpoint ring\n");
|
||||
ep = &xhci->devs[udev->slot_id]->eps[ep_index];
|
||||
/* We need to move the HW's dequeue pointer past this TD,
|
||||
* or it will attempt to resend it on the next doorbell ring.
|
||||
*/
|
||||
xhci_find_new_dequeue_state(xhci, udev->slot_id,
|
||||
ep_index, ep->stopped_td,
|
||||
&deq_state);
|
||||
|
||||
/* HW with the reset endpoint quirk will use the saved dequeue state to
|
||||
* issue a configure endpoint command later.
|
||||
*/
|
||||
if (!(xhci->quirks & XHCI_RESET_EP_QUIRK)) {
|
||||
xhci_dbg(xhci, "Queueing new dequeue state\n");
|
||||
xhci_queue_new_dequeue_state(xhci, udev->slot_id,
|
||||
ep_index, &deq_state);
|
||||
} else {
|
||||
/* Better hope no one uses the input context between now and the
|
||||
* reset endpoint completion!
|
||||
*/
|
||||
xhci_dbg(xhci, "Setting up input context for "
|
||||
"configure endpoint command\n");
|
||||
xhci_setup_input_ctx_for_quirk(xhci, udev->slot_id,
|
||||
ep_index, &deq_state);
|
||||
}
|
||||
}
|
||||
|
||||
/* Deal with stalled endpoints. The core should have sent the control message
|
||||
* to clear the halt condition. However, we need to make the xHCI hardware
|
||||
* reset its sequence number, since a device will expect a sequence number of
|
||||
@@ -1089,8 +1361,7 @@ void xhci_endpoint_reset(struct usb_hcd *hcd,
|
||||
unsigned int ep_index;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
struct xhci_dequeue_state deq_state;
|
||||
struct xhci_ring *ep_ring;
|
||||
struct xhci_virt_ep *virt_ep;
|
||||
|
||||
xhci = hcd_to_xhci(hcd);
|
||||
udev = (struct usb_device *) ep->hcpriv;
|
||||
@@ -1100,12 +1371,16 @@ void xhci_endpoint_reset(struct usb_hcd *hcd,
|
||||
if (!ep->hcpriv)
|
||||
return;
|
||||
ep_index = xhci_get_endpoint_index(&ep->desc);
|
||||
ep_ring = xhci->devs[udev->slot_id]->ep_rings[ep_index];
|
||||
if (!ep_ring->stopped_td) {
|
||||
virt_ep = &xhci->devs[udev->slot_id]->eps[ep_index];
|
||||
if (!virt_ep->stopped_td) {
|
||||
xhci_dbg(xhci, "Endpoint 0x%x not halted, refusing to reset.\n",
|
||||
ep->desc.bEndpointAddress);
|
||||
return;
|
||||
}
|
||||
if (usb_endpoint_xfer_control(&ep->desc)) {
|
||||
xhci_dbg(xhci, "Control endpoint stall already handled.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
xhci_dbg(xhci, "Queueing reset endpoint command\n");
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
@@ -1116,17 +1391,8 @@ void xhci_endpoint_reset(struct usb_hcd *hcd,
|
||||
* command. Better hope that last command worked!
|
||||
*/
|
||||
if (!ret) {
|
||||
xhci_dbg(xhci, "Cleaning up stalled endpoint ring\n");
|
||||
/* We need to move the HW's dequeue pointer past this TD,
|
||||
* or it will attempt to resend it on the next doorbell ring.
|
||||
*/
|
||||
xhci_find_new_dequeue_state(xhci, udev->slot_id,
|
||||
ep_index, ep_ring->stopped_td, &deq_state);
|
||||
xhci_dbg(xhci, "Queueing new dequeue state\n");
|
||||
xhci_queue_new_dequeue_state(xhci, ep_ring,
|
||||
udev->slot_id,
|
||||
ep_index, &deq_state);
|
||||
kfree(ep_ring->stopped_td);
|
||||
xhci_cleanup_stalled_ring(xhci, udev, ep_index);
|
||||
kfree(virt_ep->stopped_td);
|
||||
xhci_ring_cmd_db(xhci);
|
||||
}
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
@@ -1328,6 +1594,88 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Once a hub descriptor is fetched for a device, we need to update the xHC's
|
||||
* internal data structures for the device.
|
||||
*/
|
||||
int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
|
||||
struct usb_tt *tt, gfp_t mem_flags)
|
||||
{
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
struct xhci_virt_device *vdev;
|
||||
struct xhci_command *config_cmd;
|
||||
struct xhci_input_control_ctx *ctrl_ctx;
|
||||
struct xhci_slot_ctx *slot_ctx;
|
||||
unsigned long flags;
|
||||
unsigned think_time;
|
||||
int ret;
|
||||
|
||||
/* Ignore root hubs */
|
||||
if (!hdev->parent)
|
||||
return 0;
|
||||
|
||||
vdev = xhci->devs[hdev->slot_id];
|
||||
if (!vdev) {
|
||||
xhci_warn(xhci, "Cannot update hub desc for unknown device.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
config_cmd = xhci_alloc_command(xhci, true, mem_flags);
|
||||
if (!config_cmd) {
|
||||
xhci_dbg(xhci, "Could not allocate xHCI command structure.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
xhci_slot_copy(xhci, config_cmd->in_ctx, vdev->out_ctx);
|
||||
ctrl_ctx = xhci_get_input_control_ctx(xhci, config_cmd->in_ctx);
|
||||
ctrl_ctx->add_flags |= SLOT_FLAG;
|
||||
slot_ctx = xhci_get_slot_ctx(xhci, config_cmd->in_ctx);
|
||||
slot_ctx->dev_info |= DEV_HUB;
|
||||
if (tt->multi)
|
||||
slot_ctx->dev_info |= DEV_MTT;
|
||||
if (xhci->hci_version > 0x95) {
|
||||
xhci_dbg(xhci, "xHCI version %x needs hub "
|
||||
"TT think time and number of ports\n",
|
||||
(unsigned int) xhci->hci_version);
|
||||
slot_ctx->dev_info2 |= XHCI_MAX_PORTS(hdev->maxchild);
|
||||
/* Set TT think time - convert from ns to FS bit times.
|
||||
* 0 = 8 FS bit times, 1 = 16 FS bit times,
|
||||
* 2 = 24 FS bit times, 3 = 32 FS bit times.
|
||||
*/
|
||||
think_time = tt->think_time;
|
||||
if (think_time != 0)
|
||||
think_time = (think_time / 666) - 1;
|
||||
slot_ctx->tt_info |= TT_THINK_TIME(think_time);
|
||||
} else {
|
||||
xhci_dbg(xhci, "xHCI version %x doesn't need hub "
|
||||
"TT think time or number of ports\n",
|
||||
(unsigned int) xhci->hci_version);
|
||||
}
|
||||
slot_ctx->dev_state = 0;
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
|
||||
xhci_dbg(xhci, "Set up %s for hub device.\n",
|
||||
(xhci->hci_version > 0x95) ?
|
||||
"configure endpoint" : "evaluate context");
|
||||
xhci_dbg(xhci, "Slot %u Input Context:\n", hdev->slot_id);
|
||||
xhci_dbg_ctx(xhci, config_cmd->in_ctx, 0);
|
||||
|
||||
/* Issue and wait for the configure endpoint or
|
||||
* evaluate context command.
|
||||
*/
|
||||
if (xhci->hci_version > 0x95)
|
||||
ret = xhci_configure_endpoint(xhci, hdev, config_cmd,
|
||||
false, false);
|
||||
else
|
||||
ret = xhci_configure_endpoint(xhci, hdev, config_cmd,
|
||||
true, false);
|
||||
|
||||
xhci_dbg(xhci, "Slot %u Output Context:\n", hdev->slot_id);
|
||||
xhci_dbg_ctx(xhci, vdev->out_ctx, 0);
|
||||
|
||||
xhci_free_command(xhci, config_cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int xhci_get_frame(struct usb_hcd *hcd)
|
||||
{
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
|
@@ -94,6 +94,9 @@ static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev,
|
||||
val = prev->trbs[TRBS_PER_SEGMENT-1].link.control;
|
||||
val &= ~TRB_TYPE_BITMASK;
|
||||
val |= TRB_TYPE(TRB_LINK);
|
||||
/* Always set the chain bit with 0.95 hardware */
|
||||
if (xhci_link_trb_quirk(xhci))
|
||||
val |= TRB_CHAIN;
|
||||
prev->trbs[TRBS_PER_SEGMENT-1].link.control = val;
|
||||
}
|
||||
xhci_dbg(xhci, "Linking segment 0x%llx to segment 0x%llx (DMA)\n",
|
||||
@@ -141,7 +144,6 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,
|
||||
return 0;
|
||||
|
||||
INIT_LIST_HEAD(&ring->td_list);
|
||||
INIT_LIST_HEAD(&ring->cancelled_td_list);
|
||||
if (num_segs == 0)
|
||||
return ring;
|
||||
|
||||
@@ -262,8 +264,8 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
|
||||
return;
|
||||
|
||||
for (i = 0; i < 31; ++i)
|
||||
if (dev->ep_rings[i])
|
||||
xhci_ring_free(xhci, dev->ep_rings[i]);
|
||||
if (dev->eps[i].ring)
|
||||
xhci_ring_free(xhci, dev->eps[i].ring);
|
||||
|
||||
if (dev->in_ctx)
|
||||
xhci_free_container_ctx(xhci, dev->in_ctx);
|
||||
@@ -278,6 +280,7 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
|
||||
struct usb_device *udev, gfp_t flags)
|
||||
{
|
||||
struct xhci_virt_device *dev;
|
||||
int i;
|
||||
|
||||
/* Slot ID 0 is reserved */
|
||||
if (slot_id == 0 || xhci->devs[slot_id]) {
|
||||
@@ -306,12 +309,17 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
|
||||
xhci_dbg(xhci, "Slot %d input ctx = 0x%llx (dma)\n", slot_id,
|
||||
(unsigned long long)dev->in_ctx->dma);
|
||||
|
||||
/* Initialize the cancellation list for each endpoint */
|
||||
for (i = 0; i < 31; i++)
|
||||
INIT_LIST_HEAD(&dev->eps[i].cancelled_td_list);
|
||||
|
||||
/* Allocate endpoint 0 ring */
|
||||
dev->ep_rings[0] = xhci_ring_alloc(xhci, 1, true, flags);
|
||||
if (!dev->ep_rings[0])
|
||||
dev->eps[0].ring = xhci_ring_alloc(xhci, 1, true, flags);
|
||||
if (!dev->eps[0].ring)
|
||||
goto fail;
|
||||
|
||||
init_completion(&dev->cmd_completion);
|
||||
INIT_LIST_HEAD(&dev->cmd_list);
|
||||
|
||||
/* Point to output device context in dcbaa. */
|
||||
xhci->dcbaa->dev_context_ptrs[slot_id] = dev->out_ctx->dma;
|
||||
@@ -352,9 +360,9 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
|
||||
/* 3) Only the control endpoint is valid - one endpoint context */
|
||||
slot_ctx->dev_info |= LAST_CTX(1);
|
||||
|
||||
slot_ctx->dev_info |= (u32) udev->route;
|
||||
switch (udev->speed) {
|
||||
case USB_SPEED_SUPER:
|
||||
slot_ctx->dev_info |= (u32) udev->route;
|
||||
slot_ctx->dev_info |= (u32) SLOT_SPEED_SS;
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
@@ -382,14 +390,12 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
|
||||
xhci_dbg(xhci, "Set root hub portnum to %d\n", top_dev->portnum);
|
||||
|
||||
/* Is this a LS/FS device under a HS hub? */
|
||||
/*
|
||||
* FIXME: I don't think this is right, where does the TT info for the
|
||||
* roothub or parent hub come from?
|
||||
*/
|
||||
if ((udev->speed == USB_SPEED_LOW || udev->speed == USB_SPEED_FULL) &&
|
||||
udev->tt) {
|
||||
slot_ctx->tt_info = udev->tt->hub->slot_id;
|
||||
slot_ctx->tt_info |= udev->ttport << 8;
|
||||
if (udev->tt->multi)
|
||||
slot_ctx->dev_info |= DEV_MTT;
|
||||
}
|
||||
xhci_dbg(xhci, "udev->tt = %p\n", udev->tt);
|
||||
xhci_dbg(xhci, "udev->ttport = 0x%x\n", udev->ttport);
|
||||
@@ -398,22 +404,35 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
|
||||
/* Step 5 */
|
||||
ep0_ctx->ep_info2 = EP_TYPE(CTRL_EP);
|
||||
/*
|
||||
* See section 4.3 bullet 6:
|
||||
* The default Max Packet size for ep0 is "8 bytes for a USB2
|
||||
* LS/FS/HS device or 512 bytes for a USB3 SS device"
|
||||
* XXX: Not sure about wireless USB devices.
|
||||
*/
|
||||
if (udev->speed == USB_SPEED_SUPER)
|
||||
switch (udev->speed) {
|
||||
case USB_SPEED_SUPER:
|
||||
ep0_ctx->ep_info2 |= MAX_PACKET(512);
|
||||
else
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
/* USB core guesses at a 64-byte max packet first for FS devices */
|
||||
case USB_SPEED_FULL:
|
||||
ep0_ctx->ep_info2 |= MAX_PACKET(64);
|
||||
break;
|
||||
case USB_SPEED_LOW:
|
||||
ep0_ctx->ep_info2 |= MAX_PACKET(8);
|
||||
break;
|
||||
case USB_SPEED_VARIABLE:
|
||||
xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n");
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
/* New speed? */
|
||||
BUG();
|
||||
}
|
||||
/* EP 0 can handle "burst" sizes of 1, so Max Burst Size field is 0 */
|
||||
ep0_ctx->ep_info2 |= MAX_BURST(0);
|
||||
ep0_ctx->ep_info2 |= ERROR_COUNT(3);
|
||||
|
||||
ep0_ctx->deq =
|
||||
dev->ep_rings[0]->first_seg->dma;
|
||||
ep0_ctx->deq |= dev->ep_rings[0]->cycle_state;
|
||||
dev->eps[0].ring->first_seg->dma;
|
||||
ep0_ctx->deq |= dev->eps[0].ring->cycle_state;
|
||||
|
||||
/* Steps 7 and 8 were done in xhci_alloc_virt_device() */
|
||||
|
||||
@@ -523,10 +542,11 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
|
||||
ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
|
||||
|
||||
/* Set up the endpoint ring */
|
||||
virt_dev->new_ep_rings[ep_index] = xhci_ring_alloc(xhci, 1, true, mem_flags);
|
||||
if (!virt_dev->new_ep_rings[ep_index])
|
||||
virt_dev->eps[ep_index].new_ring =
|
||||
xhci_ring_alloc(xhci, 1, true, mem_flags);
|
||||
if (!virt_dev->eps[ep_index].new_ring)
|
||||
return -ENOMEM;
|
||||
ep_ring = virt_dev->new_ep_rings[ep_index];
|
||||
ep_ring = virt_dev->eps[ep_index].new_ring;
|
||||
ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state;
|
||||
|
||||
ep_ctx->ep_info = xhci_get_endpoint_interval(udev, ep);
|
||||
@@ -598,6 +618,48 @@ void xhci_endpoint_zero(struct xhci_hcd *xhci,
|
||||
*/
|
||||
}
|
||||
|
||||
/* Copy output xhci_ep_ctx to the input xhci_ep_ctx copy.
|
||||
* Useful when you want to change one particular aspect of the endpoint and then
|
||||
* issue a configure endpoint command.
|
||||
*/
|
||||
void xhci_endpoint_copy(struct xhci_hcd *xhci,
|
||||
struct xhci_container_ctx *in_ctx,
|
||||
struct xhci_container_ctx *out_ctx,
|
||||
unsigned int ep_index)
|
||||
{
|
||||
struct xhci_ep_ctx *out_ep_ctx;
|
||||
struct xhci_ep_ctx *in_ep_ctx;
|
||||
|
||||
out_ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
|
||||
in_ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index);
|
||||
|
||||
in_ep_ctx->ep_info = out_ep_ctx->ep_info;
|
||||
in_ep_ctx->ep_info2 = out_ep_ctx->ep_info2;
|
||||
in_ep_ctx->deq = out_ep_ctx->deq;
|
||||
in_ep_ctx->tx_info = out_ep_ctx->tx_info;
|
||||
}
|
||||
|
||||
/* Copy output xhci_slot_ctx to the input xhci_slot_ctx.
|
||||
* Useful when you want to change one particular aspect of the endpoint and then
|
||||
* issue a configure endpoint command. Only the context entries field matters,
|
||||
* but we'll copy the whole thing anyway.
|
||||
*/
|
||||
void xhci_slot_copy(struct xhci_hcd *xhci,
|
||||
struct xhci_container_ctx *in_ctx,
|
||||
struct xhci_container_ctx *out_ctx)
|
||||
{
|
||||
struct xhci_slot_ctx *in_slot_ctx;
|
||||
struct xhci_slot_ctx *out_slot_ctx;
|
||||
|
||||
in_slot_ctx = xhci_get_slot_ctx(xhci, in_ctx);
|
||||
out_slot_ctx = xhci_get_slot_ctx(xhci, out_ctx);
|
||||
|
||||
in_slot_ctx->dev_info = out_slot_ctx->dev_info;
|
||||
in_slot_ctx->dev_info2 = out_slot_ctx->dev_info2;
|
||||
in_slot_ctx->tt_info = out_slot_ctx->tt_info;
|
||||
in_slot_ctx->dev_state = out_slot_ctx->dev_state;
|
||||
}
|
||||
|
||||
/* Set up the scratchpad buffer array and scratchpad buffers, if needed. */
|
||||
static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags)
|
||||
{
|
||||
@@ -695,6 +757,44 @@ static void scratchpad_free(struct xhci_hcd *xhci)
|
||||
xhci->scratchpad = NULL;
|
||||
}
|
||||
|
||||
struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci,
|
||||
bool allocate_completion, gfp_t mem_flags)
|
||||
{
|
||||
struct xhci_command *command;
|
||||
|
||||
command = kzalloc(sizeof(*command), mem_flags);
|
||||
if (!command)
|
||||
return NULL;
|
||||
|
||||
command->in_ctx =
|
||||
xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_INPUT, mem_flags);
|
||||
if (!command->in_ctx)
|
||||
return NULL;
|
||||
|
||||
if (allocate_completion) {
|
||||
command->completion =
|
||||
kzalloc(sizeof(struct completion), mem_flags);
|
||||
if (!command->completion) {
|
||||
xhci_free_container_ctx(xhci, command->in_ctx);
|
||||
return NULL;
|
||||
}
|
||||
init_completion(command->completion);
|
||||
}
|
||||
|
||||
command->status = 0;
|
||||
INIT_LIST_HEAD(&command->cmd_list);
|
||||
return command;
|
||||
}
|
||||
|
||||
void xhci_free_command(struct xhci_hcd *xhci,
|
||||
struct xhci_command *command)
|
||||
{
|
||||
xhci_free_container_ctx(xhci,
|
||||
command->in_ctx);
|
||||
kfree(command->completion);
|
||||
kfree(command);
|
||||
}
|
||||
|
||||
void xhci_mem_cleanup(struct xhci_hcd *xhci)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
|
||||
|
@@ -24,6 +24,10 @@
|
||||
|
||||
#include "xhci.h"
|
||||
|
||||
/* Device for a quirk */
|
||||
#define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73
|
||||
#define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000
|
||||
|
||||
static const char hcd_name[] = "xhci_hcd";
|
||||
|
||||
/* called after powerup, by probe or system-pm "wakeup" */
|
||||
@@ -59,9 +63,20 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
|
||||
xhci->hcs_params1 = xhci_readl(xhci, &xhci->cap_regs->hcs_params1);
|
||||
xhci->hcs_params2 = xhci_readl(xhci, &xhci->cap_regs->hcs_params2);
|
||||
xhci->hcs_params3 = xhci_readl(xhci, &xhci->cap_regs->hcs_params3);
|
||||
xhci->hcc_params = xhci_readl(xhci, &xhci->cap_regs->hc_capbase);
|
||||
xhci->hci_version = HC_VERSION(xhci->hcc_params);
|
||||
xhci->hcc_params = xhci_readl(xhci, &xhci->cap_regs->hcc_params);
|
||||
xhci_print_registers(xhci);
|
||||
|
||||
/* Look for vendor-specific quirks */
|
||||
if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC &&
|
||||
pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK &&
|
||||
pdev->revision == 0x0) {
|
||||
xhci->quirks |= XHCI_RESET_EP_QUIRK;
|
||||
xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure"
|
||||
" endpoint cmd after reset endpoint\n");
|
||||
}
|
||||
|
||||
/* Make sure the HC is halted. */
|
||||
retval = xhci_halt(xhci);
|
||||
if (retval)
|
||||
@@ -121,6 +136,7 @@ static const struct hc_driver xhci_pci_hc_driver = {
|
||||
.check_bandwidth = xhci_check_bandwidth,
|
||||
.reset_bandwidth = xhci_reset_bandwidth,
|
||||
.address_device = xhci_address_device,
|
||||
.update_hub_device = xhci_update_hub_device,
|
||||
|
||||
/*
|
||||
* scheduling support
|
||||
|
@@ -172,8 +172,9 @@ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
|
||||
* have their chain bit cleared (so that each Link TRB is a separate TD).
|
||||
*
|
||||
* Section 6.4.4.1 of the 0.95 spec says link TRBs cannot have the chain bit
|
||||
* set, but other sections talk about dealing with the chain bit set.
|
||||
* Assume section 6.4.4.1 is wrong, and the chain bit can be set in a Link TRB.
|
||||
* set, but other sections talk about dealing with the chain bit set. This was
|
||||
* fixed in the 0.96 specification errata, but we have to assume that all 0.95
|
||||
* xHCI hardware can't handle the chain bit being cleared on a link TRB.
|
||||
*/
|
||||
static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer)
|
||||
{
|
||||
@@ -191,8 +192,14 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
|
||||
while (last_trb(xhci, ring, ring->enq_seg, next)) {
|
||||
if (!consumer) {
|
||||
if (ring != xhci->event_ring) {
|
||||
next->link.control &= ~TRB_CHAIN;
|
||||
next->link.control |= chain;
|
||||
/* If we're not dealing with 0.95 hardware,
|
||||
* carry over the chain bit of the previous TRB
|
||||
* (which may mean the chain bit is cleared).
|
||||
*/
|
||||
if (!xhci_link_trb_quirk(xhci)) {
|
||||
next->link.control &= ~TRB_CHAIN;
|
||||
next->link.control |= chain;
|
||||
}
|
||||
/* Give this link TRB to the hardware */
|
||||
wmb();
|
||||
if (next->link.control & TRB_CYCLE)
|
||||
@@ -289,16 +296,18 @@ static void ring_ep_doorbell(struct xhci_hcd *xhci,
|
||||
unsigned int slot_id,
|
||||
unsigned int ep_index)
|
||||
{
|
||||
struct xhci_ring *ep_ring;
|
||||
struct xhci_virt_ep *ep;
|
||||
unsigned int ep_state;
|
||||
u32 field;
|
||||
__u32 __iomem *db_addr = &xhci->dba->doorbell[slot_id];
|
||||
|
||||
ep_ring = xhci->devs[slot_id]->ep_rings[ep_index];
|
||||
ep = &xhci->devs[slot_id]->eps[ep_index];
|
||||
ep_state = ep->ep_state;
|
||||
/* Don't ring the doorbell for this endpoint if there are pending
|
||||
* cancellations because the we don't want to interrupt processing.
|
||||
*/
|
||||
if (!ep_ring->cancels_pending && !(ep_ring->state & SET_DEQ_PENDING)
|
||||
&& !(ep_ring->state & EP_HALTED)) {
|
||||
if (!ep->cancels_pending && !(ep_state & SET_DEQ_PENDING)
|
||||
&& !(ep_state & EP_HALTED)) {
|
||||
field = xhci_readl(xhci, db_addr) & DB_MASK;
|
||||
xhci_writel(xhci, field | EPI_TO_DB(ep_index), db_addr);
|
||||
/* Flush PCI posted writes - FIXME Matthew Wilcox says this
|
||||
@@ -354,7 +363,7 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
|
||||
struct xhci_td *cur_td, struct xhci_dequeue_state *state)
|
||||
{
|
||||
struct xhci_virt_device *dev = xhci->devs[slot_id];
|
||||
struct xhci_ring *ep_ring = dev->ep_rings[ep_index];
|
||||
struct xhci_ring *ep_ring = dev->eps[ep_index].ring;
|
||||
struct xhci_generic_trb *trb;
|
||||
struct xhci_ep_ctx *ep_ctx;
|
||||
dma_addr_t addr;
|
||||
@@ -362,7 +371,7 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
|
||||
state->new_cycle_state = 0;
|
||||
xhci_dbg(xhci, "Finding segment containing stopped TRB.\n");
|
||||
state->new_deq_seg = find_trb_seg(cur_td->start_seg,
|
||||
ep_ring->stopped_trb,
|
||||
dev->eps[ep_index].stopped_trb,
|
||||
&state->new_cycle_state);
|
||||
if (!state->new_deq_seg)
|
||||
BUG();
|
||||
@@ -442,9 +451,11 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id,
|
||||
union xhci_trb *deq_ptr, u32 cycle_state);
|
||||
|
||||
void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
|
||||
struct xhci_ring *ep_ring, unsigned int slot_id,
|
||||
unsigned int ep_index, struct xhci_dequeue_state *deq_state)
|
||||
unsigned int slot_id, unsigned int ep_index,
|
||||
struct xhci_dequeue_state *deq_state)
|
||||
{
|
||||
struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index];
|
||||
|
||||
xhci_dbg(xhci, "Set TR Deq Ptr cmd, new deq seg = %p (0x%llx dma), "
|
||||
"new deq ptr = %p (0x%llx dma), new cycle = %u\n",
|
||||
deq_state->new_deq_seg,
|
||||
@@ -461,8 +472,7 @@ void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
|
||||
* if the ring is running, and ringing the doorbell starts the
|
||||
* ring running.
|
||||
*/
|
||||
ep_ring->state |= SET_DEQ_PENDING;
|
||||
xhci_ring_cmd_db(xhci);
|
||||
ep->ep_state |= SET_DEQ_PENDING;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -481,6 +491,7 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci,
|
||||
unsigned int slot_id;
|
||||
unsigned int ep_index;
|
||||
struct xhci_ring *ep_ring;
|
||||
struct xhci_virt_ep *ep;
|
||||
struct list_head *entry;
|
||||
struct xhci_td *cur_td = 0;
|
||||
struct xhci_td *last_unlinked_td;
|
||||
@@ -493,9 +504,10 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci,
|
||||
memset(&deq_state, 0, sizeof(deq_state));
|
||||
slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]);
|
||||
ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]);
|
||||
ep_ring = xhci->devs[slot_id]->ep_rings[ep_index];
|
||||
ep = &xhci->devs[slot_id]->eps[ep_index];
|
||||
ep_ring = ep->ring;
|
||||
|
||||
if (list_empty(&ep_ring->cancelled_td_list))
|
||||
if (list_empty(&ep->cancelled_td_list))
|
||||
return;
|
||||
|
||||
/* Fix up the ep ring first, so HW stops executing cancelled TDs.
|
||||
@@ -503,7 +515,7 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci,
|
||||
* it. We're also in the event handler, so we can't get re-interrupted
|
||||
* if another Stop Endpoint command completes
|
||||
*/
|
||||
list_for_each(entry, &ep_ring->cancelled_td_list) {
|
||||
list_for_each(entry, &ep->cancelled_td_list) {
|
||||
cur_td = list_entry(entry, struct xhci_td, cancelled_td_list);
|
||||
xhci_dbg(xhci, "Cancelling TD starting at %p, 0x%llx (dma).\n",
|
||||
cur_td->first_trb,
|
||||
@@ -512,7 +524,7 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci,
|
||||
* If we stopped on the TD we need to cancel, then we have to
|
||||
* move the xHC endpoint ring dequeue pointer past this TD.
|
||||
*/
|
||||
if (cur_td == ep_ring->stopped_td)
|
||||
if (cur_td == ep->stopped_td)
|
||||
xhci_find_new_dequeue_state(xhci, slot_id, ep_index, cur_td,
|
||||
&deq_state);
|
||||
else
|
||||
@@ -523,14 +535,15 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci,
|
||||
* the cancelled TD list for URB completion later.
|
||||
*/
|
||||
list_del(&cur_td->td_list);
|
||||
ep_ring->cancels_pending--;
|
||||
ep->cancels_pending--;
|
||||
}
|
||||
last_unlinked_td = cur_td;
|
||||
|
||||
/* If necessary, queue a Set Transfer Ring Dequeue Pointer command */
|
||||
if (deq_state.new_deq_ptr && deq_state.new_deq_seg) {
|
||||
xhci_queue_new_dequeue_state(xhci, ep_ring,
|
||||
xhci_queue_new_dequeue_state(xhci,
|
||||
slot_id, ep_index, &deq_state);
|
||||
xhci_ring_cmd_db(xhci);
|
||||
} else {
|
||||
/* Otherwise just ring the doorbell to restart the ring */
|
||||
ring_ep_doorbell(xhci, slot_id, ep_index);
|
||||
@@ -543,7 +556,7 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci,
|
||||
* So stop when we've completed the URB for the last TD we unlinked.
|
||||
*/
|
||||
do {
|
||||
cur_td = list_entry(ep_ring->cancelled_td_list.next,
|
||||
cur_td = list_entry(ep->cancelled_td_list.next,
|
||||
struct xhci_td, cancelled_td_list);
|
||||
list_del(&cur_td->cancelled_td_list);
|
||||
|
||||
@@ -590,7 +603,7 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci,
|
||||
slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]);
|
||||
ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]);
|
||||
dev = xhci->devs[slot_id];
|
||||
ep_ring = dev->ep_rings[ep_index];
|
||||
ep_ring = dev->eps[ep_index].ring;
|
||||
ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index);
|
||||
slot_ctx = xhci_get_slot_ctx(xhci, dev->out_ctx);
|
||||
|
||||
@@ -634,7 +647,7 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci,
|
||||
ep_ctx->deq);
|
||||
}
|
||||
|
||||
ep_ring->state &= ~SET_DEQ_PENDING;
|
||||
dev->eps[ep_index].ep_state &= ~SET_DEQ_PENDING;
|
||||
ring_ep_doorbell(xhci, slot_id, ep_index);
|
||||
}
|
||||
|
||||
@@ -644,18 +657,60 @@ static void handle_reset_ep_completion(struct xhci_hcd *xhci,
|
||||
{
|
||||
int slot_id;
|
||||
unsigned int ep_index;
|
||||
struct xhci_ring *ep_ring;
|
||||
|
||||
slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]);
|
||||
ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]);
|
||||
ep_ring = xhci->devs[slot_id]->eps[ep_index].ring;
|
||||
/* This command will only fail if the endpoint wasn't halted,
|
||||
* but we don't care.
|
||||
*/
|
||||
xhci_dbg(xhci, "Ignoring reset ep completion code of %u\n",
|
||||
(unsigned int) GET_COMP_CODE(event->status));
|
||||
|
||||
/* Clear our internal halted state and restart the ring */
|
||||
xhci->devs[slot_id]->ep_rings[ep_index]->state &= ~EP_HALTED;
|
||||
ring_ep_doorbell(xhci, slot_id, ep_index);
|
||||
/* HW with the reset endpoint quirk needs to have a configure endpoint
|
||||
* command complete before the endpoint can be used. Queue that here
|
||||
* because the HW can't handle two commands being queued in a row.
|
||||
*/
|
||||
if (xhci->quirks & XHCI_RESET_EP_QUIRK) {
|
||||
xhci_dbg(xhci, "Queueing configure endpoint command\n");
|
||||
xhci_queue_configure_endpoint(xhci,
|
||||
xhci->devs[slot_id]->in_ctx->dma, slot_id,
|
||||
false);
|
||||
xhci_ring_cmd_db(xhci);
|
||||
} else {
|
||||
/* Clear our internal halted state and restart the ring */
|
||||
xhci->devs[slot_id]->eps[ep_index].ep_state &= ~EP_HALTED;
|
||||
ring_ep_doorbell(xhci, slot_id, ep_index);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check to see if a command in the device's command queue matches this one.
|
||||
* Signal the completion or free the command, and return 1. Return 0 if the
|
||||
* completed command isn't at the head of the command list.
|
||||
*/
|
||||
static int handle_cmd_in_cmd_wait_list(struct xhci_hcd *xhci,
|
||||
struct xhci_virt_device *virt_dev,
|
||||
struct xhci_event_cmd *event)
|
||||
{
|
||||
struct xhci_command *command;
|
||||
|
||||
if (list_empty(&virt_dev->cmd_list))
|
||||
return 0;
|
||||
|
||||
command = list_entry(virt_dev->cmd_list.next,
|
||||
struct xhci_command, cmd_list);
|
||||
if (xhci->cmd_ring->dequeue != command->command_trb)
|
||||
return 0;
|
||||
|
||||
command->status =
|
||||
GET_COMP_CODE(event->status);
|
||||
list_del(&command->cmd_list);
|
||||
if (command->completion)
|
||||
complete(command->completion);
|
||||
else
|
||||
xhci_free_command(xhci, command);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void handle_cmd_completion(struct xhci_hcd *xhci,
|
||||
@@ -664,6 +719,11 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
|
||||
int slot_id = TRB_TO_SLOT_ID(event->flags);
|
||||
u64 cmd_dma;
|
||||
dma_addr_t cmd_dequeue_dma;
|
||||
struct xhci_input_control_ctx *ctrl_ctx;
|
||||
struct xhci_virt_device *virt_dev;
|
||||
unsigned int ep_index;
|
||||
struct xhci_ring *ep_ring;
|
||||
unsigned int ep_state;
|
||||
|
||||
cmd_dma = event->cmd_trb;
|
||||
cmd_dequeue_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
|
||||
@@ -691,6 +751,47 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
|
||||
xhci_free_virt_device(xhci, slot_id);
|
||||
break;
|
||||
case TRB_TYPE(TRB_CONFIG_EP):
|
||||
virt_dev = xhci->devs[slot_id];
|
||||
if (handle_cmd_in_cmd_wait_list(xhci, virt_dev, event))
|
||||
break;
|
||||
/*
|
||||
* Configure endpoint commands can come from the USB core
|
||||
* configuration or alt setting changes, or because the HW
|
||||
* needed an extra configure endpoint command after a reset
|
||||
* endpoint command. In the latter case, the xHCI driver is
|
||||
* not waiting on the configure endpoint command.
|
||||
*/
|
||||
ctrl_ctx = xhci_get_input_control_ctx(xhci,
|
||||
virt_dev->in_ctx);
|
||||
/* Input ctx add_flags are the endpoint index plus one */
|
||||
ep_index = xhci_last_valid_endpoint(ctrl_ctx->add_flags) - 1;
|
||||
ep_ring = xhci->devs[slot_id]->eps[ep_index].ring;
|
||||
if (!ep_ring) {
|
||||
/* This must have been an initial configure endpoint */
|
||||
xhci->devs[slot_id]->cmd_status =
|
||||
GET_COMP_CODE(event->status);
|
||||
complete(&xhci->devs[slot_id]->cmd_completion);
|
||||
break;
|
||||
}
|
||||
ep_state = xhci->devs[slot_id]->eps[ep_index].ep_state;
|
||||
xhci_dbg(xhci, "Completed config ep cmd - last ep index = %d, "
|
||||
"state = %d\n", ep_index, ep_state);
|
||||
if (xhci->quirks & XHCI_RESET_EP_QUIRK &&
|
||||
ep_state & EP_HALTED) {
|
||||
/* Clear our internal halted state and restart ring */
|
||||
xhci->devs[slot_id]->eps[ep_index].ep_state &=
|
||||
~EP_HALTED;
|
||||
ring_ep_doorbell(xhci, slot_id, ep_index);
|
||||
} else {
|
||||
xhci->devs[slot_id]->cmd_status =
|
||||
GET_COMP_CODE(event->status);
|
||||
complete(&xhci->devs[slot_id]->cmd_completion);
|
||||
}
|
||||
break;
|
||||
case TRB_TYPE(TRB_EVAL_CONTEXT):
|
||||
virt_dev = xhci->devs[slot_id];
|
||||
if (handle_cmd_in_cmd_wait_list(xhci, virt_dev, event))
|
||||
break;
|
||||
xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status);
|
||||
complete(&xhci->devs[slot_id]->cmd_completion);
|
||||
break;
|
||||
@@ -805,7 +906,9 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
||||
struct xhci_transfer_event *event)
|
||||
{
|
||||
struct xhci_virt_device *xdev;
|
||||
struct xhci_virt_ep *ep;
|
||||
struct xhci_ring *ep_ring;
|
||||
unsigned int slot_id;
|
||||
int ep_index;
|
||||
struct xhci_td *td = 0;
|
||||
dma_addr_t event_dma;
|
||||
@@ -814,9 +917,11 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
||||
struct urb *urb = 0;
|
||||
int status = -EINPROGRESS;
|
||||
struct xhci_ep_ctx *ep_ctx;
|
||||
u32 trb_comp_code;
|
||||
|
||||
xhci_dbg(xhci, "In %s\n", __func__);
|
||||
xdev = xhci->devs[TRB_TO_SLOT_ID(event->flags)];
|
||||
slot_id = TRB_TO_SLOT_ID(event->flags);
|
||||
xdev = xhci->devs[slot_id];
|
||||
if (!xdev) {
|
||||
xhci_err(xhci, "ERROR Transfer event pointed to bad slot\n");
|
||||
return -ENODEV;
|
||||
@@ -825,7 +930,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
||||
/* Endpoint ID is 1 based, our index is zero based */
|
||||
ep_index = TRB_TO_EP_ID(event->flags) - 1;
|
||||
xhci_dbg(xhci, "%s - ep index = %d\n", __func__, ep_index);
|
||||
ep_ring = xdev->ep_rings[ep_index];
|
||||
ep = &xdev->eps[ep_index];
|
||||
ep_ring = ep->ring;
|
||||
ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
|
||||
if (!ep_ring || (ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED) {
|
||||
xhci_err(xhci, "ERROR Transfer event pointed to disabled endpoint\n");
|
||||
@@ -870,7 +976,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
||||
(unsigned int) event->flags);
|
||||
|
||||
/* Look for common error cases */
|
||||
switch (GET_COMP_CODE(event->transfer_len)) {
|
||||
trb_comp_code = GET_COMP_CODE(event->transfer_len);
|
||||
switch (trb_comp_code) {
|
||||
/* Skip codes that require special handling depending on
|
||||
* transfer type
|
||||
*/
|
||||
@@ -885,7 +992,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
||||
break;
|
||||
case COMP_STALL:
|
||||
xhci_warn(xhci, "WARN: Stalled endpoint\n");
|
||||
ep_ring->state |= EP_HALTED;
|
||||
ep->ep_state |= EP_HALTED;
|
||||
status = -EPIPE;
|
||||
break;
|
||||
case COMP_TRB_ERR:
|
||||
@@ -913,7 +1020,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
||||
/* Was this a control transfer? */
|
||||
if (usb_endpoint_xfer_control(&td->urb->ep->desc)) {
|
||||
xhci_debug_trb(xhci, xhci->event_ring->dequeue);
|
||||
switch (GET_COMP_CODE(event->transfer_len)) {
|
||||
switch (trb_comp_code) {
|
||||
case COMP_SUCCESS:
|
||||
if (event_trb == ep_ring->dequeue) {
|
||||
xhci_warn(xhci, "WARN: Success on ctrl setup TRB without IOC set??\n");
|
||||
@@ -928,8 +1035,37 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
||||
break;
|
||||
case COMP_SHORT_TX:
|
||||
xhci_warn(xhci, "WARN: short transfer on control ep\n");
|
||||
status = -EREMOTEIO;
|
||||
if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
|
||||
status = -EREMOTEIO;
|
||||
else
|
||||
status = 0;
|
||||
break;
|
||||
case COMP_BABBLE:
|
||||
/* The 0.96 spec says a babbling control endpoint
|
||||
* is not halted. The 0.96 spec says it is. Some HW
|
||||
* claims to be 0.95 compliant, but it halts the control
|
||||
* endpoint anyway. Check if a babble halted the
|
||||
* endpoint.
|
||||
*/
|
||||
if (ep_ctx->ep_info != EP_STATE_HALTED)
|
||||
break;
|
||||
/* else fall through */
|
||||
case COMP_STALL:
|
||||
/* Did we transfer part of the data (middle) phase? */
|
||||
if (event_trb != ep_ring->dequeue &&
|
||||
event_trb != td->last_trb)
|
||||
td->urb->actual_length =
|
||||
td->urb->transfer_buffer_length
|
||||
- TRB_LEN(event->transfer_len);
|
||||
else
|
||||
td->urb->actual_length = 0;
|
||||
|
||||
ep->stopped_td = td;
|
||||
ep->stopped_trb = event_trb;
|
||||
xhci_queue_reset_ep(xhci, slot_id, ep_index);
|
||||
xhci_cleanup_stalled_ring(xhci, td->urb->dev, ep_index);
|
||||
xhci_ring_cmd_db(xhci);
|
||||
goto td_cleanup;
|
||||
default:
|
||||
/* Others already handled above */
|
||||
break;
|
||||
@@ -943,7 +1079,10 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
||||
if (event_trb == td->last_trb) {
|
||||
if (td->urb->actual_length != 0) {
|
||||
/* Don't overwrite a previously set error code */
|
||||
if (status == -EINPROGRESS || status == 0)
|
||||
if ((status == -EINPROGRESS ||
|
||||
status == 0) &&
|
||||
(td->urb->transfer_flags
|
||||
& URB_SHORT_NOT_OK))
|
||||
/* Did we already see a short data stage? */
|
||||
status = -EREMOTEIO;
|
||||
} else {
|
||||
@@ -952,7 +1091,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
||||
}
|
||||
} else {
|
||||
/* Maybe the event was for the data stage? */
|
||||
if (GET_COMP_CODE(event->transfer_len) != COMP_STOP_INVAL) {
|
||||
if (trb_comp_code != COMP_STOP_INVAL) {
|
||||
/* We didn't stop on a link TRB in the middle */
|
||||
td->urb->actual_length =
|
||||
td->urb->transfer_buffer_length -
|
||||
@@ -964,7 +1103,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (GET_COMP_CODE(event->transfer_len)) {
|
||||
switch (trb_comp_code) {
|
||||
case COMP_SUCCESS:
|
||||
/* Double check that the HW transferred everything. */
|
||||
if (event_trb != td->last_trb) {
|
||||
@@ -975,7 +1114,12 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
||||
else
|
||||
status = 0;
|
||||
} else {
|
||||
xhci_dbg(xhci, "Successful bulk transfer!\n");
|
||||
if (usb_endpoint_xfer_bulk(&td->urb->ep->desc))
|
||||
xhci_dbg(xhci, "Successful bulk "
|
||||
"transfer!\n");
|
||||
else
|
||||
xhci_dbg(xhci, "Successful interrupt "
|
||||
"transfer!\n");
|
||||
status = 0;
|
||||
}
|
||||
break;
|
||||
@@ -1001,11 +1145,17 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
||||
td->urb->actual_length =
|
||||
td->urb->transfer_buffer_length -
|
||||
TRB_LEN(event->transfer_len);
|
||||
if (td->urb->actual_length < 0) {
|
||||
if (td->urb->transfer_buffer_length <
|
||||
td->urb->actual_length) {
|
||||
xhci_warn(xhci, "HC gave bad length "
|
||||
"of %d bytes left\n",
|
||||
TRB_LEN(event->transfer_len));
|
||||
td->urb->actual_length = 0;
|
||||
if (td->urb->transfer_flags &
|
||||
URB_SHORT_NOT_OK)
|
||||
status = -EREMOTEIO;
|
||||
else
|
||||
status = 0;
|
||||
}
|
||||
/* Don't overwrite a previously set error code */
|
||||
if (status == -EINPROGRESS) {
|
||||
@@ -1041,30 +1191,31 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
||||
/* If the ring didn't stop on a Link or No-op TRB, add
|
||||
* in the actual bytes transferred from the Normal TRB
|
||||
*/
|
||||
if (GET_COMP_CODE(event->transfer_len) != COMP_STOP_INVAL)
|
||||
if (trb_comp_code != COMP_STOP_INVAL)
|
||||
td->urb->actual_length +=
|
||||
TRB_LEN(cur_trb->generic.field[2]) -
|
||||
TRB_LEN(event->transfer_len);
|
||||
}
|
||||
}
|
||||
if (GET_COMP_CODE(event->transfer_len) == COMP_STOP_INVAL ||
|
||||
GET_COMP_CODE(event->transfer_len) == COMP_STOP) {
|
||||
if (trb_comp_code == COMP_STOP_INVAL ||
|
||||
trb_comp_code == COMP_STOP) {
|
||||
/* The Endpoint Stop Command completion will take care of any
|
||||
* stopped TDs. A stopped TD may be restarted, so don't update
|
||||
* the ring dequeue pointer or take this TD off any lists yet.
|
||||
*/
|
||||
ep_ring->stopped_td = td;
|
||||
ep_ring->stopped_trb = event_trb;
|
||||
ep->stopped_td = td;
|
||||
ep->stopped_trb = event_trb;
|
||||
} else {
|
||||
if (GET_COMP_CODE(event->transfer_len) == COMP_STALL) {
|
||||
if (trb_comp_code == COMP_STALL ||
|
||||
trb_comp_code == COMP_BABBLE) {
|
||||
/* The transfer is completed from the driver's
|
||||
* perspective, but we need to issue a set dequeue
|
||||
* command for this stalled endpoint to move the dequeue
|
||||
* pointer past the TD. We can't do that here because
|
||||
* the halt condition must be cleared first.
|
||||
*/
|
||||
ep_ring->stopped_td = td;
|
||||
ep_ring->stopped_trb = event_trb;
|
||||
ep->stopped_td = td;
|
||||
ep->stopped_trb = event_trb;
|
||||
} else {
|
||||
/* Update ring dequeue pointer */
|
||||
while (ep_ring->dequeue != td->last_trb)
|
||||
@@ -1072,16 +1223,41 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
||||
inc_deq(xhci, ep_ring, false);
|
||||
}
|
||||
|
||||
td_cleanup:
|
||||
/* Clean up the endpoint's TD list */
|
||||
urb = td->urb;
|
||||
/* Do one last check of the actual transfer length.
|
||||
* If the host controller said we transferred more data than
|
||||
* the buffer length, urb->actual_length will be a very big
|
||||
* number (since it's unsigned). Play it safe and say we didn't
|
||||
* transfer anything.
|
||||
*/
|
||||
if (urb->actual_length > urb->transfer_buffer_length) {
|
||||
xhci_warn(xhci, "URB transfer length is wrong, "
|
||||
"xHC issue? req. len = %u, "
|
||||
"act. len = %u\n",
|
||||
urb->transfer_buffer_length,
|
||||
urb->actual_length);
|
||||
urb->actual_length = 0;
|
||||
if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
|
||||
status = -EREMOTEIO;
|
||||
else
|
||||
status = 0;
|
||||
}
|
||||
list_del(&td->td_list);
|
||||
/* Was this TD slated to be cancelled but completed anyway? */
|
||||
if (!list_empty(&td->cancelled_td_list)) {
|
||||
list_del(&td->cancelled_td_list);
|
||||
ep_ring->cancels_pending--;
|
||||
ep->cancels_pending--;
|
||||
}
|
||||
/* Leave the TD around for the reset endpoint function to use */
|
||||
if (GET_COMP_CODE(event->transfer_len) != COMP_STALL) {
|
||||
/* Leave the TD around for the reset endpoint function to use
|
||||
* (but only if it's not a control endpoint, since we already
|
||||
* queued the Set TR dequeue pointer command for stalled
|
||||
* control endpoints).
|
||||
*/
|
||||
if (usb_endpoint_xfer_control(&urb->ep->desc) ||
|
||||
(trb_comp_code != COMP_STALL &&
|
||||
trb_comp_code != COMP_BABBLE)) {
|
||||
kfree(td);
|
||||
}
|
||||
urb->hcpriv = NULL;
|
||||
@@ -1094,7 +1270,7 @@ cleanup:
|
||||
if (urb) {
|
||||
usb_hcd_unlink_urb_from_ep(xhci_to_hcd(xhci), urb);
|
||||
xhci_dbg(xhci, "Giveback URB %p, len = %d, status = %d\n",
|
||||
urb, td->urb->actual_length, status);
|
||||
urb, urb->actual_length, status);
|
||||
spin_unlock(&xhci->lock);
|
||||
usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, status);
|
||||
spin_lock(&xhci->lock);
|
||||
@@ -1235,7 +1411,7 @@ static int prepare_transfer(struct xhci_hcd *xhci,
|
||||
{
|
||||
int ret;
|
||||
struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
|
||||
ret = prepare_ring(xhci, xdev->ep_rings[ep_index],
|
||||
ret = prepare_ring(xhci, xdev->eps[ep_index].ring,
|
||||
ep_ctx->ep_info & EP_STATE_MASK,
|
||||
num_trbs, mem_flags);
|
||||
if (ret)
|
||||
@@ -1255,9 +1431,9 @@ static int prepare_transfer(struct xhci_hcd *xhci,
|
||||
(*td)->urb = urb;
|
||||
urb->hcpriv = (void *) (*td);
|
||||
/* Add this TD to the tail of the endpoint ring's TD list */
|
||||
list_add_tail(&(*td)->td_list, &xdev->ep_rings[ep_index]->td_list);
|
||||
(*td)->start_seg = xdev->ep_rings[ep_index]->enq_seg;
|
||||
(*td)->first_trb = xdev->ep_rings[ep_index]->enqueue;
|
||||
list_add_tail(&(*td)->td_list, &xdev->eps[ep_index].ring->td_list);
|
||||
(*td)->start_seg = xdev->eps[ep_index].ring->enq_seg;
|
||||
(*td)->first_trb = xdev->eps[ep_index].ring->enqueue;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1335,6 +1511,47 @@ static void giveback_first_trb(struct xhci_hcd *xhci, int slot_id,
|
||||
ring_ep_doorbell(xhci, slot_id, ep_index);
|
||||
}
|
||||
|
||||
/*
|
||||
* xHCI uses normal TRBs for both bulk and interrupt. When the interrupt
|
||||
* endpoint is to be serviced, the xHC will consume (at most) one TD. A TD
|
||||
* (comprised of sg list entries) can take several service intervals to
|
||||
* transmit.
|
||||
*/
|
||||
int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||
struct urb *urb, int slot_id, unsigned int ep_index)
|
||||
{
|
||||
struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci,
|
||||
xhci->devs[slot_id]->out_ctx, ep_index);
|
||||
int xhci_interval;
|
||||
int ep_interval;
|
||||
|
||||
xhci_interval = EP_INTERVAL_TO_UFRAMES(ep_ctx->ep_info);
|
||||
ep_interval = urb->interval;
|
||||
/* Convert to microframes */
|
||||
if (urb->dev->speed == USB_SPEED_LOW ||
|
||||
urb->dev->speed == USB_SPEED_FULL)
|
||||
ep_interval *= 8;
|
||||
/* FIXME change this to a warning and a suggestion to use the new API
|
||||
* to set the polling interval (once the API is added).
|
||||
*/
|
||||
if (xhci_interval != ep_interval) {
|
||||
if (!printk_ratelimit())
|
||||
dev_dbg(&urb->dev->dev, "Driver uses different interval"
|
||||
" (%d microframe%s) than xHCI "
|
||||
"(%d microframe%s)\n",
|
||||
ep_interval,
|
||||
ep_interval == 1 ? "" : "s",
|
||||
xhci_interval,
|
||||
xhci_interval == 1 ? "" : "s");
|
||||
urb->interval = xhci_interval;
|
||||
/* Convert back to frames for LS/FS devices */
|
||||
if (urb->dev->speed == USB_SPEED_LOW ||
|
||||
urb->dev->speed == USB_SPEED_FULL)
|
||||
urb->interval /= 8;
|
||||
}
|
||||
return xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index);
|
||||
}
|
||||
|
||||
static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||
struct urb *urb, int slot_id, unsigned int ep_index)
|
||||
{
|
||||
@@ -1350,7 +1567,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||
struct xhci_generic_trb *start_trb;
|
||||
int start_cycle;
|
||||
|
||||
ep_ring = xhci->devs[slot_id]->ep_rings[ep_index];
|
||||
ep_ring = xhci->devs[slot_id]->eps[ep_index].ring;
|
||||
num_trbs = count_sg_trbs_needed(xhci, urb);
|
||||
num_sgs = urb->num_sgs;
|
||||
|
||||
@@ -1483,7 +1700,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||
if (urb->sg)
|
||||
return queue_bulk_sg_tx(xhci, mem_flags, urb, slot_id, ep_index);
|
||||
|
||||
ep_ring = xhci->devs[slot_id]->ep_rings[ep_index];
|
||||
ep_ring = xhci->devs[slot_id]->eps[ep_index].ring;
|
||||
|
||||
num_trbs = 0;
|
||||
/* How much data is (potentially) left before the 64KB boundary? */
|
||||
@@ -1594,7 +1811,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||
u32 field, length_field;
|
||||
struct xhci_td *td;
|
||||
|
||||
ep_ring = xhci->devs[slot_id]->ep_rings[ep_index];
|
||||
ep_ring = xhci->devs[slot_id]->eps[ep_index].ring;
|
||||
|
||||
/*
|
||||
* Need to copy setup packet into setup TRB, so we can't use the setup
|
||||
@@ -1677,12 +1894,27 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||
|
||||
/**** Command Ring Operations ****/
|
||||
|
||||
/* Generic function for queueing a command TRB on the command ring */
|
||||
static int queue_command(struct xhci_hcd *xhci, u32 field1, u32 field2, u32 field3, u32 field4)
|
||||
/* Generic function for queueing a command TRB on the command ring.
|
||||
* Check to make sure there's room on the command ring for one command TRB.
|
||||
* Also check that there's room reserved for commands that must not fail.
|
||||
* If this is a command that must not fail, meaning command_must_succeed = TRUE,
|
||||
* then only check for the number of reserved spots.
|
||||
* Don't decrement xhci->cmd_ring_reserved_trbs after we've queued the TRB
|
||||
* because the command event handler may want to resubmit a failed command.
|
||||
*/
|
||||
static int queue_command(struct xhci_hcd *xhci, u32 field1, u32 field2,
|
||||
u32 field3, u32 field4, bool command_must_succeed)
|
||||
{
|
||||
if (!room_on_ring(xhci, xhci->cmd_ring, 1)) {
|
||||
int reserved_trbs = xhci->cmd_ring_reserved_trbs;
|
||||
if (!command_must_succeed)
|
||||
reserved_trbs++;
|
||||
|
||||
if (!room_on_ring(xhci, xhci->cmd_ring, reserved_trbs)) {
|
||||
if (!in_interrupt())
|
||||
xhci_err(xhci, "ERR: No room for command on command ring\n");
|
||||
if (command_must_succeed)
|
||||
xhci_err(xhci, "ERR: Reserved TRB counting for "
|
||||
"unfailable commands failed.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
queue_trb(xhci, xhci->cmd_ring, false, field1, field2, field3,
|
||||
@@ -1693,7 +1925,7 @@ static int queue_command(struct xhci_hcd *xhci, u32 field1, u32 field2, u32 fiel
|
||||
/* Queue a no-op command on the command ring */
|
||||
static int queue_cmd_noop(struct xhci_hcd *xhci)
|
||||
{
|
||||
return queue_command(xhci, 0, 0, 0, TRB_TYPE(TRB_CMD_NOOP));
|
||||
return queue_command(xhci, 0, 0, 0, TRB_TYPE(TRB_CMD_NOOP), false);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1712,7 +1944,7 @@ void *xhci_setup_one_noop(struct xhci_hcd *xhci)
|
||||
int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id)
|
||||
{
|
||||
return queue_command(xhci, 0, 0, 0,
|
||||
TRB_TYPE(trb_type) | SLOT_ID_FOR_TRB(slot_id));
|
||||
TRB_TYPE(trb_type) | SLOT_ID_FOR_TRB(slot_id), false);
|
||||
}
|
||||
|
||||
/* Queue an address device command TRB */
|
||||
@@ -1721,16 +1953,28 @@ int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
|
||||
{
|
||||
return queue_command(xhci, lower_32_bits(in_ctx_ptr),
|
||||
upper_32_bits(in_ctx_ptr), 0,
|
||||
TRB_TYPE(TRB_ADDR_DEV) | SLOT_ID_FOR_TRB(slot_id));
|
||||
TRB_TYPE(TRB_ADDR_DEV) | SLOT_ID_FOR_TRB(slot_id),
|
||||
false);
|
||||
}
|
||||
|
||||
/* Queue a configure endpoint command TRB */
|
||||
int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
|
||||
u32 slot_id, bool command_must_succeed)
|
||||
{
|
||||
return queue_command(xhci, lower_32_bits(in_ctx_ptr),
|
||||
upper_32_bits(in_ctx_ptr), 0,
|
||||
TRB_TYPE(TRB_CONFIG_EP) | SLOT_ID_FOR_TRB(slot_id),
|
||||
command_must_succeed);
|
||||
}
|
||||
|
||||
/* Queue an evaluate context command TRB */
|
||||
int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
|
||||
u32 slot_id)
|
||||
{
|
||||
return queue_command(xhci, lower_32_bits(in_ctx_ptr),
|
||||
upper_32_bits(in_ctx_ptr), 0,
|
||||
TRB_TYPE(TRB_CONFIG_EP) | SLOT_ID_FOR_TRB(slot_id));
|
||||
TRB_TYPE(TRB_EVAL_CONTEXT) | SLOT_ID_FOR_TRB(slot_id),
|
||||
false);
|
||||
}
|
||||
|
||||
int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id,
|
||||
@@ -1741,7 +1985,7 @@ int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id,
|
||||
u32 type = TRB_TYPE(TRB_STOP_RING);
|
||||
|
||||
return queue_command(xhci, 0, 0, 0,
|
||||
trb_slot_id | trb_ep_index | type);
|
||||
trb_slot_id | trb_ep_index | type, false);
|
||||
}
|
||||
|
||||
/* Set Transfer Ring Dequeue Pointer command.
|
||||
@@ -1765,7 +2009,7 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id,
|
||||
}
|
||||
return queue_command(xhci, lower_32_bits(addr) | cycle_state,
|
||||
upper_32_bits(addr), 0,
|
||||
trb_slot_id | trb_ep_index | type);
|
||||
trb_slot_id | trb_ep_index | type, false);
|
||||
}
|
||||
|
||||
int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id,
|
||||
@@ -1775,5 +2019,6 @@ int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id,
|
||||
u32 trb_ep_index = EP_ID_FOR_TRB(ep_index);
|
||||
u32 type = TRB_TYPE(TRB_RESET_EP);
|
||||
|
||||
return queue_command(xhci, 0, 0, 0, trb_slot_id | trb_ep_index | type);
|
||||
return queue_command(xhci, 0, 0, 0, trb_slot_id | trb_ep_index | type,
|
||||
false);
|
||||
}
|
||||
|
@@ -509,6 +509,8 @@ struct xhci_slot_ctx {
|
||||
#define MAX_EXIT (0xffff)
|
||||
/* Root hub port number that is needed to access the USB device */
|
||||
#define ROOT_HUB_PORT(p) (((p) & 0xff) << 16)
|
||||
/* Maximum number of ports under a hub device */
|
||||
#define XHCI_MAX_PORTS(p) (((p) & 0xff) << 24)
|
||||
|
||||
/* tt_info bitmasks */
|
||||
/*
|
||||
@@ -522,6 +524,7 @@ struct xhci_slot_ctx {
|
||||
* '0' if the device is not low or full speed.
|
||||
*/
|
||||
#define TT_PORT (0xff << 8)
|
||||
#define TT_THINK_TIME(p) (((p) & 0x3) << 16)
|
||||
|
||||
/* dev_state bitmasks */
|
||||
/* USB device address - assigned by the HC */
|
||||
@@ -581,6 +584,7 @@ struct xhci_ep_ctx {
|
||||
/* bit 15 is Linear Stream Array */
|
||||
/* Interval - period between requests to an endpoint - 125u increments. */
|
||||
#define EP_INTERVAL(p) ((p & 0xff) << 16)
|
||||
#define EP_INTERVAL_TO_UFRAMES(p) (1 << (((p) >> 16) & 0xff))
|
||||
|
||||
/* ep_info2 bitmasks */
|
||||
/*
|
||||
@@ -589,6 +593,7 @@ struct xhci_ep_ctx {
|
||||
*/
|
||||
#define FORCE_EVENT (0x1)
|
||||
#define ERROR_COUNT(p) (((p) & 0x3) << 1)
|
||||
#define CTX_TO_EP_TYPE(p) (((p) >> 3) & 0x7)
|
||||
#define EP_TYPE(p) ((p) << 3)
|
||||
#define ISOC_OUT_EP 1
|
||||
#define BULK_OUT_EP 2
|
||||
@@ -601,6 +606,8 @@ struct xhci_ep_ctx {
|
||||
/* bit 7 is Host Initiate Disable - for disabling stream selection */
|
||||
#define MAX_BURST(p) (((p)&0xff) << 8)
|
||||
#define MAX_PACKET(p) (((p)&0xffff) << 16)
|
||||
#define MAX_PACKET_MASK (0xffff << 16)
|
||||
#define MAX_PACKET_DECODED(p) (((p) >> 16) & 0xffff)
|
||||
|
||||
|
||||
/**
|
||||
@@ -616,11 +623,44 @@ struct xhci_input_control_ctx {
|
||||
u32 rsvd2[6];
|
||||
};
|
||||
|
||||
/* Represents everything that is needed to issue a command on the command ring.
|
||||
* It's useful to pre-allocate these for commands that cannot fail due to
|
||||
* out-of-memory errors, like freeing streams.
|
||||
*/
|
||||
struct xhci_command {
|
||||
/* Input context for changing device state */
|
||||
struct xhci_container_ctx *in_ctx;
|
||||
u32 status;
|
||||
/* If completion is null, no one is waiting on this command
|
||||
* and the structure can be freed after the command completes.
|
||||
*/
|
||||
struct completion *completion;
|
||||
union xhci_trb *command_trb;
|
||||
struct list_head cmd_list;
|
||||
};
|
||||
|
||||
/* drop context bitmasks */
|
||||
#define DROP_EP(x) (0x1 << x)
|
||||
/* add context bitmasks */
|
||||
#define ADD_EP(x) (0x1 << x)
|
||||
|
||||
struct xhci_virt_ep {
|
||||
struct xhci_ring *ring;
|
||||
/* Temporary storage in case the configure endpoint command fails and we
|
||||
* have to restore the device state to the previous state
|
||||
*/
|
||||
struct xhci_ring *new_ring;
|
||||
unsigned int ep_state;
|
||||
#define SET_DEQ_PENDING (1 << 0)
|
||||
#define EP_HALTED (1 << 1)
|
||||
/* ---- Related to URB cancellation ---- */
|
||||
struct list_head cancelled_td_list;
|
||||
unsigned int cancels_pending;
|
||||
/* The TRB that was last reported in a stopped endpoint ring */
|
||||
union xhci_trb *stopped_trb;
|
||||
struct xhci_td *stopped_td;
|
||||
};
|
||||
|
||||
struct xhci_virt_device {
|
||||
/*
|
||||
* Commands to the hardware are passed an "input context" that
|
||||
@@ -633,16 +673,11 @@ struct xhci_virt_device {
|
||||
struct xhci_container_ctx *out_ctx;
|
||||
/* Used for addressing devices and configuration changes */
|
||||
struct xhci_container_ctx *in_ctx;
|
||||
|
||||
/* FIXME when stream support is added */
|
||||
struct xhci_ring *ep_rings[31];
|
||||
/* Temporary storage in case the configure endpoint command fails and we
|
||||
* have to restore the device state to the previous state
|
||||
*/
|
||||
struct xhci_ring *new_ep_rings[31];
|
||||
struct xhci_virt_ep eps[31];
|
||||
struct completion cmd_completion;
|
||||
/* Status of the last command issued for this device */
|
||||
u32 cmd_status;
|
||||
struct list_head cmd_list;
|
||||
};
|
||||
|
||||
|
||||
@@ -905,6 +940,8 @@ union xhci_trb {
|
||||
* It must also be greater than 16.
|
||||
*/
|
||||
#define TRBS_PER_SEGMENT 64
|
||||
/* Allow two commands + a link TRB, along with any reserved command TRBs */
|
||||
#define MAX_RSVD_CMD_TRBS (TRBS_PER_SEGMENT - 3)
|
||||
#define SEGMENT_SIZE (TRBS_PER_SEGMENT*16)
|
||||
/* TRB buffer pointers can't cross 64KB boundaries */
|
||||
#define TRB_MAX_BUFF_SHIFT 16
|
||||
@@ -926,6 +963,12 @@ struct xhci_td {
|
||||
union xhci_trb *last_trb;
|
||||
};
|
||||
|
||||
struct xhci_dequeue_state {
|
||||
struct xhci_segment *new_deq_seg;
|
||||
union xhci_trb *new_deq_ptr;
|
||||
int new_cycle_state;
|
||||
};
|
||||
|
||||
struct xhci_ring {
|
||||
struct xhci_segment *first_seg;
|
||||
union xhci_trb *enqueue;
|
||||
@@ -935,15 +978,6 @@ struct xhci_ring {
|
||||
struct xhci_segment *deq_seg;
|
||||
unsigned int deq_updates;
|
||||
struct list_head td_list;
|
||||
/* ---- Related to URB cancellation ---- */
|
||||
struct list_head cancelled_td_list;
|
||||
unsigned int cancels_pending;
|
||||
unsigned int state;
|
||||
#define SET_DEQ_PENDING (1 << 0)
|
||||
#define EP_HALTED (1 << 1)
|
||||
/* The TRB that was last reported in a stopped endpoint ring */
|
||||
union xhci_trb *stopped_trb;
|
||||
struct xhci_td *stopped_td;
|
||||
/*
|
||||
* Write the cycle state into the TRB cycle field to give ownership of
|
||||
* the TRB to the host controller (if we are the producer), or to check
|
||||
@@ -952,12 +986,6 @@ struct xhci_ring {
|
||||
u32 cycle_state;
|
||||
};
|
||||
|
||||
struct xhci_dequeue_state {
|
||||
struct xhci_segment *new_deq_seg;
|
||||
union xhci_trb *new_deq_ptr;
|
||||
int new_cycle_state;
|
||||
};
|
||||
|
||||
struct xhci_erst_entry {
|
||||
/* 64-bit event ring segment address */
|
||||
u64 seg_addr;
|
||||
@@ -1034,6 +1062,7 @@ struct xhci_hcd {
|
||||
/* data structures */
|
||||
struct xhci_device_context_array *dcbaa;
|
||||
struct xhci_ring *cmd_ring;
|
||||
unsigned int cmd_ring_reserved_trbs;
|
||||
struct xhci_ring *event_ring;
|
||||
struct xhci_erst erst;
|
||||
/* Scratchpad */
|
||||
@@ -1058,6 +1087,9 @@ struct xhci_hcd {
|
||||
int noops_submitted;
|
||||
int noops_handled;
|
||||
int error_bitmask;
|
||||
unsigned int quirks;
|
||||
#define XHCI_LINK_TRB_QUIRK (1 << 0)
|
||||
#define XHCI_RESET_EP_QUIRK (1 << 1)
|
||||
};
|
||||
|
||||
/* For testing purposes */
|
||||
@@ -1136,6 +1168,13 @@ static inline void xhci_write_64(struct xhci_hcd *xhci,
|
||||
writel(val_hi, ptr + 1);
|
||||
}
|
||||
|
||||
static inline int xhci_link_trb_quirk(struct xhci_hcd *xhci)
|
||||
{
|
||||
u32 temp = xhci_readl(xhci, &xhci->cap_regs->hc_capbase);
|
||||
return ((HC_VERSION(temp) == 0x95) &&
|
||||
(xhci->quirks & XHCI_LINK_TRB_QUIRK));
|
||||
}
|
||||
|
||||
/* xHCI debugging */
|
||||
void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int set_num);
|
||||
void xhci_print_registers(struct xhci_hcd *xhci);
|
||||
@@ -1150,7 +1189,7 @@ void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci);
|
||||
void xhci_dbg_ring_ptrs(struct xhci_hcd *xhci, struct xhci_ring *ring);
|
||||
void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int last_ep);
|
||||
|
||||
/* xHCI memory managment */
|
||||
/* xHCI memory management */
|
||||
void xhci_mem_cleanup(struct xhci_hcd *xhci);
|
||||
int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags);
|
||||
void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id);
|
||||
@@ -1158,11 +1197,24 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, struct usb_device
|
||||
int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udev);
|
||||
unsigned int xhci_get_endpoint_index(struct usb_endpoint_descriptor *desc);
|
||||
unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc);
|
||||
unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index);
|
||||
unsigned int xhci_last_valid_endpoint(u32 added_ctxs);
|
||||
void xhci_endpoint_zero(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, struct usb_host_endpoint *ep);
|
||||
void xhci_endpoint_copy(struct xhci_hcd *xhci,
|
||||
struct xhci_container_ctx *in_ctx,
|
||||
struct xhci_container_ctx *out_ctx,
|
||||
unsigned int ep_index);
|
||||
void xhci_slot_copy(struct xhci_hcd *xhci,
|
||||
struct xhci_container_ctx *in_ctx,
|
||||
struct xhci_container_ctx *out_ctx);
|
||||
int xhci_endpoint_init(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev,
|
||||
struct usb_device *udev, struct usb_host_endpoint *ep,
|
||||
gfp_t mem_flags);
|
||||
void xhci_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring);
|
||||
struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci,
|
||||
bool allocate_completion, gfp_t mem_flags);
|
||||
void xhci_free_command(struct xhci_hcd *xhci,
|
||||
struct xhci_command *command);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
/* xHCI PCI glue */
|
||||
@@ -1182,6 +1234,8 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd);
|
||||
int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev);
|
||||
void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev);
|
||||
int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev);
|
||||
int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
|
||||
struct usb_tt *tt, gfp_t mem_flags);
|
||||
int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags);
|
||||
int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status);
|
||||
int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep);
|
||||
@@ -1205,7 +1259,11 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
|
||||
int slot_id, unsigned int ep_index);
|
||||
int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
|
||||
int slot_id, unsigned int ep_index);
|
||||
int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
|
||||
int slot_id, unsigned int ep_index);
|
||||
int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
|
||||
u32 slot_id, bool command_must_succeed);
|
||||
int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
|
||||
u32 slot_id);
|
||||
int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id,
|
||||
unsigned int ep_index);
|
||||
@@ -1213,8 +1271,13 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
|
||||
unsigned int slot_id, unsigned int ep_index,
|
||||
struct xhci_td *cur_td, struct xhci_dequeue_state *state);
|
||||
void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
|
||||
struct xhci_ring *ep_ring, unsigned int slot_id,
|
||||
unsigned int ep_index, struct xhci_dequeue_state *deq_state);
|
||||
unsigned int slot_id, unsigned int ep_index,
|
||||
struct xhci_dequeue_state *deq_state);
|
||||
void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
|
||||
struct usb_device *udev, unsigned int ep_index);
|
||||
void xhci_queue_config_ep_quirk(struct xhci_hcd *xhci,
|
||||
unsigned int slot_id, unsigned int ep_index,
|
||||
struct xhci_dequeue_state *deq_state);
|
||||
|
||||
/* xHCI roothub code */
|
||||
int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
|
||||
|
Verwijs in nieuw issue
Block a user