From 6d7798dc01d71f5db2a8d468a7cfdc67444ae090 Mon Sep 17 00:00:00 2001
From: hauke <hauke@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Date: Sun, 12 Feb 2012 16:38:10 +0000
Subject: brcm47xx: update usb driver for brcm47xx.

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@30480 3c298f89-4303-0410-b956-a3cf2f4a3e73
---
 .../0028-bcma-scan-for-extra-address-space.patch   |  60 ----
 ...nction-to-check-every-10-s-if-a-reg-is-se.patch | 115 -------
 ...OHCI-Add-a-generic-platform-device-driver.patch | 291 ----------------
 ...EHCI-Add-a-generic-platform-device-driver.patch | 265 ---------------
 .../0032-USB-Add-driver-for-the-bcma-bus.patch     | 358 -------------------
 .../0033-USB-Add-driver-for-the-ssb-bus.patch      | 325 ------------------
 .../0034-USB-OHCI-remove-old-SSB-OHCI-driver.patch | 357 -------------------
 ...-struct-for-ehci-and-ohci-platform-driver.patch |  48 +++
 ...OHCI-Add-a-generic-platform-device-driver.patch | 237 +++++++++++++
 ...EHCI-Add-a-generic-platform-device-driver.patch | 253 ++++++++++++++
 .../183-bcma-scan-for-extra-address-space.patch    |  61 ++++
 .../184-USB-Add-driver-for-the-bcma-bus.patch      | 377 +++++++++++++++++++++
 .../185-USB-Add-driver-for-the-ssb-bus.patch       | 326 ++++++++++++++++++
 .../186-USB-OHCI-remove-old-SSB-OHCI-driver.patch  | 359 ++++++++++++++++++++
 14 files changed, 1661 insertions(+), 1771 deletions(-)
 delete mode 100644 target/linux/brcm47xx/patches-3.2/0028-bcma-scan-for-extra-address-space.patch
 delete mode 100644 target/linux/brcm47xx/patches-3.2/0029-bcma-add-function-to-check-every-10-s-if-a-reg-is-se.patch
 delete mode 100644 target/linux/brcm47xx/patches-3.2/0030-USB-OHCI-Add-a-generic-platform-device-driver.patch
 delete mode 100644 target/linux/brcm47xx/patches-3.2/0031-USB-EHCI-Add-a-generic-platform-device-driver.patch
 delete mode 100644 target/linux/brcm47xx/patches-3.2/0032-USB-Add-driver-for-the-bcma-bus.patch
 delete mode 100644 target/linux/brcm47xx/patches-3.2/0033-USB-Add-driver-for-the-ssb-bus.patch
 delete mode 100644 target/linux/brcm47xx/patches-3.2/0034-USB-OHCI-remove-old-SSB-OHCI-driver.patch
 create mode 100644 target/linux/brcm47xx/patches-3.2/180-USB-HCI-add-struct-for-ehci-and-ohci-platform-driver.patch
 create mode 100644 target/linux/brcm47xx/patches-3.2/181-USB-OHCI-Add-a-generic-platform-device-driver.patch
 create mode 100644 target/linux/brcm47xx/patches-3.2/182-USB-EHCI-Add-a-generic-platform-device-driver.patch
 create mode 100644 target/linux/brcm47xx/patches-3.2/183-bcma-scan-for-extra-address-space.patch
 create mode 100644 target/linux/brcm47xx/patches-3.2/184-USB-Add-driver-for-the-bcma-bus.patch
 create mode 100644 target/linux/brcm47xx/patches-3.2/185-USB-Add-driver-for-the-ssb-bus.patch
 create mode 100644 target/linux/brcm47xx/patches-3.2/186-USB-OHCI-remove-old-SSB-OHCI-driver.patch

(limited to 'target')

diff --git a/target/linux/brcm47xx/patches-3.2/0028-bcma-scan-for-extra-address-space.patch b/target/linux/brcm47xx/patches-3.2/0028-bcma-scan-for-extra-address-space.patch
deleted file mode 100644
index d74dfcb73..000000000
--- a/target/linux/brcm47xx/patches-3.2/0028-bcma-scan-for-extra-address-space.patch
+++ /dev/null
@@ -1,60 +0,0 @@
-From 1735daf1db79d338dccfc55444b52ed52af79e86 Mon Sep 17 00:00:00 2001
-From: Hauke Mehrtens <hauke@hauke-m.de>
-Date: Sun, 20 Nov 2011 18:22:35 +0100
-Subject: [PATCH 15/21] bcma: scan for extra address space
-
-Some cores like the USB core have two address spaces. In the USB host
-controller one address space is used for the OHCI and the other for the
-EHCI controller interface. The USB controller is the only core I found
-with two address spaces. This code is based on the AI scan function
-ai_scan() in shared/aiutils.c i the Broadcom SDK.
-
-Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
----
- drivers/bcma/scan.c       |   17 ++++++++++++++++-
- include/linux/bcma/bcma.h |    1 +
- 2 files changed, 17 insertions(+), 1 deletions(-)
-
---- a/drivers/bcma/scan.c
-+++ b/drivers/bcma/scan.c
-@@ -286,6 +286,21 @@ static int bcma_get_next_core(struct bcm
- 			return -EILSEQ;
- 	}
- 
-+
-+	/* First Slave Address Descriptor should be port 0:
-+	 * the main register space for the core
-+	 */
-+	tmp = bcma_erom_get_addr_desc(bus, eromptr, SCAN_ADDR_TYPE_SLAVE, 0);
-+	if (tmp < 0) {
-+		/* Try again to see if it is a bridge */
-+		tmp = bcma_erom_get_addr_desc(bus, eromptr, SCAN_ADDR_TYPE_BRIDGE, 0);
-+		if (tmp) {
-+			printk("found bridge\n");
-+		}
-+
-+	}
-+	core->addr = tmp;
-+
- 	/* get & parse slave ports */
- 	for (i = 0; i < ports[1]; i++) {
- 		for (j = 0; ; j++) {
-@@ -298,7 +313,7 @@ static int bcma_get_next_core(struct bcm
- 				break;
- 			} else {
- 				if (i == 0 && j == 0)
--					core->addr = tmp;
-+					core->addr1 = tmp;
- 			}
- 		}
- 	}
---- a/include/linux/bcma/bcma.h
-+++ b/include/linux/bcma/bcma.h
-@@ -138,6 +138,7 @@ struct bcma_device {
- 	u8 core_index;
- 
- 	u32 addr;
-+	u32 addr1;
- 	u32 wrap;
- 
- 	void __iomem *io_addr;
diff --git a/target/linux/brcm47xx/patches-3.2/0029-bcma-add-function-to-check-every-10-s-if-a-reg-is-se.patch b/target/linux/brcm47xx/patches-3.2/0029-bcma-add-function-to-check-every-10-s-if-a-reg-is-se.patch
deleted file mode 100644
index bfdc7f21c..000000000
--- a/target/linux/brcm47xx/patches-3.2/0029-bcma-add-function-to-check-every-10-s-if-a-reg-is-se.patch
+++ /dev/null
@@ -1,115 +0,0 @@
-From 6e8ae6e2cee0e7e5939dc7042584c808366e61e0 Mon Sep 17 00:00:00 2001
-From: Hauke Mehrtens <hauke@hauke-m.de>
-Date: Sun, 27 Nov 2011 14:01:01 +0100
-Subject: [PATCH 16/21] =?UTF-8?q?bcma:=20add=20function=20to=20check=20every?=
- =?UTF-8?q?=2010=20=C2=B5s=20if=20a=20reg=20is=20set?=
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This function checks if a reg get set or cleared every 10 microseconds.
-It is used in bcma_core_set_clockmode() and bcma_core_pll_ctl() to
-reduce code duplication. In addition it is needed in the USB host
-driver.
-
-Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
----
- drivers/bcma/core.c       |   48 ++++++++++++++++++++++++++++----------------
- include/linux/bcma/bcma.h |    2 +
- 2 files changed, 32 insertions(+), 18 deletions(-)
-
---- a/drivers/bcma/core.c
-+++ b/drivers/bcma/core.c
-@@ -52,11 +52,36 @@ int bcma_core_enable(struct bcma_device
- }
- EXPORT_SYMBOL_GPL(bcma_core_enable);
- 
-+/* Wait for bitmask in a register to get set or cleared.
-+ * timeout is in units of ten-microseconds.
-+ */
-+int bcma_wait_bits(struct bcma_device *dev, u16 reg, u32 bitmask, int timeout,
-+		   int set)
-+{
-+	int i;
-+	u32 val;
-+
-+	for (i = 0; i < timeout; i++) {
-+		val = bcma_read32(dev, reg);
-+		if (set) {
-+			if ((val & bitmask) == bitmask)
-+				return 0;
-+		} else {
-+			if (!(val & bitmask))
-+				return 0;
-+		}
-+		udelay(10);
-+	}
-+	pr_err("Timeout waiting for bitmask %08X on register %04X to %s.\n",
-+	       bitmask, reg, (set ? "set" : "clear"));
-+
-+	return -ETIMEDOUT;
-+}
-+EXPORT_SYMBOL_GPL(bcma_wait_bits);
-+
- void bcma_core_set_clockmode(struct bcma_device *core,
- 			     enum bcma_clkmode clkmode)
- {
--	u16 i;
--
- 	WARN_ON(core->id.id != BCMA_CORE_CHIPCOMMON &&
- 		core->id.id != BCMA_CORE_PCIE &&
- 		core->id.id != BCMA_CORE_80211);
-@@ -65,15 +90,8 @@ void bcma_core_set_clockmode(struct bcma
- 	case BCMA_CLKMODE_FAST:
- 		bcma_set32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT);
- 		udelay(64);
--		for (i = 0; i < 1500; i++) {
--			if (bcma_read32(core, BCMA_CLKCTLST) &
--			    BCMA_CLKCTLST_HAVEHT) {
--				i = 0;
--				break;
--			}
--			udelay(10);
--		}
--		if (i)
-+		if (bcma_wait_bits(core, BCMA_CLKCTLST, BCMA_CLKCTLST_HAVEHT,
-+				   1500, 1))
- 			pr_err("HT force timeout\n");
- 		break;
- 	case BCMA_CLKMODE_DYNAMIC:
-@@ -85,22 +103,12 @@ EXPORT_SYMBOL_GPL(bcma_core_set_clockmod
- 
- void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status, bool on)
- {
--	u16 i;
--
- 	WARN_ON(req & ~BCMA_CLKCTLST_EXTRESREQ);
- 	WARN_ON(status & ~BCMA_CLKCTLST_EXTRESST);
- 
- 	if (on) {
- 		bcma_set32(core, BCMA_CLKCTLST, req);
--		for (i = 0; i < 10000; i++) {
--			if ((bcma_read32(core, BCMA_CLKCTLST) & status) ==
--			    status) {
--				i = 0;
--				break;
--			}
--			udelay(10);
--		}
--		if (i)
-+		if (bcma_wait_bits(core, BCMA_CLKCTLST, status, 10000, 1))
- 			pr_err("PLL enable timeout\n");
- 	} else {
- 		pr_warn("Disabling PLL not supported yet!\n");
---- a/include/linux/bcma/bcma.h
-+++ b/include/linux/bcma/bcma.h
-@@ -283,6 +283,9 @@ static inline void bcma_maskset16(struct
- 	bcma_write16(cc, offset, (bcma_read16(cc, offset) & mask) | set);
- }
- 
-+extern int bcma_wait_bits(struct bcma_device *dev, u16 reg, u32 bitmask,
-+			  int timeout, int set);
-+
- extern bool bcma_core_is_enabled(struct bcma_device *core);
- extern void bcma_core_disable(struct bcma_device *core, u32 flags);
- extern int bcma_core_enable(struct bcma_device *core, u32 flags);
diff --git a/target/linux/brcm47xx/patches-3.2/0030-USB-OHCI-Add-a-generic-platform-device-driver.patch b/target/linux/brcm47xx/patches-3.2/0030-USB-OHCI-Add-a-generic-platform-device-driver.patch
deleted file mode 100644
index 4aeaa78aa..000000000
--- a/target/linux/brcm47xx/patches-3.2/0030-USB-OHCI-Add-a-generic-platform-device-driver.patch
+++ /dev/null
@@ -1,291 +0,0 @@
-From 14297ee700e1c2e04a35466304f9a3c5e1387146 Mon Sep 17 00:00:00 2001
-From: Hauke Mehrtens <hauke@hauke-m.de>
-Date: Sat, 26 Nov 2011 21:20:54 +0100
-Subject: [PATCH 17/30] USB: OHCI: Add a generic platform device driver
-
-This adds a generic driver for platform devices. It works like the PCI
-driver and is based on it. This is for devices which do not have an own
-bus but their OHCI controller works like a PCI controller. It will be
-used for the Broadcom bcma and ssb USB OHCI controller.
-
-Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
----
- drivers/usb/host/Kconfig         |   10 ++
- drivers/usb/host/ohci-hcd.c      |   21 ++++-
- drivers/usb/host/ohci-platform.c |  197 ++++++++++++++++++++++++++++++++++++++
- 3 files changed, 227 insertions(+), 1 deletions(-)
- create mode 100644 drivers/usb/host/ohci-platform.c
-
---- a/drivers/usb/host/Kconfig
-+++ b/drivers/usb/host/Kconfig
-@@ -378,6 +378,16 @@ config USB_CNS3XXX_OHCI
- 	  Enable support for the CNS3XXX SOC's on-chip OHCI controller.
- 	  It is needed for low-speed USB 1.0 device support.
- 
-+config USB_OHCI_HCD_PLATFORM
-+	bool "OHCI driver for a platform device"
-+	depends on USB_OHCI_HCD && EXPERIMENTAL
-+	default n
-+	---help---
-+	  Adds an OHCI host driver for a generic platform device, which
-+	  provieds a memory space and an irq.
-+
-+	  If unsure, say N.
-+
- config USB_OHCI_BIG_ENDIAN_DESC
- 	bool
- 	depends on USB_OHCI_HCD
---- a/drivers/usb/host/ohci-hcd.c
-+++ b/drivers/usb/host/ohci-hcd.c
-@@ -1116,6 +1116,11 @@ MODULE_LICENSE ("GPL");
- #define PLATFORM_DRIVER		ohci_xls_driver
- #endif
- 
-+#ifdef CONFIG_USB_OHCI_HCD_PLATFORM
-+#include "ohci-platform.c"
-+#define PLATFORM_OHCI_DRIVER	ohci_platform_driver
-+#endif
-+
- #if	!defined(PCI_DRIVER) &&		\
- 	!defined(PLATFORM_DRIVER) &&	\
- 	!defined(OMAP1_PLATFORM_DRIVER) &&	\
-@@ -1125,7 +1130,8 @@ MODULE_LICENSE ("GPL");
- 	!defined(PS3_SYSTEM_BUS_DRIVER) && \
- 	!defined(SM501_OHCI_DRIVER) && \
- 	!defined(TMIO_OHCI_DRIVER) && \
--	!defined(SSB_OHCI_DRIVER)
-+	!defined(SSB_OHCI_DRIVER) && \
-+	!defined(PLATFORM_OHCI_DRIVER)
- #error "missing bus glue for ohci-hcd"
- #endif
- 
-@@ -1209,9 +1215,19 @@ static int __init ohci_hcd_mod_init(void
- 		goto error_tmio;
- #endif
- 
-+#ifdef PLATFORM_OHCI_DRIVER
-+	retval = platform_driver_register(&PLATFORM_OHCI_DRIVER);
-+	if (retval)
-+		goto error_platform;
-+#endif
-+
- 	return retval;
- 
- 	/* Error path */
-+#ifdef PLATFORM_OHCI_DRIVER
-+	platform_driver_unregister(&PLATFORM_OHCI_DRIVER);
-+ error_platform:
-+#endif
- #ifdef TMIO_OHCI_DRIVER
- 	platform_driver_unregister(&TMIO_OHCI_DRIVER);
-  error_tmio:
-@@ -1265,6 +1281,9 @@ module_init(ohci_hcd_mod_init);
- 
- static void __exit ohci_hcd_mod_exit(void)
- {
-+#ifdef PLATFORM_OHCI_DRIVER
-+	platform_driver_unregister(&PLATFORM_OHCI_DRIVER);
-+#endif
- #ifdef TMIO_OHCI_DRIVER
- 	platform_driver_unregister(&TMIO_OHCI_DRIVER);
- #endif
---- /dev/null
-+++ b/drivers/usb/host/ohci-platform.c
-@@ -0,0 +1,197 @@
-+/*
-+ * Generic platform ohci driver
-+ *
-+ * Copyright 2007 Michael Buesch <m@bues.ch>
-+ * Copyright 2011 Hauke Mehrtens <hauke@hauke-m.de>
-+ *
-+ * Derived from the OHCI-PCI driver
-+ * Copyright 1999 Roman Weissgaerber
-+ * Copyright 2000-2002 David Brownell
-+ * Copyright 1999 Linus Torvalds
-+ * Copyright 1999 Gregory P. Smith
-+ *
-+ * Licensed under the GNU/GPL. See COPYING for details.
-+ */
-+#include <linux/platform_device.h>
-+
-+static int ohci_platform_reset(struct usb_hcd *hcd)
-+{
-+	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-+	int err;
-+
-+	ohci_hcd_init(ohci);
-+	err = ohci_init(ohci);
-+
-+	return err;
-+}
-+
-+static int ohci_platform_start(struct usb_hcd *hcd)
-+{
-+	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-+	int err;
-+
-+	err = ohci_run(ohci);
-+	if (err < 0) {
-+		ohci_err(ohci, "can't start\n");
-+		ohci_stop(hcd);
-+	}
-+
-+	return err;
-+}
-+
-+static const struct hc_driver ohci_platform_hc_driver = {
-+	.description		= "platform-usb-ohci",
-+	.product_desc		= "Generic Platform OHCI Controller",
-+	.hcd_priv_size		= sizeof(struct ohci_hcd),
-+
-+	.irq			= ohci_irq,
-+	.flags			= HCD_MEMORY | HCD_USB11,
-+
-+	.reset			= ohci_platform_reset,
-+	.start			= ohci_platform_start,
-+	.stop			= ohci_stop,
-+	.shutdown		= ohci_shutdown,
-+
-+	.urb_enqueue		= ohci_urb_enqueue,
-+	.urb_dequeue		= ohci_urb_dequeue,
-+	.endpoint_disable	= ohci_endpoint_disable,
-+
-+	.get_frame_number	= ohci_get_frame,
-+
-+	.hub_status_data	= ohci_hub_status_data,
-+	.hub_control		= ohci_hub_control,
-+#ifdef	CONFIG_PM
-+	.bus_suspend		= ohci_bus_suspend,
-+	.bus_resume		= ohci_bus_resume,
-+#endif
-+
-+	.start_port_reset	= ohci_start_port_reset,
-+};
-+
-+static int ohci_platform_attach(struct platform_device *dev)
-+{
-+	struct usb_hcd *hcd;
-+	struct resource *res_irq, *res_mem;
-+	int err = -ENOMEM;
-+
-+	hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev,
-+			dev_name(&dev->dev));
-+	if (!hcd)
-+		goto err_return;
-+
-+	res_irq = platform_get_resource(dev, IORESOURCE_IRQ, 0);
-+	if (!res_irq) {
-+		err = -ENXIO;
-+		goto err_return;
-+	}
-+	res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
-+	if (!res_mem) {
-+		err = -ENXIO;
-+		goto err_return;
-+	}
-+	hcd->rsrc_start = res_mem->start;
-+	hcd->rsrc_len = res_mem->end - res_mem->start + 1;
-+
-+	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
-+	if (!hcd->regs)
-+		goto err_put_hcd;
-+	err = usb_add_hcd(hcd, res_irq->start, IRQF_SHARED);
-+	if (err)
-+		goto err_iounmap;
-+
-+	platform_set_drvdata(dev, hcd);
-+
-+	return err;
-+
-+err_iounmap:
-+	iounmap(hcd->regs);
-+err_put_hcd:
-+	usb_put_hcd(hcd);
-+err_return:
-+	return err;
-+}
-+
-+static int ohci_platform_probe(struct platform_device *dev)
-+{
-+	int err;
-+
-+	if (usb_disabled())
-+		return -ENODEV;
-+
-+	/* We currently always attach BCMA_DEV_USB11_HOSTDEV
-+	 * as HOST OHCI. If we want to attach it as Client device,
-+	 * we must branch here and call into the (yet to
-+	 * be written) Client mode driver. Same for remove(). */
-+
-+	err = ohci_platform_attach(dev);
-+
-+	return err;
-+}
-+
-+static int ohci_platform_remove(struct platform_device *dev)
-+{
-+	struct usb_hcd *hcd;
-+
-+	hcd = platform_get_drvdata(dev);
-+	if (!hcd)
-+		return -ENODEV;
-+
-+	usb_remove_hcd(hcd);
-+	iounmap(hcd->regs);
-+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-+	usb_put_hcd(hcd);
-+
-+	return 0;
-+}
-+
-+static void ohci_platform_shutdown(struct platform_device *dev)
-+{
-+	struct usb_hcd *hcd;
-+
-+	hcd = platform_get_drvdata(dev);
-+	if (!hcd)
-+		return;
-+
-+	if (hcd->driver->shutdown)
-+		hcd->driver->shutdown(hcd);
-+}
-+
-+#ifdef CONFIG_PM
-+
-+static int ohci_platform_suspend(struct platform_device *dev,
-+				 pm_message_t state)
-+{
-+
-+	return 0;
-+}
-+
-+static int ohci_platform_resume(struct platform_device *dev)
-+{
-+	struct usb_hcd *hcd = platform_get_drvdata(dev);
-+
-+	ohci_finish_controller_resume(hcd);
-+	return 0;
-+}
-+
-+#else /* !CONFIG_PM */
-+#define ohci_platform_suspend	NULL
-+#define ohci_platform_resume	NULL
-+#endif /* CONFIG_PM */
-+
-+static const struct platform_device_id ohci_platform_table[] = {
-+	{ "ohci-platform", 0 },
-+	{ }
-+};
-+MODULE_DEVICE_TABLE(platform, ohci_platform_table);
-+
-+static struct platform_driver ohci_platform_driver = {
-+	.id_table	= ohci_platform_table,
-+	.probe		= ohci_platform_probe,
-+	.remove		= ohci_platform_remove,
-+	.shutdown	= ohci_platform_shutdown,
-+	.suspend	= ohci_platform_suspend,
-+	.resume		= ohci_platform_resume,
-+	.driver		= {
-+		.name	= "ohci-platform",
-+	}
-+};
diff --git a/target/linux/brcm47xx/patches-3.2/0031-USB-EHCI-Add-a-generic-platform-device-driver.patch b/target/linux/brcm47xx/patches-3.2/0031-USB-EHCI-Add-a-generic-platform-device-driver.patch
deleted file mode 100644
index 8cc0f0777..000000000
--- a/target/linux/brcm47xx/patches-3.2/0031-USB-EHCI-Add-a-generic-platform-device-driver.patch
+++ /dev/null
@@ -1,265 +0,0 @@
-From 2ade1c32109d2f17fdfc0b414411d4ee7f828706 Mon Sep 17 00:00:00 2001
-From: Hauke Mehrtens <hauke@hauke-m.de>
-Date: Sat, 26 Nov 2011 21:28:56 +0100
-Subject: [PATCH 18/30] USB: EHCI: Add a generic platform device driver
-
-This adds a generic driver for platform devices. It works like the PCI
-driver and is based on it. This is for devices which do not have an own
-bus but their EHCI controller works like a PCI controller. It will be
-used for the Broadcom bcma and ssb USB EHCI controller.
-
-Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
----
- drivers/usb/host/Kconfig         |   10 ++
- drivers/usb/host/ehci-hcd.c      |    5 +
- drivers/usb/host/ehci-platform.c |  211 ++++++++++++++++++++++++++++++++++++++
- 3 files changed, 226 insertions(+), 0 deletions(-)
- create mode 100644 drivers/usb/host/ehci-platform.c
-
---- a/drivers/usb/host/Kconfig
-+++ b/drivers/usb/host/Kconfig
-@@ -388,6 +388,16 @@ config USB_OHCI_HCD_PLATFORM
- 
- 	  If unsure, say N.
- 
-+config USB_EHCI_HCD_PLATFORM
-+	bool "Generic EHCI driver for a platform device"
-+	depends on USB_EHCI_HCD && EXPERIMENTAL
-+	default n
-+	---help---
-+	  Adds an EHCI host driver for a generic platform device, which
-+	  provieds a memory space and an irq.
-+
-+	  If unsure, say N.
-+
- config USB_OHCI_BIG_ENDIAN_DESC
- 	bool
- 	depends on USB_OHCI_HCD
---- a/drivers/usb/host/ehci-hcd.c
-+++ b/drivers/usb/host/ehci-hcd.c
-@@ -1329,6 +1329,11 @@ MODULE_LICENSE ("GPL");
- #define PLATFORM_DRIVER		ehci_xls_driver
- #endif
- 
-+#ifdef CONFIG_USB_EHCI_HCD_PLATFORM
-+#include "ehci-platform.c"
-+#define PLATFORM_DRIVER		ehci_platform_driver
-+#endif
-+
- #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
-     !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
-     !defined(XILINX_OF_PLATFORM_DRIVER)
---- /dev/null
-+++ b/drivers/usb/host/ehci-platform.c
-@@ -0,0 +1,211 @@
-+/*
-+ * Generic platform ehci driver
-+ *
-+ * Copyright 2007 Steven Brown <sbrown@cortland.com>
-+ * Copyright 2010-2011 Hauke Mehrtens <hauke@hauke-m.de>
-+ *
-+ * Derived from the ohci-ssb driver
-+ * Copyright 2007 Michael Buesch <mb@bu3sch.de>
-+ *
-+ * Derived from the EHCI-PCI driver
-+ * Copyright (c) 2000-2004 by David Brownell
-+ *
-+ * Derived from the ohci-pci driver
-+ * Copyright 1999 Roman Weissgaerber
-+ * Copyright 2000-2002 David Brownell
-+ * Copyright 1999 Linus Torvalds
-+ * Copyright 1999 Gregory P. Smith
-+ *
-+ * Licensed under the GNU/GPL. See COPYING for details.
-+ */
-+#include <linux/platform_device.h>
-+
-+static int ehci_platform_reset(struct usb_hcd *hcd)
-+{
-+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-+	int retval;
-+
-+	ehci->caps = hcd->regs;
-+	ehci->regs = hcd->regs +
-+		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
-+
-+	dbg_hcs_params(ehci, "reset");
-+	dbg_hcc_params(ehci, "reset");
-+
-+	/* cache this readonly data; minimize chip reads */
-+	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-+
-+	retval = ehci_halt(ehci);
-+	if (retval)
-+		return retval;
-+
-+	/* data structure init */
-+	retval = ehci_init(hcd);
-+	if (retval)
-+		return retval;
-+
-+	ehci_reset(ehci);
-+
-+	ehci_port_power(ehci, 1);
-+
-+	return retval;
-+}
-+
-+static const struct hc_driver ehci_platform_hc_driver = {
-+	.description		= "platform-usb-ehci",
-+	.product_desc		= "Generic Platform EHCI Controller",
-+	.hcd_priv_size		= sizeof(struct ehci_hcd),
-+
-+	.irq			= ehci_irq,
-+	.flags			= HCD_MEMORY | HCD_USB2,
-+
-+	.reset			= ehci_platform_reset,
-+	.start			= ehci_run,
-+	.stop			= ehci_stop,
-+	.shutdown		= ehci_shutdown,
-+
-+	.urb_enqueue		= ehci_urb_enqueue,
-+	.urb_dequeue		= ehci_urb_dequeue,
-+	.endpoint_disable	= ehci_endpoint_disable,
-+	.endpoint_reset		= ehci_endpoint_reset,
-+
-+	.get_frame_number	= ehci_get_frame,
-+
-+	.hub_status_data	= ehci_hub_status_data,
-+	.hub_control		= ehci_hub_control,
-+#if defined(CONFIG_PM)
-+	.bus_suspend		= ehci_bus_suspend,
-+	.bus_resume		= ehci_bus_resume,
-+#endif
-+	.relinquish_port	= ehci_relinquish_port,
-+	.port_handed_over	= ehci_port_handed_over,
-+
-+	.update_device		= ehci_update_device,
-+
-+	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-+};
-+
-+static int ehci_platform_attach(struct platform_device *dev)
-+{
-+	struct usb_hcd *hcd;
-+	struct resource *res_irq, *res_mem;
-+	int err = -ENOMEM;
-+
-+	hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
-+			     dev_name(&dev->dev));
-+	if (!hcd)
-+		goto err_return;
-+
-+	res_irq = platform_get_resource(dev, IORESOURCE_IRQ, 0);
-+	if (!res_irq) {
-+		err = -ENXIO;
-+		goto err_return;
-+	}
-+	res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
-+	if (!res_mem) {
-+		err = -ENXIO;
-+		goto err_return;
-+	}
-+	hcd->rsrc_start = res_mem->start;
-+	hcd->rsrc_len = res_mem->end - res_mem->start + 1;
-+
-+	/*
-+	 * start & size modified per sbutils.c
-+	 */
-+	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
-+	if (!hcd->regs)
-+		goto err_put_hcd;
-+	err = usb_add_hcd(hcd, res_irq->start, IRQF_SHARED);
-+	if (err)
-+		goto err_iounmap;
-+
-+	platform_set_drvdata(dev, hcd);
-+
-+	return err;
-+
-+err_iounmap:
-+	iounmap(hcd->regs);
-+err_put_hcd:
-+	usb_put_hcd(hcd);
-+err_return:
-+	return err;
-+}
-+
-+static int ehci_platform_probe(struct platform_device *dev)
-+{
-+	int err;
-+
-+	if (usb_disabled())
-+		return -ENODEV;
-+
-+	err = ehci_platform_attach(dev);
-+
-+	return err;
-+}
-+
-+static int ehci_platform_remove(struct platform_device *dev)
-+{
-+	struct usb_hcd *hcd;
-+
-+	hcd = platform_get_drvdata(dev);
-+	if (!hcd)
-+		return -ENODEV;
-+
-+	usb_remove_hcd(hcd);
-+	iounmap(hcd->regs);
-+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-+	usb_put_hcd(hcd);
-+
-+	return 0;
-+}
-+
-+static void ehci_platform_shutdown(struct platform_device *dev)
-+{
-+	struct usb_hcd *hcd;
-+
-+	hcd = platform_get_drvdata(dev);
-+	if (!hcd)
-+		return;
-+
-+	if (hcd->driver->shutdown)
-+		hcd->driver->shutdown(hcd);
-+}
-+
-+#ifdef CONFIG_PM
-+
-+static int ehci_platform_suspend(struct platform_device *dev,
-+				 pm_message_t state)
-+{
-+	return 0;
-+}
-+
-+static int ehci_platform_resume(struct platform_device *dev)
-+{
-+	struct usb_hcd *hcd = platform_get_drvdata(dev);
-+
-+	ehci_finish_controller_resume(hcd);
-+	return 0;
-+}
-+
-+#else /* !CONFIG_PM */
-+#define ehci_platform_suspend	NULL
-+#define ehci_platform_resume	NULL
-+#endif /* CONFIG_PM */
-+
-+static const struct platform_device_id ehci_platform_table[] = {
-+	{ "ehci-platform", 0 },
-+	{ }
-+};
-+MODULE_DEVICE_TABLE(platform, ehci_platform_table);
-+
-+static struct platform_driver ehci_platform_driver = {
-+	.id_table	= ehci_platform_table,
-+	.probe		= ehci_platform_probe,
-+	.remove		= ehci_platform_remove,
-+	.shutdown	= ehci_platform_shutdown,
-+	.suspend	= ehci_platform_suspend,
-+	.resume		= ehci_platform_resume,
-+	.driver		= {
-+		.name	= "ehci-platform",
-+	}
-+};
diff --git a/target/linux/brcm47xx/patches-3.2/0032-USB-Add-driver-for-the-bcma-bus.patch b/target/linux/brcm47xx/patches-3.2/0032-USB-Add-driver-for-the-bcma-bus.patch
deleted file mode 100644
index 598aedd26..000000000
--- a/target/linux/brcm47xx/patches-3.2/0032-USB-Add-driver-for-the-bcma-bus.patch
+++ /dev/null
@@ -1,358 +0,0 @@
-From 0da055d81f77272ebc41d4c2cd5f533aa9025cc7 Mon Sep 17 00:00:00 2001
-From: Hauke Mehrtens <hauke@hauke-m.de>
-Date: Sat, 26 Nov 2011 21:33:41 +0100
-Subject: [PATCH 19/30] USB: Add driver for the bcma bus
-
-This adds a USB driver using the generic platform device driver for the
-USB controller found on the Broadcom bcma bus. The bcma bus just
-exposes one device which serves the OHCI and the EHCI controller at the
-same time. This driver probes for this USB controller and creates and
-registers two new platform devices which will be probed by the new
-generic platform device driver. This makes it possible to use the EHCI
-and the OCHI controller on the bcma bus at the same time.
-
-Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
----
- drivers/usb/host/Kconfig    |   12 ++
- drivers/usb/host/Makefile   |    1 +
- drivers/usb/host/bcma-hcd.c |  309 +++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 322 insertions(+), 0 deletions(-)
- create mode 100644 drivers/usb/host/bcma-hcd.c
-
---- a/drivers/usb/host/Kconfig
-+++ b/drivers/usb/host/Kconfig
-@@ -618,3 +618,15 @@ config USB_PXA168_EHCI
- 	help
- 	  Enable support for Marvell PXA168 SoC's on-chip EHCI
- 	  host controller
-+
-+config USB_HCD_BCMA
-+	tristate "BCMA usb host driver"
-+	depends on BCMA && EXPERIMENTAL
-+	select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD
-+	select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD
-+	help
-+	  Enbale support for the EHCI and OCHI host controller on an bcma bus.
-+	  It converts the bcma driver into two platform device drivers
-+	  for ehci and ohci.
-+
-+	  If unsure, say N.
---- a/drivers/usb/host/Makefile
-+++ b/drivers/usb/host/Makefile
-@@ -37,3 +37,4 @@ obj-$(CONFIG_USB_IMX21_HCD)	+= imx21-hcd
- obj-$(CONFIG_USB_FSL_MPH_DR_OF)	+= fsl-mph-dr-of.o
- obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o
- obj-$(CONFIG_MIPS_ALCHEMY)	+= alchemy-common.o
-+obj-$(CONFIG_USB_HCD_BCMA)	+= bcma-hcd.o
---- /dev/null
-+++ b/drivers/usb/host/bcma-hcd.c
-@@ -0,0 +1,309 @@
-+/*
-+ * Broadcom specific Advanced Microcontroller Bus
-+ * Broadcom USB-core driver (BCMA bus glue)
-+ *
-+ * Copyright 2011 Hauke Mehrtens <hauke@hauke-m.de>
-+ *
-+ * Based on ssb-ohci driver
-+ * Copyright 2007 Michael Buesch <m@bues.ch>
-+ *
-+ * Derived from the OHCI-PCI driver
-+ * Copyright 1999 Roman Weissgaerber
-+ * Copyright 2000-2002 David Brownell
-+ * Copyright 1999 Linus Torvalds
-+ * Copyright 1999 Gregory P. Smith
-+ *
-+ * Derived from the USBcore related parts of Broadcom-SB
-+ * Copyright 2005-2011 Broadcom Corporation
-+ *
-+ * Licensed under the GNU/GPL. See COPYING for details.
-+ */
-+#include <linux/bcma/bcma.h>
-+#include <linux/delay.h>
-+#include <linux/platform_device.h>
-+#include <linux/module.h>
-+
-+MODULE_AUTHOR("Hauke Mehrtens");
-+MODULE_DESCRIPTION("Common USB driver for BCMA Bus");
-+MODULE_LICENSE("GPL");
-+
-+struct bcma_hcd_device {
-+	struct platform_device *ehci_dev;
-+	struct platform_device *ohci_dev;
-+};
-+
-+static void __devinit bcma_hcd_4716wa(struct bcma_device *dev)
-+{
-+#ifdef CONFIG_BCMA_DRIVER_MIPS
-+	/* Work around for 4716 failures. */
-+	if (dev->bus->chipinfo.id == 0x4716) {
-+		u32 tmp;
-+
-+		tmp = bcma_cpu_clock(&dev->bus->drv_mips);
-+		if (tmp >= 480000000)
-+			tmp = 0x1846b; /* set CDR to 0x11(fast) */
-+		else if (tmp == 453000000)
-+			tmp = 0x1046b; /* set CDR to 0x10(slow) */
-+		else
-+			tmp = 0;
-+
-+		/* Change Shim mdio control reg to fix host not acking at
-+		 * high frequencies
-+		 */
-+		if (tmp) {
-+			bcma_write32(dev, 0x524, 0x1); /* write sel to enable */
-+			udelay(500);
-+
-+			bcma_write32(dev, 0x524, tmp);
-+			udelay(500);
-+			bcma_write32(dev, 0x524, 0x4ab);
-+			udelay(500);
-+			bcma_read32(dev, 0x528);
-+			bcma_write32(dev, 0x528, 0x80000000);
-+		}
-+	}
-+#endif /* CONFIG_BCMA_DRIVER_MIPS */
-+}
-+
-+/* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */
-+static void __devinit bcma_hcd_init_chip(struct bcma_device *dev)
-+{
-+	u32 tmp;
-+
-+	/*
-+	 * USB 2.0 special considerations:
-+	 *
-+	 * 1. Since the core supports both OHCI and EHCI functions, it must
-+	 *    only be reset once.
-+	 *
-+	 * 2. In addition to the standard SI reset sequence, the Host Control
-+	 *    Register must be programmed to bring the USB core and various
-+	 *    phy components out of reset.
-+	 */
-+	if (!bcma_core_is_enabled(dev)) {
-+		bcma_core_enable(dev, 0);
-+		mdelay(10);
-+		if (dev->id.rev >= 5) {
-+			/* Enable Misc PLL */
-+			tmp = bcma_read32(dev, 0x1e0);
-+			tmp |= 0x100;
-+			bcma_write32(dev, 0x1e0, tmp);
-+			if (bcma_wait_bits(dev, 0x1e0, 1 << 24, 100, 1))
-+				printk(KERN_EMERG "Failed to enable misc PPL!\n");
-+
-+			/* Take out of resets */
-+			bcma_write32(dev, 0x200, 0x4ff);
-+			udelay(25);
-+			bcma_write32(dev, 0x200, 0x6ff);
-+			udelay(25);
-+
-+			/* Make sure digital and AFE are locked in USB PHY */
-+			bcma_write32(dev, 0x524, 0x6b);
-+			udelay(50);
-+			tmp = bcma_read32(dev, 0x524);
-+			udelay(50);
-+			bcma_write32(dev, 0x524, 0xab);
-+			udelay(50);
-+			tmp = bcma_read32(dev, 0x524);
-+			udelay(50);
-+			bcma_write32(dev, 0x524, 0x2b);
-+			udelay(50);
-+			tmp = bcma_read32(dev, 0x524);
-+			udelay(50);
-+			bcma_write32(dev, 0x524, 0x10ab);
-+			udelay(50);
-+			tmp = bcma_read32(dev, 0x524);
-+
-+			if (bcma_wait_bits(dev, 0x528, 0xc000, 10000, 1)) {
-+				tmp = bcma_read32(dev, 0x528);
-+				printk(KERN_EMERG
-+				       "USB20H mdio_rddata 0x%08x\n", tmp);
-+			}
-+			bcma_write32(dev, 0x528, 0x80000000);
-+			tmp = bcma_read32(dev, 0x314);
-+			udelay(265);
-+			bcma_write32(dev, 0x200, 0x7ff);
-+			udelay(10);
-+
-+			/* Take USB and HSIC out of non-driving modes */
-+			bcma_write32(dev, 0x510, 0);
-+		} else {
-+			bcma_write32(dev, 0x200, 0x7ff);
-+
-+			udelay(1);
-+		}
-+
-+		bcma_hcd_4716wa(dev);
-+	}
-+}
-+
-+static struct platform_device * __devinit
-+bcma_hcd_create_pdev(struct bcma_device *dev, char *name, u32 addr)
-+{
-+	struct platform_device *hci_dev;
-+	struct resource hci_res[2];
-+	int ret = -ENOMEM;
-+
-+	memset(hci_res, 0, sizeof(hci_res));
-+
-+	hci_res[0].start = addr;
-+	hci_res[0].end = hci_res[0].start + 0x1000 - 1;
-+	hci_res[0].flags = IORESOURCE_MEM;
-+
-+	hci_res[1].start = dev->irq;
-+	hci_res[1].flags = IORESOURCE_IRQ;
-+
-+	hci_dev = platform_device_alloc(name, 0);
-+	if (!hci_dev)
-+		goto err_alloc;
-+
-+	hci_dev->dev.parent = &dev->dev;
-+	hci_dev->dev.dma_mask = &hci_dev->dev.coherent_dma_mask;
-+
-+	ret = platform_device_add_resources(hci_dev, hci_res,
-+					    ARRAY_SIZE(hci_res));
-+	if (ret)
-+		goto err_alloc;
-+
-+	ret = platform_device_add(hci_dev);
-+	if (ret) {
-+err_alloc:
-+		platform_device_put(hci_dev);
-+		return ERR_PTR(ret);
-+	}
-+
-+	return hci_dev;
-+}
-+
-+static int __devinit bcma_hcd_probe(struct bcma_device *dev)
-+{
-+	int err;
-+	u16 chipid_top;
-+	u32 ohci_addr;
-+	struct bcma_hcd_device *usb_dev;
-+	struct bcma_chipinfo *chipinfo;
-+
-+	chipinfo = &dev->bus->chipinfo;
-+	/* USBcores are only connected on embedded devices. */
-+	chipid_top = (chipinfo->id & 0xFF00);
-+	if (chipid_top != 0x4700 && chipid_top != 0x5300)
-+		return -ENODEV;
-+
-+	/* TODO: Probably need checks here; is the core connected? */
-+
-+	if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
-+	    dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
-+		return -EOPNOTSUPP;
-+
-+	usb_dev = kzalloc(sizeof(struct bcma_hcd_device), GFP_KERNEL);
-+	if (!usb_dev)
-+		return -ENOMEM;
-+
-+	bcma_hcd_init_chip(dev);
-+
-+	/* In AI chips EHCI is addrspace 0, OHCI is 1 */
-+	ohci_addr = dev->addr1;
-+	if ((chipinfo->id == 0x5357 || chipinfo->id == 0x4749)
-+	    && chipinfo->rev == 0)
-+		ohci_addr = 0x18009000;
-+
-+	usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, "ohci-platform",
-+						 ohci_addr);
-+	if (IS_ERR(usb_dev->ohci_dev)) {
-+		err = PTR_ERR(usb_dev->ohci_dev);
-+		goto err_free_usb_dev;
-+	}
-+
-+	usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, "ehci-platform",
-+						 dev->addr);
-+	if (IS_ERR(usb_dev->ehci_dev)) {
-+		err = PTR_ERR(usb_dev->ehci_dev);
-+		goto err_unregister_ohci_dev;
-+	}
-+
-+	bcma_set_drvdata(dev, usb_dev);
-+	return 0;
-+
-+err_unregister_ohci_dev:
-+	platform_device_unregister(usb_dev->ohci_dev);
-+err_free_usb_dev:
-+	kfree(usb_dev);
-+	return err;
-+}
-+
-+static void __devexit bcma_hcd_remove(struct bcma_device *dev)
-+{
-+	struct bcma_hcd_device *usb_dev;
-+	struct platform_device *ohci_dev;
-+	struct platform_device *ehci_dev;
-+
-+	usb_dev = bcma_get_drvdata(dev);
-+	if (!usb_dev)
-+		return;
-+
-+	ohci_dev = usb_dev->ohci_dev;
-+	ehci_dev = usb_dev->ehci_dev;
-+
-+	if (ohci_dev) {
-+		platform_device_unregister(ohci_dev);
-+	}
-+	if (ehci_dev) {
-+		platform_device_unregister(ehci_dev);
-+	}
-+
-+	bcma_core_disable(dev, 0);
-+}
-+
-+static void bcma_hcd_shutdown(struct bcma_device *dev)
-+{
-+	bcma_core_disable(dev, 0);
-+}
-+
-+#ifdef CONFIG_PM
-+
-+static int bcma_hcd_suspend(struct bcma_device *dev, pm_message_t state)
-+{
-+	bcma_core_disable(dev, 0);
-+
-+	return 0;
-+}
-+
-+static int bcma_hcd_resume(struct bcma_device *dev)
-+{
-+	bcma_core_enable(dev, 0);
-+
-+	return 0;
-+}
-+
-+#else /* !CONFIG_PM */
-+#define bcma_hcd_suspend	NULL
-+#define bcma_hcd_resume	NULL
-+#endif /* CONFIG_PM */
-+
-+static const struct bcma_device_id bcma_hcd_table[] __devinitconst = {
-+	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS),
-+	BCMA_CORETABLE_END
-+};
-+MODULE_DEVICE_TABLE(bcma, bcma_hcd_table);
-+
-+static struct bcma_driver bcma_hcd_driver = {
-+	.name		= KBUILD_MODNAME,
-+	.id_table	= bcma_hcd_table,
-+	.probe		= bcma_hcd_probe,
-+	.remove		= __devexit_p(bcma_hcd_remove),
-+	.shutdown	= bcma_hcd_shutdown,
-+	.suspend	= bcma_hcd_suspend,
-+	.resume		= bcma_hcd_resume,
-+};
-+
-+static int __init bcma_hcd_init(void)
-+{
-+	return bcma_driver_register(&bcma_hcd_driver);
-+}
-+module_init(bcma_hcd_init);
-+
-+static void __exit bcma_hcd_exit(void)
-+{
-+	bcma_driver_unregister(&bcma_hcd_driver);
-+}
-+module_exit(bcma_hcd_exit);
diff --git a/target/linux/brcm47xx/patches-3.2/0033-USB-Add-driver-for-the-ssb-bus.patch b/target/linux/brcm47xx/patches-3.2/0033-USB-Add-driver-for-the-ssb-bus.patch
deleted file mode 100644
index f03657d12..000000000
--- a/target/linux/brcm47xx/patches-3.2/0033-USB-Add-driver-for-the-ssb-bus.patch
+++ /dev/null
@@ -1,325 +0,0 @@
-From ca1db834336ac19edc7a5d342f8acece1ae1feb9 Mon Sep 17 00:00:00 2001
-From: Hauke Mehrtens <hauke@hauke-m.de>
-Date: Sat, 26 Nov 2011 21:35:17 +0100
-Subject: [PATCH 20/30] USB: Add driver for the ssb bus
-
-This adds a USB driver using the generic platform device driver for the
-USB controller found on the Broadcom ssb bus. The ssb bus just
-exposes one device which serves the OHCI and the EHCI controller at the
-same time. This driver probes for this USB controller and creates and
-registers two new platform devices which will be probed by the new
-generic platform device driver. This makes it possible to use the EHCI
-and the OCHI controller on the ssb bus at the same time.
-
-The old ssb OHCI USB driver will be removed in the next step as this
-driver also provide an OHCI driver and an EHCI for the cores supporting
-it.
-
-Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
----
- drivers/usb/host/Kconfig   |   12 ++
- drivers/usb/host/Makefile  |    1 +
- drivers/usb/host/ssb-hcd.c |  272 ++++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 285 insertions(+), 0 deletions(-)
- create mode 100644 drivers/usb/host/ssb-hcd.c
-
---- a/drivers/usb/host/Kconfig
-+++ b/drivers/usb/host/Kconfig
-@@ -630,3 +630,15 @@ config USB_HCD_BCMA
- 	  for ehci and ohci.
- 
- 	  If unsure, say N.
-+
-+config USB_HCD_SSB
-+	tristate "SSB usb host driver"
-+	depends on SSB && EXPERIMENTAL
-+	select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD
-+	select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD
-+	help
-+	  Enbale support for the EHCI and OCHI host controller on an bcma bus.
-+	  It converts the bcma driver into two platform device drivers
-+	  for ehci and ohci.
-+
-+	  If unsure, say N.
---- a/drivers/usb/host/Makefile
-+++ b/drivers/usb/host/Makefile
-@@ -38,3 +38,4 @@ obj-$(CONFIG_USB_FSL_MPH_DR_OF)	+= fsl-m
- obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o
- obj-$(CONFIG_MIPS_ALCHEMY)	+= alchemy-common.o
- obj-$(CONFIG_USB_HCD_BCMA)	+= bcma-hcd.o
-+obj-$(CONFIG_USB_HCD_SSB)	+= ssb-hcd.o
---- /dev/null
-+++ b/drivers/usb/host/ssb-hcd.c
-@@ -0,0 +1,272 @@
-+/*
-+ * Sonics Silicon Backplane
-+ * Broadcom USB-core driver  (SSB bus glue)
-+ *
-+ * Copyright 2011 Hauke Mehrtens <hauke@hauke-m.de>
-+ *
-+ * Based on ssb-ohci driver
-+ * Copyright 2007 Michael Buesch <m@bues.ch>
-+ *
-+ * Derived from the OHCI-PCI driver
-+ * Copyright 1999 Roman Weissgaerber
-+ * Copyright 2000-2002 David Brownell
-+ * Copyright 1999 Linus Torvalds
-+ * Copyright 1999 Gregory P. Smith
-+ *
-+ * Derived from the USBcore related parts of Broadcom-SB
-+ * Copyright 2005-2011 Broadcom Corporation
-+ *
-+ * Licensed under the GNU/GPL. See COPYING for details.
-+ */
-+#include <linux/ssb/ssb.h>
-+#include <linux/delay.h>
-+#include <linux/platform_device.h>
-+#include <linux/module.h>
-+
-+MODULE_AUTHOR("Hauke Mehrtens");
-+MODULE_DESCRIPTION("Common USB driver for SSB Bus");
-+MODULE_LICENSE("GPL");
-+
-+#define SSB_HCD_TMSLOW_HOSTMODE	(1 << 29)
-+
-+struct ssb_hcd_device {
-+	struct platform_device *ehci_dev;
-+	struct platform_device *ohci_dev;
-+
-+	u32 enable_flags;
-+};
-+
-+static void __devinit ssb_hcd_5354wa(struct ssb_device *dev)
-+{
-+#ifdef CONFIG_SSB_DRIVER_MIPS
-+	/* Work around for 5354 failures */
-+	if (dev->id.revision == 2 && dev->bus->chip_id == 0x5354) {
-+		/* Change syn01 reg */
-+		ssb_write32(dev, 0x894, 0x00fe00fe);
-+
-+		/* Change syn03 reg */
-+		ssb_write32(dev, 0x89c, ssb_read32(dev, 0x89c) | 0x1);
-+	}
-+#endif
-+}
-+
-+static void __devinit ssb_hcd_usb20wa(struct ssb_device *dev)
-+{
-+	if (dev->id.coreid == SSB_DEV_USB20_HOST) {
-+		/*
-+		 * USB 2.0 special considerations:
-+		 *
-+		 * 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.
-+		 */
-+		ssb_write32(dev, 0x200, 0x7ff);
-+
-+		/* Change Flush control reg */
-+		ssb_write32(dev, 0x400, ssb_read32(dev, 0x400) & ~8);
-+		ssb_read32(dev, 0x400);
-+
-+		/* Change Shim control reg */
-+		ssb_write32(dev, 0x304, ssb_read32(dev, 0x304) & ~0x100);
-+		ssb_read32(dev, 0x304);
-+
-+		udelay(1);
-+
-+		ssb_hcd_5354wa(dev);
-+	}
-+}
-+
-+/* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */
-+static u32 __devinit ssb_hcd_init_chip(struct ssb_device *dev)
-+{
-+	u32 flags = 0;
-+
-+	if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV)
-+		/* Put the device into host-mode. */
-+		flags |= SSB_HCD_TMSLOW_HOSTMODE;
-+
-+	ssb_device_enable(dev, flags);
-+
-+	ssb_hcd_usb20wa(dev);
-+
-+	return flags;
-+}
-+
-+static struct platform_device * __devinit
-+ssb_hcd_create_pdev(struct ssb_device *dev, char *name, u32 addr, u32 len)
-+{
-+	struct platform_device *hci_dev;
-+	struct resource hci_res[2];
-+	int ret = -ENOMEM;
-+
-+	memset(hci_res, 0, sizeof(hci_res));
-+
-+	hci_res[0].start = addr;
-+	hci_res[0].end = hci_res[0].start + len - 1;
-+	hci_res[0].flags = IORESOURCE_MEM;
-+
-+	hci_res[1].start = dev->irq;
-+	hci_res[1].flags = IORESOURCE_IRQ;
-+
-+	hci_dev = platform_device_alloc(name, 0);
-+	if (!hci_dev)
-+		goto err_alloc;
-+
-+	hci_dev->dev.parent = dev->dev;
-+	hci_dev->dev.dma_mask = &hci_dev->dev.coherent_dma_mask;
-+
-+	ret = platform_device_add_resources(hci_dev, hci_res, 2);
-+	if (ret)
-+		goto err_alloc;
-+
-+	ret = platform_device_add(hci_dev);
-+	if (ret) {
-+err_alloc:
-+		platform_device_put(hci_dev);
-+		return ERR_PTR(ret);
-+	}
-+
-+	return hci_dev;
-+}
-+
-+static int __devinit ssb_hcd_probe(struct ssb_device *dev,
-+				   const struct ssb_device_id *id)
-+{
-+	int err, tmp;
-+	int start, len;
-+	u16 chipid_top;
-+	struct ssb_hcd_device *usb_dev;
-+
-+	/* USBcores are only connected on embedded devices. */
-+	chipid_top = (dev->bus->chip_id & 0xFF00);
-+	if (chipid_top != 0x4700 && chipid_top != 0x5300)
-+		return -ENODEV;
-+
-+	/* TODO: Probably need checks here; is the core connected? */
-+
-+	if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
-+	    dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
-+		return -EOPNOTSUPP;
-+
-+	usb_dev = kzalloc(sizeof(struct ssb_hcd_device), GFP_KERNEL);
-+	if (!usb_dev)
-+		return -ENOMEM;
-+
-+	/* We currently always attach SSB_DEV_USB11_HOSTDEV
-+	 * as HOST OHCI. If we want to attach it as Client device,
-+	 * we must branch here and call into the (yet to
-+	 * be written) Client mode driver. Same for remove(). */
-+	usb_dev->enable_flags = ssb_hcd_init_chip(dev);
-+
-+	tmp = ssb_read32(dev, SSB_ADMATCH0);
-+
-+	start = ssb_admatch_base(tmp);
-+	len = ssb_admatch_size(tmp);
-+	usb_dev->ohci_dev = ssb_hcd_create_pdev(dev, "ohci-platform", start,
-+						len);
-+	if (IS_ERR(usb_dev->ohci_dev)) {
-+		err = PTR_ERR(usb_dev->ohci_dev);
-+		goto err_free_usb_dev;
-+	}
-+
-+	if (dev->id.coreid == SSB_DEV_USB20_HOST) {
-+		start = ssb_admatch_base(tmp) + 0x800; /* ehci core offset */
-+		len = 0x100; /* ehci reg block size */
-+		usb_dev->ehci_dev = ssb_hcd_create_pdev(dev, "ehci-platform",
-+							start, len);
-+		if (IS_ERR(usb_dev->ehci_dev)) {
-+			err = PTR_ERR(usb_dev->ehci_dev);
-+			goto err_unregister_ohci_dev;
-+		}
-+	}
-+
-+	ssb_set_drvdata(dev, usb_dev);
-+	return 0;
-+
-+err_unregister_ohci_dev:
-+	platform_device_unregister(usb_dev->ohci_dev);
-+err_free_usb_dev:
-+	kfree(usb_dev);
-+	return err;
-+}
-+
-+static void __devexit ssb_hcd_remove(struct ssb_device *dev)
-+{
-+	struct ssb_hcd_device *usb_dev;
-+	struct platform_device *ohci_dev;
-+	struct platform_device *ehci_dev;
-+
-+	usb_dev = ssb_get_drvdata(dev);
-+	if (!usb_dev)
-+		return;
-+
-+	ohci_dev = usb_dev->ohci_dev;
-+	ehci_dev = usb_dev->ehci_dev;
-+
-+	if (ohci_dev) {
-+		platform_device_unregister(ohci_dev);
-+	}
-+	if (ehci_dev) {
-+		platform_device_unregister(ehci_dev);
-+	}
-+
-+	ssb_device_disable(dev, 0);
-+}
-+
-+static void __devexit ssb_hcd_shutdown(struct ssb_device *dev)
-+{
-+	ssb_device_disable(dev, 0);
-+}
-+
-+#ifdef CONFIG_PM
-+
-+static int ssb_hcd_suspend(struct ssb_device *dev, pm_message_t state)
-+{
-+	ssb_device_disable(dev, 0);
-+
-+	return 0;
-+}
-+
-+static int ssb_hcd_resume(struct ssb_device *dev)
-+{
-+	struct ssb_hcd_device *usb_dev = ssb_get_drvdata(dev);
-+
-+	ssb_device_enable(dev, usb_dev->enable_flags);
-+
-+	return 0;
-+}
-+
-+#else /* !CONFIG_PM */
-+#define ssb_hcd_suspend	NULL
-+#define ssb_hcd_resume	NULL
-+#endif /* CONFIG_PM */
-+
-+static const struct ssb_device_id ssb_hcd_table[] __devinitconst = {
-+	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
-+	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
-+	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
-+	SSB_DEVTABLE_END
-+};
-+MODULE_DEVICE_TABLE(ssb, ssb_hcd_table);
-+
-+static struct ssb_driver ssb_hcd_driver = {
-+	.name		= KBUILD_MODNAME,
-+	.id_table	= ssb_hcd_table,
-+	.probe		= ssb_hcd_probe,
-+	.remove		= __devexit_p(ssb_hcd_remove),
-+	.shutdown	= ssb_hcd_shutdown,
-+	.suspend	= ssb_hcd_suspend,
-+	.resume		= ssb_hcd_resume,
-+};
-+
-+static int __init ssb_hcd_init(void)
-+{
-+	return ssb_driver_register(&ssb_hcd_driver);
-+}
-+module_init(ssb_hcd_init);
-+
-+static void __exit ssb_hcd_exit(void)
-+{
-+	ssb_driver_unregister(&ssb_hcd_driver);
-+}
-+module_exit(ssb_hcd_exit);
diff --git a/target/linux/brcm47xx/patches-3.2/0034-USB-OHCI-remove-old-SSB-OHCI-driver.patch b/target/linux/brcm47xx/patches-3.2/0034-USB-OHCI-remove-old-SSB-OHCI-driver.patch
deleted file mode 100644
index 2e859f1f4..000000000
--- a/target/linux/brcm47xx/patches-3.2/0034-USB-OHCI-remove-old-SSB-OHCI-driver.patch
+++ /dev/null
@@ -1,357 +0,0 @@
-From 77190e21ed262397eb924e6d48e12ecf3e9f6316 Mon Sep 17 00:00:00 2001
-From: Hauke Mehrtens <hauke@hauke-m.de>
-Date: Sat, 26 Nov 2011 21:36:50 +0100
-Subject: [PATCH 21/30] USB: OHCI: remove old SSB OHCI driver
-
-This is now replaced by the new ssb USB driver, which also supports
-devices with an EHCI controller.
-
-Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
----
- drivers/usb/host/Kconfig    |   13 --
- drivers/usb/host/ohci-hcd.c |   19 ---
- drivers/usb/host/ohci-ssb.c |  260 -------------------------------------------
- 3 files changed, 0 insertions(+), 292 deletions(-)
- delete mode 100644 drivers/usb/host/ohci-ssb.c
-
---- a/drivers/usb/host/Kconfig
-+++ b/drivers/usb/host/Kconfig
-@@ -351,19 +351,6 @@ config USB_OHCI_HCD_PCI
- 	  Enables support for PCI-bus plug-in USB controller cards.
- 	  If unsure, say Y.
- 
--config USB_OHCI_HCD_SSB
--	bool "OHCI support for Broadcom SSB OHCI core"
--	depends on USB_OHCI_HCD && (SSB = y || SSB = USB_OHCI_HCD) && EXPERIMENTAL
--	default n
--	---help---
--	  Support for the Sonics Silicon Backplane (SSB) attached
--	  Broadcom USB OHCI core.
--
--	  This device is present in some embedded devices with
--	  Broadcom based SSB bus.
--
--	  If unsure, say N.
--
- config USB_OHCI_SH
- 	bool "OHCI support for SuperH USB controller"
- 	depends on USB_OHCI_HCD && SUPERH
---- a/drivers/usb/host/ohci-hcd.c
-+++ b/drivers/usb/host/ohci-hcd.c
-@@ -1076,11 +1076,6 @@ MODULE_LICENSE ("GPL");
- #define PS3_SYSTEM_BUS_DRIVER	ps3_ohci_driver
- #endif
- 
--#ifdef CONFIG_USB_OHCI_HCD_SSB
--#include "ohci-ssb.c"
--#define SSB_OHCI_DRIVER		ssb_ohci_driver
--#endif
--
- #ifdef CONFIG_MFD_SM501
- #include "ohci-sm501.c"
- #define SM501_OHCI_DRIVER	ohci_hcd_sm501_driver
-@@ -1130,7 +1125,6 @@ MODULE_LICENSE ("GPL");
- 	!defined(PS3_SYSTEM_BUS_DRIVER) && \
- 	!defined(SM501_OHCI_DRIVER) && \
- 	!defined(TMIO_OHCI_DRIVER) && \
--	!defined(SSB_OHCI_DRIVER) && \
- 	!defined(PLATFORM_OHCI_DRIVER)
- #error "missing bus glue for ohci-hcd"
- #endif
-@@ -1197,12 +1191,6 @@ static int __init ohci_hcd_mod_init(void
- 		goto error_pci;
- #endif
- 
--#ifdef SSB_OHCI_DRIVER
--	retval = ssb_driver_register(&SSB_OHCI_DRIVER);
--	if (retval)
--		goto error_ssb;
--#endif
--
- #ifdef SM501_OHCI_DRIVER
- 	retval = platform_driver_register(&SM501_OHCI_DRIVER);
- 	if (retval < 0)
-@@ -1236,10 +1224,6 @@ static int __init ohci_hcd_mod_init(void
- 	platform_driver_unregister(&SM501_OHCI_DRIVER);
-  error_sm501:
- #endif
--#ifdef SSB_OHCI_DRIVER
--	ssb_driver_unregister(&SSB_OHCI_DRIVER);
-- error_ssb:
--#endif
- #ifdef PCI_DRIVER
- 	pci_unregister_driver(&PCI_DRIVER);
-  error_pci:
-@@ -1290,9 +1274,6 @@ static void __exit ohci_hcd_mod_exit(voi
- #ifdef SM501_OHCI_DRIVER
- 	platform_driver_unregister(&SM501_OHCI_DRIVER);
- #endif
--#ifdef SSB_OHCI_DRIVER
--	ssb_driver_unregister(&SSB_OHCI_DRIVER);
--#endif
- #ifdef PCI_DRIVER
- 	pci_unregister_driver(&PCI_DRIVER);
- #endif
---- a/drivers/usb/host/ohci-ssb.c
-+++ /dev/null
-@@ -1,260 +0,0 @@
--/*
-- * Sonics Silicon Backplane
-- * Broadcom USB-core OHCI driver
-- *
-- * Copyright 2007 Michael Buesch <m@bues.ch>
-- *
-- * Derived from the OHCI-PCI driver
-- * Copyright 1999 Roman Weissgaerber
-- * Copyright 2000-2002 David Brownell
-- * Copyright 1999 Linus Torvalds
-- * Copyright 1999 Gregory P. Smith
-- *
-- * Derived from the USBcore related parts of Broadcom-SB
-- * Copyright 2005 Broadcom Corporation
-- *
-- * Licensed under the GNU/GPL. See COPYING for details.
-- */
--#include <linux/ssb/ssb.h>
--
--
--#define SSB_OHCI_TMSLOW_HOSTMODE	(1 << 29)
--
--struct ssb_ohci_device {
--	struct ohci_hcd ohci; /* _must_ be at the beginning. */
--
--	u32 enable_flags;
--};
--
--static inline
--struct ssb_ohci_device *hcd_to_ssb_ohci(struct usb_hcd *hcd)
--{
--	return (struct ssb_ohci_device *)(hcd->hcd_priv);
--}
--
--
--static int ssb_ohci_reset(struct usb_hcd *hcd)
--{
--	struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
--	struct ohci_hcd *ohci = &ohcidev->ohci;
--	int err;
--
--	ohci_hcd_init(ohci);
--	err = ohci_init(ohci);
--
--	return err;
--}
--
--static int ssb_ohci_start(struct usb_hcd *hcd)
--{
--	struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
--	struct ohci_hcd *ohci = &ohcidev->ohci;
--	int err;
--
--	err = ohci_run(ohci);
--	if (err < 0) {
--		ohci_err(ohci, "can't start\n");
--		ohci_stop(hcd);
--	}
--
--	return err;
--}
--
--static const struct hc_driver ssb_ohci_hc_driver = {
--	.description		= "ssb-usb-ohci",
--	.product_desc		= "SSB OHCI Controller",
--	.hcd_priv_size		= sizeof(struct ssb_ohci_device),
--
--	.irq			= ohci_irq,
--	.flags			= HCD_MEMORY | HCD_USB11,
--
--	.reset			= ssb_ohci_reset,
--	.start			= ssb_ohci_start,
--	.stop			= ohci_stop,
--	.shutdown		= ohci_shutdown,
--
--	.urb_enqueue		= ohci_urb_enqueue,
--	.urb_dequeue		= ohci_urb_dequeue,
--	.endpoint_disable	= ohci_endpoint_disable,
--
--	.get_frame_number	= ohci_get_frame,
--
--	.hub_status_data	= ohci_hub_status_data,
--	.hub_control		= ohci_hub_control,
--#ifdef	CONFIG_PM
--	.bus_suspend		= ohci_bus_suspend,
--	.bus_resume		= ohci_bus_resume,
--#endif
--
--	.start_port_reset	= ohci_start_port_reset,
--};
--
--static void ssb_ohci_detach(struct ssb_device *dev)
--{
--	struct usb_hcd *hcd = ssb_get_drvdata(dev);
--
--	if (hcd->driver->shutdown)
--		hcd->driver->shutdown(hcd);
--	usb_remove_hcd(hcd);
--	iounmap(hcd->regs);
--	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
--	usb_put_hcd(hcd);
--	ssb_device_disable(dev, 0);
--}
--
--static int ssb_ohci_attach(struct ssb_device *dev)
--{
--	struct ssb_ohci_device *ohcidev;
--	struct usb_hcd *hcd;
--	int err = -ENOMEM;
--	u32 tmp, flags = 0;
--
--	if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
--	    dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
--		return -EOPNOTSUPP;
--
--	if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
--		/* Put the device into host-mode. */
--		flags |= SSB_OHCI_TMSLOW_HOSTMODE;
--		ssb_device_enable(dev, flags);
--	} else if (dev->id.coreid == SSB_DEV_USB20_HOST) {
--		/*
--		 * USB 2.0 special considerations:
--		 *
--		 * 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.
--		 */
--		ssb_device_enable(dev, 0);
--		ssb_write32(dev, 0x200, 0x7ff);
--
--		/* Change Flush control reg */
--		tmp = ssb_read32(dev, 0x400);
--		tmp &= ~8;
--		ssb_write32(dev, 0x400, tmp);
--		tmp = ssb_read32(dev, 0x400);
--
--		/* Change Shim control reg */
--		tmp = ssb_read32(dev, 0x304);
--		tmp &= ~0x100;
--		ssb_write32(dev, 0x304, tmp);
--		tmp = ssb_read32(dev, 0x304);
--
--		udelay(1);
--
--		/* Work around for 5354 failures */
--		if (dev->id.revision == 2 && dev->bus->chip_id == 0x5354) {
--			/* Change syn01 reg */
--			tmp = 0x00fe00fe;
--			ssb_write32(dev, 0x894, tmp);
--
--			/* Change syn03 reg */
--			tmp = ssb_read32(dev, 0x89c);
--			tmp |= 0x1;
--			ssb_write32(dev, 0x89c, tmp);
--		}
--	} else
--		ssb_device_enable(dev, 0);
--
--	hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev,
--			dev_name(dev->dev));
--	if (!hcd)
--		goto err_dev_disable;
--	ohcidev = hcd_to_ssb_ohci(hcd);
--	ohcidev->enable_flags = flags;
--
--	tmp = ssb_read32(dev, SSB_ADMATCH0);
--	hcd->rsrc_start = ssb_admatch_base(tmp);
--	hcd->rsrc_len = ssb_admatch_size(tmp);
--	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
--	if (!hcd->regs)
--		goto err_put_hcd;
--	err = usb_add_hcd(hcd, dev->irq, IRQF_SHARED);
--	if (err)
--		goto err_iounmap;
--
--	ssb_set_drvdata(dev, hcd);
--
--	return err;
--
--err_iounmap:
--	iounmap(hcd->regs);
--err_put_hcd:
--	usb_put_hcd(hcd);
--err_dev_disable:
--	ssb_device_disable(dev, flags);
--	return err;
--}
--
--static int ssb_ohci_probe(struct ssb_device *dev,
--		const struct ssb_device_id *id)
--{
--	int err;
--	u16 chipid_top;
--
--	/* USBcores are only connected on embedded devices. */
--	chipid_top = (dev->bus->chip_id & 0xFF00);
--	if (chipid_top != 0x4700 && chipid_top != 0x5300)
--		return -ENODEV;
--
--	/* TODO: Probably need checks here; is the core connected? */
--
--	if (usb_disabled())
--		return -ENODEV;
--
--	/* We currently always attach SSB_DEV_USB11_HOSTDEV
--	 * as HOST OHCI. If we want to attach it as Client device,
--	 * we must branch here and call into the (yet to
--	 * be written) Client mode driver. Same for remove(). */
--
--	err = ssb_ohci_attach(dev);
--
--	return err;
--}
--
--static void ssb_ohci_remove(struct ssb_device *dev)
--{
--	ssb_ohci_detach(dev);
--}
--
--#ifdef CONFIG_PM
--
--static int ssb_ohci_suspend(struct ssb_device *dev, pm_message_t state)
--{
--	ssb_device_disable(dev, 0);
--
--	return 0;
--}
--
--static int ssb_ohci_resume(struct ssb_device *dev)
--{
--	struct usb_hcd *hcd = ssb_get_drvdata(dev);
--	struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
--
--	ssb_device_enable(dev, ohcidev->enable_flags);
--
--	ohci_finish_controller_resume(hcd);
--	return 0;
--}
--
--#else /* !CONFIG_PM */
--#define ssb_ohci_suspend	NULL
--#define ssb_ohci_resume	NULL
--#endif /* CONFIG_PM */
--
--static const struct ssb_device_id ssb_ohci_table[] = {
--	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
--	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
--	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
--	SSB_DEVTABLE_END
--};
--MODULE_DEVICE_TABLE(ssb, ssb_ohci_table);
--
--static struct ssb_driver ssb_ohci_driver = {
--	.name		= KBUILD_MODNAME,
--	.id_table	= ssb_ohci_table,
--	.probe		= ssb_ohci_probe,
--	.remove		= ssb_ohci_remove,
--	.suspend	= ssb_ohci_suspend,
--	.resume		= ssb_ohci_resume,
--};
diff --git a/target/linux/brcm47xx/patches-3.2/180-USB-HCI-add-struct-for-ehci-and-ohci-platform-driver.patch b/target/linux/brcm47xx/patches-3.2/180-USB-HCI-add-struct-for-ehci-and-ohci-platform-driver.patch
new file mode 100644
index 000000000..73d79a369
--- /dev/null
+++ b/target/linux/brcm47xx/patches-3.2/180-USB-HCI-add-struct-for-ehci-and-ohci-platform-driver.patch
@@ -0,0 +1,48 @@
+From d85bba4eb399a8273aabaef5c21c89820d7a0514 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Thu, 9 Feb 2012 23:14:57 +0100
+Subject: [PATCH 180/186] USB: HCI: add struct for ehci and ohci platform
+ driver
+
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ include/linux/usb/hci_driver.h |   32 ++++++++++++++++++++++++++++++++
+ 1 files changed, 32 insertions(+), 0 deletions(-)
+ create mode 100644 include/linux/usb/hci_driver.h
+
+--- /dev/null
++++ b/include/linux/usb/hci_driver.h
+@@ -0,0 +1,32 @@
++/*
++ * Copyright (C) 2012 Hauke Mehrtens <hauke@hauke-m.de>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef __USB_CORE_HCI_PDRIVER_H
++#define __USB_CORE_HCI_PDRIVER_H
++
++#define USB_HCI_PDATA_PORT_POWER_SET (1 << 0)
++#define USB_HCI_PDATA_HAS_TT_SET (1 << 1)
++
++struct usb_hci_pdata {
++	int		flags;
++	int		caps_offset;
++	unsigned	has_tt:1;
++	unsigned	power_set_is_on:1;
++};
++
++#endif /* __USB_CORE_HCI_PDRIVER_H */
diff --git a/target/linux/brcm47xx/patches-3.2/181-USB-OHCI-Add-a-generic-platform-device-driver.patch b/target/linux/brcm47xx/patches-3.2/181-USB-OHCI-Add-a-generic-platform-device-driver.patch
new file mode 100644
index 000000000..8832f22fa
--- /dev/null
+++ b/target/linux/brcm47xx/patches-3.2/181-USB-OHCI-Add-a-generic-platform-device-driver.patch
@@ -0,0 +1,237 @@
+From 2232a2ab6015496fecdfad68a9d6794312a9b2f2 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Sat, 26 Nov 2011 21:20:54 +0100
+Subject: [PATCH 181/186] USB: OHCI: Add a generic platform device driver
+
+This adds a generic driver for platform devices. It works like the PCI
+driver and is based on it. This is for devices which do not have an own
+bus but their OHCI controller works like a PCI controller. It will be
+used for the Broadcom bcma and ssb USB OHCI controller.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ drivers/usb/host/Kconfig         |   10 ++
+ drivers/usb/host/ohci-hcd.c      |    5 +
+ drivers/usb/host/ohci-platform.c |  183 ++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 198 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/usb/host/ohci-platform.c
+
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -378,6 +378,16 @@ config USB_CNS3XXX_OHCI
+ 	  Enable support for the CNS3XXX SOC's on-chip OHCI controller.
+ 	  It is needed for low-speed USB 1.0 device support.
+ 
++config USB_OHCI_HCD_PLATFORM
++	bool "OHCI driver for a platform device"
++	depends on USB_OHCI_HCD && EXPERIMENTAL
++	default n
++	---help---
++	  Adds an OHCI host driver for a generic platform device, which
++	  provieds a memory space and an irq.
++
++	  If unsure, say N.
++
+ config USB_OHCI_BIG_ENDIAN_DESC
+ 	bool
+ 	depends on USB_OHCI_HCD
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -1116,6 +1116,11 @@ MODULE_LICENSE ("GPL");
+ #define PLATFORM_DRIVER		ohci_xls_driver
+ #endif
+ 
++#ifdef CONFIG_USB_OHCI_HCD_PLATFORM
++#include "ohci-platform.c"
++#define PLATFORM_DRIVER		ohci_platform_driver
++#endif
++
+ #if	!defined(PCI_DRIVER) &&		\
+ 	!defined(PLATFORM_DRIVER) &&	\
+ 	!defined(OMAP1_PLATFORM_DRIVER) &&	\
+--- /dev/null
++++ b/drivers/usb/host/ohci-platform.c
+@@ -0,0 +1,183 @@
++/*
++ * Generic platform ohci driver
++ *
++ * Copyright 2007 Michael Buesch <m@bues.ch>
++ * Copyright 2011-2012 Hauke Mehrtens <hauke@hauke-m.de>
++ *
++ * Derived from the OCHI-SSB driver
++ * Derived from the OHCI-PCI driver
++ * Copyright 1999 Roman Weissgaerber
++ * Copyright 2000-2002 David Brownell
++ * Copyright 1999 Linus Torvalds
++ * Copyright 1999 Gregory P. Smith
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++#include <linux/platform_device.h>
++#include <linux/usb/hci_driver.h>
++
++static int ohci_platform_reset(struct usb_hcd *hcd)
++{
++	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
++	int err;
++
++	ohci_hcd_init(ohci);
++	err = ohci_init(ohci);
++
++	return err;
++}
++
++static int ohci_platform_start(struct usb_hcd *hcd)
++{
++	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
++	int err;
++
++	err = ohci_run(ohci);
++	if (err < 0) {
++		ohci_err(ohci, "can't start\n");
++		ohci_stop(hcd);
++	}
++
++	return err;
++}
++
++static const struct hc_driver ohci_platform_hc_driver = {
++	.description		= hcd_name,
++	.product_desc		= "Generic Platform OHCI Controller",
++	.hcd_priv_size		= sizeof(struct ohci_hcd),
++
++	.irq			= ohci_irq,
++	.flags			= HCD_MEMORY | HCD_USB11,
++
++	.reset			= ohci_platform_reset,
++	.start			= ohci_platform_start,
++	.stop			= ohci_stop,
++	.shutdown		= ohci_shutdown,
++
++	.urb_enqueue		= ohci_urb_enqueue,
++	.urb_dequeue		= ohci_urb_dequeue,
++	.endpoint_disable	= ohci_endpoint_disable,
++
++	.get_frame_number	= ohci_get_frame,
++
++	.hub_status_data	= ohci_hub_status_data,
++	.hub_control		= ohci_hub_control,
++#ifdef	CONFIG_PM
++	.bus_suspend		= ohci_bus_suspend,
++	.bus_resume		= ohci_bus_resume,
++#endif
++
++	.start_port_reset	= ohci_start_port_reset,
++};
++
++static int __devinit ohci_platform_probe(struct platform_device *dev)
++{
++	struct usb_hcd *hcd;
++	struct resource *res_mem;
++	int irq;
++	int err = -ENOMEM;
++
++	if (usb_disabled())
++		return -ENODEV;
++
++	irq = platform_get_irq(dev, 0);
++	if (irq < 0) {
++		pr_err("no irq provieded");
++		return irq;
++	}
++
++	res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
++	if (!res_mem) {
++		pr_err("no memory recourse provieded");
++		return -ENXIO;
++	}
++
++	hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev,
++			dev_name(&dev->dev));
++	if (!hcd)
++		return -ENOMEM;
++
++	hcd->rsrc_start = res_mem->start;
++	hcd->rsrc_len = resource_size(res_mem);
++
++	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
++		pr_err("controller already in use");
++		err = -EBUSY;
++		goto err_put_hcd;
++	}
++
++	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
++	if (!hcd->regs)
++		goto err_release_region;
++	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
++	if (err)
++		goto err_iounmap;
++
++	platform_set_drvdata(dev, hcd);
++
++	return err;
++
++err_iounmap:
++	iounmap(hcd->regs);
++err_release_region:
++	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
++err_put_hcd:
++	usb_put_hcd(hcd);
++	return err;
++}
++
++static int __devexit ohci_platform_remove(struct platform_device *dev)
++{
++	struct usb_hcd *hcd = platform_get_drvdata(dev);
++
++	usb_remove_hcd(hcd);
++	iounmap(hcd->regs);
++	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
++	usb_put_hcd(hcd);
++	platform_set_drvdata(dev, NULL);
++
++	return 0;
++}
++
++#ifdef CONFIG_PM
++
++static int ohci_platform_suspend(struct device *dev)
++{
++	return 0;
++}
++
++static int ohci_platform_resume(struct device *dev)
++{
++	struct usb_hcd *hcd = dev_get_drvdata(dev);
++
++	ohci_finish_controller_resume(hcd);
++	return 0;
++}
++
++#else /* !CONFIG_PM */
++#define ohci_platform_suspend	NULL
++#define ohci_platform_resume	NULL
++#endif /* CONFIG_PM */
++
++static const struct platform_device_id ohci_platform_table[] = {
++	{ "ohci-platform", 0 },
++	{ }
++};
++MODULE_DEVICE_TABLE(platform, ohci_platform_table);
++
++static const struct dev_pm_ops ohci_platform_pm_ops = {
++	.suspend	= ohci_platform_suspend,
++	.resume		= ohci_platform_resume,
++};
++
++static struct platform_driver ohci_platform_driver = {
++	.id_table	= ohci_platform_table,
++	.probe		= ohci_platform_probe,
++	.remove		= __devexit_p(ohci_platform_remove),
++	.shutdown	= usb_hcd_platform_shutdown,
++	.driver		= {
++		.owner	= THIS_MODULE,
++		.name	= "ohci-platform",
++		.pm	= &ohci_platform_pm_ops,
++	}
++};
diff --git a/target/linux/brcm47xx/patches-3.2/182-USB-EHCI-Add-a-generic-platform-device-driver.patch b/target/linux/brcm47xx/patches-3.2/182-USB-EHCI-Add-a-generic-platform-device-driver.patch
new file mode 100644
index 000000000..9a8b0cd0f
--- /dev/null
+++ b/target/linux/brcm47xx/patches-3.2/182-USB-EHCI-Add-a-generic-platform-device-driver.patch
@@ -0,0 +1,253 @@
+From 1be00523336ac484c52681f838dfb8a76e8531cd Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Sat, 26 Nov 2011 21:28:56 +0100
+Subject: [PATCH 182/186] USB: EHCI: Add a generic platform device driver
+
+This adds a generic driver for platform devices. It works like the PCI
+driver and is based on it. This is for devices which do not have an own
+bus but their EHCI controller works like a PCI controller. It will be
+used for the Broadcom bcma and ssb USB EHCI controller.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ drivers/usb/host/Kconfig         |   10 ++
+ drivers/usb/host/ehci-hcd.c      |    5 +
+ drivers/usb/host/ehci-platform.c |  199 ++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 214 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/usb/host/ehci-platform.c
+
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -388,6 +388,16 @@ config USB_OHCI_HCD_PLATFORM
+ 
+ 	  If unsure, say N.
+ 
++config USB_EHCI_HCD_PLATFORM
++	bool "Generic EHCI driver for a platform device"
++	depends on USB_EHCI_HCD && EXPERIMENTAL
++	default n
++	---help---
++	  Adds an EHCI host driver for a generic platform device, which
++	  provieds a memory space and an irq.
++
++	  If unsure, say N.
++
+ config USB_OHCI_BIG_ENDIAN_DESC
+ 	bool
+ 	depends on USB_OHCI_HCD
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1329,6 +1329,11 @@ MODULE_LICENSE ("GPL");
+ #define PLATFORM_DRIVER		ehci_xls_driver
+ #endif
+ 
++#ifdef CONFIG_USB_EHCI_HCD_PLATFORM
++#include "ehci-platform.c"
++#define PLATFORM_DRIVER		ehci_platform_driver
++#endif
++
+ #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
+     !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
+     !defined(XILINX_OF_PLATFORM_DRIVER)
+--- /dev/null
++++ b/drivers/usb/host/ehci-platform.c
+@@ -0,0 +1,199 @@
++/*
++ * Generic platform ehci driver
++ *
++ * Copyright 2007 Steven Brown <sbrown@cortland.com>
++ * Copyright 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
++ *
++ * Derived from the ohci-ssb driver
++ * Copyright 2007 Michael Buesch <m@bues.ch>
++ *
++ * Derived from the EHCI-PCI driver
++ * Copyright (c) 2000-2004 by David Brownell
++ *
++ * Derived from the ohci-pci driver
++ * Copyright 1999 Roman Weissgaerber
++ * Copyright 2000-2002 David Brownell
++ * Copyright 1999 Linus Torvalds
++ * Copyright 1999 Gregory P. Smith
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++#include <linux/platform_device.h>
++#include <linux/usb/hci_driver.h>
++
++static int ehci_platform_reset(struct usb_hcd *hcd)
++{
++	struct platform_device *pdev = to_platform_device(hcd->self.controller);
++	struct usb_hci_pdata *pdata = pdev->dev.platform_data;
++	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
++	int caps_offset = 0;
++	int flags = 0;
++	int retval;
++
++	if (pdata) {
++		caps_offset = pdata->caps_offset;
++		flags = pdata->flags;
++	}
++
++	if (flags & USB_HCI_PDATA_HAS_TT_SET)
++		hcd->has_tt = pdata->has_tt;
++
++	ehci->caps = hcd->regs + caps_offset;
++	retval = ehci_setup(hcd);
++	if (retval)
++		return retval;
++
++	if (flags & USB_HCI_PDATA_PORT_POWER_SET)
++		ehci_port_power(ehci, pdata->power_set_is_on);
++
++	return 0;
++}
++
++static const struct hc_driver ehci_platform_hc_driver = {
++	.description		= hcd_name,
++	.product_desc		= "Generic Platform EHCI Controller",
++	.hcd_priv_size		= sizeof(struct ehci_hcd),
++
++	.irq			= ehci_irq,
++	.flags			= HCD_MEMORY | HCD_USB2,
++
++	.reset			= ehci_platform_reset,
++	.start			= ehci_run,
++	.stop			= ehci_stop,
++	.shutdown		= ehci_shutdown,
++
++	.urb_enqueue		= ehci_urb_enqueue,
++	.urb_dequeue		= ehci_urb_dequeue,
++	.endpoint_disable	= ehci_endpoint_disable,
++	.endpoint_reset		= ehci_endpoint_reset,
++
++	.get_frame_number	= ehci_get_frame,
++
++	.hub_status_data	= ehci_hub_status_data,
++	.hub_control		= ehci_hub_control,
++#if defined(CONFIG_PM)
++	.bus_suspend		= ehci_bus_suspend,
++	.bus_resume		= ehci_bus_resume,
++#endif
++	.relinquish_port	= ehci_relinquish_port,
++	.port_handed_over	= ehci_port_handed_over,
++
++	.update_device		= ehci_update_device,
++
++	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
++};
++
++static int __devinit ehci_platform_probe(struct platform_device *dev)
++{
++	struct usb_hcd *hcd;
++	struct resource *res_mem;
++	int irq;
++	int err = -ENOMEM;
++
++	if (usb_disabled())
++		return -ENODEV;
++
++	irq = platform_get_irq(dev, 0);
++	if (irq < 0) {
++		pr_err("no irq provieded");
++		return irq;
++	}
++	res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
++	if (!res_mem) {
++		pr_err("no memory recourse provieded");
++		return -ENXIO;
++	}
++
++	hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
++			     dev_name(&dev->dev));
++	if (!hcd)
++		return -ENOMEM;
++
++	hcd->rsrc_start = res_mem->start;
++	hcd->rsrc_len = resource_size(res_mem);
++
++	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
++		pr_err("controller already in use");
++		err = -EBUSY;
++		goto err_put_hcd;
++	}
++
++	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
++	if (!hcd->regs)
++		goto err_release_region;
++	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
++	if (err)
++		goto err_iounmap;
++
++	platform_set_drvdata(dev, hcd);
++
++	return err;
++
++err_iounmap:
++	iounmap(hcd->regs);
++err_release_region:
++	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
++err_put_hcd:
++	usb_put_hcd(hcd);
++	return err;
++}
++
++static int __devexit ehci_platform_remove(struct platform_device *dev)
++{
++	struct usb_hcd *hcd = platform_get_drvdata(dev);
++
++	usb_remove_hcd(hcd);
++	iounmap(hcd->regs);
++	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
++	usb_put_hcd(hcd);
++	platform_set_drvdata(dev, NULL);
++
++	return 0;
++}
++
++#ifdef CONFIG_PM
++
++static int ehci_platform_suspend(struct device *dev)
++{
++	struct usb_hcd *hcd = dev_get_drvdata(dev);
++	bool wakeup = device_may_wakeup(dev);
++
++	ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd), wakeup);
++	return 0;
++}
++
++static int ehci_platform_resume(struct device *dev)
++{
++	struct usb_hcd *hcd = dev_get_drvdata(dev);
++
++	ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd));
++	return 0;
++}
++
++#else /* !CONFIG_PM */
++#define ehci_platform_suspend	NULL
++#define ehci_platform_resume	NULL
++#endif /* CONFIG_PM */
++
++static const struct platform_device_id ehci_platform_table[] = {
++	{ "ehci-platform", 0 },
++	{ }
++};
++MODULE_DEVICE_TABLE(platform, ehci_platform_table);
++
++static const struct dev_pm_ops ehci_platform_pm_ops = {
++	.suspend	= ehci_platform_suspend,
++	.resume		= ehci_platform_resume,
++};
++
++static struct platform_driver ehci_platform_driver = {
++	.id_table	= ehci_platform_table,
++	.probe		= ehci_platform_probe,
++	.remove		= __devexit_p(ehci_platform_remove),
++	.shutdown	= usb_hcd_platform_shutdown,
++	.driver		= {
++		.owner	= THIS_MODULE,
++		.name	= "ehci-platform",
++		.pm	= &ehci_platform_pm_ops,
++	}
++};
diff --git a/target/linux/brcm47xx/patches-3.2/183-bcma-scan-for-extra-address-space.patch b/target/linux/brcm47xx/patches-3.2/183-bcma-scan-for-extra-address-space.patch
new file mode 100644
index 000000000..29fdfce20
--- /dev/null
+++ b/target/linux/brcm47xx/patches-3.2/183-bcma-scan-for-extra-address-space.patch
@@ -0,0 +1,61 @@
+From adebff2358c2b631fc04e31ba87eee48e546c655 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Sun, 20 Nov 2011 18:22:35 +0100
+Subject: [PATCH 183/186] bcma: scan for extra address space
+
+Some cores like the USB core have two address spaces. In the USB host
+controller one address space is used for the OHCI and the other for the
+EHCI controller interface. The USB controller is the only core I found
+with two address spaces. This code is based on the AI scan function
+ai_scan() in shared/aiutils.c i the Broadcom SDK.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ drivers/bcma/scan.c       |   18 +++++++++++++++++-
+ include/linux/bcma/bcma.h |    1 +
+ 2 files changed, 18 insertions(+), 1 deletions(-)
+
+--- a/drivers/bcma/scan.c
++++ b/drivers/bcma/scan.c
+@@ -297,6 +297,22 @@ static int bcma_get_next_core(struct bcm
+ 			return -EILSEQ;
+ 	}
+ 
++
++	/* First Slave Address Descriptor should be port 0:
++	 * the main register space for the core
++	 */
++	tmp = bcma_erom_get_addr_desc(bus, eromptr, SCAN_ADDR_TYPE_SLAVE, 0);
++	if (tmp <= 0) {
++		/* Try again to see if it is a bridge */
++		tmp = bcma_erom_get_addr_desc(bus, eromptr,
++					      SCAN_ADDR_TYPE_BRIDGE, 0);
++		if (tmp > 0) {
++			pr_info("found bridge");
++			return -ENXIO;
++		}
++	}
++	core->addr = tmp;
++
+ 	/* get & parse slave ports */
+ 	for (i = 0; i < ports[1]; i++) {
+ 		for (j = 0; ; j++) {
+@@ -309,7 +325,7 @@ static int bcma_get_next_core(struct bcm
+ 				break;
+ 			} else {
+ 				if (i == 0 && j == 0)
+-					core->addr = tmp;
++					core->addr1 = tmp;
+ 			}
+ 		}
+ 	}
+--- a/include/linux/bcma/bcma.h
++++ b/include/linux/bcma/bcma.h
+@@ -139,6 +139,7 @@ struct bcma_device {
+ 	u8 core_unit;
+ 
+ 	u32 addr;
++	u32 addr1;
+ 	u32 wrap;
+ 
+ 	void __iomem *io_addr;
diff --git a/target/linux/brcm47xx/patches-3.2/184-USB-Add-driver-for-the-bcma-bus.patch b/target/linux/brcm47xx/patches-3.2/184-USB-Add-driver-for-the-bcma-bus.patch
new file mode 100644
index 000000000..259af4f1a
--- /dev/null
+++ b/target/linux/brcm47xx/patches-3.2/184-USB-Add-driver-for-the-bcma-bus.patch
@@ -0,0 +1,377 @@
+From 70fc4b2a6200ef7a1b99a6aa28234b919f23b43c Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Sat, 26 Nov 2011 21:33:41 +0100
+Subject: [PATCH 184/186] USB: Add driver for the bcma bus
+
+This adds a USB driver using the generic platform device driver for the
+USB controller found on the Broadcom bcma bus. The bcma bus just
+exposes one device which serves the OHCI and the EHCI controller at the
+same time. This driver probes for this USB controller and creates and
+registers two new platform devices which will be probed by the new
+generic platform device driver. This makes it possible to use the EHCI
+and the OCHI controller on the bcma bus at the same time.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ drivers/usb/host/Kconfig    |   12 ++
+ drivers/usb/host/Makefile   |    1 +
+ drivers/usb/host/bcma-hcd.c |  328 +++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 341 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/usb/host/bcma-hcd.c
+
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -618,3 +618,15 @@ config USB_PXA168_EHCI
+ 	help
+ 	  Enable support for Marvell PXA168 SoC's on-chip EHCI
+ 	  host controller
++
++config USB_HCD_BCMA
++	tristate "BCMA usb host driver"
++	depends on BCMA && EXPERIMENTAL
++	select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD
++	select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD
++	help
++	  Enbale support for the EHCI and OCHI host controller on an bcma bus.
++	  It converts the bcma driver into two platform device drivers
++	  for ehci and ohci.
++
++	  If unsure, say N.
+--- a/drivers/usb/host/Makefile
++++ b/drivers/usb/host/Makefile
+@@ -37,3 +37,4 @@ obj-$(CONFIG_USB_IMX21_HCD)	+= imx21-hcd
+ obj-$(CONFIG_USB_FSL_MPH_DR_OF)	+= fsl-mph-dr-of.o
+ obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o
+ obj-$(CONFIG_MIPS_ALCHEMY)	+= alchemy-common.o
++obj-$(CONFIG_USB_HCD_BCMA)	+= bcma-hcd.o
+--- /dev/null
++++ b/drivers/usb/host/bcma-hcd.c
+@@ -0,0 +1,328 @@
++/*
++ * Broadcom specific Advanced Microcontroller Bus
++ * Broadcom USB-core driver (BCMA bus glue)
++ *
++ * Copyright 2011 Hauke Mehrtens <hauke@hauke-m.de>
++ *
++ * Based on ssb-ohci driver
++ * Copyright 2007 Michael Buesch <m@bues.ch>
++ *
++ * Derived from the OHCI-PCI driver
++ * Copyright 1999 Roman Weissgaerber
++ * Copyright 2000-2002 David Brownell
++ * Copyright 1999 Linus Torvalds
++ * Copyright 1999 Gregory P. Smith
++ *
++ * Derived from the USBcore related parts of Broadcom-SB
++ * Copyright 2005-2011 Broadcom Corporation
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++#include <linux/bcma/bcma.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <linux/module.h>
++#include <linux/usb/hci_driver.h>
++
++MODULE_AUTHOR("Hauke Mehrtens");
++MODULE_DESCRIPTION("Common USB driver for BCMA Bus");
++MODULE_LICENSE("GPL");
++
++struct bcma_hcd_device {
++	struct platform_device *ehci_dev;
++	struct platform_device *ohci_dev;
++};
++
++/* Wait for bitmask in a register to get set or cleared.
++ * timeout is in units of ten-microseconds.
++ */
++static int bcma_wait_bits(struct bcma_device *dev, u16 reg, u32 bitmask,
++			  int timeout)
++{
++	int i;
++	u32 val;
++
++	for (i = 0; i < timeout; i++) {
++		val = bcma_read32(dev, reg);
++		if ((val & bitmask) == bitmask)
++			return 0;
++		udelay(10);
++	}
++
++	return -ETIMEDOUT;
++}
++
++static void __devinit bcma_hcd_4716wa(struct bcma_device *dev)
++{
++#ifdef CONFIG_BCMA_DRIVER_MIPS
++	/* Work around for 4716 failures. */
++	if (dev->bus->chipinfo.id == 0x4716) {
++		u32 tmp;
++
++		tmp = bcma_cpu_clock(&dev->bus->drv_mips);
++		if (tmp >= 480000000)
++			tmp = 0x1846b; /* set CDR to 0x11(fast) */
++		else if (tmp == 453000000)
++			tmp = 0x1046b; /* set CDR to 0x10(slow) */
++		else
++			tmp = 0;
++
++		/* Change Shim mdio control reg to fix host not acking at
++		 * high frequencies
++		 */
++		if (tmp) {
++			bcma_write32(dev, 0x524, 0x1); /* write sel to enable */
++			udelay(500);
++
++			bcma_write32(dev, 0x524, tmp);
++			udelay(500);
++			bcma_write32(dev, 0x524, 0x4ab);
++			udelay(500);
++			bcma_read32(dev, 0x528);
++			bcma_write32(dev, 0x528, 0x80000000);
++		}
++	}
++#endif /* CONFIG_BCMA_DRIVER_MIPS */
++}
++
++/* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */
++static void __devinit bcma_hcd_init_chip(struct bcma_device *dev)
++{
++	u32 tmp;
++
++	/*
++	 * USB 2.0 special considerations:
++	 *
++	 * 1. Since the core supports both OHCI and EHCI functions, it must
++	 *    only be reset once.
++	 *
++	 * 2. In addition to the standard SI reset sequence, the Host Control
++	 *    Register must be programmed to bring the USB core and various
++	 *    phy components out of reset.
++	 */
++	if (!bcma_core_is_enabled(dev)) {
++		bcma_core_enable(dev, 0);
++		mdelay(10);
++		if (dev->id.rev >= 5) {
++			/* Enable Misc PLL */
++			tmp = bcma_read32(dev, 0x1e0);
++			tmp |= 0x100;
++			bcma_write32(dev, 0x1e0, tmp);
++			if (bcma_wait_bits(dev, 0x1e0, 1 << 24, 100))
++				printk(KERN_EMERG "Failed to enable misc PPL!\n");
++
++			/* Take out of resets */
++			bcma_write32(dev, 0x200, 0x4ff);
++			udelay(25);
++			bcma_write32(dev, 0x200, 0x6ff);
++			udelay(25);
++
++			/* Make sure digital and AFE are locked in USB PHY */
++			bcma_write32(dev, 0x524, 0x6b);
++			udelay(50);
++			tmp = bcma_read32(dev, 0x524);
++			udelay(50);
++			bcma_write32(dev, 0x524, 0xab);
++			udelay(50);
++			tmp = bcma_read32(dev, 0x524);
++			udelay(50);
++			bcma_write32(dev, 0x524, 0x2b);
++			udelay(50);
++			tmp = bcma_read32(dev, 0x524);
++			udelay(50);
++			bcma_write32(dev, 0x524, 0x10ab);
++			udelay(50);
++			tmp = bcma_read32(dev, 0x524);
++
++			if (bcma_wait_bits(dev, 0x528, 0xc000, 10000)) {
++				tmp = bcma_read32(dev, 0x528);
++				printk(KERN_EMERG
++				       "USB20H mdio_rddata 0x%08x\n", tmp);
++			}
++			bcma_write32(dev, 0x528, 0x80000000);
++			tmp = bcma_read32(dev, 0x314);
++			udelay(265);
++			bcma_write32(dev, 0x200, 0x7ff);
++			udelay(10);
++
++			/* Take USB and HSIC out of non-driving modes */
++			bcma_write32(dev, 0x510, 0);
++		} else {
++			bcma_write32(dev, 0x200, 0x7ff);
++
++			udelay(1);
++		}
++
++		bcma_hcd_4716wa(dev);
++	}
++}
++
++static const struct usb_hci_pdata p_data = {
++	.flags = USB_HCI_PDATA_PORT_POWER_SET,
++	.power_set_is_on = 1,
++};
++
++static struct platform_device * __devinit
++bcma_hcd_create_pdev(struct bcma_device *dev, char *name, u32 addr)
++{
++	struct platform_device *hci_dev;
++	struct resource hci_res[2];
++	int ret = -ENOMEM;
++
++	memset(hci_res, 0, sizeof(hci_res));
++
++	hci_res[0].start = addr;
++	hci_res[0].end = hci_res[0].start + 0x1000 - 1;
++	hci_res[0].flags = IORESOURCE_MEM;
++
++	hci_res[1].start = dev->irq;
++	hci_res[1].flags = IORESOURCE_IRQ;
++
++	hci_dev = platform_device_alloc(name, 0);
++	if (!hci_dev)
++		return NULL;
++
++	hci_dev->dev.parent = &dev->dev;
++	hci_dev->dev.dma_mask = &hci_dev->dev.coherent_dma_mask;
++
++	ret = platform_device_add_resources(hci_dev, hci_res,
++					    ARRAY_SIZE(hci_res));
++	if (ret)
++		goto err_alloc;
++	ret = platform_device_add_data(hci_dev, &p_data, sizeof(p_data));
++	if (ret)
++		goto err_alloc;
++	ret = platform_device_add(hci_dev);
++	if (ret)
++		goto err_alloc;
++
++	return hci_dev;
++
++err_alloc:
++	platform_device_put(hci_dev);
++	return ERR_PTR(ret);
++}
++
++static int __devinit bcma_hcd_probe(struct bcma_device *dev)
++{
++	int err;
++	u16 chipid_top;
++	u32 ohci_addr;
++	struct bcma_hcd_device *usb_dev;
++	struct bcma_chipinfo *chipinfo;
++
++	chipinfo = &dev->bus->chipinfo;
++	/* USBcores are only connected on embedded devices. */
++	chipid_top = (chipinfo->id & 0xFF00);
++	if (chipid_top != 0x4700 && chipid_top != 0x5300)
++		return -ENODEV;
++
++	/* TODO: Probably need checks here; is the core connected? */
++
++	if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
++	    dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
++		return -EOPNOTSUPP;
++
++	usb_dev = kzalloc(sizeof(struct bcma_hcd_device), GFP_KERNEL);
++	if (!usb_dev)
++		return -ENOMEM;
++
++	bcma_hcd_init_chip(dev);
++
++	/* In AI chips EHCI is addrspace 0, OHCI is 1 */
++	ohci_addr = dev->addr1;
++	if ((chipinfo->id == 0x5357 || chipinfo->id == 0x4749)
++	    && chipinfo->rev == 0)
++		ohci_addr = 0x18009000;
++
++	usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, "ohci-platform",
++						 ohci_addr);
++	if (IS_ERR(usb_dev->ohci_dev)) {
++		err = PTR_ERR(usb_dev->ohci_dev);
++		goto err_free_usb_dev;
++	}
++
++	usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, "ehci-platform",
++						 dev->addr);
++	if (IS_ERR(usb_dev->ehci_dev)) {
++		err = PTR_ERR(usb_dev->ehci_dev);
++		goto err_unregister_ohci_dev;
++	}
++
++	bcma_set_drvdata(dev, usb_dev);
++	return 0;
++
++err_unregister_ohci_dev:
++	platform_device_unregister(usb_dev->ohci_dev);
++err_free_usb_dev:
++	kfree(usb_dev);
++	return err;
++}
++
++static void __devexit bcma_hcd_remove(struct bcma_device *dev)
++{
++	struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev);
++	struct platform_device *ohci_dev = usb_dev->ohci_dev;
++	struct platform_device *ehci_dev = usb_dev->ehci_dev;
++
++	if (ohci_dev)
++		platform_device_unregister(ohci_dev);
++	if (ehci_dev)
++		platform_device_unregister(ehci_dev);
++
++	bcma_core_disable(dev, 0);
++}
++
++static void bcma_hcd_shutdown(struct bcma_device *dev)
++{
++	bcma_core_disable(dev, 0);
++}
++
++#ifdef CONFIG_PM
++
++static int bcma_hcd_suspend(struct bcma_device *dev, pm_message_t state)
++{
++	bcma_core_disable(dev, 0);
++
++	return 0;
++}
++
++static int bcma_hcd_resume(struct bcma_device *dev)
++{
++	bcma_core_enable(dev, 0);
++
++	return 0;
++}
++
++#else /* !CONFIG_PM */
++#define bcma_hcd_suspend	NULL
++#define bcma_hcd_resume	NULL
++#endif /* CONFIG_PM */
++
++static const struct bcma_device_id bcma_hcd_table[] __devinitconst = {
++	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS),
++	BCMA_CORETABLE_END
++};
++MODULE_DEVICE_TABLE(bcma, bcma_hcd_table);
++
++static struct bcma_driver bcma_hcd_driver = {
++	.name		= KBUILD_MODNAME,
++	.id_table	= bcma_hcd_table,
++	.probe		= bcma_hcd_probe,
++	.remove		= __devexit_p(bcma_hcd_remove),
++	.shutdown	= bcma_hcd_shutdown,
++	.suspend	= bcma_hcd_suspend,
++	.resume		= bcma_hcd_resume,
++};
++
++static int __init bcma_hcd_init(void)
++{
++	return bcma_driver_register(&bcma_hcd_driver);
++}
++module_init(bcma_hcd_init);
++
++static void __exit bcma_hcd_exit(void)
++{
++	bcma_driver_unregister(&bcma_hcd_driver);
++}
++module_exit(bcma_hcd_exit);
diff --git a/target/linux/brcm47xx/patches-3.2/185-USB-Add-driver-for-the-ssb-bus.patch b/target/linux/brcm47xx/patches-3.2/185-USB-Add-driver-for-the-ssb-bus.patch
new file mode 100644
index 000000000..d13fb998d
--- /dev/null
+++ b/target/linux/brcm47xx/patches-3.2/185-USB-Add-driver-for-the-ssb-bus.patch
@@ -0,0 +1,326 @@
+From 1840ddf07a452e640549fbd82e2f570da28e377f Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Sat, 26 Nov 2011 21:35:17 +0100
+Subject: [PATCH 185/186] USB: Add driver for the ssb bus
+
+This adds a USB driver using the generic platform device driver for the
+USB controller found on the Broadcom ssb bus. The ssb bus just
+exposes one device which serves the OHCI and the EHCI controller at the
+same time. This driver probes for this USB controller and creates and
+registers two new platform devices which will be probed by the new
+generic platform device driver. This makes it possible to use the EHCI
+and the OCHI controller on the ssb bus at the same time.
+
+The old ssb OHCI USB driver will be removed in the next step as this
+driver also provide an OHCI driver and an EHCI for the cores supporting
+it.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ drivers/usb/host/Kconfig   |   12 ++
+ drivers/usb/host/Makefile  |    1 +
+ drivers/usb/host/ssb-hcd.c |  273 ++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 286 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/usb/host/ssb-hcd.c
+
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -630,3 +630,15 @@ config USB_HCD_BCMA
+ 	  for ehci and ohci.
+ 
+ 	  If unsure, say N.
++
++config USB_HCD_SSB
++	tristate "SSB usb host driver"
++	depends on SSB && EXPERIMENTAL
++	select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD
++	select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD
++	help
++	  Enbale support for the EHCI and OCHI host controller on an bcma bus.
++	  It converts the bcma driver into two platform device drivers
++	  for ehci and ohci.
++
++	  If unsure, say N.
+--- a/drivers/usb/host/Makefile
++++ b/drivers/usb/host/Makefile
+@@ -38,3 +38,4 @@ obj-$(CONFIG_USB_FSL_MPH_DR_OF)	+= fsl-m
+ obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o
+ obj-$(CONFIG_MIPS_ALCHEMY)	+= alchemy-common.o
+ obj-$(CONFIG_USB_HCD_BCMA)	+= bcma-hcd.o
++obj-$(CONFIG_USB_HCD_SSB)	+= ssb-hcd.o
+--- /dev/null
++++ b/drivers/usb/host/ssb-hcd.c
+@@ -0,0 +1,273 @@
++/*
++ * Sonics Silicon Backplane
++ * Broadcom USB-core driver  (SSB bus glue)
++ *
++ * Copyright 2011 Hauke Mehrtens <hauke@hauke-m.de>
++ *
++ * Based on ssb-ohci driver
++ * Copyright 2007 Michael Buesch <m@bues.ch>
++ *
++ * Derived from the OHCI-PCI driver
++ * Copyright 1999 Roman Weissgaerber
++ * Copyright 2000-2002 David Brownell
++ * Copyright 1999 Linus Torvalds
++ * Copyright 1999 Gregory P. Smith
++ *
++ * Derived from the USBcore related parts of Broadcom-SB
++ * Copyright 2005-2011 Broadcom Corporation
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++#include <linux/ssb/ssb.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <linux/module.h>
++#include <linux/usb/hci_driver.h>
++
++MODULE_AUTHOR("Hauke Mehrtens");
++MODULE_DESCRIPTION("Common USB driver for SSB Bus");
++MODULE_LICENSE("GPL");
++
++#define SSB_HCD_TMSLOW_HOSTMODE	(1 << 29)
++
++struct ssb_hcd_device {
++	struct platform_device *ehci_dev;
++	struct platform_device *ohci_dev;
++
++	u32 enable_flags;
++};
++
++static void __devinit ssb_hcd_5354wa(struct ssb_device *dev)
++{
++#ifdef CONFIG_SSB_DRIVER_MIPS
++	/* Work around for 5354 failures */
++	if (dev->id.revision == 2 && dev->bus->chip_id == 0x5354) {
++		/* Change syn01 reg */
++		ssb_write32(dev, 0x894, 0x00fe00fe);
++
++		/* Change syn03 reg */
++		ssb_write32(dev, 0x89c, ssb_read32(dev, 0x89c) | 0x1);
++	}
++#endif
++}
++
++static void __devinit ssb_hcd_usb20wa(struct ssb_device *dev)
++{
++	if (dev->id.coreid == SSB_DEV_USB20_HOST) {
++		/*
++		 * USB 2.0 special considerations:
++		 *
++		 * 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.
++		 */
++		ssb_write32(dev, 0x200, 0x7ff);
++
++		/* Change Flush control reg */
++		ssb_write32(dev, 0x400, ssb_read32(dev, 0x400) & ~8);
++		ssb_read32(dev, 0x400);
++
++		/* Change Shim control reg */
++		ssb_write32(dev, 0x304, ssb_read32(dev, 0x304) & ~0x100);
++		ssb_read32(dev, 0x304);
++
++		udelay(1);
++
++		ssb_hcd_5354wa(dev);
++	}
++}
++
++/* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */
++static u32 __devinit ssb_hcd_init_chip(struct ssb_device *dev)
++{
++	u32 flags = 0;
++
++	if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV)
++		/* Put the device into host-mode. */
++		flags |= SSB_HCD_TMSLOW_HOSTMODE;
++
++	ssb_device_enable(dev, flags);
++
++	ssb_hcd_usb20wa(dev);
++
++	return flags;
++}
++
++static const struct usb_hci_pdata p_data = {
++	.flags = USB_HCI_PDATA_PORT_POWER_SET,
++	.power_set_is_on = 1,
++};
++
++static struct platform_device * __devinit
++ssb_hcd_create_pdev(struct ssb_device *dev, char *name, u32 addr, u32 len)
++{
++	struct platform_device *hci_dev;
++	struct resource hci_res[2];
++	int ret = -ENOMEM;
++
++	memset(hci_res, 0, sizeof(hci_res));
++
++	hci_res[0].start = addr;
++	hci_res[0].end = hci_res[0].start + len - 1;
++	hci_res[0].flags = IORESOURCE_MEM;
++
++	hci_res[1].start = dev->irq;
++	hci_res[1].flags = IORESOURCE_IRQ;
++
++	hci_dev = platform_device_alloc(name, 0);
++	if (!hci_dev)
++		return NULL;
++
++	hci_dev->dev.parent = dev->dev;
++	hci_dev->dev.dma_mask = &hci_dev->dev.coherent_dma_mask;
++
++	ret = platform_device_add_resources(hci_dev, hci_res,
++					    ARRAY_SIZE(hci_res));
++	if (ret)
++		goto err_alloc;
++	ret = platform_device_add_data(hci_dev, &p_data, sizeof(p_data));
++	if (ret)
++		goto err_alloc;
++	ret = platform_device_add(hci_dev);
++	if (ret)
++		goto err_alloc;
++
++	return hci_dev;
++
++err_alloc:
++	platform_device_put(hci_dev);
++	return ERR_PTR(ret);
++}
++
++static int __devinit ssb_hcd_probe(struct ssb_device *dev,
++				   const struct ssb_device_id *id)
++{
++	int err, tmp;
++	int start, len;
++	u16 chipid_top;
++	u16 coreid = dev->id.coreid;
++	struct ssb_hcd_device *usb_dev;
++
++	/* USBcores are only connected on embedded devices. */
++	chipid_top = (dev->bus->chip_id & 0xFF00);
++	if (chipid_top != 0x4700 && chipid_top != 0x5300)
++		return -ENODEV;
++
++	/* TODO: Probably need checks here; is the core connected? */
++
++	if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
++	    dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
++		return -EOPNOTSUPP;
++
++	usb_dev = kzalloc(sizeof(struct ssb_hcd_device), GFP_KERNEL);
++	if (!usb_dev)
++		return -ENOMEM;
++
++	/* We currently always attach SSB_DEV_USB11_HOSTDEV
++	 * as HOST OHCI. If we want to attach it as Client device,
++	 * we must branch here and call into the (yet to
++	 * be written) Client mode driver. Same for remove(). */
++	usb_dev->enable_flags = ssb_hcd_init_chip(dev);
++
++	tmp = ssb_read32(dev, SSB_ADMATCH0);
++
++	start = ssb_admatch_base(tmp);
++	len = (coreid == SSB_DEV_USB20_HOST) ? 0x800 : ssb_admatch_size(tmp);
++	usb_dev->ohci_dev = ssb_hcd_create_pdev(dev, "ohci-platform", start,
++						len);
++	if (IS_ERR(usb_dev->ohci_dev)) {
++		err = PTR_ERR(usb_dev->ohci_dev);
++		goto err_free_usb_dev;
++	}
++
++	if (coreid == SSB_DEV_USB20_HOST) {
++		start = ssb_admatch_base(tmp) + 0x800; /* ehci core offset */
++		usb_dev->ehci_dev = ssb_hcd_create_pdev(dev, "ehci-platform",
++							start, len);
++		if (IS_ERR(usb_dev->ehci_dev)) {
++			err = PTR_ERR(usb_dev->ehci_dev);
++			goto err_unregister_ohci_dev;
++		}
++	}
++
++	ssb_set_drvdata(dev, usb_dev);
++	return 0;
++
++err_unregister_ohci_dev:
++	platform_device_unregister(usb_dev->ohci_dev);
++err_free_usb_dev:
++	kfree(usb_dev);
++	return err;
++}
++
++static void __devexit ssb_hcd_remove(struct ssb_device *dev)
++{
++	struct ssb_hcd_device *usb_dev = ssb_get_drvdata(dev);
++	struct platform_device *ohci_dev = usb_dev->ohci_dev;
++	struct platform_device *ehci_dev = usb_dev->ehci_dev;
++
++	if (ohci_dev)
++		platform_device_unregister(ohci_dev);
++	if (ehci_dev)
++		platform_device_unregister(ehci_dev);
++
++	ssb_device_disable(dev, 0);
++}
++
++static void __devexit ssb_hcd_shutdown(struct ssb_device *dev)
++{
++	ssb_device_disable(dev, 0);
++}
++
++#ifdef CONFIG_PM
++
++static int ssb_hcd_suspend(struct ssb_device *dev, pm_message_t state)
++{
++	ssb_device_disable(dev, 0);
++
++	return 0;
++}
++
++static int ssb_hcd_resume(struct ssb_device *dev)
++{
++	struct ssb_hcd_device *usb_dev = ssb_get_drvdata(dev);
++
++	ssb_device_enable(dev, usb_dev->enable_flags);
++
++	return 0;
++}
++
++#else /* !CONFIG_PM */
++#define ssb_hcd_suspend	NULL
++#define ssb_hcd_resume	NULL
++#endif /* CONFIG_PM */
++
++static const struct ssb_device_id ssb_hcd_table[] __devinitconst = {
++	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
++	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
++	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
++	SSB_DEVTABLE_END
++};
++MODULE_DEVICE_TABLE(ssb, ssb_hcd_table);
++
++static struct ssb_driver ssb_hcd_driver = {
++	.name		= KBUILD_MODNAME,
++	.id_table	= ssb_hcd_table,
++	.probe		= ssb_hcd_probe,
++	.remove		= __devexit_p(ssb_hcd_remove),
++	.shutdown	= ssb_hcd_shutdown,
++	.suspend	= ssb_hcd_suspend,
++	.resume		= ssb_hcd_resume,
++};
++
++static int __init ssb_hcd_init(void)
++{
++	return ssb_driver_register(&ssb_hcd_driver);
++}
++module_init(ssb_hcd_init);
++
++static void __exit ssb_hcd_exit(void)
++{
++	ssb_driver_unregister(&ssb_hcd_driver);
++}
++module_exit(ssb_hcd_exit);
diff --git a/target/linux/brcm47xx/patches-3.2/186-USB-OHCI-remove-old-SSB-OHCI-driver.patch b/target/linux/brcm47xx/patches-3.2/186-USB-OHCI-remove-old-SSB-OHCI-driver.patch
new file mode 100644
index 000000000..89a7df9ea
--- /dev/null
+++ b/target/linux/brcm47xx/patches-3.2/186-USB-OHCI-remove-old-SSB-OHCI-driver.patch
@@ -0,0 +1,359 @@
+From 57857d7df6c22eaf11e3c67042d55a9546415059 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Sat, 26 Nov 2011 21:36:50 +0100
+Subject: [PATCH 186/186] USB: OHCI: remove old SSB OHCI driver
+
+This is now replaced by the new ssb USB driver, which also supports
+devices with an EHCI controller.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ drivers/usb/host/Kconfig    |   13 --
+ drivers/usb/host/ohci-hcd.c |   21 +----
+ drivers/usb/host/ohci-ssb.c |  260 -------------------------------------------
+ 3 files changed, 1 insertions(+), 293 deletions(-)
+ delete mode 100644 drivers/usb/host/ohci-ssb.c
+
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -351,19 +351,6 @@ config USB_OHCI_HCD_PCI
+ 	  Enables support for PCI-bus plug-in USB controller cards.
+ 	  If unsure, say Y.
+ 
+-config USB_OHCI_HCD_SSB
+-	bool "OHCI support for Broadcom SSB OHCI core"
+-	depends on USB_OHCI_HCD && (SSB = y || SSB = USB_OHCI_HCD) && EXPERIMENTAL
+-	default n
+-	---help---
+-	  Support for the Sonics Silicon Backplane (SSB) attached
+-	  Broadcom USB OHCI core.
+-
+-	  This device is present in some embedded devices with
+-	  Broadcom based SSB bus.
+-
+-	  If unsure, say N.
+-
+ config USB_OHCI_SH
+ 	bool "OHCI support for SuperH USB controller"
+ 	depends on USB_OHCI_HCD && SUPERH
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -1076,11 +1076,6 @@ MODULE_LICENSE ("GPL");
+ #define PS3_SYSTEM_BUS_DRIVER	ps3_ohci_driver
+ #endif
+ 
+-#ifdef CONFIG_USB_OHCI_HCD_SSB
+-#include "ohci-ssb.c"
+-#define SSB_OHCI_DRIVER		ssb_ohci_driver
+-#endif
+-
+ #ifdef CONFIG_MFD_SM501
+ #include "ohci-sm501.c"
+ #define SM501_OHCI_DRIVER	ohci_hcd_sm501_driver
+@@ -1129,8 +1124,7 @@ MODULE_LICENSE ("GPL");
+ 	!defined(SA1111_DRIVER) &&	\
+ 	!defined(PS3_SYSTEM_BUS_DRIVER) && \
+ 	!defined(SM501_OHCI_DRIVER) && \
+-	!defined(TMIO_OHCI_DRIVER) && \
+-	!defined(SSB_OHCI_DRIVER)
++	!defined(TMIO_OHCI_DRIVER)
+ #error "missing bus glue for ohci-hcd"
+ #endif
+ 
+@@ -1196,12 +1190,6 @@ static int __init ohci_hcd_mod_init(void
+ 		goto error_pci;
+ #endif
+ 
+-#ifdef SSB_OHCI_DRIVER
+-	retval = ssb_driver_register(&SSB_OHCI_DRIVER);
+-	if (retval)
+-		goto error_ssb;
+-#endif
+-
+ #ifdef SM501_OHCI_DRIVER
+ 	retval = platform_driver_register(&SM501_OHCI_DRIVER);
+ 	if (retval < 0)
+@@ -1225,10 +1213,6 @@ static int __init ohci_hcd_mod_init(void
+ 	platform_driver_unregister(&SM501_OHCI_DRIVER);
+  error_sm501:
+ #endif
+-#ifdef SSB_OHCI_DRIVER
+-	ssb_driver_unregister(&SSB_OHCI_DRIVER);
+- error_ssb:
+-#endif
+ #ifdef PCI_DRIVER
+ 	pci_unregister_driver(&PCI_DRIVER);
+  error_pci:
+@@ -1276,9 +1260,6 @@ static void __exit ohci_hcd_mod_exit(voi
+ #ifdef SM501_OHCI_DRIVER
+ 	platform_driver_unregister(&SM501_OHCI_DRIVER);
+ #endif
+-#ifdef SSB_OHCI_DRIVER
+-	ssb_driver_unregister(&SSB_OHCI_DRIVER);
+-#endif
+ #ifdef PCI_DRIVER
+ 	pci_unregister_driver(&PCI_DRIVER);
+ #endif
+--- a/drivers/usb/host/ohci-ssb.c
++++ /dev/null
+@@ -1,260 +0,0 @@
+-/*
+- * Sonics Silicon Backplane
+- * Broadcom USB-core OHCI driver
+- *
+- * Copyright 2007 Michael Buesch <m@bues.ch>
+- *
+- * Derived from the OHCI-PCI driver
+- * Copyright 1999 Roman Weissgaerber
+- * Copyright 2000-2002 David Brownell
+- * Copyright 1999 Linus Torvalds
+- * Copyright 1999 Gregory P. Smith
+- *
+- * Derived from the USBcore related parts of Broadcom-SB
+- * Copyright 2005 Broadcom Corporation
+- *
+- * Licensed under the GNU/GPL. See COPYING for details.
+- */
+-#include <linux/ssb/ssb.h>
+-
+-
+-#define SSB_OHCI_TMSLOW_HOSTMODE	(1 << 29)
+-
+-struct ssb_ohci_device {
+-	struct ohci_hcd ohci; /* _must_ be at the beginning. */
+-
+-	u32 enable_flags;
+-};
+-
+-static inline
+-struct ssb_ohci_device *hcd_to_ssb_ohci(struct usb_hcd *hcd)
+-{
+-	return (struct ssb_ohci_device *)(hcd->hcd_priv);
+-}
+-
+-
+-static int ssb_ohci_reset(struct usb_hcd *hcd)
+-{
+-	struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
+-	struct ohci_hcd *ohci = &ohcidev->ohci;
+-	int err;
+-
+-	ohci_hcd_init(ohci);
+-	err = ohci_init(ohci);
+-
+-	return err;
+-}
+-
+-static int ssb_ohci_start(struct usb_hcd *hcd)
+-{
+-	struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
+-	struct ohci_hcd *ohci = &ohcidev->ohci;
+-	int err;
+-
+-	err = ohci_run(ohci);
+-	if (err < 0) {
+-		ohci_err(ohci, "can't start\n");
+-		ohci_stop(hcd);
+-	}
+-
+-	return err;
+-}
+-
+-static const struct hc_driver ssb_ohci_hc_driver = {
+-	.description		= "ssb-usb-ohci",
+-	.product_desc		= "SSB OHCI Controller",
+-	.hcd_priv_size		= sizeof(struct ssb_ohci_device),
+-
+-	.irq			= ohci_irq,
+-	.flags			= HCD_MEMORY | HCD_USB11,
+-
+-	.reset			= ssb_ohci_reset,
+-	.start			= ssb_ohci_start,
+-	.stop			= ohci_stop,
+-	.shutdown		= ohci_shutdown,
+-
+-	.urb_enqueue		= ohci_urb_enqueue,
+-	.urb_dequeue		= ohci_urb_dequeue,
+-	.endpoint_disable	= ohci_endpoint_disable,
+-
+-	.get_frame_number	= ohci_get_frame,
+-
+-	.hub_status_data	= ohci_hub_status_data,
+-	.hub_control		= ohci_hub_control,
+-#ifdef	CONFIG_PM
+-	.bus_suspend		= ohci_bus_suspend,
+-	.bus_resume		= ohci_bus_resume,
+-#endif
+-
+-	.start_port_reset	= ohci_start_port_reset,
+-};
+-
+-static void ssb_ohci_detach(struct ssb_device *dev)
+-{
+-	struct usb_hcd *hcd = ssb_get_drvdata(dev);
+-
+-	if (hcd->driver->shutdown)
+-		hcd->driver->shutdown(hcd);
+-	usb_remove_hcd(hcd);
+-	iounmap(hcd->regs);
+-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+-	usb_put_hcd(hcd);
+-	ssb_device_disable(dev, 0);
+-}
+-
+-static int ssb_ohci_attach(struct ssb_device *dev)
+-{
+-	struct ssb_ohci_device *ohcidev;
+-	struct usb_hcd *hcd;
+-	int err = -ENOMEM;
+-	u32 tmp, flags = 0;
+-
+-	if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
+-	    dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
+-		return -EOPNOTSUPP;
+-
+-	if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
+-		/* Put the device into host-mode. */
+-		flags |= SSB_OHCI_TMSLOW_HOSTMODE;
+-		ssb_device_enable(dev, flags);
+-	} else if (dev->id.coreid == SSB_DEV_USB20_HOST) {
+-		/*
+-		 * USB 2.0 special considerations:
+-		 *
+-		 * 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.
+-		 */
+-		ssb_device_enable(dev, 0);
+-		ssb_write32(dev, 0x200, 0x7ff);
+-
+-		/* Change Flush control reg */
+-		tmp = ssb_read32(dev, 0x400);
+-		tmp &= ~8;
+-		ssb_write32(dev, 0x400, tmp);
+-		tmp = ssb_read32(dev, 0x400);
+-
+-		/* Change Shim control reg */
+-		tmp = ssb_read32(dev, 0x304);
+-		tmp &= ~0x100;
+-		ssb_write32(dev, 0x304, tmp);
+-		tmp = ssb_read32(dev, 0x304);
+-
+-		udelay(1);
+-
+-		/* Work around for 5354 failures */
+-		if (dev->id.revision == 2 && dev->bus->chip_id == 0x5354) {
+-			/* Change syn01 reg */
+-			tmp = 0x00fe00fe;
+-			ssb_write32(dev, 0x894, tmp);
+-
+-			/* Change syn03 reg */
+-			tmp = ssb_read32(dev, 0x89c);
+-			tmp |= 0x1;
+-			ssb_write32(dev, 0x89c, tmp);
+-		}
+-	} else
+-		ssb_device_enable(dev, 0);
+-
+-	hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev,
+-			dev_name(dev->dev));
+-	if (!hcd)
+-		goto err_dev_disable;
+-	ohcidev = hcd_to_ssb_ohci(hcd);
+-	ohcidev->enable_flags = flags;
+-
+-	tmp = ssb_read32(dev, SSB_ADMATCH0);
+-	hcd->rsrc_start = ssb_admatch_base(tmp);
+-	hcd->rsrc_len = ssb_admatch_size(tmp);
+-	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+-	if (!hcd->regs)
+-		goto err_put_hcd;
+-	err = usb_add_hcd(hcd, dev->irq, IRQF_SHARED);
+-	if (err)
+-		goto err_iounmap;
+-
+-	ssb_set_drvdata(dev, hcd);
+-
+-	return err;
+-
+-err_iounmap:
+-	iounmap(hcd->regs);
+-err_put_hcd:
+-	usb_put_hcd(hcd);
+-err_dev_disable:
+-	ssb_device_disable(dev, flags);
+-	return err;
+-}
+-
+-static int ssb_ohci_probe(struct ssb_device *dev,
+-		const struct ssb_device_id *id)
+-{
+-	int err;
+-	u16 chipid_top;
+-
+-	/* USBcores are only connected on embedded devices. */
+-	chipid_top = (dev->bus->chip_id & 0xFF00);
+-	if (chipid_top != 0x4700 && chipid_top != 0x5300)
+-		return -ENODEV;
+-
+-	/* TODO: Probably need checks here; is the core connected? */
+-
+-	if (usb_disabled())
+-		return -ENODEV;
+-
+-	/* We currently always attach SSB_DEV_USB11_HOSTDEV
+-	 * as HOST OHCI. If we want to attach it as Client device,
+-	 * we must branch here and call into the (yet to
+-	 * be written) Client mode driver. Same for remove(). */
+-
+-	err = ssb_ohci_attach(dev);
+-
+-	return err;
+-}
+-
+-static void ssb_ohci_remove(struct ssb_device *dev)
+-{
+-	ssb_ohci_detach(dev);
+-}
+-
+-#ifdef CONFIG_PM
+-
+-static int ssb_ohci_suspend(struct ssb_device *dev, pm_message_t state)
+-{
+-	ssb_device_disable(dev, 0);
+-
+-	return 0;
+-}
+-
+-static int ssb_ohci_resume(struct ssb_device *dev)
+-{
+-	struct usb_hcd *hcd = ssb_get_drvdata(dev);
+-	struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
+-
+-	ssb_device_enable(dev, ohcidev->enable_flags);
+-
+-	ohci_finish_controller_resume(hcd);
+-	return 0;
+-}
+-
+-#else /* !CONFIG_PM */
+-#define ssb_ohci_suspend	NULL
+-#define ssb_ohci_resume	NULL
+-#endif /* CONFIG_PM */
+-
+-static const struct ssb_device_id ssb_ohci_table[] = {
+-	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
+-	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
+-	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
+-	SSB_DEVTABLE_END
+-};
+-MODULE_DEVICE_TABLE(ssb, ssb_ohci_table);
+-
+-static struct ssb_driver ssb_ohci_driver = {
+-	.name		= KBUILD_MODNAME,
+-	.id_table	= ssb_ohci_table,
+-	.probe		= ssb_ohci_probe,
+-	.remove		= ssb_ohci_remove,
+-	.suspend	= ssb_ohci_suspend,
+-	.resume		= ssb_ohci_resume,
+-};
-- 
cgit v1.2.3