summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoracoul <acoul@3c298f89-4303-0410-b956-a3cf2f4a3e73>2010-08-15 16:30:00 +0000
committeracoul <acoul@3c298f89-4303-0410-b956-a3cf2f4a3e73>2010-08-15 16:30:00 +0000
commit4913e9e06fe982942a6c26bebe0355239c3f617a (patch)
tree84ff736b2dfd2b7391284952f06c87a1641ea2f9
parentcbcb84e29cd690e03847aa1d0f2ccdf16f78ee76 (diff)
brcm47xx/patches-2.6.35: Allow SSB EHCI/OHCI drivers to co-exist (thank you Steve Brown)
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@22661 3c298f89-4303-0410-b956-a3cf2f4a3e73
-rw-r--r--target/linux/brcm47xx/patches-2.6.35/023-usb_ehci_ohci.patch188
1 files changed, 188 insertions, 0 deletions
diff --git a/target/linux/brcm47xx/patches-2.6.35/023-usb_ehci_ohci.patch b/target/linux/brcm47xx/patches-2.6.35/023-usb_ehci_ohci.patch
new file mode 100644
index 000000000..15d43ccc3
--- /dev/null
+++ b/target/linux/brcm47xx/patches-2.6.35/023-usb_ehci_ohci.patch
@@ -0,0 +1,188 @@
+--- a/drivers/usb/host/ohci-ssb.c
++++ b/drivers/usb/host/ohci-ssb.c
+@@ -17,6 +17,8 @@
+ */
+ #include <linux/ssb/ssb.h>
+
++extern int ssb_ehci_attach(struct ssb_device *dev, struct usb_hcd **hcd);
++extern void ssb_ehci_detach(struct ssb_device *dev, struct usb_hcd *hcd);
+
+ #define SSB_OHCI_TMSLOW_HOSTMODE (1 << 29)
+
+@@ -24,6 +26,9 @@ struct ssb_ohci_device {
+ struct ohci_hcd ohci; /* _must_ be at the beginning. */
+
+ u32 enable_flags;
++#ifdef CONFIG_USB_EHCI_HCD_SSB
++ struct usb_hcd *ehci_hcd;
++#endif
+ };
+
+ static inline
+@@ -92,6 +97,9 @@ static const struct hc_driver ssb_ohci_h
+ static void ssb_ohci_detach(struct ssb_device *dev)
+ {
+ struct usb_hcd *hcd = ssb_get_drvdata(dev);
++#ifdef CONFIG_USB_EHCI_HCD_SSB
++ struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
++#endif
+
+ if (hcd->driver->shutdown)
+ hcd->driver->shutdown(hcd);
+@@ -99,6 +107,14 @@ static void ssb_ohci_detach(struct ssb_d
+ iounmap(hcd->regs);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ usb_put_hcd(hcd);
++
++#ifdef CONFIG_USB_EHCI_HCD_SSB
++ /*
++ * Also detach ehci function
++ */
++ if (dev->id.coreid == SSB_DEV_USB20_HOST)
++ ssb_ehci_detach(dev, ohcidev->ehci_hcd);
++#endif
+ ssb_device_disable(dev, 0);
+ }
+
+@@ -121,6 +137,9 @@ static int ssb_ohci_attach(struct ssb_de
+ /*
+ * USB 2.0 special considerations:
+ *
++ * Since the core supports both OHCI and EHCI functions,
++ * it must only be reset once.
++ *
+ * In addition to the standard SSB reset sequence, the Host
+ * Control Register must be programmed to bring the USB core
+ * and various phy components out of reset.
+@@ -175,6 +194,14 @@ static int ssb_ohci_attach(struct ssb_de
+
+ ssb_set_drvdata(dev, hcd);
+
++#ifdef CONFIG_USB_EHCI_HCD_SSB
++ /*
++ * attach ehci function in this core
++ */
++ if (dev->id.coreid == SSB_DEV_USB20_HOST)
++ err = ssb_ehci_attach(dev, &(ohcidev->ehci_hcd));
++#endif
++
+ return err;
+
+ err_iounmap:
+--- a/drivers/usb/host/ehci-ssb.c
++++ b/drivers/usb/host/ehci-ssb.c
+@@ -106,10 +106,18 @@ static void ssb_ehci_detach(struct ssb_d
+ iounmap(hcd->regs);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ usb_put_hcd(hcd);
++#ifndef CONFIG_USB_OHCI_HCD_SSB
++ ssb_device_disable(dev, 0);
++#endif
+ ssb_device_disable(dev, 0);
+ }
++EXPORT_SYMBOL_GPL(ssb_ehci_detach);
+
++#ifndef CONFIG_USB_OHCI_HCD_SSB
+ static int ssb_ehci_attach(struct ssb_device *dev)
++#else
++static int ssb_ehci_attach(struct ssb_device *dev, struct usb_hcd **ehci_hcd)
++#endif
+ {
+ struct ssb_ehci_device *ehcidev;
+ struct usb_hcd *hcd;
+@@ -120,6 +128,7 @@ static int ssb_ehci_attach(struct ssb_de
+ dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
+ return -EOPNOTSUPP;
+
++#ifndef CONFIG_USB_OHCI_HCD_SSB
+ /*
+ * USB 2.0 special considerations:
+ *
+@@ -155,6 +164,7 @@ static int ssb_ehci_attach(struct ssb_de
+ tmp |= 0x1;
+ ssb_write32(dev, 0x89c, tmp);
+ }
++#endif
+
+ hcd = usb_create_hcd(&ssb_ehci_hc_driver, dev->dev,
+ dev_name(dev->dev));
+@@ -175,7 +185,11 @@ static int ssb_ehci_attach(struct ssb_de
+ if (err)
+ goto err_iounmap;
+
++#ifndef CONFIG_USB_OHCI_HCD_SSB
+ ssb_set_drvdata(dev, hcd);
++#else
++ *ehci_hcd = hcd;
++#endif
+
+ return err;
+
+@@ -187,7 +201,9 @@ err_dev_disable:
+ ssb_device_disable(dev, 0);
+ return err;
+ }
++EXPORT_SYMBOL_GPL(ssb_ehci_attach);
+
++#ifndef CONFIG_USB_OHCI_HCD_SSB
+ static int ssb_ehci_probe(struct ssb_device *dev,
+ const struct ssb_device_id *id)
+ {
+@@ -238,6 +254,7 @@ static int ssb_ehci_resume(struct ssb_de
+ #define ssb_ehci_suspend NULL
+ #define ssb_ehci_resume NULL
+ #endif /* CONFIG_PM */
++#endif /* !CONFIG_USB_OHCI_HCD_SSB */
+
+ static const struct ssb_device_id ssb_ehci_table[] = {
+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
+@@ -245,6 +262,8 @@ static const struct ssb_device_id ssb_eh
+ };
+ MODULE_DEVICE_TABLE(ssb, ssb_ehci_table);
+
++
++#ifndef CONFIG_USB_OHCI_HCD_SSB
+ static struct ssb_driver ssb_ehci_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = ssb_ehci_table,
+@@ -253,3 +272,4 @@ static struct ssb_driver ssb_ehci_driver
+ .suspend = ssb_ehci_suspend,
+ .resume = ssb_ehci_resume,
+ };
++#endif
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1226,17 +1226,21 @@ static int __init ehci_hcd_init(void)
+ goto clean4;
+ #endif
+
++#ifndef CONFIG_USB_OHCI_HCD_SSB
+ #ifdef SSB_EHCI_DRIVER
+ retval = ssb_driver_register(&SSB_EHCI_DRIVER);
+ if (retval < 0)
+ goto clean5;
+ #endif
++#endif /* !CONFIG_USB_OHCI_HCD_SSB */
+ return retval;
+
++#ifndef CONFIG_USB_OHCI_HCD_SSB
+ #ifdef SSB_EHCI_DRIVER
+ /* ssb_driver_unregister(&SSB_EHCI_DRIVER); */
+ clean5:
+ #endif
++#endif /* !CONFIG_USB_OHCI_HCD_SSB */
+ #ifdef XILINX_OF_PLATFORM_DRIVER
+ of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER);
+ clean4:
+@@ -1269,9 +1273,11 @@ module_init(ehci_hcd_init);
+
+ static void __exit ehci_hcd_cleanup(void)
+ {
++#ifndef CONFIG_USB_OHCI_HCD_SSB
+ #ifdef SSB_EHCI_DRIVER
+ ssb_driver_unregister(&SSB_EHCI_DRIVER);
+ #endif
++#endif /* !CONFIG_USB_OHCI_HCD_SSB */
+ #ifdef XILINX_OF_PLATFORM_DRIVER
+ of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER);
+ #endif