brcm47xx/patches-2.6.35: Allow SSB EHCI/OHCI drivers to co-exist (thank you Steve...
authoracoul <acoul@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Sun, 15 Aug 2010 16:30:00 +0000 (16:30 +0000)
committeracoul <acoul@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Sun, 15 Aug 2010 16:30:00 +0000 (16:30 +0000)
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@22661 3c298f89-4303-0410-b956-a3cf2f4a3e73

target/linux/brcm47xx/patches-2.6.35/023-usb_ehci_ohci.patch [new file with mode: 0644]

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 (file)
index 0000000..15d43cc
--- /dev/null
@@ -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