summaryrefslogtreecommitdiffstats
path: root/target/linux/brcm47xx/patches-2.6.25/250-ohci-ssb-usb2.patch
blob: 856651b3de87e015d2eb77570f1bf859bd1fed07 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
--- a/drivers/usb/host/ohci-ssb.c
+++ b/drivers/usb/host/ohci-ssb.c
@@ -142,10 +142,59 @@ static int ssb_ohci_attach(struct ssb_de
 	int err = -ENOMEM;
 	u32 tmp, flags = 0;
 
-	if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV)
+	/*
+	 * THE FOLLOWING COMMENTS PRESERVED FROM GPL SOURCE RELEASE
+	 *
+	 * The USB core requires a special bit to be set during core
+	 * reset to enable host (OHCI) mode. Resetting the SB core in
+	 * pcibios_enable_device() is a hack for compatibility with
+	 * vanilla usb-ohci so that it does not have to know about
+	 * SB. A driver that wants to use the USB core in device mode
+	 * should know about SB and should reset the bit back to 0
+	 * after calling pcibios_enable_device().
+	 */
+
+	if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
 		flags |= SSB_OHCI_TMSLOW_HOSTMODE;
+		ssb_device_enable(dev, flags);
+	}
+
+	/*
+	 * USB 2.0 special considerations:
+	 *
+	 * 1. Since the core supports both OHCI and EHCI functions, it must
+	 *    only be reset once.
+	 * 
+	 * 2. In addition to the standard SB reset sequence, the Host Control
+	 *    Register must be programmed to bring the USB core and various
+	 *    phy components out of reset. 
+	 */
+
+	else if (dev->id.coreid == SSB_DEV_USB20_HOST) {
+#warning FIX ME need test for core being up & exit
+		ssb_device_enable(dev, 0);
+		ssb_write32(dev, 0x200, 0x7ff);
+		udelay(1);
+		if (dev->id.revision == 1) { // bug in rev 1
+
+			/* Change Flush control reg */
+			tmp = ssb_read32(dev, 0x400);
+			tmp &= ~8;
+			ssb_write32(dev, 0x400, tmp);
+			tmp = ssb_read32(dev, 0x400);
+			printk("USB20H fcr: 0x%0x\n", tmp);
+
+			/* Change Shim control reg */
+			tmp = ssb_read32(dev, 0x304);
+			tmp &= ~0x100;
+			ssb_write32(dev, 0x304, tmp);
+			tmp = ssb_read32(dev, 0x304);
+			printk("USB20H shim: 0x%0x\n", tmp);
+		}
+	}
+	else
+		ssb_device_enable(dev, 0);
 
-	ssb_device_enable(dev, flags);
 
 	hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev,
 			dev->dev->bus_id);
@@ -236,6 +285,7 @@ static int ssb_ohci_resume(struct ssb_de
 static const struct ssb_device_id ssb_ohci_table[] = {
 	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),
 	SSB_DEVTABLE_END
 };
 MODULE_DEVICE_TABLE(ssb, ssb_ohci_table);