From 0780aa22781b0bc98428dbfaa312a0249475b632 Mon Sep 17 00:00:00 2001 From: "Alexandros C. Couloumbis" Date: Sun, 15 Aug 2010 16:30:00 +0000 Subject: [PATCH] brcm47xx/patches-2.6.35: Allow SSB EHCI/OHCI drivers to co-exist (thank you Steve Brown) SVN-Revision: 22661 --- .../patches-2.6.35/023-usb_ehci_ohci.patch | 188 ++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 target/linux/brcm47xx/patches-2.6.35/023-usb_ehci_ohci.patch 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 0000000000..15d43ccc36 --- /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 + ++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 -- 2.30.2