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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
|
--- a/drivers/usb/host/ohci-ssb.c
+++ b/drivers/usb/host/ohci-ssb.c
@@ -17,6 +17,8 @@
*/
#include <linux/ssb/ssb.h>
+extern int ssb_ehci_attach(struct ssb_device *dev, struct usb_hcd **hcd);
+extern void ssb_ehci_detach(struct ssb_device *dev, struct usb_hcd *hcd);
#define SSB_OHCI_TMSLOW_HOSTMODE (1 << 29)
@@ -24,6 +26,9 @@ struct ssb_ohci_device {
struct ohci_hcd ohci; /* _must_ be at the beginning. */
u32 enable_flags;
+#ifdef CONFIG_USB_EHCI_HCD_SSB
+ struct usb_hcd *ehci_hcd;
+#endif
};
static inline
@@ -92,6 +97,9 @@ static const struct hc_driver ssb_ohci_h
static void ssb_ohci_detach(struct ssb_device *dev)
{
struct usb_hcd *hcd = ssb_get_drvdata(dev);
+#ifdef CONFIG_USB_EHCI_HCD_SSB
+ struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
+#endif
if (hcd->driver->shutdown)
hcd->driver->shutdown(hcd);
@@ -99,6 +107,14 @@ static void ssb_ohci_detach(struct ssb_d
iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
+
+#ifdef CONFIG_USB_EHCI_HCD_SSB
+ /*
+ * Also detach ehci function
+ */
+ if (dev->id.coreid == SSB_DEV_USB20_HOST)
+ ssb_ehci_detach(dev, ohcidev->ehci_hcd);
+#endif
ssb_device_disable(dev, 0);
}
@@ -121,6 +137,9 @@ static int ssb_ohci_attach(struct ssb_de
/*
* USB 2.0 special considerations:
*
+ * Since the core supports both OHCI and EHCI functions,
+ * it must only be reset once.
+ *
* In addition to the standard SSB reset sequence, the Host
* Control Register must be programmed to bring the USB core
* and various phy components out of reset.
@@ -175,6 +194,14 @@ static int ssb_ohci_attach(struct ssb_de
ssb_set_drvdata(dev, hcd);
+#ifdef CONFIG_USB_EHCI_HCD_SSB
+ /*
+ * attach ehci function in this core
+ */
+ if (dev->id.coreid == SSB_DEV_USB20_HOST)
+ err = ssb_ehci_attach(dev, &(ohcidev->ehci_hcd));
+#endif
+
return err;
err_iounmap:
--- a/drivers/usb/host/ehci-ssb.c
+++ b/drivers/usb/host/ehci-ssb.c
@@ -106,10 +106,18 @@ static void ssb_ehci_detach(struct ssb_d
iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
+#ifndef CONFIG_USB_OHCI_HCD_SSB
+ ssb_device_disable(dev, 0);
+#endif
ssb_device_disable(dev, 0);
}
+EXPORT_SYMBOL_GPL(ssb_ehci_detach);
+#ifndef CONFIG_USB_OHCI_HCD_SSB
static int ssb_ehci_attach(struct ssb_device *dev)
+#else
+static int ssb_ehci_attach(struct ssb_device *dev, struct usb_hcd **ehci_hcd)
+#endif
{
struct ssb_ehci_device *ehcidev;
struct usb_hcd *hcd;
@@ -120,6 +128,7 @@ static int ssb_ehci_attach(struct ssb_de
dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
return -EOPNOTSUPP;
+#ifndef CONFIG_USB_OHCI_HCD_SSB
/*
* USB 2.0 special considerations:
*
@@ -155,6 +164,7 @@ static int ssb_ehci_attach(struct ssb_de
tmp |= 0x1;
ssb_write32(dev, 0x89c, tmp);
}
+#endif
hcd = usb_create_hcd(&ssb_ehci_hc_driver, dev->dev,
dev_name(dev->dev));
@@ -175,7 +185,11 @@ static int ssb_ehci_attach(struct ssb_de
if (err)
goto err_iounmap;
+#ifndef CONFIG_USB_OHCI_HCD_SSB
ssb_set_drvdata(dev, hcd);
+#else
+ *ehci_hcd = hcd;
+#endif
return err;
@@ -187,7 +201,9 @@ err_dev_disable:
ssb_device_disable(dev, 0);
return err;
}
+EXPORT_SYMBOL_GPL(ssb_ehci_attach);
+#ifndef CONFIG_USB_OHCI_HCD_SSB
static int ssb_ehci_probe(struct ssb_device *dev,
const struct ssb_device_id *id)
{
@@ -238,6 +254,7 @@ static int ssb_ehci_resume(struct ssb_de
#define ssb_ehci_suspend NULL
#define ssb_ehci_resume NULL
#endif /* CONFIG_PM */
+#endif /* !CONFIG_USB_OHCI_HCD_SSB */
static const struct ssb_device_id ssb_ehci_table[] = {
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
@@ -245,6 +262,8 @@ static const struct ssb_device_id ssb_eh
};
MODULE_DEVICE_TABLE(ssb, ssb_ehci_table);
+
+#ifndef CONFIG_USB_OHCI_HCD_SSB
static struct ssb_driver ssb_ehci_driver = {
.name = KBUILD_MODNAME,
.id_table = ssb_ehci_table,
@@ -253,3 +272,4 @@ static struct ssb_driver ssb_ehci_driver
.suspend = ssb_ehci_suspend,
.resume = ssb_ehci_resume,
};
+#endif
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1380,17 +1380,21 @@ static int __init ehci_hcd_init(void)
goto clean4;
#endif
+#ifndef CONFIG_USB_OHCI_HCD_SSB
#ifdef SSB_EHCI_DRIVER
retval = ssb_driver_register(&SSB_EHCI_DRIVER);
if (retval < 0)
goto clean5;
#endif
+#endif /* !CONFIG_USB_OHCI_HCD_SSB */
return retval;
+#ifndef CONFIG_USB_OHCI_HCD_SSB
#ifdef SSB_EHCI_DRIVER
/* ssb_driver_unregister(&SSB_EHCI_DRIVER); */
clean5:
#endif
+#endif /* !CONFIG_USB_OHCI_HCD_SSB */
#ifdef XILINX_OF_PLATFORM_DRIVER
platform_driver_unregister(&XILINX_OF_PLATFORM_DRIVER);
clean4:
@@ -1423,9 +1427,11 @@ module_init(ehci_hcd_init);
static void __exit ehci_hcd_cleanup(void)
{
+#ifndef CONFIG_USB_OHCI_HCD_SSB
#ifdef SSB_EHCI_DRIVER
ssb_driver_unregister(&SSB_EHCI_DRIVER);
#endif
+#endif /* !CONFIG_USB_OHCI_HCD_SSB */
#ifdef XILINX_OF_PLATFORM_DRIVER
platform_driver_unregister(&XILINX_OF_PLATFORM_DRIVER);
#endif
|