diff options
| author | hauke <hauke@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2012-01-13 20:11:23 +0000 | 
|---|---|---|
| committer | hauke <hauke@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2012-01-13 20:11:23 +0000 | 
| commit | 01cb3619d31b15281e127b8c9ba91b9139268b3c (patch) | |
| tree | bc3f22dd92d37c45f6d16be65a294b4c8ec65b09 | |
| parent | 3651d1c3327053bb67b1442502345473a4152884 (diff) | |
brcm47xx: update usb driver
Add workarround for BCM5357 and BCM4749.
This patch contains the following fixes from George Kashperko:
* separate subroutines for controller initialization workarounds -
   following CodingStyle recommendations;
* __devinit __devexit __devinitconst annotations for CONFIG_HOTPLUG;
* fix leak in ssb_hcd_create_pdev/bcma_hcd_create_pdev - as hci_res being
   kmalloc'ed is never freed anywhere while platform_device_add_resources
   will kmemdup resources right away;
* fix compilation error in ssb_hcd_resume - it will fail as soon as
   CONFIG_PM is selected.
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@29734 3c298f89-4303-0410-b956-a3cf2f4a3e73
| -rw-r--r-- | target/linux/brcm47xx/patches-3.0/0032-USB-Add-driver-for-the-bcma-bus.patch | 114 | ||||
| -rw-r--r-- | target/linux/brcm47xx/patches-3.0/0033-USB-Add-driver-for-the-ssb-bus.patch | 98 | 
2 files changed, 113 insertions, 99 deletions
diff --git a/target/linux/brcm47xx/patches-3.0/0032-USB-Add-driver-for-the-bcma-bus.patch b/target/linux/brcm47xx/patches-3.0/0032-USB-Add-driver-for-the-bcma-bus.patch index cecc017d0..e2a2f1e47 100644 --- a/target/linux/brcm47xx/patches-3.0/0032-USB-Add-driver-for-the-bcma-bus.patch +++ b/target/linux/brcm47xx/patches-3.0/0032-USB-Add-driver-for-the-bcma-bus.patch @@ -1,7 +1,7 @@ -From 7151c34627b938486008cfab25bfb4e4f730a021 Mon Sep 17 00:00:00 2001 +From 4ea647c5a257d57eaf230f783e54b2c0232852b8 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/21] USB: Add driver for the bcma bus +Subject: [PATCH 19/26] 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 @@ -15,8 +15,8 @@ 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 |  350 +++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 363 insertions(+), 0 deletions(-) + 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 @@ -46,7 +46,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>  +obj-$(CONFIG_USB_HCD_BCMA)	+= bcma-hcd.o  --- /dev/null  +++ b/drivers/usb/host/bcma-hcd.c -@@ -0,0 +1,299 @@ +@@ -0,0 +1,309 @@  +/*  + * Broadcom specific Advanced Microcontroller Bus  + * Broadcom USB-core driver (BCMA bus glue) @@ -76,15 +76,46 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>  +MODULE_DESCRIPTION("Common USB driver for BCMA Bus");  +MODULE_LICENSE("GPL");  + -+#define BCMA_CORE_SIZE		0x1000 -+  +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 bcma_hcd_init_chip(struct bcma_device *dev) ++static void __devinit bcma_hcd_init_chip(struct bcma_device *dev)  +{  +	u32 tmp;  + @@ -150,51 +181,22 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>  +  +			udelay(1);  +		} -+	} -+#ifdef CONFIG_BCMA_DRIVER_MIPS -+	/* Work around for 4716 failures. */ -+	if (dev->bus->chipinfo.id == 0x4716) { -+		u32 clk_freq; -+ -+		clk_freq = bcma_cpu_clock(&dev->bus->drv_mips); -+		if (clk_freq >= 480000000) -+			tmp = 0x1846b; /* set CDR to 0x11(fast) */ -+		else if (clk_freq == 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); -+			tmp = bcma_read32(dev, 0x528); -+			bcma_write32(dev, 0x528, 0x80000000); -+		} ++		bcma_hcd_4716wa(dev);  +	} -+#endif /* CONFIG_BCMA_DRIVER_MIPS */  +}  + -+static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, -+						    char *name, u32 addr) ++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; ++	struct resource hci_res[2];  +	int ret = -ENOMEM;  + -+	hci_res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL); -+	if (!hci_res) -+		return ERR_PTR(-ENOMEM); ++	memset(hci_res, 0, sizeof(hci_res));  +  +	hci_res[0].start = addr; -+	hci_res[0].end = hci_res[0].start + BCMA_CORE_SIZE - 1; ++	hci_res[0].end = hci_res[0].start + 0x1000 - 1;  +	hci_res[0].flags = IORESOURCE_MEM;  +  +	hci_res[1].start = dev->irq; @@ -207,14 +209,14 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>  +	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); ++	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: -+		kfree(hci_res);  +		platform_device_put(hci_dev);  +		return ERR_PTR(ret);  +	} @@ -222,14 +224,17 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>  +	return hci_dev;  +}  + -+static int bcma_hcd_probe(struct bcma_device *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 = (dev->bus->chipinfo.id & 0xFF00); ++	chipid_top = (chipinfo->id & 0xFF00);  +	if (chipid_top != 0x4700 && chipid_top != 0x5300)  +		return -ENODEV;  + @@ -245,8 +250,14 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>  +  +	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", -+						 dev->addr1); ++						 ohci_addr);  +	if (IS_ERR(usb_dev->ohci_dev)) {  +		err = PTR_ERR(usb_dev->ohci_dev);  +		goto err_free_usb_dev; @@ -257,7 +268,6 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>  +	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); @@ -270,7 +280,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>  +	return err;  +}  + -+static void bcma_hcd_remove(struct bcma_device *dev) ++static void __devexit bcma_hcd_remove(struct bcma_device *dev)  +{  +	struct bcma_hcd_device *usb_dev;  +	struct platform_device *ohci_dev; @@ -319,7 +329,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>  +#define bcma_hcd_resume	NULL  +#endif /* CONFIG_PM */  + -+static const struct bcma_device_id bcma_hcd_table[] = { ++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  +}; @@ -329,7 +339,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>  +	.name		= KBUILD_MODNAME,  +	.id_table	= bcma_hcd_table,  +	.probe		= bcma_hcd_probe, -+	.remove		= bcma_hcd_remove, ++	.remove		= __devexit_p(bcma_hcd_remove),  +	.shutdown	= bcma_hcd_shutdown,  +	.suspend	= bcma_hcd_suspend,  +	.resume		= bcma_hcd_resume, diff --git a/target/linux/brcm47xx/patches-3.0/0033-USB-Add-driver-for-the-ssb-bus.patch b/target/linux/brcm47xx/patches-3.0/0033-USB-Add-driver-for-the-ssb-bus.patch index 866540b87..91b6c9cbc 100644 --- a/target/linux/brcm47xx/patches-3.0/0033-USB-Add-driver-for-the-ssb-bus.patch +++ b/target/linux/brcm47xx/patches-3.0/0033-USB-Add-driver-for-the-ssb-bus.patch @@ -1,7 +1,7 @@ -From b61e70ad9080a6dbd3731917ec21dbcbb9d382a2 Mon Sep 17 00:00:00 2001 +From 0f91c21de577d2d9f1fd164ca686d9a4ff0e2c8b 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/21] USB: Add driver for the ssb bus +Subject: [PATCH 20/26] 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 @@ -19,8 +19,8 @@ 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 |  320 ++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 333 insertions(+), 0 deletions(-) + 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 @@ -50,7 +50,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>  +obj-$(CONFIG_USB_HCD_SSB)	+= ssb-hcd.o  --- /dev/null  +++ b/drivers/usb/host/ssb-hcd.c -@@ -0,0 +1,268 @@ +@@ -0,0 +1,272 @@  +/*  + * Sonics Silicon Backplane  + * Broadcom USB-core driver  (SSB bus glue) @@ -89,16 +89,23 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>  +	u32 enable_flags;  +};  + -+/* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */ -+static u32 ssb_hcd_init_chip(struct ssb_device *dev) ++static void __devinit ssb_hcd_5354wa(struct ssb_device *dev)  +{ -+	u32 tmp, flags = 0; ++#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 ++}  + -+	if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) { -+		/* Put the device into host-mode. */ -+		flags |= SSB_HCD_TMSLOW_HOSTMODE; -+		ssb_device_enable(dev, flags); -+	} else if (dev->id.coreid == SSB_DEV_USB20_HOST) { ++static void __devinit ssb_hcd_usb20wa(struct ssb_device *dev) ++{ ++	if (dev->id.coreid == SSB_DEV_USB20_HOST) {  +		/*  +		 * USB 2.0 special considerations:  +		 * @@ -106,51 +113,46 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>  +		 * 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); ++		ssb_write32(dev, 0x400, ssb_read32(dev, 0x400) & ~8); ++		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); ++		ssb_write32(dev, 0x304, ssb_read32(dev, 0x304) & ~0x100); ++		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); ++		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;  + -+			/* Change syn03 reg */ -+			tmp = ssb_read32(dev, 0x89c); -+			tmp |= 0x1; -+			ssb_write32(dev, 0x89c, tmp); -+		} -+	} else -+		ssb_device_enable(dev, 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 *ssb_hcd_create_pdev(struct ssb_device *dev, -+						   char *name, u32 addr, -+						   u32 len) ++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; ++	struct resource hci_res[2];  +	int ret = -ENOMEM;  + -+	hci_res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL); -+	if (!hci_res) -+		return ERR_PTR(-ENOMEM); ++	memset(hci_res, 0, sizeof(hci_res));  +  +	hci_res[0].start = addr;  +	hci_res[0].end = hci_res[0].start + len - 1; @@ -173,7 +175,6 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>  +	ret = platform_device_add(hci_dev);  +	if (ret) {  +err_alloc: -+		kfree(hci_res);  +		platform_device_put(hci_dev);  +		return ERR_PTR(ret);  +	} @@ -181,7 +182,8 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>  +	return hci_dev;  +}  + -+static int ssb_hcd_probe(struct ssb_device *dev, const struct ssb_device_id *id) ++static int __devinit ssb_hcd_probe(struct ssb_device *dev, ++				   const struct ssb_device_id *id)  +{  +	int err, tmp;  +	int start, len; @@ -241,7 +243,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>  +	return err;  +}  + -+static void ssb_hcd_remove(struct ssb_device *dev) ++static void __devexit ssb_hcd_remove(struct ssb_device *dev)  +{  +	struct ssb_hcd_device *usb_dev;  +	struct platform_device *ohci_dev; @@ -264,7 +266,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>  +	ssb_device_disable(dev, 0);  +}  + -+static void ssb_hcd_shutdown(struct ssb_device *dev) ++static void __devexit ssb_hcd_shutdown(struct ssb_device *dev)  +{  +	ssb_device_disable(dev, 0);  +} @@ -280,6 +282,8 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>  +  +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; @@ -290,7 +294,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>  +#define ssb_hcd_resume	NULL  +#endif /* CONFIG_PM */  + -+static const struct ssb_device_id ssb_hcd_table[] = { ++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), @@ -302,7 +306,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>  +	.name		= KBUILD_MODNAME,  +	.id_table	= ssb_hcd_table,  +	.probe		= ssb_hcd_probe, -+	.remove		= ssb_hcd_remove, ++	.remove		= __devexit_p(ssb_hcd_remove),  +	.shutdown	= ssb_hcd_shutdown,  +	.suspend	= ssb_hcd_suspend,  +	.resume		= ssb_hcd_resume,  | 
