Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Hauke Mehrtens and committed by
Greg Kroah-Hartman
f2402f21 356c5a48

+49 -3
+49 -3
drivers/usb/host/ohci-ssb.c
··· 93 93 { 94 94 struct usb_hcd *hcd = ssb_get_drvdata(dev); 95 95 96 + if (hcd->driver->shutdown) 97 + hcd->driver->shutdown(hcd); 96 98 usb_remove_hcd(hcd); 97 99 iounmap(hcd->regs); 100 + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 98 101 usb_put_hcd(hcd); 99 102 ssb_device_disable(dev, 0); 100 103 } ··· 109 106 int err = -ENOMEM; 110 107 u32 tmp, flags = 0; 111 108 112 - if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) 113 - flags |= SSB_OHCI_TMSLOW_HOSTMODE; 109 + if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) || 110 + dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32))) 111 + return -EOPNOTSUPP; 114 112 115 - ssb_device_enable(dev, flags); 113 + if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) { 114 + /* Put the device into host-mode. */ 115 + flags |= SSB_OHCI_TMSLOW_HOSTMODE; 116 + ssb_device_enable(dev, flags); 117 + } else if (dev->id.coreid == SSB_DEV_USB20_HOST) { 118 + /* 119 + * USB 2.0 special considerations: 120 + * 121 + * In addition to the standard SSB reset sequence, the Host 122 + * Control Register must be programmed to bring the USB core 123 + * and various phy components out of reset. 124 + */ 125 + ssb_device_enable(dev, 0); 126 + ssb_write32(dev, 0x200, 0x7ff); 127 + 128 + /* Change Flush control reg */ 129 + tmp = ssb_read32(dev, 0x400); 130 + tmp &= ~8; 131 + ssb_write32(dev, 0x400, tmp); 132 + tmp = ssb_read32(dev, 0x400); 133 + 134 + /* Change Shim control reg */ 135 + tmp = ssb_read32(dev, 0x304); 136 + tmp &= ~0x100; 137 + ssb_write32(dev, 0x304, tmp); 138 + tmp = ssb_read32(dev, 0x304); 139 + 140 + udelay(1); 141 + 142 + /* Work around for 5354 failures */ 143 + if (dev->id.revision == 2 && dev->bus->chip_id == 0x5354) { 144 + /* Change syn01 reg */ 145 + tmp = 0x00fe00fe; 146 + ssb_write32(dev, 0x894, tmp); 147 + 148 + /* Change syn03 reg */ 149 + tmp = ssb_read32(dev, 0x89c); 150 + tmp |= 0x1; 151 + ssb_write32(dev, 0x89c, tmp); 152 + } 153 + } else 154 + ssb_device_enable(dev, 0); 116 155 117 156 hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev, 118 157 dev_name(dev->dev)); ··· 245 200 static const struct ssb_device_id ssb_ohci_table[] = { 246 201 SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV), 247 202 SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV), 203 + SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV), 248 204 SSB_DEVTABLE_END 249 205 }; 250 206 MODULE_DEVICE_TABLE(ssb, ssb_ohci_table);