diff options
Diffstat (limited to 'target/linux/brcm47xx/patches-2.6.36/022-USB-Add-ehci-ssb-driver.patch')
-rw-r--r-- | target/linux/brcm47xx/patches-2.6.36/022-USB-Add-ehci-ssb-driver.patch | 345 |
1 files changed, 0 insertions, 345 deletions
diff --git a/target/linux/brcm47xx/patches-2.6.36/022-USB-Add-ehci-ssb-driver.patch b/target/linux/brcm47xx/patches-2.6.36/022-USB-Add-ehci-ssb-driver.patch deleted file mode 100644 index ef885a49e2..0000000000 --- a/target/linux/brcm47xx/patches-2.6.36/022-USB-Add-ehci-ssb-driver.patch +++ /dev/null @@ -1,345 +0,0 @@ -From ad224c0d5fa0fc05f8aaef3c19fc9b4eb275a5d2 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Sun, 18 Jul 2010 21:29:40 +0200 -Subject: [PATCH 2/2] USB: Add ehci ssb driver - -Support for the Sonics Silicon Backplane (SSB) attached Broadcom USB EHCI core. - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - drivers/usb/host/Kconfig | 13 ++ - drivers/usb/host/ehci-hcd.c | 22 ++++- - drivers/usb/host/ehci-ssb.c | 255 +++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 288 insertions(+), 2 deletions(-) - create mode 100644 drivers/usb/host/ehci-ssb.c - ---- a/drivers/usb/host/Kconfig -+++ b/drivers/usb/host/Kconfig -@@ -153,6 +153,19 @@ config USB_OXU210HP_HCD - To compile this driver as a module, choose M here: the - module will be called oxu210hp-hcd. - -+config USB_EHCI_HCD_SSB -+ bool "EHCI support for Broadcom SSB EHCI core" -+ depends on USB_EHCI_HCD && (SSB = y || SSB = USB_EHCI_HCD) && EXPERIMENTAL -+ default n -+ ---help--- -+ Support for the Sonics Silicon Backplane (SSB) attached -+ Broadcom USB EHCI core. -+ -+ This device is present in some embedded devices with -+ Broadcom based SSB bus. -+ -+ If unsure, say N. -+ - config USB_ISP116X_HCD - tristate "ISP116X HCD support" - depends on USB ---- a/drivers/usb/host/ehci-hcd.c -+++ b/drivers/usb/host/ehci-hcd.c -@@ -1197,9 +1197,14 @@ MODULE_LICENSE ("GPL"); - #define PLATFORM_DRIVER ehci_atmel_driver - #endif - -+#ifdef CONFIG_USB_EHCI_HCD_SSB -+#include "ehci-ssb.c" -+#define SSB_EHCI_DRIVER ssb_ehci_driver -+#endif -+ - #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ - !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ -- !defined(XILINX_OF_PLATFORM_DRIVER) -+ !defined(XILINX_OF_PLATFORM_DRIVER) && !defined(SSB_EHCI_DRIVER) - #error "missing bus glue for ehci-hcd" - #endif - -@@ -1259,10 +1264,20 @@ static int __init ehci_hcd_init(void) - if (retval < 0) - goto clean4; - #endif -+ -+#ifdef SSB_EHCI_DRIVER -+ retval = ssb_driver_register(&SSB_EHCI_DRIVER); -+ if (retval < 0) -+ goto clean5; -+#endif - return retval; - -+#ifdef SSB_EHCI_DRIVER -+ /* ssb_driver_unregister(&SSB_EHCI_DRIVER); */ -+clean5: -+#endif - #ifdef XILINX_OF_PLATFORM_DRIVER -- /* of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER); */ -+ of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER); - clean4: - #endif - #ifdef OF_PLATFORM_DRIVER -@@ -1293,6 +1308,9 @@ module_init(ehci_hcd_init); - - static void __exit ehci_hcd_cleanup(void) - { -+#ifdef SSB_EHCI_DRIVER -+ ssb_driver_unregister(&SSB_EHCI_DRIVER); -+#endif - #ifdef XILINX_OF_PLATFORM_DRIVER - of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER); - #endif ---- /dev/null -+++ b/drivers/usb/host/ehci-ssb.c -@@ -0,0 +1,255 @@ -+/* -+ * Sonics Silicon Backplane -+ * Broadcom USB-core EHCI driver (SSB bus glue) -+ * -+ * Copyright 2007 Steven Brown <sbrown@cortland.com> -+ * Copyright 2010 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 -+ * -+ * 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> -+ -+ -+struct ssb_ehci_device { -+ struct ehci_hcd ehci; /* _must_ be at the beginning. */ -+}; -+ -+static inline -+struct ssb_ehci_device *hcd_to_ssb_ehci(struct usb_hcd *hcd) -+{ -+ return (struct ssb_ehci_device *)(hcd->hcd_priv); -+} -+ -+static int ssb_ehci_reset(struct usb_hcd *hcd) -+{ -+ struct ehci_hcd *ehci = hcd_to_ehci(hcd); -+ int err; -+ -+ ehci->caps = hcd->regs; -+ ehci->regs = hcd->regs + -+ HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); -+ -+ dbg_hcs_params(ehci, "reset"); -+ dbg_hcc_params(ehci, "reset"); -+ -+ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); -+ -+ err = ehci_halt(ehci); -+ -+ if (err) -+ return err; -+ -+ err = ehci_init(hcd); -+ -+ if (err) -+ return err; -+ -+ ehci_reset(ehci); -+ -+ return err; -+} -+ -+static const struct hc_driver ssb_ehci_hc_driver = { -+ .description = "ssb-usb-ehci", -+ .product_desc = "SSB EHCI Controller", -+ .hcd_priv_size = sizeof(struct ssb_ehci_device), -+ -+ .irq = ehci_irq, -+ .flags = HCD_MEMORY | HCD_USB2, -+ -+ .reset = ssb_ehci_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, -+ -+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, -+}; -+ -+static void ssb_ehci_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_ehci_attach(struct ssb_device *dev) -+{ -+ struct ssb_ehci_device *ehcidev; -+ struct usb_hcd *hcd; -+ int err = -ENOMEM; -+ u32 tmp; -+ -+ 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 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); -+ } -+ -+ hcd = usb_create_hcd(&ssb_ehci_hc_driver, dev->dev, -+ dev_name(dev->dev)); -+ if (!hcd) -+ goto err_dev_disable; -+ -+ ehcidev = hcd_to_ssb_ehci(hcd); -+ tmp = ssb_read32(dev, SSB_ADMATCH0); -+ hcd->rsrc_start = ssb_admatch_base(tmp) + 0x800; /* ehci core offset */ -+ hcd->rsrc_len = 0x100; /* ehci reg block size */ -+ /* -+ * 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, dev->irq, IRQF_DISABLED | 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, 0); -+ return err; -+} -+ -+static int ssb_ehci_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; -+ -+ err = ssb_ehci_attach(dev); -+ -+ return err; -+} -+ -+static void ssb_ehci_remove(struct ssb_device *dev) -+{ -+ ssb_ehci_detach(dev); -+} -+ -+#ifdef CONFIG_PM -+ -+static int ssb_ehci_suspend(struct ssb_device *dev, pm_message_t state) -+{ -+ ssb_device_disable(dev, 0); -+ -+ return 0; -+} -+ -+static int ssb_ehci_resume(struct ssb_device *dev) -+{ -+ struct usb_hcd *hcd = ssb_get_drvdata(dev); -+ struct ssb_ehci_device *ehcidev = hcd_to_ssb_ehci(hcd); -+ -+ ssb_device_enable(dev, 0); -+ -+ ehci_finish_controller_resume(hcd); -+ return 0; -+} -+ -+#else /* !CONFIG_PM */ -+#define ssb_ehci_suspend NULL -+#define ssb_ehci_resume NULL -+#endif /* CONFIG_PM */ -+ -+static const struct ssb_device_id ssb_ehci_table[] = { -+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV), -+ SSB_DEVTABLE_END -+}; -+MODULE_DEVICE_TABLE(ssb, ssb_ehci_table); -+ -+static struct ssb_driver ssb_ehci_driver = { -+ .name = KBUILD_MODNAME, -+ .id_table = ssb_ehci_table, -+ .probe = ssb_ehci_probe, -+ .remove = ssb_ehci_remove, -+ .suspend = ssb_ehci_suspend, -+ .resume = ssb_ehci_resume, -+}; |