brcm47xx/patches-2.6.35: Allow SSB EHCI/OHCI drivers to co-exist (thank you Steve...
[openwrt/svn-archive/archive.git] / target / linux / brcm47xx / patches-2.6.35 / 023-usb_ehci_ohci.patch
1 --- a/drivers/usb/host/ohci-ssb.c
2 +++ b/drivers/usb/host/ohci-ssb.c
3 @@ -17,6 +17,8 @@
4 */
5 #include <linux/ssb/ssb.h>
6
7 +extern int ssb_ehci_attach(struct ssb_device *dev, struct usb_hcd **hcd);
8 +extern void ssb_ehci_detach(struct ssb_device *dev, struct usb_hcd *hcd);
9
10 #define SSB_OHCI_TMSLOW_HOSTMODE (1 << 29)
11
12 @@ -24,6 +26,9 @@ struct ssb_ohci_device {
13 struct ohci_hcd ohci; /* _must_ be at the beginning. */
14
15 u32 enable_flags;
16 +#ifdef CONFIG_USB_EHCI_HCD_SSB
17 + struct usb_hcd *ehci_hcd;
18 +#endif
19 };
20
21 static inline
22 @@ -92,6 +97,9 @@ static const struct hc_driver ssb_ohci_h
23 static void ssb_ohci_detach(struct ssb_device *dev)
24 {
25 struct usb_hcd *hcd = ssb_get_drvdata(dev);
26 +#ifdef CONFIG_USB_EHCI_HCD_SSB
27 + struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
28 +#endif
29
30 if (hcd->driver->shutdown)
31 hcd->driver->shutdown(hcd);
32 @@ -99,6 +107,14 @@ static void ssb_ohci_detach(struct ssb_d
33 iounmap(hcd->regs);
34 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
35 usb_put_hcd(hcd);
36 +
37 +#ifdef CONFIG_USB_EHCI_HCD_SSB
38 + /*
39 + * Also detach ehci function
40 + */
41 + if (dev->id.coreid == SSB_DEV_USB20_HOST)
42 + ssb_ehci_detach(dev, ohcidev->ehci_hcd);
43 +#endif
44 ssb_device_disable(dev, 0);
45 }
46
47 @@ -121,6 +137,9 @@ static int ssb_ohci_attach(struct ssb_de
48 /*
49 * USB 2.0 special considerations:
50 *
51 + * Since the core supports both OHCI and EHCI functions,
52 + * it must only be reset once.
53 + *
54 * In addition to the standard SSB reset sequence, the Host
55 * Control Register must be programmed to bring the USB core
56 * and various phy components out of reset.
57 @@ -175,6 +194,14 @@ static int ssb_ohci_attach(struct ssb_de
58
59 ssb_set_drvdata(dev, hcd);
60
61 +#ifdef CONFIG_USB_EHCI_HCD_SSB
62 + /*
63 + * attach ehci function in this core
64 + */
65 + if (dev->id.coreid == SSB_DEV_USB20_HOST)
66 + err = ssb_ehci_attach(dev, &(ohcidev->ehci_hcd));
67 +#endif
68 +
69 return err;
70
71 err_iounmap:
72 --- a/drivers/usb/host/ehci-ssb.c
73 +++ b/drivers/usb/host/ehci-ssb.c
74 @@ -106,10 +106,18 @@ static void ssb_ehci_detach(struct ssb_d
75 iounmap(hcd->regs);
76 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
77 usb_put_hcd(hcd);
78 +#ifndef CONFIG_USB_OHCI_HCD_SSB
79 + ssb_device_disable(dev, 0);
80 +#endif
81 ssb_device_disable(dev, 0);
82 }
83 +EXPORT_SYMBOL_GPL(ssb_ehci_detach);
84
85 +#ifndef CONFIG_USB_OHCI_HCD_SSB
86 static int ssb_ehci_attach(struct ssb_device *dev)
87 +#else
88 +static int ssb_ehci_attach(struct ssb_device *dev, struct usb_hcd **ehci_hcd)
89 +#endif
90 {
91 struct ssb_ehci_device *ehcidev;
92 struct usb_hcd *hcd;
93 @@ -120,6 +128,7 @@ static int ssb_ehci_attach(struct ssb_de
94 dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
95 return -EOPNOTSUPP;
96
97 +#ifndef CONFIG_USB_OHCI_HCD_SSB
98 /*
99 * USB 2.0 special considerations:
100 *
101 @@ -155,6 +164,7 @@ static int ssb_ehci_attach(struct ssb_de
102 tmp |= 0x1;
103 ssb_write32(dev, 0x89c, tmp);
104 }
105 +#endif
106
107 hcd = usb_create_hcd(&ssb_ehci_hc_driver, dev->dev,
108 dev_name(dev->dev));
109 @@ -175,7 +185,11 @@ static int ssb_ehci_attach(struct ssb_de
110 if (err)
111 goto err_iounmap;
112
113 +#ifndef CONFIG_USB_OHCI_HCD_SSB
114 ssb_set_drvdata(dev, hcd);
115 +#else
116 + *ehci_hcd = hcd;
117 +#endif
118
119 return err;
120
121 @@ -187,7 +201,9 @@ err_dev_disable:
122 ssb_device_disable(dev, 0);
123 return err;
124 }
125 +EXPORT_SYMBOL_GPL(ssb_ehci_attach);
126
127 +#ifndef CONFIG_USB_OHCI_HCD_SSB
128 static int ssb_ehci_probe(struct ssb_device *dev,
129 const struct ssb_device_id *id)
130 {
131 @@ -238,6 +254,7 @@ static int ssb_ehci_resume(struct ssb_de
132 #define ssb_ehci_suspend NULL
133 #define ssb_ehci_resume NULL
134 #endif /* CONFIG_PM */
135 +#endif /* !CONFIG_USB_OHCI_HCD_SSB */
136
137 static const struct ssb_device_id ssb_ehci_table[] = {
138 SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
139 @@ -245,6 +262,8 @@ static const struct ssb_device_id ssb_eh
140 };
141 MODULE_DEVICE_TABLE(ssb, ssb_ehci_table);
142
143 +
144 +#ifndef CONFIG_USB_OHCI_HCD_SSB
145 static struct ssb_driver ssb_ehci_driver = {
146 .name = KBUILD_MODNAME,
147 .id_table = ssb_ehci_table,
148 @@ -253,3 +272,4 @@ static struct ssb_driver ssb_ehci_driver
149 .suspend = ssb_ehci_suspend,
150 .resume = ssb_ehci_resume,
151 };
152 +#endif
153 --- a/drivers/usb/host/ehci-hcd.c
154 +++ b/drivers/usb/host/ehci-hcd.c
155 @@ -1226,17 +1226,21 @@ static int __init ehci_hcd_init(void)
156 goto clean4;
157 #endif
158
159 +#ifndef CONFIG_USB_OHCI_HCD_SSB
160 #ifdef SSB_EHCI_DRIVER
161 retval = ssb_driver_register(&SSB_EHCI_DRIVER);
162 if (retval < 0)
163 goto clean5;
164 #endif
165 +#endif /* !CONFIG_USB_OHCI_HCD_SSB */
166 return retval;
167
168 +#ifndef CONFIG_USB_OHCI_HCD_SSB
169 #ifdef SSB_EHCI_DRIVER
170 /* ssb_driver_unregister(&SSB_EHCI_DRIVER); */
171 clean5:
172 #endif
173 +#endif /* !CONFIG_USB_OHCI_HCD_SSB */
174 #ifdef XILINX_OF_PLATFORM_DRIVER
175 of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER);
176 clean4:
177 @@ -1269,9 +1273,11 @@ module_init(ehci_hcd_init);
178
179 static void __exit ehci_hcd_cleanup(void)
180 {
181 +#ifndef CONFIG_USB_OHCI_HCD_SSB
182 #ifdef SSB_EHCI_DRIVER
183 ssb_driver_unregister(&SSB_EHCI_DRIVER);
184 #endif
185 +#endif /* !CONFIG_USB_OHCI_HCD_SSB */
186 #ifdef XILINX_OF_PLATFORM_DRIVER
187 of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER);
188 #endif