aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHauke Mehrtens <hauke@hauke-m.de>2010-07-28 16:11:35 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-08-10 17:35:44 -0400
commitf2402f21caba2aceebbf637458b777300669020f (patch)
treeb63a4aa73da9aa8dc2fc41fdc65d60e5fefa1a48 /drivers
parent356c5a4834a74c621715f7a7f16ded914eecbd3c (diff)
USB: Add USB 2.0 to ssb ohci driver
This adds USB 2.0 support to ssb ohci driver. This patch was used in OpenWRT for a long time now. CC: Steve Brown <sbrown@cortland.com> Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/host/ohci-ssb.c52
1 files changed, 49 insertions, 3 deletions
diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c
index 23fd6a886bdd..48ee6943bf35 100644
--- a/drivers/usb/host/ohci-ssb.c
+++ b/drivers/usb/host/ohci-ssb.c
@@ -93,8 +93,11 @@ static void ssb_ohci_detach(struct ssb_device *dev)
93{ 93{
94 struct usb_hcd *hcd = ssb_get_drvdata(dev); 94 struct usb_hcd *hcd = ssb_get_drvdata(dev);
95 95
96 if (hcd->driver->shutdown)
97 hcd->driver->shutdown(hcd);
96 usb_remove_hcd(hcd); 98 usb_remove_hcd(hcd);
97 iounmap(hcd->regs); 99 iounmap(hcd->regs);
100 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
98 usb_put_hcd(hcd); 101 usb_put_hcd(hcd);
99 ssb_device_disable(dev, 0); 102 ssb_device_disable(dev, 0);
100} 103}
@@ -106,10 +109,52 @@ static int ssb_ohci_attach(struct ssb_device *dev)
106 int err = -ENOMEM; 109 int err = -ENOMEM;
107 u32 tmp, flags = 0; 110 u32 tmp, flags = 0;
108 111
109 if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) 112 if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
110 flags |= SSB_OHCI_TMSLOW_HOSTMODE; 113 dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
114 return -EOPNOTSUPP;
111 115
112 ssb_device_enable(dev, flags); 116 if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
117 /* Put the device into host-mode. */
118 flags |= SSB_OHCI_TMSLOW_HOSTMODE;
119 ssb_device_enable(dev, flags);
120 } else if (dev->id.coreid == SSB_DEV_USB20_HOST) {
121 /*
122 * USB 2.0 special considerations:
123 *
124 * In addition to the standard SSB reset sequence, the Host
125 * Control Register must be programmed to bring the USB core
126 * and various phy components out of reset.
127 */
128 ssb_device_enable(dev, 0);
129 ssb_write32(dev, 0x200, 0x7ff);
130
131 /* Change Flush control reg */
132 tmp = ssb_read32(dev, 0x400);
133 tmp &= ~8;
134 ssb_write32(dev, 0x400, tmp);
135 tmp = ssb_read32(dev, 0x400);
136
137 /* Change Shim control reg */
138 tmp = ssb_read32(dev, 0x304);
139 tmp &= ~0x100;
140 ssb_write32(dev, 0x304, tmp);
141 tmp = ssb_read32(dev, 0x304);
142
143 udelay(1);
144
145 /* Work around for 5354 failures */
146 if (dev->id.revision == 2 && dev->bus->chip_id == 0x5354) {
147 /* Change syn01 reg */
148 tmp = 0x00fe00fe;
149 ssb_write32(dev, 0x894, tmp);
150
151 /* Change syn03 reg */
152 tmp = ssb_read32(dev, 0x89c);
153 tmp |= 0x1;
154 ssb_write32(dev, 0x89c, tmp);
155 }
156 } else
157 ssb_device_enable(dev, 0);
113 158
114 hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev, 159 hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev,
115 dev_name(dev->dev)); 160 dev_name(dev->dev));
@@ -200,6 +245,7 @@ static int ssb_ohci_resume(struct ssb_device *dev)
200static const struct ssb_device_id ssb_ohci_table[] = { 245static const struct ssb_device_id ssb_ohci_table[] = {
201 SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV), 246 SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
202 SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV), 247 SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
248 SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
203 SSB_DEVTABLE_END 249 SSB_DEVTABLE_END
204}; 250};
205MODULE_DEVICE_TABLE(ssb, ssb_ohci_table); 251MODULE_DEVICE_TABLE(ssb, ssb_ohci_table);