ChangeSet 1.1713.7.2, 2004/04/02 09:56:28-08:00, [EMAIL PROTECTED]
[PATCH] USB: ehci updates: CONFIG_PCI, integrated TT
Generalize the driver a bit:
- PCI-specific handling is restricted to a small chunk of
init code. Non-PCI implementations are in the pipeline.
- Merge support from ARC International (Craig Nadler) for
their integrated root hub transaction translators (on PCI).
Other implementations should be similar.
drivers/usb/host/Kconfig | 11 +++++++++
drivers/usb/host/ehci-dbg.c | 6 +++--
drivers/usb/host/ehci-hcd.c | 50 ++++++++++++++++++++++++++++++++++++--------
drivers/usb/host/ehci-hub.c | 18 ++++++++++++++-
drivers/usb/host/ehci-q.c | 15 ++++++++++---
drivers/usb/host/ehci.h | 40 +++++++++++++++++++++++++++++++++++
include/linux/pci_ids.h | 3 ++
7 files changed, 127 insertions(+), 16 deletions(-)
diff -Nru a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
--- a/drivers/usb/host/Kconfig Wed Apr 14 14:34:12 2004
+++ b/drivers/usb/host/Kconfig Wed Apr 14 14:34:12 2004
@@ -38,6 +38,17 @@
EHCI or USB 2.0 transaction translator implementations.
It should work for ISO-OUT transfers, like audio.
+config USB_EHCI_ROOT_HUB_TT
+ bool "Root Hub Transaction Translators (EXPERIMENTAL)"
+ depends on USB_EHCI_HCD && EXPERIMENTAL
+ ---help---
+ Some EHCI chips have vendor-specific extensions to integrate
+ transaction translators, so that no OHCI or UHCI companion
+ controller is needed. It's safe to say "y" even if your
+ controller doesn't support this feature.
+
+ This supports the EHCI implementation from ARC International.
+
config USB_OHCI_HCD
tristate "OHCI HCD support"
depends on USB
diff -Nru a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
--- a/drivers/usb/host/ehci-dbg.c Wed Apr 14 14:34:12 2004
+++ b/drivers/usb/host/ehci-dbg.c Wed Apr 14 14:34:12 2004
@@ -628,8 +628,10 @@
/* Capability Registers */
i = HC_VERSION(readl (&ehci->caps->hc_capbase));
temp = scnprintf (next, size,
- "PCI device %s\nEHCI %x.%02x, hcd state %d (driver " DRIVER_VERSION
")\n",
- pci_name(to_pci_dev(hcd->self.controller)),
+ "bus %s device %s\n"
+ "EHCI %x.%02x, hcd state %d (driver " DRIVER_VERSION ")\n",
+ hcd->self.controller->bus->name,
+ hcd->self.controller->bus_id,
i >> 8, i & 0x0ff, ehci->hcd.state);
size -= temp;
next += temp;
diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
--- a/drivers/usb/host/ehci-hcd.c Wed Apr 14 14:34:12 2004
+++ b/drivers/usb/host/ehci-hcd.c Wed Apr 14 14:34:12 2004
@@ -279,6 +279,8 @@
spin_unlock_irqrestore (&ehci->lock, flags);
}
+#ifdef CONFIG_PCI
+
/* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/...
* off the controller (maybe it can boot from highspeed USB disks).
*/
@@ -307,6 +309,8 @@
return 0;
}
+#endif
+
static int
ehci_reboot (struct notifier_block *self, unsigned long code, void *null)
{
@@ -335,8 +339,12 @@
dbg_hcs_params (ehci, "reset");
dbg_hcc_params (ehci, "reset");
+#ifdef CONFIG_PCI
/* EHCI 0.96 and later may have "extended capabilities" */
- temp = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params));
+ if (hcd->self.controller->bus == &pci_bus_type)
+ temp = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params));
+ else
+ temp = 0;
while (temp) {
u32 cap;
@@ -356,6 +364,7 @@
}
temp = (cap >> 8) & 0xff;
}
+#endif
/* cache this readonly data; minimize PCI reads */
ehci->hcs_params = readl (&ehci->caps->hcs_params);
@@ -372,7 +381,7 @@
struct usb_bus *bus;
int retval;
u32 hcc_params;
- u8 tempbyte;
+ u8 sbrn = 0;
init_timer (&ehci->watchdog);
ehci->watchdog.function = ehci_watchdog;
@@ -406,6 +415,29 @@
writel (INTR_MASK, &ehci->regs->intr_enable);
writel (ehci->periodic_dma, &ehci->regs->frame_list);
+#ifdef CONFIG_PCI
+ if (hcd->self.controller->bus == &pci_bus_type) {
+ struct pci_dev *pdev;
+
+ pdev = to_pci_dev(hcd->self.controller);
+
+ /* Serial Bus Release Number is at PCI 0x60 offset */
+ pci_read_config_byte(pdev, 0x60, &sbrn);
+
+ /* help hc dma work well with cachelines */
+ pci_set_mwi (pdev);
+
+ /* chip-specific init */
+ switch (pdev->vendor) {
+ case PCI_VENDOR_ID_ARC:
+ if (pdev->device == PCI_DEVICE_ID_ARC_EHCI)
+ ehci->is_arc_rh_tt = 1;
+ break;
+ }
+
+ }
+#endif
+
/*
* dedicate a qh for the async ring head, since we couldn't unlink
* a 'real' qh without stopping the async schedule [4.8]. use it
@@ -443,9 +475,6 @@
#endif
}
- /* help hc dma work well with cachelines */
- pci_set_mwi (to_pci_dev(ehci->hcd.self.controller));
-
/* clear interrupt enables, set irq latency */
temp = readl (&ehci->regs->command) & 0x0fff;
if (log2_irq_thresh < 0 || log2_irq_thresh > 6)
@@ -493,12 +522,10 @@
writel (FLAG_CF, &ehci->regs->configured_flag);
readl (&ehci->regs->command); /* unblock posted write */
- /* PCI Serial Bus Release Number is at 0x60 offset */
- pci_read_config_byte(to_pci_dev(hcd->self.controller), 0x60, &tempbyte);
temp = HC_VERSION(readl (&ehci->caps->hc_capbase));
ehci_info (ehci,
"USB %x.%x enabled, EHCI %x.%02x, driver %s\n",
- ((tempbyte & 0xf0)>>4), (tempbyte & 0x0f),
+ ((sbrn & 0xf0)>>4), (sbrn & 0x0f),
temp >> 8, temp & 0xff, DRIVER_VERSION);
/*
@@ -995,7 +1022,9 @@
/*-------------------------------------------------------------------------*/
-/* EHCI spec says PCI is required. */
+/* EHCI 1.0 doesn't require PCI */
+
+#ifdef CONFIG_PCI
/* PCI driver selection metadata; PCI hotplugging uses this */
static const struct pci_device_id pci_ids [] = { {
@@ -1020,6 +1049,9 @@
.resume = usb_hcd_pci_resume,
#endif
};
+
+#endif /* PCI */
+
#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
diff -Nru a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
--- a/drivers/usb/host/ehci-hub.c Wed Apr 14 14:34:12 2004
+++ b/drivers/usb/host/ehci-hub.c Wed Apr 14 14:34:12 2004
@@ -40,6 +40,15 @@
/* if reset finished and it's still not enabled -- handoff */
if (!(port_status & PORT_PE)) {
+
+ /* with integrated TT, there's nobody to hand it to! */
+ if (ehci_is_ARC(ehci)) {
+ ehci_dbg (ehci,
+ "Failed to enable port %d on root hub TT\n",
+ index+1);
+ return port_status;
+ }
+
ehci_dbg (ehci, "port %d full speed --> companion\n",
index + 1);
@@ -257,7 +266,8 @@
if (!(temp & PORT_OWNER)) {
if (temp & PORT_CONNECT) {
status |= 1 << USB_PORT_FEAT_CONNECTION;
- status |= 1 << USB_PORT_FEAT_HIGHSPEED;
+ // status may be from integrated TT
+ status |= ehci_port_speed(ehci, temp);
}
if (temp & PORT_PE)
status |= 1 << USB_PORT_FEAT_ENABLE;
@@ -307,8 +317,12 @@
&ehci->regs->port_status [wIndex]);
break;
case USB_PORT_FEAT_RESET:
- /* line status bits may report this as low speed */
+ /* line status bits may report this as low speed,
+ * which can be fine if this root hub has a
+ * transaction translator built in.
+ */
if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT
+ && !ehci_is_ARC(ehci)
&& PORT_USB11 (temp)) {
ehci_dbg (ehci,
"port %d low speed --> companion\n",
diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
--- a/drivers/usb/host/ehci-q.c Wed Apr 14 14:34:12 2004
+++ b/drivers/usb/host/ehci-q.c Wed Apr 14 14:34:12 2004
@@ -165,7 +165,10 @@
/* if async CSPLIT failed, try cleaning out the TT buffer */
} else if (urb->dev->tt && !usb_pipeint (urb->pipe)
&& ((token & QTD_STS_MMF) != 0
- || QTD_CERR(token) == 0)) {
+ || QTD_CERR(token) == 0)
+ && (!ehci_is_ARC(ehci)
+ || urb->dev->tt->hub !=
+ ehci->hcd.self.root_hub)) {
#ifdef DEBUG
struct usb_device *tt = urb->dev->tt->hub;
dev_dbg (&tt->dev,
@@ -576,7 +579,7 @@
// when each interface/altsetting is established. Unlink
// any previous qh and cancel its urbs first; endpoints are
// implicitly reset then (data toggle too).
-// That'd mean updating how usbcore talks to HCDs. (2.5?)
+// That'd mean updating how usbcore talks to HCDs. (2.7?)
/*
@@ -674,7 +677,13 @@
info2 |= (EHCI_TUNE_MULT_TT << 30);
info2 |= urb->dev->ttport << 23;
- info2 |= urb->dev->tt->hub->devnum << 16;
+
+ /* set the address of the TT; for ARC's integrated
+ * root hub tt, leave it zeroed.
+ */
+ if (!ehci_is_ARC(ehci)
+ || urb->dev->tt->hub != ehci->hcd.self.root_hub)
+ info2 |= urb->dev->tt->hub->devnum << 16;
/* NOTE: if (PIPE_INTERRUPT) { scheduler sets c-mask } */
diff -Nru a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
--- a/drivers/usb/host/ehci.h Wed Apr 14 14:34:12 2004
+++ b/drivers/usb/host/ehci.h Wed Apr 14 14:34:12 2004
@@ -85,6 +85,8 @@
unsigned long actions;
unsigned stamp;
+ unsigned is_arc_rh_tt:1; /* ARC roothub with TT */
+
/* irq statistics */
#ifdef EHCI_STATS
struct ehci_stats stats;
@@ -549,6 +551,44 @@
dma_addr_t fstn_dma;
union ehci_shadow fstn_next; /* ptr to periodic q entry */
} __attribute__ ((aligned (32)));
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_USB_EHCI_ROOT_HUB_TT
+
+/*
+ * Some EHCI controllers have a Transaction Translator built into the
+ * root hub. This is a non-standard feature. Each controller will need
+ * to add code to the following inline functions, and call them as
+ * needed (mostly in root hub code).
+ */
+
+#define ehci_is_ARC(e) ((e)->is_arc_rh_tt)
+
+/* Returns the speed of a device attached to a port on the root hub. */
+static inline unsigned int
+ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
+{
+ if (ehci_is_ARC(ehci)) {
+ switch ((portsc>>26)&3) {
+ case 0:
+ return 0;
+ case 1:
+ return (1<<USB_PORT_FEAT_LOWSPEED);
+ case 2:
+ default:
+ return (1<<USB_PORT_FEAT_HIGHSPEED);
+ }
+ }
+ return (1<<USB_PORT_FEAT_HIGHSPEED);
+}
+
+#else
+
+#define ehci_is_ARC(e) (0)
+
+#define ehci_port_speed(ehci, portsc) (1<<USB_PORT_FEAT_HIGHSPEED)
+#endif
/*-------------------------------------------------------------------------*/
diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h
--- a/include/linux/pci_ids.h Wed Apr 14 14:34:12 2004
+++ b/include/linux/pci_ids.h Wed Apr 14 14:34:12 2004
@@ -1870,6 +1870,9 @@
#define PCI_DEVICE_ID_ALTIMA_AC9100 0x03ea
#define PCI_DEVICE_ID_ALTIMA_AC1003 0x03eb
+#define PCI_VENDOR_ID_ARC 0x192E
+#define PCI_DEVICE_ID_ARC_EHCI 0x0101
+
#define PCI_VENDOR_ID_SYMPHONY 0x1c1c
#define PCI_DEVICE_ID_SYMPHONY_101 0x0001
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id70&alloc_id638&op=click
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel