diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-01-08 16:24:38 +1100 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-01-08 16:24:38 +1100 |
commit | 24f030175d30f019be41766cdf88c2ff03de19ff (patch) | |
tree | 354232a84e82d5a721ed7b1a9af580ff2a59be8f /drivers/usb/host | |
parent | 4aa12f7b927c3cac0e0cf3503642597527d0ece0 (diff) | |
parent | 9e42d0cf5020aaf217433cad1a224745241d212a (diff) |
Merge commit 'origin/master' into next
Diffstat (limited to 'drivers/usb/host')
32 files changed, 5026 insertions, 385 deletions
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index f3a75a929e0..2b476b6b3d4 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -96,6 +96,19 @@ config USB_EHCI_HCD_PPC_OF Enables support for the USB controller present on the PowerPC OpenFirmware platform bus. +config USB_OXU210HP_HCD + tristate "OXU210HP HCD support" + depends on USB + ---help--- + The OXU210HP is an USB host/OTG/device controller. Enable this + option if your board has this chip. If unsure, say N. + + This driver does not support isochronous transfers and doesn't + implement OTG nor USB device controllers. + + To compile this driver as a module, choose M here: the + module will be called oxu210hp-hcd. + config USB_ISP116X_HCD tristate "ISP116X HCD support" depends on USB diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 23be2222404..e5f3f20787e 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_USB_WHCI_HCD) += whci/ 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_OHCI_HCD) += ohci-hcd.o obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 0cb53ca8d34..7f4ace73d44 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -455,9 +455,7 @@ static void qh_lines ( (scratch >> 16) & 0x7fff, scratch, td->urb); - if (temp < 0) - temp = 0; - else if (size < temp) + if (size < temp) temp = size; size -= temp; next += temp; @@ -466,9 +464,7 @@ static void qh_lines ( } temp = snprintf (next, size, "\n"); - if (temp < 0) - temp = 0; - else if (size < temp) + if (size < temp) temp = size; size -= temp; next += temp; diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 218f9660d7e..97a53a48a3d 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -194,6 +194,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd) u32 temp; u32 power_okay; int i; + u8 resume_needed = 0; if (time_before (jiffies, ehci->next_statechange)) msleep(5); @@ -228,7 +229,9 @@ static int ehci_bus_resume (struct usb_hcd *hcd) /* Some controller/firmware combinations need a delay during which * they set up the port statuses. See Bugzilla #8190. */ - mdelay(8); + spin_unlock_irq(&ehci->lock); + msleep(8); + spin_lock_irq(&ehci->lock); /* manually resume the ports we suspended during bus_suspend() */ i = HCS_N_PORTS (ehci->hcs_params); @@ -236,12 +239,21 @@ static int ehci_bus_resume (struct usb_hcd *hcd) temp = ehci_readl(ehci, &ehci->regs->port_status [i]); temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); if (test_bit(i, &ehci->bus_suspended) && - (temp & PORT_SUSPEND)) + (temp & PORT_SUSPEND)) { temp |= PORT_RESUME; + resume_needed = 1; + } ehci_writel(ehci, temp, &ehci->regs->port_status [i]); } + + /* msleep for 20ms only if code is trying to resume port */ + if (resume_needed) { + spin_unlock_irq(&ehci->lock); + msleep(20); + spin_lock_irq(&ehci->lock); + } + i = HCS_N_PORTS (ehci->hcs_params); - mdelay (20); while (i--) { temp = ehci_readl(ehci, &ehci->regs->port_status [i]); if (test_bit(i, &ehci->bus_suspended) && @@ -422,8 +434,15 @@ static int check_reset_complete ( port_status &= ~PORT_RWC_BITS; ehci_writel(ehci, port_status, status_reg); - } else + /* ensure 440EPX ohci controller state is operational */ + if (ehci->has_amcc_usb23) + set_ohci_hcfs(ehci, 1); + } else { ehci_dbg (ehci, "port %d high speed\n", index + 1); + /* ensure 440EPx ohci controller state is suspended */ + if (ehci->has_amcc_usb23) + set_ohci_hcfs(ehci, 0); + } return port_status; } diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 36864f95844..bdc6e86e1f8 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -219,15 +219,19 @@ static int ehci_pci_setup(struct usb_hcd *hcd) /* Serial Bus Release Number is at PCI 0x60 offset */ pci_read_config_byte(pdev, 0x60, &ehci->sbrn); - /* Workaround current PCI init glitch: wakeup bits aren't - * being set from PCI PM capability. + /* Keep this around for a while just in case some EHCI + * implementation uses legacy PCI PM support. This test + * can be removed on 17 Dec 2009 if the dev_warn() hasn't + * been triggered by then. */ if (!device_can_wakeup(&pdev->dev)) { u16 port_wake; pci_read_config_word(pdev, 0x62, &port_wake); - if (port_wake & 0x0001) + if (port_wake & 0x0001) { + dev_warn(&pdev->dev, "Enabling legacy PCI PM\n"); device_init_wakeup(&pdev->dev, 1); + } } #ifdef CONFIG_USB_SUSPEND @@ -428,6 +432,8 @@ static struct pci_driver ehci_pci_driver = { #ifdef CONFIG_PM .suspend = usb_hcd_pci_suspend, + .suspend_late = usb_hcd_pci_suspend_late, + .resume_early = usb_hcd_pci_resume_early, .resume = usb_hcd_pci_resume, #endif .shutdown = usb_hcd_pci_shutdown, diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index b018deed2e8..ef732b704f5 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c @@ -107,11 +107,13 @@ ehci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dn = op->node; struct usb_hcd *hcd; - struct ehci_hcd *ehci; + struct ehci_hcd *ehci = NULL; struct resource res; int irq; int rv; + struct device_node *np; + if (usb_disabled()) return -ENODEV; @@ -149,6 +151,20 @@ ehci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) } ehci = hcd_to_ehci(hcd); + np = of_find_compatible_node(NULL, NULL, "ibm,usb-ohci-440epx"); + if (np != NULL) { + /* claim we really affected by usb23 erratum */ + if (!of_address_to_resource(np, 0, &res)) + ehci->ohci_hcctrl_reg = ioremap(res.start + + OHCI_HCCTRL_OFFSET, OHCI_HCCTRL_LEN); + else + pr_debug(__FILE__ ": no ohci offset in fdt\n"); + if (!ehci->ohci_hcctrl_reg) { + pr_debug(__FILE__ ": ioremap for ohci hcctrl failed\n"); + } else { + ehci->has_amcc_usb23 = 1; + } + } if (of_get_property(dn, "big-endian", NULL)) { ehci->big_endian_mmio = 1; @@ -181,6 +197,9 @@ err_ioremap: irq_dispose_mapping(irq); err_irq: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + + if (ehci->has_amcc_usb23) + iounmap(ehci->ohci_hcctrl_reg); err_rmr: usb_put_hcd(hcd); @@ -191,6 +210,11 @@ err_rmr: static int ehci_hcd_ppc_of_remove(struct of_device *op) { struct usb_hcd *hcd = dev_get_drvdata(&op->dev); + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + + struct device_node *np; + struct resource res; + dev_set_drvdata(&op->dev, NULL); dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n"); @@ -201,6 +225,25 @@ static int ehci_hcd_ppc_of_remove(struct of_device *op) irq_dispose_mapping(hcd->irq); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + /* use request_mem_region to test if the ohci driver is loaded. if so + * ensure the ohci core is operational. + */ + if (ehci->has_amcc_usb23) { + np = of_find_compatible_node(NULL, NULL, "ibm,usb-ohci-440epx"); + if (np != NULL) { + if (!of_address_to_resource(np, 0, &res)) + if (!request_mem_region(res.start, + 0x4, hcd_name)) + set_ohci_hcfs(ehci, 1); + else + release_mem_region(res.start, 0x4); + else + pr_debug(__FILE__ ": no ohci offset in fdt\n"); + of_node_put(np); + } + + iounmap(ehci->ohci_hcctrl_reg); + } usb_put_hcd(hcd); return 0; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index c7d4b5a06bd..fb7054ccf4f 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -120,6 +120,16 @@ struct ehci_hcd { /* one per controller */ unsigned has_fsl_port_bug:1; /* FreeScale */ unsigned big_endian_mmio:1; unsigned big_endian_desc:1; + unsigned has_amcc_usb23:1; + + /* required for usb32 quirk */ + #define OHCI_CTRL_HCFS (3 << 6) + #define OHCI_USB_OPER (2 << 6) + #define OHCI_USB_SUSPEND (3 << 6) + + #define OHCI_HCCTRL_OFFSET 0x4 + #define OHCI_HCCTRL_LEN 0x4 + __hc32 *ohci_hcctrl_reg; u8 sbrn; /* packed release number */ @@ -636,6 +646,30 @@ static inline void ehci_writel(const struct ehci_hcd *ehci, #endif } +/* + * On certain ppc-44x SoC there is a HW issue, that could only worked around with + * explicit suspend/operate of OHCI. This function hereby makes sense only on that arch. + * Other common bits are dependant on has_amcc_usb23 quirk flag. + */ +#ifdef CONFIG_44x +static inline void set_ohci_hcfs(struct ehci_hcd *ehci, int operational) +{ + u32 hc_control; + + hc_control = (readl_be(ehci->ohci_hcctrl_reg) & ~OHCI_CTRL_HCFS); + if (operational) + hc_control |= OHCI_USB_OPER; + else + hc_control |= OHCI_USB_SUSPEND; + + writel_be(hc_control, ehci->ohci_hcctrl_reg); + (void) readl_be(ehci->ohci_hcctrl_reg); +} +#else +static inline void set_ohci_hcfs(struct ehci_hcd *ehci, int operational) +{ } +#endif + /*-------------------------------------------------------------------------*/ /* diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c index 64be4d88df1..8582236e4ca 100644 --- a/drivers/usb/host/hwa-hc.c +++ b/drivers/usb/host/hwa-hc.c @@ -54,7 +54,6 @@ * DWA). */ #include <linux/kernel.h> -#include <linux/version.h> #include <linux/init.h> #include <linux/module.h> #include <linux/workqueue.h> @@ -63,16 +62,12 @@ #include "../wusbcore/wa-hc.h" #include "../wusbcore/wusbhc.h" -#define D_LOCAL 0 -#include <linux/uwb/debug.h> - struct hwahc { struct wusbhc wusbhc; /* has to be 1st */ struct wahc wa; - u8 buffer[16]; /* for misc usb transactions */ }; -/** +/* * FIXME should be wusbhc * * NOTE: we need to cache the Cluster ID because later...there is no @@ -126,7 +121,6 @@ static int hwahc_op_reset(struct usb_hcd *usb_hcd) struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); struct device *dev = &hwahc->wa.usb_iface->dev; - d_fnstart(4, dev, "(hwahc %p)\n", hwahc); mutex_lock(&wusbhc->mutex); wa_nep_disarm(&hwahc->wa); result = __wa_set_feature(&hwahc->wa, WA_RESET); @@ -134,7 +128,6 @@ static int hwahc_op_reset(struct usb_hcd *usb_hcd) dev_err(dev, "error commanding HC to reset: %d\n", result); goto error_unlock; } - d_printf(3, dev, "reset: waiting for device to change state\n"); result = __wa_wait_status(&hwahc->wa, WA_STATUS_RESETTING, 0); if (result < 0) { dev_err(dev, "error waiting for HC to reset: %d\n", result); @@ -142,7 +135,6 @@ static int hwahc_op_reset(struct usb_hcd *usb_hcd) } error_unlock: mutex_unlock(&wusbhc->mutex); - d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result); return result; } @@ -155,15 +147,9 @@ static int hwahc_op_start(struct usb_hcd *usb_hcd) int result; struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); - struct device *dev = &hwahc->wa.usb_iface->dev; - /* Set up a Host Info WUSB Information Element */ - d_fnstart(4, dev, "(hwahc %p)\n", hwahc); result = -ENOSPC; mutex_lock(&wusbhc->mutex); - /* Start the numbering from the top so that the bottom - * range of the unauth addr space is used for devices, - * the top for HCs; use 0xfe - RC# */ addr = wusb_cluster_id_get(); if (addr == 0) goto error_cluster_id_get; @@ -171,22 +157,14 @@ static int hwahc_op_start(struct usb_hcd *usb_hcd) if (result < 0) goto error_set_cluster_id; - result = wa_nep_arm(&hwahc->wa, GFP_KERNEL); - if (result < 0) { - dev_err(dev, "cannot listen to notifications: %d\n", result); - goto error_stop; - } usb_hcd->uses_new_polling = 1; usb_hcd->poll_rh = 1; usb_hcd->state = HC_STATE_RUNNING; result = 0; out: mutex_unlock(&wusbhc->mutex); - d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result); return result; -error_stop: - __wa_stop(&hwahc->wa); error_set_cluster_id: wusb_cluster_id_put(wusbhc->cluster_id); error_cluster_id_get: @@ -194,39 +172,6 @@ error_cluster_id_get: } -/* - * FIXME: break this function up - */ -static int __hwahc_op_wusbhc_start(struct wusbhc *wusbhc) -{ - int result; - struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); - struct device *dev = &hwahc->wa.usb_iface->dev; - - /* Set up a Host Info WUSB Information Element */ - d_fnstart(4, dev, "(hwahc %p)\n", hwahc); - result = -ENOSPC; - - result = __wa_set_feature(&hwahc->wa, WA_ENABLE); - if (result < 0) { - dev_err(dev, "error commanding HC to start: %d\n", result); - goto error_stop; - } - result = __wa_wait_status(&hwahc->wa, WA_ENABLE, WA_ENABLE); - if (result < 0) { - dev_err(dev, "error waiting for HC to start: %d\n", result); - goto error_stop; - } - result = 0; -out: - d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result); - return result; - -error_stop: - result = __wa_clear_feature(&hwahc->wa, WA_ENABLE); - goto out; -} - static int hwahc_op_suspend(struct usb_hcd *usb_hcd, pm_message_t msg) { struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); @@ -246,18 +191,6 @@ static int hwahc_op_resume(struct usb_hcd *usb_hcd) return -ENOSYS; } -static void __hwahc_op_wusbhc_stop(struct wusbhc *wusbhc) -{ - int result; - struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); - struct device *dev = &hwahc->wa.usb_iface->dev; - - d_fnstart(4, dev, "(hwahc %p)\n", hwahc); - /* Nothing for now */ - d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result); - return; -} - /* * No need to abort pipes, as when this is called, all the children * has been disconnected and that has done it [through @@ -266,21 +199,11 @@ static void __hwahc_op_wusbhc_stop(struct wusbhc *wusbhc) */ static void hwahc_op_stop(struct usb_hcd *usb_hcd) { - int result; struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); - struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); - struct wahc *wa = &hwahc->wa; - struct device *dev = &wa->usb_iface->dev; - d_fnstart(4, dev, "(hwahc %p)\n", hwahc); mutex_lock(&wusbhc->mutex); - wusbhc_stop(wusbhc); - wa_nep_disarm(&hwahc->wa); - result = __wa_stop(&hwahc->wa); wusb_cluster_id_put(wusbhc->cluster_id); mutex_unlock(&wusbhc->mutex); - d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result); - return; } static int hwahc_op_get_frame_number(struct usb_hcd *usb_hcd) @@ -325,6 +248,54 @@ static void hwahc_op_endpoint_disable(struct usb_hcd *usb_hcd, rpipe_ep_disable(&hwahc->wa, ep); } +static int __hwahc_op_wusbhc_start(struct wusbhc *wusbhc) +{ + int result; + struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); + struct device *dev = &hwahc->wa.usb_iface->dev; + + result = __wa_set_feature(&hwahc->wa, WA_ENABLE); + if (result < 0) { + dev_err(dev, "error commanding HC to start: %d\n", result); + goto error_stop; + } + result = __wa_wait_status(&hwahc->wa, WA_ENABLE, WA_ENABLE); + if (result < 0) { + dev_err(dev, "error waiting for HC to start: %d\n", result); + goto error_stop; + } + result = wa_nep_arm(&hwahc->wa, GFP_KERNEL); + if (result < 0) { + dev_err(dev, "cannot listen to notifications: %d\n", result); + goto error_stop; + } + return result; + +error_stop: + __wa_clear_feature(&hwahc->wa, WA_ENABLE); + return result; +} + +static void __hwahc_op_wusbhc_stop(struct wusbhc *wusbhc, int delay) +{ + struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); + struct wahc *wa = &hwahc->wa; + u8 iface_no = wa->usb_iface->cur_altsetting->desc.bInterfaceNumber; + int ret; + + ret = usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0), + WUSB_REQ_CHAN_STOP, + USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + delay * 1000, + iface_no, + NULL, 0, 1000 /* FIXME: arbitrary */); + if (ret == 0) + msleep(delay); + + wa_nep_disarm(&hwahc->wa); + __wa_stop(&hwahc->wa); +} + /* * Set the UWB MAS allocation for the WUSB cluster * @@ -581,11 +552,11 @@ static int wa_fill_descr(struct wahc *wa) itr_size = le16_to_cpu(usb_dev->actconfig->desc.wTotalLength); while (itr_size >= sizeof(*hdr)) { hdr = (struct usb_descriptor_header *) itr; - d_printf(3, dev, "Extra device descriptor: " - "type %02x/%u bytes @ %zu (%zu left)\n", - hdr->bDescriptorType, hdr->bLength, - (itr - usb_dev->rawdescriptors[actconfig_idx]), - itr_size); + dev_dbg(dev, "Extra device descriptor: " + "type %02x/%u bytes @ %zu (%zu left)\n", + hdr->bDescriptorType, hdr->bLength, + (itr - usb_dev->rawdescriptors[actconfig_idx]), + itr_size); if (hdr->bDescriptorType == USB_DT_WIRE_ADAPTER) goto found; itr += hdr->bLength; @@ -794,7 +765,6 @@ static void hwahc_destroy(struct hwahc *hwahc) { struct wusbhc *wusbhc = &hwahc->wusbhc; - d_fnstart(1, NULL, "(hwahc %p)\n", hwahc); mutex_lock(&wusbhc->mutex); __wa_destroy(&hwahc->wa); wusbhc_destroy(&hwahc->wusbhc); @@ -804,7 +774,6 @@ static void hwahc_destroy(struct hwahc *hwahc) usb_put_intf(hwahc->wa.usb_iface); usb_put_dev(hwahc->wa.usb_dev); mutex_unlock(&wusbhc->mutex); - d_fnend(1, NULL, "(hwahc %p) = void\n", hwahc); } static void hwahc_init(struct hwahc *hwahc) @@ -821,7 +790,6 @@ static int hwahc_probe(struct usb_interface *usb_iface, struct hwahc *hwahc; struct device *dev = &usb_iface->dev; - d_fnstart(4, dev, "(%p, %p)\n", usb_iface, id); result = -ENOMEM; usb_hcd = usb_create_hcd(&hwahc_hc_driver, &usb_iface->dev, "wusb-hwa"); if (usb_hcd == NULL) { @@ -848,7 +816,6 @@ static int hwahc_probe(struct usb_interface *usb_iface, dev_err(dev, "Cannot setup phase B of WUSBHC: %d\n", result); goto error_wusbhc_b_create; } - d_fnend(4, dev, "(%p, %p) = 0\n", usb_iface, id); return 0; error_wusbhc_b_create: @@ -858,7 +825,6 @@ error_add_hcd: error_hwahc_create: usb_put_hcd(usb_hcd); error_alloc: - d_fnend(4, dev, "(%p, %p) = %d\n", usb_iface, id, result); return result; } @@ -872,16 +838,12 @@ static void hwahc_disconnect(struct usb_interface *usb_iface) wusbhc = usb_hcd_to_wusbhc(usb_hcd); hwahc = container_of(wusbhc, struct hwahc, wusbhc); - d_fnstart(1, NULL, "(hwahc %p [usb_iface %p])\n", hwahc, usb_iface); wusbhc_b_destroy(&hwahc->wusbhc); usb_remove_hcd(usb_hcd); hwahc_destroy(hwahc); usb_put_hcd(usb_hcd); - d_fnend(1, NULL, "(hwahc %p [usb_iface %p]) = void\n", hwahc, - usb_iface); } -/** USB device ID's that we handle */ static struct usb_device_id hwahc_id_table[] = { /* FIXME: use class labels for this */ { USB_INTERFACE_INFO(0xe0, 0x02, 0x01), }, @@ -898,18 +860,7 @@ static struct usb_driver hwahc_driver = { static int __init hwahc_driver_init(void) { - int result; - result = usb_register(&hwahc_driver); - if (result < 0) { - printk(KERN_ERR "WA-CDS: Cannot register USB driver: %d\n", - result); - goto error_usb_register; - } - return 0; - -error_usb_register: - return result; - + return usb_register(&hwahc_driver); } module_init(hwahc_driver_init); diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 8017f1cf78e..b899f1a59c2 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -435,14 +435,13 @@ static int isp1760_hc_setup(struct usb_hcd *hcd) /* * PORT 1 Control register of the ISP1760 is the OTG control - * register on ISP1761. + * register on ISP1761. Since there is no OTG or device controller + * support in this driver, we use port 1 as a "normal" USB host port on + * both chips. */ - if (!(priv->devflags & ISP1760_FLAG_ISP1761) && - !(priv->devflags & ISP1760_FLAG_PORT1_DIS)) { - isp1760_writel(PORT1_POWER | PORT1_INIT2, - hcd->regs + HC_PORT1_CTRL); - mdelay(10); - } + isp1760_writel(PORT1_POWER | PORT1_INIT2, + hcd->regs + HC_PORT1_CTRL); + mdelay(10); priv->hcs_params = isp1760_readl(hcd->regs + HC_HCSPARAMS); diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h index 4377277667d..a9daea58796 100644 --- a/drivers/usb/host/isp1760-hcd.h +++ b/drivers/usb/host/isp1760-hcd.h @@ -135,7 +135,6 @@ typedef void (packet_enqueue)(struct usb_hcd *hcd, struct isp1760_qh *qh, * indicate the most "atypical" case, so that a devflags of 0 is * a sane default configuration. */ -#define ISP1760_FLAG_PORT1_DIS 0x00000001 /* Port 1 disabled */ #define ISP1760_FLAG_BUS_WIDTH_16 0x00000002 /* 16-bit data bus width */ #define ISP1760_FLAG_OTG_EN 0x00000004 /* Port 1 supports OTG */ #define ISP1760_FLAG_ANALOG_OC 0x00000008 /* Analog overcurrent */ diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index b87ca7cf4b3..4cf7ca428b3 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -60,9 +60,6 @@ static int of_isp1760_probe(struct of_device *dev, if (of_device_is_compatible(dp, "nxp,usb-isp1761")) devflags |= ISP1760_FLAG_ISP1761; - if (of_get_property(dp, "port1-disable", NULL) != NULL) - devflags |= ISP1760_FLAG_PORT1_DIS; - /* Some systems wire up only 16 of the 32 data lines */ prop = of_get_property(dp, "bus-width", NULL); if (prop && *prop == 16) @@ -129,23 +126,23 @@ static struct of_platform_driver isp1760_of_driver = { #endif #ifdef CONFIG_PCI -static u32 nxp_pci_io_base; -static u32 iolength; -static u32 pci_mem_phy0; -static u32 length; -static u8 __iomem *chip_addr; -static u8 __iomem *iobase; - static int __devinit isp1761_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { u8 latency, limit; __u32 reg_data; int retry_count; - int length; - int status = 1; struct usb_hcd *hcd; unsigned int devflags = 0; + int ret_status = 0; + + resource_size_t pci_mem_phy0; + resource_size_t memlength; + + u8 __iomem *chip_addr; + u8 __iomem *iobase; + resource_size_t nxp_pci_io_base; + resource_size_t iolength; if (usb_disabled()) return -ENODEV; @@ -168,26 +165,30 @@ static int __devinit isp1761_pci_probe(struct pci_dev *dev, iobase = ioremap_nocache(nxp_pci_io_base, iolength); if (!iobase) { printk(KERN_ERR "ioremap #1\n"); - release_mem_region(nxp_pci_io_base, iolength); - return -ENOMEM; + ret_status = -ENOMEM; + goto cleanup1; } /* Grab the PLX PCI shared memory of the ISP 1761 we need */ pci_mem_phy0 = pci_resource_start(dev, 3); - length = pci_resource_len(dev, 3); - - if (length < 0xffff) { - printk(KERN_ERR "memory length for this resource is less than " - "required\n"); - release_mem_region(nxp_pci_io_base, iolength); - iounmap(iobase); - return -ENOMEM; + memlength = pci_resource_len(dev, 3); + if (memlength < 0xffff) { + printk(KERN_ERR "memory length for this resource is wrong\n"); + ret_status = -ENOMEM; + goto cleanup2; } - if (!request_mem_region(pci_mem_phy0, length, "ISP-PCI")) { + if (!request_mem_region(pci_mem_phy0, memlength, "ISP-PCI")) { printk(KERN_ERR "host controller already in use\n"); - release_mem_region(nxp_pci_io_base, iolength); - iounmap(iobase); - return -EBUSY; + ret_status = -EBUSY; + goto cleanup2; + } + + /* map available memory */ + chip_addr = ioremap_nocache(pci_mem_phy0,memlength); + if (!chip_addr) { + printk(KERN_ERR "Error ioremap failed\n"); + ret_status = -ENOMEM; + goto cleanup3; } /* bad pci latencies can contribute to overruns */ @@ -210,39 +211,54 @@ static int __devinit isp1761_pci_probe(struct pci_dev *dev, * */ writel(0xface, chip_addr + HC_SCRATCH_REG); udelay(100); - reg_data = readl(chip_addr + HC_SCRATCH_REG); + reg_data = readl(chip_addr + HC_SCRATCH_REG) & 0x0000ffff; retry_count--; } + iounmap(chip_addr); + /* Host Controller presence is detected by writing to scratch register * and reading back and checking the contents are same or not */ if (reg_data != 0xFACE) { dev_err(&dev->dev, "scratch register mismatch %x\n", reg_data); - goto clean; + ret_status = -ENOMEM; + goto cleanup3; } pci_set_master(dev); - status = readl(iobase + 0x68); - status |= 0x900; - writel(status, iobase + 0x68); + /* configure PLX PCI chip to pass interrupts */ +#define PLX_INT_CSR_REG 0x68 + reg_data = readl(iobase + PLX_INT_CSR_REG); + reg_data |= 0x900; + writel(reg_data, iobase + PLX_INT_CSR_REG); dev->dev.dma_mask = NULL; - hcd = isp1760_register(pci_mem_phy0, length, dev->irq, + hcd = isp1760_register(pci_mem_phy0, memlength, dev->irq, IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev), devflags); - if (!IS_ERR(hcd)) { - pci_set_drvdata(dev, hcd); - return 0; + if (IS_ERR(hcd)) { + ret_status = -ENODEV; + goto cleanup3; } -clean: - status = -ENODEV; + + /* done with PLX IO access */ + iounmap(iobase); + release_mem_region(nxp_pci_io_base, iolength); + + pci_set_dr |