| 1 | --- |
| 2 | drivers/usb/host/ohci-ssb.c | 39 ++++++++++++++++++++++++++++++++++++--- |
| 3 | 1 file changed, 36 insertions(+), 3 deletions(-) |
| 4 | |
| 5 | --- a/drivers/usb/host/ohci-ssb.c |
| 6 | +++ b/drivers/usb/host/ohci-ssb.c |
| 7 | @@ -106,10 +106,42 @@ static int ssb_ohci_attach(struct ssb_de |
| 8 | int err = -ENOMEM; |
| 9 | u32 tmp, flags = 0; |
| 10 | |
| 11 | - if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) |
| 12 | + if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) { |
| 13 | + /* Put the device into host-mode. */ |
| 14 | flags |= SSB_OHCI_TMSLOW_HOSTMODE; |
| 15 | - |
| 16 | - ssb_device_enable(dev, flags); |
| 17 | + ssb_device_enable(dev, flags); |
| 18 | + } else if (dev->id.coreid == SSB_DEV_USB20_HOST) { |
| 19 | + /* |
| 20 | + * USB 2.0 special considerations: |
| 21 | + * |
| 22 | + * 1. Since the core supports both OHCI and EHCI functions, it must |
| 23 | + * only be reset once. |
| 24 | + * |
| 25 | + * 2. In addition to the standard SSB reset sequence, the Host Control |
| 26 | + * Register must be programmed to bring the USB core and various |
| 27 | + * phy components out of reset. |
| 28 | + */ |
| 29 | + ssb_device_enable(dev, 0); |
| 30 | + ssb_write32(dev, 0x200, 0x7ff); |
| 31 | + udelay(1); |
| 32 | + if (dev->id.revision == 1) { // bug in rev 1 |
| 33 | + |
| 34 | + /* Change Flush control reg */ |
| 35 | + tmp = ssb_read32(dev, 0x400); |
| 36 | + tmp &= ~8; |
| 37 | + ssb_write32(dev, 0x400, tmp); |
| 38 | + tmp = ssb_read32(dev, 0x400); |
| 39 | + printk("USB20H fcr: 0x%0x\n", tmp); |
| 40 | + |
| 41 | + /* Change Shim control reg */ |
| 42 | + tmp = ssb_read32(dev, 0x304); |
| 43 | + tmp &= ~0x100; |
| 44 | + ssb_write32(dev, 0x304, tmp); |
| 45 | + tmp = ssb_read32(dev, 0x304); |
| 46 | + printk("USB20H shim: 0x%0x\n", tmp); |
| 47 | + } |
| 48 | + } else |
| 49 | + ssb_device_enable(dev, 0); |
| 50 | |
| 51 | hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev, |
| 52 | dev_name(dev->dev)); |
| 53 | @@ -200,6 +232,7 @@ static int ssb_ohci_resume(struct ssb_de |
| 54 | static const struct ssb_device_id ssb_ohci_table[] = { |
| 55 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV), |
| 56 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV), |
| 57 | + SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV), |
| 58 | SSB_DEVTABLE_END |
| 59 | }; |
| 60 | MODULE_DEVICE_TABLE(ssb, ssb_ohci_table); |
| 61 | |