Commit 8a6b088aff969a125cf4ed21f7608112f8b722e5
Exists in
v2017.01-smarct4x
and in
37 other branches
Merge branch 'master' of git://git.denx.de/u-boot-usb
Showing 16 changed files Inline Diff
- common/cmd_usb.c
- common/stdio.c
- common/usb_kbd.c
- drivers/serial/serial-uclass.c
- drivers/usb/gadget/ci_udc.c
- drivers/usb/gadget/f_dfu.c
- drivers/usb/gadget/f_fastboot.c
- drivers/usb/gadget/f_mass_storage.c
- drivers/usb/gadget/f_thor.c
- drivers/usb/host/ehci-hcd.c
- drivers/usb/host/ehci-tegra.c
- drivers/usb/host/ehci.h
- drivers/usb/musb-new/musb_core.c
- include/configs/siemens-am33x-common.h
- include/stdio_dev.h
- include/usb.h
common/cmd_usb.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2001 | 2 | * (C) Copyright 2001 |
3 | * Denis Peter, MPL AG Switzerland | 3 | * Denis Peter, MPL AG Switzerland |
4 | * | 4 | * |
5 | * Most of this source has been derived from the Linux USB | 5 | * Most of this source has been derived from the Linux USB |
6 | * project. | 6 | * project. |
7 | * | 7 | * |
8 | * SPDX-License-Identifier: GPL-2.0+ | 8 | * SPDX-License-Identifier: GPL-2.0+ |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <common.h> | 11 | #include <common.h> |
12 | #include <command.h> | 12 | #include <command.h> |
13 | #include <asm/byteorder.h> | 13 | #include <asm/byteorder.h> |
14 | #include <asm/unaligned.h> | 14 | #include <asm/unaligned.h> |
15 | #include <part.h> | 15 | #include <part.h> |
16 | #include <usb.h> | 16 | #include <usb.h> |
17 | 17 | ||
18 | #ifdef CONFIG_USB_STORAGE | 18 | #ifdef CONFIG_USB_STORAGE |
19 | static int usb_stor_curr_dev = -1; /* current device */ | 19 | static int usb_stor_curr_dev = -1; /* current device */ |
20 | #endif | 20 | #endif |
21 | #ifdef CONFIG_USB_HOST_ETHER | 21 | #ifdef CONFIG_USB_HOST_ETHER |
22 | static int usb_ether_curr_dev = -1; /* current ethernet device */ | 22 | static int usb_ether_curr_dev = -1; /* current ethernet device */ |
23 | #endif | 23 | #endif |
24 | 24 | ||
25 | /* some display routines (info command) */ | 25 | /* some display routines (info command) */ |
26 | static char *usb_get_class_desc(unsigned char dclass) | 26 | static char *usb_get_class_desc(unsigned char dclass) |
27 | { | 27 | { |
28 | switch (dclass) { | 28 | switch (dclass) { |
29 | case USB_CLASS_PER_INTERFACE: | 29 | case USB_CLASS_PER_INTERFACE: |
30 | return "See Interface"; | 30 | return "See Interface"; |
31 | case USB_CLASS_AUDIO: | 31 | case USB_CLASS_AUDIO: |
32 | return "Audio"; | 32 | return "Audio"; |
33 | case USB_CLASS_COMM: | 33 | case USB_CLASS_COMM: |
34 | return "Communication"; | 34 | return "Communication"; |
35 | case USB_CLASS_HID: | 35 | case USB_CLASS_HID: |
36 | return "Human Interface"; | 36 | return "Human Interface"; |
37 | case USB_CLASS_PRINTER: | 37 | case USB_CLASS_PRINTER: |
38 | return "Printer"; | 38 | return "Printer"; |
39 | case USB_CLASS_MASS_STORAGE: | 39 | case USB_CLASS_MASS_STORAGE: |
40 | return "Mass Storage"; | 40 | return "Mass Storage"; |
41 | case USB_CLASS_HUB: | 41 | case USB_CLASS_HUB: |
42 | return "Hub"; | 42 | return "Hub"; |
43 | case USB_CLASS_DATA: | 43 | case USB_CLASS_DATA: |
44 | return "CDC Data"; | 44 | return "CDC Data"; |
45 | case USB_CLASS_VENDOR_SPEC: | 45 | case USB_CLASS_VENDOR_SPEC: |
46 | return "Vendor specific"; | 46 | return "Vendor specific"; |
47 | default: | 47 | default: |
48 | return ""; | 48 | return ""; |
49 | } | 49 | } |
50 | } | 50 | } |
51 | 51 | ||
52 | static void usb_display_class_sub(unsigned char dclass, unsigned char subclass, | 52 | static void usb_display_class_sub(unsigned char dclass, unsigned char subclass, |
53 | unsigned char proto) | 53 | unsigned char proto) |
54 | { | 54 | { |
55 | switch (dclass) { | 55 | switch (dclass) { |
56 | case USB_CLASS_PER_INTERFACE: | 56 | case USB_CLASS_PER_INTERFACE: |
57 | printf("See Interface"); | 57 | printf("See Interface"); |
58 | break; | 58 | break; |
59 | case USB_CLASS_HID: | 59 | case USB_CLASS_HID: |
60 | printf("Human Interface, Subclass: "); | 60 | printf("Human Interface, Subclass: "); |
61 | switch (subclass) { | 61 | switch (subclass) { |
62 | case USB_SUB_HID_NONE: | 62 | case USB_SUB_HID_NONE: |
63 | printf("None"); | 63 | printf("None"); |
64 | break; | 64 | break; |
65 | case USB_SUB_HID_BOOT: | 65 | case USB_SUB_HID_BOOT: |
66 | printf("Boot "); | 66 | printf("Boot "); |
67 | switch (proto) { | 67 | switch (proto) { |
68 | case USB_PROT_HID_NONE: | 68 | case USB_PROT_HID_NONE: |
69 | printf("None"); | 69 | printf("None"); |
70 | break; | 70 | break; |
71 | case USB_PROT_HID_KEYBOARD: | 71 | case USB_PROT_HID_KEYBOARD: |
72 | printf("Keyboard"); | 72 | printf("Keyboard"); |
73 | break; | 73 | break; |
74 | case USB_PROT_HID_MOUSE: | 74 | case USB_PROT_HID_MOUSE: |
75 | printf("Mouse"); | 75 | printf("Mouse"); |
76 | break; | 76 | break; |
77 | default: | 77 | default: |
78 | printf("reserved"); | 78 | printf("reserved"); |
79 | break; | 79 | break; |
80 | } | 80 | } |
81 | break; | 81 | break; |
82 | default: | 82 | default: |
83 | printf("reserved"); | 83 | printf("reserved"); |
84 | break; | 84 | break; |
85 | } | 85 | } |
86 | break; | 86 | break; |
87 | case USB_CLASS_MASS_STORAGE: | 87 | case USB_CLASS_MASS_STORAGE: |
88 | printf("Mass Storage, "); | 88 | printf("Mass Storage, "); |
89 | switch (subclass) { | 89 | switch (subclass) { |
90 | case US_SC_RBC: | 90 | case US_SC_RBC: |
91 | printf("RBC "); | 91 | printf("RBC "); |
92 | break; | 92 | break; |
93 | case US_SC_8020: | 93 | case US_SC_8020: |
94 | printf("SFF-8020i (ATAPI)"); | 94 | printf("SFF-8020i (ATAPI)"); |
95 | break; | 95 | break; |
96 | case US_SC_QIC: | 96 | case US_SC_QIC: |
97 | printf("QIC-157 (Tape)"); | 97 | printf("QIC-157 (Tape)"); |
98 | break; | 98 | break; |
99 | case US_SC_UFI: | 99 | case US_SC_UFI: |
100 | printf("UFI"); | 100 | printf("UFI"); |
101 | break; | 101 | break; |
102 | case US_SC_8070: | 102 | case US_SC_8070: |
103 | printf("SFF-8070"); | 103 | printf("SFF-8070"); |
104 | break; | 104 | break; |
105 | case US_SC_SCSI: | 105 | case US_SC_SCSI: |
106 | printf("Transp. SCSI"); | 106 | printf("Transp. SCSI"); |
107 | break; | 107 | break; |
108 | default: | 108 | default: |
109 | printf("reserved"); | 109 | printf("reserved"); |
110 | break; | 110 | break; |
111 | } | 111 | } |
112 | printf(", "); | 112 | printf(", "); |
113 | switch (proto) { | 113 | switch (proto) { |
114 | case US_PR_CB: | 114 | case US_PR_CB: |
115 | printf("Command/Bulk"); | 115 | printf("Command/Bulk"); |
116 | break; | 116 | break; |
117 | case US_PR_CBI: | 117 | case US_PR_CBI: |
118 | printf("Command/Bulk/Int"); | 118 | printf("Command/Bulk/Int"); |
119 | break; | 119 | break; |
120 | case US_PR_BULK: | 120 | case US_PR_BULK: |
121 | printf("Bulk only"); | 121 | printf("Bulk only"); |
122 | break; | 122 | break; |
123 | default: | 123 | default: |
124 | printf("reserved"); | 124 | printf("reserved"); |
125 | break; | 125 | break; |
126 | } | 126 | } |
127 | break; | 127 | break; |
128 | default: | 128 | default: |
129 | printf("%s", usb_get_class_desc(dclass)); | 129 | printf("%s", usb_get_class_desc(dclass)); |
130 | break; | 130 | break; |
131 | } | 131 | } |
132 | } | 132 | } |
133 | 133 | ||
134 | static void usb_display_string(struct usb_device *dev, int index) | 134 | static void usb_display_string(struct usb_device *dev, int index) |
135 | { | 135 | { |
136 | ALLOC_CACHE_ALIGN_BUFFER(char, buffer, 256); | 136 | ALLOC_CACHE_ALIGN_BUFFER(char, buffer, 256); |
137 | 137 | ||
138 | if (index != 0) { | 138 | if (index != 0) { |
139 | if (usb_string(dev, index, &buffer[0], 256) > 0) | 139 | if (usb_string(dev, index, &buffer[0], 256) > 0) |
140 | printf("String: \"%s\"", buffer); | 140 | printf("String: \"%s\"", buffer); |
141 | } | 141 | } |
142 | } | 142 | } |
143 | 143 | ||
144 | static void usb_display_desc(struct usb_device *dev) | 144 | static void usb_display_desc(struct usb_device *dev) |
145 | { | 145 | { |
146 | if (dev->descriptor.bDescriptorType == USB_DT_DEVICE) { | 146 | if (dev->descriptor.bDescriptorType == USB_DT_DEVICE) { |
147 | printf("%d: %s, USB Revision %x.%x\n", dev->devnum, | 147 | printf("%d: %s, USB Revision %x.%x\n", dev->devnum, |
148 | usb_get_class_desc(dev->config.if_desc[0].desc.bInterfaceClass), | 148 | usb_get_class_desc(dev->config.if_desc[0].desc.bInterfaceClass), |
149 | (dev->descriptor.bcdUSB>>8) & 0xff, | 149 | (dev->descriptor.bcdUSB>>8) & 0xff, |
150 | dev->descriptor.bcdUSB & 0xff); | 150 | dev->descriptor.bcdUSB & 0xff); |
151 | 151 | ||
152 | if (strlen(dev->mf) || strlen(dev->prod) || | 152 | if (strlen(dev->mf) || strlen(dev->prod) || |
153 | strlen(dev->serial)) | 153 | strlen(dev->serial)) |
154 | printf(" - %s %s %s\n", dev->mf, dev->prod, | 154 | printf(" - %s %s %s\n", dev->mf, dev->prod, |
155 | dev->serial); | 155 | dev->serial); |
156 | if (dev->descriptor.bDeviceClass) { | 156 | if (dev->descriptor.bDeviceClass) { |
157 | printf(" - Class: "); | 157 | printf(" - Class: "); |
158 | usb_display_class_sub(dev->descriptor.bDeviceClass, | 158 | usb_display_class_sub(dev->descriptor.bDeviceClass, |
159 | dev->descriptor.bDeviceSubClass, | 159 | dev->descriptor.bDeviceSubClass, |
160 | dev->descriptor.bDeviceProtocol); | 160 | dev->descriptor.bDeviceProtocol); |
161 | printf("\n"); | 161 | printf("\n"); |
162 | } else { | 162 | } else { |
163 | printf(" - Class: (from Interface) %s\n", | 163 | printf(" - Class: (from Interface) %s\n", |
164 | usb_get_class_desc( | 164 | usb_get_class_desc( |
165 | dev->config.if_desc[0].desc.bInterfaceClass)); | 165 | dev->config.if_desc[0].desc.bInterfaceClass)); |
166 | } | 166 | } |
167 | printf(" - PacketSize: %d Configurations: %d\n", | 167 | printf(" - PacketSize: %d Configurations: %d\n", |
168 | dev->descriptor.bMaxPacketSize0, | 168 | dev->descriptor.bMaxPacketSize0, |
169 | dev->descriptor.bNumConfigurations); | 169 | dev->descriptor.bNumConfigurations); |
170 | printf(" - Vendor: 0x%04x Product 0x%04x Version %d.%d\n", | 170 | printf(" - Vendor: 0x%04x Product 0x%04x Version %d.%d\n", |
171 | dev->descriptor.idVendor, dev->descriptor.idProduct, | 171 | dev->descriptor.idVendor, dev->descriptor.idProduct, |
172 | (dev->descriptor.bcdDevice>>8) & 0xff, | 172 | (dev->descriptor.bcdDevice>>8) & 0xff, |
173 | dev->descriptor.bcdDevice & 0xff); | 173 | dev->descriptor.bcdDevice & 0xff); |
174 | } | 174 | } |
175 | 175 | ||
176 | } | 176 | } |
177 | 177 | ||
178 | static void usb_display_conf_desc(struct usb_config_descriptor *config, | 178 | static void usb_display_conf_desc(struct usb_config_descriptor *config, |
179 | struct usb_device *dev) | 179 | struct usb_device *dev) |
180 | { | 180 | { |
181 | printf(" Configuration: %d\n", config->bConfigurationValue); | 181 | printf(" Configuration: %d\n", config->bConfigurationValue); |
182 | printf(" - Interfaces: %d %s%s%dmA\n", config->bNumInterfaces, | 182 | printf(" - Interfaces: %d %s%s%dmA\n", config->bNumInterfaces, |
183 | (config->bmAttributes & 0x40) ? "Self Powered " : "Bus Powered ", | 183 | (config->bmAttributes & 0x40) ? "Self Powered " : "Bus Powered ", |
184 | (config->bmAttributes & 0x20) ? "Remote Wakeup " : "", | 184 | (config->bmAttributes & 0x20) ? "Remote Wakeup " : "", |
185 | config->bMaxPower*2); | 185 | config->bMaxPower*2); |
186 | if (config->iConfiguration) { | 186 | if (config->iConfiguration) { |
187 | printf(" - "); | 187 | printf(" - "); |
188 | usb_display_string(dev, config->iConfiguration); | 188 | usb_display_string(dev, config->iConfiguration); |
189 | printf("\n"); | 189 | printf("\n"); |
190 | } | 190 | } |
191 | } | 191 | } |
192 | 192 | ||
193 | static void usb_display_if_desc(struct usb_interface_descriptor *ifdesc, | 193 | static void usb_display_if_desc(struct usb_interface_descriptor *ifdesc, |
194 | struct usb_device *dev) | 194 | struct usb_device *dev) |
195 | { | 195 | { |
196 | printf(" Interface: %d\n", ifdesc->bInterfaceNumber); | 196 | printf(" Interface: %d\n", ifdesc->bInterfaceNumber); |
197 | printf(" - Alternate Setting %d, Endpoints: %d\n", | 197 | printf(" - Alternate Setting %d, Endpoints: %d\n", |
198 | ifdesc->bAlternateSetting, ifdesc->bNumEndpoints); | 198 | ifdesc->bAlternateSetting, ifdesc->bNumEndpoints); |
199 | printf(" - Class "); | 199 | printf(" - Class "); |
200 | usb_display_class_sub(ifdesc->bInterfaceClass, | 200 | usb_display_class_sub(ifdesc->bInterfaceClass, |
201 | ifdesc->bInterfaceSubClass, ifdesc->bInterfaceProtocol); | 201 | ifdesc->bInterfaceSubClass, ifdesc->bInterfaceProtocol); |
202 | printf("\n"); | 202 | printf("\n"); |
203 | if (ifdesc->iInterface) { | 203 | if (ifdesc->iInterface) { |
204 | printf(" - "); | 204 | printf(" - "); |
205 | usb_display_string(dev, ifdesc->iInterface); | 205 | usb_display_string(dev, ifdesc->iInterface); |
206 | printf("\n"); | 206 | printf("\n"); |
207 | } | 207 | } |
208 | } | 208 | } |
209 | 209 | ||
210 | static void usb_display_ep_desc(struct usb_endpoint_descriptor *epdesc) | 210 | static void usb_display_ep_desc(struct usb_endpoint_descriptor *epdesc) |
211 | { | 211 | { |
212 | printf(" - Endpoint %d %s ", epdesc->bEndpointAddress & 0xf, | 212 | printf(" - Endpoint %d %s ", epdesc->bEndpointAddress & 0xf, |
213 | (epdesc->bEndpointAddress & 0x80) ? "In" : "Out"); | 213 | (epdesc->bEndpointAddress & 0x80) ? "In" : "Out"); |
214 | switch ((epdesc->bmAttributes & 0x03)) { | 214 | switch ((epdesc->bmAttributes & 0x03)) { |
215 | case 0: | 215 | case 0: |
216 | printf("Control"); | 216 | printf("Control"); |
217 | break; | 217 | break; |
218 | case 1: | 218 | case 1: |
219 | printf("Isochronous"); | 219 | printf("Isochronous"); |
220 | break; | 220 | break; |
221 | case 2: | 221 | case 2: |
222 | printf("Bulk"); | 222 | printf("Bulk"); |
223 | break; | 223 | break; |
224 | case 3: | 224 | case 3: |
225 | printf("Interrupt"); | 225 | printf("Interrupt"); |
226 | break; | 226 | break; |
227 | } | 227 | } |
228 | printf(" MaxPacket %d", get_unaligned(&epdesc->wMaxPacketSize)); | 228 | printf(" MaxPacket %d", get_unaligned(&epdesc->wMaxPacketSize)); |
229 | if ((epdesc->bmAttributes & 0x03) == 0x3) | 229 | if ((epdesc->bmAttributes & 0x03) == 0x3) |
230 | printf(" Interval %dms", epdesc->bInterval); | 230 | printf(" Interval %dms", epdesc->bInterval); |
231 | printf("\n"); | 231 | printf("\n"); |
232 | } | 232 | } |
233 | 233 | ||
234 | /* main routine to diasplay the configs, interfaces and endpoints */ | 234 | /* main routine to diasplay the configs, interfaces and endpoints */ |
235 | static void usb_display_config(struct usb_device *dev) | 235 | static void usb_display_config(struct usb_device *dev) |
236 | { | 236 | { |
237 | struct usb_config *config; | 237 | struct usb_config *config; |
238 | struct usb_interface *ifdesc; | 238 | struct usb_interface *ifdesc; |
239 | struct usb_endpoint_descriptor *epdesc; | 239 | struct usb_endpoint_descriptor *epdesc; |
240 | int i, ii; | 240 | int i, ii; |
241 | 241 | ||
242 | config = &dev->config; | 242 | config = &dev->config; |
243 | usb_display_conf_desc(&config->desc, dev); | 243 | usb_display_conf_desc(&config->desc, dev); |
244 | for (i = 0; i < config->no_of_if; i++) { | 244 | for (i = 0; i < config->no_of_if; i++) { |
245 | ifdesc = &config->if_desc[i]; | 245 | ifdesc = &config->if_desc[i]; |
246 | usb_display_if_desc(&ifdesc->desc, dev); | 246 | usb_display_if_desc(&ifdesc->desc, dev); |
247 | for (ii = 0; ii < ifdesc->no_of_ep; ii++) { | 247 | for (ii = 0; ii < ifdesc->no_of_ep; ii++) { |
248 | epdesc = &ifdesc->ep_desc[ii]; | 248 | epdesc = &ifdesc->ep_desc[ii]; |
249 | usb_display_ep_desc(epdesc); | 249 | usb_display_ep_desc(epdesc); |
250 | } | 250 | } |
251 | } | 251 | } |
252 | printf("\n"); | 252 | printf("\n"); |
253 | } | 253 | } |
254 | 254 | ||
255 | static struct usb_device *usb_find_device(int devnum) | 255 | static struct usb_device *usb_find_device(int devnum) |
256 | { | 256 | { |
257 | struct usb_device *dev; | 257 | struct usb_device *dev; |
258 | int d; | 258 | int d; |
259 | 259 | ||
260 | for (d = 0; d < USB_MAX_DEVICE; d++) { | 260 | for (d = 0; d < USB_MAX_DEVICE; d++) { |
261 | dev = usb_get_dev_index(d); | 261 | dev = usb_get_dev_index(d); |
262 | if (dev == NULL) | 262 | if (dev == NULL) |
263 | return NULL; | 263 | return NULL; |
264 | if (dev->devnum == devnum) | 264 | if (dev->devnum == devnum) |
265 | return dev; | 265 | return dev; |
266 | } | 266 | } |
267 | 267 | ||
268 | return NULL; | 268 | return NULL; |
269 | } | 269 | } |
270 | 270 | ||
271 | static inline char *portspeed(int speed) | 271 | static inline char *portspeed(int speed) |
272 | { | 272 | { |
273 | char *speed_str; | 273 | char *speed_str; |
274 | 274 | ||
275 | switch (speed) { | 275 | switch (speed) { |
276 | case USB_SPEED_SUPER: | 276 | case USB_SPEED_SUPER: |
277 | speed_str = "5 Gb/s"; | 277 | speed_str = "5 Gb/s"; |
278 | break; | 278 | break; |
279 | case USB_SPEED_HIGH: | 279 | case USB_SPEED_HIGH: |
280 | speed_str = "480 Mb/s"; | 280 | speed_str = "480 Mb/s"; |
281 | break; | 281 | break; |
282 | case USB_SPEED_LOW: | 282 | case USB_SPEED_LOW: |
283 | speed_str = "1.5 Mb/s"; | 283 | speed_str = "1.5 Mb/s"; |
284 | break; | 284 | break; |
285 | default: | 285 | default: |
286 | speed_str = "12 Mb/s"; | 286 | speed_str = "12 Mb/s"; |
287 | break; | 287 | break; |
288 | } | 288 | } |
289 | 289 | ||
290 | return speed_str; | 290 | return speed_str; |
291 | } | 291 | } |
292 | 292 | ||
293 | /* shows the device tree recursively */ | 293 | /* shows the device tree recursively */ |
294 | static void usb_show_tree_graph(struct usb_device *dev, char *pre) | 294 | static void usb_show_tree_graph(struct usb_device *dev, char *pre) |
295 | { | 295 | { |
296 | int i, index; | 296 | int i, index; |
297 | int has_child, last_child; | 297 | int has_child, last_child; |
298 | 298 | ||
299 | index = strlen(pre); | 299 | index = strlen(pre); |
300 | printf(" %s", pre); | 300 | printf(" %s", pre); |
301 | /* check if the device has connected children */ | 301 | /* check if the device has connected children */ |
302 | has_child = 0; | 302 | has_child = 0; |
303 | for (i = 0; i < dev->maxchild; i++) { | 303 | for (i = 0; i < dev->maxchild; i++) { |
304 | if (dev->children[i] != NULL) | 304 | if (dev->children[i] != NULL) |
305 | has_child = 1; | 305 | has_child = 1; |
306 | } | 306 | } |
307 | /* check if we are the last one */ | 307 | /* check if we are the last one */ |
308 | last_child = 1; | 308 | last_child = 1; |
309 | if (dev->parent != NULL) { | 309 | if (dev->parent != NULL) { |
310 | for (i = 0; i < dev->parent->maxchild; i++) { | 310 | for (i = 0; i < dev->parent->maxchild; i++) { |
311 | /* search for children */ | 311 | /* search for children */ |
312 | if (dev->parent->children[i] == dev) { | 312 | if (dev->parent->children[i] == dev) { |
313 | /* found our pointer, see if we have a | 313 | /* found our pointer, see if we have a |
314 | * little sister | 314 | * little sister |
315 | */ | 315 | */ |
316 | while (i++ < dev->parent->maxchild) { | 316 | while (i++ < dev->parent->maxchild) { |
317 | if (dev->parent->children[i] != NULL) { | 317 | if (dev->parent->children[i] != NULL) { |
318 | /* found a sister */ | 318 | /* found a sister */ |
319 | last_child = 0; | 319 | last_child = 0; |
320 | break; | 320 | break; |
321 | } /* if */ | 321 | } /* if */ |
322 | } /* while */ | 322 | } /* while */ |
323 | } /* device found */ | 323 | } /* device found */ |
324 | } /* for all children of the parent */ | 324 | } /* for all children of the parent */ |
325 | printf("\b+-"); | 325 | printf("\b+-"); |
326 | /* correct last child */ | 326 | /* correct last child */ |
327 | if (last_child) | 327 | if (last_child) |
328 | pre[index-1] = ' '; | 328 | pre[index-1] = ' '; |
329 | } /* if not root hub */ | 329 | } /* if not root hub */ |
330 | else | 330 | else |
331 | printf(" "); | 331 | printf(" "); |
332 | printf("%d ", dev->devnum); | 332 | printf("%d ", dev->devnum); |
333 | pre[index++] = ' '; | 333 | pre[index++] = ' '; |
334 | pre[index++] = has_child ? '|' : ' '; | 334 | pre[index++] = has_child ? '|' : ' '; |
335 | pre[index] = 0; | 335 | pre[index] = 0; |
336 | printf(" %s (%s, %dmA)\n", usb_get_class_desc( | 336 | printf(" %s (%s, %dmA)\n", usb_get_class_desc( |
337 | dev->config.if_desc[0].desc.bInterfaceClass), | 337 | dev->config.if_desc[0].desc.bInterfaceClass), |
338 | portspeed(dev->speed), | 338 | portspeed(dev->speed), |
339 | dev->config.desc.bMaxPower * 2); | 339 | dev->config.desc.bMaxPower * 2); |
340 | if (strlen(dev->mf) || strlen(dev->prod) || strlen(dev->serial)) | 340 | if (strlen(dev->mf) || strlen(dev->prod) || strlen(dev->serial)) |
341 | printf(" %s %s %s %s\n", pre, dev->mf, dev->prod, dev->serial); | 341 | printf(" %s %s %s %s\n", pre, dev->mf, dev->prod, dev->serial); |
342 | printf(" %s\n", pre); | 342 | printf(" %s\n", pre); |
343 | if (dev->maxchild > 0) { | 343 | if (dev->maxchild > 0) { |
344 | for (i = 0; i < dev->maxchild; i++) { | 344 | for (i = 0; i < dev->maxchild; i++) { |
345 | if (dev->children[i] != NULL) { | 345 | if (dev->children[i] != NULL) { |
346 | usb_show_tree_graph(dev->children[i], pre); | 346 | usb_show_tree_graph(dev->children[i], pre); |
347 | pre[index] = 0; | 347 | pre[index] = 0; |
348 | } | 348 | } |
349 | } | 349 | } |
350 | } | 350 | } |
351 | } | 351 | } |
352 | 352 | ||
353 | /* main routine for the tree command */ | 353 | /* main routine for the tree command */ |
354 | static void usb_show_tree(struct usb_device *dev) | 354 | static void usb_show_tree(struct usb_device *dev) |
355 | { | 355 | { |
356 | char preamble[32]; | 356 | char preamble[32]; |
357 | 357 | ||
358 | memset(preamble, 0, 32); | 358 | memset(preamble, 0, 32); |
359 | usb_show_tree_graph(dev, &preamble[0]); | 359 | usb_show_tree_graph(dev, &preamble[0]); |
360 | } | 360 | } |
361 | 361 | ||
362 | static int usb_test(struct usb_device *dev, int port, char* arg) | 362 | static int usb_test(struct usb_device *dev, int port, char* arg) |
363 | { | 363 | { |
364 | int mode; | 364 | int mode; |
365 | 365 | ||
366 | if (port > dev->maxchild) { | 366 | if (port > dev->maxchild) { |
367 | printf("Device is no hub or does not have %d ports.\n", port); | 367 | printf("Device is no hub or does not have %d ports.\n", port); |
368 | return 1; | 368 | return 1; |
369 | } | 369 | } |
370 | 370 | ||
371 | switch (arg[0]) { | 371 | switch (arg[0]) { |
372 | case 'J': | 372 | case 'J': |
373 | case 'j': | 373 | case 'j': |
374 | printf("Setting Test_J mode"); | 374 | printf("Setting Test_J mode"); |
375 | mode = USB_TEST_MODE_J; | 375 | mode = USB_TEST_MODE_J; |
376 | break; | 376 | break; |
377 | case 'K': | 377 | case 'K': |
378 | case 'k': | 378 | case 'k': |
379 | printf("Setting Test_K mode"); | 379 | printf("Setting Test_K mode"); |
380 | mode = USB_TEST_MODE_K; | 380 | mode = USB_TEST_MODE_K; |
381 | break; | 381 | break; |
382 | case 'S': | 382 | case 'S': |
383 | case 's': | 383 | case 's': |
384 | printf("Setting Test_SE0_NAK mode"); | 384 | printf("Setting Test_SE0_NAK mode"); |
385 | mode = USB_TEST_MODE_SE0_NAK; | 385 | mode = USB_TEST_MODE_SE0_NAK; |
386 | break; | 386 | break; |
387 | case 'P': | 387 | case 'P': |
388 | case 'p': | 388 | case 'p': |
389 | printf("Setting Test_Packet mode"); | 389 | printf("Setting Test_Packet mode"); |
390 | mode = USB_TEST_MODE_PACKET; | 390 | mode = USB_TEST_MODE_PACKET; |
391 | break; | 391 | break; |
392 | case 'F': | 392 | case 'F': |
393 | case 'f': | 393 | case 'f': |
394 | printf("Setting Test_Force_Enable mode"); | 394 | printf("Setting Test_Force_Enable mode"); |
395 | mode = USB_TEST_MODE_FORCE_ENABLE; | 395 | mode = USB_TEST_MODE_FORCE_ENABLE; |
396 | break; | 396 | break; |
397 | default: | 397 | default: |
398 | printf("Unrecognized test mode: %s\nAvailable modes: " | 398 | printf("Unrecognized test mode: %s\nAvailable modes: " |
399 | "J, K, S[E0_NAK], P[acket], F[orce_Enable]\n", arg); | 399 | "J, K, S[E0_NAK], P[acket], F[orce_Enable]\n", arg); |
400 | return 1; | 400 | return 1; |
401 | } | 401 | } |
402 | 402 | ||
403 | if (port) | 403 | if (port) |
404 | printf(" on downstream facing port %d...\n", port); | 404 | printf(" on downstream facing port %d...\n", port); |
405 | else | 405 | else |
406 | printf(" on upstream facing port...\n"); | 406 | printf(" on upstream facing port...\n"); |
407 | 407 | ||
408 | if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_FEATURE, | 408 | if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_FEATURE, |
409 | port ? USB_RT_PORT : USB_RECIP_DEVICE, | 409 | port ? USB_RT_PORT : USB_RECIP_DEVICE, |
410 | port ? USB_PORT_FEAT_TEST : USB_FEAT_TEST, | 410 | port ? USB_PORT_FEAT_TEST : USB_FEAT_TEST, |
411 | (mode << 8) | port, | 411 | (mode << 8) | port, |
412 | NULL, 0, USB_CNTL_TIMEOUT) == -1) { | 412 | NULL, 0, USB_CNTL_TIMEOUT) == -1) { |
413 | printf("Error during SET_FEATURE.\n"); | 413 | printf("Error during SET_FEATURE.\n"); |
414 | return 1; | 414 | return 1; |
415 | } else { | 415 | } else { |
416 | printf("Test mode successfully set. Use 'usb start' " | 416 | printf("Test mode successfully set. Use 'usb start' " |
417 | "to return to normal operation.\n"); | 417 | "to return to normal operation.\n"); |
418 | return 0; | 418 | return 0; |
419 | } | 419 | } |
420 | } | 420 | } |
421 | 421 | ||
422 | 422 | ||
423 | /****************************************************************************** | 423 | /****************************************************************************** |
424 | * usb boot command intepreter. Derived from diskboot | 424 | * usb boot command intepreter. Derived from diskboot |
425 | */ | 425 | */ |
426 | #ifdef CONFIG_USB_STORAGE | 426 | #ifdef CONFIG_USB_STORAGE |
427 | static int do_usbboot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | 427 | static int do_usbboot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
428 | { | 428 | { |
429 | return common_diskboot(cmdtp, "usb", argc, argv); | 429 | return common_diskboot(cmdtp, "usb", argc, argv); |
430 | } | 430 | } |
431 | #endif /* CONFIG_USB_STORAGE */ | 431 | #endif /* CONFIG_USB_STORAGE */ |
432 | 432 | ||
433 | static int do_usb_stop_keyboard(int force) | ||
434 | { | ||
435 | #ifdef CONFIG_USB_KEYBOARD | ||
436 | if (usb_kbd_deregister(force) != 0) { | ||
437 | printf("USB not stopped: usbkbd still using USB\n"); | ||
438 | return 1; | ||
439 | } | ||
440 | #endif | ||
441 | return 0; | ||
442 | } | ||
433 | 443 | ||
434 | /****************************************************************************** | 444 | /****************************************************************************** |
435 | * usb command intepreter | 445 | * usb command intepreter |
436 | */ | 446 | */ |
437 | static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | 447 | static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
438 | { | 448 | { |
439 | 449 | ||
440 | int i; | 450 | int i; |
441 | struct usb_device *dev = NULL; | 451 | struct usb_device *dev = NULL; |
442 | extern char usb_started; | 452 | extern char usb_started; |
443 | #ifdef CONFIG_USB_STORAGE | 453 | #ifdef CONFIG_USB_STORAGE |
444 | block_dev_desc_t *stor_dev; | 454 | block_dev_desc_t *stor_dev; |
445 | #endif | 455 | #endif |
446 | 456 | ||
447 | if (argc < 2) | 457 | if (argc < 2) |
448 | return CMD_RET_USAGE; | 458 | return CMD_RET_USAGE; |
449 | 459 | ||
450 | if ((strncmp(argv[1], "reset", 5) == 0) || | 460 | if ((strncmp(argv[1], "reset", 5) == 0) || |
451 | (strncmp(argv[1], "start", 5) == 0)) { | 461 | (strncmp(argv[1], "start", 5) == 0)) { |
452 | bootstage_mark_name(BOOTSTAGE_ID_USB_START, "usb_start"); | 462 | bootstage_mark_name(BOOTSTAGE_ID_USB_START, "usb_start"); |
463 | if (do_usb_stop_keyboard(1) != 0) | ||
464 | return 1; | ||
453 | usb_stop(); | 465 | usb_stop(); |
454 | printf("(Re)start USB...\n"); | 466 | printf("(Re)start USB...\n"); |
455 | if (usb_init() >= 0) { | 467 | if (usb_init() >= 0) { |
456 | #ifdef CONFIG_USB_STORAGE | 468 | #ifdef CONFIG_USB_STORAGE |
457 | /* try to recognize storage devices immediately */ | 469 | /* try to recognize storage devices immediately */ |
458 | usb_stor_curr_dev = usb_stor_scan(1); | 470 | usb_stor_curr_dev = usb_stor_scan(1); |
459 | #endif | 471 | #endif |
460 | #ifdef CONFIG_USB_HOST_ETHER | 472 | #ifdef CONFIG_USB_HOST_ETHER |
461 | /* try to recognize ethernet devices immediately */ | 473 | /* try to recognize ethernet devices immediately */ |
462 | usb_ether_curr_dev = usb_host_eth_scan(1); | 474 | usb_ether_curr_dev = usb_host_eth_scan(1); |
463 | #endif | 475 | #endif |
464 | #ifdef CONFIG_USB_KEYBOARD | 476 | #ifdef CONFIG_USB_KEYBOARD |
465 | drv_usb_kbd_init(); | 477 | drv_usb_kbd_init(); |
466 | #endif | 478 | #endif |
467 | } | 479 | } |
468 | return 0; | 480 | return 0; |
469 | } | 481 | } |
470 | if (strncmp(argv[1], "stop", 4) == 0) { | 482 | if (strncmp(argv[1], "stop", 4) == 0) { |
471 | #ifdef CONFIG_USB_KEYBOARD | 483 | if (argc != 2) |
472 | if (argc == 2) { | ||
473 | if (usb_kbd_deregister() != 0) { | ||
474 | printf("USB not stopped: usbkbd still" | ||
475 | " using USB\n"); | ||
476 | return 1; | ||
477 | } | ||
478 | } else { | ||
479 | /* forced stop, switch console in to serial */ | ||
480 | console_assign(stdin, "serial"); | 484 | console_assign(stdin, "serial"); |
481 | usb_kbd_deregister(); | 485 | if (do_usb_stop_keyboard(0) != 0) |
482 | } | 486 | return 1; |
483 | #endif | ||
484 | printf("stopping USB..\n"); | 487 | printf("stopping USB..\n"); |
485 | usb_stop(); | 488 | usb_stop(); |
486 | return 0; | 489 | return 0; |
487 | } | 490 | } |
488 | if (!usb_started) { | 491 | if (!usb_started) { |
489 | printf("USB is stopped. Please issue 'usb start' first.\n"); | 492 | printf("USB is stopped. Please issue 'usb start' first.\n"); |
490 | return 1; | 493 | return 1; |
491 | } | 494 | } |
492 | if (strncmp(argv[1], "tree", 4) == 0) { | 495 | if (strncmp(argv[1], "tree", 4) == 0) { |
493 | puts("USB device tree:\n"); | 496 | puts("USB device tree:\n"); |
494 | for (i = 0; i < USB_MAX_DEVICE; i++) { | 497 | for (i = 0; i < USB_MAX_DEVICE; i++) { |
495 | dev = usb_get_dev_index(i); | 498 | dev = usb_get_dev_index(i); |
496 | if (dev == NULL) | 499 | if (dev == NULL) |
497 | break; | 500 | break; |
498 | if (dev->parent == NULL) | 501 | if (dev->parent == NULL) |
499 | usb_show_tree(dev); | 502 | usb_show_tree(dev); |
500 | } | 503 | } |
501 | return 0; | 504 | return 0; |
502 | } | 505 | } |
503 | if (strncmp(argv[1], "inf", 3) == 0) { | 506 | if (strncmp(argv[1], "inf", 3) == 0) { |
504 | int d; | 507 | int d; |
505 | if (argc == 2) { | 508 | if (argc == 2) { |
506 | for (d = 0; d < USB_MAX_DEVICE; d++) { | 509 | for (d = 0; d < USB_MAX_DEVICE; d++) { |
507 | dev = usb_get_dev_index(d); | 510 | dev = usb_get_dev_index(d); |
508 | if (dev == NULL) | 511 | if (dev == NULL) |
509 | break; | 512 | break; |
510 | usb_display_desc(dev); | 513 | usb_display_desc(dev); |
511 | usb_display_config(dev); | 514 | usb_display_config(dev); |
512 | } | 515 | } |
513 | return 0; | 516 | return 0; |
514 | } else { | 517 | } else { |
515 | i = simple_strtoul(argv[2], NULL, 10); | 518 | i = simple_strtoul(argv[2], NULL, 10); |
516 | printf("config for device %d\n", i); | 519 | printf("config for device %d\n", i); |
517 | dev = usb_find_device(i); | 520 | dev = usb_find_device(i); |
518 | if (dev == NULL) { | 521 | if (dev == NULL) { |
519 | printf("*** No device available ***\n"); | 522 | printf("*** No device available ***\n"); |
520 | return 0; | 523 | return 0; |
521 | } else { | 524 | } else { |
522 | usb_display_desc(dev); | 525 | usb_display_desc(dev); |
523 | usb_display_config(dev); | 526 | usb_display_config(dev); |
524 | } | 527 | } |
525 | } | 528 | } |
526 | return 0; | 529 | return 0; |
527 | } | 530 | } |
528 | if (strncmp(argv[1], "test", 4) == 0) { | 531 | if (strncmp(argv[1], "test", 4) == 0) { |
529 | if (argc < 5) | 532 | if (argc < 5) |
530 | return CMD_RET_USAGE; | 533 | return CMD_RET_USAGE; |
531 | i = simple_strtoul(argv[2], NULL, 10); | 534 | i = simple_strtoul(argv[2], NULL, 10); |
532 | dev = usb_find_device(i); | 535 | dev = usb_find_device(i); |
533 | if (dev == NULL) { | 536 | if (dev == NULL) { |
534 | printf("Device %d does not exist.\n", i); | 537 | printf("Device %d does not exist.\n", i); |
535 | return 1; | 538 | return 1; |
536 | } | 539 | } |
537 | i = simple_strtoul(argv[3], NULL, 10); | 540 | i = simple_strtoul(argv[3], NULL, 10); |
538 | return usb_test(dev, i, argv[4]); | 541 | return usb_test(dev, i, argv[4]); |
539 | } | 542 | } |
540 | #ifdef CONFIG_USB_STORAGE | 543 | #ifdef CONFIG_USB_STORAGE |
541 | if (strncmp(argv[1], "stor", 4) == 0) | 544 | if (strncmp(argv[1], "stor", 4) == 0) |
542 | return usb_stor_info(); | 545 | return usb_stor_info(); |
543 | 546 | ||
544 | if (strncmp(argv[1], "part", 4) == 0) { | 547 | if (strncmp(argv[1], "part", 4) == 0) { |
545 | int devno, ok = 0; | 548 | int devno, ok = 0; |
546 | if (argc == 2) { | 549 | if (argc == 2) { |
547 | for (devno = 0; ; ++devno) { | 550 | for (devno = 0; ; ++devno) { |
548 | stor_dev = usb_stor_get_dev(devno); | 551 | stor_dev = usb_stor_get_dev(devno); |
549 | if (stor_dev == NULL) | 552 | if (stor_dev == NULL) |
550 | break; | 553 | break; |
551 | if (stor_dev->type != DEV_TYPE_UNKNOWN) { | 554 | if (stor_dev->type != DEV_TYPE_UNKNOWN) { |
552 | ok++; | 555 | ok++; |
553 | if (devno) | 556 | if (devno) |
554 | printf("\n"); | 557 | printf("\n"); |
555 | debug("print_part of %x\n", devno); | 558 | debug("print_part of %x\n", devno); |
556 | print_part(stor_dev); | 559 | print_part(stor_dev); |
557 | } | 560 | } |
558 | } | 561 | } |
559 | } else { | 562 | } else { |
560 | devno = simple_strtoul(argv[2], NULL, 16); | 563 | devno = simple_strtoul(argv[2], NULL, 16); |
561 | stor_dev = usb_stor_get_dev(devno); | 564 | stor_dev = usb_stor_get_dev(devno); |
562 | if (stor_dev != NULL && | 565 | if (stor_dev != NULL && |
563 | stor_dev->type != DEV_TYPE_UNKNOWN) { | 566 | stor_dev->type != DEV_TYPE_UNKNOWN) { |
564 | ok++; | 567 | ok++; |
565 | debug("print_part of %x\n", devno); | 568 | debug("print_part of %x\n", devno); |
566 | print_part(stor_dev); | 569 | print_part(stor_dev); |
567 | } | 570 | } |
568 | } | 571 | } |
569 | if (!ok) { | 572 | if (!ok) { |
570 | printf("\nno USB devices available\n"); | 573 | printf("\nno USB devices available\n"); |
571 | return 1; | 574 | return 1; |
572 | } | 575 | } |
573 | return 0; | 576 | return 0; |
574 | } | 577 | } |
575 | if (strcmp(argv[1], "read") == 0) { | 578 | if (strcmp(argv[1], "read") == 0) { |
576 | if (usb_stor_curr_dev < 0) { | 579 | if (usb_stor_curr_dev < 0) { |
577 | printf("no current device selected\n"); | 580 | printf("no current device selected\n"); |
578 | return 1; | 581 | return 1; |
579 | } | 582 | } |
580 | if (argc == 5) { | 583 | if (argc == 5) { |
581 | unsigned long addr = simple_strtoul(argv[2], NULL, 16); | 584 | unsigned long addr = simple_strtoul(argv[2], NULL, 16); |
582 | unsigned long blk = simple_strtoul(argv[3], NULL, 16); | 585 | unsigned long blk = simple_strtoul(argv[3], NULL, 16); |
583 | unsigned long cnt = simple_strtoul(argv[4], NULL, 16); | 586 | unsigned long cnt = simple_strtoul(argv[4], NULL, 16); |
584 | unsigned long n; | 587 | unsigned long n; |
585 | printf("\nUSB read: device %d block # %ld, count %ld" | 588 | printf("\nUSB read: device %d block # %ld, count %ld" |
586 | " ... ", usb_stor_curr_dev, blk, cnt); | 589 | " ... ", usb_stor_curr_dev, blk, cnt); |
587 | stor_dev = usb_stor_get_dev(usb_stor_curr_dev); | 590 | stor_dev = usb_stor_get_dev(usb_stor_curr_dev); |
588 | n = stor_dev->block_read(usb_stor_curr_dev, blk, cnt, | 591 | n = stor_dev->block_read(usb_stor_curr_dev, blk, cnt, |
589 | (ulong *)addr); | 592 | (ulong *)addr); |
590 | printf("%ld blocks read: %s\n", n, | 593 | printf("%ld blocks read: %s\n", n, |
591 | (n == cnt) ? "OK" : "ERROR"); | 594 | (n == cnt) ? "OK" : "ERROR"); |
592 | if (n == cnt) | 595 | if (n == cnt) |
593 | return 0; | 596 | return 0; |
594 | return 1; | 597 | return 1; |
595 | } | 598 | } |
596 | } | 599 | } |
597 | if (strcmp(argv[1], "write") == 0) { | 600 | if (strcmp(argv[1], "write") == 0) { |
598 | if (usb_stor_curr_dev < 0) { | 601 | if (usb_stor_curr_dev < 0) { |
599 | printf("no current device selected\n"); | 602 | printf("no current device selected\n"); |
600 | return 1; | 603 | return 1; |
601 | } | 604 | } |
602 | if (argc == 5) { | 605 | if (argc == 5) { |
603 | unsigned long addr = simple_strtoul(argv[2], NULL, 16); | 606 | unsigned long addr = simple_strtoul(argv[2], NULL, 16); |
604 | unsigned long blk = simple_strtoul(argv[3], NULL, 16); | 607 | unsigned long blk = simple_strtoul(argv[3], NULL, 16); |
605 | unsigned long cnt = simple_strtoul(argv[4], NULL, 16); | 608 | unsigned long cnt = simple_strtoul(argv[4], NULL, 16); |
606 | unsigned long n; | 609 | unsigned long n; |
607 | printf("\nUSB write: device %d block # %ld, count %ld" | 610 | printf("\nUSB write: device %d block # %ld, count %ld" |
608 | " ... ", usb_stor_curr_dev, blk, cnt); | 611 | " ... ", usb_stor_curr_dev, blk, cnt); |
609 | stor_dev = usb_stor_get_dev(usb_stor_curr_dev); | 612 | stor_dev = usb_stor_get_dev(usb_stor_curr_dev); |
610 | n = stor_dev->block_write(usb_stor_curr_dev, blk, cnt, | 613 | n = stor_dev->block_write(usb_stor_curr_dev, blk, cnt, |
611 | (ulong *)addr); | 614 | (ulong *)addr); |
612 | printf("%ld blocks write: %s\n", n, | 615 | printf("%ld blocks write: %s\n", n, |
613 | (n == cnt) ? "OK" : "ERROR"); | 616 | (n == cnt) ? "OK" : "ERROR"); |
614 | if (n == cnt) | 617 | if (n == cnt) |
615 | return 0; | 618 | return 0; |
616 | return 1; | 619 | return 1; |
617 | } | 620 | } |
618 | } | 621 | } |
619 | if (strncmp(argv[1], "dev", 3) == 0) { | 622 | if (strncmp(argv[1], "dev", 3) == 0) { |
620 | if (argc == 3) { | 623 | if (argc == 3) { |
621 | int dev = (int)simple_strtoul(argv[2], NULL, 10); | 624 | int dev = (int)simple_strtoul(argv[2], NULL, 10); |
622 | printf("\nUSB device %d: ", dev); | 625 | printf("\nUSB device %d: ", dev); |
623 | stor_dev = usb_stor_get_dev(dev); | 626 | stor_dev = usb_stor_get_dev(dev); |
624 | if (stor_dev == NULL) { | 627 | if (stor_dev == NULL) { |
625 | printf("unknown device\n"); | 628 | printf("unknown device\n"); |
626 | return 1; | 629 | return 1; |
627 | } | 630 | } |
628 | printf("\n Device %d: ", dev); | 631 | printf("\n Device %d: ", dev); |
629 | dev_print(stor_dev); | 632 | dev_print(stor_dev); |
630 | if (stor_dev->type == DEV_TYPE_UNKNOWN) | 633 | if (stor_dev->type == DEV_TYPE_UNKNOWN) |
631 | return 1; | 634 | return 1; |
632 | usb_stor_curr_dev = dev; | 635 | usb_stor_curr_dev = dev; |
633 | printf("... is now current device\n"); | 636 | printf("... is now current device\n"); |
634 | return 0; | 637 | return 0; |
635 | } else { | 638 | } else { |
636 | printf("\nUSB device %d: ", usb_stor_curr_dev); | 639 | printf("\nUSB device %d: ", usb_stor_curr_dev); |
637 | stor_dev = usb_stor_get_dev(usb_stor_curr_dev); | 640 | stor_dev = usb_stor_get_dev(usb_stor_curr_dev); |
638 | dev_print(stor_dev); | 641 | dev_print(stor_dev); |
639 | if (stor_dev->type == DEV_TYPE_UNKNOWN) | 642 | if (stor_dev->type == DEV_TYPE_UNKNOWN) |
640 | return 1; | 643 | return 1; |
641 | return 0; | 644 | return 0; |
642 | } | 645 | } |
643 | return 0; | 646 | return 0; |
644 | } | 647 | } |
645 | #endif /* CONFIG_USB_STORAGE */ | 648 | #endif /* CONFIG_USB_STORAGE */ |
646 | return CMD_RET_USAGE; | 649 | return CMD_RET_USAGE; |
647 | } | 650 | } |
648 | 651 | ||
649 | U_BOOT_CMD( | 652 | U_BOOT_CMD( |
650 | usb, 5, 1, do_usb, | 653 | usb, 5, 1, do_usb, |
651 | "USB sub-system", | 654 | "USB sub-system", |
652 | "start - start (scan) USB controller\n" | 655 | "start - start (scan) USB controller\n" |
653 | "usb reset - reset (rescan) USB controller\n" | 656 | "usb reset - reset (rescan) USB controller\n" |
654 | "usb stop [f] - stop USB [f]=force stop\n" | 657 | "usb stop [f] - stop USB [f]=force stop\n" |
655 | "usb tree - show USB device tree\n" | 658 | "usb tree - show USB device tree\n" |
656 | "usb info [dev] - show available USB devices\n" | 659 | "usb info [dev] - show available USB devices\n" |
657 | "usb test [dev] [port] [mode] - set USB 2.0 test mode\n" | 660 | "usb test [dev] [port] [mode] - set USB 2.0 test mode\n" |
658 | " (specify port 0 to indicate the device's upstream port)\n" | 661 | " (specify port 0 to indicate the device's upstream port)\n" |
659 | " Available modes: J, K, S[E0_NAK], P[acket], F[orce_Enable]\n" | 662 | " Available modes: J, K, S[E0_NAK], P[acket], F[orce_Enable]\n" |
660 | #ifdef CONFIG_USB_STORAGE | 663 | #ifdef CONFIG_USB_STORAGE |
661 | "usb storage - show details of USB storage devices\n" | 664 | "usb storage - show details of USB storage devices\n" |
662 | "usb dev [dev] - show or set current USB storage device\n" | 665 | "usb dev [dev] - show or set current USB storage device\n" |
663 | "usb part [dev] - print partition table of one or all USB storage" | 666 | "usb part [dev] - print partition table of one or all USB storage" |
664 | " devices\n" | 667 | " devices\n" |
665 | "usb read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n" | 668 | "usb read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n" |
666 | " to memory address `addr'\n" | 669 | " to memory address `addr'\n" |
667 | "usb write addr blk# cnt - write `cnt' blocks starting at block `blk#'\n" | 670 | "usb write addr blk# cnt - write `cnt' blocks starting at block `blk#'\n" |
668 | " from memory address `addr'" | 671 | " from memory address `addr'" |
669 | #endif /* CONFIG_USB_STORAGE */ | 672 | #endif /* CONFIG_USB_STORAGE */ |
670 | ); | 673 | ); |
671 | 674 |
common/stdio.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2009 Sergey Kubushyn <ksi@koi8.net> | 2 | * Copyright (C) 2009 Sergey Kubushyn <ksi@koi8.net> |
3 | * | 3 | * |
4 | * Changes for multibus/multiadapter I2C support. | 4 | * Changes for multibus/multiadapter I2C support. |
5 | * | 5 | * |
6 | * (C) Copyright 2000 | 6 | * (C) Copyright 2000 |
7 | * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it | 7 | * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it |
8 | * | 8 | * |
9 | * SPDX-License-Identifier: GPL-2.0+ | 9 | * SPDX-License-Identifier: GPL-2.0+ |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <config.h> | 12 | #include <config.h> |
13 | #include <common.h> | 13 | #include <common.h> |
14 | #include <errno.h> | 14 | #include <errno.h> |
15 | #include <stdarg.h> | 15 | #include <stdarg.h> |
16 | #include <malloc.h> | 16 | #include <malloc.h> |
17 | #include <stdio_dev.h> | 17 | #include <stdio_dev.h> |
18 | #include <serial.h> | 18 | #include <serial.h> |
19 | #ifdef CONFIG_LOGBUFFER | 19 | #ifdef CONFIG_LOGBUFFER |
20 | #include <logbuff.h> | 20 | #include <logbuff.h> |
21 | #endif | 21 | #endif |
22 | 22 | ||
23 | #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C) | 23 | #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C) |
24 | #include <i2c.h> | 24 | #include <i2c.h> |
25 | #endif | 25 | #endif |
26 | 26 | ||
27 | DECLARE_GLOBAL_DATA_PTR; | 27 | DECLARE_GLOBAL_DATA_PTR; |
28 | 28 | ||
29 | static struct stdio_dev devs; | 29 | static struct stdio_dev devs; |
30 | struct stdio_dev *stdio_devices[] = { NULL, NULL, NULL }; | 30 | struct stdio_dev *stdio_devices[] = { NULL, NULL, NULL }; |
31 | char *stdio_names[MAX_FILES] = { "stdin", "stdout", "stderr" }; | 31 | char *stdio_names[MAX_FILES] = { "stdin", "stdout", "stderr" }; |
32 | 32 | ||
33 | #if defined(CONFIG_SPLASH_SCREEN) && !defined(CONFIG_SYS_DEVICE_NULLDEV) | 33 | #if defined(CONFIG_SPLASH_SCREEN) && !defined(CONFIG_SYS_DEVICE_NULLDEV) |
34 | #define CONFIG_SYS_DEVICE_NULLDEV 1 | 34 | #define CONFIG_SYS_DEVICE_NULLDEV 1 |
35 | #endif | 35 | #endif |
36 | 36 | ||
37 | #ifdef CONFIG_SYS_STDIO_DEREGISTER | ||
38 | #define CONFIG_SYS_DEVICE_NULLDEV 1 | ||
39 | #endif | ||
37 | 40 | ||
38 | #ifdef CONFIG_SYS_DEVICE_NULLDEV | 41 | #ifdef CONFIG_SYS_DEVICE_NULLDEV |
39 | void nulldev_putc(struct stdio_dev *dev, const char c) | 42 | void nulldev_putc(struct stdio_dev *dev, const char c) |
40 | { | 43 | { |
41 | /* nulldev is empty! */ | 44 | /* nulldev is empty! */ |
42 | } | 45 | } |
43 | 46 | ||
44 | void nulldev_puts(struct stdio_dev *dev, const char *s) | 47 | void nulldev_puts(struct stdio_dev *dev, const char *s) |
45 | { | 48 | { |
46 | /* nulldev is empty! */ | 49 | /* nulldev is empty! */ |
47 | } | 50 | } |
48 | 51 | ||
49 | int nulldev_input(struct stdio_dev *dev) | 52 | int nulldev_input(struct stdio_dev *dev) |
50 | { | 53 | { |
51 | /* nulldev is empty! */ | 54 | /* nulldev is empty! */ |
52 | return 0; | 55 | return 0; |
53 | } | 56 | } |
54 | #endif | 57 | #endif |
55 | 58 | ||
56 | void stdio_serial_putc(struct stdio_dev *dev, const char c) | 59 | void stdio_serial_putc(struct stdio_dev *dev, const char c) |
57 | { | 60 | { |
58 | serial_putc(c); | 61 | serial_putc(c); |
59 | } | 62 | } |
60 | 63 | ||
61 | void stdio_serial_puts(struct stdio_dev *dev, const char *s) | 64 | void stdio_serial_puts(struct stdio_dev *dev, const char *s) |
62 | { | 65 | { |
63 | serial_puts(s); | 66 | serial_puts(s); |
64 | } | 67 | } |
65 | 68 | ||
66 | int stdio_serial_getc(struct stdio_dev *dev) | 69 | int stdio_serial_getc(struct stdio_dev *dev) |
67 | { | 70 | { |
68 | return serial_getc(); | 71 | return serial_getc(); |
69 | } | 72 | } |
70 | 73 | ||
71 | int stdio_serial_tstc(struct stdio_dev *dev) | 74 | int stdio_serial_tstc(struct stdio_dev *dev) |
72 | { | 75 | { |
73 | return serial_tstc(); | 76 | return serial_tstc(); |
74 | } | 77 | } |
75 | 78 | ||
76 | /************************************************************************** | 79 | /************************************************************************** |
77 | * SYSTEM DRIVERS | 80 | * SYSTEM DRIVERS |
78 | ************************************************************************** | 81 | ************************************************************************** |
79 | */ | 82 | */ |
80 | 83 | ||
81 | static void drv_system_init (void) | 84 | static void drv_system_init (void) |
82 | { | 85 | { |
83 | struct stdio_dev dev; | 86 | struct stdio_dev dev; |
84 | 87 | ||
85 | memset (&dev, 0, sizeof (dev)); | 88 | memset (&dev, 0, sizeof (dev)); |
86 | 89 | ||
87 | strcpy (dev.name, "serial"); | 90 | strcpy (dev.name, "serial"); |
88 | dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; | 91 | dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; |
89 | dev.putc = stdio_serial_putc; | 92 | dev.putc = stdio_serial_putc; |
90 | dev.puts = stdio_serial_puts; | 93 | dev.puts = stdio_serial_puts; |
91 | dev.getc = stdio_serial_getc; | 94 | dev.getc = stdio_serial_getc; |
92 | dev.tstc = stdio_serial_tstc; | 95 | dev.tstc = stdio_serial_tstc; |
93 | stdio_register (&dev); | 96 | stdio_register (&dev); |
94 | 97 | ||
95 | #ifdef CONFIG_SYS_DEVICE_NULLDEV | 98 | #ifdef CONFIG_SYS_DEVICE_NULLDEV |
96 | memset (&dev, 0, sizeof (dev)); | 99 | memset (&dev, 0, sizeof (dev)); |
97 | 100 | ||
98 | strcpy (dev.name, "nulldev"); | 101 | strcpy (dev.name, "nulldev"); |
99 | dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; | 102 | dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; |
100 | dev.putc = nulldev_putc; | 103 | dev.putc = nulldev_putc; |
101 | dev.puts = nulldev_puts; | 104 | dev.puts = nulldev_puts; |
102 | dev.getc = nulldev_input; | 105 | dev.getc = nulldev_input; |
103 | dev.tstc = nulldev_input; | 106 | dev.tstc = nulldev_input; |
104 | 107 | ||
105 | stdio_register (&dev); | 108 | stdio_register (&dev); |
106 | #endif | 109 | #endif |
107 | } | 110 | } |
108 | 111 | ||
109 | /************************************************************************** | 112 | /************************************************************************** |
110 | * DEVICES | 113 | * DEVICES |
111 | ************************************************************************** | 114 | ************************************************************************** |
112 | */ | 115 | */ |
113 | struct list_head* stdio_get_list(void) | 116 | struct list_head* stdio_get_list(void) |
114 | { | 117 | { |
115 | return &(devs.list); | 118 | return &(devs.list); |
116 | } | 119 | } |
117 | 120 | ||
118 | struct stdio_dev* stdio_get_by_name(const char *name) | 121 | struct stdio_dev* stdio_get_by_name(const char *name) |
119 | { | 122 | { |
120 | struct list_head *pos; | 123 | struct list_head *pos; |
121 | struct stdio_dev *dev; | 124 | struct stdio_dev *dev; |
122 | 125 | ||
123 | if(!name) | 126 | if(!name) |
124 | return NULL; | 127 | return NULL; |
125 | 128 | ||
126 | list_for_each(pos, &(devs.list)) { | 129 | list_for_each(pos, &(devs.list)) { |
127 | dev = list_entry(pos, struct stdio_dev, list); | 130 | dev = list_entry(pos, struct stdio_dev, list); |
128 | if(strcmp(dev->name, name) == 0) | 131 | if(strcmp(dev->name, name) == 0) |
129 | return dev; | 132 | return dev; |
130 | } | 133 | } |
131 | 134 | ||
132 | return NULL; | 135 | return NULL; |
133 | } | 136 | } |
134 | 137 | ||
135 | struct stdio_dev* stdio_clone(struct stdio_dev *dev) | 138 | struct stdio_dev* stdio_clone(struct stdio_dev *dev) |
136 | { | 139 | { |
137 | struct stdio_dev *_dev; | 140 | struct stdio_dev *_dev; |
138 | 141 | ||
139 | if(!dev) | 142 | if(!dev) |
140 | return NULL; | 143 | return NULL; |
141 | 144 | ||
142 | _dev = calloc(1, sizeof(struct stdio_dev)); | 145 | _dev = calloc(1, sizeof(struct stdio_dev)); |
143 | 146 | ||
144 | if(!_dev) | 147 | if(!_dev) |
145 | return NULL; | 148 | return NULL; |
146 | 149 | ||
147 | memcpy(_dev, dev, sizeof(struct stdio_dev)); | 150 | memcpy(_dev, dev, sizeof(struct stdio_dev)); |
148 | 151 | ||
149 | return _dev; | 152 | return _dev; |
150 | } | 153 | } |
151 | 154 | ||
152 | int stdio_register_dev(struct stdio_dev *dev, struct stdio_dev **devp) | 155 | int stdio_register_dev(struct stdio_dev *dev, struct stdio_dev **devp) |
153 | { | 156 | { |
154 | struct stdio_dev *_dev; | 157 | struct stdio_dev *_dev; |
155 | 158 | ||
156 | _dev = stdio_clone(dev); | 159 | _dev = stdio_clone(dev); |
157 | if(!_dev) | 160 | if(!_dev) |
158 | return -ENODEV; | 161 | return -ENODEV; |
159 | list_add_tail(&(_dev->list), &(devs.list)); | 162 | list_add_tail(&(_dev->list), &(devs.list)); |
160 | if (devp) | 163 | if (devp) |
161 | *devp = _dev; | 164 | *devp = _dev; |
162 | 165 | ||
163 | return 0; | 166 | return 0; |
164 | } | 167 | } |
165 | 168 | ||
166 | int stdio_register(struct stdio_dev *dev) | 169 | int stdio_register(struct stdio_dev *dev) |
167 | { | 170 | { |
168 | return stdio_register_dev(dev, NULL); | 171 | return stdio_register_dev(dev, NULL); |
169 | } | 172 | } |
170 | 173 | ||
171 | /* deregister the device "devname". | 174 | /* deregister the device "devname". |
172 | * returns 0 if success, -1 if device is assigned and 1 if devname not found | 175 | * returns 0 if success, -1 if device is assigned and 1 if devname not found |
173 | */ | 176 | */ |
174 | #ifdef CONFIG_SYS_STDIO_DEREGISTER | 177 | #ifdef CONFIG_SYS_STDIO_DEREGISTER |
175 | int stdio_deregister_dev(struct stdio_dev *dev) | 178 | int stdio_deregister_dev(struct stdio_dev *dev, int force) |
176 | { | 179 | { |
177 | int l; | 180 | int l; |
178 | struct list_head *pos; | 181 | struct list_head *pos; |
179 | char temp_names[3][16]; | 182 | char temp_names[3][16]; |
180 | 183 | ||
181 | /* get stdio devices (ListRemoveItem changes the dev list) */ | 184 | /* get stdio devices (ListRemoveItem changes the dev list) */ |
182 | for (l=0 ; l< MAX_FILES; l++) { | 185 | for (l=0 ; l< MAX_FILES; l++) { |
183 | if (stdio_devices[l] == dev) { | 186 | if (stdio_devices[l] == dev) { |
187 | if (force) { | ||
188 | strcpy(temp_names[l], "nulldev"); | ||
189 | continue; | ||
190 | } | ||
184 | /* Device is assigned -> report error */ | 191 | /* Device is assigned -> report error */ |
185 | return -1; | 192 | return -1; |
186 | } | 193 | } |
187 | memcpy (&temp_names[l][0], | 194 | memcpy (&temp_names[l][0], |
188 | stdio_devices[l]->name, | 195 | stdio_devices[l]->name, |
189 | sizeof(temp_names[l])); | 196 | sizeof(temp_names[l])); |
190 | } | 197 | } |
191 | 198 | ||
192 | list_del(&(dev->list)); | 199 | list_del(&(dev->list)); |
193 | 200 | ||
194 | /* reassign Device list */ | 201 | /* reassign Device list */ |
195 | list_for_each(pos, &(devs.list)) { | 202 | list_for_each(pos, &(devs.list)) { |
196 | dev = list_entry(pos, struct stdio_dev, list); | 203 | dev = list_entry(pos, struct stdio_dev, list); |
197 | for (l=0 ; l< MAX_FILES; l++) { | 204 | for (l=0 ; l< MAX_FILES; l++) { |
198 | if(strcmp(dev->name, temp_names[l]) == 0) | 205 | if(strcmp(dev->name, temp_names[l]) == 0) |
199 | stdio_devices[l] = dev; | 206 | stdio_devices[l] = dev; |
200 | } | 207 | } |
201 | } | 208 | } |
202 | return 0; | 209 | return 0; |
203 | } | 210 | } |
204 | 211 | ||
205 | int stdio_deregister(const char *devname) | 212 | int stdio_deregister(const char *devname, int force) |
206 | { | 213 | { |
207 | struct stdio_dev *dev; | 214 | struct stdio_dev *dev; |
208 | 215 | ||
209 | dev = stdio_get_by_name(devname); | 216 | dev = stdio_get_by_name(devname); |
210 | 217 | ||
211 | if (!dev) /* device not found */ | 218 | if (!dev) /* device not found */ |
212 | return -ENODEV; | 219 | return -ENODEV; |
213 | 220 | ||
214 | return stdio_deregister_dev(dev); | 221 | return stdio_deregister_dev(dev, force); |
215 | } | 222 | } |
216 | #endif /* CONFIG_SYS_STDIO_DEREGISTER */ | 223 | #endif /* CONFIG_SYS_STDIO_DEREGISTER */ |
217 | 224 | ||
218 | int stdio_init_tables(void) | 225 | int stdio_init_tables(void) |
219 | { | 226 | { |
220 | #if defined(CONFIG_NEEDS_MANUAL_RELOC) | 227 | #if defined(CONFIG_NEEDS_MANUAL_RELOC) |
221 | /* already relocated for current ARM implementation */ | 228 | /* already relocated for current ARM implementation */ |
222 | ulong relocation_offset = gd->reloc_off; | 229 | ulong relocation_offset = gd->reloc_off; |
223 | int i; | 230 | int i; |
224 | 231 | ||
225 | /* relocate device name pointers */ | 232 | /* relocate device name pointers */ |
226 | for (i = 0; i < (sizeof (stdio_names) / sizeof (char *)); ++i) { | 233 | for (i = 0; i < (sizeof (stdio_names) / sizeof (char *)); ++i) { |
227 | stdio_names[i] = (char *) (((ulong) stdio_names[i]) + | 234 | stdio_names[i] = (char *) (((ulong) stdio_names[i]) + |
228 | relocation_offset); | 235 | relocation_offset); |
229 | } | 236 | } |
230 | #endif /* CONFIG_NEEDS_MANUAL_RELOC */ | 237 | #endif /* CONFIG_NEEDS_MANUAL_RELOC */ |
231 | 238 | ||
232 | /* Initialize the list */ | 239 | /* Initialize the list */ |
233 | INIT_LIST_HEAD(&(devs.list)); | 240 | INIT_LIST_HEAD(&(devs.list)); |
234 | 241 | ||
235 | return 0; | 242 | return 0; |
236 | } | 243 | } |
237 | 244 | ||
238 | int stdio_add_devices(void) | 245 | int stdio_add_devices(void) |
239 | { | 246 | { |
240 | #ifdef CONFIG_SYS_I2C | 247 | #ifdef CONFIG_SYS_I2C |
241 | i2c_init_all(); | 248 | i2c_init_all(); |
242 | #else | 249 | #else |
243 | #if defined(CONFIG_HARD_I2C) | 250 | #if defined(CONFIG_HARD_I2C) |
244 | i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); | 251 | i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); |
245 | #endif | 252 | #endif |
246 | #endif | 253 | #endif |
247 | #ifdef CONFIG_LCD | 254 | #ifdef CONFIG_LCD |
248 | drv_lcd_init (); | 255 | drv_lcd_init (); |
249 | #endif | 256 | #endif |
250 | #if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE) | 257 | #if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE) |
251 | drv_video_init (); | 258 | drv_video_init (); |
252 | #endif | 259 | #endif |
253 | #ifdef CONFIG_KEYBOARD | 260 | #ifdef CONFIG_KEYBOARD |
254 | drv_keyboard_init (); | 261 | drv_keyboard_init (); |
255 | #endif | 262 | #endif |
256 | #ifdef CONFIG_LOGBUFFER | 263 | #ifdef CONFIG_LOGBUFFER |
257 | drv_logbuff_init (); | 264 | drv_logbuff_init (); |
258 | #endif | 265 | #endif |
259 | drv_system_init (); | 266 | drv_system_init (); |
260 | serial_stdio_init (); | 267 | serial_stdio_init (); |
261 | #ifdef CONFIG_USB_TTY | 268 | #ifdef CONFIG_USB_TTY |
262 | drv_usbtty_init (); | 269 | drv_usbtty_init (); |
263 | #endif | 270 | #endif |
264 | #ifdef CONFIG_NETCONSOLE | 271 | #ifdef CONFIG_NETCONSOLE |
265 | drv_nc_init (); | 272 | drv_nc_init (); |
266 | #endif | 273 | #endif |
267 | #ifdef CONFIG_JTAG_CONSOLE | 274 | #ifdef CONFIG_JTAG_CONSOLE |
268 | drv_jtag_console_init (); | 275 | drv_jtag_console_init (); |
269 | #endif | 276 | #endif |
270 | #ifdef CONFIG_CBMEM_CONSOLE | 277 | #ifdef CONFIG_CBMEM_CONSOLE |
271 | cbmemc_init(); | 278 | cbmemc_init(); |
272 | #endif | 279 | #endif |
273 | 280 | ||
274 | return 0; | 281 | return 0; |
275 | } | 282 | } |
276 | 283 | ||
277 | int stdio_init(void) | 284 | int stdio_init(void) |
278 | { | 285 | { |
279 | stdio_init_tables(); | 286 | stdio_init_tables(); |
280 | stdio_add_devices(); | 287 | stdio_add_devices(); |
281 | 288 | ||
282 | return 0; | 289 | return 0; |
283 | } | 290 | } |
284 | 291 |
common/usb_kbd.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2001 | 2 | * (C) Copyright 2001 |
3 | * Denis Peter, MPL AG Switzerland | 3 | * Denis Peter, MPL AG Switzerland |
4 | * | 4 | * |
5 | * Part of this source has been derived from the Linux USB | 5 | * Part of this source has been derived from the Linux USB |
6 | * project. | 6 | * project. |
7 | * | 7 | * |
8 | * SPDX-License-Identifier: GPL-2.0+ | 8 | * SPDX-License-Identifier: GPL-2.0+ |
9 | */ | 9 | */ |
10 | #include <common.h> | 10 | #include <common.h> |
11 | #include <errno.h> | ||
11 | #include <malloc.h> | 12 | #include <malloc.h> |
12 | #include <stdio_dev.h> | 13 | #include <stdio_dev.h> |
13 | #include <asm/byteorder.h> | 14 | #include <asm/byteorder.h> |
14 | 15 | ||
15 | #include <usb.h> | 16 | #include <usb.h> |
16 | 17 | ||
17 | /* | 18 | /* |
18 | * If overwrite_console returns 1, the stdin, stderr and stdout | 19 | * If overwrite_console returns 1, the stdin, stderr and stdout |
19 | * are switched to the serial port, else the settings in the | 20 | * are switched to the serial port, else the settings in the |
20 | * environment are used | 21 | * environment are used |
21 | */ | 22 | */ |
22 | #ifdef CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE | 23 | #ifdef CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE |
23 | extern int overwrite_console(void); | 24 | extern int overwrite_console(void); |
24 | #else | 25 | #else |
25 | int overwrite_console(void) | 26 | int overwrite_console(void) |
26 | { | 27 | { |
27 | return 0; | 28 | return 0; |
28 | } | 29 | } |
29 | #endif | 30 | #endif |
30 | 31 | ||
31 | /* Keyboard sampling rate */ | 32 | /* Keyboard sampling rate */ |
32 | #define REPEAT_RATE (40 / 4) /* 40msec -> 25cps */ | 33 | #define REPEAT_RATE (40 / 4) /* 40msec -> 25cps */ |
33 | #define REPEAT_DELAY 10 /* 10 x REPEAT_RATE = 400msec */ | 34 | #define REPEAT_DELAY 10 /* 10 x REPEAT_RATE = 400msec */ |
34 | 35 | ||
35 | #define NUM_LOCK 0x53 | 36 | #define NUM_LOCK 0x53 |
36 | #define CAPS_LOCK 0x39 | 37 | #define CAPS_LOCK 0x39 |
37 | #define SCROLL_LOCK 0x47 | 38 | #define SCROLL_LOCK 0x47 |
38 | 39 | ||
39 | /* Modifier bits */ | 40 | /* Modifier bits */ |
40 | #define LEFT_CNTR (1 << 0) | 41 | #define LEFT_CNTR (1 << 0) |
41 | #define LEFT_SHIFT (1 << 1) | 42 | #define LEFT_SHIFT (1 << 1) |
42 | #define LEFT_ALT (1 << 2) | 43 | #define LEFT_ALT (1 << 2) |
43 | #define LEFT_GUI (1 << 3) | 44 | #define LEFT_GUI (1 << 3) |
44 | #define RIGHT_CNTR (1 << 4) | 45 | #define RIGHT_CNTR (1 << 4) |
45 | #define RIGHT_SHIFT (1 << 5) | 46 | #define RIGHT_SHIFT (1 << 5) |
46 | #define RIGHT_ALT (1 << 6) | 47 | #define RIGHT_ALT (1 << 6) |
47 | #define RIGHT_GUI (1 << 7) | 48 | #define RIGHT_GUI (1 << 7) |
48 | 49 | ||
49 | /* Size of the keyboard buffer */ | 50 | /* Size of the keyboard buffer */ |
50 | #define USB_KBD_BUFFER_LEN 0x20 | 51 | #define USB_KBD_BUFFER_LEN 0x20 |
51 | 52 | ||
52 | /* Device name */ | 53 | /* Device name */ |
53 | #define DEVNAME "usbkbd" | 54 | #define DEVNAME "usbkbd" |
54 | 55 | ||
55 | /* Keyboard maps */ | 56 | /* Keyboard maps */ |
56 | static const unsigned char usb_kbd_numkey[] = { | 57 | static const unsigned char usb_kbd_numkey[] = { |
57 | '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', | 58 | '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', |
58 | '\r', 0x1b, '\b', '\t', ' ', '-', '=', '[', ']', | 59 | '\r', 0x1b, '\b', '\t', ' ', '-', '=', '[', ']', |
59 | '\\', '#', ';', '\'', '`', ',', '.', '/' | 60 | '\\', '#', ';', '\'', '`', ',', '.', '/' |
60 | }; | 61 | }; |
61 | static const unsigned char usb_kbd_numkey_shifted[] = { | 62 | static const unsigned char usb_kbd_numkey_shifted[] = { |
62 | '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', | 63 | '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', |
63 | '\r', 0x1b, '\b', '\t', ' ', '_', '+', '{', '}', | 64 | '\r', 0x1b, '\b', '\t', ' ', '_', '+', '{', '}', |
64 | '|', '~', ':', '"', '~', '<', '>', '?' | 65 | '|', '~', ':', '"', '~', '<', '>', '?' |
65 | }; | 66 | }; |
66 | 67 | ||
67 | static const unsigned char usb_kbd_num_keypad[] = { | 68 | static const unsigned char usb_kbd_num_keypad[] = { |
68 | '/', '*', '-', '+', '\r', | 69 | '/', '*', '-', '+', '\r', |
69 | '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', | 70 | '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', |
70 | '.', 0, 0, 0, '=' | 71 | '.', 0, 0, 0, '=' |
71 | }; | 72 | }; |
72 | 73 | ||
73 | /* | 74 | /* |
74 | * map arrow keys to ^F/^B ^N/^P, can't really use the proper | 75 | * map arrow keys to ^F/^B ^N/^P, can't really use the proper |
75 | * ANSI sequence for arrow keys because the queuing code breaks | 76 | * ANSI sequence for arrow keys because the queuing code breaks |
76 | * when a single keypress expands to 3 queue elements | 77 | * when a single keypress expands to 3 queue elements |
77 | */ | 78 | */ |
78 | static const unsigned char usb_kbd_arrow[] = { | 79 | static const unsigned char usb_kbd_arrow[] = { |
79 | 0x6, 0x2, 0xe, 0x10 | 80 | 0x6, 0x2, 0xe, 0x10 |
80 | }; | 81 | }; |
81 | 82 | ||
82 | /* | 83 | /* |
83 | * NOTE: It's important for the NUM, CAPS, SCROLL-lock bits to be in this | 84 | * NOTE: It's important for the NUM, CAPS, SCROLL-lock bits to be in this |
84 | * order. See usb_kbd_setled() function! | 85 | * order. See usb_kbd_setled() function! |
85 | */ | 86 | */ |
86 | #define USB_KBD_NUMLOCK (1 << 0) | 87 | #define USB_KBD_NUMLOCK (1 << 0) |
87 | #define USB_KBD_CAPSLOCK (1 << 1) | 88 | #define USB_KBD_CAPSLOCK (1 << 1) |
88 | #define USB_KBD_SCROLLLOCK (1 << 2) | 89 | #define USB_KBD_SCROLLLOCK (1 << 2) |
89 | #define USB_KBD_CTRL (1 << 3) | 90 | #define USB_KBD_CTRL (1 << 3) |
90 | 91 | ||
91 | #define USB_KBD_LEDMASK \ | 92 | #define USB_KBD_LEDMASK \ |
92 | (USB_KBD_NUMLOCK | USB_KBD_CAPSLOCK | USB_KBD_SCROLLLOCK) | 93 | (USB_KBD_NUMLOCK | USB_KBD_CAPSLOCK | USB_KBD_SCROLLLOCK) |
93 | 94 | ||
94 | /* | 95 | /* |
95 | * USB Keyboard reports are 8 bytes in boot protocol. | 96 | * USB Keyboard reports are 8 bytes in boot protocol. |
96 | * Appendix B of HID Device Class Definition 1.11 | 97 | * Appendix B of HID Device Class Definition 1.11 |
97 | */ | 98 | */ |
98 | #define USB_KBD_BOOT_REPORT_SIZE 8 | 99 | #define USB_KBD_BOOT_REPORT_SIZE 8 |
99 | 100 | ||
100 | struct usb_kbd_pdata { | 101 | struct usb_kbd_pdata { |
101 | uint32_t repeat_delay; | 102 | uint32_t repeat_delay; |
102 | 103 | ||
103 | uint32_t usb_in_pointer; | 104 | uint32_t usb_in_pointer; |
104 | uint32_t usb_out_pointer; | 105 | uint32_t usb_out_pointer; |
105 | uint8_t usb_kbd_buffer[USB_KBD_BUFFER_LEN]; | 106 | uint8_t usb_kbd_buffer[USB_KBD_BUFFER_LEN]; |
106 | 107 | ||
107 | uint8_t *new; | 108 | uint8_t *new; |
108 | uint8_t old[USB_KBD_BOOT_REPORT_SIZE]; | 109 | uint8_t old[USB_KBD_BOOT_REPORT_SIZE]; |
109 | 110 | ||
110 | uint8_t flags; | 111 | uint8_t flags; |
111 | }; | 112 | }; |
112 | 113 | ||
113 | extern int __maybe_unused net_busy_flag; | 114 | extern int __maybe_unused net_busy_flag; |
114 | 115 | ||
115 | /* The period of time between two calls of usb_kbd_testc(). */ | 116 | /* The period of time between two calls of usb_kbd_testc(). */ |
116 | static unsigned long __maybe_unused kbd_testc_tms; | 117 | static unsigned long __maybe_unused kbd_testc_tms; |
117 | 118 | ||
118 | /* Generic keyboard event polling. */ | 119 | /* Generic keyboard event polling. */ |
119 | void usb_kbd_generic_poll(void) | 120 | void usb_kbd_generic_poll(void) |
120 | { | 121 | { |
121 | struct stdio_dev *dev; | 122 | struct stdio_dev *dev; |
122 | struct usb_device *usb_kbd_dev; | 123 | struct usb_device *usb_kbd_dev; |
123 | struct usb_kbd_pdata *data; | 124 | struct usb_kbd_pdata *data; |
124 | struct usb_interface *iface; | 125 | struct usb_interface *iface; |
125 | struct usb_endpoint_descriptor *ep; | 126 | struct usb_endpoint_descriptor *ep; |
126 | int pipe; | 127 | int pipe; |
127 | int maxp; | 128 | int maxp; |
128 | 129 | ||
129 | /* Get the pointer to USB Keyboard device pointer */ | 130 | /* Get the pointer to USB Keyboard device pointer */ |
130 | dev = stdio_get_by_name(DEVNAME); | 131 | dev = stdio_get_by_name(DEVNAME); |
131 | usb_kbd_dev = (struct usb_device *)dev->priv; | 132 | usb_kbd_dev = (struct usb_device *)dev->priv; |
132 | data = usb_kbd_dev->privptr; | 133 | data = usb_kbd_dev->privptr; |
133 | iface = &usb_kbd_dev->config.if_desc[0]; | 134 | iface = &usb_kbd_dev->config.if_desc[0]; |
134 | ep = &iface->ep_desc[0]; | 135 | ep = &iface->ep_desc[0]; |
135 | pipe = usb_rcvintpipe(usb_kbd_dev, ep->bEndpointAddress); | 136 | pipe = usb_rcvintpipe(usb_kbd_dev, ep->bEndpointAddress); |
136 | 137 | ||
137 | /* Submit a interrupt transfer request */ | 138 | /* Submit a interrupt transfer request */ |
138 | maxp = usb_maxpacket(usb_kbd_dev, pipe); | 139 | maxp = usb_maxpacket(usb_kbd_dev, pipe); |
139 | usb_submit_int_msg(usb_kbd_dev, pipe, data->new, | 140 | usb_submit_int_msg(usb_kbd_dev, pipe, data->new, |
140 | min(maxp, USB_KBD_BOOT_REPORT_SIZE), | 141 | min(maxp, USB_KBD_BOOT_REPORT_SIZE), |
141 | ep->bInterval); | 142 | ep->bInterval); |
142 | } | 143 | } |
143 | 144 | ||
144 | /* Puts character in the queue and sets up the in and out pointer. */ | 145 | /* Puts character in the queue and sets up the in and out pointer. */ |
145 | static void usb_kbd_put_queue(struct usb_kbd_pdata *data, char c) | 146 | static void usb_kbd_put_queue(struct usb_kbd_pdata *data, char c) |
146 | { | 147 | { |
147 | if (data->usb_in_pointer == USB_KBD_BUFFER_LEN - 1) { | 148 | if (data->usb_in_pointer == USB_KBD_BUFFER_LEN - 1) { |
148 | /* Check for buffer full. */ | 149 | /* Check for buffer full. */ |
149 | if (data->usb_out_pointer == 0) | 150 | if (data->usb_out_pointer == 0) |
150 | return; | 151 | return; |
151 | 152 | ||
152 | data->usb_in_pointer = 0; | 153 | data->usb_in_pointer = 0; |
153 | } else { | 154 | } else { |
154 | /* Check for buffer full. */ | 155 | /* Check for buffer full. */ |
155 | if (data->usb_in_pointer == data->usb_out_pointer - 1) | 156 | if (data->usb_in_pointer == data->usb_out_pointer - 1) |
156 | return; | 157 | return; |
157 | 158 | ||
158 | data->usb_in_pointer++; | 159 | data->usb_in_pointer++; |
159 | } | 160 | } |
160 | 161 | ||
161 | data->usb_kbd_buffer[data->usb_in_pointer] = c; | 162 | data->usb_kbd_buffer[data->usb_in_pointer] = c; |
162 | } | 163 | } |
163 | 164 | ||
164 | /* | 165 | /* |
165 | * Set the LEDs. Since this is used in the irq routine, the control job is | 166 | * Set the LEDs. Since this is used in the irq routine, the control job is |
166 | * issued with a timeout of 0. This means, that the job is queued without | 167 | * issued with a timeout of 0. This means, that the job is queued without |
167 | * waiting for job completion. | 168 | * waiting for job completion. |
168 | */ | 169 | */ |
169 | static void usb_kbd_setled(struct usb_device *dev) | 170 | static void usb_kbd_setled(struct usb_device *dev) |
170 | { | 171 | { |
171 | struct usb_interface *iface = &dev->config.if_desc[0]; | 172 | struct usb_interface *iface = &dev->config.if_desc[0]; |
172 | struct usb_kbd_pdata *data = dev->privptr; | 173 | struct usb_kbd_pdata *data = dev->privptr; |
173 | uint32_t leds = data->flags & USB_KBD_LEDMASK; | 174 | ALLOC_ALIGN_BUFFER(uint32_t, leds, 1, USB_DMA_MINALIGN); |
174 | 175 | ||
176 | *leds = data->flags & USB_KBD_LEDMASK; | ||
175 | usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 177 | usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
176 | USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, | 178 | USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, |
177 | 0x200, iface->desc.bInterfaceNumber, (void *)&leds, 1, 0); | 179 | 0x200, iface->desc.bInterfaceNumber, leds, 1, 0); |
178 | } | 180 | } |
179 | 181 | ||
180 | #define CAPITAL_MASK 0x20 | 182 | #define CAPITAL_MASK 0x20 |
181 | /* Translate the scancode in ASCII */ | 183 | /* Translate the scancode in ASCII */ |
182 | static int usb_kbd_translate(struct usb_kbd_pdata *data, unsigned char scancode, | 184 | static int usb_kbd_translate(struct usb_kbd_pdata *data, unsigned char scancode, |
183 | unsigned char modifier, int pressed) | 185 | unsigned char modifier, int pressed) |
184 | { | 186 | { |
185 | uint8_t keycode = 0; | 187 | uint8_t keycode = 0; |
186 | 188 | ||
187 | /* Key released */ | 189 | /* Key released */ |
188 | if (pressed == 0) { | 190 | if (pressed == 0) { |
189 | data->repeat_delay = 0; | 191 | data->repeat_delay = 0; |
190 | return 0; | 192 | return 0; |
191 | } | 193 | } |
192 | 194 | ||
193 | if (pressed == 2) { | 195 | if (pressed == 2) { |
194 | data->repeat_delay++; | 196 | data->repeat_delay++; |
195 | if (data->repeat_delay < REPEAT_DELAY) | 197 | if (data->repeat_delay < REPEAT_DELAY) |
196 | return 0; | 198 | return 0; |
197 | 199 | ||
198 | data->repeat_delay = REPEAT_DELAY; | 200 | data->repeat_delay = REPEAT_DELAY; |
199 | } | 201 | } |
200 | 202 | ||
201 | /* Alphanumeric values */ | 203 | /* Alphanumeric values */ |
202 | if ((scancode > 3) && (scancode <= 0x1d)) { | 204 | if ((scancode > 3) && (scancode <= 0x1d)) { |
203 | keycode = scancode - 4 + 'a'; | 205 | keycode = scancode - 4 + 'a'; |
204 | 206 | ||
205 | if (data->flags & USB_KBD_CAPSLOCK) | 207 | if (data->flags & USB_KBD_CAPSLOCK) |
206 | keycode &= ~CAPITAL_MASK; | 208 | keycode &= ~CAPITAL_MASK; |
207 | 209 | ||
208 | if (modifier & (LEFT_SHIFT | RIGHT_SHIFT)) { | 210 | if (modifier & (LEFT_SHIFT | RIGHT_SHIFT)) { |
209 | /* Handle CAPSLock + Shift pressed simultaneously */ | 211 | /* Handle CAPSLock + Shift pressed simultaneously */ |
210 | if (keycode & CAPITAL_MASK) | 212 | if (keycode & CAPITAL_MASK) |
211 | keycode &= ~CAPITAL_MASK; | 213 | keycode &= ~CAPITAL_MASK; |
212 | else | 214 | else |
213 | keycode |= CAPITAL_MASK; | 215 | keycode |= CAPITAL_MASK; |
214 | } | 216 | } |
215 | } | 217 | } |
216 | 218 | ||
217 | if ((scancode > 0x1d) && (scancode < 0x3a)) { | 219 | if ((scancode > 0x1d) && (scancode < 0x3a)) { |
218 | /* Shift pressed */ | 220 | /* Shift pressed */ |
219 | if (modifier & (LEFT_SHIFT | RIGHT_SHIFT)) | 221 | if (modifier & (LEFT_SHIFT | RIGHT_SHIFT)) |
220 | keycode = usb_kbd_numkey_shifted[scancode - 0x1e]; | 222 | keycode = usb_kbd_numkey_shifted[scancode - 0x1e]; |
221 | else | 223 | else |
222 | keycode = usb_kbd_numkey[scancode - 0x1e]; | 224 | keycode = usb_kbd_numkey[scancode - 0x1e]; |
223 | } | 225 | } |
224 | 226 | ||
225 | /* Arrow keys */ | 227 | /* Arrow keys */ |
226 | if ((scancode >= 0x4f) && (scancode <= 0x52)) | 228 | if ((scancode >= 0x4f) && (scancode <= 0x52)) |
227 | keycode = usb_kbd_arrow[scancode - 0x4f]; | 229 | keycode = usb_kbd_arrow[scancode - 0x4f]; |
228 | 230 | ||
229 | /* Numeric keypad */ | 231 | /* Numeric keypad */ |
230 | if ((scancode >= 0x54) && (scancode <= 0x67)) | 232 | if ((scancode >= 0x54) && (scancode <= 0x67)) |
231 | keycode = usb_kbd_num_keypad[scancode - 0x54]; | 233 | keycode = usb_kbd_num_keypad[scancode - 0x54]; |
232 | 234 | ||
233 | if (data->flags & USB_KBD_CTRL) | 235 | if (data->flags & USB_KBD_CTRL) |
234 | keycode = scancode - 0x3; | 236 | keycode = scancode - 0x3; |
235 | 237 | ||
236 | if (pressed == 1) { | 238 | if (pressed == 1) { |
237 | if (scancode == NUM_LOCK) { | 239 | if (scancode == NUM_LOCK) { |
238 | data->flags ^= USB_KBD_NUMLOCK; | 240 | data->flags ^= USB_KBD_NUMLOCK; |
239 | return 1; | 241 | return 1; |
240 | } | 242 | } |
241 | 243 | ||
242 | if (scancode == CAPS_LOCK) { | 244 | if (scancode == CAPS_LOCK) { |
243 | data->flags ^= USB_KBD_CAPSLOCK; | 245 | data->flags ^= USB_KBD_CAPSLOCK; |
244 | return 1; | 246 | return 1; |
245 | } | 247 | } |
246 | if (scancode == SCROLL_LOCK) { | 248 | if (scancode == SCROLL_LOCK) { |
247 | data->flags ^= USB_KBD_SCROLLLOCK; | 249 | data->flags ^= USB_KBD_SCROLLLOCK; |
248 | return 1; | 250 | return 1; |
249 | } | 251 | } |
250 | } | 252 | } |
251 | 253 | ||
252 | /* Report keycode if any */ | 254 | /* Report keycode if any */ |
253 | if (keycode) { | 255 | if (keycode) { |
254 | debug("%c", keycode); | 256 | debug("%c", keycode); |
255 | usb_kbd_put_queue(data, keycode); | 257 | usb_kbd_put_queue(data, keycode); |
256 | } | 258 | } |
257 | 259 | ||
258 | return 0; | 260 | return 0; |
259 | } | 261 | } |
260 | 262 | ||
261 | static uint32_t usb_kbd_service_key(struct usb_device *dev, int i, int up) | 263 | static uint32_t usb_kbd_service_key(struct usb_device *dev, int i, int up) |
262 | { | 264 | { |
263 | uint32_t res = 0; | 265 | uint32_t res = 0; |
264 | struct usb_kbd_pdata *data = dev->privptr; | 266 | struct usb_kbd_pdata *data = dev->privptr; |
265 | uint8_t *new; | 267 | uint8_t *new; |
266 | uint8_t *old; | 268 | uint8_t *old; |
267 | 269 | ||
268 | if (up) { | 270 | if (up) { |
269 | new = data->old; | 271 | new = data->old; |
270 | old = data->new; | 272 | old = data->new; |
271 | } else { | 273 | } else { |
272 | new = data->new; | 274 | new = data->new; |
273 | old = data->old; | 275 | old = data->old; |
274 | } | 276 | } |
275 | 277 | ||
276 | if ((old[i] > 3) && | 278 | if ((old[i] > 3) && |
277 | (memscan(new + 2, old[i], USB_KBD_BOOT_REPORT_SIZE - 2) == | 279 | (memscan(new + 2, old[i], USB_KBD_BOOT_REPORT_SIZE - 2) == |
278 | new + USB_KBD_BOOT_REPORT_SIZE)) { | 280 | new + USB_KBD_BOOT_REPORT_SIZE)) { |
279 | res |= usb_kbd_translate(data, old[i], data->new[0], up); | 281 | res |= usb_kbd_translate(data, old[i], data->new[0], up); |
280 | } | 282 | } |
281 | 283 | ||
282 | return res; | 284 | return res; |
283 | } | 285 | } |
284 | 286 | ||
285 | /* Interrupt service routine */ | 287 | /* Interrupt service routine */ |
286 | static int usb_kbd_irq_worker(struct usb_device *dev) | 288 | static int usb_kbd_irq_worker(struct usb_device *dev) |
287 | { | 289 | { |
288 | struct usb_kbd_pdata *data = dev->privptr; | 290 | struct usb_kbd_pdata *data = dev->privptr; |
289 | int i, res = 0; | 291 | int i, res = 0; |
290 | 292 | ||
291 | /* No combo key pressed */ | 293 | /* No combo key pressed */ |
292 | if (data->new[0] == 0x00) | 294 | if (data->new[0] == 0x00) |
293 | data->flags &= ~USB_KBD_CTRL; | 295 | data->flags &= ~USB_KBD_CTRL; |
294 | /* Left or Right Ctrl pressed */ | 296 | /* Left or Right Ctrl pressed */ |
295 | else if ((data->new[0] == LEFT_CNTR) || (data->new[0] == RIGHT_CNTR)) | 297 | else if ((data->new[0] == LEFT_CNTR) || (data->new[0] == RIGHT_CNTR)) |
296 | data->flags |= USB_KBD_CTRL; | 298 | data->flags |= USB_KBD_CTRL; |
297 | 299 | ||
298 | for (i = 2; i < USB_KBD_BOOT_REPORT_SIZE; i++) { | 300 | for (i = 2; i < USB_KBD_BOOT_REPORT_SIZE; i++) { |
299 | res |= usb_kbd_service_key(dev, i, 0); | 301 | res |= usb_kbd_service_key(dev, i, 0); |
300 | res |= usb_kbd_service_key(dev, i, 1); | 302 | res |= usb_kbd_service_key(dev, i, 1); |
301 | } | 303 | } |
302 | 304 | ||
303 | /* Key is still pressed */ | 305 | /* Key is still pressed */ |
304 | if ((data->new[2] > 3) && (data->old[2] == data->new[2])) | 306 | if ((data->new[2] > 3) && (data->old[2] == data->new[2])) |
305 | res |= usb_kbd_translate(data, data->new[2], data->new[0], 2); | 307 | res |= usb_kbd_translate(data, data->new[2], data->new[0], 2); |
306 | 308 | ||
307 | if (res == 1) | 309 | if (res == 1) |
308 | usb_kbd_setled(dev); | 310 | usb_kbd_setled(dev); |
309 | 311 | ||
310 | memcpy(data->old, data->new, USB_KBD_BOOT_REPORT_SIZE); | 312 | memcpy(data->old, data->new, USB_KBD_BOOT_REPORT_SIZE); |
311 | 313 | ||
312 | return 1; | 314 | return 1; |
313 | } | 315 | } |
314 | 316 | ||
315 | /* Keyboard interrupt handler */ | 317 | /* Keyboard interrupt handler */ |
316 | static int usb_kbd_irq(struct usb_device *dev) | 318 | static int usb_kbd_irq(struct usb_device *dev) |
317 | { | 319 | { |
318 | if ((dev->irq_status != 0) || | 320 | if ((dev->irq_status != 0) || |
319 | (dev->irq_act_len != USB_KBD_BOOT_REPORT_SIZE)) { | 321 | (dev->irq_act_len != USB_KBD_BOOT_REPORT_SIZE)) { |
320 | debug("USB KBD: Error %lX, len %d\n", | 322 | debug("USB KBD: Error %lX, len %d\n", |
321 | dev->irq_status, dev->irq_act_len); | 323 | dev->irq_status, dev->irq_act_len); |
322 | return 1; | 324 | return 1; |
323 | } | 325 | } |
324 | 326 | ||
325 | return usb_kbd_irq_worker(dev); | 327 | return usb_kbd_irq_worker(dev); |
326 | } | 328 | } |
327 | 329 | ||
328 | /* Interrupt polling */ | 330 | /* Interrupt polling */ |
329 | static inline void usb_kbd_poll_for_event(struct usb_device *dev) | 331 | static inline void usb_kbd_poll_for_event(struct usb_device *dev) |
330 | { | 332 | { |
331 | #if defined(CONFIG_SYS_USB_EVENT_POLL) | 333 | #if defined(CONFIG_SYS_USB_EVENT_POLL) |
332 | struct usb_interface *iface; | 334 | struct usb_interface *iface; |
333 | struct usb_endpoint_descriptor *ep; | 335 | struct usb_endpoint_descriptor *ep; |
334 | struct usb_kbd_pdata *data; | 336 | struct usb_kbd_pdata *data; |
335 | int pipe; | 337 | int pipe; |
336 | int maxp; | 338 | int maxp; |
337 | 339 | ||
338 | /* Get the pointer to USB Keyboard device pointer */ | 340 | /* Get the pointer to USB Keyboard device pointer */ |
339 | data = dev->privptr; | 341 | data = dev->privptr; |
340 | iface = &dev->config.if_desc[0]; | 342 | iface = &dev->config.if_desc[0]; |
341 | ep = &iface->ep_desc[0]; | 343 | ep = &iface->ep_desc[0]; |
342 | pipe = usb_rcvintpipe(dev, ep->bEndpointAddress); | 344 | pipe = usb_rcvintpipe(dev, ep->bEndpointAddress); |
343 | 345 | ||
344 | /* Submit a interrupt transfer request */ | 346 | /* Submit a interrupt transfer request */ |
345 | maxp = usb_maxpacket(dev, pipe); | 347 | maxp = usb_maxpacket(dev, pipe); |
346 | usb_submit_int_msg(dev, pipe, &data->new[0], | 348 | usb_submit_int_msg(dev, pipe, &data->new[0], |
347 | min(maxp, USB_KBD_BOOT_REPORT_SIZE), | 349 | min(maxp, USB_KBD_BOOT_REPORT_SIZE), |
348 | ep->bInterval); | 350 | ep->bInterval); |
349 | 351 | ||
350 | usb_kbd_irq_worker(dev); | 352 | usb_kbd_irq_worker(dev); |
351 | #elif defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) | 353 | #elif defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) |
352 | struct usb_interface *iface; | 354 | struct usb_interface *iface; |
353 | struct usb_kbd_pdata *data = dev->privptr; | 355 | struct usb_kbd_pdata *data = dev->privptr; |
354 | iface = &dev->config.if_desc[0]; | 356 | iface = &dev->config.if_desc[0]; |
355 | usb_get_report(dev, iface->desc.bInterfaceNumber, | 357 | usb_get_report(dev, iface->desc.bInterfaceNumber, |
356 | 1, 0, data->new, USB_KBD_BOOT_REPORT_SIZE); | 358 | 1, 0, data->new, USB_KBD_BOOT_REPORT_SIZE); |
357 | if (memcmp(data->old, data->new, USB_KBD_BOOT_REPORT_SIZE)) | 359 | if (memcmp(data->old, data->new, USB_KBD_BOOT_REPORT_SIZE)) |
358 | usb_kbd_irq_worker(dev); | 360 | usb_kbd_irq_worker(dev); |
359 | #endif | 361 | #endif |
360 | } | 362 | } |
361 | 363 | ||
362 | /* test if a character is in the queue */ | 364 | /* test if a character is in the queue */ |
363 | static int usb_kbd_testc(struct stdio_dev *sdev) | 365 | static int usb_kbd_testc(struct stdio_dev *sdev) |
364 | { | 366 | { |
365 | struct stdio_dev *dev; | 367 | struct stdio_dev *dev; |
366 | struct usb_device *usb_kbd_dev; | 368 | struct usb_device *usb_kbd_dev; |
367 | struct usb_kbd_pdata *data; | 369 | struct usb_kbd_pdata *data; |
368 | 370 | ||
369 | #ifdef CONFIG_CMD_NET | 371 | #ifdef CONFIG_CMD_NET |
370 | /* | 372 | /* |
371 | * If net_busy_flag is 1, NET transfer is running, | 373 | * If net_busy_flag is 1, NET transfer is running, |
372 | * then we check key-pressed every second (first check may be | 374 | * then we check key-pressed every second (first check may be |
373 | * less than 1 second) to improve TFTP booting performance. | 375 | * less than 1 second) to improve TFTP booting performance. |
374 | */ | 376 | */ |
375 | if (net_busy_flag && (get_timer(kbd_testc_tms) < CONFIG_SYS_HZ)) | 377 | if (net_busy_flag && (get_timer(kbd_testc_tms) < CONFIG_SYS_HZ)) |
376 | return 0; | 378 | return 0; |
377 | kbd_testc_tms = get_timer(0); | 379 | kbd_testc_tms = get_timer(0); |
378 | #endif | 380 | #endif |
379 | dev = stdio_get_by_name(DEVNAME); | 381 | dev = stdio_get_by_name(DEVNAME); |
380 | usb_kbd_dev = (struct usb_device *)dev->priv; | 382 | usb_kbd_dev = (struct usb_device *)dev->priv; |
381 | data = usb_kbd_dev->privptr; | 383 | data = usb_kbd_dev->privptr; |
382 | 384 | ||
383 | usb_kbd_poll_for_event(usb_kbd_dev); | 385 | usb_kbd_poll_for_event(usb_kbd_dev); |
384 | 386 | ||
385 | return !(data->usb_in_pointer == data->usb_out_pointer); | 387 | return !(data->usb_in_pointer == data->usb_out_pointer); |
386 | } | 388 | } |
387 | 389 | ||
388 | /* gets the character from the queue */ | 390 | /* gets the character from the queue */ |
389 | static int usb_kbd_getc(struct stdio_dev *sdev) | 391 | static int usb_kbd_getc(struct stdio_dev *sdev) |
390 | { | 392 | { |
391 | struct stdio_dev *dev; | 393 | struct stdio_dev *dev; |
392 | struct usb_device *usb_kbd_dev; | 394 | struct usb_device *usb_kbd_dev; |
393 | struct usb_kbd_pdata *data; | 395 | struct usb_kbd_pdata *data; |
394 | 396 | ||
395 | dev = stdio_get_by_name(DEVNAME); | 397 | dev = stdio_get_by_name(DEVNAME); |
396 | usb_kbd_dev = (struct usb_device *)dev->priv; | 398 | usb_kbd_dev = (struct usb_device *)dev->priv; |
397 | data = usb_kbd_dev->privptr; | 399 | data = usb_kbd_dev->privptr; |
398 | 400 | ||
399 | while (data->usb_in_pointer == data->usb_out_pointer) | 401 | while (data->usb_in_pointer == data->usb_out_pointer) |
400 | usb_kbd_poll_for_event(usb_kbd_dev); | 402 | usb_kbd_poll_for_event(usb_kbd_dev); |
401 | 403 | ||
402 | if (data->usb_out_pointer == USB_KBD_BUFFER_LEN - 1) | 404 | if (data->usb_out_pointer == USB_KBD_BUFFER_LEN - 1) |
403 | data->usb_out_pointer = 0; | 405 | data->usb_out_pointer = 0; |
404 | else | 406 | else |
405 | data->usb_out_pointer++; | 407 | data->usb_out_pointer++; |
406 | 408 | ||
407 | return data->usb_kbd_buffer[data->usb_out_pointer]; | 409 | return data->usb_kbd_buffer[data->usb_out_pointer]; |
408 | } | 410 | } |
409 | 411 | ||
410 | /* probes the USB device dev for keyboard type. */ | 412 | /* probes the USB device dev for keyboard type. */ |
411 | static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum) | 413 | static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum) |
412 | { | 414 | { |
413 | struct usb_interface *iface; | 415 | struct usb_interface *iface; |
414 | struct usb_endpoint_descriptor *ep; | 416 | struct usb_endpoint_descriptor *ep; |
415 | struct usb_kbd_pdata *data; | 417 | struct usb_kbd_pdata *data; |
416 | int pipe, maxp; | 418 | int pipe, maxp; |
417 | 419 | ||
418 | if (dev->descriptor.bNumConfigurations != 1) | 420 | if (dev->descriptor.bNumConfigurations != 1) |
419 | return 0; | 421 | return 0; |
420 | 422 | ||
421 | iface = &dev->config.if_desc[ifnum]; | 423 | iface = &dev->config.if_desc[ifnum]; |
422 | 424 | ||
423 | if (iface->desc.bInterfaceClass != 3) | 425 | if (iface->desc.bInterfaceClass != 3) |
424 | return 0; | 426 | return 0; |
425 | 427 | ||
426 | if (iface->desc.bInterfaceSubClass != 1) | 428 | if (iface->desc.bInterfaceSubClass != 1) |
427 | return 0; | 429 | return 0; |
428 | 430 | ||
429 | if (iface->desc.bInterfaceProtocol != 1) | 431 | if (iface->desc.bInterfaceProtocol != 1) |
430 | return 0; | 432 | return 0; |
431 | 433 | ||
432 | if (iface->desc.bNumEndpoints != 1) | 434 | if (iface->desc.bNumEndpoints != 1) |
433 | return 0; | 435 | return 0; |
434 | 436 | ||
435 | ep = &iface->ep_desc[0]; | 437 | ep = &iface->ep_desc[0]; |
436 | 438 | ||
437 | /* Check if endpoint 1 is interrupt endpoint */ | 439 | /* Check if endpoint 1 is interrupt endpoint */ |
438 | if (!(ep->bEndpointAddress & 0x80)) | 440 | if (!(ep->bEndpointAddress & 0x80)) |
439 | return 0; | 441 | return 0; |
440 | 442 | ||
441 | if ((ep->bmAttributes & 3) != 3) | 443 | if ((ep->bmAttributes & 3) != 3) |
442 | return 0; | 444 | return 0; |
443 | 445 | ||
444 | debug("USB KBD: found set protocol...\n"); | 446 | debug("USB KBD: found set protocol...\n"); |
445 | 447 | ||
446 | data = malloc(sizeof(struct usb_kbd_pdata)); | 448 | data = malloc(sizeof(struct usb_kbd_pdata)); |
447 | if (!data) { | 449 | if (!data) { |
448 | printf("USB KBD: Error allocating private data\n"); | 450 | printf("USB KBD: Error allocating private data\n"); |
449 | return 0; | 451 | return 0; |
450 | } | 452 | } |
451 | 453 | ||
452 | /* Clear private data */ | 454 | /* Clear private data */ |
453 | memset(data, 0, sizeof(struct usb_kbd_pdata)); | 455 | memset(data, 0, sizeof(struct usb_kbd_pdata)); |
454 | 456 | ||
455 | /* allocate input buffer aligned and sized to USB DMA alignment */ | 457 | /* allocate input buffer aligned and sized to USB DMA alignment */ |
456 | data->new = memalign(USB_DMA_MINALIGN, | 458 | data->new = memalign(USB_DMA_MINALIGN, |
457 | roundup(USB_KBD_BOOT_REPORT_SIZE, USB_DMA_MINALIGN)); | 459 | roundup(USB_KBD_BOOT_REPORT_SIZE, USB_DMA_MINALIGN)); |
458 | 460 | ||
459 | /* Insert private data into USB device structure */ | 461 | /* Insert private data into USB device structure */ |
460 | dev->privptr = data; | 462 | dev->privptr = data; |
461 | 463 | ||
462 | /* Set IRQ handler */ | 464 | /* Set IRQ handler */ |
463 | dev->irq_handle = usb_kbd_irq; | 465 | dev->irq_handle = usb_kbd_irq; |
464 | 466 | ||
465 | pipe = usb_rcvintpipe(dev, ep->bEndpointAddress); | 467 | pipe = usb_rcvintpipe(dev, ep->bEndpointAddress); |
466 | maxp = usb_maxpacket(dev, pipe); | 468 | maxp = usb_maxpacket(dev, pipe); |
467 | 469 | ||
468 | /* We found a USB Keyboard, install it. */ | 470 | /* We found a USB Keyboard, install it. */ |
469 | usb_set_protocol(dev, iface->desc.bInterfaceNumber, 0); | 471 | usb_set_protocol(dev, iface->desc.bInterfaceNumber, 0); |
470 | 472 | ||
471 | debug("USB KBD: found set idle...\n"); | 473 | debug("USB KBD: found set idle...\n"); |
472 | usb_set_idle(dev, iface->desc.bInterfaceNumber, REPEAT_RATE, 0); | 474 | usb_set_idle(dev, iface->desc.bInterfaceNumber, REPEAT_RATE, 0); |
473 | 475 | ||
474 | debug("USB KBD: enable interrupt pipe...\n"); | 476 | debug("USB KBD: enable interrupt pipe...\n"); |
475 | if (usb_submit_int_msg(dev, pipe, data->new, | 477 | if (usb_submit_int_msg(dev, pipe, data->new, |
476 | min(maxp, USB_KBD_BOOT_REPORT_SIZE), | 478 | min(maxp, USB_KBD_BOOT_REPORT_SIZE), |
477 | ep->bInterval) < 0) { | 479 | ep->bInterval) < 0) { |
478 | printf("Failed to get keyboard state from device %04x:%04x\n", | 480 | printf("Failed to get keyboard state from device %04x:%04x\n", |
479 | dev->descriptor.idVendor, dev->descriptor.idProduct); | 481 | dev->descriptor.idVendor, dev->descriptor.idProduct); |
480 | /* Abort, we don't want to use that non-functional keyboard. */ | 482 | /* Abort, we don't want to use that non-functional keyboard. */ |
481 | return 0; | 483 | return 0; |
482 | } | 484 | } |
483 | 485 | ||
484 | /* Success. */ | 486 | /* Success. */ |
485 | return 1; | 487 | return 1; |
486 | } | 488 | } |
487 | 489 | ||
488 | /* Search for keyboard and register it if found. */ | 490 | /* Search for keyboard and register it if found. */ |
489 | int drv_usb_kbd_init(void) | 491 | int drv_usb_kbd_init(void) |
490 | { | 492 | { |
491 | struct stdio_dev usb_kbd_dev, *old_dev; | 493 | struct stdio_dev usb_kbd_dev; |
492 | struct usb_device *dev; | 494 | struct usb_device *dev; |
493 | char *stdinname = getenv("stdin"); | 495 | char *stdinname = getenv("stdin"); |
494 | int error, i; | 496 | int error, i; |
495 | 497 | ||
496 | /* Scan all USB Devices */ | 498 | /* Scan all USB Devices */ |
497 | for (i = 0; i < USB_MAX_DEVICE; i++) { | 499 | for (i = 0; i < USB_MAX_DEVICE; i++) { |
498 | /* Get USB device. */ | 500 | /* Get USB device. */ |
499 | dev = usb_get_dev_index(i); | 501 | dev = usb_get_dev_index(i); |
500 | if (!dev) | 502 | if (!dev) |
501 | return -1; | 503 | return -1; |
502 | 504 | ||
503 | if (dev->devnum == -1) | 505 | if (dev->devnum == -1) |
504 | continue; | 506 | continue; |
505 | 507 | ||
506 | /* Try probing the keyboard */ | 508 | /* Try probing the keyboard */ |
507 | if (usb_kbd_probe(dev, 0) != 1) | 509 | if (usb_kbd_probe(dev, 0) != 1) |
508 | continue; | 510 | continue; |
509 | 511 | ||
510 | /* We found a keyboard, check if it is already registered. */ | ||
511 | debug("USB KBD: found set up device.\n"); | ||
512 | old_dev = stdio_get_by_name(DEVNAME); | ||
513 | if (old_dev) { | ||
514 | /* Already registered, just return ok. */ | ||
515 | debug("USB KBD: is already registered.\n"); | ||
516 | usb_kbd_deregister(); | ||
517 | return 1; | ||
518 | } | ||
519 | |||
520 | /* Register the keyboard */ | 512 | /* Register the keyboard */ |
521 | debug("USB KBD: register.\n"); | 513 | debug("USB KBD: register.\n"); |
522 | memset(&usb_kbd_dev, 0, sizeof(struct stdio_dev)); | 514 | memset(&usb_kbd_dev, 0, sizeof(struct stdio_dev)); |
523 | strcpy(usb_kbd_dev.name, DEVNAME); | 515 | strcpy(usb_kbd_dev.name, DEVNAME); |
524 | usb_kbd_dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; | 516 | usb_kbd_dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; |
525 | usb_kbd_dev.getc = usb_kbd_getc; | 517 | usb_kbd_dev.getc = usb_kbd_getc; |
526 | usb_kbd_dev.tstc = usb_kbd_testc; | 518 | usb_kbd_dev.tstc = usb_kbd_testc; |
527 | usb_kbd_dev.priv = (void *)dev; | 519 | usb_kbd_dev.priv = (void *)dev; |
528 | error = stdio_register(&usb_kbd_dev); | 520 | error = stdio_register(&usb_kbd_dev); |
529 | if (error) | 521 | if (error) |
530 | return error; | 522 | return error; |
531 | 523 | ||
532 | #ifdef CONFIG_CONSOLE_MUX | 524 | #ifdef CONFIG_CONSOLE_MUX |
533 | error = iomux_doenv(stdin, stdinname); | 525 | error = iomux_doenv(stdin, stdinname); |
534 | if (error) | 526 | if (error) |
535 | return error; | 527 | return error; |
536 | #else | 528 | #else |
537 | /* Check if this is the standard input device. */ | 529 | /* Check if this is the standard input device. */ |
538 | if (strcmp(stdinname, DEVNAME)) | 530 | if (strcmp(stdinname, DEVNAME)) |
539 | return 1; | 531 | return 1; |
540 | 532 | ||
541 | /* Reassign the console */ | 533 | /* Reassign the console */ |
542 | if (overwrite_console()) | 534 | if (overwrite_console()) |
543 | return 1; | 535 | return 1; |
544 | 536 | ||
545 | error = console_assign(stdin, DEVNAME); | 537 | error = console_assign(stdin, DEVNAME); |
546 | if (error) | 538 | if (error) |
547 | return error; | 539 | return error; |
548 | #endif | 540 | #endif |
549 | 541 | ||
550 | return 1; | 542 | return 1; |
551 | } | 543 | } |
552 | 544 | ||
553 | /* No USB Keyboard found */ | 545 | /* No USB Keyboard found */ |
554 | return -1; | 546 | return -1; |
555 | } | 547 | } |
556 | 548 | ||
557 | /* Deregister the keyboard. */ | 549 | /* Deregister the keyboard. */ |
558 | int usb_kbd_deregister(void) | 550 | int usb_kbd_deregister(int force) |
559 | { | 551 | { |
560 | #ifdef CONFIG_SYS_STDIO_DEREGISTER | 552 | #ifdef CONFIG_SYS_STDIO_DEREGISTER |
561 | return stdio_deregister(DEVNAME); | 553 | int ret = stdio_deregister(DEVNAME, force); |
554 | if (ret && ret != -ENODEV) | ||
555 | return ret; | ||
556 |
drivers/serial/serial-uclass.c
1 | /* | 1 | /* |
2 | * Copyright (c) 2014 The Chromium OS Authors. | 2 | * Copyright (c) 2014 The Chromium OS Authors. |
3 | * | 3 | * |
4 | * SPDX-License-Identifier: GPL-2.0+ | 4 | * SPDX-License-Identifier: GPL-2.0+ |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <common.h> | 7 | #include <common.h> |
8 | #include <dm.h> | 8 | #include <dm.h> |
9 | #include <errno.h> | 9 | #include <errno.h> |
10 | #include <fdtdec.h> | 10 | #include <fdtdec.h> |
11 | #include <os.h> | 11 | #include <os.h> |
12 | #include <serial.h> | 12 | #include <serial.h> |
13 | #include <stdio_dev.h> | 13 | #include <stdio_dev.h> |
14 | #include <dm/lists.h> | 14 | #include <dm/lists.h> |
15 | #include <dm/device-internal.h> | 15 | #include <dm/device-internal.h> |
16 | 16 | ||
17 | DECLARE_GLOBAL_DATA_PTR; | 17 | DECLARE_GLOBAL_DATA_PTR; |
18 | 18 | ||
19 | /* The currently-selected console serial device */ | 19 | /* The currently-selected console serial device */ |
20 | struct udevice *cur_dev __attribute__ ((section(".data"))); | 20 | struct udevice *cur_dev __attribute__ ((section(".data"))); |
21 | 21 | ||
22 | #ifndef CONFIG_SYS_MALLOC_F_LEN | 22 | #ifndef CONFIG_SYS_MALLOC_F_LEN |
23 | #error "Serial is required before relocation - define CONFIG_SYS_MALLOC_F_LEN to make this work" | 23 | #error "Serial is required before relocation - define CONFIG_SYS_MALLOC_F_LEN to make this work" |
24 | #endif | 24 | #endif |
25 | 25 | ||
26 | static void serial_find_console_or_panic(void) | 26 | static void serial_find_console_or_panic(void) |
27 | { | 27 | { |
28 | #ifdef CONFIG_OF_CONTROL | 28 | #ifdef CONFIG_OF_CONTROL |
29 | int node; | 29 | int node; |
30 | 30 | ||
31 | /* Check for a chosen console */ | 31 | /* Check for a chosen console */ |
32 | node = fdtdec_get_chosen_node(gd->fdt_blob, "stdout-path"); | 32 | node = fdtdec_get_chosen_node(gd->fdt_blob, "stdout-path"); |
33 | if (node < 0) | 33 | if (node < 0) |
34 | node = fdtdec_get_alias_node(gd->fdt_blob, "console"); | 34 | node = fdtdec_get_alias_node(gd->fdt_blob, "console"); |
35 | if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, &cur_dev)) | 35 | if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, &cur_dev)) |
36 | return; | 36 | return; |
37 | 37 | ||
38 | /* | 38 | /* |
39 | * If the console is not marked to be bound before relocation, bind | 39 | * If the console is not marked to be bound before relocation, bind |
40 | * it anyway. | 40 | * it anyway. |
41 | */ | 41 | */ |
42 | if (node > 0 && | 42 | if (node > 0 && |
43 | !lists_bind_fdt(gd->dm_root, gd->fdt_blob, node, &cur_dev)) { | 43 | !lists_bind_fdt(gd->dm_root, gd->fdt_blob, node, &cur_dev)) { |
44 | if (!device_probe(cur_dev)) | 44 | if (!device_probe(cur_dev)) |
45 | return; | 45 | return; |
46 | cur_dev = NULL; | 46 | cur_dev = NULL; |
47 | } | 47 | } |
48 | #endif | 48 | #endif |
49 | /* | 49 | /* |
50 | * Failing that, get the device with sequence number 0, or in extremis | 50 | * Failing that, get the device with sequence number 0, or in extremis |
51 | * just the first serial device we can find. But we insist on having | 51 | * just the first serial device we can find. But we insist on having |
52 | * a console (even if it is silent). | 52 | * a console (even if it is silent). |
53 | */ | 53 | */ |
54 | if (uclass_get_device_by_seq(UCLASS_SERIAL, 0, &cur_dev) && | 54 | if (uclass_get_device_by_seq(UCLASS_SERIAL, 0, &cur_dev) && |
55 | (uclass_first_device(UCLASS_SERIAL, &cur_dev) || !cur_dev)) | 55 | (uclass_first_device(UCLASS_SERIAL, &cur_dev) || !cur_dev)) |
56 | panic("No serial driver found"); | 56 | panic("No serial driver found"); |
57 | } | 57 | } |
58 | 58 | ||
59 | /* Called prior to relocation */ | 59 | /* Called prior to relocation */ |
60 | int serial_init(void) | 60 | int serial_init(void) |
61 | { | 61 | { |
62 | serial_find_console_or_panic(); | 62 | serial_find_console_or_panic(); |
63 | gd->flags |= GD_FLG_SERIAL_READY; | 63 | gd->flags |= GD_FLG_SERIAL_READY; |
64 | 64 | ||
65 | return 0; | 65 | return 0; |
66 | } | 66 | } |
67 | 67 | ||
68 | /* Called after relocation */ | 68 | /* Called after relocation */ |
69 | void serial_initialize(void) | 69 | void serial_initialize(void) |
70 | { | 70 | { |
71 | serial_find_console_or_panic(); | 71 | serial_find_console_or_panic(); |
72 | } | 72 | } |
73 | 73 | ||
74 | void serial_putc(char ch) | 74 | void serial_putc(char ch) |
75 | { | 75 | { |
76 | struct dm_serial_ops *ops = serial_get_ops(cur_dev); | 76 | struct dm_serial_ops *ops = serial_get_ops(cur_dev); |
77 | int err; | 77 | int err; |
78 | 78 | ||
79 | do { | 79 | do { |
80 | err = ops->putc(cur_dev, ch); | 80 | err = ops->putc(cur_dev, ch); |
81 | } while (err == -EAGAIN); | 81 | } while (err == -EAGAIN); |
82 | if (ch == '\n') | 82 | if (ch == '\n') |
83 | serial_putc('\r'); | 83 | serial_putc('\r'); |
84 | } | 84 | } |
85 | 85 | ||
86 | void serial_setbrg(void) | 86 | void serial_setbrg(void) |
87 | { | 87 | { |
88 | struct dm_serial_ops *ops = serial_get_ops(cur_dev); | 88 | struct dm_serial_ops *ops = serial_get_ops(cur_dev); |
89 | 89 | ||
90 | if (ops->setbrg) | 90 | if (ops->setbrg) |
91 | ops->setbrg(cur_dev, gd->baudrate); | 91 | ops->setbrg(cur_dev, gd->baudrate); |
92 | } | 92 | } |
93 | 93 | ||
94 | void serial_puts(const char *str) | 94 | void serial_puts(const char *str) |
95 | { | 95 | { |
96 | while (*str) | 96 | while (*str) |
97 | serial_putc(*str++); | 97 | serial_putc(*str++); |
98 | } | 98 | } |
99 | 99 | ||
100 | int serial_tstc(void) | 100 | int serial_tstc(void) |
101 | { | 101 | { |
102 | struct dm_serial_ops *ops = serial_get_ops(cur_dev); | 102 | struct dm_serial_ops *ops = serial_get_ops(cur_dev); |
103 | 103 | ||
104 | if (ops->pending) | 104 | if (ops->pending) |
105 | return ops->pending(cur_dev, true); | 105 | return ops->pending(cur_dev, true); |
106 | 106 | ||
107 | return 1; | 107 | return 1; |
108 | } | 108 | } |
109 | 109 | ||
110 | int serial_getc(void) | 110 | int serial_getc(void) |
111 | { | 111 | { |
112 | struct dm_serial_ops *ops = serial_get_ops(cur_dev); | 112 | struct dm_serial_ops *ops = serial_get_ops(cur_dev); |
113 | int err; | 113 | int err; |
114 | 114 | ||
115 | do { | 115 | do { |
116 | err = ops->getc(cur_dev); | 116 | err = ops->getc(cur_dev); |
117 | } while (err == -EAGAIN); | 117 | } while (err == -EAGAIN); |
118 | 118 | ||
119 | return err >= 0 ? err : 0; | 119 | return err >= 0 ? err : 0; |
120 | } | 120 | } |
121 | 121 | ||
122 | void serial_stdio_init(void) | 122 | void serial_stdio_init(void) |
123 | { | 123 | { |
124 | } | 124 | } |
125 | 125 | ||
126 | void serial_stub_putc(struct stdio_dev *sdev, const char ch) | 126 | void serial_stub_putc(struct stdio_dev *sdev, const char ch) |
127 | { | 127 | { |
128 | struct udevice *dev = sdev->priv; | 128 | struct udevice *dev = sdev->priv; |
129 | struct dm_serial_ops *ops = serial_get_ops(dev); | 129 | struct dm_serial_ops *ops = serial_get_ops(dev); |
130 | 130 | ||
131 | ops->putc(dev, ch); | 131 | ops->putc(dev, ch); |
132 | } | 132 | } |
133 | 133 | ||
134 | void serial_stub_puts(struct stdio_dev *sdev, const char *str) | 134 | void serial_stub_puts(struct stdio_dev *sdev, const char *str) |
135 | { | 135 | { |
136 | while (*str) | 136 | while (*str) |
137 | serial_stub_putc(sdev, *str++); | 137 | serial_stub_putc(sdev, *str++); |
138 | } | 138 | } |
139 | 139 | ||
140 | int serial_stub_getc(struct stdio_dev *sdev) | 140 | int serial_stub_getc(struct stdio_dev *sdev) |
141 | { | 141 | { |
142 | struct udevice *dev = sdev->priv; | 142 | struct udevice *dev = sdev->priv; |
143 | struct dm_serial_ops *ops = serial_get_ops(dev); | 143 | struct dm_serial_ops *ops = serial_get_ops(dev); |
144 | 144 | ||
145 | int err; | 145 | int err; |
146 | 146 | ||
147 | do { | 147 | do { |
148 | err = ops->getc(dev); | 148 | err = ops->getc(dev); |
149 | } while (err == -EAGAIN); | 149 | } while (err == -EAGAIN); |
150 | 150 | ||
151 | return err >= 0 ? err : 0; | 151 | return err >= 0 ? err : 0; |
152 | } | 152 | } |
153 | 153 | ||
154 | int serial_stub_tstc(struct stdio_dev *sdev) | 154 | int serial_stub_tstc(struct stdio_dev *sdev) |
155 | { | 155 | { |
156 | struct udevice *dev = sdev->priv; | 156 | struct udevice *dev = sdev->priv; |
157 | struct dm_serial_ops *ops = serial_get_ops(dev); | 157 | struct dm_serial_ops *ops = serial_get_ops(dev); |
158 | 158 | ||
159 | if (ops->pending) | 159 | if (ops->pending) |
160 | return ops->pending(dev, true); | 160 | return ops->pending(dev, true); |
161 | 161 | ||
162 | return 1; | 162 | return 1; |
163 | } | 163 | } |
164 | 164 | ||
165 | static int serial_post_probe(struct udevice *dev) | 165 | static int serial_post_probe(struct udevice *dev) |
166 | { | 166 | { |
167 | struct stdio_dev sdev; | 167 | struct stdio_dev sdev; |
168 | struct dm_serial_ops *ops = serial_get_ops(dev); | 168 | struct dm_serial_ops *ops = serial_get_ops(dev); |
169 | struct serial_dev_priv *upriv = dev->uclass_priv; | 169 | struct serial_dev_priv *upriv = dev->uclass_priv; |
170 | int ret; | 170 | int ret; |
171 | 171 | ||
172 | /* Set the baud rate */ | 172 | /* Set the baud rate */ |
173 | if (ops->setbrg) { | 173 | if (ops->setbrg) { |
174 | ret = ops->setbrg(dev, gd->baudrate); | 174 | ret = ops->setbrg(dev, gd->baudrate); |
175 | if (ret) | 175 | if (ret) |
176 | return ret; | 176 | return ret; |
177 | } | 177 | } |
178 | 178 | ||
179 | if (!(gd->flags & GD_FLG_RELOC)) | 179 | if (!(gd->flags & GD_FLG_RELOC)) |
180 | return 0; | 180 | return 0; |
181 | 181 | ||
182 | memset(&sdev, '\0', sizeof(sdev)); | 182 | memset(&sdev, '\0', sizeof(sdev)); |
183 | 183 | ||
184 | strncpy(sdev.name, dev->name, sizeof(sdev.name)); | 184 | strncpy(sdev.name, dev->name, sizeof(sdev.name)); |
185 | sdev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT; | 185 | sdev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT; |
186 | sdev.priv = dev; | 186 | sdev.priv = dev; |
187 | sdev.putc = serial_stub_putc; | 187 | sdev.putc = serial_stub_putc; |
188 | sdev.puts = serial_stub_puts; | 188 | sdev.puts = serial_stub_puts; |
189 | sdev.getc = serial_stub_getc; | 189 | sdev.getc = serial_stub_getc; |
190 | sdev.tstc = serial_stub_tstc; | 190 | sdev.tstc = serial_stub_tstc; |
191 | stdio_register_dev(&sdev, &upriv->sdev); | 191 | stdio_register_dev(&sdev, &upriv->sdev); |
192 | 192 | ||
193 | return 0; | 193 | return 0; |
194 | } | 194 | } |
195 | 195 | ||
196 | static int serial_pre_remove(struct udevice *dev) | 196 | static int serial_pre_remove(struct udevice *dev) |
197 | { | 197 | { |
198 | #ifdef CONFIG_SYS_STDIO_DEREGISTER | 198 | #ifdef CONFIG_SYS_STDIO_DEREGISTER |
199 | struct serial_dev_priv *upriv = dev->uclass_priv; | 199 | struct serial_dev_priv *upriv = dev->uclass_priv; |
200 | 200 | ||
201 | if (stdio_deregister_dev(upriv->sdev)) | 201 | if (stdio_deregister_dev(upriv->sdev), 0) |
202 | return -EPERM; | 202 | return -EPERM; |
203 | #endif | 203 | #endif |
204 | 204 | ||
205 | return 0; | 205 | return 0; |
206 | } | 206 | } |
207 | 207 | ||
208 | UCLASS_DRIVER(serial) = { | 208 | UCLASS_DRIVER(serial) = { |
209 | .id = UCLASS_SERIAL, | 209 | .id = UCLASS_SERIAL, |
210 | .name = "serial", | 210 | .name = "serial", |
211 | .post_probe = serial_post_probe, | 211 | .post_probe = serial_post_probe, |
212 | .pre_remove = serial_pre_remove, | 212 | .pre_remove = serial_pre_remove, |
213 | .per_device_auto_alloc_size = sizeof(struct serial_dev_priv), | 213 | .per_device_auto_alloc_size = sizeof(struct serial_dev_priv), |
214 | }; | 214 | }; |
215 | 215 |
drivers/usb/gadget/ci_udc.c
1 | /* | 1 | /* |
2 | * Copyright 2011, Marvell Semiconductor Inc. | 2 | * Copyright 2011, Marvell Semiconductor Inc. |
3 | * Lei Wen <leiwen@marvell.com> | 3 | * Lei Wen <leiwen@marvell.com> |
4 | * | 4 | * |
5 | * SPDX-License-Identifier: GPL-2.0+ | 5 | * SPDX-License-Identifier: GPL-2.0+ |
6 | * | 6 | * |
7 | * Back ported to the 8xx platform (from the 8260 platform) by | 7 | * Back ported to the 8xx platform (from the 8260 platform) by |
8 | * Murray.Jensen@cmst.csiro.au, 27-Jan-01. | 8 | * Murray.Jensen@cmst.csiro.au, 27-Jan-01. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <common.h> | 11 | #include <common.h> |
12 | #include <command.h> | 12 | #include <command.h> |
13 | #include <config.h> | 13 | #include <config.h> |
14 | #include <net.h> | 14 | #include <net.h> |
15 | #include <malloc.h> | 15 | #include <malloc.h> |
16 | #include <asm/byteorder.h> | 16 | #include <asm/byteorder.h> |
17 | #include <asm/errno.h> | 17 | #include <asm/errno.h> |
18 | #include <asm/io.h> | 18 | #include <asm/io.h> |
19 | #include <asm/unaligned.h> | 19 | #include <asm/unaligned.h> |
20 | #include <linux/types.h> | 20 | #include <linux/types.h> |
21 | #include <linux/usb/ch9.h> | 21 | #include <linux/usb/ch9.h> |
22 | #include <linux/usb/gadget.h> | 22 | #include <linux/usb/gadget.h> |
23 | #include <usb/ci_udc.h> | 23 | #include <usb/ci_udc.h> |
24 | #include "../host/ehci.h" | 24 | #include "../host/ehci.h" |
25 | #include "ci_udc.h" | 25 | #include "ci_udc.h" |
26 | 26 | ||
27 | /* | 27 | /* |
28 | * Check if the system has too long cachelines. If the cachelines are | 28 | * Check if the system has too long cachelines. If the cachelines are |
29 | * longer then 128b, the driver will not be able flush/invalidate data | 29 | * longer then 128b, the driver will not be able flush/invalidate data |
30 | * cache over separate QH entries. We use 128b because one QH entry is | 30 | * cache over separate QH entries. We use 128b because one QH entry is |
31 | * 64b long and there are always two QH list entries for each endpoint. | 31 | * 64b long and there are always two QH list entries for each endpoint. |
32 | */ | 32 | */ |
33 | #if ARCH_DMA_MINALIGN > 128 | 33 | #if ARCH_DMA_MINALIGN > 128 |
34 | #error This driver can not work on systems with caches longer than 128b | 34 | #error This driver can not work on systems with caches longer than 128b |
35 | #endif | 35 | #endif |
36 | 36 | ||
37 | /* | 37 | /* |
38 | * Every QTD must be individually aligned, since we can program any | 38 | * Every QTD must be individually aligned, since we can program any |
39 | * QTD's address into HW. Cache flushing requires ARCH_DMA_MINALIGN, | 39 | * QTD's address into HW. Cache flushing requires ARCH_DMA_MINALIGN, |
40 | * and the USB HW requires 32-byte alignment. Align to both: | 40 | * and the USB HW requires 32-byte alignment. Align to both: |
41 | */ | 41 | */ |
42 | #define ILIST_ALIGN roundup(ARCH_DMA_MINALIGN, 32) | 42 | #define ILIST_ALIGN roundup(ARCH_DMA_MINALIGN, 32) |
43 | /* Each QTD is this size */ | 43 | /* Each QTD is this size */ |
44 | #define ILIST_ENT_RAW_SZ sizeof(struct ept_queue_item) | 44 | #define ILIST_ENT_RAW_SZ sizeof(struct ept_queue_item) |
45 | /* | 45 | /* |
46 | * Align the size of the QTD too, so we can add this value to each | 46 | * Align the size of the QTD too, so we can add this value to each |
47 | * QTD's address to get another aligned address. | 47 | * QTD's address to get another aligned address. |
48 | */ | 48 | */ |
49 | #define ILIST_ENT_SZ roundup(ILIST_ENT_RAW_SZ, ILIST_ALIGN) | 49 | #define ILIST_ENT_SZ roundup(ILIST_ENT_RAW_SZ, ILIST_ALIGN) |
50 | /* For each endpoint, we need 2 QTDs, one for each of IN and OUT */ | 50 | /* For each endpoint, we need 2 QTDs, one for each of IN and OUT */ |
51 | #define ILIST_SZ (NUM_ENDPOINTS * 2 * ILIST_ENT_SZ) | 51 | #define ILIST_SZ (NUM_ENDPOINTS * 2 * ILIST_ENT_SZ) |
52 | 52 | ||
53 | #ifndef DEBUG | 53 | #ifndef DEBUG |
54 | #define DBG(x...) do {} while (0) | 54 | #define DBG(x...) do {} while (0) |
55 | #else | 55 | #else |
56 | #define DBG(x...) printf(x) | 56 | #define DBG(x...) printf(x) |
57 | static const char *reqname(unsigned r) | 57 | static const char *reqname(unsigned r) |
58 | { | 58 | { |
59 | switch (r) { | 59 | switch (r) { |
60 | case USB_REQ_GET_STATUS: return "GET_STATUS"; | 60 | case USB_REQ_GET_STATUS: return "GET_STATUS"; |
61 | case USB_REQ_CLEAR_FEATURE: return "CLEAR_FEATURE"; | 61 | case USB_REQ_CLEAR_FEATURE: return "CLEAR_FEATURE"; |
62 | case USB_REQ_SET_FEATURE: return "SET_FEATURE"; | 62 | case USB_REQ_SET_FEATURE: return "SET_FEATURE"; |
63 | case USB_REQ_SET_ADDRESS: return "SET_ADDRESS"; | 63 | case USB_REQ_SET_ADDRESS: return "SET_ADDRESS"; |
64 | case USB_REQ_GET_DESCRIPTOR: return "GET_DESCRIPTOR"; | 64 | case USB_REQ_GET_DESCRIPTOR: return "GET_DESCRIPTOR"; |
65 | case USB_REQ_SET_DESCRIPTOR: return "SET_DESCRIPTOR"; | 65 | case USB_REQ_SET_DESCRIPTOR: return "SET_DESCRIPTOR"; |
66 | case USB_REQ_GET_CONFIGURATION: return "GET_CONFIGURATION"; | 66 | case USB_REQ_GET_CONFIGURATION: return "GET_CONFIGURATION"; |
67 | case USB_REQ_SET_CONFIGURATION: return "SET_CONFIGURATION"; | 67 | case USB_REQ_SET_CONFIGURATION: return "SET_CONFIGURATION"; |
68 | case USB_REQ_GET_INTERFACE: return "GET_INTERFACE"; | 68 | case USB_REQ_GET_INTERFACE: return "GET_INTERFACE"; |
69 | case USB_REQ_SET_INTERFACE: return "SET_INTERFACE"; | 69 | case USB_REQ_SET_INTERFACE: return "SET_INTERFACE"; |
70 | default: return "*UNKNOWN*"; | 70 | default: return "*UNKNOWN*"; |
71 | } | 71 | } |
72 | } | 72 | } |
73 | #endif | 73 | #endif |
74 | 74 | ||
75 | static struct usb_endpoint_descriptor ep0_desc = { | 75 | static struct usb_endpoint_descriptor ep0_desc = { |
76 | .bLength = sizeof(struct usb_endpoint_descriptor), | 76 | .bLength = sizeof(struct usb_endpoint_descriptor), |
77 | .bDescriptorType = USB_DT_ENDPOINT, | 77 | .bDescriptorType = USB_DT_ENDPOINT, |
78 | .bEndpointAddress = USB_DIR_IN, | 78 | .bEndpointAddress = USB_DIR_IN, |
79 | .bmAttributes = USB_ENDPOINT_XFER_CONTROL, | 79 | .bmAttributes = USB_ENDPOINT_XFER_CONTROL, |
80 | }; | 80 | }; |
81 | 81 | ||
82 | static int ci_pullup(struct usb_gadget *gadget, int is_on); | 82 | static int ci_pullup(struct usb_gadget *gadget, int is_on); |
83 | static int ci_ep_enable(struct usb_ep *ep, | 83 | static int ci_ep_enable(struct usb_ep *ep, |
84 | const struct usb_endpoint_descriptor *desc); | 84 | const struct usb_endpoint_descriptor *desc); |
85 | static int ci_ep_disable(struct usb_ep *ep); | 85 | static int ci_ep_disable(struct usb_ep *ep); |
86 | static int ci_ep_queue(struct usb_ep *ep, | 86 | static int ci_ep_queue(struct usb_ep *ep, |
87 | struct usb_request *req, gfp_t gfp_flags); | 87 | struct usb_request *req, gfp_t gfp_flags); |
88 | static struct usb_request * | 88 | static struct usb_request * |
89 | ci_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags); | 89 | ci_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags); |
90 | static void ci_ep_free_request(struct usb_ep *ep, struct usb_request *_req); | 90 | static void ci_ep_free_request(struct usb_ep *ep, struct usb_request *_req); |
91 | 91 | ||
92 | static struct usb_gadget_ops ci_udc_ops = { | 92 | static struct usb_gadget_ops ci_udc_ops = { |
93 | .pullup = ci_pullup, | 93 | .pullup = ci_pullup, |
94 | }; | 94 | }; |
95 | 95 | ||
96 | static struct usb_ep_ops ci_ep_ops = { | 96 | static struct usb_ep_ops ci_ep_ops = { |
97 | .enable = ci_ep_enable, | 97 | .enable = ci_ep_enable, |
98 | .disable = ci_ep_disable, | 98 | .disable = ci_ep_disable, |
99 | .queue = ci_ep_queue, | 99 | .queue = ci_ep_queue, |
100 | .alloc_request = ci_ep_alloc_request, | 100 | .alloc_request = ci_ep_alloc_request, |
101 | .free_request = ci_ep_free_request, | 101 | .free_request = ci_ep_free_request, |
102 | }; | 102 | }; |
103 | 103 | ||
104 | /* Init values for USB endpoints. */ | 104 | /* Init values for USB endpoints. */ |
105 | static const struct usb_ep ci_ep_init[2] = { | 105 | static const struct usb_ep ci_ep_init[2] = { |
106 | [0] = { /* EP 0 */ | 106 | [0] = { /* EP 0 */ |
107 | .maxpacket = 64, | 107 | .maxpacket = 64, |
108 | .name = "ep0", | 108 | .name = "ep0", |
109 | .ops = &ci_ep_ops, | 109 | .ops = &ci_ep_ops, |
110 | }, | 110 | }, |
111 | [1] = { /* EP 1..n */ | 111 | [1] = { /* EP 1..n */ |
112 | .maxpacket = 512, | 112 | .maxpacket = 512, |
113 | .name = "ep-", | 113 | .name = "ep-", |
114 | .ops = &ci_ep_ops, | 114 | .ops = &ci_ep_ops, |
115 | }, | 115 | }, |
116 | }; | 116 | }; |
117 | 117 | ||
118 | static struct ci_drv controller = { | 118 | static struct ci_drv controller = { |
119 | .gadget = { | 119 | .gadget = { |
120 | .name = "ci_udc", | 120 | .name = "ci_udc", |
121 | .ops = &ci_udc_ops, | 121 | .ops = &ci_udc_ops, |
122 | .is_dualspeed = 1, | 122 | .is_dualspeed = 1, |
123 | }, | 123 | }, |
124 | }; | 124 | }; |
125 | 125 | ||
126 | /** | 126 | /** |
127 | * ci_get_qh() - return queue head for endpoint | 127 | * ci_get_qh() - return queue head for endpoint |
128 | * @ep_num: Endpoint number | 128 | * @ep_num: Endpoint number |
129 | * @dir_in: Direction of the endpoint (IN = 1, OUT = 0) | 129 | * @dir_in: Direction of the endpoint (IN = 1, OUT = 0) |
130 | * | 130 | * |
131 | * This function returns the QH associated with particular endpoint | 131 | * This function returns the QH associated with particular endpoint |
132 | * and it's direction. | 132 | * and it's direction. |
133 | */ | 133 | */ |
134 | static struct ept_queue_head *ci_get_qh(int ep_num, int dir_in) | 134 | static struct ept_queue_head *ci_get_qh(int ep_num, int dir_in) |
135 | { | 135 | { |
136 | return &controller.epts[(ep_num * 2) + dir_in]; | 136 | return &controller.epts[(ep_num * 2) + dir_in]; |
137 | } | 137 | } |
138 | 138 | ||
139 | /** | 139 | /** |
140 | * ci_get_qtd() - return queue item for endpoint | 140 | * ci_get_qtd() - return queue item for endpoint |
141 | * @ep_num: Endpoint number | 141 | * @ep_num: Endpoint number |
142 | * @dir_in: Direction of the endpoint (IN = 1, OUT = 0) | 142 | * @dir_in: Direction of the endpoint (IN = 1, OUT = 0) |
143 | * | 143 | * |
144 | * This function returns the QH associated with particular endpoint | 144 | * This function returns the QH associated with particular endpoint |
145 | * and it's direction. | 145 | * and it's direction. |
146 | */ | 146 | */ |
147 | static struct ept_queue_item *ci_get_qtd(int ep_num, int dir_in) | 147 | static struct ept_queue_item *ci_get_qtd(int ep_num, int dir_in) |
148 | { | 148 | { |
149 | int index = (ep_num * 2) + dir_in; | 149 | int index = (ep_num * 2) + dir_in; |
150 | uint8_t *imem = controller.items_mem + (index * ILIST_ENT_SZ); | 150 | uint8_t *imem = controller.items_mem + (index * ILIST_ENT_SZ); |
151 | return (struct ept_queue_item *)imem; | 151 | return (struct ept_queue_item *)imem; |
152 | } | 152 | } |
153 | 153 | ||
154 | /** | 154 | /** |
155 | * ci_flush_qh - flush cache over queue head | 155 | * ci_flush_qh - flush cache over queue head |
156 | * @ep_num: Endpoint number | 156 | * @ep_num: Endpoint number |
157 | * | 157 | * |
158 | * This function flushes cache over QH for particular endpoint. | 158 | * This function flushes cache over QH for particular endpoint. |
159 | */ | 159 | */ |
160 | static void ci_flush_qh(int ep_num) | 160 | static void ci_flush_qh(int ep_num) |
161 | { | 161 | { |
162 | struct ept_queue_head *head = ci_get_qh(ep_num, 0); | 162 | struct ept_queue_head *head = ci_get_qh(ep_num, 0); |
163 | const uint32_t start = (uint32_t)head; | 163 | const uint32_t start = (uint32_t)head; |
164 | const uint32_t end = start + 2 * sizeof(*head); | 164 | const uint32_t end = start + 2 * sizeof(*head); |
165 | 165 | ||
166 | flush_dcache_range(start, end); | 166 | flush_dcache_range(start, end); |
167 | } | 167 | } |
168 | 168 | ||
169 | /** | 169 | /** |
170 | * ci_invalidate_qh - invalidate cache over queue head | 170 | * ci_invalidate_qh - invalidate cache over queue head |
171 | * @ep_num: Endpoint number | 171 | * @ep_num: Endpoint number |
172 | * | 172 | * |
173 | * This function invalidates cache over QH for particular endpoint. | 173 | * This function invalidates cache over QH for particular endpoint. |
174 | */ | 174 | */ |
175 | static void ci_invalidate_qh(int ep_num) | 175 | static void ci_invalidate_qh(int ep_num) |
176 | { | 176 | { |
177 | struct ept_queue_head *head = ci_get_qh(ep_num, 0); | 177 | struct ept_queue_head *head = ci_get_qh(ep_num, 0); |
178 | uint32_t start = (uint32_t)head; | 178 | uint32_t start = (uint32_t)head; |
179 | uint32_t end = start + 2 * sizeof(*head); | 179 | uint32_t end = start + 2 * sizeof(*head); |
180 | 180 | ||
181 | invalidate_dcache_range(start, end); | 181 | invalidate_dcache_range(start, end); |
182 | } | 182 | } |
183 | 183 | ||
184 | /** | 184 | /** |
185 | * ci_flush_qtd - flush cache over queue item | 185 | * ci_flush_qtd - flush cache over queue item |
186 | * @ep_num: Endpoint number | 186 | * @ep_num: Endpoint number |
187 | * | 187 | * |
188 | * This function flushes cache over qTD pair for particular endpoint. | 188 | * This function flushes cache over qTD pair for particular endpoint. |
189 | */ | 189 | */ |
190 | static void ci_flush_qtd(int ep_num) | 190 | static void ci_flush_qtd(int ep_num) |
191 | { | 191 | { |
192 | struct ept_queue_item *item = ci_get_qtd(ep_num, 0); | 192 | struct ept_queue_item *item = ci_get_qtd(ep_num, 0); |
193 | const uint32_t start = (uint32_t)item; | 193 | const uint32_t start = (uint32_t)item; |
194 | const uint32_t end = start + 2 * ILIST_ENT_SZ; | 194 | const uint32_t end = start + 2 * ILIST_ENT_SZ; |
195 | 195 | ||
196 | flush_dcache_range(start, end); | 196 | flush_dcache_range(start, end); |
197 | } | 197 | } |
198 | 198 | ||
199 | /** | 199 | /** |
200 | * ci_invalidate_qtd - invalidate cache over queue item | 200 | * ci_invalidate_qtd - invalidate cache over queue item |
201 | * @ep_num: Endpoint number | 201 | * @ep_num: Endpoint number |
202 | * | 202 | * |
203 | * This function invalidates cache over qTD pair for particular endpoint. | 203 | * This function invalidates cache over qTD pair for particular endpoint. |
204 | */ | 204 | */ |
205 | static void ci_invalidate_qtd(int ep_num) | 205 | static void ci_invalidate_qtd(int ep_num) |
206 | { | 206 | { |
207 | struct ept_queue_item *item = ci_get_qtd(ep_num, 0); | 207 | struct ept_queue_item *item = ci_get_qtd(ep_num, 0); |
208 | const uint32_t start = (uint32_t)item; | 208 | const uint32_t start = (uint32_t)item; |
209 | const uint32_t end = start + 2 * ILIST_ENT_SZ; | 209 | const uint32_t end = start + 2 * ILIST_ENT_SZ; |
210 | 210 | ||
211 | invalidate_dcache_range(start, end); | 211 | invalidate_dcache_range(start, end); |
212 | } | 212 | } |
213 | 213 | ||
214 | static struct usb_request * | 214 | static struct usb_request * |
215 | ci_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags) | 215 | ci_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags) |
216 | { | 216 | { |
217 | struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep); | 217 | struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep); |
218 | int num; | 218 | int num; |
219 | struct ci_req *ci_req; | 219 | struct ci_req *ci_req; |
220 | 220 | ||
221 | num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | 221 | num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; |
222 | if (num == 0 && controller.ep0_req) | 222 | if (num == 0 && controller.ep0_req) |
223 | return &controller.ep0_req->req; | 223 | return &controller.ep0_req->req; |
224 | 224 | ||
225 | ci_req = calloc(1, sizeof(*ci_req)); | 225 | ci_req = calloc(1, sizeof(*ci_req)); |
226 | if (!ci_req) | 226 | if (!ci_req) |
227 | return NULL; | 227 | return NULL; |
228 | 228 | ||
229 | INIT_LIST_HEAD(&ci_req->queue); | 229 | INIT_LIST_HEAD(&ci_req->queue); |
230 | 230 | ||
231 | if (num == 0) | 231 | if (num == 0) |
232 | controller.ep0_req = ci_req; | 232 | controller.ep0_req = ci_req; |
233 | 233 | ||
234 | return &ci_req->req; | 234 | return &ci_req->req; |
235 | } | 235 | } |
236 | 236 | ||
237 | static void ci_ep_free_request(struct usb_ep *ep, struct usb_request *req) | 237 | static void ci_ep_free_request(struct usb_ep *ep, struct usb_request *req) |
238 | { | 238 | { |
239 | struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep); | 239 | struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep); |
240 | struct ci_req *ci_req = container_of(req, struct ci_req, req); | 240 | struct ci_req *ci_req = container_of(req, struct ci_req, req); |
241 | int num; | 241 | int num; |
242 | 242 | ||
243 | num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | 243 | num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; |
244 | if (num == 0) { | 244 | if (num == 0) { |
245 | if (!controller.ep0_req) | 245 | if (!controller.ep0_req) |
246 | return; | 246 | return; |
247 | controller.ep0_req = 0; | 247 | controller.ep0_req = 0; |
248 | } | 248 | } |
249 | 249 | ||
250 | if (ci_req->b_buf) | 250 | if (ci_req->b_buf) |
251 | free(ci_req->b_buf); | 251 | free(ci_req->b_buf); |
252 | free(ci_req); | 252 | free(ci_req); |
253 | } | 253 | } |
254 | 254 | ||
255 | static void ep_enable(int num, int in, int maxpacket) | 255 | static void ep_enable(int num, int in, int maxpacket) |
256 | { | 256 | { |
257 | struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; | 257 | struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; |
258 | unsigned n; | 258 | unsigned n; |
259 | 259 | ||
260 | n = readl(&udc->epctrl[num]); | 260 | n = readl(&udc->epctrl[num]); |
261 | if (in) | 261 | if (in) |
262 | n |= (CTRL_TXE | CTRL_TXR | CTRL_TXT_BULK); | 262 | n |= (CTRL_TXE | CTRL_TXR | CTRL_TXT_BULK); |
263 | else | 263 | else |
264 | n |= (CTRL_RXE | CTRL_RXR | CTRL_RXT_BULK); | 264 | n |= (CTRL_RXE | CTRL_RXR | CTRL_RXT_BULK); |
265 | 265 | ||
266 | if (num != 0) { | 266 | if (num != 0) { |
267 | struct ept_queue_head *head = ci_get_qh(num, in); | 267 | struct ept_queue_head *head = ci_get_qh(num, in); |
268 | 268 | ||
269 | head->config = CONFIG_MAX_PKT(maxpacket) | CONFIG_ZLT; | 269 | head->config = CONFIG_MAX_PKT(maxpacket) | CONFIG_ZLT; |
270 | ci_flush_qh(num); | 270 | ci_flush_qh(num); |
271 | } | 271 | } |
272 | writel(n, &udc->epctrl[num]); | 272 | writel(n, &udc->epctrl[num]); |
273 | } | 273 | } |
274 | 274 | ||
275 | static int ci_ep_enable(struct usb_ep *ep, | 275 | static int ci_ep_enable(struct usb_ep *ep, |
276 | const struct usb_endpoint_descriptor *desc) | 276 | const struct usb_endpoint_descriptor *desc) |
277 | { | 277 | { |
278 | struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep); | 278 | struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep); |
279 | int num, in; | 279 | int num, in; |
280 | num = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | 280 | num = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; |
281 | in = (desc->bEndpointAddress & USB_DIR_IN) != 0; | 281 | in = (desc->bEndpointAddress & USB_DIR_IN) != 0; |
282 | ci_ep->desc = desc; | 282 | ci_ep->desc = desc; |
283 | 283 | ||
284 | if (num) { | 284 | if (num) { |
285 | int max = get_unaligned_le16(&desc->wMaxPacketSize); | 285 | int max = get_unaligned_le16(&desc->wMaxPacketSize); |
286 | 286 | ||
287 | if ((max > 64) && (controller.gadget.speed == USB_SPEED_FULL)) | 287 | if ((max > 64) && (controller.gadget.speed == USB_SPEED_FULL)) |
288 | max = 64; | 288 | max = 64; |
289 | if (ep->maxpacket != max) { | 289 | if (ep->maxpacket != max) { |
290 | DBG("%s: from %d to %d\n", __func__, | 290 | DBG("%s: from %d to %d\n", __func__, |
291 | ep->maxpacket, max); | 291 | ep->maxpacket, max); |
292 | ep->maxpacket = max; | 292 | ep->maxpacket = max; |
293 | } | 293 | } |
294 | } | 294 | } |
295 | ep_enable(num, in, ep->maxpacket); | 295 | ep_enable(num, in, ep->maxpacket); |
296 | DBG("%s: num=%d maxpacket=%d\n", __func__, num, ep->maxpacket); | 296 | DBG("%s: num=%d maxpacket=%d\n", __func__, num, ep->maxpacket); |
297 | return 0; | 297 | return 0; |
298 | } | 298 | } |
299 | 299 | ||
300 | static int ci_ep_disable(struct usb_ep *ep) | 300 | static int ci_ep_disable(struct usb_ep *ep) |
301 | { | 301 | { |
302 | struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep); | 302 | struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep); |
303 | 303 | ||
304 | ci_ep->desc = NULL; | 304 | ci_ep->desc = NULL; |
305 | return 0; | 305 | return 0; |
306 | } | 306 | } |
307 | 307 | ||
308 | static int ci_bounce(struct ci_req *ci_req, int in) | 308 | static int ci_bounce(struct ci_req *ci_req, int in) |
309 | { | 309 | { |
310 | struct usb_request *req = &ci_req->req; | 310 | struct usb_request *req = &ci_req->req; |
311 | uint32_t addr = (uint32_t)req->buf; | 311 | uint32_t addr = (uint32_t)req->buf; |
312 | uint32_t hwaddr; | 312 | uint32_t hwaddr; |
313 | uint32_t aligned_used_len; | 313 | uint32_t aligned_used_len; |
314 | 314 | ||
315 | /* Input buffer address is not aligned. */ | 315 | /* Input buffer address is not aligned. */ |
316 | if (addr & (ARCH_DMA_MINALIGN - 1)) | 316 | if (addr & (ARCH_DMA_MINALIGN - 1)) |
317 | goto align; | 317 | goto align; |
318 | 318 | ||
319 | /* Input buffer length is not aligned. */ | 319 | /* Input buffer length is not aligned. */ |
320 | if (req->length & (ARCH_DMA_MINALIGN - 1)) | 320 | if (req->length & (ARCH_DMA_MINALIGN - 1)) |
321 | goto align; | 321 | goto align; |
322 | 322 | ||
323 | /* The buffer is well aligned, only flush cache. */ | 323 | /* The buffer is well aligned, only flush cache. */ |
324 | ci_req->hw_len = req->length; | 324 | ci_req->hw_len = req->length; |
325 | ci_req->hw_buf = req->buf; | 325 | ci_req->hw_buf = req->buf; |
326 | goto flush; | 326 | goto flush; |
327 | 327 | ||
328 | align: | 328 | align: |
329 | if (ci_req->b_buf && req->length > ci_req->b_len) { | 329 | if (ci_req->b_buf && req->length > ci_req->b_len) { |
330 | free(ci_req->b_buf); | 330 | free(ci_req->b_buf); |
331 | ci_req->b_buf = 0; | 331 | ci_req->b_buf = 0; |
332 | } | 332 | } |
333 | if (!ci_req->b_buf) { | 333 | if (!ci_req->b_buf) { |
334 | ci_req->b_len = roundup(req->length, ARCH_DMA_MINALIGN); | 334 | ci_req->b_len = roundup(req->length, ARCH_DMA_MINALIGN); |
335 | ci_req->b_buf = memalign(ARCH_DMA_MINALIGN, ci_req->b_len); | 335 | ci_req->b_buf = memalign(ARCH_DMA_MINALIGN, ci_req->b_len); |
336 | if (!ci_req->b_buf) | 336 | if (!ci_req->b_buf) |
337 | return -ENOMEM; | 337 | return -ENOMEM; |
338 | } | 338 | } |
339 | ci_req->hw_len = ci_req->b_len; | 339 | ci_req->hw_len = ci_req->b_len; |
340 | ci_req->hw_buf = ci_req->b_buf; | 340 | ci_req->hw_buf = ci_req->b_buf; |
341 | 341 | ||
342 | if (in) | 342 | if (in) |
343 | memcpy(ci_req->hw_buf, req->buf, req->length); | 343 | memcpy(ci_req->hw_buf, req->buf, req->length); |
344 | 344 | ||
345 | flush: | 345 | flush: |
346 | hwaddr = (uint32_t)ci_req->hw_buf; | 346 | hwaddr = (uint32_t)ci_req->hw_buf; |
347 | aligned_used_len = roundup(req->length, ARCH_DMA_MINALIGN); | 347 | aligned_used_len = roundup(req->length, ARCH_DMA_MINALIGN); |
348 | flush_dcache_range(hwaddr, hwaddr + aligned_used_len); | 348 | flush_dcache_range(hwaddr, hwaddr + aligned_used_len); |
349 | 349 | ||
350 | return 0; | 350 | return 0; |
351 | } | 351 | } |
352 | 352 | ||
353 | static void ci_debounce(struct ci_req *ci_req, int in) | 353 | static void ci_debounce(struct ci_req *ci_req, int in) |
354 | { | 354 | { |
355 | struct usb_request *req = &ci_req->req; | 355 | struct usb_request *req = &ci_req->req; |
356 | uint32_t addr = (uint32_t)req->buf; | 356 | uint32_t addr = (uint32_t)req->buf; |
357 | uint32_t hwaddr = (uint32_t)ci_req->hw_buf; | 357 | uint32_t hwaddr = (uint32_t)ci_req->hw_buf; |
358 | uint32_t aligned_used_len; | 358 | uint32_t aligned_used_len; |
359 | 359 | ||
360 | if (in) | 360 | if (in) |
361 | return; | 361 | return; |
362 | 362 | ||
363 | aligned_used_len = roundup(req->actual, ARCH_DMA_MINALIGN); | 363 | aligned_used_len = roundup(req->actual, ARCH_DMA_MINALIGN); |
364 | invalidate_dcache_range(hwaddr, hwaddr + aligned_used_len); | 364 | invalidate_dcache_range(hwaddr, hwaddr + aligned_used_len); |
365 | 365 | ||
366 | if (addr == hwaddr) | 366 | if (addr == hwaddr) |
367 | return; /* not a bounce */ | 367 | return; /* not a bounce */ |
368 | 368 | ||
369 | memcpy(req->buf, ci_req->hw_buf, req->actual); | 369 | memcpy(req->buf, ci_req->hw_buf, req->actual); |
370 | } | 370 | } |
371 | 371 | ||
372 | static void ci_ep_submit_next_request(struct ci_ep *ci_ep) | 372 | static void ci_ep_submit_next_request(struct ci_ep *ci_ep) |
373 | { | 373 | { |
374 | struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; | 374 | struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; |
375 | struct ept_queue_item *item; | 375 | struct ept_queue_item *item; |
376 | struct ept_queue_head *head; | 376 | struct ept_queue_head *head; |
377 | int bit, num, len, in; | 377 | int bit, num, len, in; |
378 | struct ci_req *ci_req; | 378 | struct ci_req *ci_req; |
379 | 379 | ||
380 | ci_ep->req_primed = true; | 380 | ci_ep->req_primed = true; |
381 | 381 | ||
382 | num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | 382 | num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; |
383 | in = (ci_ep->desc->bEndpointAddress & USB_DIR_IN) != 0; | 383 | in = (ci_ep->desc->bEndpointAddress & USB_DIR_IN) != 0; |
384 | item = ci_get_qtd(num, in); | 384 | item = ci_get_qtd(num, in); |
385 | head = ci_get_qh(num, in); | 385 | head = ci_get_qh(num, in); |
386 | 386 | ||
387 | ci_req = list_first_entry(&ci_ep->queue, struct ci_req, queue); | 387 | ci_req = list_first_entry(&ci_ep->queue, struct ci_req, queue); |
388 | len = ci_req->req.length; | 388 | len = ci_req->req.length; |
389 | 389 | ||
390 | item->info = INFO_BYTES(len) | INFO_ACTIVE; | 390 | item->info = INFO_BYTES(len) | INFO_ACTIVE; |
391 | item->page0 = (uint32_t)ci_req->hw_buf; | 391 | item->page0 = (uint32_t)ci_req->hw_buf; |
392 | item->page1 = ((uint32_t)ci_req->hw_buf & 0xfffff000) + 0x1000; | 392 | item->page1 = ((uint32_t)ci_req->hw_buf & 0xfffff000) + 0x1000; |
393 | item->page2 = ((uint32_t)ci_req->hw_buf & 0xfffff000) + 0x2000; | 393 | item->page2 = ((uint32_t)ci_req->hw_buf & 0xfffff000) + 0x2000; |
394 | item->page3 = ((uint32_t)ci_req->hw_buf & 0xfffff000) + 0x3000; | 394 | item->page3 = ((uint32_t)ci_req->hw_buf & 0xfffff000) + 0x3000; |
395 | item->page4 = ((uint32_t)ci_req->hw_buf & 0xfffff000) + 0x4000; | 395 | item->page4 = ((uint32_t)ci_req->hw_buf & 0xfffff000) + 0x4000; |
396 | 396 | ||
397 | head->next = (unsigned) item; | 397 | head->next = (unsigned) item; |
398 | head->info = 0; | 398 | head->info = 0; |
399 | 399 | ||
400 | /* | 400 | /* |
401 | * When sending the data for an IN transaction, the attached host | 401 | * When sending the data for an IN transaction, the attached host |
402 | * knows that all data for the IN is sent when one of the following | 402 | * knows that all data for the IN is sent when one of the following |
403 | * occurs: | 403 | * occurs: |
404 | * a) A zero-length packet is transmitted. | 404 | * a) A zero-length packet is transmitted. |
405 | * b) A packet with length that isn't an exact multiple of the ep's | 405 | * b) A packet with length that isn't an exact multiple of the ep's |
406 | * maxpacket is transmitted. | 406 | * maxpacket is transmitted. |
407 | * c) Enough data is sent to exactly fill the host's maximum expected | 407 | * c) Enough data is sent to exactly fill the host's maximum expected |
408 | * IN transaction size. | 408 | * IN transaction size. |
409 | * | 409 | * |
410 | * One of these conditions MUST apply at the end of an IN transaction, | 410 | * One of these conditions MUST apply at the end of an IN transaction, |
411 | * or the transaction will not be considered complete by the host. If | 411 | * or the transaction will not be considered complete by the host. If |
412 | * none of (a)..(c) already applies, then we must force (a) to apply | 412 | * none of (a)..(c) already applies, then we must force (a) to apply |
413 | * by explicitly sending an extra zero-length packet. | 413 | * by explicitly sending an extra zero-length packet. |
414 | */ | 414 | */ |
415 | /* IN !a !b !c */ | 415 | /* IN !a !b !c */ |
416 | if (in && len && !(len % ci_ep->ep.maxpacket) && ci_req->req.zero) { | 416 | if (in && len && !(len % ci_ep->ep.maxpacket) && ci_req->req.zero) { |
417 | /* | 417 | /* |
418 | * Each endpoint has 2 items allocated, even though typically | 418 | * Each endpoint has 2 items allocated, even though typically |
419 | * only 1 is used at a time since either an IN or an OUT but | 419 | * only 1 is used at a time since either an IN or an OUT but |
420 | * not both is queued. For an IN transaction, item currently | 420 | * not both is queued. For an IN transaction, item currently |
421 | * points at the second of these items, so we know that we | 421 | * points at the second of these items, so we know that we |
422 | * can use the other to transmit the extra zero-length packet. | 422 | * can use the other to transmit the extra zero-length packet. |
423 | */ | 423 | */ |
424 | struct ept_queue_item *other_item = ci_get_qtd(num, 0); | 424 | struct ept_queue_item *other_item = ci_get_qtd(num, 0); |
425 | item->next = (unsigned)other_item; | 425 | item->next = (unsigned)other_item; |
426 | item = other_item; | 426 | item = other_item; |
427 | item->info = INFO_ACTIVE; | 427 | item->info = INFO_ACTIVE; |
428 | } | 428 | } |
429 | 429 | ||
430 | item->next = TERMINATE; | 430 | item->next = TERMINATE; |
431 | item->info |= INFO_IOC; | 431 | item->info |= INFO_IOC; |
432 | 432 | ||
433 | ci_flush_qtd(num); | 433 | ci_flush_qtd(num); |
434 | 434 | ||
435 | DBG("ept%d %s queue len %x, req %p, buffer %p\n", | 435 | DBG("ept%d %s queue len %x, req %p, buffer %p\n", |
436 | num, in ? "in" : "out", len, ci_req, ci_req->hw_buf); | 436 | num, in ? "in" : "out", len, ci_req, ci_req->hw_buf); |
437 | ci_flush_qh(num); | 437 | ci_flush_qh(num); |
438 | 438 | ||
439 | if (in) | 439 | if (in) |
440 | bit = EPT_TX(num); | 440 | bit = EPT_TX(num); |
441 | else | 441 | else |
442 | bit = EPT_RX(num); | 442 | bit = EPT_RX(num); |
443 | 443 | ||
444 | writel(bit, &udc->epprime); | 444 | writel(bit, &udc->epprime); |
445 | } | 445 | } |
446 | 446 | ||
447 | static int ci_ep_queue(struct usb_ep *ep, | 447 | static int ci_ep_queue(struct usb_ep *ep, |
448 | struct usb_request *req, gfp_t gfp_flags) | 448 | struct usb_request *req, gfp_t gfp_flags) |
449 | { | 449 | { |
450 | struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep); | 450 | struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep); |
451 | struct ci_req *ci_req = container_of(req, struct ci_req, req); | 451 | struct ci_req *ci_req = container_of(req, struct ci_req, req); |
452 | int in, ret; | 452 | int in, ret; |
453 | int __maybe_unused num; | 453 | int __maybe_unused num; |
454 | 454 | ||
455 | num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | 455 | num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; |
456 | in = (ci_ep->desc->bEndpointAddress & USB_DIR_IN) != 0; | 456 | in = (ci_ep->desc->bEndpointAddress & USB_DIR_IN) != 0; |
457 | 457 | ||
458 | if (!num && ci_ep->req_primed) { | 458 | if (!num && ci_ep->req_primed) { |
459 | /* | 459 | /* |
460 | * The flipping of ep0 between IN and OUT relies on | 460 | * The flipping of ep0 between IN and OUT relies on |
461 | * ci_ep_queue consuming the current IN/OUT setting | 461 | * ci_ep_queue consuming the current IN/OUT setting |
462 | * immediately. If this is deferred to a later point when the | 462 | * immediately. If this is deferred to a later point when the |
463 | * req is pulled out of ci_req->queue, then the IN/OUT setting | 463 | * req is pulled out of ci_req->queue, then the IN/OUT setting |
464 | * may have been changed since the req was queued, and state | 464 | * may have been changed since the req was queued, and state |
465 | * will get out of sync. This condition doesn't occur today, | 465 | * will get out of sync. This condition doesn't occur today, |
466 | * but could if bugs were introduced later, and this error | 466 | * but could if bugs were introduced later, and this error |
467 | * check will save a lot of debugging time. | 467 | * check will save a lot of debugging time. |
468 | */ | 468 | */ |
469 | printf("%s: ep0 transaction already in progress\n", __func__); | 469 | printf("%s: ep0 transaction already in progress\n", __func__); |
470 | return -EPROTO; | 470 | return -EPROTO; |
471 | } | 471 | } |
472 | 472 | ||
473 | ret = ci_bounce(ci_req, in); | 473 | ret = ci_bounce(ci_req, in); |
474 | if (ret) | 474 | if (ret) |
475 | return ret; | 475 | return ret; |
476 | 476 | ||
477 | DBG("ept%d %s pre-queue req %p, buffer %p\n", | 477 | DBG("ept%d %s pre-queue req %p, buffer %p\n", |
478 | num, in ? "in" : "out", ci_req, ci_req->hw_buf); | 478 | num, in ? "in" : "out", ci_req, ci_req->hw_buf); |
479 | list_add_tail(&ci_req->queue, &ci_ep->queue); | 479 | list_add_tail(&ci_req->queue, &ci_ep->queue); |
480 | 480 | ||
481 | if (!ci_ep->req_primed) | 481 | if (!ci_ep->req_primed) |
482 | ci_ep_submit_next_request(ci_ep); | 482 | ci_ep_submit_next_request(ci_ep); |
483 | 483 | ||
484 | return 0; | 484 | return 0; |
485 | } | 485 | } |
486 | 486 | ||
487 | static void flip_ep0_direction(void) | 487 | static void flip_ep0_direction(void) |
488 | { | 488 | { |
489 | if (ep0_desc.bEndpointAddress == USB_DIR_IN) { | 489 | if (ep0_desc.bEndpointAddress == USB_DIR_IN) { |
490 | DBG("%s: Flipping ep0 to OUT\n", __func__); | 490 | DBG("%s: Flipping ep0 to OUT\n", __func__); |
491 | ep0_desc.bEndpointAddress = 0; | 491 | ep0_desc.bEndpointAddress = 0; |
492 | } else { | 492 | } else { |
493 | DBG("%s: Flipping ep0 to IN\n", __func__); | 493 | DBG("%s: Flipping ep0 to IN\n", __func__); |
494 | ep0_desc.bEndpointAddress = USB_DIR_IN; | 494 | ep0_desc.bEndpointAddress = USB_DIR_IN; |
495 | } | 495 | } |
496 | } | 496 | } |
497 | 497 | ||
498 | static void handle_ep_complete(struct ci_ep *ci_ep) | 498 | static void handle_ep_complete(struct ci_ep *ci_ep) |
499 | { | 499 | { |
500 | struct ept_queue_item *item; | 500 | struct ept_queue_item *item; |
501 | int num, in, len; | 501 | int num, in, len; |
502 | struct ci_req *ci_req; | 502 | struct ci_req *ci_req; |
503 | 503 | ||
504 | num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | 504 | num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; |
505 | in = (ci_ep->desc->bEndpointAddress & USB_DIR_IN) != 0; | 505 | in = (ci_ep->desc->bEndpointAddress & USB_DIR_IN) != 0; |
506 | item = ci_get_qtd(num, in); | 506 | item = ci_get_qtd(num, in); |
507 | ci_invalidate_qtd(num); | 507 | ci_invalidate_qtd(num); |
508 | 508 | ||
509 | len = (item->info >> 16) & 0x7fff; | 509 | len = (item->info >> 16) & 0x7fff; |
510 | if (item->info & 0xff) | 510 | if (item->info & 0xff) |
511 | printf("EP%d/%s FAIL info=%x pg0=%x\n", | 511 | printf("EP%d/%s FAIL info=%x pg0=%x\n", |
512 | num, in ? "in" : "out", item->info, item->page0); | 512 | num, in ? "in" : "out", item->info, item->page0); |
513 | 513 | ||
514 | ci_req = list_first_entry(&ci_ep->queue, struct ci_req, queue); | 514 | ci_req = list_first_entry(&ci_ep->queue, struct ci_req, queue); |
515 | list_del_init(&ci_req->queue); | 515 | list_del_init(&ci_req->queue); |
516 | ci_ep->req_primed = false; | 516 | ci_ep->req_primed = false; |
517 | 517 | ||
518 | if (!list_empty(&ci_ep->queue)) | 518 | if (!list_empty(&ci_ep->queue)) |
519 | ci_ep_submit_next_request(ci_ep); | 519 | ci_ep_submit_next_request(ci_ep); |
520 | 520 | ||
521 | ci_req->req.actual = ci_req->req.length - len; | 521 | ci_req->req.actual = ci_req->req.length - len; |
522 | ci_debounce(ci_req, in); | 522 | ci_debounce(ci_req, in); |
523 | 523 | ||
524 | DBG("ept%d %s req %p, complete %x\n", | 524 | DBG("ept%d %s req %p, complete %x\n", |
525 | num, in ? "in" : "out", ci_req, len); | 525 | num, in ? "in" : "out", ci_req, len); |
526 | if (num != 0 || controller.ep0_data_phase) | 526 | if (num != 0 || controller.ep0_data_phase) |
527 | ci_req->req.complete(&ci_ep->ep, &ci_req->req); | 527 | ci_req->req.complete(&ci_ep->ep, &ci_req->req); |
528 | if (num == 0 && controller.ep0_data_phase) { | 528 | if (num == 0 && controller.ep0_data_phase) { |
529 | /* | 529 | /* |
530 | * Data Stage is complete, so flip ep0 dir for Status Stage, | 530 | * Data Stage is complete, so flip ep0 dir for Status Stage, |
531 | * which always transfers a packet in the opposite direction. | 531 | * which always transfers a packet in the opposite direction. |
532 | */ | 532 | */ |
533 | DBG("%s: flip ep0 dir for Status Stage\n", __func__); | 533 | DBG("%s: flip ep0 dir for Status Stage\n", __func__); |
534 | flip_ep0_direction(); | 534 | flip_ep0_direction(); |
535 | controller.ep0_data_phase = false; | 535 | controller.ep0_data_phase = false; |
536 | ci_req->req.length = 0; | 536 | ci_req->req.length = 0; |
537 | usb_ep_queue(&ci_ep->ep, &ci_req->req, 0); | 537 | usb_ep_queue(&ci_ep->ep, &ci_req->req, 0); |
538 | } | 538 | } |
539 | } | 539 | } |
540 | 540 | ||
541 | #define SETUP(type, request) (((type) << 8) | (request)) | 541 | #define SETUP(type, request) (((type) << 8) | (request)) |
542 | 542 | ||
543 | static void handle_setup(void) | 543 | static void handle_setup(void) |
544 | { | 544 | { |
545 | struct ci_ep *ci_ep = &controller.ep[0]; | 545 | struct ci_ep *ci_ep = &controller.ep[0]; |
546 | struct ci_req *ci_req; | 546 | struct ci_req *ci_req; |
547 | struct usb_request *req; | 547 | struct usb_request *req; |
548 | struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; | 548 | struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; |
549 | struct ept_queue_head *head; | 549 | struct ept_queue_head *head; |
550 | struct usb_ctrlrequest r; | 550 | struct usb_ctrlrequest r; |
551 | int status = 0; | 551 | int status = 0; |
552 | int num, in, _num, _in, i; | 552 | int num, in, _num, _in, i; |
553 | char *buf; | 553 | char *buf; |
554 | 554 | ||
555 | ci_req = controller.ep0_req; | 555 | ci_req = controller.ep0_req; |
556 | req = &ci_req->req; | 556 | req = &ci_req->req; |
557 | head = ci_get_qh(0, 0); /* EP0 OUT */ | 557 | head = ci_get_qh(0, 0); /* EP0 OUT */ |
558 | 558 | ||
559 | ci_invalidate_qh(0); | 559 | ci_invalidate_qh(0); |
560 | memcpy(&r, head->setup_data, sizeof(struct usb_ctrlrequest)); | 560 | memcpy(&r, head->setup_data, sizeof(struct usb_ctrlrequest)); |
561 | #ifdef CONFIG_CI_UDC_HAS_HOSTPC | 561 | #ifdef CONFIG_CI_UDC_HAS_HOSTPC |
562 | writel(EPT_RX(0), &udc->epsetupstat); | 562 | writel(EPT_RX(0), &udc->epsetupstat); |
563 | #else | 563 | #else |
564 | writel(EPT_RX(0), &udc->epstat); | 564 | writel(EPT_RX(0), &udc->epstat); |
565 | #endif | 565 | #endif |
566 | DBG("handle setup %s, %x, %x index %x value %x length %x\n", | 566 | DBG("handle setup %s, %x, %x index %x value %x length %x\n", |
567 | reqname(r.bRequest), r.bRequestType, r.bRequest, r.wIndex, | 567 | reqname(r.bRequest), r.bRequestType, r.bRequest, r.wIndex, |
568 | r.wValue, r.wLength); | 568 | r.wValue, r.wLength); |
569 | 569 | ||
570 | /* Set EP0 dir for Data Stage based on Setup Stage data */ | 570 | /* Set EP0 dir for Data Stage based on Setup Stage data */ |
571 | if (r.bRequestType & USB_DIR_IN) { | 571 | if (r.bRequestType & USB_DIR_IN) { |
572 | DBG("%s: Set ep0 to IN for Data Stage\n", __func__); | 572 | DBG("%s: Set ep0 to IN for Data Stage\n", __func__); |
573 | ep0_desc.bEndpointAddress = USB_DIR_IN; | 573 | ep0_desc.bEndpointAddress = USB_DIR_IN; |
574 | } else { | 574 | } else { |
575 | DBG("%s: Set ep0 to OUT for Data Stage\n", __func__); | 575 | DBG("%s: Set ep0 to OUT for Data Stage\n", __func__); |
576 | ep0_desc.bEndpointAddress = 0; | 576 | ep0_desc.bEndpointAddress = 0; |
577 | } | 577 | } |
578 | if (r.wLength) { | 578 | if (r.wLength) { |
579 | controller.ep0_data_phase = true; | 579 | controller.ep0_data_phase = true; |
580 | } else { | 580 | } else { |
581 | /* 0 length -> no Data Stage. Flip dir for Status Stage */ | 581 | /* 0 length -> no Data Stage. Flip dir for Status Stage */ |
582 | DBG("%s: 0 length: flip ep0 dir for Status Stage\n", __func__); | 582 | DBG("%s: 0 length: flip ep0 dir for Status Stage\n", __func__); |
583 | flip_ep0_direction(); | 583 | flip_ep0_direction(); |
584 | controller.ep0_data_phase = false; | 584 | controller.ep0_data_phase = false; |
585 | } | 585 | } |
586 | 586 | ||
587 | list_del_init(&ci_req->queue); | 587 | list_del_init(&ci_req->queue); |
588 | ci_ep->req_primed = false; | 588 | ci_ep->req_primed = false; |
589 | 589 | ||
590 | switch (SETUP(r.bRequestType, r.bRequest)) { | 590 | switch (SETUP(r.bRequestType, r.bRequest)) { |
591 | case SETUP(USB_RECIP_ENDPOINT, USB_REQ_CLEAR_FEATURE): | 591 | case SETUP(USB_RECIP_ENDPOINT, USB_REQ_CLEAR_FEATURE): |
592 | _num = r.wIndex & 15; | 592 | _num = r.wIndex & 15; |
593 | _in = !!(r.wIndex & 0x80); | 593 | _in = !!(r.wIndex & 0x80); |
594 | 594 | ||
595 | if ((r.wValue == 0) && (r.wLength == 0)) { | 595 | if ((r.wValue == 0) && (r.wLength == 0)) { |
596 | req->length = 0; | 596 | req->length = 0; |
597 | for (i = 0; i < NUM_ENDPOINTS; i++) { | 597 | for (i = 0; i < NUM_ENDPOINTS; i++) { |
598 | struct ci_ep *ep = &controller.ep[i]; | 598 | struct ci_ep *ep = &controller.ep[i]; |
599 | 599 | ||
600 | if (!ep->desc) | 600 | if (!ep->desc) |
601 | continue; | 601 | continue; |
602 | num = ep->desc->bEndpointAddress | 602 | num = ep->desc->bEndpointAddress |
603 | & USB_ENDPOINT_NUMBER_MASK; | 603 | & USB_ENDPOINT_NUMBER_MASK; |
604 | in = (ep->desc->bEndpointAddress | 604 | in = (ep->desc->bEndpointAddress |
605 | & USB_DIR_IN) != 0; | 605 | & USB_DIR_IN) != 0; |
606 | if ((num == _num) && (in == _in)) { | 606 | if ((num == _num) && (in == _in)) { |
607 | ep_enable(num, in, ep->ep.maxpacket); | 607 | ep_enable(num, in, ep->ep.maxpacket); |
608 | usb_ep_queue(controller.gadget.ep0, | 608 | usb_ep_queue(controller.gadget.ep0, |
609 | req, 0); | 609 | req, 0); |
610 | break; | 610 | break; |
611 | } | 611 | } |
612 | } | 612 | } |
613 | } | 613 | } |
614 | return; | 614 | return; |
615 | 615 | ||
616 | case SETUP(USB_RECIP_DEVICE, USB_REQ_SET_ADDRESS): | 616 | case SETUP(USB_RECIP_DEVICE, USB_REQ_SET_ADDRESS): |
617 | /* | 617 | /* |
618 | * write address delayed (will take effect | 618 | * write address delayed (will take effect |
619 | * after the next IN txn) | 619 | * after the next IN txn) |
620 | */ | 620 | */ |
621 | writel((r.wValue << 25) | (1 << 24), &udc->devaddr); | 621 | writel((r.wValue << 25) | (1 << 24), &udc->devaddr); |
622 | req->length = 0; | 622 | req->length = 0; |
623 | usb_ep_queue(controller.gadget.ep0, req, 0); | 623 | usb_ep_queue(controller.gadget.ep0, req, 0); |
624 | return; | 624 | return; |
625 | 625 | ||
626 | case SETUP(USB_DIR_IN | USB_RECIP_DEVICE, USB_REQ_GET_STATUS): | 626 | case SETUP(USB_DIR_IN | USB_RECIP_DEVICE, USB_REQ_GET_STATUS): |
627 | req->length = 2; | 627 | req->length = 2; |
628 | buf = (char *)req->buf; | 628 | buf = (char *)req->buf; |
629 | buf[0] = 1 << USB_DEVICE_SELF_POWERED; | 629 | buf[0] = 1 << USB_DEVICE_SELF_POWERED; |
630 | buf[1] = 0; | 630 | buf[1] = 0; |
631 | usb_ep_queue(controller.gadget.ep0, req, 0); | 631 | usb_ep_queue(controller.gadget.ep0, req, 0); |
632 | return; | 632 | return; |
633 | } | 633 | } |
634 | /* pass request up to the gadget driver */ | 634 | /* pass request up to the gadget driver */ |
635 | if (controller.driver) | 635 | if (controller.driver) |
636 | status = controller.driver->setup(&controller.gadget, &r); | 636 | status = controller.driver->setup(&controller.gadget, &r); |
637 | else | 637 | else |
638 | status = -ENODEV; | 638 | status = -ENODEV; |
639 | 639 | ||
640 | if (!status) | 640 | if (!status) |
641 | return; | 641 | return; |
642 | DBG("STALL reqname %s type %x value %x, index %x\n", | 642 | DBG("STALL reqname %s type %x value %x, index %x\n", |
643 | reqname(r.bRequest), r.bRequestType, r.wValue, r.wIndex); | 643 | reqname(r.bRequest), r.bRequestType, r.wValue, r.wIndex); |
644 | writel((1<<16) | (1 << 0), &udc->epctrl[0]); | 644 | writel((1<<16) | (1 << 0), &udc->epctrl[0]); |
645 | } | 645 | } |
646 | 646 | ||
647 | static void stop_activity(void) | 647 | static void stop_activity(void) |
648 | { | 648 | { |
649 | int i, num, in; | 649 | int i, num, in; |
650 | struct ept_queue_head *head; | 650 | struct ept_queue_head *head; |
651 | struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; | 651 | struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; |
652 | writel(readl(&udc->epcomp), &udc->epcomp); | 652 | writel(readl(&udc->epcomp), &udc->epcomp); |
653 | #ifdef CONFIG_CI_UDC_HAS_HOSTPC | 653 | #ifdef CONFIG_CI_UDC_HAS_HOSTPC |
654 | writel(readl(&udc->epsetupstat), &udc->epsetupstat); | 654 | writel(readl(&udc->epsetupstat), &udc->epsetupstat); |
655 | #endif | 655 | #endif |
656 | writel(readl(&udc->epstat), &udc->epstat); | 656 | writel(readl(&udc->epstat), &udc->epstat); |
657 | writel(0xffffffff, &udc->epflush); | 657 | writel(0xffffffff, &udc->epflush); |
658 | 658 | ||
659 | /* error out any pending reqs */ | 659 | /* error out any pending reqs */ |
660 | for (i = 0; i < NUM_ENDPOINTS; i++) { | 660 | for (i = 0; i < NUM_ENDPOINTS; i++) { |
661 | if (i != 0) | 661 | if (i != 0) |
662 | writel(0, &udc->epctrl[i]); | 662 | writel(0, &udc->epctrl[i]); |
663 | if (controller.ep[i].desc) { | 663 | if (controller.ep[i].desc) { |
664 | num = controller.ep[i].desc->bEndpointAddress | 664 | num = controller.ep[i].desc->bEndpointAddress |
665 | & USB_ENDPOINT_NUMBER_MASK; | 665 | & USB_ENDPOINT_NUMBER_MASK; |
666 | in = (controller.ep[i].desc->bEndpointAddress | 666 | in = (controller.ep[i].desc->bEndpointAddress |
667 | & USB_DIR_IN) != 0; | 667 | & USB_DIR_IN) != 0; |
668 | head = ci_get_qh(num, in); | 668 | head = ci_get_qh(num, in); |
669 | head->info = INFO_ACTIVE; | 669 | head->info = INFO_ACTIVE; |
670 | ci_flush_qh(num); | 670 | ci_flush_qh(num); |
671 | } | 671 | } |
672 | } | 672 | } |
673 | } | 673 | } |
674 | 674 | ||
675 | void udc_irq(void) | 675 | void udc_irq(void) |
676 | { | 676 | { |
677 | struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; | 677 | struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; |
678 | unsigned n = readl(&udc->usbsts); | 678 | unsigned n = readl(&udc->usbsts); |
679 | writel(n, &udc->usbsts); | 679 | writel(n, &udc->usbsts); |
680 | int bit, i, num, in; | 680 | int bit, i, num, in; |
681 | 681 | ||
682 | n &= (STS_SLI | STS_URI | STS_PCI | STS_UI | STS_UEI); | 682 | n &= (STS_SLI | STS_URI | STS_PCI | STS_UI | STS_UEI); |
683 | if (n == 0) | 683 | if (n == 0) |
684 | return; | 684 | return; |
685 | 685 | ||
686 | if (n & STS_URI) { | 686 | if (n & STS_URI) { |
687 | DBG("-- reset --\n"); | 687 | DBG("-- reset --\n"); |
688 | stop_activity(); | 688 | stop_activity(); |
689 | } | 689 | } |
690 | if (n & STS_SLI) | 690 | if (n & STS_SLI) |
691 | DBG("-- suspend --\n"); | 691 | DBG("-- suspend --\n"); |
692 | 692 | ||
693 | if (n & STS_PCI) { | 693 | if (n & STS_PCI) { |
694 | int max = 64; | 694 | int max = 64; |
695 | int speed = USB_SPEED_FULL; | 695 | int speed = USB_SPEED_FULL; |
696 | 696 | ||
697 | #ifdef CONFIG_CI_UDC_HAS_HOSTPC | 697 | #ifdef CONFIG_CI_UDC_HAS_HOSTPC |
698 | bit = (readl(&udc->hostpc1_devlc) >> 25) & 3; | 698 | bit = (readl(&udc->hostpc1_devlc) >> 25) & 3; |
699 | #else | 699 | #else |
700 | bit = (readl(&udc->portsc) >> 26) & 3; | 700 | bit = (readl(&udc->portsc) >> 26) & 3; |
701 | #endif | 701 | #endif |
702 | DBG("-- portchange %x %s\n", bit, (bit == 2) ? "High" : "Full"); | 702 | DBG("-- portchange %x %s\n", bit, (bit == 2) ? "High" : "Full"); |
703 | if (bit == 2) { | 703 | if (bit == 2) { |
704 | speed = USB_SPEED_HIGH; | 704 | speed = USB_SPEED_HIGH; |
705 | max = 512; | 705 | max = 512; |
706 | } | 706 | } |
707 | controller.gadget.speed = speed; | 707 | controller.gadget.speed = speed; |
708 | for (i = 1; i < NUM_ENDPOINTS; i++) { | 708 | for (i = 1; i < NUM_ENDPOINTS; i++) { |
709 | if (controller.ep[i].ep.maxpacket > max) | 709 | if (controller.ep[i].ep.maxpacket > max) |
710 | controller.ep[i].ep.maxpacket = max; | 710 | controller.ep[i].ep.maxpacket = max; |
711 | } | 711 | } |
712 | } | 712 | } |
713 | 713 | ||
714 | if (n & STS_UEI) | 714 | if (n & STS_UEI) |
715 | printf("<UEI %x>\n", readl(&udc->epcomp)); | 715 | printf("<UEI %x>\n", readl(&udc->epcomp)); |
716 | 716 | ||
717 | if ((n & STS_UI) || (n & STS_UEI)) { | 717 | if ((n & STS_UI) || (n & STS_UEI)) { |
718 | #ifdef CONFIG_CI_UDC_HAS_HOSTPC | 718 | #ifdef CONFIG_CI_UDC_HAS_HOSTPC |
719 | n = readl(&udc->epsetupstat); | 719 | n = readl(&udc->epsetupstat); |
720 | #else | 720 | #else |
721 | n = readl(&udc->epstat); | 721 | n = readl(&udc->epstat); |
722 | #endif | 722 | #endif |
723 | if (n & EPT_RX(0)) | 723 | if (n & EPT_RX(0)) |
724 | handle_setup(); | 724 | handle_setup(); |
725 | 725 | ||
726 | n = readl(&udc->epcomp); | 726 | n = readl(&udc->epcomp); |
727 | if (n != 0) | 727 | if (n != 0) |
728 | writel(n, &udc->epcomp); | 728 | writel(n, &udc->epcomp); |
729 | 729 | ||
730 | for (i = 0; i < NUM_ENDPOINTS && n; i++) { | 730 | for (i = 0; i < NUM_ENDPOINTS && n; i++) { |
731 | if (controller.ep[i].desc) { | 731 | if (controller.ep[i].desc) { |
732 | num = controller.ep[i].desc->bEndpointAddress | 732 | num = controller.ep[i].desc->bEndpointAddress |
733 | & USB_ENDPOINT_NUMBER_MASK; | 733 | & USB_ENDPOINT_NUMBER_MASK; |
734 | in = (controller.ep[i].desc->bEndpointAddress | 734 | in = (controller.ep[i].desc->bEndpointAddress |
735 | & USB_DIR_IN) != 0; | 735 | & USB_DIR_IN) != 0; |
736 | bit = (in) ? EPT_TX(num) : EPT_RX(num); | 736 | bit = (in) ? EPT_TX(num) : EPT_RX(num); |
737 | if (n & bit) | 737 | if (n & bit) |
738 | handle_ep_complete(&controller.ep[i]); | 738 | handle_ep_complete(&controller.ep[i]); |
739 | } | 739 | } |
740 | } | 740 | } |
741 | } | 741 | } |
742 | } | 742 | } |
743 | 743 | ||
744 | int usb_gadget_handle_interrupts(void) | 744 | int usb_gadget_handle_interrupts(void) |
745 | { | 745 | { |
746 | u32 value; | 746 | u32 value; |
747 | struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; | 747 | struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; |
748 | 748 | ||
749 | value = readl(&udc->usbsts); | 749 | value = readl(&udc->usbsts); |
750 | if (value) | 750 | if (value) |
751 | udc_irq(); | 751 | udc_irq(); |
752 | 752 | ||
753 | return value; | 753 | return value; |
754 | } | 754 | } |
755 | 755 | ||
756 | void udc_disconnect(void) | 756 | void udc_disconnect(void) |
757 | { | 757 | { |
758 | struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; | 758 | struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; |
759 | /* disable pullup */ | 759 | /* disable pullup */ |
760 | stop_activity(); | 760 | stop_activity(); |
761 | writel(USBCMD_FS2, &udc->usbcmd); | 761 | writel(USBCMD_FS2, &udc->usbcmd); |
762 | udelay(800); | 762 | udelay(800); |
763 | if (controller.driver) | 763 | if (controller.driver) |
764 | controller.driver->disconnect(&controller.gadget); | 764 | controller.driver->disconnect(&controller.gadget); |
765 | } | 765 | } |
766 | 766 | ||
767 | static int ci_pullup(struct usb_gadget *gadget, int is_on) | 767 | static int ci_pullup(struct usb_gadget *gadget, int is_on) |
768 | { | 768 | { |
769 | struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; | 769 | struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; |
770 | if (is_on) { | 770 | if (is_on) { |
771 | /* RESET */ | 771 | /* RESET */ |
772 | writel(USBCMD_ITC(MICRO_8FRAME) | USBCMD_RST, &udc->usbcmd); | 772 | writel(USBCMD_ITC(MICRO_8FRAME) | USBCMD_RST, &udc->usbcmd); |
773 | udelay(200); | 773 | udelay(200); |
774 | 774 | ||
775 | writel((unsigned)controller.epts, &udc->epinitaddr); | 775 | writel((unsigned)controller.epts, &udc->epinitaddr); |
776 | 776 | ||
777 | /* select DEVICE mode */ | 777 | /* select DEVICE mode */ |
778 | writel(USBMODE_DEVICE, &udc->usbmode); | 778 | writel(USBMODE_DEVICE, &udc->usbmode); |
779 | 779 | ||
780 | #if !defined(CONFIG_USB_GADGET_DUALSPEED) | ||
781 | /* Port force Full-Speed Connect */ | ||
782 | setbits_le32(&udc->portsc, PFSC); | ||
783 | #endif | ||
784 | |||
780 | writel(0xffffffff, &udc->epflush); | 785 | writel(0xffffffff, &udc->epflush); |
781 | 786 | ||
782 | /* Turn on the USB connection by enabling the pullup resistor */ | 787 | /* Turn on the USB connection by enabling the pullup resistor */ |
783 | writel(USBCMD_ITC(MICRO_8FRAME) | USBCMD_RUN, &udc->usbcmd); | 788 | writel(USBCMD_ITC(MICRO_8FRAME) | USBCMD_RUN, &udc->usbcmd); |
784 | } else { | 789 | } else { |
785 | udc_disconnect(); | 790 | udc_disconnect(); |
786 | } | 791 | } |
787 | 792 | ||
788 | return 0; | 793 | return 0; |
789 | } | 794 | } |
790 | 795 | ||
791 | static int ci_udc_probe(void) | 796 | static int ci_udc_probe(void) |
792 | { | 797 | { |
793 | struct ept_queue_head *head; | 798 | struct ept_queue_head *head; |
794 | int i; | 799 | int i; |
795 | 800 | ||
796 | const int num = 2 * NUM_ENDPOINTS; | 801 | const int num = 2 * NUM_ENDPOINTS; |
797 | 802 | ||
798 | const int eplist_min_align = 4096; | 803 | const int eplist_min_align = 4096; |
799 | const int eplist_align = roundup(eplist_min_align, ARCH_DMA_MINALIGN); | 804 | const int eplist_align = roundup(eplist_min_align, ARCH_DMA_MINALIGN); |
800 | const int eplist_raw_sz = num * sizeof(struct ept_queue_head); | 805 | const int eplist_raw_sz = num * sizeof(struct ept_queue_head); |
801 | const int eplist_sz = roundup(eplist_raw_sz, ARCH_DMA_MINALIGN); | 806 | const int eplist_sz = roundup(eplist_raw_sz, ARCH_DMA_MINALIGN); |
802 | 807 | ||
803 | /* The QH list must be aligned to 4096 bytes. */ | 808 | /* The QH list must be aligned to 4096 bytes. */ |
804 | controller.epts = memalign(eplist_align, eplist_sz); | 809 | controller.epts = memalign(eplist_align, eplist_sz); |
805 | if (!controller.epts) | 810 | if (!controller.epts) |
806 | return -ENOMEM; | 811 | return -ENOMEM; |
807 | memset(controller.epts, 0, eplist_sz); | 812 | memset(controller.epts, 0, eplist_sz); |
808 | 813 | ||
809 | controller.items_mem = memalign(ILIST_ALIGN, ILIST_SZ); | 814 | controller.items_mem = memalign(ILIST_ALIGN, ILIST_SZ); |
810 | if (!controller.items_mem) { | 815 | if (!controller.items_mem) { |
811 | free(controller.epts); | 816 | free(controller.epts); |
812 | return -ENOMEM; | 817 | return -ENOMEM; |
813 | } | 818 | } |
814 | memset(controller.items_mem, 0, ILIST_SZ); | 819 | memset(controller.items_mem, 0, ILIST_SZ); |
815 | 820 | ||
816 | for (i = 0; i < 2 * NUM_ENDPOINTS; i++) { | 821 | for (i = 0; i < 2 * NUM_ENDPOINTS; i++) { |
817 | /* | 822 | /* |
818 | * Configure QH for each endpoint. The structure of the QH list | 823 | * Configure QH for each endpoint. The structure of the QH list |
819 | * is such that each two subsequent fields, N and N+1 where N is | 824 | * is such that each two subsequent fields, N and N+1 where N is |
820 | * even, in the QH list represent QH for one endpoint. The Nth | 825 | * even, in the QH list represent QH for one endpoint. The Nth |
821 | * entry represents OUT configuration and the N+1th entry does | 826 | * entry represents OUT configuration and the N+1th entry does |
822 | * represent IN configuration of the endpoint. | 827 | * represent IN configuration of the endpoint. |
823 | */ | 828 | */ |
824 | head = controller.epts + i; | 829 | head = controller.epts + i; |
825 | if (i < 2) | 830 | if (i < 2) |
826 | head->config = CONFIG_MAX_PKT(EP0_MAX_PACKET_SIZE) | 831 | head->config = CONFIG_MAX_PKT(EP0_MAX_PACKET_SIZE) |
827 | | CONFIG_ZLT | CONFIG_IOS; | 832 | | CONFIG_ZLT | CONFIG_IOS; |
828 | else | 833 | else |
829 | head->config = CONFIG_MAX_PKT(EP_MAX_PACKET_SIZE) | 834 | head->config = CONFIG_MAX_PKT(EP_MAX_PACKET_SIZE) |
830 | | CONFIG_ZLT; | 835 | | CONFIG_ZLT; |
831 | head->next = TERMINATE; | 836 | head->next = TERMINATE; |
832 | head->info = 0; | 837 | head->info = 0; |
833 | 838 | ||
834 | if (i & 1) { | 839 | if (i & 1) { |
835 | ci_flush_qh(i / 2); | 840 | ci_flush_qh(i / 2); |
836 | ci_flush_qtd(i / 2); | 841 | ci_flush_qtd(i / 2); |
837 | } | 842 | } |
838 | } | 843 | } |
839 | 844 | ||
840 | INIT_LIST_HEAD(&controller.gadget.ep_list); | 845 | INIT_LIST_HEAD(&controller.gadget.ep_list); |
841 | 846 | ||
842 | /* Init EP 0 */ | 847 | /* Init EP 0 */ |
843 | memcpy(&controller.ep[0].ep, &ci_ep_init[0], sizeof(*ci_ep_init)); | 848 | memcpy(&controller.ep[0].ep, &ci_ep_init[0], sizeof(*ci_ep_init)); |
844 | controller.ep[0].desc = &ep0_desc; | 849 | controller.ep[0].desc = &ep0_desc; |
845 | INIT_LIST_HEAD(&controller.ep[0].queue); | 850 | INIT_LIST_HEAD(&controller.ep[0].queue); |
846 | controller.ep[0].req_primed = false; | 851 | controller.ep[0].req_primed = false; |
847 | controller.gadget.ep0 = &controller.ep[0].ep; | 852 | controller.gadget.ep0 = &controller.ep[0].ep; |
848 | INIT_LIST_HEAD(&controller.gadget.ep0->ep_list); | 853 | INIT_LIST_HEAD(&controller.gadget.ep0->ep_list); |
849 | 854 | ||
850 | /* Init EP 1..n */ | 855 | /* Init EP 1..n */ |
851 | for (i = 1; i < NUM_ENDPOINTS; i++) { | 856 | for (i = 1; i < NUM_ENDPOINTS; i++) { |
852 | memcpy(&controller.ep[i].ep, &ci_ep_init[1], | 857 | memcpy(&controller.ep[i].ep, &ci_ep_init[1], |
853 | sizeof(*ci_ep_init)); | 858 | sizeof(*ci_ep_init)); |
854 | INIT_LIST_HEAD(&controller.ep[i].queue); | 859 | INIT_LIST_HEAD(&controller.ep[i].queue); |
855 | controller.ep[i].req_primed = false; | 860 | controller.ep[i].req_primed = false; |
856 | list_add_tail(&controller.ep[i].ep.ep_list, | 861 | list_add_tail(&controller.ep[i].ep.ep_list, |
857 | &controller.gadget.ep_list); | 862 | &controller.gadget.ep_list); |
858 | } | 863 | } |
859 | 864 | ||
860 | ci_ep_alloc_request(&controller.ep[0].ep, 0); | 865 | ci_ep_alloc_request(&controller.ep[0].ep, 0); |
861 | if (!controller.ep0_req) { | 866 | if (!controller.ep0_req) { |
862 | free(controller.items_mem); | 867 | free(controller.items_mem); |
863 | free(controller.epts); | 868 | free(controller.epts); |
864 | return -ENOMEM; | 869 | return -ENOMEM; |
865 | } | 870 | } |
866 | 871 | ||
867 | return 0; | 872 | return 0; |
868 | } | 873 | } |
869 | 874 | ||
870 | int usb_gadget_register_driver(struct usb_gadget_driver *driver) | 875 | int usb_gadget_register_driver(struct usb_gadget_driver *driver) |
871 | { | 876 | { |
872 | int ret; | 877 | int ret; |
873 | 878 | ||
874 | if (!driver) | 879 | if (!driver) |
875 | return -EINVAL; | 880 | return -EINVAL; |
876 | if (!driver->bind || !driver->setup || !driver->disconnect) | 881 | if (!driver->bind || !driver->setup || !driver->disconnect) |
877 | return -EINVAL; | 882 | return -EINVAL; |
878 | if (driver->speed != USB_SPEED_FULL && driver->speed != USB_SPEED_HIGH) | 883 | if (driver->speed != USB_SPEED_FULL && driver->speed != USB_SPEED_HIGH) |
879 | return -EINVAL; | 884 | return -EINVAL; |
880 | 885 | ||
881 | ret = usb_lowlevel_init(0, USB_INIT_DEVICE, (void **)&controller.ctrl); | 886 | ret = usb_lowlevel_init(0, USB_INIT_DEVICE, (void **)&controller.ctrl); |
882 | if (ret) | 887 | if (ret) |
883 | return ret; | 888 | return ret; |
884 | 889 | ||
885 | ret = ci_udc_probe(); | 890 | ret = ci_udc_probe(); |
886 | #if defined(CONFIG_USB_EHCI_MX6) || defined(CONFIG_USB_EHCI_MXS) | 891 | #if defined(CONFIG_USB_EHCI_MX6) || defined(CONFIG_USB_EHCI_MXS) |
887 | /* | 892 | /* |
888 | * FIXME: usb_lowlevel_init()->ehci_hcd_init() should be doing all | 893 | * FIXME: usb_lowlevel_init()->ehci_hcd_init() should be doing all |
889 | * HW-specific initialization, e.g. ULPI-vs-UTMI PHY selection | 894 | * HW-specific initialization, e.g. ULPI-vs-UTMI PHY selection |
890 | */ | 895 | */ |
891 | if (!ret) { | 896 | if (!ret) { |
892 | struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; | 897 | struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; |
893 | 898 | ||
894 | /* select ULPI phy */ | 899 | /* select ULPI phy */ |
895 | writel(PTS(PTS_ENABLE) | PFSC, &udc->portsc); | 900 | writel(PTS(PTS_ENABLE) | PFSC, &udc->portsc); |
896 | } | 901 | } |
897 | #endif | 902 | #endif |
898 | 903 | ||
899 | ret = driver->bind(&controller.gadget); | 904 | ret = driver->bind(&controller.gadget); |
900 | if (ret) { | 905 | if (ret) { |
901 | DBG("driver->bind() returned %d\n", ret); | 906 | DBG("driver->bind() returned %d\n", ret); |
902 | return ret; | 907 | return ret; |
903 | } | 908 | } |
904 | controller.driver = driver; | 909 | controller.driver = driver; |
905 | 910 | ||
906 | return 0; | 911 | return 0; |
907 | } | 912 | } |
908 | 913 | ||
909 | int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | 914 | int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) |
910 | { | 915 | { |
911 | udc_disconnect(); | 916 | udc_disconnect(); |
912 | 917 | ||
913 | driver->unbind(&controller.gadget); | 918 | driver->unbind(&controller.gadget); |
914 | controller.driver = NULL; | 919 | controller.driver = NULL; |
915 | 920 | ||
916 | ci_ep_free_request(&controller.ep[0].ep, &controller.ep0_req->req); | 921 | ci_ep_free_request(&controller.ep[0].ep, &controller.ep0_req->req); |
917 | free(controller.items_mem); | 922 | free(controller.items_mem); |
918 | free(controller.epts); | 923 | free(controller.epts); |
919 | 924 | ||
920 | return 0; | 925 | return 0; |
921 | } | 926 | } |
922 | 927 | ||
923 | bool dfu_usb_get_reset(void) | 928 | bool dfu_usb_get_reset(void) |
924 | { | 929 | { |
925 | struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; | 930 | struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; |
926 | 931 | ||
927 | return !!(readl(&udc->usbsts) & STS_URI); | 932 | return !!(readl(&udc->usbsts) & STS_URI); |
928 | } | 933 | } |
929 | 934 |
drivers/usb/gadget/f_dfu.c
1 | /* | 1 | /* |
2 | * f_dfu.c -- Device Firmware Update USB function | 2 | * f_dfu.c -- Device Firmware Update USB function |
3 | * | 3 | * |
4 | * Copyright (C) 2012 Samsung Electronics | 4 | * Copyright (C) 2012 Samsung Electronics |
5 | * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com> | 5 | * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com> |
6 | * Lukasz Majewski <l.majewski@samsung.com> | 6 | * Lukasz Majewski <l.majewski@samsung.com> |
7 | * | 7 | * |
8 | * Based on OpenMoko u-boot: drivers/usb/usbdfu.c | 8 | * Based on OpenMoko u-boot: drivers/usb/usbdfu.c |
9 | * (C) 2007 by OpenMoko, Inc. | 9 | * (C) 2007 by OpenMoko, Inc. |
10 | * Author: Harald Welte <laforge@openmoko.org> | 10 | * Author: Harald Welte <laforge@openmoko.org> |
11 | * | 11 | * |
12 | * based on existing SAM7DFU code from OpenPCD: | 12 | * based on existing SAM7DFU code from OpenPCD: |
13 | * (C) Copyright 2006 by Harald Welte <hwelte at hmw-consulting.de> | 13 | * (C) Copyright 2006 by Harald Welte <hwelte at hmw-consulting.de> |
14 | * | 14 | * |
15 | * SPDX-License-Identifier: GPL-2.0+ | 15 | * SPDX-License-Identifier: GPL-2.0+ |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <errno.h> | 18 | #include <errno.h> |
19 | #include <common.h> | 19 | #include <common.h> |
20 | #include <malloc.h> | 20 | #include <malloc.h> |
21 | 21 | ||
22 | #include <linux/usb/ch9.h> | 22 | #include <linux/usb/ch9.h> |
23 | #include <linux/usb/gadget.h> | 23 | #include <linux/usb/gadget.h> |
24 | #include <linux/usb/composite.h> | 24 | #include <linux/usb/composite.h> |
25 | 25 | ||
26 | #include <dfu.h> | 26 | #include <dfu.h> |
27 | #include <g_dnl.h> | 27 | #include <g_dnl.h> |
28 | #include "f_dfu.h" | 28 | #include "f_dfu.h" |
29 | 29 | ||
30 | struct f_dfu { | 30 | struct f_dfu { |
31 | struct usb_function usb_function; | 31 | struct usb_function usb_function; |
32 | 32 | ||
33 | struct usb_descriptor_header **function; | 33 | struct usb_descriptor_header **function; |
34 | struct usb_string *strings; | 34 | struct usb_string *strings; |
35 | 35 | ||
36 | /* when configured, we have one config */ | 36 | /* when configured, we have one config */ |
37 | u8 config; | 37 | u8 config; |
38 | u8 altsetting; | 38 | u8 altsetting; |
39 | enum dfu_state dfu_state; | 39 | enum dfu_state dfu_state; |
40 | unsigned int dfu_status; | 40 | unsigned int dfu_status; |
41 | 41 | ||
42 | /* Send/received block number is handy for data integrity check */ | 42 | /* Send/received block number is handy for data integrity check */ |
43 | int blk_seq_num; | 43 | int blk_seq_num; |
44 | unsigned int poll_timeout; | 44 | unsigned int poll_timeout; |
45 | }; | 45 | }; |
46 | 46 | ||
47 | typedef int (*dfu_state_fn) (struct f_dfu *, | 47 | typedef int (*dfu_state_fn) (struct f_dfu *, |
48 | const struct usb_ctrlrequest *, | 48 | const struct usb_ctrlrequest *, |
49 | struct usb_gadget *, | 49 | struct usb_gadget *, |
50 | struct usb_request *); | 50 | struct usb_request *); |
51 | 51 | ||
52 | static inline struct f_dfu *func_to_dfu(struct usb_function *f) | 52 | static inline struct f_dfu *func_to_dfu(struct usb_function *f) |
53 | { | 53 | { |
54 | return container_of(f, struct f_dfu, usb_function); | 54 | return container_of(f, struct f_dfu, usb_function); |
55 | } | 55 | } |
56 | 56 | ||
57 | static const struct dfu_function_descriptor dfu_func = { | 57 | static const struct dfu_function_descriptor dfu_func = { |
58 | .bLength = sizeof dfu_func, | 58 | .bLength = sizeof dfu_func, |
59 | .bDescriptorType = DFU_DT_FUNC, | 59 | .bDescriptorType = DFU_DT_FUNC, |
60 | .bmAttributes = DFU_BIT_WILL_DETACH | | 60 | .bmAttributes = DFU_BIT_WILL_DETACH | |
61 | DFU_BIT_MANIFESTATION_TOLERANT | | 61 | DFU_BIT_MANIFESTATION_TOLERANT | |
62 | DFU_BIT_CAN_UPLOAD | | 62 | DFU_BIT_CAN_UPLOAD | |
63 | DFU_BIT_CAN_DNLOAD, | 63 | DFU_BIT_CAN_DNLOAD, |
64 | .wDetachTimeOut = 0, | 64 | .wDetachTimeOut = 0, |
65 | .wTransferSize = DFU_USB_BUFSIZ, | 65 | .wTransferSize = DFU_USB_BUFSIZ, |
66 | .bcdDFUVersion = __constant_cpu_to_le16(0x0110), | 66 | .bcdDFUVersion = __constant_cpu_to_le16(0x0110), |
67 | }; | 67 | }; |
68 | 68 | ||
69 | static struct usb_interface_descriptor dfu_intf_runtime = { | 69 | static struct usb_interface_descriptor dfu_intf_runtime = { |
70 | .bLength = sizeof dfu_intf_runtime, | 70 | .bLength = sizeof dfu_intf_runtime, |
71 | .bDescriptorType = USB_DT_INTERFACE, | 71 | .bDescriptorType = USB_DT_INTERFACE, |
72 | .bNumEndpoints = 0, | 72 | .bNumEndpoints = 0, |
73 | .bInterfaceClass = USB_CLASS_APP_SPEC, | 73 | .bInterfaceClass = USB_CLASS_APP_SPEC, |
74 | .bInterfaceSubClass = 1, | 74 | .bInterfaceSubClass = 1, |
75 | .bInterfaceProtocol = 1, | 75 | .bInterfaceProtocol = 1, |
76 | /* .iInterface = DYNAMIC */ | 76 | /* .iInterface = DYNAMIC */ |
77 | }; | 77 | }; |
78 | 78 | ||
79 | static struct usb_descriptor_header *dfu_runtime_descs[] = { | 79 | static struct usb_descriptor_header *dfu_runtime_descs[] = { |
80 | (struct usb_descriptor_header *) &dfu_intf_runtime, | 80 | (struct usb_descriptor_header *) &dfu_intf_runtime, |
81 | NULL, | 81 | NULL, |
82 | }; | 82 | }; |
83 | 83 | ||
84 | static const struct usb_qualifier_descriptor dev_qualifier = { | ||
85 | .bLength = sizeof dev_qualifier, | ||
86 | .bDescriptorType = USB_DT_DEVICE_QUALIFIER, | ||
87 | .bcdUSB = __constant_cpu_to_le16(0x0200), | ||
88 | .bDeviceClass = USB_CLASS_VENDOR_SPEC, | ||
89 | .bNumConfigurations = 1, | ||
90 | }; | ||
91 | |||
92 | static const char dfu_name[] = "Device Firmware Upgrade"; | 84 | static const char dfu_name[] = "Device Firmware Upgrade"; |
93 | 85 | ||
94 | /* | 86 | /* |
95 | * static strings, in UTF-8 | 87 | * static strings, in UTF-8 |
96 | * | 88 | * |
97 | * dfu_generic configuration | 89 | * dfu_generic configuration |
98 | */ | 90 | */ |
99 | static struct usb_string strings_dfu_generic[] = { | 91 | static struct usb_string strings_dfu_generic[] = { |
100 | [0].s = dfu_name, | 92 | [0].s = dfu_name, |
101 | { } /* end of list */ | 93 | { } /* end of list */ |
102 | }; | 94 | }; |
103 | 95 | ||
104 | static struct usb_gadget_strings stringtab_dfu_generic = { | 96 | static struct usb_gadget_strings stringtab_dfu_generic = { |
105 | .language = 0x0409, /* en-us */ | 97 | .language = 0x0409, /* en-us */ |
106 | .strings = strings_dfu_generic, | 98 | .strings = strings_dfu_generic, |
107 | }; | 99 | }; |
108 | 100 | ||
109 | static struct usb_gadget_strings *dfu_generic_strings[] = { | 101 | static struct usb_gadget_strings *dfu_generic_strings[] = { |
110 | &stringtab_dfu_generic, | 102 | &stringtab_dfu_generic, |
111 | NULL, | 103 | NULL, |
112 | }; | 104 | }; |
113 | 105 | ||
114 | /* | 106 | /* |
115 | * usb_function specific | 107 | * usb_function specific |
116 | */ | 108 | */ |
117 | static struct usb_gadget_strings stringtab_dfu = { | 109 | static struct usb_gadget_strings stringtab_dfu = { |
118 | .language = 0x0409, /* en-us */ | 110 | .language = 0x0409, /* en-us */ |
119 | /* | 111 | /* |
120 | * .strings | 112 | * .strings |
121 | * | 113 | * |
122 | * assigned during initialization, | 114 | * assigned during initialization, |
123 | * depends on number of flash entities | 115 | * depends on number of flash entities |
124 | * | 116 | * |
125 | */ | 117 | */ |
126 | }; | 118 | }; |
127 | 119 | ||
128 | static struct usb_gadget_strings *dfu_strings[] = { | 120 | static struct usb_gadget_strings *dfu_strings[] = { |
129 | &stringtab_dfu, | 121 | &stringtab_dfu, |
130 | NULL, | 122 | NULL, |
131 | }; | 123 | }; |
132 | 124 | ||
133 | static void dfu_set_poll_timeout(struct dfu_status *dstat, unsigned int ms) | 125 | static void dfu_set_poll_timeout(struct dfu_status *dstat, unsigned int ms) |
134 | { | 126 | { |
135 | /* | 127 | /* |
136 | * The bwPollTimeout DFU_GETSTATUS request payload provides information | 128 | * The bwPollTimeout DFU_GETSTATUS request payload provides information |
137 | * about minimum time, in milliseconds, that the host should wait before | 129 | * about minimum time, in milliseconds, that the host should wait before |
138 | * sending a subsequent DFU_GETSTATUS request | 130 | * sending a subsequent DFU_GETSTATUS request |
139 | * | 131 | * |
140 | * This permits the device to vary the delay depending on its need to | 132 | * This permits the device to vary the delay depending on its need to |
141 | * erase or program the memory | 133 | * erase or program the memory |
142 | * | 134 | * |
143 | */ | 135 | */ |
144 | 136 | ||
145 | unsigned char *p = (unsigned char *)&ms; | 137 | unsigned char *p = (unsigned char *)&ms; |
146 | 138 | ||
147 | if (!ms || (ms & ~DFU_POLL_TIMEOUT_MASK)) { | 139 | if (!ms || (ms & ~DFU_POLL_TIMEOUT_MASK)) { |
148 | dstat->bwPollTimeout[0] = 0; | 140 | dstat->bwPollTimeout[0] = 0; |
149 | dstat->bwPollTimeout[1] = 0; | 141 | dstat->bwPollTimeout[1] = 0; |
150 | dstat->bwPollTimeout[2] = 0; | 142 | dstat->bwPollTimeout[2] = 0; |
151 | 143 | ||
152 | return; | 144 | return; |
153 | } | 145 | } |
154 | 146 | ||
155 | dstat->bwPollTimeout[0] = *p++; | 147 | dstat->bwPollTimeout[0] = *p++; |
156 | dstat->bwPollTimeout[1] = *p++; | 148 | dstat->bwPollTimeout[1] = *p++; |
157 | dstat->bwPollTimeout[2] = *p; | 149 | dstat->bwPollTimeout[2] = *p; |
158 | } | 150 | } |
159 | 151 | ||
160 | /*-------------------------------------------------------------------------*/ | 152 | /*-------------------------------------------------------------------------*/ |
161 | 153 | ||
162 | static void dnload_request_complete(struct usb_ep *ep, struct usb_request *req) | 154 | static void dnload_request_complete(struct usb_ep *ep, struct usb_request *req) |
163 | { | 155 | { |
164 | struct f_dfu *f_dfu = req->context; | 156 | struct f_dfu *f_dfu = req->context; |
165 | int ret; | 157 | int ret; |
166 | 158 | ||
167 | ret = dfu_write(dfu_get_entity(f_dfu->altsetting), req->buf, | 159 | ret = dfu_write(dfu_get_entity(f_dfu->altsetting), req->buf, |
168 | req->length, f_dfu->blk_seq_num); | 160 | req->length, f_dfu->blk_seq_num); |
169 | if (ret) { | 161 | if (ret) { |
170 | f_dfu->dfu_status = DFU_STATUS_errUNKNOWN; | 162 | f_dfu->dfu_status = DFU_STATUS_errUNKNOWN; |
171 | f_dfu->dfu_state = DFU_STATE_dfuERROR; | 163 | f_dfu->dfu_state = DFU_STATE_dfuERROR; |
172 | } | 164 | } |
173 | } | 165 | } |
174 | 166 | ||
175 | static void dnload_request_flush(struct usb_ep *ep, struct usb_request *req) | 167 | static void dnload_request_flush(struct usb_ep *ep, struct usb_request *req) |
176 | { | 168 | { |
177 | struct f_dfu *f_dfu = req->context; | 169 | struct f_dfu *f_dfu = req->context; |
178 | int ret; | 170 | int ret; |
179 | 171 | ||
180 | ret = dfu_flush(dfu_get_entity(f_dfu->altsetting), req->buf, | 172 | ret = dfu_flush(dfu_get_entity(f_dfu->altsetting), req->buf, |
181 | req->length, f_dfu->blk_seq_num); | 173 | req->length, f_dfu->blk_seq_num); |
182 | if (ret) { | 174 | if (ret) { |
183 | f_dfu->dfu_status = DFU_STATUS_errUNKNOWN; | 175 | f_dfu->dfu_status = DFU_STATUS_errUNKNOWN; |
184 | f_dfu->dfu_state = DFU_STATE_dfuERROR; | 176 | f_dfu->dfu_state = DFU_STATE_dfuERROR; |
185 | } | 177 | } |
186 | } | 178 | } |
187 | 179 | ||
188 | static inline int dfu_get_manifest_timeout(struct dfu_entity *dfu) | 180 | static inline int dfu_get_manifest_timeout(struct dfu_entity *dfu) |
189 | { | 181 | { |
190 | return dfu->poll_timeout ? dfu->poll_timeout(dfu) : | 182 | return dfu->poll_timeout ? dfu->poll_timeout(dfu) : |
191 | DFU_MANIFEST_POLL_TIMEOUT; | 183 | DFU_MANIFEST_POLL_TIMEOUT; |
192 | } | 184 | } |
193 | 185 | ||
194 | static void handle_getstatus(struct usb_request *req) | 186 | static void handle_getstatus(struct usb_request *req) |
195 | { | 187 | { |
196 | struct dfu_status *dstat = (struct dfu_status *)req->buf; | 188 | struct dfu_status *dstat = (struct dfu_status *)req->buf; |
197 | struct f_dfu *f_dfu = req->context; | 189 | struct f_dfu *f_dfu = req->context; |
198 | struct dfu_entity *dfu = dfu_get_entity(f_dfu->altsetting); | 190 | struct dfu_entity *dfu = dfu_get_entity(f_dfu->altsetting); |
199 | 191 | ||
200 | dfu_set_poll_timeout(dstat, 0); | 192 | dfu_set_poll_timeout(dstat, 0); |
201 | 193 | ||
202 | switch (f_dfu->dfu_state) { | 194 | switch (f_dfu->dfu_state) { |
203 | case DFU_STATE_dfuDNLOAD_SYNC: | 195 | case DFU_STATE_dfuDNLOAD_SYNC: |
204 | case DFU_STATE_dfuDNBUSY: | 196 | case DFU_STATE_dfuDNBUSY: |
205 | f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE; | 197 | f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE; |
206 | break; | 198 | break; |
207 | case DFU_STATE_dfuMANIFEST_SYNC: | 199 | case DFU_STATE_dfuMANIFEST_SYNC: |
208 | f_dfu->dfu_state = DFU_STATE_dfuMANIFEST; | 200 | f_dfu->dfu_state = DFU_STATE_dfuMANIFEST; |
209 | break; | 201 | break; |
210 | case DFU_STATE_dfuMANIFEST: | 202 | case DFU_STATE_dfuMANIFEST: |
211 | dfu_set_poll_timeout(dstat, dfu_get_manifest_timeout(dfu)); | 203 | dfu_set_poll_timeout(dstat, dfu_get_manifest_timeout(dfu)); |
212 | break; | 204 | break; |
213 | default: | 205 | default: |
214 | break; | 206 | break; |
215 | } | 207 | } |
216 | 208 | ||
217 | if (f_dfu->poll_timeout) | 209 | if (f_dfu->poll_timeout) |
218 | if (!(f_dfu->blk_seq_num % | 210 | if (!(f_dfu->blk_seq_num % |
219 | (dfu_get_buf_size() / DFU_USB_BUFSIZ))) | 211 | (dfu_get_buf_size() / DFU_USB_BUFSIZ))) |
220 | dfu_set_poll_timeout(dstat, f_dfu->poll_timeout); | 212 | dfu_set_poll_timeout(dstat, f_dfu->poll_timeout); |
221 | 213 | ||
222 | /* send status response */ | 214 | /* send status response */ |
223 | dstat->bStatus = f_dfu->dfu_status; | 215 | dstat->bStatus = f_dfu->dfu_status; |
224 | dstat->bState = f_dfu->dfu_state; | 216 | dstat->bState = f_dfu->dfu_state; |
225 | dstat->iString = 0; | 217 | dstat->iString = 0; |
226 | } | 218 | } |
227 | 219 | ||
228 | static void handle_getstate(struct usb_request *req) | 220 | static void handle_getstate(struct usb_request *req) |
229 | { | 221 | { |
230 | struct f_dfu *f_dfu = req->context; | 222 | struct f_dfu *f_dfu = req->context; |
231 | 223 | ||
232 | ((u8 *)req->buf)[0] = f_dfu->dfu_state; | 224 | ((u8 *)req->buf)[0] = f_dfu->dfu_state; |
233 | req->actual = sizeof(u8); | 225 | req->actual = sizeof(u8); |
234 | } | 226 | } |
235 | 227 | ||
236 | static inline void to_dfu_mode(struct f_dfu *f_dfu) | 228 | static inline void to_dfu_mode(struct f_dfu *f_dfu) |
237 | { | 229 | { |
238 | f_dfu->usb_function.strings = dfu_strings; | 230 | f_dfu->usb_function.strings = dfu_strings; |
239 | f_dfu->usb_function.hs_descriptors = f_dfu->function; | 231 | f_dfu->usb_function.hs_descriptors = f_dfu->function; |
232 | f_dfu->usb_function.descriptors = f_dfu->function; | ||
240 | f_dfu->dfu_state = DFU_STATE_dfuIDLE; | 233 | f_dfu->dfu_state = DFU_STATE_dfuIDLE; |
241 | } | 234 | } |
242 | 235 | ||
243 | static inline void to_runtime_mode(struct f_dfu *f_dfu) | 236 | static inline void to_runtime_mode(struct f_dfu *f_dfu) |
244 | { | 237 | { |
245 | f_dfu->usb_function.strings = NULL; | 238 | f_dfu->usb_function.strings = NULL; |
246 | f_dfu->usb_function.hs_descriptors = dfu_runtime_descs; | 239 | f_dfu->usb_function.hs_descriptors = dfu_runtime_descs; |
240 | f_dfu->usb_function.descriptors = dfu_runtime_descs; | ||
247 | } | 241 | } |
248 | 242 | ||
249 | static int handle_upload(struct usb_request *req, u16 len) | 243 | static int handle_upload(struct usb_request *req, u16 len) |
250 | { | 244 | { |
251 | struct f_dfu *f_dfu = req->context; | 245 | struct f_dfu *f_dfu = req->context; |
252 | 246 | ||
253 | return dfu_read(dfu_get_entity(f_dfu->altsetting), req->buf, | 247 | return dfu_read(dfu_get_entity(f_dfu->altsetting), req->buf, |
254 | req->length, f_dfu->blk_seq_num); | 248 | req->length, f_dfu->blk_seq_num); |
255 | } | 249 | } |
256 | 250 | ||
257 | static int handle_dnload(struct usb_gadget *gadget, u16 len) | 251 | static int handle_dnload(struct usb_gadget *gadget, u16 len) |
258 | { | 252 | { |
259 | struct usb_composite_dev *cdev = get_gadget_data(gadget); | 253 | struct usb_composite_dev *cdev = get_gadget_data(gadget); |
260 | struct usb_request *req = cdev->req; | 254 | struct usb_request *req = cdev->req; |
261 | struct f_dfu *f_dfu = req->context; | 255 | struct f_dfu *f_dfu = req->context; |
262 | 256 | ||
263 | if (len == 0) | 257 | if (len == 0) |
264 | f_dfu->dfu_state = DFU_STATE_dfuMANIFEST_SYNC; | 258 | f_dfu->dfu_state = DFU_STATE_dfuMANIFEST_SYNC; |
265 | 259 | ||
266 | req->complete = dnload_request_complete; | 260 | req->complete = dnload_request_complete; |
267 | 261 | ||
268 | return len; | 262 | return len; |
269 | } | 263 | } |
270 | 264 | ||
271 | /*-------------------------------------------------------------------------*/ | 265 | /*-------------------------------------------------------------------------*/ |
272 | /* DFU state machine */ | 266 | /* DFU state machine */ |
273 | static int state_app_idle(struct f_dfu *f_dfu, | 267 | static int state_app_idle(struct f_dfu *f_dfu, |
274 | const struct usb_ctrlrequest *ctrl, | 268 | const struct usb_ctrlrequest *ctrl, |
275 | struct usb_gadget *gadget, | 269 | struct usb_gadget *gadget, |
276 | struct usb_request *req) | 270 | struct usb_request *req) |
277 | { | 271 | { |
278 | int value = 0; | 272 | int value = 0; |
279 | 273 | ||
280 | switch (ctrl->bRequest) { | 274 | switch (ctrl->bRequest) { |
281 | case USB_REQ_DFU_GETSTATUS: | 275 | case USB_REQ_DFU_GETSTATUS: |
282 | handle_getstatus(req); | 276 | handle_getstatus(req); |
283 | value = RET_STAT_LEN; | 277 | value = RET_STAT_LEN; |
284 | break; | 278 | break; |
285 | case USB_REQ_DFU_GETSTATE: | 279 | case USB_REQ_DFU_GETSTATE: |
286 | handle_getstate(req); | 280 | handle_getstate(req); |
287 | break; | 281 | break; |
288 | case USB_REQ_DFU_DETACH: | 282 | case USB_REQ_DFU_DETACH: |
289 | f_dfu->dfu_state = DFU_STATE_appDETACH; | 283 | f_dfu->dfu_state = DFU_STATE_appDETACH; |
290 | to_dfu_mode(f_dfu); | 284 | to_dfu_mode(f_dfu); |
291 | value = RET_ZLP; | 285 | value = RET_ZLP; |
292 | break; | 286 | break; |
293 | default: | 287 | default: |
294 | value = RET_STALL; | 288 | value = RET_STALL; |
295 | break; | 289 | break; |
296 | } | 290 | } |
297 | 291 | ||
298 | return value; | 292 | return value; |
299 | } | 293 | } |
300 | 294 | ||
301 | static int state_app_detach(struct f_dfu *f_dfu, | 295 | static int state_app_detach(struct f_dfu *f_dfu, |
302 | const struct usb_ctrlrequest *ctrl, | 296 | const struct usb_ctrlrequest *ctrl, |
303 | struct usb_gadget *gadget, | 297 | struct usb_gadget *gadget, |
304 | struct usb_request *req) | 298 | struct usb_request *req) |
305 | { | 299 | { |
306 | int value = 0; | 300 | int value = 0; |
307 | 301 | ||
308 | switch (ctrl->bRequest) { | 302 | switch (ctrl->bRequest) { |
309 | case USB_REQ_DFU_GETSTATUS: | 303 | case USB_REQ_DFU_GETSTATUS: |
310 | handle_getstatus(req); | 304 | handle_getstatus(req); |
311 | value = RET_STAT_LEN; | 305 | value = RET_STAT_LEN; |
312 | break; | 306 | break; |
313 | case USB_REQ_DFU_GETSTATE: | 307 | case USB_REQ_DFU_GETSTATE: |
314 | handle_getstate(req); | 308 | handle_getstate(req); |
315 | break; | 309 | break; |
316 | default: | 310 | default: |
317 | f_dfu->dfu_state = DFU_STATE_appIDLE; | 311 | f_dfu->dfu_state = DFU_STATE_appIDLE; |
318 | value = RET_STALL; | 312 | value = RET_STALL; |
319 | break; | 313 | break; |
320 | } | 314 | } |
321 | 315 | ||
322 | return value; | 316 | return value; |
323 | } | 317 | } |
324 | 318 | ||
325 | static int state_dfu_idle(struct f_dfu *f_dfu, | 319 | static int state_dfu_idle(struct f_dfu *f_dfu, |
326 | const struct usb_ctrlrequest *ctrl, | 320 | const struct usb_ctrlrequest *ctrl, |
327 | struct usb_gadget *gadget, | 321 | struct usb_gadget *gadget, |
328 | struct usb_request *req) | 322 | struct usb_request *req) |
329 | { | 323 | { |
330 | u16 w_value = le16_to_cpu(ctrl->wValue); | 324 | u16 w_value = le16_to_cpu(ctrl->wValue); |
331 | u16 len = le16_to_cpu(ctrl->wLength); | 325 | u16 len = le16_to_cpu(ctrl->wLength); |
332 | int value = 0; | 326 | int value = 0; |
333 | 327 | ||
334 | switch (ctrl->bRequest) { | 328 | switch (ctrl->bRequest) { |
335 | case USB_REQ_DFU_DNLOAD: | 329 | case USB_REQ_DFU_DNLOAD: |
336 | if (len == 0) { | 330 | if (len == 0) { |
337 | f_dfu->dfu_state = DFU_STATE_dfuERROR; | 331 | f_dfu->dfu_state = DFU_STATE_dfuERROR; |
338 | value = RET_STALL; | 332 | value = RET_STALL; |
339 | break; | 333 | break; |
340 | } | 334 | } |
341 | f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC; | 335 | f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC; |
342 | f_dfu->blk_seq_num = w_value; | 336 | f_dfu->blk_seq_num = w_value; |
343 | value = handle_dnload(gadget, len); | 337 | value = handle_dnload(gadget, len); |
344 | break; | 338 | break; |
345 | case USB_REQ_DFU_UPLOAD: | 339 | case USB_REQ_DFU_UPLOAD: |
346 | f_dfu->dfu_state = DFU_STATE_dfuUPLOAD_IDLE; | 340 | f_dfu->dfu_state = DFU_STATE_dfuUPLOAD_IDLE; |
347 | f_dfu->blk_seq_num = 0; | 341 | f_dfu->blk_seq_num = 0; |
348 | value = handle_upload(req, len); | 342 | value = handle_upload(req, len); |
349 | break; | 343 | break; |
350 | case USB_REQ_DFU_ABORT: | 344 | case USB_REQ_DFU_ABORT: |
351 | /* no zlp? */ | 345 | /* no zlp? */ |
352 | value = RET_ZLP; | 346 | value = RET_ZLP; |
353 | break; | 347 | break; |
354 | case USB_REQ_DFU_GETSTATUS: | 348 | case USB_REQ_DFU_GETSTATUS: |
355 | handle_getstatus(req); | 349 | handle_getstatus(req); |
356 | value = RET_STAT_LEN; | 350 | value = RET_STAT_LEN; |
357 | break; | 351 | break; |
358 | case USB_REQ_DFU_GETSTATE: | 352 | case USB_REQ_DFU_GETSTATE: |
359 | handle_getstate(req); | 353 | handle_getstate(req); |
360 | break; | 354 | break; |
361 | case USB_REQ_DFU_DETACH: | 355 | case USB_REQ_DFU_DETACH: |
362 | /* | 356 | /* |
363 | * Proprietary extension: 'detach' from idle mode and | 357 | * Proprietary extension: 'detach' from idle mode and |
364 | * get back to runtime mode in case of USB Reset. As | 358 | * get back to runtime mode in case of USB Reset. As |
365 | * much as I dislike this, we just can't use every USB | 359 | * much as I dislike this, we just can't use every USB |
366 | * bus reset to switch back to runtime mode, since at | 360 | * bus reset to switch back to runtime mode, since at |
367 | * least the Linux USB stack likes to send a number of | 361 | * least the Linux USB stack likes to send a number of |
368 | * resets in a row :( | 362 | * resets in a row :( |
369 | */ | 363 | */ |
370 | f_dfu->dfu_state = | 364 | f_dfu->dfu_state = |
371 | DFU_STATE_dfuMANIFEST_WAIT_RST; | 365 | DFU_STATE_dfuMANIFEST_WAIT_RST; |
372 | to_runtime_mode(f_dfu); | 366 | to_runtime_mode(f_dfu); |
373 | f_dfu->dfu_state = DFU_STATE_appIDLE; | 367 | f_dfu->dfu_state = DFU_STATE_appIDLE; |
374 | 368 | ||
375 | dfu_trigger_detach(); | 369 | dfu_trigger_detach(); |
376 | break; | 370 | break; |
377 | default: | 371 | default: |
378 | f_dfu->dfu_state = DFU_STATE_dfuERROR; | 372 | f_dfu->dfu_state = DFU_STATE_dfuERROR; |
379 | value = RET_STALL; | 373 | value = RET_STALL; |
380 | break; | 374 | break; |
381 | } | 375 | } |
382 | 376 | ||
383 | return value; | 377 | return value; |
384 | } | 378 | } |
385 | 379 | ||
386 | static int state_dfu_dnload_sync(struct f_dfu *f_dfu, | 380 | static int state_dfu_dnload_sync(struct f_dfu *f_dfu, |
387 | const struct usb_ctrlrequest *ctrl, | 381 | const struct usb_ctrlrequest *ctrl, |
388 | struct usb_gadget *gadget, | 382 | struct usb_gadget *gadget, |
389 | struct usb_request *req) | 383 | struct usb_request *req) |
390 | { | 384 | { |
391 | int value = 0; | 385 | int value = 0; |
392 | 386 | ||
393 | switch (ctrl->bRequest) { | 387 | switch (ctrl->bRequest) { |
394 | case USB_REQ_DFU_GETSTATUS: | 388 | case USB_REQ_DFU_GETSTATUS: |
395 | handle_getstatus(req); | 389 | handle_getstatus(req); |
396 | value = RET_STAT_LEN; | 390 | value = RET_STAT_LEN; |
397 | break; | 391 | break; |
398 | case USB_REQ_DFU_GETSTATE: | 392 | case USB_REQ_DFU_GETSTATE: |
399 | handle_getstate(req); | 393 | handle_getstate(req); |
400 | break; | 394 | break; |
401 | default: | 395 | default: |
402 | f_dfu->dfu_state = DFU_STATE_dfuERROR; | 396 | f_dfu->dfu_state = DFU_STATE_dfuERROR; |
403 | value = RET_STALL; | 397 | value = RET_STALL; |
404 | break; | 398 | break; |
405 | } | 399 | } |
406 | 400 | ||
407 | return value; | 401 | return value; |
408 | } | 402 | } |
409 | 403 | ||
410 | static int state_dfu_dnbusy(struct f_dfu *f_dfu, | 404 | static int state_dfu_dnbusy(struct f_dfu *f_dfu, |
411 | const struct usb_ctrlrequest *ctrl, | 405 | const struct usb_ctrlrequest *ctrl, |
412 | struct usb_gadget *gadget, | 406 | struct usb_gadget *gadget, |
413 | struct usb_request *req) | 407 | struct usb_request *req) |
414 | { | 408 | { |
415 | int value = 0; | 409 | int value = 0; |
416 | 410 | ||
417 | switch (ctrl->bRequest) { | 411 | switch (ctrl->bRequest) { |
418 | case USB_REQ_DFU_GETSTATUS: | 412 | case USB_REQ_DFU_GETSTATUS: |
419 | handle_getstatus(req); | 413 | handle_getstatus(req); |
420 | value = RET_STAT_LEN; | 414 | value = RET_STAT_LEN; |
421 | break; | 415 | break; |
422 | default: | 416 | default: |
423 | f_dfu->dfu_state = DFU_STATE_dfuERROR; | 417 | f_dfu->dfu_state = DFU_STATE_dfuERROR; |
424 | value = RET_STALL; | 418 | value = RET_STALL; |
425 | break; | 419 | break; |
426 | } | 420 | } |
427 | 421 | ||
428 | return value; | 422 | return value; |
429 | } | 423 | } |
430 | 424 | ||
431 | static int state_dfu_dnload_idle(struct f_dfu *f_dfu, | 425 | static int state_dfu_dnload_idle(struct f_dfu *f_dfu, |
432 | const struct usb_ctrlrequest *ctrl, | 426 | const struct usb_ctrlrequest *ctrl, |
433 | struct usb_gadget *gadget, | 427 | struct usb_gadget *gadget, |
434 | struct usb_request *req) | 428 | struct usb_request *req) |
435 | { | 429 | { |
436 | u16 w_value = le16_to_cpu(ctrl->wValue); | 430 | u16 w_value = le16_to_cpu(ctrl->wValue); |
437 | u16 len = le16_to_cpu(ctrl->wLength); | 431 | u16 len = le16_to_cpu(ctrl->wLength); |
438 | int value = 0; | 432 | int value = 0; |
439 | 433 | ||
440 | switch (ctrl->bRequest) { | 434 | switch (ctrl->bRequest) { |
441 | case USB_REQ_DFU_DNLOAD: | 435 | case USB_REQ_DFU_DNLOAD: |
442 | f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC; | 436 | f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC; |
443 | f_dfu->blk_seq_num = w_value; | 437 | f_dfu->blk_seq_num = w_value; |
444 | value = handle_dnload(gadget, len); | 438 | value = handle_dnload(gadget, len); |
445 | break; | 439 | break; |
446 | case USB_REQ_DFU_ABORT: | 440 | case USB_REQ_DFU_ABORT: |
447 | f_dfu->dfu_state = DFU_STATE_dfuIDLE; | 441 | f_dfu->dfu_state = DFU_STATE_dfuIDLE; |
448 | value = RET_ZLP; | 442 | value = RET_ZLP; |
449 | break; | 443 | break; |
450 | case USB_REQ_DFU_GETSTATUS: | 444 | case USB_REQ_DFU_GETSTATUS: |
451 | handle_getstatus(req); | 445 | handle_getstatus(req); |
452 | value = RET_STAT_LEN; | 446 | value = RET_STAT_LEN; |
453 | break; | 447 | break; |
454 | case USB_REQ_DFU_GETSTATE: | 448 | case USB_REQ_DFU_GETSTATE: |
455 | handle_getstate(req); | 449 | handle_getstate(req); |
456 | break; | 450 | break; |
457 | default: | 451 | default: |
458 | f_dfu->dfu_state = DFU_STATE_dfuERROR; | 452 | f_dfu->dfu_state = DFU_STATE_dfuERROR; |
459 | value = RET_STALL; | 453 | value = RET_STALL; |
460 | break; | 454 | break; |
461 | } | 455 | } |
462 | 456 | ||
463 | return value; | 457 | return value; |
464 | } | 458 | } |
465 | 459 | ||
466 | static int state_dfu_manifest_sync(struct f_dfu *f_dfu, | 460 | static int state_dfu_manifest_sync(struct f_dfu *f_dfu, |
467 | const struct usb_ctrlrequest *ctrl, | 461 | const struct usb_ctrlrequest *ctrl, |
468 | struct usb_gadget *gadget, | 462 | struct usb_gadget *gadget, |
469 | struct usb_request *req) | 463 | struct usb_request *req) |
470 | { | 464 | { |
471 | int value = 0; | 465 | int value = 0; |
472 | 466 | ||
473 | switch (ctrl->bRequest) { | 467 | switch (ctrl->bRequest) { |
474 | case USB_REQ_DFU_GETSTATUS: | 468 | case USB_REQ_DFU_GETSTATUS: |
475 | /* We're MainfestationTolerant */ | 469 | /* We're MainfestationTolerant */ |
476 | f_dfu->dfu_state = DFU_STATE_dfuMANIFEST; | 470 | f_dfu->dfu_state = DFU_STATE_dfuMANIFEST; |
477 | handle_getstatus(req); | 471 | handle_getstatus(req); |
478 | f_dfu->blk_seq_num = 0; | 472 | f_dfu->blk_seq_num = 0; |
479 | value = RET_STAT_LEN; | 473 | value = RET_STAT_LEN; |
480 | req->complete = dnload_request_flush; | 474 | req->complete = dnload_request_flush; |
481 | break; | 475 | break; |
482 | case USB_REQ_DFU_GETSTATE: | 476 | case USB_REQ_DFU_GETSTATE: |
483 | handle_getstate(req); | 477 | handle_getstate(req); |
484 | break; | 478 | break; |
485 | default: | 479 | default: |
486 | f_dfu->dfu_state = DFU_STATE_dfuERROR; | 480 | f_dfu->dfu_state = DFU_STATE_dfuERROR; |
487 | value = RET_STALL; | 481 | value = RET_STALL; |
488 | break; | 482 | break; |
489 | } | 483 | } |
490 | 484 | ||
491 | return value; | 485 | return value; |
492 | } | 486 | } |
493 | 487 | ||
494 | static int state_dfu_manifest(struct f_dfu *f_dfu, | 488 | static int state_dfu_manifest(struct f_dfu *f_dfu, |
495 | const struct usb_ctrlrequest *ctrl, | 489 | const struct usb_ctrlrequest *ctrl, |
496 | struct usb_gadget *gadget, | 490 | struct usb_gadget *gadget, |
497 | struct usb_request *req) | 491 | struct usb_request *req) |
498 | { | 492 | { |
499 | int value = 0; | 493 | int value = 0; |
500 | 494 | ||
501 | switch (ctrl->bRequest) { | 495 | switch (ctrl->bRequest) { |
502 | case USB_REQ_DFU_GETSTATUS: | 496 | case USB_REQ_DFU_GETSTATUS: |
503 | /* We're MainfestationTolerant */ | 497 | /* We're MainfestationTolerant */ |
504 | f_dfu->dfu_state = DFU_STATE_dfuIDLE; | 498 | f_dfu->dfu_state = DFU_STATE_dfuIDLE; |
505 | handle_getstatus(req); | 499 | handle_getstatus(req); |
506 | f_dfu->blk_seq_num = 0; | 500 | f_dfu->blk_seq_num = 0; |
507 | value = RET_STAT_LEN; | 501 | value = RET_STAT_LEN; |
508 | puts("DOWNLOAD ... OK\nCtrl+C to exit ...\n"); | 502 | puts("DOWNLOAD ... OK\nCtrl+C to exit ...\n"); |
509 | break; | 503 | break; |
510 | case USB_REQ_DFU_GETSTATE: | 504 | case USB_REQ_DFU_GETSTATE: |
511 | handle_getstate(req); | 505 | handle_getstate(req); |
512 | break; | 506 | break; |
513 | default: | 507 | default: |
514 | f_dfu->dfu_state = DFU_STATE_dfuERROR; | 508 | f_dfu->dfu_state = DFU_STATE_dfuERROR; |
515 | value = RET_STALL; | 509 | value = RET_STALL; |
516 | break; | 510 | break; |
517 | } | 511 | } |
518 | return value; | 512 | return value; |
519 | } | 513 | } |
520 | 514 | ||
521 | static int state_dfu_upload_idle(struct f_dfu *f_dfu, | 515 | static int state_dfu_upload_idle(struct f_dfu *f_dfu, |
522 | const struct usb_ctrlrequest *ctrl, | 516 | const struct usb_ctrlrequest *ctrl, |
523 | struct usb_gadget *gadget, | 517 | struct usb_gadget *gadget, |
524 | struct usb_request *req) | 518 | struct usb_request *req) |
525 | { | 519 | { |
526 | u16 w_value = le16_to_cpu(ctrl->wValue); | 520 | u16 w_value = le16_to_cpu(ctrl->wValue); |
527 | u16 len = le16_to_cpu(ctrl->wLength); | 521 | u16 len = le16_to_cpu(ctrl->wLength); |
528 | int value = 0; | 522 | int value = 0; |
529 | 523 | ||
530 | switch (ctrl->bRequest) { | 524 | switch (ctrl->bRequest) { |
531 | case USB_REQ_DFU_UPLOAD: | 525 | case USB_REQ_DFU_UPLOAD: |
532 | /* state transition if less data then requested */ | 526 | /* state transition if less data then requested */ |
533 | f_dfu->blk_seq_num = w_value; | 527 | f_dfu->blk_seq_num = w_value; |
534 | value = handle_upload(req, len); | 528 | value = handle_upload(req, len); |
535 | if (value >= 0 && value < len) | 529 | if (value >= 0 && value < len) |
536 | f_dfu->dfu_state = DFU_STATE_dfuIDLE; | 530 | f_dfu->dfu_state = DFU_STATE_dfuIDLE; |
537 | break; | 531 | break; |
538 | case USB_REQ_DFU_ABORT: | 532 | case USB_REQ_DFU_ABORT: |
539 | f_dfu->dfu_state = DFU_STATE_dfuIDLE; | 533 | f_dfu->dfu_state = DFU_STATE_dfuIDLE; |
540 | /* no zlp? */ | 534 | /* no zlp? */ |
541 | value = RET_ZLP; | 535 | value = RET_ZLP; |
542 | break; | 536 | break; |
543 | case USB_REQ_DFU_GETSTATUS: | 537 | case USB_REQ_DFU_GETSTATUS: |
544 | handle_getstatus(req); | 538 | handle_getstatus(req); |
545 | value = RET_STAT_LEN; | 539 | value = RET_STAT_LEN; |
546 | break; | 540 | break; |
547 | case USB_REQ_DFU_GETSTATE: | 541 | case USB_REQ_DFU_GETSTATE: |
548 | handle_getstate(req); | 542 | handle_getstate(req); |
549 | break; | 543 | break; |
550 | default: | 544 | default: |
551 | f_dfu->dfu_state = DFU_STATE_dfuERROR; | 545 | f_dfu->dfu_state = DFU_STATE_dfuERROR; |
552 | value = RET_STALL; | 546 | value = RET_STALL; |
553 | break; | 547 | break; |
554 | } | 548 | } |
555 | 549 | ||
556 | return value; | 550 | return value; |
557 | } | 551 | } |
558 | 552 | ||
559 | static int state_dfu_error(struct f_dfu *f_dfu, | 553 | static int state_dfu_error(struct f_dfu *f_dfu, |
560 | const struct usb_ctrlrequest *ctrl, | 554 | const struct usb_ctrlrequest *ctrl, |
561 | struct usb_gadget *gadget, | 555 | struct usb_gadget *gadget, |
562 | struct usb_request *req) | 556 | struct usb_request *req) |
563 | { | 557 | { |
564 | int value = 0; | 558 | int value = 0; |
565 | 559 | ||
566 | switch (ctrl->bRequest) { | 560 | switch (ctrl->bRequest) { |
567 | case USB_REQ_DFU_GETSTATUS: | 561 | case USB_REQ_DFU_GETSTATUS: |
568 | handle_getstatus(req); | 562 | handle_getstatus(req); |
569 | value = RET_STAT_LEN; | 563 | value = RET_STAT_LEN; |
570 | break; | 564 | break; |
571 | case USB_REQ_DFU_GETSTATE: | 565 | case USB_REQ_DFU_GETSTATE: |
572 | handle_getstate(req); | 566 | handle_getstate(req); |
573 | break; | 567 | break; |
574 | case USB_REQ_DFU_CLRSTATUS: | 568 | case USB_REQ_DFU_CLRSTATUS: |
575 | f_dfu->dfu_state = DFU_STATE_dfuIDLE; | 569 | f_dfu->dfu_state = DFU_STATE_dfuIDLE; |
576 | f_dfu->dfu_status = DFU_STATUS_OK; | 570 | f_dfu->dfu_status = DFU_STATUS_OK; |
577 | /* no zlp? */ | 571 | /* no zlp? */ |
578 | value = RET_ZLP; | 572 | value = RET_ZLP; |
579 | break; | 573 | break; |
580 | default: | 574 | default: |
581 | f_dfu->dfu_state = DFU_STATE_dfuERROR; | 575 | f_dfu->dfu_state = DFU_STATE_dfuERROR; |
582 | value = RET_STALL; | 576 | value = RET_STALL; |
583 | break; | 577 | break; |
584 | } | 578 | } |
585 | 579 | ||
586 | return value; | 580 | return value; |
587 | } | 581 | } |
588 | 582 | ||
589 | static dfu_state_fn dfu_state[] = { | 583 | static dfu_state_fn dfu_state[] = { |
590 | state_app_idle, /* DFU_STATE_appIDLE */ | 584 | state_app_idle, /* DFU_STATE_appIDLE */ |
591 | state_app_detach, /* DFU_STATE_appDETACH */ | 585 | state_app_detach, /* DFU_STATE_appDETACH */ |
592 | state_dfu_idle, /* DFU_STATE_dfuIDLE */ | 586 | state_dfu_idle, /* DFU_STATE_dfuIDLE */ |
593 | state_dfu_dnload_sync, /* DFU_STATE_dfuDNLOAD_SYNC */ | 587 | state_dfu_dnload_sync, /* DFU_STATE_dfuDNLOAD_SYNC */ |
594 | state_dfu_dnbusy, /* DFU_STATE_dfuDNBUSY */ | 588 | state_dfu_dnbusy, /* DFU_STATE_dfuDNBUSY */ |
595 | state_dfu_dnload_idle, /* DFU_STATE_dfuDNLOAD_IDLE */ | 589 | state_dfu_dnload_idle, /* DFU_STATE_dfuDNLOAD_IDLE */ |
596 | state_dfu_manifest_sync, /* DFU_STATE_dfuMANIFEST_SYNC */ | 590 | state_dfu_manifest_sync, /* DFU_STATE_dfuMANIFEST_SYNC */ |
597 | state_dfu_manifest, /* DFU_STATE_dfuMANIFEST */ | 591 | state_dfu_manifest, /* DFU_STATE_dfuMANIFEST */ |
598 | NULL, /* DFU_STATE_dfuMANIFEST_WAIT_RST */ | 592 | NULL, /* DFU_STATE_dfuMANIFEST_WAIT_RST */ |
599 | state_dfu_upload_idle, /* DFU_STATE_dfuUPLOAD_IDLE */ | 593 | state_dfu_upload_idle, /* DFU_STATE_dfuUPLOAD_IDLE */ |
600 | state_dfu_error /* DFU_STATE_dfuERROR */ | 594 | state_dfu_error /* DFU_STATE_dfuERROR */ |
601 | }; | 595 | }; |
602 | 596 | ||
603 | static int | 597 | static int |
604 | dfu_handle(struct usb_function *f, const struct usb_ctrlrequest *ctrl) | 598 | dfu_handle(struct usb_function *f, const struct usb_ctrlrequest *ctrl) |
605 | { | 599 | { |
606 | struct usb_gadget *gadget = f->config->cdev->gadget; | 600 | struct usb_gadget *gadget = f->config->cdev->gadget; |
607 | struct usb_request *req = f->config->cdev->req; | 601 | struct usb_request *req = f->config->cdev->req; |
608 | struct f_dfu *f_dfu = f->config->cdev->req->context; | 602 | struct f_dfu *f_dfu = f->config->cdev->req->context; |
609 | u16 len = le16_to_cpu(ctrl->wLength); | 603 | u16 len = le16_to_cpu(ctrl->wLength); |
610 | u16 w_value = le16_to_cpu(ctrl->wValue); | 604 | u16 w_value = le16_to_cpu(ctrl->wValue); |
611 | int value = 0; | 605 | int value = 0; |
612 | u8 req_type = ctrl->bRequestType & USB_TYPE_MASK; | 606 | u8 req_type = ctrl->bRequestType & USB_TYPE_MASK; |
613 | 607 | ||
614 | debug("w_value: 0x%x len: 0x%x\n", w_value, len); | 608 | debug("w_value: 0x%x len: 0x%x\n", w_value, len); |
615 | debug("req_type: 0x%x ctrl->bRequest: 0x%x f_dfu->dfu_state: 0x%x\n", | 609 | debug("req_type: 0x%x ctrl->bRequest: 0x%x f_dfu->dfu_state: 0x%x\n", |
616 | req_type, ctrl->bRequest, f_dfu->dfu_state); | 610 | req_type, ctrl->bRequest, f_dfu->dfu_state); |
617 | 611 | ||
618 | if (req_type == USB_TYPE_STANDARD) { | 612 | if (req_type == USB_TYPE_STANDARD) { |
619 | if (ctrl->bRequest == USB_REQ_GET_DESCRIPTOR && | 613 | if (ctrl->bRequest == USB_REQ_GET_DESCRIPTOR && |
620 | (w_value >> 8) == DFU_DT_FUNC) { | 614 | (w_value >> 8) == DFU_DT_FUNC) { |
621 | value = min(len, (u16) sizeof(dfu_func)); | 615 | value = min(len, (u16) sizeof(dfu_func)); |
622 | memcpy(req->buf, &dfu_func, value); | 616 | memcpy(req->buf, &dfu_func, value); |
623 | } | 617 | } |
624 | } else /* DFU specific request */ | 618 | } else /* DFU specific request */ |
625 | value = dfu_state[f_dfu->dfu_state] (f_dfu, ctrl, gadget, req); | 619 | value = dfu_state[f_dfu->dfu_state] (f_dfu, ctrl, gadget, req); |
626 | 620 | ||
627 | if (value >= 0) { | 621 | if (value >= 0) { |
628 | req->length = value; | 622 | req->length = value; |
629 | req->zero = value < len; | 623 | req->zero = value < len; |
630 | value = usb_ep_queue(gadget->ep0, req, 0); | 624 | value = usb_ep_queue(gadget->ep0, req, 0); |
631 | if (value < 0) { | 625 | if (value < 0) { |
632 | debug("ep_queue --> %d\n", value); | 626 | debug("ep_queue --> %d\n", value); |
633 | req->status = 0; | 627 | req->status = 0; |
634 | } | 628 | } |
635 | } | 629 | } |
636 | 630 | ||
637 | return value; | 631 | return value; |
638 | } | 632 | } |
639 | 633 | ||
640 | /*-------------------------------------------------------------------------*/ | 634 | /*-------------------------------------------------------------------------*/ |
641 | 635 | ||
642 | static int | 636 | static int |
643 | dfu_prepare_strings(struct f_dfu *f_dfu, int n) | 637 | dfu_prepare_strings(struct f_dfu *f_dfu, int n) |
644 | { | 638 | { |
645 | struct dfu_entity *de = NULL; | 639 | struct dfu_entity *de = NULL; |
646 | int i = 0; | 640 | int i = 0; |
647 | 641 | ||
648 | f_dfu->strings = calloc(sizeof(struct usb_string), n + 1); | 642 | f_dfu->strings = calloc(sizeof(struct usb_string), n + 1); |
649 | if (!f_dfu->strings) | 643 | if (!f_dfu->strings) |
650 | goto enomem; | 644 | goto enomem; |
651 | 645 | ||
652 | for (i = 0; i < n; ++i) { | 646 | for (i = 0; i < n; ++i) { |
653 | de = dfu_get_entity(i); | 647 | de = dfu_get_entity(i); |
654 | f_dfu->strings[i].s = de->name; | 648 | f_dfu->strings[i].s = de->name; |
655 | } | 649 | } |
656 | 650 | ||
657 | f_dfu->strings[i].id = 0; | 651 | f_dfu->strings[i].id = 0; |
658 | f_dfu->strings[i].s = NULL; | 652 | f_dfu->strings[i].s = NULL; |
659 | 653 | ||
660 | return 0; | 654 | return 0; |
661 | 655 | ||
662 | enomem: | 656 | enomem: |
663 | while (i) | 657 | while (i) |
664 | f_dfu->strings[--i].s = NULL; | 658 | f_dfu->strings[--i].s = NULL; |
665 | 659 | ||
666 | free(f_dfu->strings); | 660 | free(f_dfu->strings); |
667 | 661 | ||
668 | return -ENOMEM; | 662 | return -ENOMEM; |
669 | } | 663 | } |
670 | 664 | ||
671 | static int dfu_prepare_function(struct f_dfu *f_dfu, int n) | 665 | static int dfu_prepare_function(struct f_dfu *f_dfu, int n) |
672 | { | 666 | { |
673 | struct usb_interface_descriptor *d; | 667 | struct usb_interface_descriptor *d; |
674 | int i = 0; | 668 | int i = 0; |
675 | 669 | ||
676 | f_dfu->function = calloc(sizeof(struct usb_descriptor_header *), n + 1); | 670 | f_dfu->function = calloc(sizeof(struct usb_descriptor_header *), n + 1); |
677 | if (!f_dfu->function) | 671 | if (!f_dfu->function) |
678 | goto enomem; | 672 | goto enomem; |
679 | 673 | ||
680 | for (i = 0; i < n; ++i) { | 674 | for (i = 0; i < n; ++i) { |
681 | d = calloc(sizeof(*d), 1); | 675 | d = calloc(sizeof(*d), 1); |
682 | if (!d) | 676 | if (!d) |
683 | goto enomem; | 677 | goto enomem; |
684 | 678 | ||
685 | d->bLength = sizeof(*d); | 679 | d->bLength = sizeof(*d); |
686 | d->bDescriptorType = USB_DT_INTERFACE; | 680 | d->bDescriptorType = USB_DT_INTERFACE; |
687 | d->bAlternateSetting = i; | 681 | d->bAlternateSetting = i; |
688 | d->bNumEndpoints = 0; | 682 | d->bNumEndpoints = 0; |
689 | d->bInterfaceClass = USB_CLASS_APP_SPEC; | 683 | d->bInterfaceClass = USB_CLASS_APP_SPEC; |
690 | d->bInterfaceSubClass = 1; | 684 | d->bInterfaceSubClass = 1; |
691 | d->bInterfaceProtocol = 2; | 685 | d->bInterfaceProtocol = 2; |
692 | 686 | ||
693 | f_dfu->function[i] = (struct usb_descriptor_header *)d; | 687 | f_dfu->function[i] = (struct usb_descriptor_header *)d; |
694 | } | 688 | } |
695 | f_dfu->function[i] = NULL; | 689 | f_dfu->function[i] = NULL; |
696 | 690 | ||
697 | return 0; | 691 | return 0; |
698 | 692 | ||
699 | enomem: | 693 | enomem: |
700 | while (i) { | 694 | while (i) { |
701 | free(f_dfu->function[--i]); | 695 | free(f_dfu->function[--i]); |
702 | f_dfu->function[i] = NULL; | 696 | f_dfu->function[i] = NULL; |
703 | } | 697 | } |
704 | free(f_dfu->function); | 698 | free(f_dfu->function); |
705 | 699 | ||
706 | return -ENOMEM; | 700 | return -ENOMEM; |
707 | } | 701 | } |
708 | 702 | ||
709 | static int dfu_bind(struct usb_configuration *c, struct usb_function *f) | 703 | static int dfu_bind(struct usb_configuration *c, struct usb_function *f) |
710 | { | 704 | { |
711 | struct usb_composite_dev *cdev = c->cdev; | 705 | struct usb_composite_dev *cdev = c->cdev; |
712 | struct f_dfu *f_dfu = func_to_dfu(f); | 706 | struct f_dfu *f_dfu = func_to_dfu(f); |
713 | int alt_num = dfu_get_alt_number(); | 707 | int alt_num = dfu_get_alt_number(); |
714 | int rv, id, i; | 708 | int rv, id, i; |
715 | 709 | ||
716 | id = usb_interface_id(c, f); | 710 | id = usb_interface_id(c, f); |
717 | if (id < 0) | 711 | if (id < 0) |
718 | return id; | 712 | return id; |
719 | dfu_intf_runtime.bInterfaceNumber = id; | 713 | dfu_intf_runtime.bInterfaceNumber = id; |
720 | 714 | ||
721 | f_dfu->dfu_state = DFU_STATE_appIDLE; | 715 | f_dfu->dfu_state = DFU_STATE_appIDLE; |
722 | f_dfu->dfu_status = DFU_STATUS_OK; | 716 | f_dfu->dfu_status = DFU_STATUS_OK; |
723 | 717 | ||
724 | rv = dfu_prepare_function(f_dfu, alt_num); | 718 | rv = dfu_prepare_function(f_dfu, alt_num); |
725 | if (rv) | 719 | if (rv) |
726 | goto error; | 720 | goto error; |
727 | 721 | ||
728 | rv = dfu_prepare_strings(f_dfu, alt_num); | 722 | rv = dfu_prepare_strings(f_dfu, alt_num); |
729 | if (rv) | 723 | if (rv) |
730 | goto error; | 724 | goto error; |
731 | for (i = 0; i < alt_num; i++) { | 725 | for (i = 0; i < alt_num; i++) { |
732 | id = usb_string_id(cdev); | 726 | id = usb_string_id(cdev); |
733 | if (id < 0) | 727 | if (id < 0) |
734 | return id; | 728 | return id; |
735 | f_dfu->strings[i].id = id; | 729 | f_dfu->strings[i].id = id; |
736 | ((struct usb_interface_descriptor *)f_dfu->function[i]) | 730 | ((struct usb_interface_descriptor *)f_dfu->function[i]) |
737 | ->iInterface = id; | 731 | ->iInterface = id; |
738 | } | 732 | } |
739 | 733 | ||
740 | to_dfu_mode(f_dfu); | 734 | to_dfu_mode(f_dfu); |
741 | 735 | ||
742 | stringtab_dfu.strings = f_dfu->strings; | 736 | stringtab_dfu.strings = f_dfu->strings; |
743 | 737 | ||
744 | cdev->req->context = f_dfu; | 738 | cdev->req->context = f_dfu; |
745 | 739 | ||
746 | error: | 740 | error: |
747 | return rv; | 741 | return rv; |
748 | } | 742 | } |
749 | 743 | ||
750 | static void dfu_unbind(struct usb_configuration *c, struct usb_function *f) | 744 | static void dfu_unbind(struct usb_configuration *c, struct usb_function *f) |
751 | { | 745 | { |
752 | struct f_dfu *f_dfu = func_to_dfu(f); | 746 | struct f_dfu *f_dfu = func_to_dfu(f); |
753 | int alt_num = dfu_get_alt_number(); | 747 | int alt_num = dfu_get_alt_number(); |
754 | int i; | 748 | int i; |
755 | 749 | ||
756 | if (f_dfu->strings) { | 750 | if (f_dfu->strings) { |
757 | i = alt_num; | 751 | i = alt_num; |
758 | while (i) | 752 | while (i) |
759 | f_dfu->strings[--i].s = NULL; | 753 | f_dfu->strings[--i].s = NULL; |
760 | 754 | ||
761 | free(f_dfu->strings); | 755 | free(f_dfu->strings); |
762 | } | 756 | } |
763 | 757 | ||
764 | if (f_dfu->function) { | 758 | if (f_dfu->function) { |
765 | i = alt_num; | 759 | i = alt_num; |
766 | while (i) { | 760 | while (i) { |
767 | free(f_dfu->function[--i]); | 761 | free(f_dfu->function[--i]); |
768 | f_dfu->function[i] = NULL; | 762 | f_dfu->function[i] = NULL; |
769 | } | 763 | } |
770 | free(f_dfu->function); | 764 | free(f_dfu->function); |
771 | } | 765 | } |
772 | 766 | ||
773 | free(f_dfu); | 767 | free(f_dfu); |
774 | } | 768 | } |
775 | 769 | ||
776 | static int dfu_set_alt(struct usb_function *f, unsigned intf, unsigned alt) | 770 | static int dfu_set_alt(struct usb_function *f, unsigned intf, unsigned alt) |
777 | { | 771 | { |
778 | struct f_dfu *f_dfu = func_to_dfu(f); | 772 | struct f_dfu *f_dfu = func_to_dfu(f); |
779 | 773 | ||
780 | debug("%s: intf:%d alt:%d\n", __func__, intf, alt); | 774 | debug("%s: intf:%d alt:%d\n", __func__, intf, alt); |
781 | 775 | ||
782 | f_dfu->altsetting = alt; | 776 | f_dfu->altsetting = alt; |
783 | f_dfu->dfu_state = DFU_STATE_dfuIDLE; | 777 | f_dfu->dfu_state = DFU_STATE_dfuIDLE; |
784 | f_dfu->dfu_status = DFU_STATUS_OK; | 778 | f_dfu->dfu_status = DFU_STATUS_OK; |
785 | 779 | ||
786 | return 0; | 780 | return 0; |
787 | } | 781 | } |
788 | 782 | ||
789 | /* TODO: is this really what we need here? */ | 783 | /* TODO: is this really what we need here? */ |
790 | static void dfu_disable(struct usb_function *f) | 784 | static void dfu_disable(struct usb_function *f) |
791 | { | 785 | { |
792 | struct f_dfu *f_dfu = func_to_dfu(f); | 786 | struct f_dfu *f_dfu = func_to_dfu(f); |
793 | if (f_dfu->config == 0) | 787 | if (f_dfu->config == 0) |
794 | return; | 788 | return; |
795 | 789 | ||
796 | debug("%s: reset config\n", __func__); | 790 | debug("%s: reset config\n", __func__); |
797 | 791 | ||
798 | f_dfu->config = 0; | 792 | f_dfu->config = 0; |
799 | } | 793 | } |
800 | 794 | ||
801 | static int dfu_bind_config(struct usb_configuration *c) | 795 | static int dfu_bind_config(struct usb_configuration *c) |
802 | { | 796 | { |
803 | struct f_dfu *f_dfu; | 797 | struct f_dfu *f_dfu; |
804 | int status; | 798 | int status; |
805 | 799 | ||
806 | f_dfu = calloc(sizeof(*f_dfu), 1); | 800 | f_dfu = calloc(sizeof(*f_dfu), 1); |
807 | if (!f_dfu) | 801 | if (!f_dfu) |
808 | return -ENOMEM; | 802 | return -ENOMEM; |
809 | f_dfu->usb_function.name = "dfu"; | 803 | f_dfu->usb_function.name = "dfu"; |
810 | f_dfu->usb_function.hs_descriptors = dfu_runtime_descs; | 804 | f_dfu->usb_function.hs_descriptors = dfu_runtime_descs; |
805 | f_dfu->usb_function.descriptors = dfu_runtime_descs; | ||
811 | f_dfu->usb_function.bind = dfu_bind; | 806 | f_dfu->usb_function.bind = dfu_bind; |
812 | f_dfu->usb_function.unbind = dfu_unbind; | 807 | f_dfu->usb_function.unbind = dfu_unbind; |
813 | f_dfu->usb_function.set_alt = dfu_set_alt; | 808 | f_dfu->usb_function.set_alt = dfu_set_alt; |
814 | f_dfu->usb_function.disable = dfu_disable; | 809 | f_dfu->usb_function.disable = dfu_disable; |
815 | f_dfu->usb_function.strings = dfu_generic_strings; | 810 | f_dfu->usb_function.strings = dfu_generic_strings; |
816 | f_dfu->usb_function.setup = dfu_handle; | 811 | f_dfu->usb_function.setup = dfu_handle; |
817 | f_dfu->poll_timeout = DFU_DEFAULT_POLL_TIMEOUT; | 812 | f_dfu->poll_timeout = DFU_DEFAULT_POLL_TIMEOUT; |
818 | 813 | ||
819 | status = usb_add_function(c, &f_dfu->usb_function); | 814 | status = usb_add_function(c, &f_dfu->usb_function); |
820 | if (status) | 815 | if (status) |
821 | free(f_dfu); | 816 | free(f_dfu); |
822 | 817 | ||
823 | return status; | 818 | return status; |
824 | } | 819 | } |
825 | 820 | ||
826 | int dfu_add(struct usb_configuration *c) | 821 | int dfu_add(struct usb_configuration *c) |
827 | { | 822 | { |
828 | int id; | 823 | int id; |
829 | 824 | ||
830 | id = usb_string_id(c->cdev); | 825 | id = usb_string_id(c->cdev); |
831 | if (id < 0) | 826 | if (id < 0) |
832 | return id; | 827 | return id; |
833 | strings_dfu_generic[0].id = id; | 828 | strings_dfu_generic[0].id = id; |
834 | dfu_intf_runtime.iInterface = id; | 829 | dfu_intf_runtime.iInterface = id; |
835 | 830 | ||
836 | debug("%s: cdev: 0x%p gadget:0x%p gadget->ep0: 0x%p\n", __func__, | 831 | debug("%s: cdev: 0x%p gadget:0x%p gadget->ep0: 0x%p\n", __func__, |
837 | c->cdev, c->cdev->gadget, c->cdev->gadget->ep0); | 832 | c->cdev, c->cdev->gadget, c->cdev->gadget->ep0); |
838 | 833 | ||
839 | return dfu_bind_config(c); | 834 | return dfu_bind_config(c); |
840 | } | 835 | } |
drivers/usb/gadget/f_fastboot.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2008 - 2009 | 2 | * (C) Copyright 2008 - 2009 |
3 | * Windriver, <www.windriver.com> | 3 | * Windriver, <www.windriver.com> |
4 | * Tom Rix <Tom.Rix@windriver.com> | 4 | * Tom Rix <Tom.Rix@windriver.com> |
5 | * | 5 | * |
6 | * Copyright 2011 Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 6 | * Copyright 2011 Sebastian Andrzej Siewior <bigeasy@linutronix.de> |
7 | * | 7 | * |
8 | * Copyright 2014 Linaro, Ltd. | 8 | * Copyright 2014 Linaro, Ltd. |
9 | * Rob Herring <robh@kernel.org> | 9 | * Rob Herring <robh@kernel.org> |
10 | * | 10 | * |
11 | * SPDX-License-Identifier: GPL-2.0+ | 11 | * SPDX-License-Identifier: GPL-2.0+ |
12 | */ | 12 | */ |
13 | #include <config.h> | 13 | #include <config.h> |
14 | #include <common.h> | 14 | #include <common.h> |
15 | #include <errno.h> | 15 | #include <errno.h> |
16 | #include <malloc.h> | 16 | #include <malloc.h> |
17 | #include <linux/usb/ch9.h> | 17 | #include <linux/usb/ch9.h> |
18 | #include <linux/usb/gadget.h> | 18 | #include <linux/usb/gadget.h> |
19 | #include <linux/usb/composite.h> | 19 | #include <linux/usb/composite.h> |
20 | #include <linux/compiler.h> | 20 | #include <linux/compiler.h> |
21 | #include <version.h> | 21 | #include <version.h> |
22 | #include <g_dnl.h> | 22 | #include <g_dnl.h> |
23 | #ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV | 23 | #ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV |
24 | #include <fb_mmc.h> | 24 | #include <fb_mmc.h> |
25 | #endif | 25 | #endif |
26 | 26 | ||
27 | #define FASTBOOT_VERSION "0.4" | 27 | #define FASTBOOT_VERSION "0.4" |
28 | 28 | ||
29 | #define FASTBOOT_INTERFACE_CLASS 0xff | 29 | #define FASTBOOT_INTERFACE_CLASS 0xff |
30 | #define FASTBOOT_INTERFACE_SUB_CLASS 0x42 | 30 | #define FASTBOOT_INTERFACE_SUB_CLASS 0x42 |
31 | #define FASTBOOT_INTERFACE_PROTOCOL 0x03 | 31 | #define FASTBOOT_INTERFACE_PROTOCOL 0x03 |
32 | 32 | ||
33 | #define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_2_0 (0x0200) | 33 | #define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_2_0 (0x0200) |
34 | #define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_1_1 (0x0040) | 34 | #define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_1_1 (0x0040) |
35 | #define TX_ENDPOINT_MAXIMUM_PACKET_SIZE (0x0040) | 35 | #define TX_ENDPOINT_MAXIMUM_PACKET_SIZE (0x0040) |
36 | 36 | ||
37 | /* The 64 defined bytes plus \0 */ | 37 | /* The 64 defined bytes plus \0 */ |
38 | #define RESPONSE_LEN (64 + 1) | 38 | #define RESPONSE_LEN (64 + 1) |
39 | 39 | ||
40 | #define EP_BUFFER_SIZE 4096 | 40 | #define EP_BUFFER_SIZE 4096 |
41 | 41 | ||
42 | struct f_fastboot { | 42 | struct f_fastboot { |
43 | struct usb_function usb_function; | 43 | struct usb_function usb_function; |
44 | 44 | ||
45 | /* IN/OUT EP's and corresponding requests */ | 45 | /* IN/OUT EP's and corresponding requests */ |
46 | struct usb_ep *in_ep, *out_ep; | 46 | struct usb_ep *in_ep, *out_ep; |
47 | struct usb_request *in_req, *out_req; | 47 | struct usb_request *in_req, *out_req; |
48 | }; | 48 | }; |
49 | 49 | ||
50 | static inline struct f_fastboot *func_to_fastboot(struct usb_function *f) | 50 | static inline struct f_fastboot *func_to_fastboot(struct usb_function *f) |
51 | { | 51 | { |
52 | return container_of(f, struct f_fastboot, usb_function); | 52 | return container_of(f, struct f_fastboot, usb_function); |
53 | } | 53 | } |
54 | 54 | ||
55 | static struct f_fastboot *fastboot_func; | 55 | static struct f_fastboot *fastboot_func; |
56 | static unsigned int download_size; | 56 | static unsigned int download_size; |
57 | static unsigned int download_bytes; | 57 | static unsigned int download_bytes; |
58 | 58 | ||
59 | static struct usb_endpoint_descriptor fs_ep_in = { | 59 | static struct usb_endpoint_descriptor fs_ep_in = { |
60 | .bLength = USB_DT_ENDPOINT_SIZE, | 60 | .bLength = USB_DT_ENDPOINT_SIZE, |
61 | .bDescriptorType = USB_DT_ENDPOINT, | 61 | .bDescriptorType = USB_DT_ENDPOINT, |
62 | .bEndpointAddress = USB_DIR_IN, | 62 | .bEndpointAddress = USB_DIR_IN, |
63 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 63 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
64 | .wMaxPacketSize = TX_ENDPOINT_MAXIMUM_PACKET_SIZE, | 64 | .wMaxPacketSize = TX_ENDPOINT_MAXIMUM_PACKET_SIZE, |
65 | .bInterval = 0x00, | 65 | .bInterval = 0x00, |
66 | }; | 66 | }; |
67 | 67 | ||
68 | static struct usb_endpoint_descriptor fs_ep_out = { | 68 | static struct usb_endpoint_descriptor fs_ep_out = { |
69 | .bLength = USB_DT_ENDPOINT_SIZE, | 69 | .bLength = USB_DT_ENDPOINT_SIZE, |
70 | .bDescriptorType = USB_DT_ENDPOINT, | 70 | .bDescriptorType = USB_DT_ENDPOINT, |
71 | .bEndpointAddress = USB_DIR_OUT, | 71 | .bEndpointAddress = USB_DIR_OUT, |
72 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 72 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
73 | .wMaxPacketSize = RX_ENDPOINT_MAXIMUM_PACKET_SIZE_1_1, | 73 | .wMaxPacketSize = RX_ENDPOINT_MAXIMUM_PACKET_SIZE_1_1, |
74 | .bInterval = 0x00, | 74 | .bInterval = 0x00, |
75 | }; | 75 | }; |
76 | 76 | ||
77 | static struct usb_endpoint_descriptor hs_ep_out = { | 77 | static struct usb_endpoint_descriptor hs_ep_out = { |
78 | .bLength = USB_DT_ENDPOINT_SIZE, | 78 | .bLength = USB_DT_ENDPOINT_SIZE, |
79 | .bDescriptorType = USB_DT_ENDPOINT, | 79 | .bDescriptorType = USB_DT_ENDPOINT, |
80 | .bEndpointAddress = USB_DIR_OUT, | 80 | .bEndpointAddress = USB_DIR_OUT, |
81 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 81 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
82 | .wMaxPacketSize = RX_ENDPOINT_MAXIMUM_PACKET_SIZE_2_0, | 82 | .wMaxPacketSize = RX_ENDPOINT_MAXIMUM_PACKET_SIZE_2_0, |
83 | .bInterval = 0x00, | 83 | .bInterval = 0x00, |
84 | }; | 84 | }; |
85 | 85 | ||
86 | static struct usb_interface_descriptor interface_desc = { | 86 | static struct usb_interface_descriptor interface_desc = { |
87 | .bLength = USB_DT_INTERFACE_SIZE, | 87 | .bLength = USB_DT_INTERFACE_SIZE, |
88 | .bDescriptorType = USB_DT_INTERFACE, | 88 | .bDescriptorType = USB_DT_INTERFACE, |
89 | .bInterfaceNumber = 0x00, | 89 | .bInterfaceNumber = 0x00, |
90 | .bAlternateSetting = 0x00, | 90 | .bAlternateSetting = 0x00, |
91 | .bNumEndpoints = 0x02, | 91 | .bNumEndpoints = 0x02, |
92 | .bInterfaceClass = FASTBOOT_INTERFACE_CLASS, | 92 | .bInterfaceClass = FASTBOOT_INTERFACE_CLASS, |
93 | .bInterfaceSubClass = FASTBOOT_INTERFACE_SUB_CLASS, | 93 | .bInterfaceSubClass = FASTBOOT_INTERFACE_SUB_CLASS, |
94 | .bInterfaceProtocol = FASTBOOT_INTERFACE_PROTOCOL, | 94 | .bInterfaceProtocol = FASTBOOT_INTERFACE_PROTOCOL, |
95 | }; | 95 | }; |
96 | 96 | ||
97 | static struct usb_descriptor_header *fb_runtime_descs[] = { | 97 | static struct usb_descriptor_header *fb_runtime_descs[] = { |
98 | (struct usb_descriptor_header *)&interface_desc, | 98 | (struct usb_descriptor_header *)&interface_desc, |
99 | (struct usb_descriptor_header *)&fs_ep_in, | 99 | (struct usb_descriptor_header *)&fs_ep_in, |
100 | (struct usb_descriptor_header *)&hs_ep_out, | 100 | (struct usb_descriptor_header *)&hs_ep_out, |
101 | NULL, | 101 | NULL, |
102 | }; | 102 | }; |
103 | 103 | ||
104 | /* | 104 | /* |
105 | * static strings, in UTF-8 | 105 | * static strings, in UTF-8 |
106 | */ | 106 | */ |
107 | static const char fastboot_name[] = "Android Fastboot"; | 107 | static const char fastboot_name[] = "Android Fastboot"; |
108 | 108 | ||
109 | static struct usb_string fastboot_string_defs[] = { | 109 | static struct usb_string fastboot_string_defs[] = { |
110 | [0].s = fastboot_name, | 110 | [0].s = fastboot_name, |
111 | { } /* end of list */ | 111 | { } /* end of list */ |
112 | }; | 112 | }; |
113 | 113 | ||
114 | static struct usb_gadget_strings stringtab_fastboot = { | 114 | static struct usb_gadget_strings stringtab_fastboot = { |
115 | .language = 0x0409, /* en-us */ | 115 | .language = 0x0409, /* en-us */ |
116 | .strings = fastboot_string_defs, | 116 | .strings = fastboot_string_defs, |
117 | }; | 117 | }; |
118 | 118 | ||
119 | static struct usb_gadget_strings *fastboot_strings[] = { | 119 | static struct usb_gadget_strings *fastboot_strings[] = { |
120 | &stringtab_fastboot, | 120 | &stringtab_fastboot, |
121 | NULL, | 121 | NULL, |
122 | }; | 122 | }; |
123 | 123 | ||
124 | static void rx_handler_command(struct usb_ep *ep, struct usb_request *req); | 124 | static void rx_handler_command(struct usb_ep *ep, struct usb_request *req); |
125 | 125 | ||
126 | static void fastboot_complete(struct usb_ep *ep, struct usb_request *req) | 126 | static void fastboot_complete(struct usb_ep *ep, struct usb_request *req) |
127 | { | 127 | { |
128 | int status = req->status; | 128 | int status = req->status; |
129 | if (!status) | 129 | if (!status) |
130 | return; | 130 | return; |
131 | printf("status: %d ep '%s' trans: %d\n", status, ep->name, req->actual); | 131 | printf("status: %d ep '%s' trans: %d\n", status, ep->name, req->actual); |
132 | } | 132 | } |
133 | 133 | ||
134 | static int fastboot_bind(struct usb_configuration *c, struct usb_function *f) | 134 | static int fastboot_bind(struct usb_configuration *c, struct usb_function *f) |
135 | { | 135 | { |
136 | int id; | 136 | int id; |
137 | struct usb_gadget *gadget = c->cdev->gadget; | 137 | struct usb_gadget *gadget = c->cdev->gadget; |
138 | struct f_fastboot *f_fb = func_to_fastboot(f); | 138 | struct f_fastboot *f_fb = func_to_fastboot(f); |
139 | 139 | ||
140 | /* DYNAMIC interface numbers assignments */ | 140 | /* DYNAMIC interface numbers assignments */ |
141 | id = usb_interface_id(c, f); | 141 | id = usb_interface_id(c, f); |
142 | if (id < 0) | 142 | if (id < 0) |
143 | return id; | 143 | return id; |
144 | interface_desc.bInterfaceNumber = id; | 144 | interface_desc.bInterfaceNumber = id; |
145 | 145 | ||
146 | id = usb_string_id(c->cdev); | 146 | id = usb_string_id(c->cdev); |
147 | if (id < 0) | 147 | if (id < 0) |
148 | return id; | 148 | return id; |
149 | fastboot_string_defs[0].id = id; | 149 | fastboot_string_defs[0].id = id; |
150 | interface_desc.iInterface = id; | 150 | interface_desc.iInterface = id; |
151 | 151 | ||
152 | f_fb->in_ep = usb_ep_autoconfig(gadget, &fs_ep_in); | 152 | f_fb->in_ep = usb_ep_autoconfig(gadget, &fs_ep_in); |
153 | if (!f_fb->in_ep) | 153 | if (!f_fb->in_ep) |
154 | return -ENODEV; | 154 | return -ENODEV; |
155 | f_fb->in_ep->driver_data = c->cdev; | 155 | f_fb->in_ep->driver_data = c->cdev; |
156 | 156 | ||
157 | f_fb->out_ep = usb_ep_autoconfig(gadget, &fs_ep_out); | 157 | f_fb->out_ep = usb_ep_autoconfig(gadget, &fs_ep_out); |
158 | if (!f_fb->out_ep) | 158 | if (!f_fb->out_ep) |
159 | return -ENODEV; | 159 | return -ENODEV; |
160 | f_fb->out_ep->driver_data = c->cdev; | 160 | f_fb->out_ep->driver_data = c->cdev; |
161 | 161 | ||
162 | hs_ep_out.bEndpointAddress = fs_ep_out.bEndpointAddress; | 162 | hs_ep_out.bEndpointAddress = fs_ep_out.bEndpointAddress; |
163 | 163 | ||
164 | return 0; | 164 | return 0; |
165 | } | 165 | } |
166 | 166 | ||
167 | static void fastboot_unbind(struct usb_configuration *c, struct usb_function *f) | 167 | static void fastboot_unbind(struct usb_configuration *c, struct usb_function *f) |
168 | { | 168 | { |
169 | memset(fastboot_func, 0, sizeof(*fastboot_func)); | 169 | memset(fastboot_func, 0, sizeof(*fastboot_func)); |
170 | } | 170 | } |
171 | 171 | ||
172 | static void fastboot_disable(struct usb_function *f) | 172 | static void fastboot_disable(struct usb_function *f) |
173 | { | 173 | { |
174 | struct f_fastboot *f_fb = func_to_fastboot(f); | 174 | struct f_fastboot *f_fb = func_to_fastboot(f); |
175 | 175 | ||
176 | usb_ep_disable(f_fb->out_ep); | 176 | usb_ep_disable(f_fb->out_ep); |
177 | usb_ep_disable(f_fb->in_ep); | 177 | usb_ep_disable(f_fb->in_ep); |
178 | 178 | ||
179 | if (f_fb->out_req) { | 179 | if (f_fb->out_req) { |
180 | free(f_fb->out_req->buf); | 180 | free(f_fb->out_req->buf); |
181 | usb_ep_free_request(f_fb->out_ep, f_fb->out_req); | 181 | usb_ep_free_request(f_fb->out_ep, f_fb->out_req); |
182 | f_fb->out_req = NULL; | 182 | f_fb->out_req = NULL; |
183 | } | 183 | } |
184 | if (f_fb->in_req) { | 184 | if (f_fb->in_req) { |
185 | free(f_fb->in_req->buf); | 185 | free(f_fb->in_req->buf); |
186 | usb_ep_free_request(f_fb->in_ep, f_fb->in_req); | 186 | usb_ep_free_request(f_fb->in_ep, f_fb->in_req); |
187 | f_fb->in_req = NULL; | 187 | f_fb->in_req = NULL; |
188 | } | 188 | } |
189 | } | 189 | } |
190 | 190 | ||
191 | static struct usb_request *fastboot_start_ep(struct usb_ep *ep) | 191 | static struct usb_request *fastboot_start_ep(struct usb_ep *ep) |
192 | { | 192 | { |
193 | struct usb_request *req; | 193 | struct usb_request *req; |
194 | 194 | ||
195 | req = usb_ep_alloc_request(ep, 0); | 195 | req = usb_ep_alloc_request(ep, 0); |
196 | if (!req) | 196 | if (!req) |
197 | return NULL; | 197 | return NULL; |
198 | 198 | ||
199 | req->length = EP_BUFFER_SIZE; | 199 | req->length = EP_BUFFER_SIZE; |
200 | req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, EP_BUFFER_SIZE); | 200 | req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, EP_BUFFER_SIZE); |
201 | if (!req->buf) { | 201 | if (!req->buf) { |
202 | usb_ep_free_request(ep, req); | 202 | usb_ep_free_request(ep, req); |
203 | return NULL; | 203 | return NULL; |
204 | } | 204 | } |
205 | 205 | ||
206 | memset(req->buf, 0, req->length); | 206 | memset(req->buf, 0, req->length); |
207 | return req; | 207 | return req; |
208 | } | 208 | } |
209 | 209 | ||
210 | static int fastboot_set_alt(struct usb_function *f, | 210 | static int fastboot_set_alt(struct usb_function *f, |
211 | unsigned interface, unsigned alt) | 211 | unsigned interface, unsigned alt) |
212 | { | 212 | { |
213 | int ret; | 213 | int ret; |
214 | struct usb_composite_dev *cdev = f->config->cdev; | 214 | struct usb_composite_dev *cdev = f->config->cdev; |
215 | struct usb_gadget *gadget = cdev->gadget; | 215 | struct usb_gadget *gadget = cdev->gadget; |
216 | struct f_fastboot *f_fb = func_to_fastboot(f); | 216 | struct f_fastboot *f_fb = func_to_fastboot(f); |
217 | 217 | ||
218 | debug("%s: func: %s intf: %d alt: %d\n", | 218 | debug("%s: func: %s intf: %d alt: %d\n", |
219 | __func__, f->name, interface, alt); | 219 | __func__, f->name, interface, alt); |
220 | 220 | ||
221 | /* make sure we don't enable the ep twice */ | 221 | /* make sure we don't enable the ep twice */ |
222 | if (gadget->speed == USB_SPEED_HIGH) | 222 | if (gadget->speed == USB_SPEED_HIGH) |
223 | ret = usb_ep_enable(f_fb->out_ep, &hs_ep_out); | 223 | ret = usb_ep_enable(f_fb->out_ep, &hs_ep_out); |
224 | else | 224 | else |
225 | ret = usb_ep_enable(f_fb->out_ep, &fs_ep_out); | 225 | ret = usb_ep_enable(f_fb->out_ep, &fs_ep_out); |
226 | if (ret) { | 226 | if (ret) { |
227 | puts("failed to enable out ep\n"); | 227 | puts("failed to enable out ep\n"); |
228 | return ret; | 228 | return ret; |
229 | } | 229 | } |
230 | 230 | ||
231 | f_fb->out_req = fastboot_start_ep(f_fb->out_ep); | 231 | f_fb->out_req = fastboot_start_ep(f_fb->out_ep); |
232 | if (!f_fb->out_req) { | 232 | if (!f_fb->out_req) { |
233 | puts("failed to alloc out req\n"); | 233 | puts("failed to alloc out req\n"); |
234 | ret = -EINVAL; | 234 | ret = -EINVAL; |
235 | goto err; | 235 | goto err; |
236 | } | 236 | } |
237 | f_fb->out_req->complete = rx_handler_command; | 237 | f_fb->out_req->complete = rx_handler_command; |
238 | 238 | ||
239 | ret = usb_ep_enable(f_fb->in_ep, &fs_ep_in); | 239 | ret = usb_ep_enable(f_fb->in_ep, &fs_ep_in); |
240 | if (ret) { | 240 | if (ret) { |
241 | puts("failed to enable in ep\n"); | 241 | puts("failed to enable in ep\n"); |
242 | goto err; | 242 | goto err; |
243 | } | 243 | } |
244 | 244 | ||
245 | f_fb->in_req = fastboot_start_ep(f_fb->in_ep); | 245 | f_fb->in_req = fastboot_start_ep(f_fb->in_ep); |
246 | if (!f_fb->in_req) { | 246 | if (!f_fb->in_req) { |
247 | puts("failed alloc req in\n"); | 247 | puts("failed alloc req in\n"); |
248 | ret = -EINVAL; | 248 | ret = -EINVAL; |
249 | goto err; | 249 | goto err; |
250 | } | 250 | } |
251 | f_fb->in_req->complete = fastboot_complete; | 251 | f_fb->in_req->complete = fastboot_complete; |
252 | 252 | ||
253 | ret = usb_ep_queue(f_fb->out_ep, f_fb->out_req, 0); | 253 | ret = usb_ep_queue(f_fb->out_ep, f_fb->out_req, 0); |
254 | if (ret) | 254 | if (ret) |
255 | goto err; | 255 | goto err; |
256 | 256 | ||
257 | return 0; | 257 | return 0; |
258 | err: | 258 | err: |
259 | fastboot_disable(f); | 259 | fastboot_disable(f); |
260 | return ret; | 260 | return ret; |
261 | } | 261 | } |
262 | 262 | ||
263 | static int fastboot_add(struct usb_configuration *c) | 263 | static int fastboot_add(struct usb_configuration *c) |
264 | { | 264 | { |
265 | struct f_fastboot *f_fb = fastboot_func; | 265 | struct f_fastboot *f_fb = fastboot_func; |
266 | int status; | 266 | int status; |
267 | 267 | ||
268 | debug("%s: cdev: 0x%p\n", __func__, c->cdev); | 268 | debug("%s: cdev: 0x%p\n", __func__, c->cdev); |
269 | 269 | ||
270 | if (!f_fb) { | 270 | if (!f_fb) { |
271 | f_fb = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*f_fb)); | 271 | f_fb = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*f_fb)); |
272 | if (!f_fb) | 272 | if (!f_fb) |
273 | return -ENOMEM; | 273 | return -ENOMEM; |
274 | 274 | ||
275 | fastboot_func = f_fb; | 275 | fastboot_func = f_fb; |
276 | memset(f_fb, 0, sizeof(*f_fb)); | 276 | memset(f_fb, 0, sizeof(*f_fb)); |
277 | } | 277 | } |
278 | 278 | ||
279 | f_fb->usb_function.name = "f_fastboot"; | 279 | f_fb->usb_function.name = "f_fastboot"; |
280 | f_fb->usb_function.hs_descriptors = fb_runtime_descs; | 280 | f_fb->usb_function.hs_descriptors = fb_runtime_descs; |
281 | f_fb->usb_function.bind = fastboot_bind; | 281 | f_fb->usb_function.bind = fastboot_bind; |
282 | f_fb->usb_function.unbind = fastboot_unbind; | 282 | f_fb->usb_function.unbind = fastboot_unbind; |
283 | f_fb->usb_function.set_alt = fastboot_set_alt; | 283 | f_fb->usb_function.set_alt = fastboot_set_alt; |
284 | f_fb->usb_function.disable = fastboot_disable; | 284 | f_fb->usb_function.disable = fastboot_disable; |
285 | f_fb->usb_function.strings = fastboot_strings; | 285 | f_fb->usb_function.strings = fastboot_strings; |
286 | 286 | ||
287 | status = usb_add_function(c, &f_fb->usb_function); | 287 | status = usb_add_function(c, &f_fb->usb_function); |
288 | if (status) { | 288 | if (status) { |
289 | free(f_fb); | 289 | free(f_fb); |
290 | fastboot_func = f_fb; | 290 | fastboot_func = f_fb; |
291 | } | 291 | } |
292 | 292 | ||
293 | return status; | 293 | return status; |
294 | } | 294 | } |
295 | DECLARE_GADGET_BIND_CALLBACK(usb_dnl_fastboot, fastboot_add); | 295 | DECLARE_GADGET_BIND_CALLBACK(usb_dnl_fastboot, fastboot_add); |
296 | 296 | ||
297 | static int fastboot_tx_write(const char *buffer, unsigned int buffer_size) | 297 | static int fastboot_tx_write(const char *buffer, unsigned int buffer_size) |
298 | { | 298 | { |
299 | struct usb_request *in_req = fastboot_func->in_req; | 299 | struct usb_request *in_req = fastboot_func->in_req; |
300 | int ret; | 300 | int ret; |
301 | 301 | ||
302 | memcpy(in_req->buf, buffer, buffer_size); | 302 | memcpy(in_req->buf, buffer, buffer_size); |
303 | in_req->length = buffer_size; | 303 | in_req->length = buffer_size; |
304 | ret = usb_ep_queue(fastboot_func->in_ep, in_req, 0); | 304 | ret = usb_ep_queue(fastboot_func->in_ep, in_req, 0); |
305 | if (ret) | 305 | if (ret) |
306 | printf("Error %d on queue\n", ret); | 306 | printf("Error %d on queue\n", ret); |
307 | return 0; | 307 | return 0; |
308 | } | 308 | } |
309 | 309 | ||
310 | static int fastboot_tx_write_str(const char *buffer) | 310 | static int fastboot_tx_write_str(const char *buffer) |
311 | { | 311 | { |
312 | return fastboot_tx_write(buffer, strlen(buffer)); | 312 | return fastboot_tx_write(buffer, strlen(buffer)); |
313 | } | 313 | } |
314 | 314 | ||
315 | static void compl_do_reset(struct usb_ep *ep, struct usb_request *req) | 315 | static void compl_do_reset(struct usb_ep *ep, struct usb_request *req) |
316 | { | 316 | { |
317 | do_reset(NULL, 0, 0, NULL); | 317 | do_reset(NULL, 0, 0, NULL); |
318 | } | 318 | } |
319 | 319 | ||
320 | static void cb_reboot(struct usb_ep *ep, struct usb_request *req) | 320 | static void cb_reboot(struct usb_ep *ep, struct usb_request *req) |
321 | { | 321 | { |
322 | fastboot_func->in_req->complete = compl_do_reset; | 322 | fastboot_func->in_req->complete = compl_do_reset; |
323 | fastboot_tx_write_str("OKAY"); | 323 | fastboot_tx_write_str("OKAY"); |
324 | } | 324 | } |
325 | 325 | ||
326 | static int strcmp_l1(const char *s1, const char *s2) | 326 | static int strcmp_l1(const char *s1, const char *s2) |
327 | { | 327 | { |
328 | if (!s1 || !s2) | 328 | if (!s1 || !s2) |
329 | return -1; | 329 | return -1; |
330 | return strncmp(s1, s2, strlen(s1)); | 330 | return strncmp(s1, s2, strlen(s1)); |
331 | } | 331 | } |
332 | 332 | ||
333 | static void cb_getvar(struct usb_ep *ep, struct usb_request *req) | 333 | static void cb_getvar(struct usb_ep *ep, struct usb_request *req) |
334 | { | 334 | { |
335 | char *cmd = req->buf; | 335 | char *cmd = req->buf; |
336 | char response[RESPONSE_LEN]; | 336 | char response[RESPONSE_LEN]; |
337 | const char *s; | 337 | const char *s; |
338 | size_t chars_left; | 338 | size_t chars_left; |
339 | 339 | ||
340 | strcpy(response, "OKAY"); | 340 | strcpy(response, "OKAY"); |
341 | chars_left = sizeof(response) - strlen(response) - 1; | 341 | chars_left = sizeof(response) - strlen(response) - 1; |
342 | 342 | ||
343 | strsep(&cmd, ":"); | 343 | strsep(&cmd, ":"); |
344 | if (!cmd) { | 344 | if (!cmd) { |
345 | error("missing variable\n"); | 345 | error("missing variable\n"); |
346 | fastboot_tx_write_str("FAILmissing var"); | 346 | fastboot_tx_write_str("FAILmissing var"); |
347 | return; | 347 | return; |
348 | } | 348 | } |
349 | 349 | ||
350 | if (!strcmp_l1("version", cmd)) { | 350 | if (!strcmp_l1("version", cmd)) { |
351 | strncat(response, FASTBOOT_VERSION, chars_left); | 351 | strncat(response, FASTBOOT_VERSION, chars_left); |
352 | } else if (!strcmp_l1("bootloader-version", cmd)) { | 352 | } else if (!strcmp_l1("bootloader-version", cmd)) { |
353 | strncat(response, U_BOOT_VERSION, chars_left); | 353 | strncat(response, U_BOOT_VERSION, chars_left); |
354 | } else if (!strcmp_l1("downloadsize", cmd)) { | 354 | } else if (!strcmp_l1("downloadsize", cmd) || |
355 | !strcmp_l1("max-download-size", cmd)) { | ||
355 | char str_num[12]; | 356 | char str_num[12]; |
356 | 357 | ||
357 | sprintf(str_num, "%08x", CONFIG_USB_FASTBOOT_BUF_SIZE); | 358 | sprintf(str_num, "0x%08x", CONFIG_USB_FASTBOOT_BUF_SIZE); |
358 | strncat(response, str_num, chars_left); | 359 | strncat(response, str_num, chars_left); |
359 | } else if (!strcmp_l1("serialno", cmd)) { | 360 | } else if (!strcmp_l1("serialno", cmd)) { |
360 | s = getenv("serial#"); | 361 | s = getenv("serial#"); |
361 | if (s) | 362 | if (s) |
362 | strncat(response, s, chars_left); | 363 | strncat(response, s, chars_left); |
363 | else | 364 | else |
364 | strcpy(response, "FAILValue not set"); | 365 | strcpy(response, "FAILValue not set"); |
365 | } else { | 366 | } else { |
366 | error("unknown variable: %s\n", cmd); | 367 | error("unknown variable: %s\n", cmd); |
367 | strcpy(response, "FAILVariable not implemented"); | 368 | strcpy(response, "FAILVariable not implemented"); |
368 | } | 369 | } |
369 | fastboot_tx_write_str(response); | 370 | fastboot_tx_write_str(response); |
370 | } | 371 | } |
371 | 372 | ||
372 | static unsigned int rx_bytes_expected(void) | 373 | static unsigned int rx_bytes_expected(void) |
373 | { | 374 | { |
374 | int rx_remain = download_size - download_bytes; | 375 | int rx_remain = download_size - download_bytes; |
375 | if (rx_remain < 0) | 376 | if (rx_remain < 0) |
376 | return 0; | 377 | return 0; |
377 | if (rx_remain > EP_BUFFER_SIZE) | 378 | if (rx_remain > EP_BUFFER_SIZE) |
378 | return EP_BUFFER_SIZE; | 379 | return EP_BUFFER_SIZE; |
379 | return rx_remain; | 380 | return rx_remain; |
380 | } | 381 | } |
381 | 382 | ||
382 | #define BYTES_PER_DOT 0x20000 | 383 | #define BYTES_PER_DOT 0x20000 |
383 | static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req) | 384 | static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req) |
384 | { | 385 | { |
385 | char response[RESPONSE_LEN]; | 386 | char response[RESPONSE_LEN]; |
386 | unsigned int transfer_size = download_size - download_bytes; | 387 | unsigned int transfer_size = download_size - download_bytes; |
387 | const unsigned char *buffer = req->buf; | 388 | const unsigned char *buffer = req->buf; |
388 | unsigned int buffer_size = req->actual; | 389 | unsigned int buffer_size = req->actual; |
390 | unsigned int pre_dot_num, now_dot_num; | ||
389 | 391 | ||
390 | if (req->status != 0) { | 392 | if (req->status != 0) { |
391 | printf("Bad status: %d\n", req->status); | 393 | printf("Bad status: %d\n", req->status); |
392 | return; | 394 | return; |
393 | } | 395 | } |
394 | 396 | ||
395 | if (buffer_size < transfer_size) | 397 | if (buffer_size < transfer_size) |
396 | transfer_size = buffer_size; | 398 | transfer_size = buffer_size; |
397 | 399 | ||
398 | memcpy((void *)CONFIG_USB_FASTBOOT_BUF_ADDR + download_bytes, | 400 | memcpy((void *)CONFIG_USB_FASTBOOT_BUF_ADDR + download_bytes, |
399 | buffer, transfer_size); | 401 | buffer, transfer_size); |
400 | 402 | ||
403 | pre_dot_num = download_bytes / BYTES_PER_DOT; | ||
401 | download_bytes += transfer_size; | 404 | download_bytes += transfer_size; |
405 | now_dot_num = download_bytes / BYTES_PER_DOT; | ||
402 | 406 | ||
407 | if (pre_dot_num != now_dot_num) { | ||
408 | putc('.'); | ||
409 | if (!(now_dot_num % 74)) | ||
410 | putc('\n'); | ||
411 | } | ||
412 | |||
403 | /* Check if transfer is done */ | 413 | /* Check if transfer is done */ |
404 | if (download_bytes >= download_size) { | 414 | if (download_bytes >= download_size) { |
405 | /* | 415 | /* |
406 | * Reset global transfer variable, keep download_bytes because | 416 | * Reset global transfer variable, keep download_bytes because |
407 | * it will be used in the next possible flashing command | 417 | * it will be used in the next possible flashing command |
408 | */ | 418 | */ |
409 | download_size = 0; | 419 | download_size = 0; |
410 | req->complete = rx_handler_command; | 420 | req->complete = rx_handler_command; |
411 | req->length = EP_BUFFER_SIZE; | 421 | req->length = EP_BUFFER_SIZE; |
412 | 422 | ||
413 | sprintf(response, "OKAY"); | 423 | sprintf(response, "OKAY"); |
414 | fastboot_tx_write_str(response); | 424 | fastboot_tx_write_str(response); |
415 | 425 | ||
416 | printf("\ndownloading of %d bytes finished\n", download_bytes); | 426 | printf("\ndownloading of %d bytes finished\n", download_bytes); |
417 | } else { | 427 | } else { |
418 | req->length = rx_bytes_expected(); | 428 | req->length = rx_bytes_expected(); |
419 | if (req->length < ep->maxpacket) | 429 | if (req->length < ep->maxpacket) |
420 | req->length = ep->maxpacket; | 430 | req->length = ep->maxpacket; |
421 | } | 431 | } |
422 | 432 | ||
423 | if (download_bytes && !(download_bytes % BYTES_PER_DOT)) { | ||
424 | putc('.'); | ||
425 | if (!(download_bytes % (74 * BYTES_PER_DOT))) | ||
426 | putc('\n'); | ||
427 | } | ||
428 | req->actual = 0; | 433 | req->actual = 0; |
429 | usb_ep_queue(ep, req, 0); | 434 | usb_ep_queue(ep, req, 0); |
430 | } | 435 | } |
431 | 436 | ||
432 | static void cb_download(struct usb_ep *ep, struct usb_request *req) | 437 | static void cb_download(struct usb_ep *ep, struct usb_request *req) |
433 | { | 438 | { |
434 | char *cmd = req->buf; | 439 | char *cmd = req->buf; |
435 | char response[RESPONSE_LEN]; | 440 | char response[RESPONSE_LEN]; |
436 | 441 | ||
437 | strsep(&cmd, ":"); | 442 | strsep(&cmd, ":"); |
438 | download_size = simple_strtoul(cmd, NULL, 16); | 443 | download_size = simple_strtoul(cmd, NULL, 16); |
439 | download_bytes = 0; | 444 | download_bytes = 0; |
440 | 445 | ||
441 | printf("Starting download of %d bytes\n", download_size); | 446 | printf("Starting download of %d bytes\n", download_size); |
442 | 447 | ||
443 | if (0 == download_size) { | 448 | if (0 == download_size) { |
444 | sprintf(response, "FAILdata invalid size"); | 449 | sprintf(response, "FAILdata invalid size"); |
445 | } else if (download_size > CONFIG_USB_FASTBOOT_BUF_SIZE) { | 450 | } else if (download_size > CONFIG_USB_FASTBOOT_BUF_SIZE) { |
446 | download_size = 0; | 451 | download_size = 0; |
447 | sprintf(response, "FAILdata too large"); | 452 | sprintf(response, "FAILdata too large"); |
448 | } else { | 453 | } else { |
449 | sprintf(response, "DATA%08x", download_size); | 454 | sprintf(response, "DATA%08x", download_size); |
450 | req->complete = rx_handler_dl_image; | 455 | req->complete = rx_handler_dl_image; |
451 | req->length = rx_bytes_expected(); | 456 | req->length = rx_bytes_expected(); |
452 | if (req->length < ep->maxpacket) | 457 | if (req->length < ep->maxpacket) |
453 | req->length = ep->maxpacket; | 458 | req->length = ep->maxpacket; |
454 | } | 459 | } |
455 | fastboot_tx_write_str(response); | 460 | fastboot_tx_write_str(response); |
456 | } | 461 | } |
457 | 462 | ||
458 | static void do_bootm_on_complete(struct usb_ep *ep, struct usb_request *req) | 463 | static void do_bootm_on_complete(struct usb_ep *ep, struct usb_request *req) |
459 | { | 464 | { |
460 | char boot_addr_start[12]; | 465 | char boot_addr_start[12]; |
461 | char *bootm_args[] = { "bootm", boot_addr_start, NULL }; | 466 | char *bootm_args[] = { "bootm", boot_addr_start, NULL }; |
462 | 467 | ||
463 | puts("Booting kernel..\n"); | 468 | puts("Booting kernel..\n"); |
464 | 469 | ||
465 | sprintf(boot_addr_start, "0x%lx", load_addr); | 470 | sprintf(boot_addr_start, "0x%lx", load_addr); |
466 | do_bootm(NULL, 0, 2, bootm_args); | 471 | do_bootm(NULL, 0, 2, bootm_args); |
467 | 472 | ||
468 | /* This only happens if image is somehow faulty so we start over */ | 473 | /* This only happens if image is somehow faulty so we start over */ |
469 | do_reset(NULL, 0, 0, NULL); | 474 | do_reset(NULL, 0, 0, NULL); |
470 | } | 475 | } |
471 | 476 | ||
472 | static void cb_boot(struct usb_ep *ep, struct usb_request *req) | 477 | static void cb_boot(struct usb_ep *ep, struct usb_request *req) |
473 | { | 478 | { |
474 | fastboot_func->in_req->complete = do_bootm_on_complete; | 479 | fastboot_func->in_req->complete = do_bootm_on_complete; |
475 | fastboot_tx_write_str("OKAY"); | 480 | fastboot_tx_write_str("OKAY"); |
476 | } | 481 | } |
477 | 482 | ||
478 | #ifdef CONFIG_FASTBOOT_FLASH | 483 | #ifdef CONFIG_FASTBOOT_FLASH |
479 | static void cb_flash(struct usb_ep *ep, struct usb_request *req) | 484 | static void cb_flash(struct usb_ep *ep, struct usb_request *req) |
480 | { | 485 | { |
481 | char *cmd = req->buf; | 486 | char *cmd = req->buf; |
482 | char response[RESPONSE_LEN]; | 487 | char response[RESPONSE_LEN]; |
483 | 488 | ||
484 | strsep(&cmd, ":"); | 489 | strsep(&cmd, ":"); |
485 | if (!cmd) { | 490 | if (!cmd) { |
486 | error("missing partition name\n"); | 491 | error("missing partition name\n"); |
487 | fastboot_tx_write_str("FAILmissing partition name"); | 492 | fastboot_tx_write_str("FAILmissing partition name"); |
488 | return; | 493 | return; |
489 | } | 494 | } |
490 | 495 | ||
491 | strcpy(response, "FAILno flash device defined"); | 496 | strcpy(response, "FAILno flash device defined"); |
492 | #ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV | 497 | #ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV |
493 | fb_mmc_flash_write(cmd, (void *)CONFIG_USB_FASTBOOT_BUF_ADDR, | 498 | fb_mmc_flash_write(cmd, (void *)CONFIG_USB_FASTBOOT_BUF_ADDR, |
494 | download_bytes, response); | 499 | download_bytes, response); |
495 | #endif | 500 | #endif |
496 | fastboot_tx_write_str(response); | 501 | fastboot_tx_write_str(response); |
497 | } | 502 | } |
498 | #endif | 503 | #endif |
499 | 504 | ||
500 | struct cmd_dispatch_info { | 505 | struct cmd_dispatch_info { |
501 | char *cmd; | 506 | char *cmd; |
502 | void (*cb)(struct usb_ep *ep, struct usb_request *req); | 507 | void (*cb)(struct usb_ep *ep, struct usb_request *req); |
503 | }; | 508 | }; |
504 | 509 | ||
505 | static const struct cmd_dispatch_info cmd_dispatch_info[] = { | 510 | static const struct cmd_dispatch_info cmd_dispatch_info[] = { |
506 | { | 511 | { |
507 | .cmd = "reboot", | 512 | .cmd = "reboot", |
508 | .cb = cb_reboot, | 513 | .cb = cb_reboot, |
509 | }, { | 514 | }, { |
510 | .cmd = "getvar:", | 515 | .cmd = "getvar:", |
511 | .cb = cb_getvar, | 516 | .cb = cb_getvar, |
512 | }, { | 517 | }, { |
513 | .cmd = "download:", | 518 | .cmd = "download:", |
514 | .cb = cb_download, | 519 | .cb = cb_download, |
515 | }, { | 520 | }, { |
516 | .cmd = "boot", | 521 | .cmd = "boot", |
517 | .cb = cb_boot, | 522 | .cb = cb_boot, |
518 | }, | 523 | }, |
519 | #ifdef CONFIG_FASTBOOT_FLASH | 524 | #ifdef CONFIG_FASTBOOT_FLASH |
520 | { | 525 | { |
521 | .cmd = "flash", | 526 | .cmd = "flash", |
522 | .cb = cb_flash, | 527 | .cb = cb_flash, |
523 | }, | 528 | }, |
524 | #endif | 529 | #endif |
525 | }; | 530 | }; |
526 | 531 | ||
527 | static void rx_handler_command(struct usb_ep *ep, struct usb_request *req) | 532 | static void rx_handler_command(struct usb_ep *ep, struct usb_request *req) |
528 | { | 533 | { |
529 | char *cmdbuf = req->buf; | 534 | char *cmdbuf = req->buf; |
530 | void (*func_cb)(struct usb_ep *ep, struct usb_request *req) = NULL; | 535 | void (*func_cb)(struct usb_ep *ep, struct usb_request *req) = NULL; |
531 | int i; | 536 | int i; |
532 | 537 | ||
533 | for (i = 0; i < ARRAY_SIZE(cmd_dispatch_info); i++) { | 538 | for (i = 0; i < ARRAY_SIZE(cmd_dispatch_info); i++) { |
534 | if (!strcmp_l1(cmd_dispatch_info[i].cmd, cmdbuf)) { | 539 | if (!strcmp_l1(cmd_dispatch_info[i].cmd, cmdbuf)) { |
535 | func_cb = cmd_dispatch_info[i].cb; | 540 | func_cb = cmd_dispatch_info[i].cb; |
536 | break; | 541 | break; |
537 | } | 542 | } |
538 | } | 543 | } |
539 | 544 | ||
540 | if (!func_cb) { | 545 | if (!func_cb) { |
541 | error("unknown command: %s\n", cmdbuf); | 546 | error("unknown command: %s\n", cmdbuf); |
542 | fastboot_tx_write_str("FAILunknown command"); | 547 | fastboot_tx_write_str("FAILunknown command"); |
543 | } else { | 548 | } else { |
544 | func_cb(ep, req); | 549 | if (req->actual < req->length) { |
550 | u8 *buf = (u8 *)req->buf; | ||
551 | buf[req->actual] = 0; | ||
552 | func_cb(ep, req); | ||
553 | } else { | ||
554 | error("buffer overflow\n"); | ||
555 | fastboot_tx_write_str("FAILbuffer overflow"); | ||
556 | } | ||
545 | } | 557 | } |
546 | 558 | ||
547 | if (req->status == 0) { | 559 | if (req->status == 0) { |
548 | *cmdbuf = '\0'; | 560 | *cmdbuf = '\0'; |
drivers/usb/gadget/f_mass_storage.c
1 | /* | 1 | /* |
2 | * f_mass_storage.c -- Mass Storage USB Composite Function | 2 | * f_mass_storage.c -- Mass Storage USB Composite Function |
3 | * | 3 | * |
4 | * Copyright (C) 2003-2008 Alan Stern | 4 | * Copyright (C) 2003-2008 Alan Stern |
5 | * Copyright (C) 2009 Samsung Electronics | 5 | * Copyright (C) 2009 Samsung Electronics |
6 | * Author: Michal Nazarewicz <m.nazarewicz@samsung.com> | 6 | * Author: Michal Nazarewicz <m.nazarewicz@samsung.com> |
7 | * All rights reserved. | 7 | * All rights reserved. |
8 | * | 8 | * |
9 | * SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause | 9 | * SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause |
10 | */ | 10 | */ |
11 | 11 | ||
12 | /* | 12 | /* |
13 | * The Mass Storage Function acts as a USB Mass Storage device, | 13 | * The Mass Storage Function acts as a USB Mass Storage device, |
14 | * appearing to the host as a disk drive or as a CD-ROM drive. In | 14 | * appearing to the host as a disk drive or as a CD-ROM drive. In |
15 | * addition to providing an example of a genuinely useful composite | 15 | * addition to providing an example of a genuinely useful composite |
16 | * function for a USB device, it also illustrates a technique of | 16 | * function for a USB device, it also illustrates a technique of |
17 | * double-buffering for increased throughput. | 17 | * double-buffering for increased throughput. |
18 | * | 18 | * |
19 | * Function supports multiple logical units (LUNs). Backing storage | 19 | * Function supports multiple logical units (LUNs). Backing storage |
20 | * for each LUN is provided by a regular file or a block device. | 20 | * for each LUN is provided by a regular file or a block device. |
21 | * Access for each LUN can be limited to read-only. Moreover, the | 21 | * Access for each LUN can be limited to read-only. Moreover, the |
22 | * function can indicate that LUN is removable and/or CD-ROM. (The | 22 | * function can indicate that LUN is removable and/or CD-ROM. (The |
23 | * later implies read-only access.) | 23 | * later implies read-only access.) |
24 | * | 24 | * |
25 | * MSF is configured by specifying a fsg_config structure. It has the | 25 | * MSF is configured by specifying a fsg_config structure. It has the |
26 | * following fields: | 26 | * following fields: |
27 | * | 27 | * |
28 | * nluns Number of LUNs function have (anywhere from 1 | 28 | * nluns Number of LUNs function have (anywhere from 1 |
29 | * to FSG_MAX_LUNS which is 8). | 29 | * to FSG_MAX_LUNS which is 8). |
30 | * luns An array of LUN configuration values. This | 30 | * luns An array of LUN configuration values. This |
31 | * should be filled for each LUN that | 31 | * should be filled for each LUN that |
32 | * function will include (ie. for "nluns" | 32 | * function will include (ie. for "nluns" |
33 | * LUNs). Each element of the array has | 33 | * LUNs). Each element of the array has |
34 | * the following fields: | 34 | * the following fields: |
35 | * ->filename The path to the backing file for the LUN. | 35 | * ->filename The path to the backing file for the LUN. |
36 | * Required if LUN is not marked as | 36 | * Required if LUN is not marked as |
37 | * removable. | 37 | * removable. |
38 | * ->ro Flag specifying access to the LUN shall be | 38 | * ->ro Flag specifying access to the LUN shall be |
39 | * read-only. This is implied if CD-ROM | 39 | * read-only. This is implied if CD-ROM |
40 | * emulation is enabled as well as when | 40 | * emulation is enabled as well as when |
41 | * it was impossible to open "filename" | 41 | * it was impossible to open "filename" |
42 | * in R/W mode. | 42 | * in R/W mode. |
43 | * ->removable Flag specifying that LUN shall be indicated as | 43 | * ->removable Flag specifying that LUN shall be indicated as |
44 | * being removable. | 44 | * being removable. |
45 | * ->cdrom Flag specifying that LUN shall be reported as | 45 | * ->cdrom Flag specifying that LUN shall be reported as |
46 | * being a CD-ROM. | 46 | * being a CD-ROM. |
47 | * | 47 | * |
48 | * lun_name_format A printf-like format for names of the LUN | 48 | * lun_name_format A printf-like format for names of the LUN |
49 | * devices. This determines how the | 49 | * devices. This determines how the |
50 | * directory in sysfs will be named. | 50 | * directory in sysfs will be named. |
51 | * Unless you are using several MSFs in | 51 | * Unless you are using several MSFs in |
52 | * a single gadget (as opposed to single | 52 | * a single gadget (as opposed to single |
53 | * MSF in many configurations) you may | 53 | * MSF in many configurations) you may |
54 | * leave it as NULL (in which case | 54 | * leave it as NULL (in which case |
55 | * "lun%d" will be used). In the format | 55 | * "lun%d" will be used). In the format |
56 | * you can use "%d" to index LUNs for | 56 | * you can use "%d" to index LUNs for |
57 | * MSF's with more than one LUN. (Beware | 57 | * MSF's with more than one LUN. (Beware |
58 | * that there is only one integer given | 58 | * that there is only one integer given |
59 | * as an argument for the format and | 59 | * as an argument for the format and |
60 | * specifying invalid format may cause | 60 | * specifying invalid format may cause |
61 | * unspecified behaviour.) | 61 | * unspecified behaviour.) |
62 | * thread_name Name of the kernel thread process used by the | 62 | * thread_name Name of the kernel thread process used by the |
63 | * MSF. You can safely set it to NULL | 63 | * MSF. You can safely set it to NULL |
64 | * (in which case default "file-storage" | 64 | * (in which case default "file-storage" |
65 | * will be used). | 65 | * will be used). |
66 | * | 66 | * |
67 | * vendor_name | 67 | * vendor_name |
68 | * product_name | 68 | * product_name |
69 | * release Information used as a reply to INQUIRY | 69 | * release Information used as a reply to INQUIRY |
70 | * request. To use default set to NULL, | 70 | * request. To use default set to NULL, |
71 | * NULL, 0xffff respectively. The first | 71 | * NULL, 0xffff respectively. The first |
72 | * field should be 8 and the second 16 | 72 | * field should be 8 and the second 16 |
73 | * characters or less. | 73 | * characters or less. |
74 | * | 74 | * |
75 | * can_stall Set to permit function to halt bulk endpoints. | 75 | * can_stall Set to permit function to halt bulk endpoints. |
76 | * Disabled on some USB devices known not | 76 | * Disabled on some USB devices known not |
77 | * to work correctly. You should set it | 77 | * to work correctly. You should set it |
78 | * to true. | 78 | * to true. |
79 | * | 79 | * |
80 | * If "removable" is not set for a LUN then a backing file must be | 80 | * If "removable" is not set for a LUN then a backing file must be |
81 | * specified. If it is set, then NULL filename means the LUN's medium | 81 | * specified. If it is set, then NULL filename means the LUN's medium |
82 | * is not loaded (an empty string as "filename" in the fsg_config | 82 | * is not loaded (an empty string as "filename" in the fsg_config |
83 | * structure causes error). The CD-ROM emulation includes a single | 83 | * structure causes error). The CD-ROM emulation includes a single |
84 | * data track and no audio tracks; hence there need be only one | 84 | * data track and no audio tracks; hence there need be only one |
85 | * backing file per LUN. Note also that the CD-ROM block length is | 85 | * backing file per LUN. Note also that the CD-ROM block length is |
86 | * set to 512 rather than the more common value 2048. | 86 | * set to 512 rather than the more common value 2048. |
87 | * | 87 | * |
88 | * | 88 | * |
89 | * MSF includes support for module parameters. If gadget using it | 89 | * MSF includes support for module parameters. If gadget using it |
90 | * decides to use it, the following module parameters will be | 90 | * decides to use it, the following module parameters will be |
91 | * available: | 91 | * available: |
92 | * | 92 | * |
93 | * file=filename[,filename...] | 93 | * file=filename[,filename...] |
94 | * Names of the files or block devices used for | 94 | * Names of the files or block devices used for |
95 | * backing storage. | 95 | * backing storage. |
96 | * ro=b[,b...] Default false, boolean for read-only access. | 96 | * ro=b[,b...] Default false, boolean for read-only access. |
97 | * removable=b[,b...] | 97 | * removable=b[,b...] |
98 | * Default true, boolean for removable media. | 98 | * Default true, boolean for removable media. |
99 | * cdrom=b[,b...] Default false, boolean for whether to emulate | 99 | * cdrom=b[,b...] Default false, boolean for whether to emulate |
100 | * a CD-ROM drive. | 100 | * a CD-ROM drive. |
101 | * luns=N Default N = number of filenames, number of | 101 | * luns=N Default N = number of filenames, number of |
102 | * LUNs to support. | 102 | * LUNs to support. |
103 | * stall Default determined according to the type of | 103 | * stall Default determined according to the type of |
104 | * USB device controller (usually true), | 104 | * USB device controller (usually true), |
105 | * boolean to permit the driver to halt | 105 | * boolean to permit the driver to halt |
106 | * bulk endpoints. | 106 | * bulk endpoints. |
107 | * | 107 | * |
108 | * The module parameters may be prefixed with some string. You need | 108 | * The module parameters may be prefixed with some string. You need |
109 | * to consult gadget's documentation or source to verify whether it is | 109 | * to consult gadget's documentation or source to verify whether it is |
110 | * using those module parameters and if it does what are the prefixes | 110 | * using those module parameters and if it does what are the prefixes |
111 | * (look for FSG_MODULE_PARAMETERS() macro usage, what's inside it is | 111 | * (look for FSG_MODULE_PARAMETERS() macro usage, what's inside it is |
112 | * the prefix). | 112 | * the prefix). |
113 | * | 113 | * |
114 | * | 114 | * |
115 | * Requirements are modest; only a bulk-in and a bulk-out endpoint are | 115 | * Requirements are modest; only a bulk-in and a bulk-out endpoint are |
116 | * needed. The memory requirement amounts to two 16K buffers, size | 116 | * needed. The memory requirement amounts to two 16K buffers, size |
117 | * configurable by a parameter. Support is included for both | 117 | * configurable by a parameter. Support is included for both |
118 | * full-speed and high-speed operation. | 118 | * full-speed and high-speed operation. |
119 | * | 119 | * |
120 | * Note that the driver is slightly non-portable in that it assumes a | 120 | * Note that the driver is slightly non-portable in that it assumes a |
121 | * single memory/DMA buffer will be useable for bulk-in, bulk-out, and | 121 | * single memory/DMA buffer will be useable for bulk-in, bulk-out, and |
122 | * interrupt-in endpoints. With most device controllers this isn't an | 122 | * interrupt-in endpoints. With most device controllers this isn't an |
123 | * issue, but there may be some with hardware restrictions that prevent | 123 | * issue, but there may be some with hardware restrictions that prevent |
124 | * a buffer from being used by more than one endpoint. | 124 | * a buffer from being used by more than one endpoint. |
125 | * | 125 | * |
126 | * | 126 | * |
127 | * The pathnames of the backing files and the ro settings are | 127 | * The pathnames of the backing files and the ro settings are |
128 | * available in the attribute files "file" and "ro" in the lun<n> (or | 128 | * available in the attribute files "file" and "ro" in the lun<n> (or |
129 | * to be more precise in a directory which name comes from | 129 | * to be more precise in a directory which name comes from |
130 | * "lun_name_format" option!) subdirectory of the gadget's sysfs | 130 | * "lun_name_format" option!) subdirectory of the gadget's sysfs |
131 | * directory. If the "removable" option is set, writing to these | 131 | * directory. If the "removable" option is set, writing to these |
132 | * files will simulate ejecting/loading the medium (writing an empty | 132 | * files will simulate ejecting/loading the medium (writing an empty |
133 | * line means eject) and adjusting a write-enable tab. Changes to the | 133 | * line means eject) and adjusting a write-enable tab. Changes to the |
134 | * ro setting are not allowed when the medium is loaded or if CD-ROM | 134 | * ro setting are not allowed when the medium is loaded or if CD-ROM |
135 | * emulation is being used. | 135 | * emulation is being used. |
136 | * | 136 | * |
137 | * When a LUN receive an "eject" SCSI request (Start/Stop Unit), | 137 | * When a LUN receive an "eject" SCSI request (Start/Stop Unit), |
138 | * if the LUN is removable, the backing file is released to simulate | 138 | * if the LUN is removable, the backing file is released to simulate |
139 | * ejection. | 139 | * ejection. |
140 | * | 140 | * |
141 | * | 141 | * |
142 | * This function is heavily based on "File-backed Storage Gadget" by | 142 | * This function is heavily based on "File-backed Storage Gadget" by |
143 | * Alan Stern which in turn is heavily based on "Gadget Zero" by David | 143 | * Alan Stern which in turn is heavily based on "Gadget Zero" by David |
144 | * Brownell. The driver's SCSI command interface was based on the | 144 | * Brownell. The driver's SCSI command interface was based on the |
145 | * "Information technology - Small Computer System Interface - 2" | 145 | * "Information technology - Small Computer System Interface - 2" |
146 | * document from X3T9.2 Project 375D, Revision 10L, 7-SEP-93, | 146 | * document from X3T9.2 Project 375D, Revision 10L, 7-SEP-93, |
147 | * available at <http://www.t10.org/ftp/t10/drafts/s2/s2-r10l.pdf>. | 147 | * available at <http://www.t10.org/ftp/t10/drafts/s2/s2-r10l.pdf>. |
148 | * The single exception is opcode 0x23 (READ FORMAT CAPACITIES), which | 148 | * The single exception is opcode 0x23 (READ FORMAT CAPACITIES), which |
149 | * was based on the "Universal Serial Bus Mass Storage Class UFI | 149 | * was based on the "Universal Serial Bus Mass Storage Class UFI |
150 | * Command Specification" document, Revision 1.0, December 14, 1998, | 150 | * Command Specification" document, Revision 1.0, December 14, 1998, |
151 | * available at | 151 | * available at |
152 | * <http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf>. | 152 | * <http://www.usb.org/developers/devclass_docs/usbmass-ufi10.pdf>. |
153 | */ | 153 | */ |
154 | 154 | ||
155 | /* | 155 | /* |
156 | * Driver Design | 156 | * Driver Design |
157 | * | 157 | * |
158 | * The MSF is fairly straightforward. There is a main kernel | 158 | * The MSF is fairly straightforward. There is a main kernel |
159 | * thread that handles most of the work. Interrupt routines field | 159 | * thread that handles most of the work. Interrupt routines field |
160 | * callbacks from the controller driver: bulk- and interrupt-request | 160 | * callbacks from the controller driver: bulk- and interrupt-request |
161 | * completion notifications, endpoint-0 events, and disconnect events. | 161 | * completion notifications, endpoint-0 events, and disconnect events. |
162 | * Completion events are passed to the main thread by wakeup calls. Many | 162 | * Completion events are passed to the main thread by wakeup calls. Many |
163 | * ep0 requests are handled at interrupt time, but SetInterface, | 163 | * ep0 requests are handled at interrupt time, but SetInterface, |
164 | * SetConfiguration, and device reset requests are forwarded to the | 164 | * SetConfiguration, and device reset requests are forwarded to the |
165 | * thread in the form of "exceptions" using SIGUSR1 signals (since they | 165 | * thread in the form of "exceptions" using SIGUSR1 signals (since they |
166 | * should interrupt any ongoing file I/O operations). | 166 | * should interrupt any ongoing file I/O operations). |
167 | * | 167 | * |
168 | * The thread's main routine implements the standard command/data/status | 168 | * The thread's main routine implements the standard command/data/status |
169 | * parts of a SCSI interaction. It and its subroutines are full of tests | 169 | * parts of a SCSI interaction. It and its subroutines are full of tests |
170 | * for pending signals/exceptions -- all this polling is necessary since | 170 | * for pending signals/exceptions -- all this polling is necessary since |
171 | * the kernel has no setjmp/longjmp equivalents. (Maybe this is an | 171 | * the kernel has no setjmp/longjmp equivalents. (Maybe this is an |
172 | * indication that the driver really wants to be running in userspace.) | 172 | * indication that the driver really wants to be running in userspace.) |
173 | * An important point is that so long as the thread is alive it keeps an | 173 | * An important point is that so long as the thread is alive it keeps an |
174 | * open reference to the backing file. This will prevent unmounting | 174 | * open reference to the backing file. This will prevent unmounting |
175 | * the backing file's underlying filesystem and could cause problems | 175 | * the backing file's underlying filesystem and could cause problems |
176 | * during system shutdown, for example. To prevent such problems, the | 176 | * during system shutdown, for example. To prevent such problems, the |
177 | * thread catches INT, TERM, and KILL signals and converts them into | 177 | * thread catches INT, TERM, and KILL signals and converts them into |
178 | * an EXIT exception. | 178 | * an EXIT exception. |
179 | * | 179 | * |
180 | * In normal operation the main thread is started during the gadget's | 180 | * In normal operation the main thread is started during the gadget's |
181 | * fsg_bind() callback and stopped during fsg_unbind(). But it can | 181 | * fsg_bind() callback and stopped during fsg_unbind(). But it can |
182 | * also exit when it receives a signal, and there's no point leaving | 182 | * also exit when it receives a signal, and there's no point leaving |
183 | * the gadget running when the thread is dead. At of this moment, MSF | 183 | * the gadget running when the thread is dead. At of this moment, MSF |
184 | * provides no way to deregister the gadget when thread dies -- maybe | 184 | * provides no way to deregister the gadget when thread dies -- maybe |
185 | * a callback functions is needed. | 185 | * a callback functions is needed. |
186 | * | 186 | * |
187 | * To provide maximum throughput, the driver uses a circular pipeline of | 187 | * To provide maximum throughput, the driver uses a circular pipeline of |
188 | * buffer heads (struct fsg_buffhd). In principle the pipeline can be | 188 | * buffer heads (struct fsg_buffhd). In principle the pipeline can be |
189 | * arbitrarily long; in practice the benefits don't justify having more | 189 | * arbitrarily long; in practice the benefits don't justify having more |
190 | * than 2 stages (i.e., double buffering). But it helps to think of the | 190 | * than 2 stages (i.e., double buffering). But it helps to think of the |
191 | * pipeline as being a long one. Each buffer head contains a bulk-in and | 191 | * pipeline as being a long one. Each buffer head contains a bulk-in and |
192 | * a bulk-out request pointer (since the buffer can be used for both | 192 | * a bulk-out request pointer (since the buffer can be used for both |
193 | * output and input -- directions always are given from the host's | 193 | * output and input -- directions always are given from the host's |
194 | * point of view) as well as a pointer to the buffer and various state | 194 | * point of view) as well as a pointer to the buffer and various state |
195 | * variables. | 195 | * variables. |
196 | * | 196 | * |
197 | * Use of the pipeline follows a simple protocol. There is a variable | 197 | * Use of the pipeline follows a simple protocol. There is a variable |
198 | * (fsg->next_buffhd_to_fill) that points to the next buffer head to use. | 198 | * (fsg->next_buffhd_to_fill) that points to the next buffer head to use. |
199 | * At any time that buffer head may still be in use from an earlier | 199 | * At any time that buffer head may still be in use from an earlier |
200 | * request, so each buffer head has a state variable indicating whether | 200 | * request, so each buffer head has a state variable indicating whether |
201 | * it is EMPTY, FULL, or BUSY. Typical use involves waiting for the | 201 | * it is EMPTY, FULL, or BUSY. Typical use involves waiting for the |
202 | * buffer head to be EMPTY, filling the buffer either by file I/O or by | 202 | * buffer head to be EMPTY, filling the buffer either by file I/O or by |
203 | * USB I/O (during which the buffer head is BUSY), and marking the buffer | 203 | * USB I/O (during which the buffer head is BUSY), and marking the buffer |
204 | * head FULL when the I/O is complete. Then the buffer will be emptied | 204 | * head FULL when the I/O is complete. Then the buffer will be emptied |
205 | * (again possibly by USB I/O, during which it is marked BUSY) and | 205 | * (again possibly by USB I/O, during which it is marked BUSY) and |
206 | * finally marked EMPTY again (possibly by a completion routine). | 206 | * finally marked EMPTY again (possibly by a completion routine). |
207 | * | 207 | * |
208 | * A module parameter tells the driver to avoid stalling the bulk | 208 | * A module parameter tells the driver to avoid stalling the bulk |
209 | * endpoints wherever the transport specification allows. This is | 209 | * endpoints wherever the transport specification allows. This is |
210 | * necessary for some UDCs like the SuperH, which cannot reliably clear a | 210 | * necessary for some UDCs like the SuperH, which cannot reliably clear a |
211 | * halt on a bulk endpoint. However, under certain circumstances the | 211 | * halt on a bulk endpoint. However, under certain circumstances the |
212 | * Bulk-only specification requires a stall. In such cases the driver | 212 | * Bulk-only specification requires a stall. In such cases the driver |
213 | * will halt the endpoint and set a flag indicating that it should clear | 213 | * will halt the endpoint and set a flag indicating that it should clear |
214 | * the halt in software during the next device reset. Hopefully this | 214 | * the halt in software during the next device reset. Hopefully this |
215 | * will permit everything to work correctly. Furthermore, although the | 215 | * will permit everything to work correctly. Furthermore, although the |
216 | * specification allows the bulk-out endpoint to halt when the host sends | 216 | * specification allows the bulk-out endpoint to halt when the host sends |
217 | * too much data, implementing this would cause an unavoidable race. | 217 | * too much data, implementing this would cause an unavoidable race. |
218 | * The driver will always use the "no-stall" approach for OUT transfers. | 218 | * The driver will always use the "no-stall" approach for OUT transfers. |
219 | * | 219 | * |
220 | * One subtle point concerns sending status-stage responses for ep0 | 220 | * One subtle point concerns sending status-stage responses for ep0 |
221 | * requests. Some of these requests, such as device reset, can involve | 221 | * requests. Some of these requests, such as device reset, can involve |
222 | * interrupting an ongoing file I/O operation, which might take an | 222 | * interrupting an ongoing file I/O operation, which might take an |
223 | * arbitrarily long time. During that delay the host might give up on | 223 | * arbitrarily long time. During that delay the host might give up on |
224 | * the original ep0 request and issue a new one. When that happens the | 224 | * the original ep0 request and issue a new one. When that happens the |
225 | * driver should not notify the host about completion of the original | 225 | * driver should not notify the host about completion of the original |
226 | * request, as the host will no longer be waiting for it. So the driver | 226 | * request, as the host will no longer be waiting for it. So the driver |
227 | * assigns to each ep0 request a unique tag, and it keeps track of the | 227 | * assigns to each ep0 request a unique tag, and it keeps track of the |
228 | * tag value of the request associated with a long-running exception | 228 | * tag value of the request associated with a long-running exception |
229 | * (device-reset, interface-change, or configuration-change). When the | 229 | * (device-reset, interface-change, or configuration-change). When the |
230 | * exception handler is finished, the status-stage response is submitted | 230 | * exception handler is finished, the status-stage response is submitted |
231 | * only if the current ep0 request tag is equal to the exception request | 231 | * only if the current ep0 request tag is equal to the exception request |
232 | * tag. Thus only the most recently received ep0 request will get a | 232 | * tag. Thus only the most recently received ep0 request will get a |
233 | * status-stage response. | 233 | * status-stage response. |
234 | * | 234 | * |
235 | * Warning: This driver source file is too long. It ought to be split up | 235 | * Warning: This driver source file is too long. It ought to be split up |
236 | * into a header file plus about 3 separate .c files, to handle the details | 236 | * into a header file plus about 3 separate .c files, to handle the details |
237 | * of the Gadget, USB Mass Storage, and SCSI protocols. | 237 | * of the Gadget, USB Mass Storage, and SCSI protocols. |
238 | */ | 238 | */ |
239 | 239 | ||
240 | /* #define VERBOSE_DEBUG */ | 240 | /* #define VERBOSE_DEBUG */ |
241 | /* #define DUMP_MSGS */ | 241 | /* #define DUMP_MSGS */ |
242 | 242 | ||
243 | #include <config.h> | 243 | #include <config.h> |
244 | #include <malloc.h> | 244 | #include <malloc.h> |
245 | #include <common.h> | 245 | #include <common.h> |
246 | #include <g_dnl.h> | 246 | #include <g_dnl.h> |
247 | 247 | ||
248 | #include <linux/err.h> | 248 | #include <linux/err.h> |
249 | #include <linux/usb/ch9.h> | 249 | #include <linux/usb/ch9.h> |
250 | #include <linux/usb/gadget.h> | 250 | #include <linux/usb/gadget.h> |
251 | #include <usb_mass_storage.h> | 251 | #include <usb_mass_storage.h> |
252 | 252 | ||
253 | #include <asm/unaligned.h> | 253 | #include <asm/unaligned.h> |
254 | #include <linux/usb/gadget.h> | 254 | #include <linux/usb/gadget.h> |
255 | #include <linux/usb/gadget.h> | 255 | #include <linux/usb/gadget.h> |
256 | #include <linux/usb/composite.h> | 256 | #include <linux/usb/composite.h> |
257 | #include <usb/lin_gadget_compat.h> | 257 | #include <usb/lin_gadget_compat.h> |
258 | #include <g_dnl.h> | 258 | #include <g_dnl.h> |
259 | 259 | ||
260 | /*------------------------------------------------------------------------*/ | 260 | /*------------------------------------------------------------------------*/ |
261 | 261 | ||
262 | #define FSG_DRIVER_DESC "Mass Storage Function" | 262 | #define FSG_DRIVER_DESC "Mass Storage Function" |
263 | #define FSG_DRIVER_VERSION "2012/06/5" | 263 | #define FSG_DRIVER_VERSION "2012/06/5" |
264 | 264 | ||
265 | static const char fsg_string_interface[] = "Mass Storage"; | 265 | static const char fsg_string_interface[] = "Mass Storage"; |
266 | 266 | ||
267 | #define FSG_NO_INTR_EP 1 | 267 | #define FSG_NO_INTR_EP 1 |
268 | #define FSG_NO_DEVICE_STRINGS 1 | 268 | #define FSG_NO_DEVICE_STRINGS 1 |
269 | #define FSG_NO_OTG 1 | 269 | #define FSG_NO_OTG 1 |
270 | #define FSG_NO_INTR_EP 1 | 270 | #define FSG_NO_INTR_EP 1 |
271 | 271 | ||
272 | #include "storage_common.c" | 272 | #include "storage_common.c" |
273 | 273 | ||
274 | /*-------------------------------------------------------------------------*/ | 274 | /*-------------------------------------------------------------------------*/ |
275 | 275 | ||
276 | #define GFP_ATOMIC ((gfp_t) 0) | 276 | #define GFP_ATOMIC ((gfp_t) 0) |
277 | #define PAGE_CACHE_SHIFT 12 | 277 | #define PAGE_CACHE_SHIFT 12 |
278 | #define PAGE_CACHE_SIZE (1 << PAGE_CACHE_SHIFT) | 278 | #define PAGE_CACHE_SIZE (1 << PAGE_CACHE_SHIFT) |
279 | #define kthread_create(...) __builtin_return_address(0) | 279 | #define kthread_create(...) __builtin_return_address(0) |
280 | #define wait_for_completion(...) do {} while (0) | 280 | #define wait_for_completion(...) do {} while (0) |
281 | 281 | ||
282 | struct kref {int x; }; | 282 | struct kref {int x; }; |
283 | struct completion {int x; }; | 283 | struct completion {int x; }; |
284 | 284 | ||
285 | inline void set_bit(int nr, volatile void *addr) | 285 | inline void set_bit(int nr, volatile void *addr) |
286 | { | 286 | { |
287 | int mask; | 287 | int mask; |
288 | unsigned int *a = (unsigned int *) addr; | 288 | unsigned int *a = (unsigned int *) addr; |
289 | 289 | ||
290 | a += nr >> 5; | 290 | a += nr >> 5; |
291 | mask = 1 << (nr & 0x1f); | 291 | mask = 1 << (nr & 0x1f); |
292 | *a |= mask; | 292 | *a |= mask; |
293 | } | 293 | } |
294 | 294 | ||
295 | inline void clear_bit(int nr, volatile void *addr) | 295 | inline void clear_bit(int nr, volatile void *addr) |
296 | { | 296 | { |
297 | int mask; | 297 | int mask; |
298 | unsigned int *a = (unsigned int *) addr; | 298 | unsigned int *a = (unsigned int *) addr; |
299 | 299 | ||
300 | a += nr >> 5; | 300 | a += nr >> 5; |
301 | mask = 1 << (nr & 0x1f); | 301 | mask = 1 << (nr & 0x1f); |
302 | *a &= ~mask; | 302 | *a &= ~mask; |
303 | } | 303 | } |
304 | 304 | ||
305 | struct fsg_dev; | 305 | struct fsg_dev; |
306 | struct fsg_common; | 306 | struct fsg_common; |
307 | 307 | ||
308 | /* Data shared by all the FSG instances. */ | 308 | /* Data shared by all the FSG instances. */ |
309 | struct fsg_common { | 309 | struct fsg_common { |
310 | struct usb_gadget *gadget; | 310 | struct usb_gadget *gadget; |
311 | struct fsg_dev *fsg, *new_fsg; | 311 | struct fsg_dev *fsg, *new_fsg; |
312 | 312 | ||
313 | struct usb_ep *ep0; /* Copy of gadget->ep0 */ | 313 | struct usb_ep *ep0; /* Copy of gadget->ep0 */ |
314 | struct usb_request *ep0req; /* Copy of cdev->req */ | 314 | struct usb_request *ep0req; /* Copy of cdev->req */ |
315 | unsigned int ep0_req_tag; | 315 | unsigned int ep0_req_tag; |
316 | 316 | ||
317 | struct fsg_buffhd *next_buffhd_to_fill; | 317 | struct fsg_buffhd *next_buffhd_to_fill; |
318 | struct fsg_buffhd *next_buffhd_to_drain; | 318 | struct fsg_buffhd *next_buffhd_to_drain; |
319 | struct fsg_buffhd buffhds[FSG_NUM_BUFFERS]; | 319 | struct fsg_buffhd buffhds[FSG_NUM_BUFFERS]; |
320 | 320 | ||
321 | int cmnd_size; | 321 | int cmnd_size; |
322 | u8 cmnd[MAX_COMMAND_SIZE]; | 322 | u8 cmnd[MAX_COMMAND_SIZE]; |
323 | 323 | ||
324 | unsigned int nluns; | 324 | unsigned int nluns; |
325 | unsigned int lun; | 325 | unsigned int lun; |
326 | struct fsg_lun luns[FSG_MAX_LUNS]; | 326 | struct fsg_lun luns[FSG_MAX_LUNS]; |
327 | 327 | ||
328 | unsigned int bulk_out_maxpacket; | 328 | unsigned int bulk_out_maxpacket; |
329 | enum fsg_state state; /* For exception handling */ | 329 | enum fsg_state state; /* For exception handling */ |
330 | unsigned int exception_req_tag; | 330 | unsigned int exception_req_tag; |
331 | 331 | ||
332 | enum data_direction data_dir; | 332 | enum data_direction data_dir; |
333 | u32 data_size; | 333 | u32 data_size; |
334 | u32 data_size_from_cmnd; | 334 | u32 data_size_from_cmnd; |
335 | u32 tag; | 335 | u32 tag; |
336 | u32 residue; | 336 | u32 residue; |
337 | u32 usb_amount_left; | 337 | u32 usb_amount_left; |
338 | 338 | ||
339 | unsigned int can_stall:1; | 339 | unsigned int can_stall:1; |
340 | unsigned int free_storage_on_release:1; | 340 | unsigned int free_storage_on_release:1; |
341 | unsigned int phase_error:1; | 341 | unsigned int phase_error:1; |
342 | unsigned int short_packet_received:1; | 342 | unsigned int short_packet_received:1; |
343 | unsigned int bad_lun_okay:1; | 343 | unsigned int bad_lun_okay:1; |
344 | unsigned int running:1; | 344 | unsigned int running:1; |
345 | 345 | ||
346 | int thread_wakeup_needed; | 346 | int thread_wakeup_needed; |
347 | struct completion thread_notifier; | 347 | struct completion thread_notifier; |
348 | struct task_struct *thread_task; | 348 | struct task_struct *thread_task; |
349 | 349 | ||
350 | /* Callback functions. */ | 350 | /* Callback functions. */ |
351 | const struct fsg_operations *ops; | 351 | const struct fsg_operations *ops; |
352 | /* Gadget's private data. */ | 352 | /* Gadget's private data. */ |
353 | void *private_data; | 353 | void *private_data; |
354 | 354 | ||
355 | const char *vendor_name; /* 8 characters or less */ | 355 | const char *vendor_name; /* 8 characters or less */ |
356 | const char *product_name; /* 16 characters or less */ | 356 | const char *product_name; /* 16 characters or less */ |
357 | u16 release; | 357 | u16 release; |
358 | 358 | ||
359 | /* Vendor (8 chars), product (16 chars), release (4 | 359 | /* Vendor (8 chars), product (16 chars), release (4 |
360 | * hexadecimal digits) and NUL byte */ | 360 | * hexadecimal digits) and NUL byte */ |
361 | char inquiry_string[8 + 16 + 4 + 1]; | 361 | char inquiry_string[8 + 16 + 4 + 1]; |
362 | 362 | ||
363 | struct kref ref; | 363 | struct kref ref; |
364 | }; | 364 | }; |
365 | 365 | ||
366 | struct fsg_config { | 366 | struct fsg_config { |
367 | unsigned nluns; | 367 | unsigned nluns; |
368 | struct fsg_lun_config { | 368 | struct fsg_lun_config { |
369 | const char *filename; | 369 | const char *filename; |
370 | char ro; | 370 | char ro; |
371 | char removable; | 371 | char removable; |
372 | char cdrom; | 372 | char cdrom; |
373 | char nofua; | 373 | char nofua; |
374 | } luns[FSG_MAX_LUNS]; | 374 | } luns[FSG_MAX_LUNS]; |
375 | 375 | ||
376 | /* Callback functions. */ | 376 | /* Callback functions. */ |
377 | const struct fsg_operations *ops; | 377 | const struct fsg_operations *ops; |
378 | /* Gadget's private data. */ | 378 | /* Gadget's private data. */ |
379 | void *private_data; | 379 | void *private_data; |
380 | 380 | ||
381 | const char *vendor_name; /* 8 characters or less */ | 381 | const char *vendor_name; /* 8 characters or less */ |
382 | const char *product_name; /* 16 characters or less */ | 382 | const char *product_name; /* 16 characters or less */ |
383 | 383 | ||
384 | char can_stall; | 384 | char can_stall; |
385 | }; | 385 | }; |
386 | 386 | ||
387 | struct fsg_dev { | 387 | struct fsg_dev { |
388 | struct usb_function function; | 388 | struct usb_function function; |
389 | struct usb_gadget *gadget; /* Copy of cdev->gadget */ | 389 | struct usb_gadget *gadget; /* Copy of cdev->gadget */ |
390 | struct fsg_common *common; | 390 | struct fsg_common *common; |
391 | 391 | ||
392 | u16 interface_number; | 392 | u16 interface_number; |
393 | 393 | ||
394 | unsigned int bulk_in_enabled:1; | 394 | unsigned int bulk_in_enabled:1; |
395 | unsigned int bulk_out_enabled:1; | 395 | unsigned int bulk_out_enabled:1; |
396 | 396 | ||
397 | unsigned long atomic_bitflags; | 397 | unsigned long atomic_bitflags; |
398 | #define IGNORE_BULK_OUT 0 | 398 | #define IGNORE_BULK_OUT 0 |
399 | 399 | ||
400 | struct usb_ep *bulk_in; | 400 | struct usb_ep *bulk_in; |
401 | struct usb_ep *bulk_out; | 401 | struct usb_ep *bulk_out; |
402 | }; | 402 | }; |
403 | 403 | ||
404 | 404 | ||
405 | static inline int __fsg_is_set(struct fsg_common *common, | 405 | static inline int __fsg_is_set(struct fsg_common *common, |
406 | const char *func, unsigned line) | 406 | const char *func, unsigned line) |
407 | { | 407 | { |
408 | if (common->fsg) | 408 | if (common->fsg) |
409 | return 1; | 409 | return 1; |
410 | ERROR(common, "common->fsg is NULL in %s at %u\n", func, line); | 410 | ERROR(common, "common->fsg is NULL in %s at %u\n", func, line); |
411 | WARN_ON(1); | 411 | WARN_ON(1); |
412 | return 0; | 412 | return 0; |
413 | } | 413 | } |
414 | 414 | ||
415 | #define fsg_is_set(common) likely(__fsg_is_set(common, __func__, __LINE__)) | 415 | #define fsg_is_set(common) likely(__fsg_is_set(common, __func__, __LINE__)) |
416 | 416 | ||
417 | 417 | ||
418 | static inline struct fsg_dev *fsg_from_func(struct usb_function *f) | 418 | static inline struct fsg_dev *fsg_from_func(struct usb_function *f) |
419 | { | 419 | { |
420 | return container_of(f, struct fsg_dev, function); | 420 | return container_of(f, struct fsg_dev, function); |
421 | } | 421 | } |
422 | 422 | ||
423 | 423 | ||
424 | typedef void (*fsg_routine_t)(struct fsg_dev *); | 424 | typedef void (*fsg_routine_t)(struct fsg_dev *); |
425 | 425 | ||
426 | static int exception_in_progress(struct fsg_common *common) | 426 | static int exception_in_progress(struct fsg_common *common) |
427 | { | 427 | { |
428 | return common->state > FSG_STATE_IDLE; | 428 | return common->state > FSG_STATE_IDLE; |
429 | } | 429 | } |
430 | 430 | ||
431 | /* Make bulk-out requests be divisible by the maxpacket size */ | 431 | /* Make bulk-out requests be divisible by the maxpacket size */ |
432 | static void set_bulk_out_req_length(struct fsg_common *common, | 432 | static void set_bulk_out_req_length(struct fsg_common *common, |
433 | struct fsg_buffhd *bh, unsigned int length) | 433 | struct fsg_buffhd *bh, unsigned int length) |
434 | { | 434 | { |
435 | unsigned int rem; | 435 | unsigned int rem; |
436 | 436 | ||
437 | bh->bulk_out_intended_length = length; | 437 | bh->bulk_out_intended_length = length; |
438 | rem = length % common->bulk_out_maxpacket; | 438 | rem = length % common->bulk_out_maxpacket; |
439 | if (rem > 0) | 439 | if (rem > 0) |
440 | length += common->bulk_out_maxpacket - rem; | 440 | length += common->bulk_out_maxpacket - rem; |
441 | bh->outreq->length = length; | 441 | bh->outreq->length = length; |
442 | } | 442 | } |
443 | 443 | ||
444 | /*-------------------------------------------------------------------------*/ | 444 | /*-------------------------------------------------------------------------*/ |
445 | 445 | ||
446 | struct ums *ums; | 446 | struct ums *ums; |
447 | struct fsg_common *the_fsg_common; | 447 | struct fsg_common *the_fsg_common; |
448 | 448 | ||
449 | static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) | 449 | static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) |
450 | { | 450 | { |
451 | const char *name; | 451 | const char *name; |
452 | 452 | ||
453 | if (ep == fsg->bulk_in) | 453 | if (ep == fsg->bulk_in) |
454 | name = "bulk-in"; | 454 | name = "bulk-in"; |
455 | else if (ep == fsg->bulk_out) | 455 | else if (ep == fsg->bulk_out) |
456 | name = "bulk-out"; | 456 | name = "bulk-out"; |
457 | else | 457 | else |
458 | name = ep->name; | 458 | name = ep->name; |
459 | DBG(fsg, "%s set halt\n", name); | 459 | DBG(fsg, "%s set halt\n", name); |
460 | return usb_ep_set_halt(ep); | 460 | return usb_ep_set_halt(ep); |
461 | } | 461 | } |
462 | 462 | ||
463 | /*-------------------------------------------------------------------------*/ | 463 | /*-------------------------------------------------------------------------*/ |
464 | 464 | ||
465 | /* These routines may be called in process context or in_irq */ | 465 | /* These routines may be called in process context or in_irq */ |
466 | 466 | ||
467 | /* Caller must hold fsg->lock */ | 467 | /* Caller must hold fsg->lock */ |
468 | static void wakeup_thread(struct fsg_common *common) | 468 | static void wakeup_thread(struct fsg_common *common) |
469 | { | 469 | { |
470 | common->thread_wakeup_needed = 1; | 470 | common->thread_wakeup_needed = 1; |
471 | } | 471 | } |
472 | 472 | ||
473 | static void raise_exception(struct fsg_common *common, enum fsg_state new_state) | 473 | static void raise_exception(struct fsg_common *common, enum fsg_state new_state) |
474 | { | 474 | { |
475 | /* Do nothing if a higher-priority exception is already in progress. | 475 | /* Do nothing if a higher-priority exception is already in progress. |
476 | * If a lower-or-equal priority exception is in progress, preempt it | 476 | * If a lower-or-equal priority exception is in progress, preempt it |
477 | * and notify the main thread by sending it a signal. */ | 477 | * and notify the main thread by sending it a signal. */ |
478 | if (common->state <= new_state) { | 478 | if (common->state <= new_state) { |
479 | common->exception_req_tag = common->ep0_req_tag; | 479 | common->exception_req_tag = common->ep0_req_tag; |
480 | common->state = new_state; | 480 | common->state = new_state; |
481 | common->thread_wakeup_needed = 1; | 481 | common->thread_wakeup_needed = 1; |
482 | } | 482 | } |
483 | } | 483 | } |
484 | 484 | ||
485 | /*-------------------------------------------------------------------------*/ | 485 | /*-------------------------------------------------------------------------*/ |
486 | 486 | ||
487 | static int ep0_queue(struct fsg_common *common) | 487 | static int ep0_queue(struct fsg_common *common) |
488 | { | 488 | { |
489 | int rc; | 489 | int rc; |
490 | 490 | ||
491 | rc = usb_ep_queue(common->ep0, common->ep0req, GFP_ATOMIC); | 491 | rc = usb_ep_queue(common->ep0, common->ep0req, GFP_ATOMIC); |
492 | common->ep0->driver_data = common; | 492 | common->ep0->driver_data = common; |
493 | if (rc != 0 && rc != -ESHUTDOWN) { | 493 | if (rc != 0 && rc != -ESHUTDOWN) { |
494 | /* We can't do much more than wait for a reset */ | 494 | /* We can't do much more than wait for a reset */ |
495 | WARNING(common, "error in submission: %s --> %d\n", | 495 | WARNING(common, "error in submission: %s --> %d\n", |
496 | common->ep0->name, rc); | 496 | common->ep0->name, rc); |
497 | } | 497 | } |
498 | return rc; | 498 | return rc; |
499 | } | 499 | } |
500 | 500 | ||
501 | /*-------------------------------------------------------------------------*/ | 501 | /*-------------------------------------------------------------------------*/ |
502 | 502 | ||
503 | /* Bulk and interrupt endpoint completion handlers. | 503 | /* Bulk and interrupt endpoint completion handlers. |
504 | * These always run in_irq. */ | 504 | * These always run in_irq. */ |
505 | 505 | ||
506 | static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req) | 506 | static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req) |
507 | { | 507 | { |
508 | struct fsg_common *common = ep->driver_data; | 508 | struct fsg_common *common = ep->driver_data; |
509 | struct fsg_buffhd *bh = req->context; | 509 | struct fsg_buffhd *bh = req->context; |
510 | 510 | ||
511 | if (req->status || req->actual != req->length) | 511 | if (req->status || req->actual != req->length) |
512 | DBG(common, "%s --> %d, %u/%u\n", __func__, | 512 | DBG(common, "%s --> %d, %u/%u\n", __func__, |
513 | req->status, req->actual, req->length); | 513 | req->status, req->actual, req->length); |
514 | if (req->status == -ECONNRESET) /* Request was cancelled */ | 514 | if (req->status == -ECONNRESET) /* Request was cancelled */ |
515 | usb_ep_fifo_flush(ep); | 515 | usb_ep_fifo_flush(ep); |
516 | 516 | ||
517 | /* Hold the lock while we update the request and buffer states */ | 517 | /* Hold the lock while we update the request and buffer states */ |
518 | bh->inreq_busy = 0; | 518 | bh->inreq_busy = 0; |
519 | bh->state = BUF_STATE_EMPTY; | 519 | bh->state = BUF_STATE_EMPTY; |
520 | wakeup_thread(common); | 520 | wakeup_thread(common); |
521 | } | 521 | } |
522 | 522 | ||
523 | static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) | 523 | static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) |
524 | { | 524 | { |
525 | struct fsg_common *common = ep->driver_data; | 525 | struct fsg_common *common = ep->driver_data; |
526 | struct fsg_buffhd *bh = req->context; | 526 | struct fsg_buffhd *bh = req->context; |
527 | 527 | ||
528 | dump_msg(common, "bulk-out", req->buf, req->actual); | 528 | dump_msg(common, "bulk-out", req->buf, req->actual); |
529 | if (req->status || req->actual != bh->bulk_out_intended_length) | 529 | if (req->status || req->actual != bh->bulk_out_intended_length) |
530 | DBG(common, "%s --> %d, %u/%u\n", __func__, | 530 | DBG(common, "%s --> %d, %u/%u\n", __func__, |
531 | req->status, req->actual, | 531 | req->status, req->actual, |
532 | bh->bulk_out_intended_length); | 532 | bh->bulk_out_intended_length); |
533 | if (req->status == -ECONNRESET) /* Request was cancelled */ | 533 | if (req->status == -ECONNRESET) /* Request was cancelled */ |
534 | usb_ep_fifo_flush(ep); | 534 | usb_ep_fifo_flush(ep); |
535 | 535 | ||
536 | /* Hold the lock while we update the request and buffer states */ | 536 | /* Hold the lock while we update the request and buffer states */ |
537 | bh->outreq_busy = 0; | 537 | bh->outreq_busy = 0; |
538 | bh->state = BUF_STATE_FULL; | 538 | bh->state = BUF_STATE_FULL; |
539 | wakeup_thread(common); | 539 | wakeup_thread(common); |
540 | } | 540 | } |
541 | 541 | ||
542 | /*-------------------------------------------------------------------------*/ | 542 | /*-------------------------------------------------------------------------*/ |
543 | 543 | ||
544 | /* Ep0 class-specific handlers. These always run in_irq. */ | 544 | /* Ep0 class-specific handlers. These always run in_irq. */ |
545 | 545 | ||
546 | static int fsg_setup(struct usb_function *f, | 546 | static int fsg_setup(struct usb_function *f, |
547 | const struct usb_ctrlrequest *ctrl) | 547 | const struct usb_ctrlrequest *ctrl) |
548 | { | 548 | { |
549 | struct fsg_dev *fsg = fsg_from_func(f); | 549 | struct fsg_dev *fsg = fsg_from_func(f); |
550 | struct usb_request *req = fsg->common->ep0req; | 550 | struct usb_request *req = fsg->common->ep0req; |
551 | u16 w_index = get_unaligned_le16(&ctrl->wIndex); | 551 | u16 w_index = get_unaligned_le16(&ctrl->wIndex); |
552 | u16 w_value = get_unaligned_le16(&ctrl->wValue); | 552 | u16 w_value = get_unaligned_le16(&ctrl->wValue); |
553 | u16 w_length = get_unaligned_le16(&ctrl->wLength); | 553 | u16 w_length = get_unaligned_le16(&ctrl->wLength); |
554 | 554 | ||
555 | if (!fsg_is_set(fsg->common)) | 555 | if (!fsg_is_set(fsg->common)) |
556 | return -EOPNOTSUPP; | 556 | return -EOPNOTSUPP; |
557 | 557 | ||
558 | switch (ctrl->bRequest) { | 558 | switch (ctrl->bRequest) { |
559 | 559 | ||
560 | case USB_BULK_RESET_REQUEST: | 560 | case USB_BULK_RESET_REQUEST: |
561 | if (ctrl->bRequestType != | 561 | if (ctrl->bRequestType != |
562 | (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) | 562 | (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) |
563 | break; | 563 | break; |
564 | if (w_index != fsg->interface_number || w_value != 0) | 564 | if (w_index != fsg->interface_number || w_value != 0) |
565 | return -EDOM; | 565 | return -EDOM; |
566 | 566 | ||
567 | /* Raise an exception to stop the current operation | 567 | /* Raise an exception to stop the current operation |
568 | * and reinitialize our state. */ | 568 | * and reinitialize our state. */ |
569 | DBG(fsg, "bulk reset request\n"); | 569 | DBG(fsg, "bulk reset request\n"); |
570 | raise_exception(fsg->common, FSG_STATE_RESET); | 570 | raise_exception(fsg->common, FSG_STATE_RESET); |
571 | return DELAYED_STATUS; | 571 | return DELAYED_STATUS; |
572 | 572 | ||
573 | case USB_BULK_GET_MAX_LUN_REQUEST: | 573 | case USB_BULK_GET_MAX_LUN_REQUEST: |
574 | if (ctrl->bRequestType != | 574 | if (ctrl->bRequestType != |
575 | (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) | 575 | (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) |
576 | break; | 576 | break; |
577 | if (w_index != fsg->interface_number || w_value != 0) | 577 | if (w_index != fsg->interface_number || w_value != 0) |
578 | return -EDOM; | 578 | return -EDOM; |
579 | VDBG(fsg, "get max LUN\n"); | 579 | VDBG(fsg, "get max LUN\n"); |
580 | *(u8 *) req->buf = fsg->common->nluns - 1; | 580 | *(u8 *) req->buf = fsg->common->nluns - 1; |
581 | 581 | ||
582 | /* Respond with data/status */ | 582 | /* Respond with data/status */ |
583 | req->length = min((u16)1, w_length); | 583 | req->length = min((u16)1, w_length); |
584 | return ep0_queue(fsg->common); | 584 | return ep0_queue(fsg->common); |
585 | } | 585 | } |
586 | 586 | ||
587 | VDBG(fsg, | 587 | VDBG(fsg, |
588 | "unknown class-specific control req " | 588 | "unknown class-specific control req " |
589 | "%02x.%02x v%04x i%04x l%u\n", | 589 | "%02x.%02x v%04x i%04x l%u\n", |
590 | ctrl->bRequestType, ctrl->bRequest, | 590 | ctrl->bRequestType, ctrl->bRequest, |
591 | get_unaligned_le16(&ctrl->wValue), w_index, w_length); | 591 | get_unaligned_le16(&ctrl->wValue), w_index, w_length); |
592 | return -EOPNOTSUPP; | 592 | return -EOPNOTSUPP; |
593 | } | 593 | } |
594 | 594 | ||
595 | /*-------------------------------------------------------------------------*/ | 595 | /*-------------------------------------------------------------------------*/ |
596 | 596 | ||
597 | /* All the following routines run in process context */ | 597 | /* All the following routines run in process context */ |
598 | 598 | ||
599 | /* Use this for bulk or interrupt transfers, not ep0 */ | 599 | /* Use this for bulk or interrupt transfers, not ep0 */ |
600 | static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep, | 600 | static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep, |
601 | struct usb_request *req, int *pbusy, | 601 | struct usb_request *req, int *pbusy, |
602 | enum fsg_buffer_state *state) | 602 | enum fsg_buffer_state *state) |
603 | { | 603 | { |
604 | int rc; | 604 | int rc; |
605 | 605 | ||
606 | if (ep == fsg->bulk_in) | 606 | if (ep == fsg->bulk_in) |
607 | dump_msg(fsg, "bulk-in", req->buf, req->length); | 607 | dump_msg(fsg, "bulk-in", req->buf, req->length); |
608 | 608 | ||
609 | *pbusy = 1; | 609 | *pbusy = 1; |
610 | *state = BUF_STATE_BUSY; | 610 | *state = BUF_STATE_BUSY; |
611 | rc = usb_ep_queue(ep, req, GFP_KERNEL); | 611 | rc = usb_ep_queue(ep, req, GFP_KERNEL); |
612 | if (rc != 0) { | 612 | if (rc != 0) { |
613 | *pbusy = 0; | 613 | *pbusy = 0; |
614 | *state = BUF_STATE_EMPTY; | 614 | *state = BUF_STATE_EMPTY; |
615 | 615 | ||
616 | /* We can't do much more than wait for a reset */ | 616 | /* We can't do much more than wait for a reset */ |
617 | 617 | ||
618 | /* Note: currently the net2280 driver fails zero-length | 618 | /* Note: currently the net2280 driver fails zero-length |
619 | * submissions if DMA is enabled. */ | 619 | * submissions if DMA is enabled. */ |
620 | if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP && | 620 | if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP && |
621 | req->length == 0)) | 621 | req->length == 0)) |
622 | WARNING(fsg, "error in submission: %s --> %d\n", | 622 | WARNING(fsg, "error in submission: %s --> %d\n", |
623 | ep->name, rc); | 623 | ep->name, rc); |
624 | } | 624 | } |
625 | } | 625 | } |
626 | 626 | ||
627 | #define START_TRANSFER_OR(common, ep_name, req, pbusy, state) \ | 627 | #define START_TRANSFER_OR(common, ep_name, req, pbusy, state) \ |
628 | if (fsg_is_set(common)) \ | 628 | if (fsg_is_set(common)) \ |
629 | start_transfer((common)->fsg, (common)->fsg->ep_name, \ | 629 | start_transfer((common)->fsg, (common)->fsg->ep_name, \ |
630 | req, pbusy, state); \ | 630 | req, pbusy, state); \ |
631 | else | 631 | else |
632 | 632 | ||
633 | #define START_TRANSFER(common, ep_name, req, pbusy, state) \ | 633 | #define START_TRANSFER(common, ep_name, req, pbusy, state) \ |
634 | START_TRANSFER_OR(common, ep_name, req, pbusy, state) (void)0 | 634 | START_TRANSFER_OR(common, ep_name, req, pbusy, state) (void)0 |
635 | 635 | ||
636 | static void busy_indicator(void) | 636 | static void busy_indicator(void) |
637 | { | 637 | { |
638 | static int state; | 638 | static int state; |
639 | 639 | ||
640 | switch (state) { | 640 | switch (state) { |
641 | case 0: | 641 | case 0: |
642 | puts("\r|"); break; | 642 | puts("\r|"); break; |
643 | case 1: | 643 | case 1: |
644 | puts("\r/"); break; | 644 | puts("\r/"); break; |
645 | case 2: | 645 | case 2: |
646 | puts("\r-"); break; | 646 | puts("\r-"); break; |
647 | case 3: | 647 | case 3: |
648 | puts("\r\\"); break; | 648 | puts("\r\\"); break; |
649 | case 4: | 649 | case 4: |
650 | puts("\r|"); break; | 650 | puts("\r|"); break; |
651 | case 5: | 651 | case 5: |
652 | puts("\r/"); break; | 652 | puts("\r/"); break; |
653 | case 6: | 653 | case 6: |
654 | puts("\r-"); break; | 654 | puts("\r-"); break; |
655 | case 7: | 655 | case 7: |
656 | puts("\r\\"); break; | 656 | puts("\r\\"); break; |
657 | default: | 657 | default: |
658 | state = 0; | 658 | state = 0; |
659 | } | 659 | } |
660 | if (state++ == 8) | 660 | if (state++ == 8) |
661 | state = 0; | 661 | state = 0; |
662 | } | 662 | } |
663 | 663 | ||
664 | static int sleep_thread(struct fsg_common *common) | 664 | static int sleep_thread(struct fsg_common *common) |
665 | { | 665 | { |
666 | int rc = 0; | 666 | int rc = 0; |
667 | int i = 0, k = 0; | 667 | int i = 0, k = 0; |
668 | 668 | ||
669 | /* Wait until a signal arrives or we are woken up */ | 669 | /* Wait until a signal arrives or we are woken up */ |
670 | for (;;) { | 670 | for (;;) { |
671 | if (common->thread_wakeup_needed) | 671 | if (common->thread_wakeup_needed) |
672 | break; | 672 | break; |
673 | 673 | ||
674 | if (++i == 50000) { | 674 | if (++i == 50000) { |
675 | busy_indicator(); | 675 | busy_indicator(); |
676 | i = 0; | 676 | i = 0; |
677 | k++; | 677 | k++; |
678 | } | 678 | } |
679 | 679 | ||
680 | if (k == 10) { | 680 | if (k == 10) { |
681 | /* Handle CTRL+C */ | 681 | /* Handle CTRL+C */ |
682 | if (ctrlc()) | 682 | if (ctrlc()) |
683 | return -EPIPE; | 683 | return -EPIPE; |
684 | 684 | ||
685 | /* Check cable connection */ | 685 | /* Check cable connection */ |
686 | if (!g_dnl_board_usb_cable_connected()) | 686 | if (!g_dnl_board_usb_cable_connected()) |
687 | return -EIO; | 687 | return -EIO; |
688 | 688 | ||
689 | k = 0; | 689 | k = 0; |
690 | } | 690 | } |
691 | 691 | ||
692 | usb_gadget_handle_interrupts(); | 692 | usb_gadget_handle_interrupts(); |
693 | } | 693 | } |
694 | common->thread_wakeup_needed = 0; | 694 | common->thread_wakeup_needed = 0; |
695 | return rc; | 695 | return rc; |
696 | } | 696 | } |
697 | 697 | ||
698 | /*-------------------------------------------------------------------------*/ | 698 | /*-------------------------------------------------------------------------*/ |
699 | 699 | ||
700 | static int do_read(struct fsg_common *common) | 700 | static int do_read(struct fsg_common *common) |
701 | { | 701 | { |
702 | struct fsg_lun *curlun = &common->luns[common->lun]; | 702 | struct fsg_lun *curlun = &common->luns[common->lun]; |
703 | u32 lba; | 703 | u32 lba; |
704 | struct fsg_buffhd *bh; | 704 | struct fsg_buffhd *bh; |
705 | int rc; | 705 | int rc; |
706 | u32 amount_left; | 706 | u32 amount_left; |
707 | loff_t file_offset; | 707 | loff_t file_offset; |
708 | unsigned int amount; | 708 | unsigned int amount; |
709 | unsigned int partial_page; | 709 | unsigned int partial_page; |
710 | ssize_t nread; | 710 | ssize_t nread; |
711 | 711 | ||
712 | /* Get the starting Logical Block Address and check that it's | 712 | /* Get the starting Logical Block Address and check that it's |
713 | * not too big */ | 713 | * not too big */ |
714 | if (common->cmnd[0] == SC_READ_6) | 714 | if (common->cmnd[0] == SC_READ_6) |
715 | lba = get_unaligned_be24(&common->cmnd[1]); | 715 | lba = get_unaligned_be24(&common->cmnd[1]); |
716 | else { | 716 | else { |
717 | lba = get_unaligned_be32(&common->cmnd[2]); | 717 | lba = get_unaligned_be32(&common->cmnd[2]); |
718 | 718 | ||
719 | /* We allow DPO (Disable Page Out = don't save data in the | 719 | /* We allow DPO (Disable Page Out = don't save data in the |
720 | * cache) and FUA (Force Unit Access = don't read from the | 720 | * cache) and FUA (Force Unit Access = don't read from the |
721 | * cache), but we don't implement them. */ | 721 | * cache), but we don't implement them. */ |
722 | if ((common->cmnd[1] & ~0x18) != 0) { | 722 | if ((common->cmnd[1] & ~0x18) != 0) { |
723 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | 723 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; |
724 | return -EINVAL; | 724 | return -EINVAL; |
725 | } | 725 | } |
726 | } | 726 | } |
727 | if (lba >= curlun->num_sectors) { | 727 | if (lba >= curlun->num_sectors) { |
728 | curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; | 728 | curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; |
729 | return -EINVAL; | 729 | return -EINVAL; |
730 | } | 730 | } |
731 | file_offset = ((loff_t) lba) << 9; | 731 | file_offset = ((loff_t) lba) << 9; |
732 | 732 | ||
733 | /* Carry out the file reads */ | 733 | /* Carry out the file reads */ |
734 | amount_left = common->data_size_from_cmnd; | 734 | amount_left = common->data_size_from_cmnd; |
735 | if (unlikely(amount_left == 0)) | 735 | if (unlikely(amount_left == 0)) |
736 | return -EIO; /* No default reply */ | 736 | return -EIO; /* No default reply */ |
737 | 737 | ||
738 | for (;;) { | 738 | for (;;) { |
739 | 739 | ||
740 | /* Figure out how much we need to read: | 740 | /* Figure out how much we need to read: |
741 | * Try to read the remaining amount. | 741 | * Try to read the remaining amount. |
742 | * But don't read more than the buffer size. | 742 | * But don't read more than the buffer size. |
743 | * And don't try to read past the end of the file. | 743 | * And don't try to read past the end of the file. |
744 | * Finally, if we're not at a page boundary, don't read past | 744 | * Finally, if we're not at a page boundary, don't read past |
745 | * the next page. | 745 | * the next page. |
746 | * If this means reading 0 then we were asked to read past | 746 | * If this means reading 0 then we were asked to read past |
747 | * the end of file. */ | 747 | * the end of file. */ |
748 | amount = min(amount_left, FSG_BUFLEN); | 748 | amount = min(amount_left, FSG_BUFLEN); |
749 | partial_page = file_offset & (PAGE_CACHE_SIZE - 1); | 749 | partial_page = file_offset & (PAGE_CACHE_SIZE - 1); |
750 | if (partial_page > 0) | 750 | if (partial_page > 0) |
751 | amount = min(amount, (unsigned int) PAGE_CACHE_SIZE - | 751 | amount = min(amount, (unsigned int) PAGE_CACHE_SIZE - |
752 | partial_page); | 752 | partial_page); |
753 | 753 | ||
754 | /* Wait for the next buffer to become available */ | 754 | /* Wait for the next buffer to become available */ |
755 | bh = common->next_buffhd_to_fill; | 755 | bh = common->next_buffhd_to_fill; |
756 | while (bh->state != BUF_STATE_EMPTY) { | 756 | while (bh->state != BUF_STATE_EMPTY) { |
757 | rc = sleep_thread(common); | 757 | rc = sleep_thread(common); |
758 | if (rc) | 758 | if (rc) |
759 | return rc; | 759 | return rc; |
760 | } | 760 | } |
761 | 761 | ||
762 | /* If we were asked to read past the end of file, | 762 | /* If we were asked to read past the end of file, |
763 | * end with an empty buffer. */ | 763 | * end with an empty buffer. */ |
764 | if (amount == 0) { | 764 | if (amount == 0) { |
765 | curlun->sense_data = | 765 | curlun->sense_data = |
766 | SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; | 766 | SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; |
767 | curlun->info_valid = 1; | 767 | curlun->info_valid = 1; |
768 | bh->inreq->length = 0; | 768 | bh->inreq->length = 0; |
769 | bh->state = BUF_STATE_FULL; | 769 | bh->state = BUF_STATE_FULL; |
770 | break; | 770 | break; |
771 | } | 771 | } |
772 | 772 | ||
773 | /* Perform the read */ | 773 | /* Perform the read */ |
774 | rc = ums->read_sector(ums, | 774 | rc = ums->read_sector(ums, |
775 | file_offset / SECTOR_SIZE, | 775 | file_offset / SECTOR_SIZE, |
776 | amount / SECTOR_SIZE, | 776 | amount / SECTOR_SIZE, |
777 | (char __user *)bh->buf); | 777 | (char __user *)bh->buf); |
778 | if (!rc) | 778 | if (!rc) |
779 | return -EIO; | 779 | return -EIO; |
780 | 780 | ||
781 | nread = rc * SECTOR_SIZE; | 781 | nread = rc * SECTOR_SIZE; |
782 | 782 | ||
783 | VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, | 783 | VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, |
784 | (unsigned long long) file_offset, | 784 | (unsigned long long) file_offset, |
785 | (int) nread); | 785 | (int) nread); |
786 | 786 | ||
787 | if (nread < 0) { | 787 | if (nread < 0) { |
788 | LDBG(curlun, "error in file read: %d\n", | 788 | LDBG(curlun, "error in file read: %d\n", |
789 | (int) nread); | 789 | (int) nread); |
790 | nread = 0; | 790 | nread = 0; |
791 | } else if (nread < amount) { | 791 | } else if (nread < amount) { |
792 | LDBG(curlun, "partial file read: %d/%u\n", | 792 | LDBG(curlun, "partial file read: %d/%u\n", |
793 | (int) nread, amount); | 793 | (int) nread, amount); |
794 | nread -= (nread & 511); /* Round down to a block */ | 794 | nread -= (nread & 511); /* Round down to a block */ |
795 | } | 795 | } |
796 | file_offset += nread; | 796 | file_offset += nread; |
797 | amount_left -= nread; | 797 | amount_left -= nread; |
798 | common->residue -= nread; | 798 | common->residue -= nread; |
799 | bh->inreq->length = nread; | 799 | bh->inreq->length = nread; |
800 | bh->state = BUF_STATE_FULL; | 800 | bh->state = BUF_STATE_FULL; |
801 | 801 | ||
802 | /* If an error occurred, report it and its position */ | 802 | /* If an error occurred, report it and its position */ |
803 | if (nread < amount) { | 803 | if (nread < amount) { |
804 | curlun->sense_data = SS_UNRECOVERED_READ_ERROR; | 804 | curlun->sense_data = SS_UNRECOVERED_READ_ERROR; |
805 | curlun->info_valid = 1; | 805 | curlun->info_valid = 1; |
806 | break; | 806 | break; |
807 | } | 807 | } |
808 | 808 | ||
809 | if (amount_left == 0) | 809 | if (amount_left == 0) |
810 | break; /* No more left to read */ | 810 | break; /* No more left to read */ |
811 | 811 | ||
812 | /* Send this buffer and go read some more */ | 812 | /* Send this buffer and go read some more */ |
813 | bh->inreq->zero = 0; | 813 | bh->inreq->zero = 0; |
814 | START_TRANSFER_OR(common, bulk_in, bh->inreq, | 814 | START_TRANSFER_OR(common, bulk_in, bh->inreq, |
815 | &bh->inreq_busy, &bh->state) | 815 | &bh->inreq_busy, &bh->state) |
816 | /* Don't know what to do if | 816 | /* Don't know what to do if |
817 | * common->fsg is NULL */ | 817 | * common->fsg is NULL */ |
818 | return -EIO; | 818 | return -EIO; |
819 | common->next_buffhd_to_fill = bh->next; | 819 | common->next_buffhd_to_fill = bh->next; |
820 | } | 820 | } |
821 | 821 | ||
822 | return -EIO; /* No default reply */ | 822 | return -EIO; /* No default reply */ |
823 | } | 823 | } |
824 | 824 | ||
825 | /*-------------------------------------------------------------------------*/ | 825 | /*-------------------------------------------------------------------------*/ |
826 | 826 | ||
827 | static int do_write(struct fsg_common *common) | 827 | static int do_write(struct fsg_common *common) |
828 | { | 828 | { |
829 | struct fsg_lun *curlun = &common->luns[common->lun]; | 829 | struct fsg_lun *curlun = &common->luns[common->lun]; |
830 | u32 lba; | 830 | u32 lba; |
831 | struct fsg_buffhd *bh; | 831 | struct fsg_buffhd *bh; |
832 | int get_some_more; | 832 | int get_some_more; |
833 | u32 amount_left_to_req, amount_left_to_write; | 833 | u32 amount_left_to_req, amount_left_to_write; |
834 | loff_t usb_offset, file_offset; | 834 | loff_t usb_offset, file_offset; |
835 | unsigned int amount; | 835 | unsigned int amount; |
836 | unsigned int partial_page; | 836 | unsigned int partial_page; |
837 | ssize_t nwritten; | 837 | ssize_t nwritten; |
838 | int rc; | 838 | int rc; |
839 | 839 | ||
840 | if (curlun->ro) { | 840 | if (curlun->ro) { |
841 | curlun->sense_data = SS_WRITE_PROTECTED; | 841 | curlun->sense_data = SS_WRITE_PROTECTED; |
842 | return -EINVAL; | 842 | return -EINVAL; |
843 | } | 843 | } |
844 | 844 | ||
845 | /* Get the starting Logical Block Address and check that it's | 845 | /* Get the starting Logical Block Address and check that it's |
846 | * not too big */ | 846 | * not too big */ |
847 | if (common->cmnd[0] == SC_WRITE_6) | 847 | if (common->cmnd[0] == SC_WRITE_6) |
848 | lba = get_unaligned_be24(&common->cmnd[1]); | 848 | lba = get_unaligned_be24(&common->cmnd[1]); |
849 | else { | 849 | else { |
850 | lba = get_unaligned_be32(&common->cmnd[2]); | 850 | lba = get_unaligned_be32(&common->cmnd[2]); |
851 | 851 | ||
852 | /* We allow DPO (Disable Page Out = don't save data in the | 852 | /* We allow DPO (Disable Page Out = don't save data in the |
853 | * cache) and FUA (Force Unit Access = write directly to the | 853 | * cache) and FUA (Force Unit Access = write directly to the |
854 | * medium). We don't implement DPO; we implement FUA by | 854 | * medium). We don't implement DPO; we implement FUA by |
855 | * performing synchronous output. */ | 855 | * performing synchronous output. */ |
856 | if (common->cmnd[1] & ~0x18) { | 856 | if (common->cmnd[1] & ~0x18) { |
857 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | 857 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; |
858 | return -EINVAL; | 858 | return -EINVAL; |
859 | } | 859 | } |
860 | } | 860 | } |
861 | if (lba >= curlun->num_sectors) { | 861 | if (lba >= curlun->num_sectors) { |
862 | curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; | 862 | curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; |
863 | return -EINVAL; | 863 | return -EINVAL; |
864 | } | 864 | } |
865 | 865 | ||
866 | /* Carry out the file writes */ | 866 | /* Carry out the file writes */ |
867 | get_some_more = 1; | 867 | get_some_more = 1; |
868 | file_offset = usb_offset = ((loff_t) lba) << 9; | 868 | file_offset = usb_offset = ((loff_t) lba) << 9; |
869 | amount_left_to_req = common->data_size_from_cmnd; | 869 | amount_left_to_req = common->data_size_from_cmnd; |
870 | amount_left_to_write = common->data_size_from_cmnd; | 870 | amount_left_to_write = common->data_size_from_cmnd; |
871 | 871 | ||
872 | while (amount_left_to_write > 0) { | 872 | while (amount_left_to_write > 0) { |
873 | 873 | ||
874 | /* Queue a request for more data from the host */ | 874 | /* Queue a request for more data from the host */ |
875 | bh = common->next_buffhd_to_fill; | 875 | bh = common->next_buffhd_to_fill; |
876 | if (bh->state == BUF_STATE_EMPTY && get_some_more) { | 876 | if (bh->state == BUF_STATE_EMPTY && get_some_more) { |
877 | 877 | ||
878 | /* Figure out how much we want to get: | 878 | /* Figure out how much we want to get: |
879 | * Try to get the remaining amount. | 879 | * Try to get the remaining amount. |
880 | * But don't get more than the buffer size. | 880 | * But don't get more than the buffer size. |
881 | * And don't try to go past the end of the file. | 881 | * And don't try to go past the end of the file. |
882 | * If we're not at a page boundary, | 882 | * If we're not at a page boundary, |
883 | * don't go past the next page. | 883 | * don't go past the next page. |
884 | * If this means getting 0, then we were asked | 884 | * If this means getting 0, then we were asked |
885 | * to write past the end of file. | 885 | * to write past the end of file. |
886 | * Finally, round down to a block boundary. */ | 886 | * Finally, round down to a block boundary. */ |
887 | amount = min(amount_left_to_req, FSG_BUFLEN); | 887 | amount = min(amount_left_to_req, FSG_BUFLEN); |
888 | partial_page = usb_offset & (PAGE_CACHE_SIZE - 1); | 888 | partial_page = usb_offset & (PAGE_CACHE_SIZE - 1); |
889 | if (partial_page > 0) | 889 | if (partial_page > 0) |
890 | amount = min(amount, | 890 | amount = min(amount, |
891 | (unsigned int) PAGE_CACHE_SIZE - partial_page); | 891 | (unsigned int) PAGE_CACHE_SIZE - partial_page); |
892 | 892 | ||
893 | if (amount == 0) { | 893 | if (amount == 0) { |
894 | get_some_more = 0; | 894 | get_some_more = 0; |
895 | curlun->sense_data = | 895 | curlun->sense_data = |
896 | SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; | 896 | SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; |
897 | curlun->info_valid = 1; | 897 | curlun->info_valid = 1; |
898 | continue; | 898 | continue; |
899 | } | 899 | } |
900 | amount -= (amount & 511); | 900 | amount -= (amount & 511); |
901 | if (amount == 0) { | 901 | if (amount == 0) { |
902 | 902 | ||
903 | /* Why were we were asked to transfer a | 903 | /* Why were we were asked to transfer a |
904 | * partial block? */ | 904 | * partial block? */ |
905 | get_some_more = 0; | 905 | get_some_more = 0; |
906 | continue; | 906 | continue; |
907 | } | 907 | } |
908 | 908 | ||
909 | /* Get the next buffer */ | 909 | /* Get the next buffer */ |
910 | usb_offset += amount; | 910 | usb_offset += amount; |
911 | common->usb_amount_left -= amount; | 911 | common->usb_amount_left -= amount; |
912 | amount_left_to_req -= amount; | 912 | amount_left_to_req -= amount; |
913 | if (amount_left_to_req == 0) | 913 | if (amount_left_to_req == 0) |
914 | get_some_more = 0; | 914 | get_some_more = 0; |
915 | 915 | ||
916 | /* amount is always divisible by 512, hence by | 916 | /* amount is always divisible by 512, hence by |
917 | * the bulk-out maxpacket size */ | 917 | * the bulk-out maxpacket size */ |
918 | bh->outreq->length = amount; | 918 | bh->outreq->length = amount; |
919 | bh->bulk_out_intended_length = amount; | 919 | bh->bulk_out_intended_length = amount; |
920 | bh->outreq->short_not_ok = 1; | 920 | bh->outreq->short_not_ok = 1; |
921 | START_TRANSFER_OR(common, bulk_out, bh->outreq, | 921 | START_TRANSFER_OR(common, bulk_out, bh->outreq, |
922 | &bh->outreq_busy, &bh->state) | 922 | &bh->outreq_busy, &bh->state) |
923 | /* Don't know what to do if | 923 | /* Don't know what to do if |
924 | * common->fsg is NULL */ | 924 | * common->fsg is NULL */ |
925 | return -EIO; | 925 | return -EIO; |
926 | common->next_buffhd_to_fill = bh->next; | 926 | common->next_buffhd_to_fill = bh->next; |
927 | continue; | 927 | continue; |
928 | } | 928 | } |
929 | 929 | ||
930 | /* Write the received data to the backing file */ | 930 | /* Write the received data to the backing file */ |
931 | bh = common->next_buffhd_to_drain; | 931 | bh = common->next_buffhd_to_drain; |
932 | if (bh->state == BUF_STATE_EMPTY && !get_some_more) | 932 | if (bh->state == BUF_STATE_EMPTY && !get_some_more) |
933 | break; /* We stopped early */ | 933 | break; /* We stopped early */ |
934 | if (bh->state == BUF_STATE_FULL) { | 934 | if (bh->state == BUF_STATE_FULL) { |
935 | common->next_buffhd_to_drain = bh->next; | 935 | common->next_buffhd_to_drain = bh->next; |
936 | bh->state = BUF_STATE_EMPTY; | 936 | bh->state = BUF_STATE_EMPTY; |
937 | 937 | ||
938 | /* Did something go wrong with the transfer? */ | 938 | /* Did something go wrong with the transfer? */ |
939 | if (bh->outreq->status != 0) { | 939 | if (bh->outreq->status != 0) { |
940 | curlun->sense_data = SS_COMMUNICATION_FAILURE; | 940 | curlun->sense_data = SS_COMMUNICATION_FAILURE; |
941 | curlun->info_valid = 1; | 941 | curlun->info_valid = 1; |
942 | break; | 942 | break; |
943 | } | 943 | } |
944 | 944 | ||
945 | amount = bh->outreq->actual; | 945 | amount = bh->outreq->actual; |
946 | 946 | ||
947 | /* Perform the write */ | 947 | /* Perform the write */ |
948 | rc = ums->write_sector(ums, | 948 | rc = ums->write_sector(ums, |
949 | file_offset / SECTOR_SIZE, | 949 | file_offset / SECTOR_SIZE, |
950 | amount / SECTOR_SIZE, | 950 | amount / SECTOR_SIZE, |
951 | (char __user *)bh->buf); | 951 | (char __user *)bh->buf); |
952 | if (!rc) | 952 | if (!rc) |
953 | return -EIO; | 953 | return -EIO; |
954 | nwritten = rc * SECTOR_SIZE; | 954 | nwritten = rc * SECTOR_SIZE; |
955 | 955 | ||
956 | VLDBG(curlun, "file write %u @ %llu -> %d\n", amount, | 956 | VLDBG(curlun, "file write %u @ %llu -> %d\n", amount, |
957 | (unsigned long long) file_offset, | 957 | (unsigned long long) file_offset, |
958 | (int) nwritten); | 958 | (int) nwritten); |
959 | 959 | ||
960 | if (nwritten < 0) { | 960 | if (nwritten < 0) { |
961 | LDBG(curlun, "error in file write: %d\n", | 961 | LDBG(curlun, "error in file write: %d\n", |
962 | (int) nwritten); | 962 | (int) nwritten); |
963 | nwritten = 0; | 963 | nwritten = 0; |
964 | } else if (nwritten < amount) { | 964 | } else if (nwritten < amount) { |
965 | LDBG(curlun, "partial file write: %d/%u\n", | 965 | LDBG(curlun, "partial file write: %d/%u\n", |
966 | (int) nwritten, amount); | 966 | (int) nwritten, amount); |
967 | nwritten -= (nwritten & 511); | 967 | nwritten -= (nwritten & 511); |
968 | /* Round down to a block */ | 968 | /* Round down to a block */ |
969 | } | 969 | } |
970 | file_offset += nwritten; | 970 | file_offset += nwritten; |
971 | amount_left_to_write -= nwritten; | 971 | amount_left_to_write -= nwritten; |
972 | common->residue -= nwritten; | 972 | common->residue -= nwritten; |
973 | 973 | ||
974 | /* If an error occurred, report it and its position */ | 974 | /* If an error occurred, report it and its position */ |
975 | if (nwritten < amount) { | 975 | if (nwritten < amount) { |
976 | printf("nwritten:%d amount:%d\n", nwritten, | 976 | printf("nwritten:%d amount:%d\n", nwritten, |
977 | amount); | 977 | amount); |
978 | curlun->sense_data = SS_WRITE_ERROR; | 978 | curlun->sense_data = SS_WRITE_ERROR; |
979 | curlun->info_valid = 1; | 979 | curlun->info_valid = 1; |
980 | break; | 980 | break; |
981 | } | 981 | } |
982 | 982 | ||
983 | /* Did the host decide to stop early? */ | 983 | /* Did the host decide to stop early? */ |
984 | if (bh->outreq->actual != bh->outreq->length) { | 984 | if (bh->outreq->actual != bh->outreq->length) { |
985 | common->short_packet_received = 1; | 985 | common->short_packet_received = 1; |
986 | break; | 986 | break; |
987 | } | 987 | } |
988 | continue; | 988 | continue; |
989 | } | 989 | } |
990 | 990 | ||
991 | /* Wait for something to happen */ | 991 | /* Wait for something to happen */ |
992 | rc = sleep_thread(common); | 992 | rc = sleep_thread(common); |
993 | if (rc) | 993 | if (rc) |
994 | return rc; | 994 | return rc; |
995 | } | 995 | } |
996 | 996 | ||
997 | return -EIO; /* No default reply */ | 997 | return -EIO; /* No default reply */ |
998 | } | 998 | } |
999 | 999 | ||
1000 | /*-------------------------------------------------------------------------*/ | 1000 | /*-------------------------------------------------------------------------*/ |
1001 | 1001 | ||
1002 | static int do_synchronize_cache(struct fsg_common *common) | 1002 | static int do_synchronize_cache(struct fsg_common *common) |
1003 | { | 1003 | { |
1004 | return 0; | 1004 | return 0; |
1005 | } | 1005 | } |
1006 | 1006 | ||
1007 | /*-------------------------------------------------------------------------*/ | 1007 | /*-------------------------------------------------------------------------*/ |
1008 | 1008 | ||
1009 | static int do_verify(struct fsg_common *common) | 1009 | static int do_verify(struct fsg_common *common) |
1010 | { | 1010 | { |
1011 | struct fsg_lun *curlun = &common->luns[common->lun]; | 1011 | struct fsg_lun *curlun = &common->luns[common->lun]; |
1012 | u32 lba; | 1012 | u32 lba; |
1013 | u32 verification_length; | 1013 | u32 verification_length; |
1014 | struct fsg_buffhd *bh = common->next_buffhd_to_fill; | 1014 | struct fsg_buffhd *bh = common->next_buffhd_to_fill; |
1015 | loff_t file_offset; | 1015 | loff_t file_offset; |
1016 | u32 amount_left; | 1016 | u32 amount_left; |
1017 | unsigned int amount; | 1017 | unsigned int amount; |
1018 | ssize_t nread; | 1018 | ssize_t nread; |
1019 | int rc; | 1019 | int rc; |
1020 | 1020 | ||
1021 | /* Get the starting Logical Block Address and check that it's | 1021 | /* Get the starting Logical Block Address and check that it's |
1022 | * not too big */ | 1022 | * not too big */ |
1023 | lba = get_unaligned_be32(&common->cmnd[2]); | 1023 | lba = get_unaligned_be32(&common->cmnd[2]); |
1024 | if (lba >= curlun->num_sectors) { | 1024 | if (lba >= curlun->num_sectors) { |
1025 | curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; | 1025 | curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; |
1026 | return -EINVAL; | 1026 | return -EINVAL; |
1027 | } | 1027 | } |
1028 | 1028 | ||
1029 | /* We allow DPO (Disable Page Out = don't save data in the | 1029 | /* We allow DPO (Disable Page Out = don't save data in the |
1030 | * cache) but we don't implement it. */ | 1030 | * cache) but we don't implement it. */ |
1031 | if (common->cmnd[1] & ~0x10) { | 1031 | if (common->cmnd[1] & ~0x10) { |
1032 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | 1032 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; |
1033 | return -EINVAL; | 1033 | return -EINVAL; |
1034 | } | 1034 | } |
1035 | 1035 | ||
1036 | verification_length = get_unaligned_be16(&common->cmnd[7]); | 1036 | verification_length = get_unaligned_be16(&common->cmnd[7]); |
1037 | if (unlikely(verification_length == 0)) | 1037 | if (unlikely(verification_length == 0)) |
1038 | return -EIO; /* No default reply */ | 1038 | return -EIO; /* No default reply */ |
1039 | 1039 | ||
1040 | /* Prepare to carry out the file verify */ | 1040 | /* Prepare to carry out the file verify */ |
1041 | amount_left = verification_length << 9; | 1041 | amount_left = verification_length << 9; |
1042 | file_offset = ((loff_t) lba) << 9; | 1042 | file_offset = ((loff_t) lba) << 9; |
1043 | 1043 | ||
1044 | /* Write out all the dirty buffers before invalidating them */ | 1044 | /* Write out all the dirty buffers before invalidating them */ |
1045 | 1045 | ||
1046 | /* Just try to read the requested blocks */ | 1046 | /* Just try to read the requested blocks */ |
1047 | while (amount_left > 0) { | 1047 | while (amount_left > 0) { |
1048 | 1048 | ||
1049 | /* Figure out how much we need to read: | 1049 | /* Figure out how much we need to read: |
1050 | * Try to read the remaining amount, but not more than | 1050 | * Try to read the remaining amount, but not more than |
1051 | * the buffer size. | 1051 | * the buffer size. |
1052 | * And don't try to read past the end of the file. | 1052 | * And don't try to read past the end of the file. |
1053 | * If this means reading 0 then we were asked to read | 1053 | * If this means reading 0 then we were asked to read |
1054 | * past the end of file. */ | 1054 | * past the end of file. */ |
1055 | amount = min(amount_left, FSG_BUFLEN); | 1055 | amount = min(amount_left, FSG_BUFLEN); |
1056 | if (amount == 0) { | 1056 | if (amount == 0) { |
1057 | curlun->sense_data = | 1057 | curlun->sense_data = |
1058 | SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; | 1058 | SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; |
1059 | curlun->info_valid = 1; | 1059 | curlun->info_valid = 1; |
1060 | break; | 1060 | break; |
1061 | } | 1061 | } |
1062 | 1062 | ||
1063 | /* Perform the read */ | 1063 | /* Perform the read */ |
1064 | rc = ums->read_sector(ums, | 1064 | rc = ums->read_sector(ums, |
1065 | file_offset / SECTOR_SIZE, | 1065 | file_offset / SECTOR_SIZE, |
1066 | amount / SECTOR_SIZE, | 1066 | amount / SECTOR_SIZE, |
1067 | (char __user *)bh->buf); | 1067 | (char __user *)bh->buf); |
1068 | if (!rc) | 1068 | if (!rc) |
1069 | return -EIO; | 1069 | return -EIO; |
1070 | nread = rc * SECTOR_SIZE; | 1070 | nread = rc * SECTOR_SIZE; |
1071 | 1071 | ||
1072 | VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, | 1072 | VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, |
1073 | (unsigned long long) file_offset, | 1073 | (unsigned long long) file_offset, |
1074 | (int) nread); | 1074 | (int) nread); |
1075 | if (nread < 0) { | 1075 | if (nread < 0) { |
1076 | LDBG(curlun, "error in file verify: %d\n", | 1076 | LDBG(curlun, "error in file verify: %d\n", |
1077 | (int) nread); | 1077 | (int) nread); |
1078 | nread = 0; | 1078 | nread = 0; |
1079 | } else if (nread < amount) { | 1079 | } else if (nread < amount) { |
1080 | LDBG(curlun, "partial file verify: %d/%u\n", | 1080 | LDBG(curlun, "partial file verify: %d/%u\n", |
1081 | (int) nread, amount); | 1081 | (int) nread, amount); |
1082 | nread -= (nread & 511); /* Round down to a sector */ | 1082 | nread -= (nread & 511); /* Round down to a sector */ |
1083 | } | 1083 | } |
1084 | if (nread == 0) { | 1084 | if (nread == 0) { |
1085 | curlun->sense_data = SS_UNRECOVERED_READ_ERROR; | 1085 | curlun->sense_data = SS_UNRECOVERED_READ_ERROR; |
1086 | curlun->info_valid = 1; | 1086 | curlun->info_valid = 1; |
1087 | break; | 1087 | break; |
1088 | } | 1088 | } |
1089 | file_offset += nread; | 1089 | file_offset += nread; |
1090 | amount_left -= nread; | 1090 | amount_left -= nread; |
1091 | } | 1091 | } |
1092 | return 0; | 1092 | return 0; |
1093 | } | 1093 | } |
1094 | 1094 | ||
1095 | /*-------------------------------------------------------------------------*/ | 1095 | /*-------------------------------------------------------------------------*/ |
1096 | 1096 | ||
1097 | static int do_inquiry(struct fsg_common *common, struct fsg_buffhd *bh) | 1097 | static int do_inquiry(struct fsg_common *common, struct fsg_buffhd *bh) |
1098 | { | 1098 | { |
1099 | struct fsg_lun *curlun = &common->luns[common->lun]; | 1099 | struct fsg_lun *curlun = &common->luns[common->lun]; |
1100 | static const char vendor_id[] = "Linux "; | 1100 | static const char vendor_id[] = "Linux "; |
1101 | u8 *buf = (u8 *) bh->buf; | 1101 | u8 *buf = (u8 *) bh->buf; |
1102 | 1102 | ||
1103 | if (!curlun) { /* Unsupported LUNs are okay */ | 1103 | if (!curlun) { /* Unsupported LUNs are okay */ |
1104 | common->bad_lun_okay = 1; | 1104 | common->bad_lun_okay = 1; |
1105 | memset(buf, 0, 36); | 1105 | memset(buf, 0, 36); |
1106 | buf[0] = 0x7f; /* Unsupported, no device-type */ | 1106 | buf[0] = 0x7f; /* Unsupported, no device-type */ |
1107 | buf[4] = 31; /* Additional length */ | 1107 | buf[4] = 31; /* Additional length */ |
1108 | return 36; | 1108 | return 36; |
1109 | } | 1109 | } |
1110 | 1110 | ||
1111 | memset(buf, 0, 8); | 1111 | memset(buf, 0, 8); |
1112 | buf[0] = TYPE_DISK; | 1112 | buf[0] = TYPE_DISK; |
1113 | buf[1] = curlun->removable ? 0x80 : 0; | ||
1113 | buf[2] = 2; /* ANSI SCSI level 2 */ | 1114 | buf[2] = 2; /* ANSI SCSI level 2 */ |
1114 | buf[3] = 2; /* SCSI-2 INQUIRY data format */ | 1115 | buf[3] = 2; /* SCSI-2 INQUIRY data format */ |
1115 | buf[4] = 31; /* Additional length */ | 1116 | buf[4] = 31; /* Additional length */ |
1116 | /* No special options */ | 1117 | /* No special options */ |
1117 | sprintf((char *) (buf + 8), "%-8s%-16s%04x", (char*) vendor_id , | 1118 | sprintf((char *) (buf + 8), "%-8s%-16s%04x", (char*) vendor_id , |
1118 | ums->name, (u16) 0xffff); | 1119 | ums->name, (u16) 0xffff); |
1119 | 1120 | ||
1120 | return 36; | 1121 | return 36; |
1121 | } | 1122 | } |
1122 | 1123 | ||
1123 | 1124 | ||
1124 | static int do_request_sense(struct fsg_common *common, struct fsg_buffhd *bh) | 1125 | static int do_request_sense(struct fsg_common *common, struct fsg_buffhd *bh) |
1125 | { | 1126 | { |
1126 | struct fsg_lun *curlun = &common->luns[common->lun]; | 1127 | struct fsg_lun *curlun = &common->luns[common->lun]; |
1127 | u8 *buf = (u8 *) bh->buf; | 1128 | u8 *buf = (u8 *) bh->buf; |
1128 | u32 sd, sdinfo; | 1129 | u32 sd, sdinfo; |
1129 | int valid; | 1130 | int valid; |
1130 | 1131 | ||
1131 | /* | 1132 | /* |
1132 | * From the SCSI-2 spec., section 7.9 (Unit attention condition): | 1133 | * From the SCSI-2 spec., section 7.9 (Unit attention condition): |
1133 | * | 1134 | * |
1134 | * If a REQUEST SENSE command is received from an initiator | 1135 | * If a REQUEST SENSE command is received from an initiator |
1135 | * with a pending unit attention condition (before the target | 1136 | * with a pending unit attention condition (before the target |
1136 | * generates the contingent allegiance condition), then the | 1137 | * generates the contingent allegiance condition), then the |
1137 | * target shall either: | 1138 | * target shall either: |
1138 | * a) report any pending sense data and preserve the unit | 1139 | * a) report any pending sense data and preserve the unit |
1139 | * attention condition on the logical unit, or, | 1140 | * attention condition on the logical unit, or, |
1140 | * b) report the unit attention condition, may discard any | 1141 | * b) report the unit attention condition, may discard any |
1141 | * pending sense data, and clear the unit attention | 1142 | * pending sense data, and clear the unit attention |
1142 | * condition on the logical unit for that initiator. | 1143 | * condition on the logical unit for that initiator. |
1143 | * | 1144 | * |
1144 | * FSG normally uses option a); enable this code to use option b). | 1145 | * FSG normally uses option a); enable this code to use option b). |
1145 | */ | 1146 | */ |
1146 | #if 0 | 1147 | #if 0 |
1147 | if (curlun && curlun->unit_attention_data != SS_NO_SENSE) { | 1148 | if (curlun && curlun->unit_attention_data != SS_NO_SENSE) { |
1148 | curlun->sense_data = curlun->unit_attention_data; | 1149 | curlun->sense_data = curlun->unit_attention_data; |
1149 | curlun->unit_attention_data = SS_NO_SENSE; | 1150 | curlun->unit_attention_data = SS_NO_SENSE; |
1150 | } | 1151 | } |
1151 | #endif | 1152 | #endif |
1152 | 1153 | ||
1153 | if (!curlun) { /* Unsupported LUNs are okay */ | 1154 | if (!curlun) { /* Unsupported LUNs are okay */ |
1154 | common->bad_lun_okay = 1; | 1155 | common->bad_lun_okay = 1; |
1155 | sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; | 1156 | sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; |
1156 | sdinfo = 0; | 1157 | sdinfo = 0; |
1157 | valid = 0; | 1158 | valid = 0; |
1158 | } else { | 1159 | } else { |
1159 | sd = curlun->sense_data; | 1160 | sd = curlun->sense_data; |
1160 | valid = curlun->info_valid << 7; | 1161 | valid = curlun->info_valid << 7; |
1161 | curlun->sense_data = SS_NO_SENSE; | 1162 | curlun->sense_data = SS_NO_SENSE; |
1162 | curlun->info_valid = 0; | 1163 | curlun->info_valid = 0; |
1163 | } | 1164 | } |
1164 | 1165 | ||
1165 | memset(buf, 0, 18); | 1166 | memset(buf, 0, 18); |
1166 | buf[0] = valid | 0x70; /* Valid, current error */ | 1167 | buf[0] = valid | 0x70; /* Valid, current error */ |
1167 | buf[2] = SK(sd); | 1168 | buf[2] = SK(sd); |
1168 | put_unaligned_be32(sdinfo, &buf[3]); /* Sense information */ | 1169 | put_unaligned_be32(sdinfo, &buf[3]); /* Sense information */ |
1169 | buf[7] = 18 - 8; /* Additional sense length */ | 1170 | buf[7] = 18 - 8; /* Additional sense length */ |
1170 | buf[12] = ASC(sd); | 1171 | buf[12] = ASC(sd); |
1171 | buf[13] = ASCQ(sd); | 1172 | buf[13] = ASCQ(sd); |
1172 | return 18; | 1173 | return 18; |
1173 | } | 1174 | } |
1174 | 1175 | ||
1175 | static int do_read_capacity(struct fsg_common *common, struct fsg_buffhd *bh) | 1176 | static int do_read_capacity(struct fsg_common *common, struct fsg_buffhd *bh) |
1176 | { | 1177 | { |
1177 | struct fsg_lun *curlun = &common->luns[common->lun]; | 1178 | struct fsg_lun *curlun = &common->luns[common->lun]; |
1178 | u32 lba = get_unaligned_be32(&common->cmnd[2]); | 1179 | u32 lba = get_unaligned_be32(&common->cmnd[2]); |
1179 | int pmi = common->cmnd[8]; | 1180 | int pmi = common->cmnd[8]; |
1180 | u8 *buf = (u8 *) bh->buf; | 1181 | u8 *buf = (u8 *) bh->buf; |
1181 | 1182 | ||
1182 | /* Check the PMI and LBA fields */ | 1183 | /* Check the PMI and LBA fields */ |
1183 | if (pmi > 1 || (pmi == 0 && lba != 0)) { | 1184 | if (pmi > 1 || (pmi == 0 && lba != 0)) { |
1184 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | 1185 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; |
1185 | return -EINVAL; | 1186 | return -EINVAL; |
1186 | } | 1187 | } |
1187 | 1188 | ||
1188 | put_unaligned_be32(curlun->num_sectors - 1, &buf[0]); | 1189 | put_unaligned_be32(curlun->num_sectors - 1, &buf[0]); |
1189 | /* Max logical block */ | 1190 | /* Max logical block */ |
1190 | put_unaligned_be32(512, &buf[4]); /* Block length */ | 1191 | put_unaligned_be32(512, &buf[4]); /* Block length */ |
1191 | return 8; | 1192 | return 8; |
1192 | } | 1193 | } |
1193 | 1194 | ||
1194 | static int do_read_header(struct fsg_common *common, struct fsg_buffhd *bh) | 1195 | static int do_read_header(struct fsg_common *common, struct fsg_buffhd *bh) |
1195 | { | 1196 | { |
1196 | struct fsg_lun *curlun = &common->luns[common->lun]; | 1197 | struct fsg_lun *curlun = &common->luns[common->lun]; |
1197 | int msf = common->cmnd[1] & 0x02; | 1198 | int msf = common->cmnd[1] & 0x02; |
1198 | u32 lba = get_unaligned_be32(&common->cmnd[2]); | 1199 | u32 lba = get_unaligned_be32(&common->cmnd[2]); |
1199 | u8 *buf = (u8 *) bh->buf; | 1200 | u8 *buf = (u8 *) bh->buf; |
1200 | 1201 | ||
1201 | if (common->cmnd[1] & ~0x02) { /* Mask away MSF */ | 1202 | if (common->cmnd[1] & ~0x02) { /* Mask away MSF */ |
1202 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | 1203 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; |
1203 | return -EINVAL; | 1204 | return -EINVAL; |
1204 | } | 1205 | } |
1205 | if (lba >= curlun->num_sectors) { | 1206 | if (lba >= curlun->num_sectors) { |
1206 | curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; | 1207 | curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; |
1207 | return -EINVAL; | 1208 | return -EINVAL; |
1208 | } | 1209 | } |
1209 | 1210 | ||
1210 | memset(buf, 0, 8); | 1211 | memset(buf, 0, 8); |
1211 | buf[0] = 0x01; /* 2048 bytes of user data, rest is EC */ | 1212 | buf[0] = 0x01; /* 2048 bytes of user data, rest is EC */ |
1212 | store_cdrom_address(&buf[4], msf, lba); | 1213 | store_cdrom_address(&buf[4], msf, lba); |
1213 | return 8; | 1214 | return 8; |
1214 | } | 1215 | } |
1215 | 1216 | ||
1216 | 1217 | ||
1217 | static int do_read_toc(struct fsg_common *common, struct fsg_buffhd *bh) | 1218 | static int do_read_toc(struct fsg_common *common, struct fsg_buffhd *bh) |
1218 | { | 1219 | { |
1219 | struct fsg_lun *curlun = &common->luns[common->lun]; | 1220 | struct fsg_lun *curlun = &common->luns[common->lun]; |
1220 | int msf = common->cmnd[1] & 0x02; | 1221 | int msf = common->cmnd[1] & 0x02; |
1221 | int start_track = common->cmnd[6]; | 1222 | int start_track = common->cmnd[6]; |
1222 | u8 *buf = (u8 *) bh->buf; | 1223 | u8 *buf = (u8 *) bh->buf; |
1223 | 1224 | ||
1224 | if ((common->cmnd[1] & ~0x02) != 0 || /* Mask away MSF */ | 1225 | if ((common->cmnd[1] & ~0x02) != 0 || /* Mask away MSF */ |
1225 | start_track > 1) { | 1226 | start_track > 1) { |
1226 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | 1227 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; |
1227 | return -EINVAL; | 1228 | return -EINVAL; |
1228 | } | 1229 | } |
1229 | 1230 | ||
1230 | memset(buf, 0, 20); | 1231 | memset(buf, 0, 20); |
1231 | buf[1] = (20-2); /* TOC data length */ | 1232 | buf[1] = (20-2); /* TOC data length */ |
1232 | buf[2] = 1; /* First track number */ | 1233 | buf[2] = 1; /* First track number */ |
1233 | buf[3] = 1; /* Last track number */ | 1234 | buf[3] = 1; /* Last track number */ |
1234 | buf[5] = 0x16; /* Data track, copying allowed */ | 1235 | buf[5] = 0x16; /* Data track, copying allowed */ |
1235 | buf[6] = 0x01; /* Only track is number 1 */ | 1236 | buf[6] = 0x01; /* Only track is number 1 */ |
1236 | store_cdrom_address(&buf[8], msf, 0); | 1237 | store_cdrom_address(&buf[8], msf, 0); |
1237 | 1238 | ||
1238 | buf[13] = 0x16; /* Lead-out track is data */ | 1239 | buf[13] = 0x16; /* Lead-out track is data */ |
1239 | buf[14] = 0xAA; /* Lead-out track number */ | 1240 | buf[14] = 0xAA; /* Lead-out track number */ |
1240 | store_cdrom_address(&buf[16], msf, curlun->num_sectors); | 1241 | store_cdrom_address(&buf[16], msf, curlun->num_sectors); |
1241 | 1242 | ||
1242 | return 20; | 1243 | return 20; |
1243 | } | 1244 | } |
1244 | 1245 | ||
1245 | static int do_mode_sense(struct fsg_common *common, struct fsg_buffhd *bh) | 1246 | static int do_mode_sense(struct fsg_common *common, struct fsg_buffhd *bh) |
1246 | { | 1247 | { |
1247 | struct fsg_lun *curlun = &common->luns[common->lun]; | 1248 | struct fsg_lun *curlun = &common->luns[common->lun]; |
1248 | int mscmnd = common->cmnd[0]; | 1249 | int mscmnd = common->cmnd[0]; |
1249 | u8 *buf = (u8 *) bh->buf; | 1250 | u8 *buf = (u8 *) bh->buf; |
1250 | u8 *buf0 = buf; | 1251 | u8 *buf0 = buf; |
1251 | int pc, page_code; | 1252 | int pc, page_code; |
1252 | int changeable_values, all_pages; | 1253 | int changeable_values, all_pages; |
1253 | int valid_page = 0; | 1254 | int valid_page = 0; |
1254 | int len, limit; | 1255 | int len, limit; |
1255 | 1256 | ||
1256 | if ((common->cmnd[1] & ~0x08) != 0) { /* Mask away DBD */ | 1257 | if ((common->cmnd[1] & ~0x08) != 0) { /* Mask away DBD */ |
1257 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | 1258 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; |
1258 | return -EINVAL; | 1259 | return -EINVAL; |
1259 | } | 1260 | } |
1260 | pc = common->cmnd[2] >> 6; | 1261 | pc = common->cmnd[2] >> 6; |
1261 | page_code = common->cmnd[2] & 0x3f; | 1262 | page_code = common->cmnd[2] & 0x3f; |
1262 | if (pc == 3) { | 1263 | if (pc == 3) { |
1263 | curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED; | 1264 | curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED; |
1264 | return -EINVAL; | 1265 | return -EINVAL; |
1265 | } | 1266 | } |
1266 | changeable_values = (pc == 1); | 1267 | changeable_values = (pc == 1); |
1267 | all_pages = (page_code == 0x3f); | 1268 | all_pages = (page_code == 0x3f); |
1268 | 1269 | ||
1269 | /* Write the mode parameter header. Fixed values are: default | 1270 | /* Write the mode parameter header. Fixed values are: default |
1270 | * medium type, no cache control (DPOFUA), and no block descriptors. | 1271 | * medium type, no cache control (DPOFUA), and no block descriptors. |
1271 | * The only variable value is the WriteProtect bit. We will fill in | 1272 | * The only variable value is the WriteProtect bit. We will fill in |
1272 | * the mode data length later. */ | 1273 | * the mode data length later. */ |
1273 | memset(buf, 0, 8); | 1274 | memset(buf, 0, 8); |
1274 | if (mscmnd == SC_MODE_SENSE_6) { | 1275 | if (mscmnd == SC_MODE_SENSE_6) { |
1275 | buf[2] = (curlun->ro ? 0x80 : 0x00); /* WP, DPOFUA */ | 1276 | buf[2] = (curlun->ro ? 0x80 : 0x00); /* WP, DPOFUA */ |
1276 | buf += 4; | 1277 | buf += 4; |
1277 | limit = 255; | 1278 | limit = 255; |
1278 | } else { /* SC_MODE_SENSE_10 */ | 1279 | } else { /* SC_MODE_SENSE_10 */ |
1279 | buf[3] = (curlun->ro ? 0x80 : 0x00); /* WP, DPOFUA */ | 1280 | buf[3] = (curlun->ro ? 0x80 : 0x00); /* WP, DPOFUA */ |
1280 | buf += 8; | 1281 | buf += 8; |
1281 | limit = 65535; /* Should really be FSG_BUFLEN */ | 1282 | limit = 65535; /* Should really be FSG_BUFLEN */ |
1282 | } | 1283 | } |
1283 | 1284 | ||
1284 | /* No block descriptors */ | 1285 | /* No block descriptors */ |
1285 | 1286 | ||
1286 | /* The mode pages, in numerical order. The only page we support | 1287 | /* The mode pages, in numerical order. The only page we support |
1287 | * is the Caching page. */ | 1288 | * is the Caching page. */ |
1288 | if (page_code == 0x08 || all_pages) { | 1289 | if (page_code == 0x08 || all_pages) { |
1289 | valid_page = 1; | 1290 | valid_page = 1; |
1290 | buf[0] = 0x08; /* Page code */ | 1291 | buf[0] = 0x08; /* Page code */ |
1291 | buf[1] = 10; /* Page length */ | 1292 | buf[1] = 10; /* Page length */ |
1292 | memset(buf+2, 0, 10); /* None of the fields are changeable */ | 1293 | memset(buf+2, 0, 10); /* None of the fields are changeable */ |
1293 | 1294 | ||
1294 | if (!changeable_values) { | 1295 | if (!changeable_values) { |
1295 | buf[2] = 0x04; /* Write cache enable, */ | 1296 | buf[2] = 0x04; /* Write cache enable, */ |
1296 | /* Read cache not disabled */ | 1297 | /* Read cache not disabled */ |
1297 | /* No cache retention priorities */ | 1298 | /* No cache retention priorities */ |
1298 | put_unaligned_be16(0xffff, &buf[4]); | 1299 | put_unaligned_be16(0xffff, &buf[4]); |
1299 | /* Don't disable prefetch */ | 1300 | /* Don't disable prefetch */ |
1300 | /* Minimum prefetch = 0 */ | 1301 | /* Minimum prefetch = 0 */ |
1301 | put_unaligned_be16(0xffff, &buf[8]); | 1302 | put_unaligned_be16(0xffff, &buf[8]); |
1302 | /* Maximum prefetch */ | 1303 | /* Maximum prefetch */ |
1303 | put_unaligned_be16(0xffff, &buf[10]); | 1304 | put_unaligned_be16(0xffff, &buf[10]); |
1304 | /* Maximum prefetch ceiling */ | 1305 | /* Maximum prefetch ceiling */ |
1305 | } | 1306 | } |
1306 | buf += 12; | 1307 | buf += 12; |
1307 | } | 1308 | } |
1308 | 1309 | ||
1309 | /* Check that a valid page was requested and the mode data length | 1310 | /* Check that a valid page was requested and the mode data length |
1310 | * isn't too long. */ | 1311 | * isn't too long. */ |
1311 | len = buf - buf0; | 1312 | len = buf - buf0; |
1312 | if (!valid_page || len > limit) { | 1313 | if (!valid_page || len > limit) { |
1313 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | 1314 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; |
1314 | return -EINVAL; | 1315 | return -EINVAL; |
1315 | } | 1316 | } |
1316 | 1317 | ||
1317 | /* Store the mode data length */ | 1318 | /* Store the mode data length */ |
1318 | if (mscmnd == SC_MODE_SENSE_6) | 1319 | if (mscmnd == SC_MODE_SENSE_6) |
1319 | buf0[0] = len - 1; | 1320 | buf0[0] = len - 1; |
1320 | else | 1321 | else |
1321 | put_unaligned_be16(len - 2, buf0); | 1322 | put_unaligned_be16(len - 2, buf0); |
1322 | return len; | 1323 | return len; |
1323 | } | 1324 | } |
1324 | 1325 | ||
1325 | 1326 | ||
1326 | static int do_start_stop(struct fsg_common *common) | 1327 | static int do_start_stop(struct fsg_common *common) |
1327 | { | 1328 | { |
1328 | struct fsg_lun *curlun = &common->luns[common->lun]; | 1329 | struct fsg_lun *curlun = &common->luns[common->lun]; |
1329 | 1330 | ||
1330 | if (!curlun) { | 1331 | if (!curlun) { |
1331 | return -EINVAL; | 1332 | return -EINVAL; |
1332 | } else if (!curlun->removable) { | 1333 | } else if (!curlun->removable) { |
1333 | curlun->sense_data = SS_INVALID_COMMAND; | 1334 | curlun->sense_data = SS_INVALID_COMMAND; |
1334 | return -EINVAL; | 1335 | return -EINVAL; |
1335 | } | 1336 | } |
1336 | 1337 | ||
1337 | return 0; | 1338 | return 0; |
1338 | } | 1339 | } |
1339 | 1340 | ||
1340 | static int do_prevent_allow(struct fsg_common *common) | 1341 | static int do_prevent_allow(struct fsg_common *common) |
1341 | { | 1342 | { |
1342 | struct fsg_lun *curlun = &common->luns[common->lun]; | 1343 | struct fsg_lun *curlun = &common->luns[common->lun]; |
1343 | int prevent; | 1344 | int prevent; |
1344 | 1345 | ||
1345 | if (!curlun->removable) { | 1346 | if (!curlun->removable) { |
1346 | curlun->sense_data = SS_INVALID_COMMAND; | 1347 | curlun->sense_data = SS_INVALID_COMMAND; |
1347 | return -EINVAL; | 1348 | return -EINVAL; |
1348 | } | 1349 | } |
1349 | 1350 | ||
1350 | prevent = common->cmnd[4] & 0x01; | 1351 | prevent = common->cmnd[4] & 0x01; |
1351 | if ((common->cmnd[4] & ~0x01) != 0) { /* Mask away Prevent */ | 1352 | if ((common->cmnd[4] & ~0x01) != 0) { /* Mask away Prevent */ |
1352 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | 1353 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; |
1353 | return -EINVAL; | 1354 | return -EINVAL; |
1354 | } | 1355 | } |
1355 | 1356 | ||
1356 | if (curlun->prevent_medium_removal && !prevent) | 1357 | if (curlun->prevent_medium_removal && !prevent) |
1357 | fsg_lun_fsync_sub(curlun); | 1358 | fsg_lun_fsync_sub(curlun); |
1358 | curlun->prevent_medium_removal = prevent; | 1359 | curlun->prevent_medium_removal = prevent; |
1359 | return 0; | 1360 | return 0; |
1360 | } | 1361 | } |
1361 | 1362 | ||
1362 | 1363 | ||
1363 | static int do_read_format_capacities(struct fsg_common *common, | 1364 | static int do_read_format_capacities(struct fsg_common *common, |
1364 | struct fsg_buffhd *bh) | 1365 | struct fsg_buffhd *bh) |
1365 | { | 1366 | { |
1366 | struct fsg_lun *curlun = &common->luns[common->lun]; | 1367 | struct fsg_lun *curlun = &common->luns[common->lun]; |
1367 | u8 *buf = (u8 *) bh->buf; | 1368 | u8 *buf = (u8 *) bh->buf; |
1368 | 1369 | ||
1369 | buf[0] = buf[1] = buf[2] = 0; | 1370 | buf[0] = buf[1] = buf[2] = 0; |
1370 | buf[3] = 8; /* Only the Current/Maximum Capacity Descriptor */ | 1371 | buf[3] = 8; /* Only the Current/Maximum Capacity Descriptor */ |
1371 | buf += 4; | 1372 | buf += 4; |
1372 | 1373 | ||
1373 | put_unaligned_be32(curlun->num_sectors, &buf[0]); | 1374 | put_unaligned_be32(curlun->num_sectors, &buf[0]); |
1374 | /* Number of blocks */ | 1375 | /* Number of blocks */ |
1375 | put_unaligned_be32(512, &buf[4]); /* Block length */ | 1376 | put_unaligned_be32(512, &buf[4]); /* Block length */ |
1376 | buf[4] = 0x02; /* Current capacity */ | 1377 | buf[4] = 0x02; /* Current capacity */ |
1377 | return 12; | 1378 | return 12; |
1378 | } | 1379 | } |
1379 | 1380 | ||
1380 | 1381 | ||
1381 | static int do_mode_select(struct fsg_common *common, struct fsg_buffhd *bh) | 1382 | static int do_mode_select(struct fsg_common *common, struct fsg_buffhd *bh) |
1382 | { | 1383 | { |
1383 | struct fsg_lun *curlun = &common->luns[common->lun]; | 1384 | struct fsg_lun *curlun = &common->luns[common->lun]; |
1384 | 1385 | ||
1385 | /* We don't support MODE SELECT */ | 1386 | /* We don't support MODE SELECT */ |
1386 | if (curlun) | 1387 | if (curlun) |
1387 | curlun->sense_data = SS_INVALID_COMMAND; | 1388 | curlun->sense_data = SS_INVALID_COMMAND; |
1388 | return -EINVAL; | 1389 | return -EINVAL; |
1389 | } | 1390 | } |
1390 | 1391 | ||
1391 | 1392 | ||
1392 | /*-------------------------------------------------------------------------*/ | 1393 | /*-------------------------------------------------------------------------*/ |
1393 | 1394 | ||
1394 | static int halt_bulk_in_endpoint(struct fsg_dev *fsg) | 1395 | static int halt_bulk_in_endpoint(struct fsg_dev *fsg) |
1395 | { | 1396 | { |
1396 | int rc; | 1397 | int rc; |
1397 | 1398 | ||
1398 | rc = fsg_set_halt(fsg, fsg->bulk_in); | 1399 | rc = fsg_set_halt(fsg, fsg->bulk_in); |
1399 | if (rc == -EAGAIN) | 1400 | if (rc == -EAGAIN) |
1400 | VDBG(fsg, "delayed bulk-in endpoint halt\n"); | 1401 | VDBG(fsg, "delayed bulk-in endpoint halt\n"); |
1401 | while (rc != 0) { | 1402 | while (rc != 0) { |
1402 | if (rc != -EAGAIN) { | 1403 | if (rc != -EAGAIN) { |
1403 | WARNING(fsg, "usb_ep_set_halt -> %d\n", rc); | 1404 | WARNING(fsg, "usb_ep_set_halt -> %d\n", rc); |
1404 | rc = 0; | 1405 | rc = 0; |
1405 | break; | 1406 | break; |
1406 | } | 1407 | } |
1407 | 1408 | ||
1408 | rc = usb_ep_set_halt(fsg->bulk_in); | 1409 | rc = usb_ep_set_halt(fsg->bulk_in); |
1409 | } | 1410 | } |
1410 | return rc; | 1411 | return rc; |
1411 | } | 1412 | } |
1412 | 1413 | ||
1413 | static int wedge_bulk_in_endpoint(struct fsg_dev *fsg) | 1414 | static int wedge_bulk_in_endpoint(struct fsg_dev *fsg) |
1414 | { | 1415 | { |
1415 | int rc; | 1416 | int rc; |
1416 | 1417 | ||
1417 | DBG(fsg, "bulk-in set wedge\n"); | 1418 | DBG(fsg, "bulk-in set wedge\n"); |
1418 | rc = 0; /* usb_ep_set_wedge(fsg->bulk_in); */ | 1419 | rc = 0; /* usb_ep_set_wedge(fsg->bulk_in); */ |
1419 | if (rc == -EAGAIN) | 1420 | if (rc == -EAGAIN) |
1420 | VDBG(fsg, "delayed bulk-in endpoint wedge\n"); | 1421 | VDBG(fsg, "delayed bulk-in endpoint wedge\n"); |
1421 | while (rc != 0) { | 1422 | while (rc != 0) { |
1422 | if (rc != -EAGAIN) { | 1423 | if (rc != -EAGAIN) { |
1423 | WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc); | 1424 | WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc); |
1424 | rc = 0; | 1425 | rc = 0; |
1425 | break; | 1426 | break; |
1426 | } | 1427 | } |
1427 | } | 1428 | } |
1428 | return rc; | 1429 | return rc; |
1429 | } | 1430 | } |
1430 | 1431 | ||
1431 | static int pad_with_zeros(struct fsg_dev *fsg) | 1432 | static int pad_with_zeros(struct fsg_dev *fsg) |
1432 | { | 1433 | { |
1433 | struct fsg_buffhd *bh = fsg->common->next_buffhd_to_fill; | 1434 | struct fsg_buffhd *bh = fsg->common->next_buffhd_to_fill; |
1434 | u32 nkeep = bh->inreq->length; | 1435 | u32 nkeep = bh->inreq->length; |
1435 | u32 nsend; | 1436 | u32 nsend; |
1436 | int rc; | 1437 | int rc; |
1437 | 1438 | ||
1438 | bh->state = BUF_STATE_EMPTY; /* For the first iteration */ | 1439 | bh->state = BUF_STATE_EMPTY; /* For the first iteration */ |
1439 | fsg->common->usb_amount_left = nkeep + fsg->common->residue; | 1440 | fsg->common->usb_amount_left = nkeep + fsg->common->residue; |
1440 | while (fsg->common->usb_amount_left > 0) { | 1441 | while (fsg->common->usb_amount_left > 0) { |
1441 | 1442 | ||
1442 | /* Wait for the next buffer to be free */ | 1443 | /* Wait for the next buffer to be free */ |
1443 | while (bh->state != BUF_STATE_EMPTY) { | 1444 | while (bh->state != BUF_STATE_EMPTY) { |
1444 | rc = sleep_thread(fsg->common); | 1445 | rc = sleep_thread(fsg->common); |
1445 | if (rc) | 1446 | if (rc) |
1446 | return rc; | 1447 | return rc; |
1447 | } | 1448 | } |
1448 | 1449 | ||
1449 | nsend = min(fsg->common->usb_amount_left, FSG_BUFLEN); | 1450 | nsend = min(fsg->common->usb_amount_left, FSG_BUFLEN); |
1450 | memset(bh->buf + nkeep, 0, nsend - nkeep); | 1451 | memset(bh->buf + nkeep, 0, nsend - nkeep); |
1451 | bh->inreq->length = nsend; | 1452 | bh->inreq->length = nsend; |
1452 | bh->inreq->zero = 0; | 1453 | bh->inreq->zero = 0; |
1453 | start_transfer(fsg, fsg->bulk_in, bh->inreq, | 1454 | start_transfer(fsg, fsg->bulk_in, bh->inreq, |
1454 | &bh->inreq_busy, &bh->state); | 1455 | &bh->inreq_busy, &bh->state); |
1455 | bh = fsg->common->next_buffhd_to_fill = bh->next; | 1456 | bh = fsg->common->next_buffhd_to_fill = bh->next; |
1456 | fsg->common->usb_amount_left -= nsend; | 1457 | fsg->common->usb_amount_left -= nsend; |
1457 | nkeep = 0; | 1458 | nkeep = 0; |
1458 | } | 1459 | } |
1459 | return 0; | 1460 | return 0; |
1460 | } | 1461 | } |
1461 | 1462 | ||
1462 | static int throw_away_data(struct fsg_common *common) | 1463 | static int throw_away_data(struct fsg_common *common) |
1463 | { | 1464 | { |
1464 | struct fsg_buffhd *bh; | 1465 | struct fsg_buffhd *bh; |
1465 | u32 amount; | 1466 | u32 amount; |
1466 | int rc; | 1467 | int rc; |
1467 | 1468 | ||
1468 | for (bh = common->next_buffhd_to_drain; | 1469 | for (bh = common->next_buffhd_to_drain; |
1469 | bh->state != BUF_STATE_EMPTY || common->usb_amount_left > 0; | 1470 | bh->state != BUF_STATE_EMPTY || common->usb_amount_left > 0; |
1470 | bh = common->next_buffhd_to_drain) { | 1471 | bh = common->next_buffhd_to_drain) { |
1471 | 1472 | ||
1472 | /* Throw away the data in a filled buffer */ | 1473 | /* Throw away the data in a filled buffer */ |
1473 | if (bh->state == BUF_STATE_FULL) { | 1474 | if (bh->state == BUF_STATE_FULL) { |
1474 | bh->state = BUF_STATE_EMPTY; | 1475 | bh->state = BUF_STATE_EMPTY; |
1475 | common->next_buffhd_to_drain = bh->next; | 1476 | common->next_buffhd_to_drain = bh->next; |
1476 | 1477 | ||
1477 | /* A short packet or an error ends everything */ | 1478 | /* A short packet or an error ends everything */ |
1478 | if (bh->outreq->actual != bh->outreq->length || | 1479 | if (bh->outreq->actual != bh->outreq->length || |
1479 | bh->outreq->status != 0) { | 1480 | bh->outreq->status != 0) { |
1480 | raise_exception(common, | 1481 | raise_exception(common, |
1481 | FSG_STATE_ABORT_BULK_OUT); | 1482 | FSG_STATE_ABORT_BULK_OUT); |
1482 | return -EINTR; | 1483 | return -EINTR; |
1483 | } | 1484 | } |
1484 | continue; | 1485 | continue; |
1485 | } | 1486 | } |
1486 | 1487 | ||
1487 | /* Try to submit another request if we need one */ | 1488 | /* Try to submit another request if we need one */ |
1488 | bh = common->next_buffhd_to_fill; | 1489 | bh = common->next_buffhd_to_fill; |
1489 | if (bh->state == BUF_STATE_EMPTY | 1490 | if (bh->state == BUF_STATE_EMPTY |
1490 | && common->usb_amount_left > 0) { | 1491 | && common->usb_amount_left > 0) { |
1491 | amount = min(common->usb_amount_left, FSG_BUFLEN); | 1492 | amount = min(common->usb_amount_left, FSG_BUFLEN); |
1492 | 1493 | ||
1493 | /* amount is always divisible by 512, hence by | 1494 | /* amount is always divisible by 512, hence by |
1494 | * the bulk-out maxpacket size */ | 1495 | * the bulk-out maxpacket size */ |
1495 | bh->outreq->length = amount; | 1496 | bh->outreq->length = amount; |
1496 | bh->bulk_out_intended_length = amount; | 1497 | bh->bulk_out_intended_length = amount; |
1497 | bh->outreq->short_not_ok = 1; | 1498 | bh->outreq->short_not_ok = 1; |
1498 | START_TRANSFER_OR(common, bulk_out, bh->outreq, | 1499 | START_TRANSFER_OR(common, bulk_out, bh->outreq, |
1499 | &bh->outreq_busy, &bh->state) | 1500 | &bh->outreq_busy, &bh->state) |
1500 | /* Don't know what to do if | 1501 | /* Don't know what to do if |
1501 | * common->fsg is NULL */ | 1502 | * common->fsg is NULL */ |
1502 | return -EIO; | 1503 | return -EIO; |
1503 | common->next_buffhd_to_fill = bh->next; | 1504 | common->next_buffhd_to_fill = bh->next; |
1504 | common->usb_amount_left -= amount; | 1505 | common->usb_amount_left -= amount; |
1505 | continue; | 1506 | continue; |
1506 | } | 1507 | } |
1507 | 1508 | ||
1508 | /* Otherwise wait for something to happen */ | 1509 | /* Otherwise wait for something to happen */ |
1509 | rc = sleep_thread(common); | 1510 | rc = sleep_thread(common); |
1510 | if (rc) | 1511 | if (rc) |
1511 | return rc; | 1512 | return rc; |
1512 | } | 1513 | } |
1513 | return 0; | 1514 | return 0; |
1514 | } | 1515 | } |
1515 | 1516 | ||
1516 | 1517 | ||
1517 | static int finish_reply(struct fsg_common *common) | 1518 | static int finish_reply(struct fsg_common *common) |
1518 | { | 1519 | { |
1519 | struct fsg_buffhd *bh = common->next_buffhd_to_fill; | 1520 | struct fsg_buffhd *bh = common->next_buffhd_to_fill; |
1520 | int rc = 0; | 1521 | int rc = 0; |
1521 | 1522 | ||
1522 | switch (common->data_dir) { | 1523 | switch (common->data_dir) { |
1523 | case DATA_DIR_NONE: | 1524 | case DATA_DIR_NONE: |
1524 | break; /* Nothing to send */ | 1525 | break; /* Nothing to send */ |
1525 | 1526 | ||
1526 | /* If we don't know whether the host wants to read or write, | 1527 | /* If we don't know whether the host wants to read or write, |
1527 | * this must be CB or CBI with an unknown command. We mustn't | 1528 | * this must be CB or CBI with an unknown command. We mustn't |
1528 | * try to send or receive any data. So stall both bulk pipes | 1529 | * try to send or receive any data. So stall both bulk pipes |
1529 | * if we can and wait for a reset. */ | 1530 | * if we can and wait for a reset. */ |
1530 | case DATA_DIR_UNKNOWN: | 1531 | case DATA_DIR_UNKNOWN: |
1531 | if (!common->can_stall) { | 1532 | if (!common->can_stall) { |
1532 | /* Nothing */ | 1533 | /* Nothing */ |
1533 | } else if (fsg_is_set(common)) { | 1534 | } else if (fsg_is_set(common)) { |
1534 | fsg_set_halt(common->fsg, common->fsg->bulk_out); | 1535 | fsg_set_halt(common->fsg, common->fsg->bulk_out); |
1535 | rc = halt_bulk_in_endpoint(common->fsg); | 1536 | rc = halt_bulk_in_endpoint(common->fsg); |
1536 | } else { | 1537 | } else { |
1537 | /* Don't know what to do if common->fsg is NULL */ | 1538 | /* Don't know what to do if common->fsg is NULL */ |
1538 | rc = -EIO; | 1539 | rc = -EIO; |
1539 | } | 1540 | } |
1540 | break; | 1541 | break; |
1541 | 1542 | ||
1542 | /* All but the last buffer of data must have already been sent */ | 1543 | /* All but the last buffer of data must have already been sent */ |
1543 | case DATA_DIR_TO_HOST: | 1544 | case DATA_DIR_TO_HOST: |
1544 | if (common->data_size == 0) { | 1545 | if (common->data_size == 0) { |
1545 | /* Nothing to send */ | 1546 | /* Nothing to send */ |
1546 | 1547 | ||
1547 | /* If there's no residue, simply send the last buffer */ | 1548 | /* If there's no residue, simply send the last buffer */ |
1548 | } else if (common->residue == 0) { | 1549 | } else if (common->residue == 0) { |
1549 | bh->inreq->zero = 0; | 1550 | bh->inreq->zero = 0; |
1550 | START_TRANSFER_OR(common, bulk_in, bh->inreq, | 1551 | START_TRANSFER_OR(common, bulk_in, bh->inreq, |
1551 | &bh->inreq_busy, &bh->state) | 1552 | &bh->inreq_busy, &bh->state) |
1552 | return -EIO; | 1553 | return -EIO; |
1553 | common->next_buffhd_to_fill = bh->next; | 1554 | common->next_buffhd_to_fill = bh->next; |
1554 | 1555 | ||
1555 | /* For Bulk-only, if we're allowed to stall then send the | 1556 | /* For Bulk-only, if we're allowed to stall then send the |
1556 | * short packet and halt the bulk-in endpoint. If we can't | 1557 | * short packet and halt the bulk-in endpoint. If we can't |
1557 | * stall, pad out the remaining data with 0's. */ | 1558 | * stall, pad out the remaining data with 0's. */ |
1558 | } else if (common->can_stall) { | 1559 | } else if (common->can_stall) { |
1559 | bh->inreq->zero = 1; | 1560 | bh->inreq->zero = 1; |
1560 | START_TRANSFER_OR(common, bulk_in, bh->inreq, | 1561 | START_TRANSFER_OR(common, bulk_in, bh->inreq, |
1561 | &bh->inreq_busy, &bh->state) | 1562 | &bh->inreq_busy, &bh->state) |
1562 | /* Don't know what to do if | 1563 | /* Don't know what to do if |
1563 | * common->fsg is NULL */ | 1564 | * common->fsg is NULL */ |
1564 | rc = -EIO; | 1565 | rc = -EIO; |
1565 | common->next_buffhd_to_fill = bh->next; | 1566 | common->next_buffhd_to_fill = bh->next; |
1566 | if (common->fsg) | 1567 | if (common->fsg) |
1567 | rc = halt_bulk_in_endpoint(common->fsg); | 1568 | rc = halt_bulk_in_endpoint(common->fsg); |
1568 | } else if (fsg_is_set(common)) { | 1569 | } else if (fsg_is_set(common)) { |
1569 | rc = pad_with_zeros(common->fsg); | 1570 | rc = pad_with_zeros(common->fsg); |
1570 | } else { | 1571 | } else { |
1571 | /* Don't know what to do if common->fsg is NULL */ | 1572 | /* Don't know what to do if common->fsg is NULL */ |
1572 | rc = -EIO; | 1573 | rc = -EIO; |
1573 | } | 1574 | } |
1574 | break; | 1575 | break; |
1575 | 1576 | ||
1576 | /* We have processed all we want from the data the host has sent. | 1577 | /* We have processed all we want from the data the host has sent. |
1577 | * There may still be outstanding bulk-out requests. */ | 1578 | * There may still be outstanding bulk-out requests. */ |
1578 | case DATA_DIR_FROM_HOST: | 1579 | case DATA_DIR_FROM_HOST: |
1579 | if (common->residue == 0) { | 1580 | if (common->residue == 0) { |
1580 | /* Nothing to receive */ | 1581 | /* Nothing to receive */ |
1581 | 1582 | ||
1582 | /* Did the host stop sending unexpectedly early? */ | 1583 | /* Did the host stop sending unexpectedly early? */ |
1583 | } else if (common->short_packet_received) { | 1584 | } else if (common->short_packet_received) { |
1584 | raise_exception(common, FSG_STATE_ABORT_BULK_OUT); | 1585 | raise_exception(common, FSG_STATE_ABORT_BULK_OUT); |
1585 | rc = -EINTR; | 1586 | rc = -EINTR; |
1586 | 1587 | ||
1587 | /* We haven't processed all the incoming data. Even though | 1588 | /* We haven't processed all the incoming data. Even though |
1588 | * we may be allowed to stall, doing so would cause a race. | 1589 | * we may be allowed to stall, doing so would cause a race. |
1589 | * The controller may already have ACK'ed all the remaining | 1590 | * The controller may already have ACK'ed all the remaining |
1590 | * bulk-out packets, in which case the host wouldn't see a | 1591 | * bulk-out packets, in which case the host wouldn't see a |
1591 | * STALL. Not realizing the endpoint was halted, it wouldn't | 1592 | * STALL. Not realizing the endpoint was halted, it wouldn't |
1592 | * clear the halt -- leading to problems later on. */ | 1593 | * clear the halt -- leading to problems later on. */ |
1593 | #if 0 | 1594 | #if 0 |
1594 | } else if (common->can_stall) { | 1595 | } else if (common->can_stall) { |
1595 | if (fsg_is_set(common)) | 1596 | if (fsg_is_set(common)) |
1596 | fsg_set_halt(common->fsg, | 1597 | fsg_set_halt(common->fsg, |
1597 | common->fsg->bulk_out); | 1598 | common->fsg->bulk_out); |
1598 | raise_exception(common, FSG_STATE_ABORT_BULK_OUT); | 1599 | raise_exception(common, FSG_STATE_ABORT_BULK_OUT); |
1599 | rc = -EINTR; | 1600 | rc = -EINTR; |
1600 | #endif | 1601 | #endif |
1601 | 1602 | ||
1602 | /* We can't stall. Read in the excess data and throw it | 1603 | /* We can't stall. Read in the excess data and throw it |
1603 | * all away. */ | 1604 | * all away. */ |
1604 | } else { | 1605 | } else { |
1605 | rc = throw_away_data(common); | 1606 | rc = throw_away_data(common); |
1606 | } | 1607 | } |
1607 | break; | 1608 | break; |
1608 | } | 1609 | } |
1609 | return rc; | 1610 | return rc; |
1610 | } | 1611 | } |
1611 | 1612 | ||
1612 | 1613 | ||
1613 | static int send_status(struct fsg_common *common) | 1614 | static int send_status(struct fsg_common *common) |
1614 | { | 1615 | { |
1615 | struct fsg_lun *curlun = &common->luns[common->lun]; | 1616 | struct fsg_lun *curlun = &common->luns[common->lun]; |
1616 | struct fsg_buffhd *bh; | 1617 | struct fsg_buffhd *bh; |
1617 | struct bulk_cs_wrap *csw; | 1618 | struct bulk_cs_wrap *csw; |
1618 | int rc; | 1619 | int rc; |
1619 | u8 status = USB_STATUS_PASS; | 1620 | u8 status = USB_STATUS_PASS; |
1620 | u32 sd, sdinfo = 0; | 1621 | u32 sd, sdinfo = 0; |
1621 | 1622 | ||
1622 | /* Wait for the next buffer to become available */ | 1623 | /* Wait for the next buffer to become available */ |
1623 | bh = common->next_buffhd_to_fill; | 1624 | bh = common->next_buffhd_to_fill; |
1624 | while (bh->state != BUF_STATE_EMPTY) { | 1625 | while (bh->state != BUF_STATE_EMPTY) { |
1625 | rc = sleep_thread(common); | 1626 | rc = sleep_thread(common); |
1626 | if (rc) | 1627 | if (rc) |
1627 | return rc; | 1628 | return rc; |
1628 | } | 1629 | } |
1629 | 1630 | ||
1630 | if (curlun) | 1631 | if (curlun) |
1631 | sd = curlun->sense_data; | 1632 | sd = curlun->sense_data; |
1632 | else if (common->bad_lun_okay) | 1633 | else if (common->bad_lun_okay) |
1633 | sd = SS_NO_SENSE; | 1634 | sd = SS_NO_SENSE; |
1634 | else | 1635 | else |
1635 | sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; | 1636 | sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; |
1636 | 1637 | ||
1637 | if (common->phase_error) { | 1638 | if (common->phase_error) { |
1638 | DBG(common, "sending phase-error status\n"); | 1639 | DBG(common, "sending phase-error status\n"); |
1639 | status = USB_STATUS_PHASE_ERROR; | 1640 | status = USB_STATUS_PHASE_ERROR; |
1640 | sd = SS_INVALID_COMMAND; | 1641 | sd = SS_INVALID_COMMAND; |
1641 | } else if (sd != SS_NO_SENSE) { | 1642 | } else if (sd != SS_NO_SENSE) { |
1642 | DBG(common, "sending command-failure status\n"); | 1643 | DBG(common, "sending command-failure status\n"); |
1643 | status = USB_STATUS_FAIL; | 1644 | status = USB_STATUS_FAIL; |
1644 | VDBG(common, " sense data: SK x%02x, ASC x%02x, ASCQ x%02x;" | 1645 | VDBG(common, " sense data: SK x%02x, ASC x%02x, ASCQ x%02x;" |
1645 | " info x%x\n", | 1646 | " info x%x\n", |
1646 | SK(sd), ASC(sd), ASCQ(sd), sdinfo); | 1647 | SK(sd), ASC(sd), ASCQ(sd), sdinfo); |
1647 | } | 1648 | } |
1648 | 1649 | ||
1649 | /* Store and send the Bulk-only CSW */ | 1650 | /* Store and send the Bulk-only CSW */ |
1650 | csw = (void *)bh->buf; | 1651 | csw = (void *)bh->buf; |
1651 | 1652 | ||
1652 | csw->Signature = cpu_to_le32(USB_BULK_CS_SIG); | 1653 | csw->Signature = cpu_to_le32(USB_BULK_CS_SIG); |
1653 | csw->Tag = common->tag; | 1654 | csw->Tag = common->tag; |
1654 | csw->Residue = cpu_to_le32(common->residue); | 1655 | csw->Residue = cpu_to_le32(common->residue); |
1655 | csw->Status = status; | 1656 | csw->Status = status; |
1656 | 1657 | ||
1657 | bh->inreq->length = USB_BULK_CS_WRAP_LEN; | 1658 | bh->inreq->length = USB_BULK_CS_WRAP_LEN; |
1658 | bh->inreq->zero = 0; | 1659 | bh->inreq->zero = 0; |
1659 | START_TRANSFER_OR(common, bulk_in, bh->inreq, | 1660 | START_TRANSFER_OR(common, bulk_in, bh->inreq, |
1660 | &bh->inreq_busy, &bh->state) | 1661 | &bh->inreq_busy, &bh->state) |
1661 | /* Don't know what to do if common->fsg is NULL */ | 1662 | /* Don't know what to do if common->fsg is NULL */ |
1662 | return -EIO; | 1663 | return -EIO; |
1663 | 1664 | ||
1664 | common->next_buffhd_to_fill = bh->next; | 1665 | common->next_buffhd_to_fill = bh->next; |
1665 | return 0; | 1666 | return 0; |
1666 | } | 1667 | } |
1667 | 1668 | ||
1668 | 1669 | ||
1669 | /*-------------------------------------------------------------------------*/ | 1670 | /*-------------------------------------------------------------------------*/ |
1670 | 1671 | ||
1671 | /* Check whether the command is properly formed and whether its data size | 1672 | /* Check whether the command is properly formed and whether its data size |
1672 | * and direction agree with the values we already have. */ | 1673 | * and direction agree with the values we already have. */ |
1673 | static int check_command(struct fsg_common *common, int cmnd_size, | 1674 | static int check_command(struct fsg_common *common, int cmnd_size, |
1674 | enum data_direction data_dir, unsigned int mask, | 1675 | enum data_direction data_dir, unsigned int mask, |
1675 | int needs_medium, const char *name) | 1676 | int needs_medium, const char *name) |
1676 | { | 1677 | { |
1677 | int i; | 1678 | int i; |
1678 | int lun = common->cmnd[1] >> 5; | 1679 | int lun = common->cmnd[1] >> 5; |
1679 | static const char dirletter[4] = {'u', 'o', 'i', 'n'}; | 1680 | static const char dirletter[4] = {'u', 'o', 'i', 'n'}; |
1680 | char hdlen[20]; | 1681 | char hdlen[20]; |
1681 | struct fsg_lun *curlun; | 1682 | struct fsg_lun *curlun; |
1682 | 1683 | ||
1683 | hdlen[0] = 0; | 1684 | hdlen[0] = 0; |
1684 | if (common->data_dir != DATA_DIR_UNKNOWN) | 1685 | if (common->data_dir != DATA_DIR_UNKNOWN) |
1685 | sprintf(hdlen, ", H%c=%u", dirletter[(int) common->data_dir], | 1686 | sprintf(hdlen, ", H%c=%u", dirletter[(int) common->data_dir], |
1686 | common->data_size); | 1687 | common->data_size); |
1687 | VDBG(common, "SCSI command: %s; Dc=%d, D%c=%u; Hc=%d%s\n", | 1688 | VDBG(common, "SCSI command: %s; Dc=%d, D%c=%u; Hc=%d%s\n", |
1688 | name, cmnd_size, dirletter[(int) data_dir], | 1689 | name, cmnd_size, dirletter[(int) data_dir], |
1689 | common->data_size_from_cmnd, common->cmnd_size, hdlen); | 1690 | common->data_size_from_cmnd, common->cmnd_size, hdlen); |
1690 | 1691 | ||
1691 | /* We can't reply at all until we know the correct data direction | 1692 | /* We can't reply at all until we know the correct data direction |
1692 | * and size. */ | 1693 | * and size. */ |
1693 | if (common->data_size_from_cmnd == 0) | 1694 | if (common->data_size_from_cmnd == 0) |
1694 | data_dir = DATA_DIR_NONE; | 1695 | data_dir = DATA_DIR_NONE; |
1695 | if (common->data_size < common->data_size_from_cmnd) { | 1696 | if (common->data_size < common->data_size_from_cmnd) { |
1696 | /* Host data size < Device data size is a phase error. | 1697 | /* Host data size < Device data size is a phase error. |
1697 | * Carry out the command, but only transfer as much as | 1698 | * Carry out the command, but only transfer as much as |
1698 | * we are allowed. */ | 1699 | * we are allowed. */ |
1699 | common->data_size_from_cmnd = common->data_size; | 1700 | common->data_size_from_cmnd = common->data_size; |
1700 | common->phase_error = 1; | 1701 | common->phase_error = 1; |
1701 | } | 1702 | } |
1702 | common->residue = common->data_size; | 1703 | common->residue = common->data_size; |
1703 | common->usb_amount_left = common->data_size; | 1704 | common->usb_amount_left = common->data_size; |
1704 | 1705 | ||
1705 | /* Conflicting data directions is a phase error */ | 1706 | /* Conflicting data directions is a phase error */ |
1706 | if (common->data_dir != data_dir | 1707 | if (common->data_dir != data_dir |
1707 | && common->data_size_from_cmnd > 0) { | 1708 | && common->data_size_from_cmnd > 0) { |
1708 | common->phase_error = 1; | 1709 | common->phase_error = 1; |
1709 | return -EINVAL; | 1710 | return -EINVAL; |
1710 | } | 1711 | } |
1711 | 1712 | ||
1712 | /* Verify the length of the command itself */ | 1713 | /* Verify the length of the command itself */ |
1713 | if (cmnd_size != common->cmnd_size) { | 1714 | if (cmnd_size != common->cmnd_size) { |
1714 | 1715 | ||
1715 | /* Special case workaround: There are plenty of buggy SCSI | 1716 | /* Special case workaround: There are plenty of buggy SCSI |
1716 | * implementations. Many have issues with cbw->Length | 1717 | * implementations. Many have issues with cbw->Length |
1717 | * field passing a wrong command size. For those cases we | 1718 | * field passing a wrong command size. For those cases we |
1718 | * always try to work around the problem by using the length | 1719 | * always try to work around the problem by using the length |
1719 | * sent by the host side provided it is at least as large | 1720 | * sent by the host side provided it is at least as large |
1720 | * as the correct command length. | 1721 | * as the correct command length. |
1721 | * Examples of such cases would be MS-Windows, which issues | 1722 | * Examples of such cases would be MS-Windows, which issues |
1722 | * REQUEST SENSE with cbw->Length == 12 where it should | 1723 | * REQUEST SENSE with cbw->Length == 12 where it should |
1723 | * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and | 1724 | * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and |
1724 | * REQUEST SENSE with cbw->Length == 10 where it should | 1725 | * REQUEST SENSE with cbw->Length == 10 where it should |
1725 | * be 6 as well. | 1726 | * be 6 as well. |
1726 | */ | 1727 | */ |
1727 | if (cmnd_size <= common->cmnd_size) { | 1728 | if (cmnd_size <= common->cmnd_size) { |
1728 | DBG(common, "%s is buggy! Expected length %d " | 1729 | DBG(common, "%s is buggy! Expected length %d " |
1729 | "but we got %d\n", name, | 1730 | "but we got %d\n", name, |
1730 | cmnd_size, common->cmnd_size); | 1731 | cmnd_size, common->cmnd_size); |
1731 | cmnd_size = common->cmnd_size; | 1732 | cmnd_size = common->cmnd_size; |
1732 | } else { | 1733 | } else { |
1733 | common->phase_error = 1; | 1734 | common->phase_error = 1; |
1734 | return -EINVAL; | 1735 | return -EINVAL; |
1735 | } | 1736 | } |
1736 | } | 1737 | } |
1737 | 1738 | ||
1738 | /* Check that the LUN values are consistent */ | 1739 | /* Check that the LUN values are consistent */ |
1739 | if (common->lun != lun) | 1740 | if (common->lun != lun) |
1740 | DBG(common, "using LUN %d from CBW, not LUN %d from CDB\n", | 1741 | DBG(common, "using LUN %d from CBW, not LUN %d from CDB\n", |
1741 | common->lun, lun); | 1742 | common->lun, lun); |
1742 | 1743 | ||
1743 | /* Check the LUN */ | 1744 | /* Check the LUN */ |
1744 | if (common->lun >= 0 && common->lun < common->nluns) { | 1745 | if (common->lun >= 0 && common->lun < common->nluns) { |
1745 | curlun = &common->luns[common->lun]; | 1746 | curlun = &common->luns[common->lun]; |
1746 | if (common->cmnd[0] != SC_REQUEST_SENSE) { | 1747 | if (common->cmnd[0] != SC_REQUEST_SENSE) { |
1747 | curlun->sense_data = SS_NO_SENSE; | 1748 | curlun->sense_data = SS_NO_SENSE; |
1748 | curlun->info_valid = 0; | 1749 | curlun->info_valid = 0; |
1749 | } | 1750 | } |
1750 | } else { | 1751 | } else { |
1751 | curlun = NULL; | 1752 | curlun = NULL; |
1752 | common->bad_lun_okay = 0; | 1753 | common->bad_lun_okay = 0; |
1753 | 1754 | ||
1754 | /* INQUIRY and REQUEST SENSE commands are explicitly allowed | 1755 | /* INQUIRY and REQUEST SENSE commands are explicitly allowed |
1755 | * to use unsupported LUNs; all others may not. */ | 1756 | * to use unsupported LUNs; all others may not. */ |
1756 | if (common->cmnd[0] != SC_INQUIRY && | 1757 | if (common->cmnd[0] != SC_INQUIRY && |
1757 | common->cmnd[0] != SC_REQUEST_SENSE) { | 1758 | common->cmnd[0] != SC_REQUEST_SENSE) { |
1758 | DBG(common, "unsupported LUN %d\n", common->lun); | 1759 | DBG(common, "unsupported LUN %d\n", common->lun); |
1759 | return -EINVAL; | 1760 | return -EINVAL; |
1760 | } | 1761 | } |
1761 | } | 1762 | } |
1762 | #if 0 | 1763 | #if 0 |
1763 | /* If a unit attention condition exists, only INQUIRY and | 1764 | /* If a unit attention condition exists, only INQUIRY and |
1764 | * REQUEST SENSE commands are allowed; anything else must fail. */ | 1765 | * REQUEST SENSE commands are allowed; anything else must fail. */ |
1765 | if (curlun && curlun->unit_attention_data != SS_NO_SENSE && | 1766 | if (curlun && curlun->unit_attention_data != SS_NO_SENSE && |
1766 | common->cmnd[0] != SC_INQUIRY && | 1767 | common->cmnd[0] != SC_INQUIRY && |
1767 | common->cmnd[0] != SC_REQUEST_SENSE) { | 1768 | common->cmnd[0] != SC_REQUEST_SENSE) { |
1768 | curlun->sense_data = curlun->unit_attention_data; | 1769 | curlun->sense_data = curlun->unit_attention_data; |
1769 | curlun->unit_attention_data = SS_NO_SENSE; | 1770 | curlun->unit_attention_data = SS_NO_SENSE; |
1770 | return -EINVAL; | 1771 | return -EINVAL; |
1771 | } | 1772 | } |
1772 | #endif | 1773 | #endif |
1773 | /* Check that only command bytes listed in the mask are non-zero */ | 1774 | /* Check that only command bytes listed in the mask are non-zero */ |
1774 | common->cmnd[1] &= 0x1f; /* Mask away the LUN */ | 1775 | common->cmnd[1] &= 0x1f; /* Mask away the LUN */ |
1775 | for (i = 1; i < cmnd_size; ++i) { | 1776 | for (i = 1; i < cmnd_size; ++i) { |
1776 | if (common->cmnd[i] && !(mask & (1 << i))) { | 1777 | if (common->cmnd[i] && !(mask & (1 << i))) { |
1777 | if (curlun) | 1778 | if (curlun) |
1778 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | 1779 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; |
1779 | return -EINVAL; | 1780 | return -EINVAL; |
1780 | } | 1781 | } |
1781 | } | 1782 | } |
1782 | 1783 | ||
1783 | return 0; | 1784 | return 0; |
1784 | } | 1785 | } |
1785 | 1786 | ||
1786 | 1787 | ||
1787 | static int do_scsi_command(struct fsg_common *common) | 1788 | static int do_scsi_command(struct fsg_common *common) |
1788 | { | 1789 | { |
1789 | struct fsg_buffhd *bh; | 1790 | struct fsg_buffhd *bh; |
1790 | int rc; | 1791 | int rc; |
1791 | int reply = -EINVAL; | 1792 | int reply = -EINVAL; |
1792 | int i; | 1793 | int i; |
1793 | static char unknown[16]; | 1794 | static char unknown[16]; |
1794 | struct fsg_lun *curlun = &common->luns[common->lun]; | 1795 | struct fsg_lun *curlun = &common->luns[common->lun]; |
1795 | 1796 | ||
1796 | dump_cdb(common); | 1797 | dump_cdb(common); |
1797 | 1798 | ||
1798 | /* Wait for the next buffer to become available for data or status */ | 1799 | /* Wait for the next buffer to become available for data or status */ |
1799 | bh = common->next_buffhd_to_fill; | 1800 | bh = common->next_buffhd_to_fill; |
1800 | common->next_buffhd_to_drain = bh; | 1801 | common->next_buffhd_to_drain = bh; |
1801 | while (bh->state != BUF_STATE_EMPTY) { | 1802 | while (bh->state != BUF_STATE_EMPTY) { |
1802 | rc = sleep_thread(common); | 1803 | rc = sleep_thread(common); |
1803 | if (rc) | 1804 | if (rc) |
1804 | return rc; | 1805 | return rc; |
1805 | } | 1806 | } |
1806 | common->phase_error = 0; | 1807 | common->phase_error = 0; |
1807 | common->short_packet_received = 0; | 1808 | common->short_packet_received = 0; |
1808 | 1809 | ||
1809 | down_read(&common->filesem); /* We're using the backing file */ | 1810 | down_read(&common->filesem); /* We're using the backing file */ |
1810 | switch (common->cmnd[0]) { | 1811 | switch (common->cmnd[0]) { |
1811 | 1812 | ||
1812 | case SC_INQUIRY: | 1813 | case SC_INQUIRY: |
1813 | common->data_size_from_cmnd = common->cmnd[4]; | 1814 | common->data_size_from_cmnd = common->cmnd[4]; |
1814 | reply = check_command(common, 6, DATA_DIR_TO_HOST, | 1815 | reply = check_command(common, 6, DATA_DIR_TO_HOST, |
1815 | (1<<4), 0, | 1816 | (1<<4), 0, |
1816 | "INQUIRY"); | 1817 | "INQUIRY"); |
1817 | if (reply == 0) | 1818 | if (reply == 0) |
1818 | reply = do_inquiry(common, bh); | 1819 | reply = do_inquiry(common, bh); |
1819 | break; | 1820 | break; |
1820 | 1821 | ||
1821 | case SC_MODE_SELECT_6: | 1822 | case SC_MODE_SELECT_6: |
1822 | common->data_size_from_cmnd = common->cmnd[4]; | 1823 | common->data_size_from_cmnd = common->cmnd[4]; |
1823 | reply = check_command(common, 6, DATA_DIR_FROM_HOST, | 1824 | reply = check_command(common, 6, DATA_DIR_FROM_HOST, |
1824 | (1<<1) | (1<<4), 0, | 1825 | (1<<1) | (1<<4), 0, |
1825 | "MODE SELECT(6)"); | 1826 | "MODE SELECT(6)"); |
1826 | if (reply == 0) | 1827 | if (reply == 0) |
1827 | reply = do_mode_select(common, bh); | 1828 | reply = do_mode_select(common, bh); |
1828 | break; | 1829 | break; |
1829 | 1830 | ||
1830 | case SC_MODE_SELECT_10: | 1831 | case SC_MODE_SELECT_10: |
1831 | common->data_size_from_cmnd = | 1832 | common->data_size_from_cmnd = |
1832 | get_unaligned_be16(&common->cmnd[7]); | 1833 | get_unaligned_be16(&common->cmnd[7]); |
1833 | reply = check_command(common, 10, DATA_DIR_FROM_HOST, | 1834 | reply = check_command(common, 10, DATA_DIR_FROM_HOST, |
1834 | (1<<1) | (3<<7), 0, | 1835 | (1<<1) | (3<<7), 0, |
1835 | "MODE SELECT(10)"); | 1836 | "MODE SELECT(10)"); |
1836 | if (reply == 0) | 1837 | if (reply == 0) |
1837 | reply = do_mode_select(common, bh); | 1838 | reply = do_mode_select(common, bh); |
1838 | break; | 1839 | break; |
1839 | 1840 | ||
1840 | case SC_MODE_SENSE_6: | 1841 | case SC_MODE_SENSE_6: |
1841 | common->data_size_from_cmnd = common->cmnd[4]; | 1842 | common->data_size_from_cmnd = common->cmnd[4]; |
1842 | reply = check_command(common, 6, DATA_DIR_TO_HOST, | 1843 | reply = check_command(common, 6, DATA_DIR_TO_HOST, |
1843 | (1<<1) | (1<<2) | (1<<4), 0, | 1844 | (1<<1) | (1<<2) | (1<<4), 0, |
1844 | "MODE SENSE(6)"); | 1845 | "MODE SENSE(6)"); |
1845 | if (reply == 0) | 1846 | if (reply == 0) |
1846 | reply = do_mode_sense(common, bh); | 1847 | reply = do_mode_sense(common, bh); |
1847 | break; | 1848 | break; |
1848 | 1849 | ||
1849 | case SC_MODE_SENSE_10: | 1850 | case SC_MODE_SENSE_10: |
1850 | common->data_size_from_cmnd = | 1851 | common->data_size_from_cmnd = |
1851 | get_unaligned_be16(&common->cmnd[7]); | 1852 | get_unaligned_be16(&common->cmnd[7]); |
1852 | reply = check_command(common, 10, DATA_DIR_TO_HOST, | 1853 | reply = check_command(common, 10, DATA_DIR_TO_HOST, |
1853 | (1<<1) | (1<<2) | (3<<7), 0, | 1854 | (1<<1) | (1<<2) | (3<<7), 0, |
1854 | "MODE SENSE(10)"); | 1855 | "MODE SENSE(10)"); |
1855 | if (reply == 0) | 1856 | if (reply == 0) |
1856 | reply = do_mode_sense(common, bh); | 1857 | reply = do_mode_sense(common, bh); |
1857 | break; | 1858 | break; |
1858 | 1859 | ||
1859 | case SC_PREVENT_ALLOW_MEDIUM_REMOVAL: | 1860 | case SC_PREVENT_ALLOW_MEDIUM_REMOVAL: |
1860 | common->data_size_from_cmnd = 0; | 1861 | common->data_size_from_cmnd = 0; |
1861 | reply = check_command(common, 6, DATA_DIR_NONE, | 1862 | reply = check_command(common, 6, DATA_DIR_NONE, |
1862 | (1<<4), 0, | 1863 | (1<<4), 0, |
1863 | "PREVENT-ALLOW MEDIUM REMOVAL"); | 1864 | "PREVENT-ALLOW MEDIUM REMOVAL"); |
1864 | if (reply == 0) | 1865 | if (reply == 0) |
1865 | reply = do_prevent_allow(common); | 1866 | reply = do_prevent_allow(common); |
1866 | break; | 1867 | break; |
1867 | 1868 | ||
1868 | case SC_READ_6: | 1869 | case SC_READ_6: |
1869 | i = common->cmnd[4]; | 1870 | i = common->cmnd[4]; |
1870 | common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; | 1871 | common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; |
1871 | reply = check_command(common, 6, DATA_DIR_TO_HOST, | 1872 | reply = check_command(common, 6, DATA_DIR_TO_HOST, |
1872 | (7<<1) | (1<<4), 1, | 1873 | (7<<1) | (1<<4), 1, |
1873 | "READ(6)"); | 1874 | "READ(6)"); |
1874 | if (reply == 0) | 1875 | if (reply == 0) |
1875 | reply = do_read(common); | 1876 | reply = do_read(common); |
1876 | break; | 1877 | break; |
1877 | 1878 | ||
1878 | case SC_READ_10: | 1879 | case SC_READ_10: |
1879 | common->data_size_from_cmnd = | 1880 | common->data_size_from_cmnd = |
1880 | get_unaligned_be16(&common->cmnd[7]) << 9; | 1881 | get_unaligned_be16(&common->cmnd[7]) << 9; |
1881 | reply = check_command(common, 10, DATA_DIR_TO_HOST, | 1882 | reply = check_command(common, 10, DATA_DIR_TO_HOST, |
1882 | (1<<1) | (0xf<<2) | (3<<7), 1, | 1883 | (1<<1) | (0xf<<2) | (3<<7), 1, |
1883 | "READ(10)"); | 1884 | "READ(10)"); |
1884 | if (reply == 0) | 1885 | if (reply == 0) |
1885 | reply = do_read(common); | 1886 | reply = do_read(common); |
1886 | break; | 1887 | break; |
1887 | 1888 | ||
1888 | case SC_READ_12: | 1889 | case SC_READ_12: |
1889 | common->data_size_from_cmnd = | 1890 | common->data_size_from_cmnd = |
1890 | get_unaligned_be32(&common->cmnd[6]) << 9; | 1891 | get_unaligned_be32(&common->cmnd[6]) << 9; |
1891 | reply = check_command(common, 12, DATA_DIR_TO_HOST, | 1892 | reply = check_command(common, 12, DATA_DIR_TO_HOST, |
1892 | (1<<1) | (0xf<<2) | (0xf<<6), 1, | 1893 | (1<<1) | (0xf<<2) | (0xf<<6), 1, |
1893 | "READ(12)"); | 1894 | "READ(12)"); |
1894 | if (reply == 0) | 1895 | if (reply == 0) |
1895 | reply = do_read(common); | 1896 | reply = do_read(common); |
1896 | break; | 1897 | break; |
1897 | 1898 | ||
1898 | case SC_READ_CAPACITY: | 1899 | case SC_READ_CAPACITY: |
1899 | common->data_size_from_cmnd = 8; | 1900 | common->data_size_from_cmnd = 8; |
1900 | reply = check_command(common, 10, DATA_DIR_TO_HOST, | 1901 | reply = check_command(common, 10, DATA_DIR_TO_HOST, |
1901 | (0xf<<2) | (1<<8), 1, | 1902 | (0xf<<2) | (1<<8), 1, |
1902 | "READ CAPACITY"); | 1903 | "READ CAPACITY"); |
1903 | if (reply == 0) | 1904 | if (reply == 0) |
1904 | reply = do_read_capacity(common, bh); | 1905 | reply = do_read_capacity(common, bh); |
1905 | break; | 1906 | break; |
1906 | 1907 | ||
1907 | case SC_READ_HEADER: | 1908 | case SC_READ_HEADER: |
1908 | if (!common->luns[common->lun].cdrom) | 1909 | if (!common->luns[common->lun].cdrom) |
1909 | goto unknown_cmnd; | 1910 | goto unknown_cmnd; |
1910 | common->data_size_from_cmnd = | 1911 | common->data_size_from_cmnd = |
1911 | get_unaligned_be16(&common->cmnd[7]); | 1912 | get_unaligned_be16(&common->cmnd[7]); |
1912 | reply = check_command(common, 10, DATA_DIR_TO_HOST, | 1913 | reply = check_command(common, 10, DATA_DIR_TO_HOST, |
1913 | (3<<7) | (0x1f<<1), 1, | 1914 | (3<<7) | (0x1f<<1), 1, |
1914 | "READ HEADER"); | 1915 | "READ HEADER"); |
1915 | if (reply == 0) | 1916 | if (reply == 0) |
1916 | reply = do_read_header(common, bh); | 1917 | reply = do_read_header(common, bh); |
1917 | break; | 1918 | break; |
1918 | 1919 | ||
1919 | case SC_READ_TOC: | 1920 | case SC_READ_TOC: |
1920 | if (!common->luns[common->lun].cdrom) | 1921 | if (!common->luns[common->lun].cdrom) |
1921 | goto unknown_cmnd; | 1922 | goto unknown_cmnd; |
1922 | common->data_size_from_cmnd = | 1923 | common->data_size_from_cmnd = |
1923 | get_unaligned_be16(&common->cmnd[7]); | 1924 | get_unaligned_be16(&common->cmnd[7]); |
1924 | reply = check_command(common, 10, DATA_DIR_TO_HOST, | 1925 | reply = check_command(common, 10, DATA_DIR_TO_HOST, |
1925 | (7<<6) | (1<<1), 1, | 1926 | (7<<6) | (1<<1), 1, |
1926 | "READ TOC"); | 1927 | "READ TOC"); |
1927 | if (reply == 0) | 1928 | if (reply == 0) |
1928 | reply = do_read_toc(common, bh); | 1929 | reply = do_read_toc(common, bh); |
1929 | break; | 1930 | break; |
1930 | 1931 | ||
1931 | case SC_READ_FORMAT_CAPACITIES: | 1932 | case SC_READ_FORMAT_CAPACITIES: |
1932 | common->data_size_from_cmnd = | 1933 | common->data_size_from_cmnd = |
1933 | get_unaligned_be16(&common->cmnd[7]); | 1934 | get_unaligned_be16(&common->cmnd[7]); |
1934 | reply = check_command(common, 10, DATA_DIR_TO_HOST, | 1935 | reply = check_command(common, 10, DATA_DIR_TO_HOST, |
1935 | (3<<7), 1, | 1936 | (3<<7), 1, |
1936 | "READ FORMAT CAPACITIES"); | 1937 | "READ FORMAT CAPACITIES"); |
1937 | if (reply == 0) | 1938 | if (reply == 0) |
1938 | reply = do_read_format_capacities(common, bh); | 1939 | reply = do_read_format_capacities(common, bh); |
1939 | break; | 1940 | break; |
1940 | 1941 | ||
1941 | case SC_REQUEST_SENSE: | 1942 | case SC_REQUEST_SENSE: |
1942 | common->data_size_from_cmnd = common->cmnd[4]; | 1943 | common->data_size_from_cmnd = common->cmnd[4]; |
1943 | reply = check_command(common, 6, DATA_DIR_TO_HOST, | 1944 | reply = check_command(common, 6, DATA_DIR_TO_HOST, |
1944 | (1<<4), 0, | 1945 | (1<<4), 0, |
1945 | "REQUEST SENSE"); | 1946 | "REQUEST SENSE"); |
1946 | if (reply == 0) | 1947 | if (reply == 0) |
1947 | reply = do_request_sense(common, bh); | 1948 | reply = do_request_sense(common, bh); |
1948 | break; | 1949 | break; |
1949 | 1950 | ||
1950 | case SC_START_STOP_UNIT: | 1951 | case SC_START_STOP_UNIT: |
1951 | common->data_size_from_cmnd = 0; | 1952 | common->data_size_from_cmnd = 0; |
1952 | reply = check_command(common, 6, DATA_DIR_NONE, | 1953 | reply = check_command(common, 6, DATA_DIR_NONE, |
1953 | (1<<1) | (1<<4), 0, | 1954 | (1<<1) | (1<<4), 0, |
1954 | "START-STOP UNIT"); | 1955 | "START-STOP UNIT"); |
1955 | if (reply == 0) | 1956 | if (reply == 0) |
1956 | reply = do_start_stop(common); | 1957 | reply = do_start_stop(common); |
1957 | break; | 1958 | break; |
1958 | 1959 | ||
1959 | case SC_SYNCHRONIZE_CACHE: | 1960 | case SC_SYNCHRONIZE_CACHE: |
1960 | common->data_size_from_cmnd = 0; | 1961 | common->data_size_from_cmnd = 0; |
1961 | reply = check_command(common, 10, DATA_DIR_NONE, | 1962 | reply = check_command(common, 10, DATA_DIR_NONE, |
1962 | (0xf<<2) | (3<<7), 1, | 1963 | (0xf<<2) | (3<<7), 1, |
1963 | "SYNCHRONIZE CACHE"); | 1964 | "SYNCHRONIZE CACHE"); |
1964 | if (reply == 0) | 1965 | if (reply == 0) |
1965 | reply = do_synchronize_cache(common); | 1966 | reply = do_synchronize_cache(common); |
1966 | break; | 1967 | break; |
1967 | 1968 | ||
1968 | case SC_TEST_UNIT_READY: | 1969 | case SC_TEST_UNIT_READY: |
1969 | common->data_size_from_cmnd = 0; | 1970 | common->data_size_from_cmnd = 0; |
1970 | reply = check_command(common, 6, DATA_DIR_NONE, | 1971 | reply = check_command(common, 6, DATA_DIR_NONE, |
1971 | 0, 1, | 1972 | 0, 1, |
1972 | "TEST UNIT READY"); | 1973 | "TEST UNIT READY"); |
1973 | break; | 1974 | break; |
1974 | 1975 | ||
1975 | /* Although optional, this command is used by MS-Windows. We | 1976 | /* Although optional, this command is used by MS-Windows. We |
1976 | * support a minimal version: BytChk must be 0. */ | 1977 | * support a minimal version: BytChk must be 0. */ |
1977 | case SC_VERIFY: | 1978 | case SC_VERIFY: |
1978 | common->data_size_from_cmnd = 0; | 1979 | common->data_size_from_cmnd = 0; |
1979 | reply = check_command(common, 10, DATA_DIR_NONE, | 1980 | reply = check_command(common, 10, DATA_DIR_NONE, |
1980 | (1<<1) | (0xf<<2) | (3<<7), 1, | 1981 | (1<<1) | (0xf<<2) | (3<<7), 1, |
1981 | "VERIFY"); | 1982 | "VERIFY"); |
1982 | if (reply == 0) | 1983 | if (reply == 0) |
1983 | reply = do_verify(common); | 1984 | reply = do_verify(common); |
1984 | break; | 1985 | break; |
1985 | 1986 | ||
1986 | case SC_WRITE_6: | 1987 | case SC_WRITE_6: |
1987 | i = common->cmnd[4]; | 1988 | i = common->cmnd[4]; |
1988 | common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; | 1989 | common->data_size_from_cmnd = (i == 0 ? 256 : i) << 9; |
1989 | reply = check_command(common, 6, DATA_DIR_FROM_HOST, | 1990 | reply = check_command(common, 6, DATA_DIR_FROM_HOST, |
1990 | (7<<1) | (1<<4), 1, | 1991 | (7<<1) | (1<<4), 1, |
1991 | "WRITE(6)"); | 1992 | "WRITE(6)"); |
1992 | if (reply == 0) | 1993 | if (reply == 0) |
1993 | reply = do_write(common); | 1994 | reply = do_write(common); |
1994 | break; | 1995 | break; |
1995 | 1996 | ||
1996 | case SC_WRITE_10: | 1997 | case SC_WRITE_10: |
1997 | common->data_size_from_cmnd = | 1998 | common->data_size_from_cmnd = |
1998 | get_unaligned_be16(&common->cmnd[7]) << 9; | 1999 | get_unaligned_be16(&common->cmnd[7]) << 9; |
1999 | reply = check_command(common, 10, DATA_DIR_FROM_HOST, | 2000 | reply = check_command(common, 10, DATA_DIR_FROM_HOST, |
2000 | (1<<1) | (0xf<<2) | (3<<7), 1, | 2001 | (1<<1) | (0xf<<2) | (3<<7), 1, |
2001 | "WRITE(10)"); | 2002 | "WRITE(10)"); |
2002 | if (reply == 0) | 2003 | if (reply == 0) |
2003 | reply = do_write(common); | 2004 | reply = do_write(common); |
2004 | break; | 2005 | break; |
2005 | 2006 | ||
2006 | case SC_WRITE_12: | 2007 | case SC_WRITE_12: |
2007 | common->data_size_from_cmnd = | 2008 | common->data_size_from_cmnd = |
2008 | get_unaligned_be32(&common->cmnd[6]) << 9; | 2009 | get_unaligned_be32(&common->cmnd[6]) << 9; |
2009 | reply = check_command(common, 12, DATA_DIR_FROM_HOST, | 2010 | reply = check_command(common, 12, DATA_DIR_FROM_HOST, |
2010 | (1<<1) | (0xf<<2) | (0xf<<6), 1, | 2011 | (1<<1) | (0xf<<2) | (0xf<<6), 1, |
2011 | "WRITE(12)"); | 2012 | "WRITE(12)"); |
2012 | if (reply == 0) | 2013 | if (reply == 0) |
2013 | reply = do_write(common); | 2014 | reply = do_write(common); |
2014 | break; | 2015 | break; |
2015 | 2016 | ||
2016 | /* Some mandatory commands that we recognize but don't implement. | 2017 | /* Some mandatory commands that we recognize but don't implement. |
2017 | * They don't mean much in this setting. It's left as an exercise | 2018 | * They don't mean much in this setting. It's left as an exercise |
2018 | * for anyone interested to implement RESERVE and RELEASE in terms | 2019 | * for anyone interested to implement RESERVE and RELEASE in terms |
2019 | * of Posix locks. */ | 2020 | * of Posix locks. */ |
2020 | case SC_FORMAT_UNIT: | 2021 | case SC_FORMAT_UNIT: |
2021 | case SC_RELEASE: | 2022 | case SC_RELEASE: |
2022 | case SC_RESERVE: | 2023 | case SC_RESERVE: |
2023 | case SC_SEND_DIAGNOSTIC: | 2024 | case SC_SEND_DIAGNOSTIC: |
2024 | /* Fall through */ | 2025 | /* Fall through */ |
2025 | 2026 | ||
2026 | default: | 2027 | default: |
2027 | unknown_cmnd: | 2028 | unknown_cmnd: |
2028 | common->data_size_from_cmnd = 0; | 2029 | common->data_size_from_cmnd = 0; |
2029 | sprintf(unknown, "Unknown x%02x", common->cmnd[0]); | 2030 | sprintf(unknown, "Unknown x%02x", common->cmnd[0]); |
2030 | reply = check_command(common, common->cmnd_size, | 2031 | reply = check_command(common, common->cmnd_size, |
2031 | DATA_DIR_UNKNOWN, 0xff, 0, unknown); | 2032 | DATA_DIR_UNKNOWN, 0xff, 0, unknown); |
2032 | if (reply == 0) { | 2033 | if (reply == 0) { |
2033 | curlun->sense_data = SS_INVALID_COMMAND; | 2034 | curlun->sense_data = SS_INVALID_COMMAND; |
2034 | reply = -EINVAL; | 2035 | reply = -EINVAL; |
2035 | } | 2036 | } |
2036 | break; | 2037 | break; |
2037 | } | 2038 | } |
2038 | up_read(&common->filesem); | 2039 | up_read(&common->filesem); |
2039 | 2040 | ||
2040 | if (reply == -EINTR) | 2041 | if (reply == -EINTR) |
2041 | return -EINTR; | 2042 | return -EINTR; |
2042 | 2043 | ||
2043 | /* Set up the single reply buffer for finish_reply() */ | 2044 | /* Set up the single reply buffer for finish_reply() */ |
2044 | if (reply == -EINVAL) | 2045 | if (reply == -EINVAL) |
2045 | reply = 0; /* Error reply length */ | 2046 | reply = 0; /* Error reply length */ |
2046 | if (reply >= 0 && common->data_dir == DATA_DIR_TO_HOST) { | 2047 | if (reply >= 0 && common->data_dir == DATA_DIR_TO_HOST) { |
2047 | reply = min((u32) reply, common->data_size_from_cmnd); | 2048 | reply = min((u32) reply, common->data_size_from_cmnd); |
2048 | bh->inreq->length = reply; | 2049 | bh->inreq->length = reply; |
2049 | bh->state = BUF_STATE_FULL; | 2050 | bh->state = BUF_STATE_FULL; |
2050 | common->residue -= reply; | 2051 | common->residue -= reply; |
2051 | } /* Otherwise it's already set */ | 2052 | } /* Otherwise it's already set */ |
2052 | 2053 | ||
2053 | return 0; | 2054 | return 0; |
2054 | } | 2055 | } |
2055 | 2056 | ||
2056 | /*-------------------------------------------------------------------------*/ | 2057 | /*-------------------------------------------------------------------------*/ |
2057 | 2058 | ||
2058 | static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) | 2059 | static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) |
2059 | { | 2060 | { |
2060 | struct usb_request *req = bh->outreq; | 2061 | struct usb_request *req = bh->outreq; |
2061 | struct fsg_bulk_cb_wrap *cbw = req->buf; | 2062 | struct fsg_bulk_cb_wrap *cbw = req->buf; |
2062 | struct fsg_common *common = fsg->common; | 2063 | struct fsg_common *common = fsg->common; |
2063 | 2064 | ||
2064 | /* Was this a real packet? Should it be ignored? */ | 2065 | /* Was this a real packet? Should it be ignored? */ |
2065 | if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags)) | 2066 | if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags)) |
2066 | return -EINVAL; | 2067 | return -EINVAL; |
2067 | 2068 | ||
2068 | /* Is the CBW valid? */ | 2069 | /* Is the CBW valid? */ |
2069 | if (req->actual != USB_BULK_CB_WRAP_LEN || | 2070 | if (req->actual != USB_BULK_CB_WRAP_LEN || |
2070 | cbw->Signature != cpu_to_le32( | 2071 | cbw->Signature != cpu_to_le32( |
2071 | USB_BULK_CB_SIG)) { | 2072 | USB_BULK_CB_SIG)) { |
2072 | DBG(fsg, "invalid CBW: len %u sig 0x%x\n", | 2073 | DBG(fsg, "invalid CBW: len %u sig 0x%x\n", |
2073 | req->actual, | 2074 | req->actual, |
2074 | le32_to_cpu(cbw->Signature)); | 2075 | le32_to_cpu(cbw->Signature)); |
2075 | 2076 | ||
2076 | /* The Bulk-only spec says we MUST stall the IN endpoint | 2077 | /* The Bulk-only spec says we MUST stall the IN endpoint |
2077 | * (6.6.1), so it's unavoidable. It also says we must | 2078 | * (6.6.1), so it's unavoidable. It also says we must |
2078 | * retain this state until the next reset, but there's | 2079 | * retain this state until the next reset, but there's |
2079 | * no way to tell the controller driver it should ignore | 2080 | * no way to tell the controller driver it should ignore |
2080 | * Clear-Feature(HALT) requests. | 2081 | * Clear-Feature(HALT) requests. |
2081 | * | 2082 | * |
2082 | * We aren't required to halt the OUT endpoint; instead | 2083 | * We aren't required to halt the OUT endpoint; instead |
2083 | * we can simply accept and discard any data received | 2084 | * we can simply accept and discard any data received |
2084 | * until the next reset. */ | 2085 | * until the next reset. */ |
2085 | wedge_bulk_in_endpoint(fsg); | 2086 | wedge_bulk_in_endpoint(fsg); |
2086 | set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); | 2087 | set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); |
2087 | return -EINVAL; | 2088 | return -EINVAL; |
2088 | } | 2089 | } |
2089 | 2090 | ||
2090 | /* Is the CBW meaningful? */ | 2091 | /* Is the CBW meaningful? */ |
2091 | if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~USB_BULK_IN_FLAG || | 2092 | if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~USB_BULK_IN_FLAG || |
2092 | cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) { | 2093 | cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) { |
2093 | DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, " | 2094 | DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, " |
2094 | "cmdlen %u\n", | 2095 | "cmdlen %u\n", |
2095 | cbw->Lun, cbw->Flags, cbw->Length); | 2096 | cbw->Lun, cbw->Flags, cbw->Length); |
2096 | 2097 | ||
2097 | /* We can do anything we want here, so let's stall the | 2098 | /* We can do anything we want here, so let's stall the |
2098 | * bulk pipes if we are allowed to. */ | 2099 | * bulk pipes if we are allowed to. */ |
2099 | if (common->can_stall) { | 2100 | if (common->can_stall) { |
2100 | fsg_set_halt(fsg, fsg->bulk_out); | 2101 | fsg_set_halt(fsg, fsg->bulk_out); |
2101 | halt_bulk_in_endpoint(fsg); | 2102 | halt_bulk_in_endpoint(fsg); |
2102 | } | 2103 | } |
2103 | return -EINVAL; | 2104 | return -EINVAL; |
2104 | } | 2105 | } |
2105 | 2106 | ||
2106 | /* Save the command for later */ | 2107 | /* Save the command for later */ |
2107 | common->cmnd_size = cbw->Length; | 2108 | common->cmnd_size = cbw->Length; |
2108 | memcpy(common->cmnd, cbw->CDB, common->cmnd_size); | 2109 | memcpy(common->cmnd, cbw->CDB, common->cmnd_size); |
2109 | if (cbw->Flags & USB_BULK_IN_FLAG) | 2110 | if (cbw->Flags & USB_BULK_IN_FLAG) |
2110 | common->data_dir = DATA_DIR_TO_HOST; | 2111 | common->data_dir = DATA_DIR_TO_HOST; |
2111 | else | 2112 | else |
2112 | common->data_dir = DATA_DIR_FROM_HOST; | 2113 | common->data_dir = DATA_DIR_FROM_HOST; |
2113 | common->data_size = le32_to_cpu(cbw->DataTransferLength); | 2114 | common->data_size = le32_to_cpu(cbw->DataTransferLength); |
2114 | if (common->data_size == 0) | 2115 | if (common->data_size == 0) |
2115 | common->data_dir = DATA_DIR_NONE; | 2116 | common->data_dir = DATA_DIR_NONE; |
2116 | common->lun = cbw->Lun; | 2117 | common->lun = cbw->Lun; |
2117 | common->tag = cbw->Tag; | 2118 | common->tag = cbw->Tag; |
2118 | return 0; | 2119 | return 0; |
2119 | } | 2120 | } |
2120 | 2121 | ||
2121 | 2122 | ||
2122 | static int get_next_command(struct fsg_common *common) | 2123 | static int get_next_command(struct fsg_common *common) |
2123 | { | 2124 | { |
2124 | struct fsg_buffhd *bh; | 2125 | struct fsg_buffhd *bh; |
2125 | int rc = 0; | 2126 | int rc = 0; |
2126 | 2127 | ||
2127 | /* Wait for the next buffer to become available */ | 2128 | /* Wait for the next buffer to become available */ |
2128 | bh = common->next_buffhd_to_fill; | 2129 | bh = common->next_buffhd_to_fill; |
2129 | while (bh->state != BUF_STATE_EMPTY) { | 2130 | while (bh->state != BUF_STATE_EMPTY) { |
2130 | rc = sleep_thread(common); | 2131 | rc = sleep_thread(common); |
2131 | if (rc) | 2132 | if (rc) |
2132 | return rc; | 2133 | return rc; |
2133 | } | 2134 | } |
2134 | 2135 | ||
2135 | /* Queue a request to read a Bulk-only CBW */ | 2136 | /* Queue a request to read a Bulk-only CBW */ |
2136 | set_bulk_out_req_length(common, bh, USB_BULK_CB_WRAP_LEN); | 2137 | set_bulk_out_req_length(common, bh, USB_BULK_CB_WRAP_LEN); |
2137 | bh->outreq->short_not_ok = 1; | 2138 | bh->outreq->short_not_ok = 1; |
2138 | START_TRANSFER_OR(common, bulk_out, bh->outreq, | 2139 | START_TRANSFER_OR(common, bulk_out, bh->outreq, |
2139 | &bh->outreq_busy, &bh->state) | 2140 | &bh->outreq_busy, &bh->state) |
2140 | /* Don't know what to do if common->fsg is NULL */ | 2141 | /* Don't know what to do if common->fsg is NULL */ |
2141 | return -EIO; | 2142 | return -EIO; |
2142 | 2143 | ||
2143 | /* We will drain the buffer in software, which means we | 2144 | /* We will drain the buffer in software, which means we |
2144 | * can reuse it for the next filling. No need to advance | 2145 | * can reuse it for the next filling. No need to advance |
2145 | * next_buffhd_to_fill. */ | 2146 | * next_buffhd_to_fill. */ |
2146 | 2147 | ||
2147 | /* Wait for the CBW to arrive */ | 2148 | /* Wait for the CBW to arrive */ |
2148 | while (bh->state != BUF_STATE_FULL) { | 2149 | while (bh->state != BUF_STATE_FULL) { |
2149 | rc = sleep_thread(common); | 2150 | rc = sleep_thread(common); |
2150 | if (rc) | 2151 | if (rc) |
2151 | return rc; | 2152 | return rc; |
2152 | } | 2153 | } |
2153 | 2154 | ||
2154 | rc = fsg_is_set(common) ? received_cbw(common->fsg, bh) : -EIO; | 2155 | rc = fsg_is_set(common) ? received_cbw(common->fsg, bh) : -EIO; |
2155 | bh->state = BUF_STATE_EMPTY; | 2156 | bh->state = BUF_STATE_EMPTY; |
2156 | 2157 | ||
2157 | return rc; | 2158 | return rc; |
2158 | } | 2159 | } |
2159 | 2160 | ||
2160 | 2161 | ||
2161 | /*-------------------------------------------------------------------------*/ | 2162 | /*-------------------------------------------------------------------------*/ |
2162 | 2163 | ||
2163 | static int enable_endpoint(struct fsg_common *common, struct usb_ep *ep, | 2164 | static int enable_endpoint(struct fsg_common *common, struct usb_ep *ep, |
2164 | const struct usb_endpoint_descriptor *d) | 2165 | const struct usb_endpoint_descriptor *d) |
2165 | { | 2166 | { |
2166 | int rc; | 2167 | int rc; |
2167 | 2168 | ||
2168 | ep->driver_data = common; | 2169 | ep->driver_data = common; |
2169 | rc = usb_ep_enable(ep, d); | 2170 | rc = usb_ep_enable(ep, d); |
2170 | if (rc) | 2171 | if (rc) |
2171 | ERROR(common, "can't enable %s, result %d\n", ep->name, rc); | 2172 | ERROR(common, "can't enable %s, result %d\n", ep->name, rc); |
2172 | return rc; | 2173 | return rc; |
2173 | } | 2174 | } |
2174 | 2175 | ||
2175 | static int alloc_request(struct fsg_common *common, struct usb_ep *ep, | 2176 | static int alloc_request(struct fsg_common *common, struct usb_ep *ep, |
2176 | struct usb_request **preq) | 2177 | struct usb_request **preq) |
2177 | { | 2178 | { |
2178 | *preq = usb_ep_alloc_request(ep, GFP_ATOMIC); | 2179 | *preq = usb_ep_alloc_request(ep, GFP_ATOMIC); |
2179 | if (*preq) | 2180 | if (*preq) |
2180 | return 0; | 2181 | return 0; |
2181 | ERROR(common, "can't allocate request for %s\n", ep->name); | 2182 | ERROR(common, "can't allocate request for %s\n", ep->name); |
2182 | return -ENOMEM; | 2183 | return -ENOMEM; |
2183 | } | 2184 | } |
2184 | 2185 | ||
2185 | /* Reset interface setting and re-init endpoint state (toggle etc). */ | 2186 | /* Reset interface setting and re-init endpoint state (toggle etc). */ |
2186 | static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg) | 2187 | static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg) |
2187 | { | 2188 | { |
2188 | const struct usb_endpoint_descriptor *d; | 2189 | const struct usb_endpoint_descriptor *d; |
2189 | struct fsg_dev *fsg; | 2190 | struct fsg_dev *fsg; |
2190 | int i, rc = 0; | 2191 | int i, rc = 0; |
2191 | 2192 | ||
2192 | if (common->running) | 2193 | if (common->running) |
2193 | DBG(common, "reset interface\n"); | 2194 | DBG(common, "reset interface\n"); |
2194 | 2195 | ||
2195 | reset: | 2196 | reset: |
2196 | /* Deallocate the requests */ | 2197 | /* Deallocate the requests */ |
2197 | if (common->fsg) { | 2198 | if (common->fsg) { |
2198 | fsg = common->fsg; | 2199 | fsg = common->fsg; |
2199 | 2200 | ||
2200 | for (i = 0; i < FSG_NUM_BUFFERS; ++i) { | 2201 | for (i = 0; i < FSG_NUM_BUFFERS; ++i) { |
2201 | struct fsg_buffhd *bh = &common->buffhds[i]; | 2202 | struct fsg_buffhd *bh = &common->buffhds[i]; |
2202 | 2203 | ||
2203 | if (bh->inreq) { | 2204 | if (bh->inreq) { |
2204 | usb_ep_free_request(fsg->bulk_in, bh->inreq); | 2205 | usb_ep_free_request(fsg->bulk_in, bh->inreq); |
2205 | bh->inreq = NULL; | 2206 | bh->inreq = NULL; |
2206 | } | 2207 | } |
2207 | if (bh->outreq) { | 2208 | if (bh->outreq) { |
2208 | usb_ep_free_request(fsg->bulk_out, bh->outreq); | 2209 | usb_ep_free_request(fsg->bulk_out, bh->outreq); |
2209 | bh->outreq = NULL; | 2210 | bh->outreq = NULL; |
2210 | } | 2211 | } |
2211 | } | 2212 | } |
2212 | 2213 | ||
2213 | /* Disable the endpoints */ | 2214 | /* Disable the endpoints */ |
2214 | if (fsg->bulk_in_enabled) { | 2215 | if (fsg->bulk_in_enabled) { |
2215 | usb_ep_disable(fsg->bulk_in); | 2216 | usb_ep_disable(fsg->bulk_in); |
2216 | fsg->bulk_in_enabled = 0; | 2217 | fsg->bulk_in_enabled = 0; |
2217 | } | 2218 | } |
2218 | if (fsg->bulk_out_enabled) { | 2219 | if (fsg->bulk_out_enabled) { |
2219 | usb_ep_disable(fsg->bulk_out); | 2220 | usb_ep_disable(fsg->bulk_out); |
2220 | fsg->bulk_out_enabled = 0; | 2221 | fsg->bulk_out_enabled = 0; |
2221 | } | 2222 | } |
2222 | 2223 | ||
2223 | common->fsg = NULL; | 2224 | common->fsg = NULL; |
2224 | /* wake_up(&common->fsg_wait); */ | 2225 | /* wake_up(&common->fsg_wait); */ |
2225 | } | 2226 | } |
2226 | 2227 | ||
2227 | common->running = 0; | 2228 | common->running = 0; |
2228 | if (!new_fsg || rc) | 2229 | if (!new_fsg || rc) |
2229 | return rc; | 2230 | return rc; |
2230 | 2231 | ||
2231 | common->fsg = new_fsg; | 2232 | common->fsg = new_fsg; |
2232 | fsg = common->fsg; | 2233 | fsg = common->fsg; |
2233 | 2234 | ||
2234 | /* Enable the endpoints */ | 2235 | /* Enable the endpoints */ |
2235 | d = fsg_ep_desc(common->gadget, | 2236 | d = fsg_ep_desc(common->gadget, |
2236 | &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc); | 2237 | &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc); |
2237 | rc = enable_endpoint(common, fsg->bulk_in, d); | 2238 | rc = enable_endpoint(common, fsg->bulk_in, d); |
2238 | if (rc) | 2239 | if (rc) |
2239 | goto reset; | 2240 | goto reset; |
2240 | fsg->bulk_in_enabled = 1; | 2241 | fsg->bulk_in_enabled = 1; |
2241 | 2242 | ||
2242 | d = fsg_ep_desc(common->gadget, | 2243 | d = fsg_ep_desc(common->gadget, |
2243 | &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc); | 2244 | &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc); |
2244 | rc = enable_endpoint(common, fsg->bulk_out, d); | 2245 | rc = enable_endpoint(common, fsg->bulk_out, d); |
2245 | if (rc) | 2246 | if (rc) |
2246 | goto reset; | 2247 | goto reset; |
2247 | fsg->bulk_out_enabled = 1; | 2248 | fsg->bulk_out_enabled = 1; |
2248 | common->bulk_out_maxpacket = | 2249 | common->bulk_out_maxpacket = |
2249 | le16_to_cpu(get_unaligned(&d->wMaxPacketSize)); | 2250 | le16_to_cpu(get_unaligned(&d->wMaxPacketSize)); |
2250 | clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); | 2251 | clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); |
2251 | 2252 | ||
2252 | /* Allocate the requests */ | 2253 | /* Allocate the requests */ |
2253 | for (i = 0; i < FSG_NUM_BUFFERS; ++i) { | 2254 | for (i = 0; i < FSG_NUM_BUFFERS; ++i) { |
2254 | struct fsg_buffhd *bh = &common->buffhds[i]; | 2255 | struct fsg_buffhd *bh = &common->buffhds[i]; |
2255 | 2256 | ||
2256 | rc = alloc_request(common, fsg->bulk_in, &bh->inreq); | 2257 | rc = alloc_request(common, fsg->bulk_in, &bh->inreq); |
2257 | if (rc) | 2258 | if (rc) |
2258 | goto reset; | 2259 | goto reset; |
2259 | rc = alloc_request(common, fsg->bulk_out, &bh->outreq); | 2260 | rc = alloc_request(common, fsg->bulk_out, &bh->outreq); |
2260 | if (rc) | 2261 | if (rc) |
2261 | goto reset; | 2262 | goto reset; |
2262 | bh->inreq->buf = bh->outreq->buf = bh->buf; | 2263 | bh->inreq->buf = bh->outreq->buf = bh->buf; |
2263 | bh->inreq->context = bh->outreq->context = bh; | 2264 | bh->inreq->context = bh->outreq->context = bh; |
2264 | bh->inreq->complete = bulk_in_complete; | 2265 | bh->inreq->complete = bulk_in_complete; |
2265 | bh->outreq->complete = bulk_out_complete; | 2266 | bh->outreq->complete = bulk_out_complete; |
2266 | } | 2267 | } |
2267 | 2268 | ||
2268 | common->running = 1; | 2269 | common->running = 1; |
2269 | 2270 | ||
2270 | return rc; | 2271 | return rc; |
2271 | } | 2272 | } |
2272 | 2273 | ||
2273 | 2274 | ||
2274 | /****************************** ALT CONFIGS ******************************/ | 2275 | /****************************** ALT CONFIGS ******************************/ |
2275 | 2276 | ||
2276 | 2277 | ||
2277 | static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) | 2278 | static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) |
2278 | { | 2279 | { |
2279 | struct fsg_dev *fsg = fsg_from_func(f); | 2280 | struct fsg_dev *fsg = fsg_from_func(f); |
2280 | fsg->common->new_fsg = fsg; | 2281 | fsg->common->new_fsg = fsg; |
2281 | raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); | 2282 | raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); |
2282 | return 0; | 2283 | return 0; |
2283 | } | 2284 | } |
2284 | 2285 | ||
2285 | static void fsg_disable(struct usb_function *f) | 2286 | static void fsg_disable(struct usb_function *f) |
2286 | { | 2287 | { |
2287 | struct fsg_dev *fsg = fsg_from_func(f); | 2288 | struct fsg_dev *fsg = fsg_from_func(f); |
2288 | fsg->common->new_fsg = NULL; | 2289 | fsg->common->new_fsg = NULL; |
2289 | raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); | 2290 | raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); |
2290 | } | 2291 | } |
2291 | 2292 | ||
2292 | /*-------------------------------------------------------------------------*/ | 2293 | /*-------------------------------------------------------------------------*/ |
2293 | 2294 | ||
2294 | static void handle_exception(struct fsg_common *common) | 2295 | static void handle_exception(struct fsg_common *common) |
2295 | { | 2296 | { |
2296 | int i; | 2297 | int i; |
2297 | struct fsg_buffhd *bh; | 2298 | struct fsg_buffhd *bh; |
2298 | enum fsg_state old_state; | 2299 | enum fsg_state old_state; |
2299 | struct fsg_lun *curlun; | 2300 | struct fsg_lun *curlun; |
2300 | unsigned int exception_req_tag; | 2301 | unsigned int exception_req_tag; |
2301 | 2302 | ||
2302 | /* Cancel all the pending transfers */ | 2303 | /* Cancel all the pending transfers */ |
2303 | if (common->fsg) { | 2304 | if (common->fsg) { |
2304 | for (i = 0; i < FSG_NUM_BUFFERS; ++i) { | 2305 | for (i = 0; i < FSG_NUM_BUFFERS; ++i) { |
2305 | bh = &common->buffhds[i]; | 2306 | bh = &common->buffhds[i]; |
2306 | if (bh->inreq_busy) | 2307 | if (bh->inreq_busy) |
2307 | usb_ep_dequeue(common->fsg->bulk_in, bh->inreq); | 2308 | usb_ep_dequeue(common->fsg->bulk_in, bh->inreq); |
2308 | if (bh->outreq_busy) | 2309 | if (bh->outreq_busy) |
2309 | usb_ep_dequeue(common->fsg->bulk_out, | 2310 | usb_ep_dequeue(common->fsg->bulk_out, |
2310 | bh->outreq); | 2311 | bh->outreq); |
2311 | } | 2312 | } |
2312 | 2313 | ||
2313 | /* Wait until everything is idle */ | 2314 | /* Wait until everything is idle */ |
2314 | for (;;) { | 2315 | for (;;) { |
2315 | int num_active = 0; | 2316 | int num_active = 0; |
2316 | for (i = 0; i < FSG_NUM_BUFFERS; ++i) { | 2317 | for (i = 0; i < FSG_NUM_BUFFERS; ++i) { |
2317 | bh = &common->buffhds[i]; | 2318 | bh = &common->buffhds[i]; |
2318 | num_active += bh->inreq_busy + bh->outreq_busy; | 2319 | num_active += bh->inreq_busy + bh->outreq_busy; |
2319 | } | 2320 | } |
2320 | if (num_active == 0) | 2321 | if (num_active == 0) |
2321 | break; | 2322 | break; |
2322 | if (sleep_thread(common)) | 2323 | if (sleep_thread(common)) |
2323 | return; | 2324 | return; |
2324 | } | 2325 | } |
2325 | 2326 | ||
2326 | /* Clear out the controller's fifos */ | 2327 | /* Clear out the controller's fifos */ |
2327 | if (common->fsg->bulk_in_enabled) | 2328 | if (common->fsg->bulk_in_enabled) |
2328 | usb_ep_fifo_flush(common->fsg->bulk_in); | 2329 | usb_ep_fifo_flush(common->fsg->bulk_in); |
2329 | if (common->fsg->bulk_out_enabled) | 2330 | if (common->fsg->bulk_out_enabled) |
2330 | usb_ep_fifo_flush(common->fsg->bulk_out); | 2331 | usb_ep_fifo_flush(common->fsg->bulk_out); |
2331 | } | 2332 | } |
2332 | 2333 | ||
2333 | /* Reset the I/O buffer states and pointers, the SCSI | 2334 | /* Reset the I/O buffer states and pointers, the SCSI |
2334 | * state, and the exception. Then invoke the handler. */ | 2335 | * state, and the exception. Then invoke the handler. */ |
2335 | 2336 | ||
2336 | for (i = 0; i < FSG_NUM_BUFFERS; ++i) { | 2337 | for (i = 0; i < FSG_NUM_BUFFERS; ++i) { |
2337 | bh = &common->buffhds[i]; | 2338 | bh = &common->buffhds[i]; |
2338 | bh->state = BUF_STATE_EMPTY; | 2339 | bh->state = BUF_STATE_EMPTY; |
2339 | } | 2340 | } |
2340 | common->next_buffhd_to_fill = &common->buffhds[0]; | 2341 | common->next_buffhd_to_fill = &common->buffhds[0]; |
2341 | common->next_buffhd_to_drain = &common->buffhds[0]; | 2342 | common->next_buffhd_to_drain = &common->buffhds[0]; |
2342 | exception_req_tag = common->exception_req_tag; | 2343 | exception_req_tag = common->exception_req_tag; |
2343 | old_state = common->state; | 2344 | old_state = common->state; |
2344 | 2345 | ||
2345 | if (old_state == FSG_STATE_ABORT_BULK_OUT) | 2346 | if (old_state == FSG_STATE_ABORT_BULK_OUT) |
2346 | common->state = FSG_STATE_STATUS_PHASE; | 2347 | common->state = FSG_STATE_STATUS_PHASE; |
2347 | else { | 2348 | else { |
2348 | for (i = 0; i < common->nluns; ++i) { | 2349 | for (i = 0; i < common->nluns; ++i) { |
2349 | curlun = &common->luns[i]; | 2350 | curlun = &common->luns[i]; |
2350 | curlun->sense_data = SS_NO_SENSE; | 2351 | curlun->sense_data = SS_NO_SENSE; |
2351 | curlun->info_valid = 0; | 2352 | curlun->info_valid = 0; |
2352 | } | 2353 | } |
2353 | common->state = FSG_STATE_IDLE; | 2354 | common->state = FSG_STATE_IDLE; |
2354 | } | 2355 | } |
2355 | 2356 | ||
2356 | /* Carry out any extra actions required for the exception */ | 2357 | /* Carry out any extra actions required for the exception */ |
2357 | switch (old_state) { | 2358 | switch (old_state) { |
2358 | case FSG_STATE_ABORT_BULK_OUT: | 2359 | case FSG_STATE_ABORT_BULK_OUT: |
2359 | send_status(common); | 2360 | send_status(common); |
2360 | 2361 | ||
2361 | if (common->state == FSG_STATE_STATUS_PHASE) | 2362 | if (common->state == FSG_STATE_STATUS_PHASE) |
2362 | common->state = FSG_STATE_IDLE; | 2363 | common->state = FSG_STATE_IDLE; |
2363 | break; | 2364 | break; |
2364 | 2365 | ||
2365 | case FSG_STATE_RESET: | 2366 | case FSG_STATE_RESET: |
2366 | /* In case we were forced against our will to halt a | 2367 | /* In case we were forced against our will to halt a |
2367 | * bulk endpoint, clear the halt now. (The SuperH UDC | 2368 | * bulk endpoint, clear the halt now. (The SuperH UDC |
2368 | * requires this.) */ | 2369 | * requires this.) */ |
2369 | if (!fsg_is_set(common)) | 2370 | if (!fsg_is_set(common)) |
2370 | break; | 2371 | break; |
2371 | if (test_and_clear_bit(IGNORE_BULK_OUT, | 2372 | if (test_and_clear_bit(IGNORE_BULK_OUT, |
2372 | &common->fsg->atomic_bitflags)) | 2373 | &common->fsg->atomic_bitflags)) |
2373 | usb_ep_clear_halt(common->fsg->bulk_in); | 2374 | usb_ep_clear_halt(common->fsg->bulk_in); |
2374 | 2375 | ||
2375 | if (common->ep0_req_tag == exception_req_tag) | 2376 | if (common->ep0_req_tag == exception_req_tag) |
2376 | ep0_queue(common); /* Complete the status stage */ | 2377 | ep0_queue(common); /* Complete the status stage */ |
2377 | 2378 | ||
2378 | break; | 2379 | break; |
2379 | 2380 | ||
2380 | case FSG_STATE_CONFIG_CHANGE: | 2381 | case FSG_STATE_CONFIG_CHANGE: |
2381 | do_set_interface(common, common->new_fsg); | 2382 | do_set_interface(common, common->new_fsg); |
2382 | break; | 2383 | break; |
2383 | 2384 | ||
2384 | case FSG_STATE_EXIT: | 2385 | case FSG_STATE_EXIT: |
2385 | case FSG_STATE_TERMINATED: | 2386 | case FSG_STATE_TERMINATED: |
2386 | do_set_interface(common, NULL); /* Free resources */ | 2387 | do_set_interface(common, NULL); /* Free resources */ |
2387 | common->state = FSG_STATE_TERMINATED; /* Stop the thread */ | 2388 | common->state = FSG_STATE_TERMINATED; /* Stop the thread */ |
2388 | break; | 2389 | break; |
2389 | 2390 | ||
2390 | case FSG_STATE_INTERFACE_CHANGE: | 2391 | case FSG_STATE_INTERFACE_CHANGE: |
2391 | case FSG_STATE_DISCONNECT: | 2392 | case FSG_STATE_DISCONNECT: |
2392 | case FSG_STATE_COMMAND_PHASE: | 2393 | case FSG_STATE_COMMAND_PHASE: |
2393 | case FSG_STATE_DATA_PHASE: | 2394 | case FSG_STATE_DATA_PHASE: |
2394 | case FSG_STATE_STATUS_PHASE: | 2395 | case FSG_STATE_STATUS_PHASE: |
2395 | case FSG_STATE_IDLE: | 2396 | case FSG_STATE_IDLE: |
2396 | break; | 2397 | break; |
2397 | } | 2398 | } |
2398 | } | 2399 | } |
2399 | 2400 | ||
2400 | /*-------------------------------------------------------------------------*/ | 2401 | /*-------------------------------------------------------------------------*/ |
2401 | 2402 | ||
2402 | int fsg_main_thread(void *common_) | 2403 | int fsg_main_thread(void *common_) |
2403 | { | 2404 | { |
2404 | int ret; | 2405 | int ret; |
2405 | struct fsg_common *common = the_fsg_common; | 2406 | struct fsg_common *common = the_fsg_common; |
2406 | /* The main loop */ | 2407 | /* The main loop */ |
2407 | do { | 2408 | do { |
2408 | if (exception_in_progress(common)) { | 2409 | if (exception_in_progress(common)) { |
2409 | handle_exception(common); | 2410 | handle_exception(common); |
2410 | continue; | 2411 | continue; |
2411 | } | 2412 | } |
2412 | 2413 | ||
2413 | if (!common->running) { | 2414 | if (!common->running) { |
2414 | ret = sleep_thread(common); | 2415 | ret = sleep_thread(common); |
2415 | if (ret) | 2416 | if (ret) |
2416 | return ret; | 2417 | return ret; |
2417 | 2418 | ||
2418 | continue; | 2419 | continue; |
2419 | } | 2420 | } |
2420 | 2421 | ||
2421 | ret = get_next_command(common); | 2422 | ret = get_next_command(common); |
2422 | if (ret) | 2423 | if (ret) |
2423 | return ret; | 2424 | return ret; |
2424 | 2425 | ||
2425 | if (!exception_in_progress(common)) | 2426 | if (!exception_in_progress(common)) |
2426 | common->state = FSG_STATE_DATA_PHASE; | 2427 | common->state = FSG_STATE_DATA_PHASE; |
2427 | 2428 | ||
2428 | if (do_scsi_command(common) || finish_reply(common)) | 2429 | if (do_scsi_command(common) || finish_reply(common)) |
2429 | continue; | 2430 | continue; |
2430 | 2431 | ||
2431 | if (!exception_in_progress(common)) | 2432 | if (!exception_in_progress(common)) |
2432 | common->state = FSG_STATE_STATUS_PHASE; | 2433 | common->state = FSG_STATE_STATUS_PHASE; |
2433 | 2434 | ||
2434 | if (send_status(common)) | 2435 | if (send_status(common)) |
2435 | continue; | 2436 | continue; |
2436 | 2437 | ||
2437 | if (!exception_in_progress(common)) | 2438 | if (!exception_in_progress(common)) |
2438 | common->state = FSG_STATE_IDLE; | 2439 | common->state = FSG_STATE_IDLE; |
2439 | } while (0); | 2440 | } while (0); |
2440 | 2441 | ||
2441 | common->thread_task = NULL; | 2442 | common->thread_task = NULL; |
2442 | 2443 | ||
2443 | return 0; | 2444 | return 0; |
2444 | } | 2445 | } |
2445 | 2446 | ||
2446 | static void fsg_common_release(struct kref *ref); | 2447 | static void fsg_common_release(struct kref *ref); |
2447 | 2448 | ||
2448 | static struct fsg_common *fsg_common_init(struct fsg_common *common, | 2449 | static struct fsg_common *fsg_common_init(struct fsg_common *common, |
2449 | struct usb_composite_dev *cdev) | 2450 | struct usb_composite_dev *cdev) |
2450 | { | 2451 | { |
2451 | struct usb_gadget *gadget = cdev->gadget; | 2452 | struct usb_gadget *gadget = cdev->gadget; |
2452 | struct fsg_buffhd *bh; | 2453 | struct fsg_buffhd *bh; |
2453 | struct fsg_lun *curlun; | 2454 | struct fsg_lun *curlun; |
2454 | int nluns, i, rc; | 2455 | int nluns, i, rc; |
2455 | 2456 | ||
2456 | /* Find out how many LUNs there should be */ | 2457 | /* Find out how many LUNs there should be */ |
2457 | nluns = 1; | 2458 | nluns = 1; |
2458 | if (nluns < 1 || nluns > FSG_MAX_LUNS) { | 2459 | if (nluns < 1 || nluns > FSG_MAX_LUNS) { |
2459 | printf("invalid number of LUNs: %u\n", nluns); | 2460 | printf("invalid number of LUNs: %u\n", nluns); |
2460 | return ERR_PTR(-EINVAL); | 2461 | return ERR_PTR(-EINVAL); |
2461 | } | 2462 | } |
2462 | 2463 | ||
2463 | /* Allocate? */ | 2464 | /* Allocate? */ |
2464 | if (!common) { | 2465 | if (!common) { |
2465 | common = calloc(sizeof(*common), 1); | 2466 | common = calloc(sizeof(*common), 1); |
2466 | if (!common) | 2467 | if (!common) |
2467 | return ERR_PTR(-ENOMEM); | 2468 | return ERR_PTR(-ENOMEM); |
2468 | common->free_storage_on_release = 1; | 2469 | common->free_storage_on_release = 1; |
2469 | } else { | 2470 | } else { |
2470 | memset(common, 0, sizeof(*common)); | 2471 | memset(common, 0, sizeof(*common)); |
2471 | common->free_storage_on_release = 0; | 2472 | common->free_storage_on_release = 0; |
2472 | } | 2473 | } |
2473 | 2474 | ||
2474 | common->ops = NULL; | 2475 | common->ops = NULL; |
2475 | common->private_data = NULL; | 2476 | common->private_data = NULL; |
2476 | 2477 | ||
2477 | common->gadget = gadget; | 2478 | common->gadget = gadget; |
2478 | common->ep0 = gadget->ep0; | 2479 | common->ep0 = gadget->ep0; |
2479 | common->ep0req = cdev->req; | 2480 | common->ep0req = cdev->req; |
2480 | 2481 | ||
2481 | /* Maybe allocate device-global string IDs, and patch descriptors */ | 2482 | /* Maybe allocate device-global string IDs, and patch descriptors */ |
2482 | if (fsg_strings[FSG_STRING_INTERFACE].id == 0) { | 2483 | if (fsg_strings[FSG_STRING_INTERFACE].id == 0) { |
2483 | rc = usb_string_id(cdev); | 2484 | rc = usb_string_id(cdev); |
2484 | if (unlikely(rc < 0)) | 2485 | if (unlikely(rc < 0)) |
2485 | goto error_release; | 2486 | goto error_release; |
2486 | fsg_strings[FSG_STRING_INTERFACE].id = rc; | 2487 | fsg_strings[FSG_STRING_INTERFACE].id = rc; |
2487 | fsg_intf_desc.iInterface = rc; | 2488 | fsg_intf_desc.iInterface = rc; |
2488 | } | 2489 | } |
2489 | 2490 | ||
2490 | /* Create the LUNs, open their backing files, and register the | 2491 | /* Create the LUNs, open their backing files, and register the |
2491 | * LUN devices in sysfs. */ | 2492 | * LUN devices in sysfs. */ |
2492 | curlun = calloc(nluns, sizeof *curlun); | 2493 | curlun = calloc(nluns, sizeof *curlun); |
2493 | if (!curlun) { | 2494 | if (!curlun) { |
2494 | rc = -ENOMEM; | 2495 | rc = -ENOMEM; |
2495 | goto error_release; | 2496 | goto error_release; |
2496 | } | 2497 | } |
2497 | common->nluns = nluns; | 2498 | common->nluns = nluns; |
2498 | 2499 | ||
2499 | for (i = 0; i < nluns; i++) { | 2500 | for (i = 0; i < nluns; i++) { |
2500 | common->luns[i].removable = 1; | 2501 | common->luns[i].removable = 1; |
2501 | 2502 | ||
2502 | rc = fsg_lun_open(&common->luns[i], ""); | 2503 | rc = fsg_lun_open(&common->luns[i], ""); |
2503 | if (rc) | 2504 | if (rc) |
2504 | goto error_luns; | 2505 | goto error_luns; |
2505 | } | 2506 | } |
2506 | common->lun = 0; | 2507 | common->lun = 0; |
2507 | 2508 | ||
2508 | /* Data buffers cyclic list */ | 2509 | /* Data buffers cyclic list */ |
2509 | bh = common->buffhds; | 2510 | bh = common->buffhds; |
2510 | 2511 | ||
2511 | i = FSG_NUM_BUFFERS; | 2512 | i = FSG_NUM_BUFFERS; |
2512 | goto buffhds_first_it; | 2513 | goto buffhds_first_it; |
2513 | do { | 2514 | do { |
2514 | bh->next = bh + 1; | 2515 | bh->next = bh + 1; |
2515 | ++bh; | 2516 | ++bh; |
2516 | buffhds_first_it: | 2517 | buffhds_first_it: |
2517 | bh->inreq_busy = 0; | 2518 | bh->inreq_busy = 0; |
2518 | bh->outreq_busy = 0; | 2519 | bh->outreq_busy = 0; |
2519 | bh->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, FSG_BUFLEN); | 2520 | bh->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, FSG_BUFLEN); |
2520 | if (unlikely(!bh->buf)) { | 2521 | if (unlikely(!bh->buf)) { |
2521 | rc = -ENOMEM; | 2522 | rc = -ENOMEM; |
2522 | goto error_release; | 2523 | goto error_release; |
2523 | } | 2524 | } |
2524 | } while (--i); | 2525 | } while (--i); |
2525 | bh->next = common->buffhds; | 2526 | bh->next = common->buffhds; |
2526 | 2527 | ||
2527 | snprintf(common->inquiry_string, sizeof common->inquiry_string, | 2528 | snprintf(common->inquiry_string, sizeof common->inquiry_string, |
2528 | "%-8s%-16s%04x", | 2529 | "%-8s%-16s%04x", |
2529 | "Linux ", | 2530 | "Linux ", |
2530 | "File-Store Gadget", | 2531 | "File-Store Gadget", |
2531 | 0xffff); | 2532 | 0xffff); |
2532 | 2533 | ||
2533 | /* Some peripheral controllers are known not to be able to | 2534 | /* Some peripheral controllers are known not to be able to |
2534 | * halt bulk endpoints correctly. If one of them is present, | 2535 | * halt bulk endpoints correctly. If one of them is present, |
2535 | * disable stalls. | 2536 | * disable stalls. |
2536 | */ | 2537 | */ |
2537 | 2538 | ||
2538 | /* Tell the thread to start working */ | 2539 | /* Tell the thread to start working */ |
2539 | common->thread_task = | 2540 | common->thread_task = |
2540 | kthread_create(fsg_main_thread, common, | 2541 | kthread_create(fsg_main_thread, common, |
2541 | OR(cfg->thread_name, "file-storage")); | 2542 | OR(cfg->thread_name, "file-storage")); |
2542 | if (IS_ERR(common->thread_task)) { | 2543 | if (IS_ERR(common->thread_task)) { |
2543 | rc = PTR_ERR(common->thread_task); | 2544 | rc = PTR_ERR(common->thread_task); |
2544 | goto error_release; | 2545 | goto error_release; |
2545 | } | 2546 | } |
2546 | 2547 | ||
2547 | #undef OR | 2548 | #undef OR |
2548 | /* Information */ | 2549 | /* Information */ |
2549 | INFO(common, FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n"); | 2550 | INFO(common, FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n"); |
2550 | INFO(common, "Number of LUNs=%d\n", common->nluns); | 2551 | INFO(common, "Number of LUNs=%d\n", common->nluns); |
2551 | 2552 | ||
2552 | return common; | 2553 | return common; |
2553 | 2554 | ||
2554 | error_luns: | 2555 | error_luns: |
2555 | common->nluns = i + 1; | 2556 | common->nluns = i + 1; |
2556 | error_release: | 2557 | error_release: |
2557 | common->state = FSG_STATE_TERMINATED; /* The thread is dead */ | 2558 | common->state = FSG_STATE_TERMINATED; /* The thread is dead */ |
2558 | /* Call fsg_common_release() directly, ref might be not | 2559 | /* Call fsg_common_release() directly, ref might be not |
2559 | * initialised */ | 2560 | * initialised */ |
2560 | fsg_common_release(&common->ref); | 2561 | fsg_common_release(&common->ref); |
2561 | return ERR_PTR(rc); | 2562 | return ERR_PTR(rc); |
2562 | } | 2563 | } |
2563 | 2564 | ||
2564 | static void fsg_common_release(struct kref *ref) | 2565 | static void fsg_common_release(struct kref *ref) |
2565 | { | 2566 | { |
2566 | struct fsg_common *common = container_of(ref, struct fsg_common, ref); | 2567 | struct fsg_common *common = container_of(ref, struct fsg_common, ref); |
2567 | 2568 | ||
2568 | /* If the thread isn't already dead, tell it to exit now */ | 2569 | /* If the thread isn't already dead, tell it to exit now */ |
2569 | if (common->state != FSG_STATE_TERMINATED) { | 2570 | if (common->state != FSG_STATE_TERMINATED) { |
2570 | raise_exception(common, FSG_STATE_EXIT); | 2571 | raise_exception(common, FSG_STATE_EXIT); |
2571 | wait_for_completion(&common->thread_notifier); | 2572 | wait_for_completion(&common->thread_notifier); |
2572 | } | 2573 | } |
2573 | 2574 | ||
2574 | if (likely(common->luns)) { | 2575 | if (likely(common->luns)) { |
2575 | struct fsg_lun *lun = common->luns; | 2576 | struct fsg_lun *lun = common->luns; |
2576 | unsigned i = common->nluns; | 2577 | unsigned i = common->nluns; |
2577 | 2578 | ||
2578 | /* In error recovery common->nluns may be zero. */ | 2579 | /* In error recovery common->nluns may be zero. */ |
2579 | for (; i; --i, ++lun) | 2580 | for (; i; --i, ++lun) |
2580 | fsg_lun_close(lun); | 2581 | fsg_lun_close(lun); |
2581 | 2582 | ||
2582 | kfree(common->luns); | 2583 | kfree(common->luns); |
2583 | } | 2584 | } |
2584 | 2585 | ||
2585 | { | 2586 | { |
2586 | struct fsg_buffhd *bh = common->buffhds; | 2587 | struct fsg_buffhd *bh = common->buffhds; |
2587 | unsigned i = FSG_NUM_BUFFERS; | 2588 | unsigned i = FSG_NUM_BUFFERS; |
2588 | do { | 2589 | do { |
2589 | kfree(bh->buf); | 2590 | kfree(bh->buf); |
2590 | } while (++bh, --i); | 2591 | } while (++bh, --i); |
2591 | } | 2592 | } |
2592 | 2593 | ||
2593 | if (common->free_storage_on_release) | 2594 | if (common->free_storage_on_release) |
2594 | kfree(common); | 2595 | kfree(common); |
2595 | } | 2596 | } |
2596 | 2597 | ||
2597 | 2598 | ||
2598 | /*-------------------------------------------------------------------------*/ | 2599 | /*-------------------------------------------------------------------------*/ |
2599 | 2600 | ||
2600 | /** | 2601 | /** |
2601 | * usb_copy_descriptors - copy a vector of USB descriptors | 2602 | * usb_copy_descriptors - copy a vector of USB descriptors |
2602 | * @src: null-terminated vector to copy | 2603 | * @src: null-terminated vector to copy |
2603 | * Context: initialization code, which may sleep | 2604 | * Context: initialization code, which may sleep |
2604 | * | 2605 | * |
2605 | * This makes a copy of a vector of USB descriptors. Its primary use | 2606 | * This makes a copy of a vector of USB descriptors. Its primary use |
2606 | * is to support usb_function objects which can have multiple copies, | 2607 | * is to support usb_function objects which can have multiple copies, |
2607 | * each needing different descriptors. Functions may have static | 2608 | * each needing different descriptors. Functions may have static |
2608 | * tables of descriptors, which are used as templates and customized | 2609 | * tables of descriptors, which are used as templates and customized |
2609 | * with identifiers (for interfaces, strings, endpoints, and more) | 2610 | * with identifiers (for interfaces, strings, endpoints, and more) |
2610 | * as needed by a given function instance. | 2611 | * as needed by a given function instance. |
2611 | */ | 2612 | */ |
2612 | struct usb_descriptor_header ** | 2613 | struct usb_descriptor_header ** |
2613 | usb_copy_descriptors(struct usb_descriptor_header **src) | 2614 | usb_copy_descriptors(struct usb_descriptor_header **src) |
2614 | { | 2615 | { |
2615 | struct usb_descriptor_header **tmp; | 2616 | struct usb_descriptor_header **tmp; |
2616 | unsigned bytes; | 2617 | unsigned bytes; |
2617 | unsigned n_desc; | 2618 | unsigned n_desc; |
2618 | void *mem; | 2619 | void *mem; |
2619 | struct usb_descriptor_header **ret; | 2620 | struct usb_descriptor_header **ret; |
2620 | 2621 | ||
2621 | /* count descriptors and their sizes; then add vector size */ | 2622 | /* count descriptors and their sizes; then add vector size */ |
2622 | for (bytes = 0, n_desc = 0, tmp = src; *tmp; tmp++, n_desc++) | 2623 | for (bytes = 0, n_desc = 0, tmp = src; *tmp; tmp++, n_desc++) |
2623 | bytes += (*tmp)->bLength; | 2624 | bytes += (*tmp)->bLength; |
2624 | bytes += (n_desc + 1) * sizeof(*tmp); | 2625 | bytes += (n_desc + 1) * sizeof(*tmp); |
2625 | 2626 | ||
2626 | mem = memalign(CONFIG_SYS_CACHELINE_SIZE, bytes); | 2627 | mem = memalign(CONFIG_SYS_CACHELINE_SIZE, bytes); |
2627 | if (!mem) | 2628 | if (!mem) |
2628 | return NULL; | 2629 | return NULL; |
2629 | 2630 | ||
2630 | /* fill in pointers starting at "tmp", | 2631 | /* fill in pointers starting at "tmp", |
2631 | * to descriptors copied starting at "mem"; | 2632 | * to descriptors copied starting at "mem"; |
2632 | * and return "ret" | 2633 | * and return "ret" |
2633 | */ | 2634 | */ |
2634 | tmp = mem; | 2635 | tmp = mem; |
2635 | ret = mem; | 2636 | ret = mem; |
2636 | mem += (n_desc + 1) * sizeof(*tmp); | 2637 | mem += (n_desc + 1) * sizeof(*tmp); |
2637 | while (*src) { | 2638 | while (*src) { |
2638 | memcpy(mem, *src, (*src)->bLength); | 2639 | memcpy(mem, *src, (*src)->bLength); |
2639 | *tmp = mem; | 2640 | *tmp = mem; |
2640 | tmp++; | 2641 | tmp++; |
2641 | mem += (*src)->bLength; | 2642 | mem += (*src)->bLength; |
2642 | src++; | 2643 | src++; |
2643 | } | 2644 | } |
2644 | *tmp = NULL; | 2645 | *tmp = NULL; |
2645 | 2646 | ||
2646 | return ret; | 2647 | return ret; |
2647 | } | 2648 | } |
2648 | 2649 | ||
2649 | static void fsg_unbind(struct usb_configuration *c, struct usb_function *f) | 2650 | static void fsg_unbind(struct usb_configuration *c, struct usb_function *f) |
2650 | { | 2651 | { |
2651 | struct fsg_dev *fsg = fsg_from_func(f); | 2652 | struct fsg_dev *fsg = fsg_from_func(f); |
2652 | 2653 | ||
2653 | DBG(fsg, "unbind\n"); | 2654 | DBG(fsg, "unbind\n"); |
2654 | if (fsg->common->fsg == fsg) { | 2655 | if (fsg->common->fsg == fsg) { |
2655 | fsg->common->new_fsg = NULL; | 2656 | fsg->common->new_fsg = NULL; |
2656 | raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); | 2657 | raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); |
2657 | } | 2658 | } |
2658 | 2659 | ||
2659 | free(fsg->function.descriptors); | 2660 | free(fsg->function.descriptors); |
2660 | free(fsg->function.hs_descriptors); | 2661 | free(fsg->function.hs_descriptors); |
2661 | kfree(fsg); | 2662 | kfree(fsg); |
2662 | } | 2663 | } |
2663 | 2664 | ||
2664 | static int fsg_bind(struct usb_configuration *c, struct usb_function *f) | 2665 | static int fsg_bind(struct usb_configuration *c, struct usb_function *f) |
2665 | { | 2666 | { |
2666 | struct fsg_dev *fsg = fsg_from_func(f); | 2667 | struct fsg_dev *fsg = fsg_from_func(f); |
2667 | struct usb_gadget *gadget = c->cdev->gadget; | 2668 | struct usb_gadget *gadget = c->cdev->gadget; |
2668 | int i; | 2669 | int i; |
2669 | struct usb_ep *ep; | 2670 | struct usb_ep *ep; |
2670 | fsg->gadget = gadget; | 2671 | fsg->gadget = gadget; |
2671 | 2672 | ||
2672 | /* New interface */ | 2673 | /* New interface */ |
2673 | i = usb_interface_id(c, f); | 2674 | i = usb_interface_id(c, f); |
2674 | if (i < 0) | 2675 | if (i < 0) |
2675 | return i; | 2676 | return i; |
2676 | fsg_intf_desc.bInterfaceNumber = i; | 2677 | fsg_intf_desc.bInterfaceNumber = i; |
2677 | fsg->interface_number = i; | 2678 | fsg->interface_number = i; |
2678 | 2679 | ||
2679 | /* Find all the endpoints we will use */ | 2680 | /* Find all the endpoints we will use */ |
2680 | ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc); | 2681 | ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc); |
2681 | if (!ep) | 2682 | if (!ep) |
2682 | goto autoconf_fail; | 2683 | goto autoconf_fail; |
2683 | ep->driver_data = fsg->common; /* claim the endpoint */ | 2684 | ep->driver_data = fsg->common; /* claim the endpoint */ |
2684 | fsg->bulk_in = ep; | 2685 | fsg->bulk_in = ep; |
2685 | 2686 | ||
2686 | ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc); | 2687 | ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc); |
2687 | if (!ep) | 2688 | if (!ep) |
2688 | goto autoconf_fail; | 2689 | goto autoconf_fail; |
2689 | ep->driver_data = fsg->common; /* claim the endpoint */ | 2690 | ep->driver_data = fsg->common; /* claim the endpoint */ |
2690 | fsg->bulk_out = ep; | 2691 | fsg->bulk_out = ep; |
2691 | 2692 | ||
2692 | /* Copy descriptors */ | 2693 | /* Copy descriptors */ |
2693 | f->descriptors = usb_copy_descriptors(fsg_fs_function); | 2694 | f->descriptors = usb_copy_descriptors(fsg_fs_function); |
2694 | if (unlikely(!f->descriptors)) | 2695 | if (unlikely(!f->descriptors)) |
2695 | return -ENOMEM; | 2696 | return -ENOMEM; |
2696 | 2697 | ||
2697 | if (gadget_is_dualspeed(gadget)) { | 2698 | if (gadget_is_dualspeed(gadget)) { |
2698 | /* Assume endpoint addresses are the same for both speeds */ | 2699 | /* Assume endpoint addresses are the same for both speeds */ |
2699 | fsg_hs_bulk_in_desc.bEndpointAddress = | 2700 | fsg_hs_bulk_in_desc.bEndpointAddress = |
2700 | fsg_fs_bulk_in_desc.bEndpointAddress; | 2701 | fsg_fs_bulk_in_desc.bEndpointAddress; |
2701 | fsg_hs_bulk_out_desc.bEndpointAddress = | 2702 | fsg_hs_bulk_out_desc.bEndpointAddress = |
2702 | fsg_fs_bulk_out_desc.bEndpointAddress; | 2703 | fsg_fs_bulk_out_desc.bEndpointAddress; |
2703 | f->hs_descriptors = usb_copy_descriptors(fsg_hs_function); | 2704 | f->hs_descriptors = usb_copy_descriptors(fsg_hs_function); |
2704 | if (unlikely(!f->hs_descriptors)) { | 2705 | if (unlikely(!f->hs_descriptors)) { |
2705 | free(f->descriptors); | 2706 | free(f->descriptors); |
2706 | return -ENOMEM; | 2707 | return -ENOMEM; |
2707 | } | 2708 | } |
2708 | } | 2709 | } |
2709 | return 0; | 2710 | return 0; |
2710 | 2711 | ||
2711 | autoconf_fail: | 2712 | autoconf_fail: |
2712 | ERROR(fsg, "unable to autoconfigure all endpoints\n"); | 2713 | ERROR(fsg, "unable to autoconfigure all endpoints\n"); |
2713 | return -ENOTSUPP; | 2714 | return -ENOTSUPP; |
2714 | } | 2715 | } |
2715 | 2716 | ||
2716 | 2717 | ||
2717 | /****************************** ADD FUNCTION ******************************/ | 2718 | /****************************** ADD FUNCTION ******************************/ |
2718 | 2719 | ||
2719 | static struct usb_gadget_strings *fsg_strings_array[] = { | 2720 | static struct usb_gadget_strings *fsg_strings_array[] = { |
2720 | &fsg_stringtab, | 2721 | &fsg_stringtab, |
2721 | NULL, | 2722 | NULL, |
2722 | }; | 2723 | }; |
2723 | 2724 | ||
2724 | static int fsg_bind_config(struct usb_composite_dev *cdev, | 2725 | static int fsg_bind_config(struct usb_composite_dev *cdev, |
2725 | struct usb_configuration *c, | 2726 | struct usb_configuration *c, |
2726 | struct fsg_common *common) | 2727 | struct fsg_common *common) |
2727 | { | 2728 | { |
2728 | struct fsg_dev *fsg; | 2729 | struct fsg_dev *fsg; |
2729 | int rc; | 2730 | int rc; |
2730 | 2731 | ||
2731 | fsg = calloc(1, sizeof *fsg); | 2732 | fsg = calloc(1, sizeof *fsg); |
2732 | if (!fsg) | 2733 | if (!fsg) |
2733 | return -ENOMEM; | 2734 | return -ENOMEM; |
2734 | fsg->function.name = FSG_DRIVER_DESC; | 2735 | fsg->function.name = FSG_DRIVER_DESC; |
2735 | fsg->function.strings = fsg_strings_array; | 2736 | fsg->function.strings = fsg_strings_array; |
2736 | fsg->function.bind = fsg_bind; | 2737 | fsg->function.bind = fsg_bind; |
2737 | fsg->function.unbind = fsg_unbind; | 2738 | fsg->function.unbind = fsg_unbind; |
2738 | fsg->function.setup = fsg_setup; | 2739 | fsg->function.setup = fsg_setup; |
2739 | fsg->function.set_alt = fsg_set_alt; | 2740 | fsg->function.set_alt = fsg_set_alt; |
2740 | fsg->function.disable = fsg_disable; | 2741 | fsg->function.disable = fsg_disable; |
2741 | 2742 | ||
2742 | fsg->common = common; | 2743 | fsg->common = common; |
2743 | common->fsg = fsg; | 2744 | common->fsg = fsg; |
2744 | /* Our caller holds a reference to common structure so we | 2745 | /* Our caller holds a reference to common structure so we |
2745 | * don't have to be worry about it being freed until we return | 2746 | * don't have to be worry about it being freed until we return |
2746 | * from this function. So instead of incrementing counter now | 2747 | * from this function. So instead of incrementing counter now |
2747 | * and decrement in error recovery we increment it only when | 2748 | * and decrement in error recovery we increment it only when |
2748 | * call to usb_add_function() was successful. */ | 2749 | * call to usb_add_function() was successful. */ |
2749 | 2750 | ||
2750 | rc = usb_add_function(c, &fsg->function); | 2751 | rc = usb_add_function(c, &fsg->function); |
2751 | 2752 | ||
2752 | if (rc) | 2753 | if (rc) |
2753 | kfree(fsg); | 2754 | kfree(fsg); |
2754 | 2755 | ||
2755 | return rc; | 2756 | return rc; |
2756 | } | 2757 | } |
2757 | 2758 | ||
2758 | int fsg_add(struct usb_configuration *c) | 2759 | int fsg_add(struct usb_configuration *c) |
2759 | { | 2760 | { |
2760 | struct fsg_common *fsg_common; | 2761 | struct fsg_common *fsg_common; |
2761 | 2762 | ||
2762 | fsg_common = fsg_common_init(NULL, c->cdev); | 2763 | fsg_common = fsg_common_init(NULL, c->cdev); |
2763 | 2764 | ||
2764 | fsg_common->vendor_name = 0; | 2765 | fsg_common->vendor_name = 0; |
2765 | fsg_common->product_name = 0; | 2766 | fsg_common->product_name = 0; |
2766 | fsg_common->release = 0xffff; | 2767 | fsg_common->release = 0xffff; |
2767 | 2768 | ||
2768 | fsg_common->ops = NULL; | 2769 | fsg_common->ops = NULL; |
2769 | fsg_common->private_data = NULL; | 2770 | fsg_common->private_data = NULL; |
2770 | 2771 | ||
2771 | the_fsg_common = fsg_common; | 2772 | the_fsg_common = fsg_common; |
2772 | 2773 | ||
2773 | return fsg_bind_config(c->cdev, c, fsg_common); | 2774 | return fsg_bind_config(c->cdev, c, fsg_common); |
2774 | } | 2775 | } |
2775 | 2776 | ||
2776 | int fsg_init(struct ums *ums_dev) | 2777 | int fsg_init(struct ums *ums_dev) |
2777 | { | 2778 | { |
2778 | ums = ums_dev; | 2779 | ums = ums_dev; |
2779 | 2780 | ||
2780 | return 0; | 2781 | return 0; |
2781 | } | 2782 | } |
2782 | 2783 | ||
2783 | DECLARE_GADGET_BIND_CALLBACK(usb_dnl_ums, fsg_add); | 2784 | DECLARE_GADGET_BIND_CALLBACK(usb_dnl_ums, fsg_add); |
2784 | 2785 |
drivers/usb/gadget/f_thor.c
1 | /* | 1 | /* |
2 | * f_thor.c -- USB TIZEN THOR Downloader gadget function | 2 | * f_thor.c -- USB TIZEN THOR Downloader gadget function |
3 | * | 3 | * |
4 | * Copyright (C) 2013 Samsung Electronics | 4 | * Copyright (C) 2013 Samsung Electronics |
5 | * Lukasz Majewski <l.majewski@samsung.com> | 5 | * Lukasz Majewski <l.majewski@samsung.com> |
6 | * | 6 | * |
7 | * Based on code from: | 7 | * Based on code from: |
8 | * git://review.tizen.org/kernel/u-boot | 8 | * git://review.tizen.org/kernel/u-boot |
9 | * | 9 | * |
10 | * Developed by: | 10 | * Developed by: |
11 | * Copyright (C) 2009 Samsung Electronics | 11 | * Copyright (C) 2009 Samsung Electronics |
12 | * Minkyu Kang <mk7.kang@samsung.com> | 12 | * Minkyu Kang <mk7.kang@samsung.com> |
13 | * Sanghee Kim <sh0130.kim@samsung.com> | 13 | * Sanghee Kim <sh0130.kim@samsung.com> |
14 | * | 14 | * |
15 | * SPDX-License-Identifier: GPL-2.0+ | 15 | * SPDX-License-Identifier: GPL-2.0+ |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <errno.h> | 18 | #include <errno.h> |
19 | #include <common.h> | 19 | #include <common.h> |
20 | #include <malloc.h> | 20 | #include <malloc.h> |
21 | #include <version.h> | 21 | #include <version.h> |
22 | #include <linux/usb/ch9.h> | 22 | #include <linux/usb/ch9.h> |
23 | #include <linux/usb/gadget.h> | 23 | #include <linux/usb/gadget.h> |
24 | #include <linux/usb/composite.h> | 24 | #include <linux/usb/composite.h> |
25 | #include <linux/usb/cdc.h> | 25 | #include <linux/usb/cdc.h> |
26 | #include <g_dnl.h> | 26 | #include <g_dnl.h> |
27 | #include <dfu.h> | 27 | #include <dfu.h> |
28 | 28 | ||
29 | #include "f_thor.h" | 29 | #include "f_thor.h" |
30 | 30 | ||
31 | static void thor_tx_data(unsigned char *data, int len); | 31 | static void thor_tx_data(unsigned char *data, int len); |
32 | static void thor_set_dma(void *addr, int len); | 32 | static void thor_set_dma(void *addr, int len); |
33 | static int thor_rx_data(void); | 33 | static int thor_rx_data(void); |
34 | 34 | ||
35 | static struct f_thor *thor_func; | 35 | static struct f_thor *thor_func; |
36 | static inline struct f_thor *func_to_thor(struct usb_function *f) | 36 | static inline struct f_thor *func_to_thor(struct usb_function *f) |
37 | { | 37 | { |
38 | return container_of(f, struct f_thor, usb_function); | 38 | return container_of(f, struct f_thor, usb_function); |
39 | } | 39 | } |
40 | 40 | ||
41 | DEFINE_CACHE_ALIGN_BUFFER(unsigned char, thor_tx_data_buf, | 41 | DEFINE_CACHE_ALIGN_BUFFER(unsigned char, thor_tx_data_buf, |
42 | sizeof(struct rsp_box)); | 42 | sizeof(struct rsp_box)); |
43 | DEFINE_CACHE_ALIGN_BUFFER(unsigned char, thor_rx_data_buf, | 43 | DEFINE_CACHE_ALIGN_BUFFER(unsigned char, thor_rx_data_buf, |
44 | sizeof(struct rqt_box)); | 44 | sizeof(struct rqt_box)); |
45 | 45 | ||
46 | /* ********************************************************** */ | 46 | /* ********************************************************** */ |
47 | /* THOR protocol - transmission handling */ | 47 | /* THOR protocol - transmission handling */ |
48 | /* ********************************************************** */ | 48 | /* ********************************************************** */ |
49 | DEFINE_CACHE_ALIGN_BUFFER(char, f_name, F_NAME_BUF_SIZE); | 49 | DEFINE_CACHE_ALIGN_BUFFER(char, f_name, F_NAME_BUF_SIZE); |
50 | static unsigned long long int thor_file_size; | 50 | static unsigned long long int thor_file_size; |
51 | static int alt_setting_num; | 51 | static int alt_setting_num; |
52 | 52 | ||
53 | static void send_rsp(const struct rsp_box *rsp) | 53 | static void send_rsp(const struct rsp_box *rsp) |
54 | { | 54 | { |
55 | memcpy(thor_tx_data_buf, rsp, sizeof(struct rsp_box)); | 55 | memcpy(thor_tx_data_buf, rsp, sizeof(struct rsp_box)); |
56 | thor_tx_data(thor_tx_data_buf, sizeof(struct rsp_box)); | 56 | thor_tx_data(thor_tx_data_buf, sizeof(struct rsp_box)); |
57 | 57 | ||
58 | debug("-RSP: %d, %d\n", rsp->rsp, rsp->rsp_data); | 58 | debug("-RSP: %d, %d\n", rsp->rsp, rsp->rsp_data); |
59 | } | 59 | } |
60 | 60 | ||
61 | static void send_data_rsp(s32 ack, s32 count) | 61 | static void send_data_rsp(s32 ack, s32 count) |
62 | { | 62 | { |
63 | ALLOC_CACHE_ALIGN_BUFFER(struct data_rsp_box, rsp, | 63 | ALLOC_CACHE_ALIGN_BUFFER(struct data_rsp_box, rsp, |
64 | sizeof(struct data_rsp_box)); | 64 | sizeof(struct data_rsp_box)); |
65 | 65 | ||
66 | rsp->ack = ack; | 66 | rsp->ack = ack; |
67 | rsp->count = count; | 67 | rsp->count = count; |
68 | 68 | ||
69 | memcpy(thor_tx_data_buf, rsp, sizeof(struct data_rsp_box)); | 69 | memcpy(thor_tx_data_buf, rsp, sizeof(struct data_rsp_box)); |
70 | thor_tx_data(thor_tx_data_buf, sizeof(struct data_rsp_box)); | 70 | thor_tx_data(thor_tx_data_buf, sizeof(struct data_rsp_box)); |
71 | 71 | ||
72 | debug("-DATA RSP: %d, %d\n", ack, count); | 72 | debug("-DATA RSP: %d, %d\n", ack, count); |
73 | } | 73 | } |
74 | 74 | ||
75 | static int process_rqt_info(const struct rqt_box *rqt) | 75 | static int process_rqt_info(const struct rqt_box *rqt) |
76 | { | 76 | { |
77 | ALLOC_CACHE_ALIGN_BUFFER(struct rsp_box, rsp, sizeof(struct rsp_box)); | 77 | ALLOC_CACHE_ALIGN_BUFFER(struct rsp_box, rsp, sizeof(struct rsp_box)); |
78 | memset(rsp, 0, sizeof(struct rsp_box)); | 78 | memset(rsp, 0, sizeof(struct rsp_box)); |
79 | 79 | ||
80 | rsp->rsp = rqt->rqt; | 80 | rsp->rsp = rqt->rqt; |
81 | rsp->rsp_data = rqt->rqt_data; | 81 | rsp->rsp_data = rqt->rqt_data; |
82 | 82 | ||
83 | switch (rqt->rqt_data) { | 83 | switch (rqt->rqt_data) { |
84 | case RQT_INFO_VER_PROTOCOL: | 84 | case RQT_INFO_VER_PROTOCOL: |
85 | rsp->int_data[0] = VER_PROTOCOL_MAJOR; | 85 | rsp->int_data[0] = VER_PROTOCOL_MAJOR; |
86 | rsp->int_data[1] = VER_PROTOCOL_MINOR; | 86 | rsp->int_data[1] = VER_PROTOCOL_MINOR; |
87 | break; | 87 | break; |
88 | case RQT_INIT_VER_HW: | 88 | case RQT_INIT_VER_HW: |
89 | snprintf(rsp->str_data[0], sizeof(rsp->str_data[0]), | 89 | snprintf(rsp->str_data[0], sizeof(rsp->str_data[0]), |
90 | "%x", checkboard()); | 90 | "%x", checkboard()); |
91 | break; | 91 | break; |
92 | case RQT_INIT_VER_BOOT: | 92 | case RQT_INIT_VER_BOOT: |
93 | sprintf(rsp->str_data[0], "%s", U_BOOT_VERSION); | 93 | sprintf(rsp->str_data[0], "%s", U_BOOT_VERSION); |
94 | break; | 94 | break; |
95 | case RQT_INIT_VER_KERNEL: | 95 | case RQT_INIT_VER_KERNEL: |
96 | sprintf(rsp->str_data[0], "%s", "k unknown"); | 96 | sprintf(rsp->str_data[0], "%s", "k unknown"); |
97 | break; | 97 | break; |
98 | case RQT_INIT_VER_PLATFORM: | 98 | case RQT_INIT_VER_PLATFORM: |
99 | sprintf(rsp->str_data[0], "%s", "p unknown"); | 99 | sprintf(rsp->str_data[0], "%s", "p unknown"); |
100 | break; | 100 | break; |
101 | case RQT_INIT_VER_CSC: | 101 | case RQT_INIT_VER_CSC: |
102 | sprintf(rsp->str_data[0], "%s", "c unknown"); | 102 | sprintf(rsp->str_data[0], "%s", "c unknown"); |
103 | break; | 103 | break; |
104 | default: | 104 | default: |
105 | return -EINVAL; | 105 | return -EINVAL; |
106 | } | 106 | } |
107 | 107 | ||
108 | send_rsp(rsp); | 108 | send_rsp(rsp); |
109 | return true; | 109 | return true; |
110 | } | 110 | } |
111 | 111 | ||
112 | static int process_rqt_cmd(const struct rqt_box *rqt) | 112 | static int process_rqt_cmd(const struct rqt_box *rqt) |
113 | { | 113 | { |
114 | ALLOC_CACHE_ALIGN_BUFFER(struct rsp_box, rsp, sizeof(struct rsp_box)); | 114 | ALLOC_CACHE_ALIGN_BUFFER(struct rsp_box, rsp, sizeof(struct rsp_box)); |
115 | memset(rsp, 0, sizeof(struct rsp_box)); | 115 | memset(rsp, 0, sizeof(struct rsp_box)); |
116 | 116 | ||
117 | rsp->rsp = rqt->rqt; | 117 | rsp->rsp = rqt->rqt; |
118 | rsp->rsp_data = rqt->rqt_data; | 118 | rsp->rsp_data = rqt->rqt_data; |
119 | 119 | ||
120 | switch (rqt->rqt_data) { | 120 | switch (rqt->rqt_data) { |
121 | case RQT_CMD_REBOOT: | 121 | case RQT_CMD_REBOOT: |
122 | debug("TARGET RESET\n"); | 122 | debug("TARGET RESET\n"); |
123 | send_rsp(rsp); | 123 | send_rsp(rsp); |
124 | g_dnl_unregister(); | 124 | g_dnl_unregister(); |
125 | dfu_free_entities(); | 125 | dfu_free_entities(); |
126 | run_command("reset", 0); | 126 | run_command("reset", 0); |
127 | break; | 127 | break; |
128 | case RQT_CMD_POWEROFF: | 128 | case RQT_CMD_POWEROFF: |
129 | case RQT_CMD_EFSCLEAR: | 129 | case RQT_CMD_EFSCLEAR: |
130 | send_rsp(rsp); | 130 | send_rsp(rsp); |
131 | default: | 131 | default: |
132 | printf("Command not supported -> cmd: %d\n", rqt->rqt_data); | 132 | printf("Command not supported -> cmd: %d\n", rqt->rqt_data); |
133 | return -EINVAL; | 133 | return -EINVAL; |
134 | } | 134 | } |
135 | 135 | ||
136 | return true; | 136 | return true; |
137 | } | 137 | } |
138 | 138 | ||
139 | static long long int download_head(unsigned long long total, | 139 | static long long int download_head(unsigned long long total, |
140 | unsigned int packet_size, | 140 | unsigned int packet_size, |
141 | long long int *left, | 141 | long long int *left, |
142 | int *cnt) | 142 | int *cnt) |
143 | { | 143 | { |
144 | long long int rcv_cnt = 0, left_to_rcv, ret_rcv; | 144 | long long int rcv_cnt = 0, left_to_rcv, ret_rcv; |
145 | struct dfu_entity *dfu_entity = dfu_get_entity(alt_setting_num); | 145 | struct dfu_entity *dfu_entity = dfu_get_entity(alt_setting_num); |
146 | void *transfer_buffer = dfu_get_buf(dfu_entity); | 146 | void *transfer_buffer = dfu_get_buf(dfu_entity); |
147 | void *buf = transfer_buffer; | 147 | void *buf = transfer_buffer; |
148 | int usb_pkt_cnt = 0, ret; | 148 | int usb_pkt_cnt = 0, ret; |
149 | 149 | ||
150 | /* | 150 | /* |
151 | * Files smaller than THOR_STORE_UNIT_SIZE (now 32 MiB) are stored on | 151 | * Files smaller than THOR_STORE_UNIT_SIZE (now 32 MiB) are stored on |
152 | * the medium. | 152 | * the medium. |
153 | * The packet response is sent on the purpose after successful data | 153 | * The packet response is sent on the purpose after successful data |
154 | * chunk write. There is a room for improvement when asynchronous write | 154 | * chunk write. There is a room for improvement when asynchronous write |
155 | * is performed. | 155 | * is performed. |
156 | */ | 156 | */ |
157 | while (total - rcv_cnt >= packet_size) { | 157 | while (total - rcv_cnt >= packet_size) { |
158 | thor_set_dma(buf, packet_size); | 158 | thor_set_dma(buf, packet_size); |
159 | buf += packet_size; | 159 | buf += packet_size; |
160 | ret_rcv = thor_rx_data(); | 160 | ret_rcv = thor_rx_data(); |
161 | if (ret_rcv < 0) | 161 | if (ret_rcv < 0) |
162 | return ret_rcv; | 162 | return ret_rcv; |
163 | rcv_cnt += ret_rcv; | 163 | rcv_cnt += ret_rcv; |
164 | debug("%d: RCV data count: %llu cnt: %d\n", usb_pkt_cnt, | 164 | debug("%d: RCV data count: %llu cnt: %d\n", usb_pkt_cnt, |
165 | rcv_cnt, *cnt); | 165 | rcv_cnt, *cnt); |
166 | 166 | ||
167 | if ((rcv_cnt % THOR_STORE_UNIT_SIZE) == 0) { | 167 | if ((rcv_cnt % THOR_STORE_UNIT_SIZE) == 0) { |
168 | ret = dfu_write(dfu_get_entity(alt_setting_num), | 168 | ret = dfu_write(dfu_get_entity(alt_setting_num), |
169 | transfer_buffer, THOR_STORE_UNIT_SIZE, | 169 | transfer_buffer, THOR_STORE_UNIT_SIZE, |
170 | (*cnt)++); | 170 | (*cnt)++); |
171 | if (ret) { | 171 | if (ret) { |
172 | error("DFU write failed [%d] cnt: %d", | 172 | error("DFU write failed [%d] cnt: %d", |
173 | ret, *cnt); | 173 | ret, *cnt); |
174 | return ret; | 174 | return ret; |
175 | } | 175 | } |
176 | buf = transfer_buffer; | 176 | buf = transfer_buffer; |
177 | } | 177 | } |
178 | send_data_rsp(0, ++usb_pkt_cnt); | 178 | send_data_rsp(0, ++usb_pkt_cnt); |
179 | } | 179 | } |
180 | 180 | ||
181 | /* Calculate the amount of data to arrive from PC (in bytes) */ | 181 | /* Calculate the amount of data to arrive from PC (in bytes) */ |
182 | left_to_rcv = total - rcv_cnt; | 182 | left_to_rcv = total - rcv_cnt; |
183 | 183 | ||
184 | /* | 184 | /* |
185 | * Calculate number of data already received. but not yet stored | 185 | * Calculate number of data already received. but not yet stored |
186 | * on the medium (they are smaller than THOR_STORE_UNIT_SIZE) | 186 | * on the medium (they are smaller than THOR_STORE_UNIT_SIZE) |
187 | */ | 187 | */ |
188 | *left = left_to_rcv + buf - transfer_buffer; | 188 | *left = left_to_rcv + buf - transfer_buffer; |
189 | debug("%s: left: %llu left_to_rcv: %llu buf: 0x%p\n", __func__, | 189 | debug("%s: left: %llu left_to_rcv: %llu buf: 0x%p\n", __func__, |
190 | *left, left_to_rcv, buf); | 190 | *left, left_to_rcv, buf); |
191 | 191 | ||
192 | if (left_to_rcv) { | 192 | if (left_to_rcv) { |
193 | thor_set_dma(buf, packet_size); | 193 | thor_set_dma(buf, packet_size); |
194 | ret_rcv = thor_rx_data(); | 194 | ret_rcv = thor_rx_data(); |
195 | if (ret_rcv < 0) | 195 | if (ret_rcv < 0) |
196 | return ret_rcv; | 196 | return ret_rcv; |
197 | rcv_cnt += ret_rcv; | 197 | rcv_cnt += ret_rcv; |
198 | send_data_rsp(0, ++usb_pkt_cnt); | 198 | send_data_rsp(0, ++usb_pkt_cnt); |
199 | } | 199 | } |
200 | 200 | ||
201 | debug("%s: %llu total: %llu cnt: %d\n", __func__, rcv_cnt, total, *cnt); | 201 | debug("%s: %llu total: %llu cnt: %d\n", __func__, rcv_cnt, total, *cnt); |
202 | 202 | ||
203 | return rcv_cnt; | 203 | return rcv_cnt; |
204 | } | 204 | } |
205 | 205 | ||
206 | static int download_tail(long long int left, int cnt) | 206 | static int download_tail(long long int left, int cnt) |
207 | { | 207 | { |
208 | struct dfu_entity *dfu_entity = dfu_get_entity(alt_setting_num); | 208 | struct dfu_entity *dfu_entity = dfu_get_entity(alt_setting_num); |
209 | void *transfer_buffer = dfu_get_buf(dfu_entity); | 209 | void *transfer_buffer = dfu_get_buf(dfu_entity); |
210 | int ret; | 210 | int ret; |
211 | 211 | ||
212 | debug("%s: left: %llu cnt: %d\n", __func__, left, cnt); | 212 | debug("%s: left: %llu cnt: %d\n", __func__, left, cnt); |
213 | 213 | ||
214 | if (left) { | 214 | if (left) { |
215 | ret = dfu_write(dfu_entity, transfer_buffer, left, cnt++); | 215 | ret = dfu_write(dfu_entity, transfer_buffer, left, cnt++); |
216 | if (ret) { | 216 | if (ret) { |
217 | error("DFU write failed [%d]: left: %llu", ret, left); | 217 | error("DFU write failed [%d]: left: %llu", ret, left); |
218 | return ret; | 218 | return ret; |
219 | } | 219 | } |
220 | } | 220 | } |
221 | 221 | ||
222 | /* | 222 | /* |
223 | * To store last "packet" or write file from buffer to filesystem | 223 | * To store last "packet" or write file from buffer to filesystem |
224 | * DFU storage backend requires dfu_flush | 224 | * DFU storage backend requires dfu_flush |
225 | * | 225 | * |
226 | * This also frees memory malloc'ed by dfu_get_buf(), so no explicit | 226 | * This also frees memory malloc'ed by dfu_get_buf(), so no explicit |
227 | * need fo call dfu_free_buf() is needed. | 227 | * need fo call dfu_free_buf() is needed. |
228 | */ | 228 | */ |
229 | ret = dfu_flush(dfu_entity, transfer_buffer, 0, cnt); | 229 | ret = dfu_flush(dfu_entity, transfer_buffer, 0, cnt); |
230 | if (ret) | 230 | if (ret) |
231 | error("DFU flush failed!"); | 231 | error("DFU flush failed!"); |
232 | 232 | ||
233 | return ret; | 233 | return ret; |
234 | } | 234 | } |
235 | 235 | ||
236 | static long long int process_rqt_download(const struct rqt_box *rqt) | 236 | static long long int process_rqt_download(const struct rqt_box *rqt) |
237 | { | 237 | { |
238 | ALLOC_CACHE_ALIGN_BUFFER(struct rsp_box, rsp, sizeof(struct rsp_box)); | 238 | ALLOC_CACHE_ALIGN_BUFFER(struct rsp_box, rsp, sizeof(struct rsp_box)); |
239 | static long long int left, ret_head; | 239 | static long long int left, ret_head; |
240 | int file_type, ret = 0; | 240 | int file_type, ret = 0; |
241 | static int cnt; | 241 | static int cnt; |
242 | 242 | ||
243 | memset(rsp, 0, sizeof(struct rsp_box)); | 243 | memset(rsp, 0, sizeof(struct rsp_box)); |
244 | rsp->rsp = rqt->rqt; | 244 | rsp->rsp = rqt->rqt; |
245 | rsp->rsp_data = rqt->rqt_data; | 245 | rsp->rsp_data = rqt->rqt_data; |
246 | 246 | ||
247 | switch (rqt->rqt_data) { | 247 | switch (rqt->rqt_data) { |
248 | case RQT_DL_INIT: | 248 | case RQT_DL_INIT: |
249 | thor_file_size = rqt->int_data[0]; | 249 | thor_file_size = rqt->int_data[0]; |
250 | debug("INIT: total %d bytes\n", rqt->int_data[0]); | 250 | debug("INIT: total %d bytes\n", rqt->int_data[0]); |
251 | break; | 251 | break; |
252 | case RQT_DL_FILE_INFO: | 252 | case RQT_DL_FILE_INFO: |
253 | file_type = rqt->int_data[0]; | 253 | file_type = rqt->int_data[0]; |
254 | if (file_type == FILE_TYPE_PIT) { | 254 | if (file_type == FILE_TYPE_PIT) { |
255 | puts("PIT table file - not supported\n"); | 255 | puts("PIT table file - not supported\n"); |
256 | rsp->ack = -ENOTSUPP; | 256 | rsp->ack = -ENOTSUPP; |
257 | ret = rsp->ack; | 257 | ret = rsp->ack; |
258 | break; | 258 | break; |
259 | } | 259 | } |
260 | 260 | ||
261 | thor_file_size = rqt->int_data[1]; | 261 | thor_file_size = rqt->int_data[1]; |
262 | memcpy(f_name, rqt->str_data[0], F_NAME_BUF_SIZE); | 262 | memcpy(f_name, rqt->str_data[0], F_NAME_BUF_SIZE); |
263 | 263 | ||
264 | debug("INFO: name(%s, %d), size(%llu), type(%d)\n", | 264 | debug("INFO: name(%s, %d), size(%llu), type(%d)\n", |
265 | f_name, 0, thor_file_size, file_type); | 265 | f_name, 0, thor_file_size, file_type); |
266 | 266 | ||
267 | rsp->int_data[0] = THOR_PACKET_SIZE; | 267 | rsp->int_data[0] = THOR_PACKET_SIZE; |
268 | 268 | ||
269 | alt_setting_num = dfu_get_alt(f_name); | 269 | alt_setting_num = dfu_get_alt(f_name); |
270 | if (alt_setting_num < 0) { | 270 | if (alt_setting_num < 0) { |
271 | error("Alt setting [%d] to write not found!", | 271 | error("Alt setting [%d] to write not found!", |
272 | alt_setting_num); | 272 | alt_setting_num); |
273 | rsp->ack = -ENODEV; | 273 | rsp->ack = -ENODEV; |
274 | ret = rsp->ack; | 274 | ret = rsp->ack; |
275 | } | 275 | } |
276 | break; | 276 | break; |
277 | case RQT_DL_FILE_START: | 277 | case RQT_DL_FILE_START: |
278 | send_rsp(rsp); | 278 | send_rsp(rsp); |
279 | ret_head = download_head(thor_file_size, THOR_PACKET_SIZE, | 279 | ret_head = download_head(thor_file_size, THOR_PACKET_SIZE, |
280 | &left, &cnt); | 280 | &left, &cnt); |
281 | if (ret_head < 0) { | 281 | if (ret_head < 0) { |
282 | left = 0; | 282 | left = 0; |
283 | cnt = 0; | 283 | cnt = 0; |
284 | } | 284 | } |
285 | return ret_head; | 285 | return ret_head; |
286 | case RQT_DL_FILE_END: | 286 | case RQT_DL_FILE_END: |
287 | debug("DL FILE_END\n"); | 287 | debug("DL FILE_END\n"); |
288 | rsp->ack = download_tail(left, cnt); | 288 | rsp->ack = download_tail(left, cnt); |
289 | ret = rsp->ack; | 289 | ret = rsp->ack; |
290 | left = 0; | 290 | left = 0; |
291 | cnt = 0; | 291 | cnt = 0; |
292 | break; | 292 | break; |
293 | case RQT_DL_EXIT: | 293 | case RQT_DL_EXIT: |
294 | debug("DL EXIT\n"); | 294 | debug("DL EXIT\n"); |
295 | break; | 295 | break; |
296 | default: | 296 | default: |
297 | error("Operation not supported: %d", rqt->rqt_data); | 297 | error("Operation not supported: %d", rqt->rqt_data); |
298 | ret = -ENOTSUPP; | 298 | ret = -ENOTSUPP; |
299 | } | 299 | } |
300 | 300 | ||
301 | send_rsp(rsp); | 301 | send_rsp(rsp); |
302 | return ret; | 302 | return ret; |
303 | } | 303 | } |
304 | 304 | ||
305 | static int process_data(void) | 305 | static int process_data(void) |
306 | { | 306 | { |
307 | ALLOC_CACHE_ALIGN_BUFFER(struct rqt_box, rqt, sizeof(struct rqt_box)); | 307 | ALLOC_CACHE_ALIGN_BUFFER(struct rqt_box, rqt, sizeof(struct rqt_box)); |
308 | int ret = -EINVAL; | 308 | int ret = -EINVAL; |
309 | 309 | ||
310 | memcpy(rqt, thor_rx_data_buf, sizeof(struct rqt_box)); | 310 | memcpy(rqt, thor_rx_data_buf, sizeof(struct rqt_box)); |
311 | 311 | ||
312 | debug("+RQT: %d, %d\n", rqt->rqt, rqt->rqt_data); | 312 | debug("+RQT: %d, %d\n", rqt->rqt, rqt->rqt_data); |
313 | 313 | ||
314 | switch (rqt->rqt) { | 314 | switch (rqt->rqt) { |
315 | case RQT_INFO: | 315 | case RQT_INFO: |
316 | ret = process_rqt_info(rqt); | 316 | ret = process_rqt_info(rqt); |
317 | break; | 317 | break; |
318 | case RQT_CMD: | 318 | case RQT_CMD: |
319 | ret = process_rqt_cmd(rqt); | 319 | ret = process_rqt_cmd(rqt); |
320 | break; | 320 | break; |
321 | case RQT_DL: | 321 | case RQT_DL: |
322 | ret = (int) process_rqt_download(rqt); | 322 | ret = (int) process_rqt_download(rqt); |
323 | break; | 323 | break; |
324 | case RQT_UL: | 324 | case RQT_UL: |
325 | puts("RQT: UPLOAD not supported!\n"); | 325 | puts("RQT: UPLOAD not supported!\n"); |
326 | break; | 326 | break; |
327 | default: | 327 | default: |
328 | error("unknown request (%d)", rqt->rqt); | 328 | error("unknown request (%d)", rqt->rqt); |
329 | } | 329 | } |
330 | 330 | ||
331 | return ret; | 331 | return ret; |
332 | } | 332 | } |
333 | 333 | ||
334 | /* ********************************************************** */ | 334 | /* ********************************************************** */ |
335 | /* THOR USB Function */ | 335 | /* THOR USB Function */ |
336 | /* ********************************************************** */ | 336 | /* ********************************************************** */ |
337 | 337 | ||
338 | static inline struct usb_endpoint_descriptor * | 338 | static inline struct usb_endpoint_descriptor * |
339 | ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs, | 339 | ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs, |
340 | struct usb_endpoint_descriptor *fs) | 340 | struct usb_endpoint_descriptor *fs) |
341 | { | 341 | { |
342 | if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) | 342 | if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) |
343 | return hs; | 343 | return hs; |
344 | return fs; | 344 | return fs; |
345 | } | 345 | } |
346 | 346 | ||
347 | static struct usb_interface_descriptor thor_downloader_intf_data = { | 347 | static struct usb_interface_descriptor thor_downloader_intf_data = { |
348 | .bLength = sizeof(thor_downloader_intf_data), | 348 | .bLength = sizeof(thor_downloader_intf_data), |
349 | .bDescriptorType = USB_DT_INTERFACE, | 349 | .bDescriptorType = USB_DT_INTERFACE, |
350 | 350 | ||
351 | .bNumEndpoints = 2, | 351 | .bNumEndpoints = 2, |
352 | .bInterfaceClass = USB_CLASS_CDC_DATA, | 352 | .bInterfaceClass = USB_CLASS_CDC_DATA, |
353 | }; | 353 | }; |
354 | 354 | ||
355 | static struct usb_endpoint_descriptor fs_in_desc = { | 355 | static struct usb_endpoint_descriptor fs_in_desc = { |
356 | .bLength = USB_DT_ENDPOINT_SIZE, | 356 | .bLength = USB_DT_ENDPOINT_SIZE, |
357 | .bDescriptorType = USB_DT_ENDPOINT, | 357 | .bDescriptorType = USB_DT_ENDPOINT, |
358 | 358 | ||
359 | .bEndpointAddress = USB_DIR_IN, | 359 | .bEndpointAddress = USB_DIR_IN, |
360 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 360 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
361 | }; | 361 | }; |
362 | 362 | ||
363 | static struct usb_endpoint_descriptor fs_out_desc = { | 363 | static struct usb_endpoint_descriptor fs_out_desc = { |
364 | .bLength = USB_DT_ENDPOINT_SIZE, | 364 | .bLength = USB_DT_ENDPOINT_SIZE, |
365 | .bDescriptorType = USB_DT_ENDPOINT, | 365 | .bDescriptorType = USB_DT_ENDPOINT, |
366 | 366 | ||
367 | .bEndpointAddress = USB_DIR_OUT, | 367 | .bEndpointAddress = USB_DIR_OUT, |
368 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 368 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
369 | }; | 369 | }; |
370 | 370 | ||
371 | /* CDC configuration */ | 371 | /* CDC configuration */ |
372 | static struct usb_interface_descriptor thor_downloader_intf_int = { | 372 | static struct usb_interface_descriptor thor_downloader_intf_int = { |
373 | .bLength = sizeof(thor_downloader_intf_int), | 373 | .bLength = sizeof(thor_downloader_intf_int), |
374 | .bDescriptorType = USB_DT_INTERFACE, | 374 | .bDescriptorType = USB_DT_INTERFACE, |
375 | 375 | ||
376 | .bNumEndpoints = 1, | 376 | .bNumEndpoints = 1, |
377 | .bInterfaceClass = USB_CLASS_COMM, | 377 | .bInterfaceClass = USB_CLASS_COMM, |
378 | /* 0x02 Abstract Line Control Model */ | 378 | /* 0x02 Abstract Line Control Model */ |
379 | .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, | 379 | .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, |
380 | /* 0x01 Common AT commands */ | 380 | /* 0x01 Common AT commands */ |
381 | .bInterfaceProtocol = USB_CDC_ACM_PROTO_AT_V25TER, | 381 | .bInterfaceProtocol = USB_CDC_ACM_PROTO_AT_V25TER, |
382 | }; | 382 | }; |
383 | 383 | ||
384 | static struct usb_cdc_header_desc thor_downloader_cdc_header = { | 384 | static struct usb_cdc_header_desc thor_downloader_cdc_header = { |
385 | .bLength = sizeof(thor_downloader_cdc_header), | 385 | .bLength = sizeof(thor_downloader_cdc_header), |
386 | .bDescriptorType = 0x24, /* CS_INTERFACE */ | 386 | .bDescriptorType = 0x24, /* CS_INTERFACE */ |
387 | .bDescriptorSubType = 0x00, | 387 | .bDescriptorSubType = 0x00, |
388 | .bcdCDC = 0x0110, | 388 | .bcdCDC = 0x0110, |
389 | }; | 389 | }; |
390 | 390 | ||
391 | static struct usb_cdc_call_mgmt_descriptor thor_downloader_cdc_call = { | 391 | static struct usb_cdc_call_mgmt_descriptor thor_downloader_cdc_call = { |
392 | .bLength = sizeof(thor_downloader_cdc_call), | 392 | .bLength = sizeof(thor_downloader_cdc_call), |
393 | .bDescriptorType = 0x24, /* CS_INTERFACE */ | 393 | .bDescriptorType = 0x24, /* CS_INTERFACE */ |
394 | .bDescriptorSubType = 0x01, | 394 | .bDescriptorSubType = 0x01, |
395 | .bmCapabilities = 0x00, | 395 | .bmCapabilities = 0x00, |
396 | .bDataInterface = 0x01, | 396 | .bDataInterface = 0x01, |
397 | }; | 397 | }; |
398 | 398 | ||
399 | static struct usb_cdc_acm_descriptor thor_downloader_cdc_abstract = { | 399 | static struct usb_cdc_acm_descriptor thor_downloader_cdc_abstract = { |
400 | .bLength = sizeof(thor_downloader_cdc_abstract), | 400 | .bLength = sizeof(thor_downloader_cdc_abstract), |
401 | .bDescriptorType = 0x24, /* CS_INTERFACE */ | 401 | .bDescriptorType = 0x24, /* CS_INTERFACE */ |
402 | .bDescriptorSubType = 0x02, | 402 | .bDescriptorSubType = 0x02, |
403 | .bmCapabilities = 0x00, | 403 | .bmCapabilities = 0x00, |
404 | }; | 404 | }; |
405 | 405 | ||
406 | static struct usb_cdc_union_desc thor_downloader_cdc_union = { | 406 | static struct usb_cdc_union_desc thor_downloader_cdc_union = { |
407 | .bLength = sizeof(thor_downloader_cdc_union), | 407 | .bLength = sizeof(thor_downloader_cdc_union), |
408 | .bDescriptorType = 0x24, /* CS_INTERFACE */ | 408 | .bDescriptorType = 0x24, /* CS_INTERFACE */ |
409 | .bDescriptorSubType = USB_CDC_UNION_TYPE, | 409 | .bDescriptorSubType = USB_CDC_UNION_TYPE, |
410 | }; | 410 | }; |
411 | 411 | ||
412 | static struct usb_endpoint_descriptor fs_int_desc = { | 412 | static struct usb_endpoint_descriptor fs_int_desc = { |
413 | .bLength = USB_DT_ENDPOINT_SIZE, | 413 | .bLength = USB_DT_ENDPOINT_SIZE, |
414 | .bDescriptorType = USB_DT_ENDPOINT, | 414 | .bDescriptorType = USB_DT_ENDPOINT, |
415 | 415 | ||
416 | .bEndpointAddress = 3 | USB_DIR_IN, | 416 | .bEndpointAddress = 3 | USB_DIR_IN, |
417 | .bmAttributes = USB_ENDPOINT_XFER_INT, | 417 | .bmAttributes = USB_ENDPOINT_XFER_INT, |
418 | .wMaxPacketSize = __constant_cpu_to_le16(16), | 418 | .wMaxPacketSize = __constant_cpu_to_le16(16), |
419 | 419 | ||
420 | .bInterval = 0x9, | 420 | .bInterval = 0x9, |
421 | }; | 421 | }; |
422 | 422 | ||
423 | static struct usb_interface_assoc_descriptor | 423 | static struct usb_interface_assoc_descriptor |
424 | thor_iad_descriptor = { | 424 | thor_iad_descriptor = { |
425 | .bLength = sizeof(thor_iad_descriptor), | 425 | .bLength = sizeof(thor_iad_descriptor), |
426 | .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, | 426 | .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, |
427 | 427 | ||
428 | .bFirstInterface = 0, | 428 | .bFirstInterface = 0, |
429 | .bInterfaceCount = 2, /* control + data */ | 429 | .bInterfaceCount = 2, /* control + data */ |
430 | .bFunctionClass = USB_CLASS_COMM, | 430 | .bFunctionClass = USB_CLASS_COMM, |
431 | .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, | 431 | .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, |
432 | .bFunctionProtocol = USB_CDC_PROTO_NONE, | 432 | .bFunctionProtocol = USB_CDC_PROTO_NONE, |
433 | }; | 433 | }; |
434 | 434 | ||
435 | static struct usb_endpoint_descriptor hs_in_desc = { | 435 | static struct usb_endpoint_descriptor hs_in_desc = { |
436 | .bLength = USB_DT_ENDPOINT_SIZE, | 436 | .bLength = USB_DT_ENDPOINT_SIZE, |
437 | .bDescriptorType = USB_DT_ENDPOINT, | 437 | .bDescriptorType = USB_DT_ENDPOINT, |
438 | 438 | ||
439 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 439 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
440 | .wMaxPacketSize = __constant_cpu_to_le16(512), | 440 | .wMaxPacketSize = __constant_cpu_to_le16(512), |
441 | }; | 441 | }; |
442 | 442 | ||
443 | static struct usb_endpoint_descriptor hs_out_desc = { | 443 | static struct usb_endpoint_descriptor hs_out_desc = { |
444 | .bLength = USB_DT_ENDPOINT_SIZE, | 444 | .bLength = USB_DT_ENDPOINT_SIZE, |
445 | .bDescriptorType = USB_DT_ENDPOINT, | 445 | .bDescriptorType = USB_DT_ENDPOINT, |
446 | 446 | ||
447 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 447 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
448 | .wMaxPacketSize = __constant_cpu_to_le16(512), | 448 | .wMaxPacketSize = __constant_cpu_to_le16(512), |
449 | }; | 449 | }; |
450 | 450 | ||
451 | static struct usb_endpoint_descriptor hs_int_desc = { | 451 | static struct usb_endpoint_descriptor hs_int_desc = { |
452 | .bLength = USB_DT_ENDPOINT_SIZE, | 452 | .bLength = USB_DT_ENDPOINT_SIZE, |
453 | .bDescriptorType = USB_DT_ENDPOINT, | 453 | .bDescriptorType = USB_DT_ENDPOINT, |
454 | 454 | ||
455 | .bmAttributes = USB_ENDPOINT_XFER_INT, | 455 | .bmAttributes = USB_ENDPOINT_XFER_INT, |
456 | .wMaxPacketSize = __constant_cpu_to_le16(16), | 456 | .wMaxPacketSize = __constant_cpu_to_le16(16), |
457 | 457 | ||
458 | .bInterval = 0x9, | 458 | .bInterval = 0x9, |
459 | }; | 459 | }; |
460 | 460 | ||
461 | static struct usb_qualifier_descriptor dev_qualifier = { | ||
462 | .bLength = sizeof(dev_qualifier), | ||
463 | .bDescriptorType = USB_DT_DEVICE_QUALIFIER, | ||
464 | |||
465 | .bcdUSB = __constant_cpu_to_le16(0x0200), | ||
466 | .bDeviceClass = USB_CLASS_VENDOR_SPEC, | ||
467 | |||
468 | .bNumConfigurations = 2, | ||
469 | }; | ||
470 | |||
471 | /* | 461 | /* |
472 | * This attribute vendor descriptor is necessary for correct operation with | 462 | * This attribute vendor descriptor is necessary for correct operation with |
473 | * Windows version of THOR download program | 463 | * Windows version of THOR download program |
474 | * | 464 | * |
475 | * It prevents windows driver from sending zero lenght packet (ZLP) after | 465 | * It prevents windows driver from sending zero lenght packet (ZLP) after |
476 | * each THOR_PACKET_SIZE. This assures consistent behaviour with libusb | 466 | * each THOR_PACKET_SIZE. This assures consistent behaviour with libusb |
477 | */ | 467 | */ |
478 | static struct usb_cdc_attribute_vendor_descriptor thor_downloader_cdc_av = { | 468 | static struct usb_cdc_attribute_vendor_descriptor thor_downloader_cdc_av = { |
479 | .bLength = sizeof(thor_downloader_cdc_av), | 469 | .bLength = sizeof(thor_downloader_cdc_av), |
480 | .bDescriptorType = 0x24, | 470 | .bDescriptorType = 0x24, |
481 | .bDescriptorSubType = 0x80, | 471 | .bDescriptorSubType = 0x80, |
482 | .DAUType = 0x0002, | 472 | .DAUType = 0x0002, |
483 | .DAULength = 0x0001, | 473 | .DAULength = 0x0001, |
484 | .DAUValue = 0x00, | 474 | .DAUValue = 0x00, |
485 | }; | 475 | }; |
486 | 476 | ||
487 | static const struct usb_descriptor_header *hs_thor_downloader_function[] = { | 477 | static const struct usb_descriptor_header *hs_thor_downloader_function[] = { |
488 | (struct usb_descriptor_header *)&thor_iad_descriptor, | 478 | (struct usb_descriptor_header *)&thor_iad_descriptor, |
489 | 479 | ||
490 | (struct usb_descriptor_header *)&thor_downloader_intf_int, | 480 | (struct usb_descriptor_header *)&thor_downloader_intf_int, |
491 | (struct usb_descriptor_header *)&thor_downloader_cdc_header, | 481 | (struct usb_descriptor_header *)&thor_downloader_cdc_header, |
492 | (struct usb_descriptor_header *)&thor_downloader_cdc_call, | 482 | (struct usb_descriptor_header *)&thor_downloader_cdc_call, |
493 | (struct usb_descriptor_header *)&thor_downloader_cdc_abstract, | 483 | (struct usb_descriptor_header *)&thor_downloader_cdc_abstract, |
494 | (struct usb_descriptor_header *)&thor_downloader_cdc_union, | 484 | (struct usb_descriptor_header *)&thor_downloader_cdc_union, |
495 | (struct usb_descriptor_header *)&hs_int_desc, | 485 | (struct usb_descriptor_header *)&hs_int_desc, |
496 | 486 | ||
497 | (struct usb_descriptor_header *)&thor_downloader_intf_data, | 487 | (struct usb_descriptor_header *)&thor_downloader_intf_data, |
498 | (struct usb_descriptor_header *)&thor_downloader_cdc_av, | 488 | (struct usb_descriptor_header *)&thor_downloader_cdc_av, |
499 | (struct usb_descriptor_header *)&hs_in_desc, | 489 | (struct usb_descriptor_header *)&hs_in_desc, |
500 | (struct usb_descriptor_header *)&hs_out_desc, | 490 | (struct usb_descriptor_header *)&hs_out_desc, |
501 | NULL, | 491 | NULL, |
502 | }; | 492 | }; |
503 | 493 | ||
504 | /*-------------------------------------------------------------------------*/ | 494 | /*-------------------------------------------------------------------------*/ |
505 | static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length) | 495 | static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length) |
506 | { | 496 | { |
507 | struct usb_request *req; | 497 | struct usb_request *req; |
508 | 498 | ||
509 | req = usb_ep_alloc_request(ep, 0); | 499 | req = usb_ep_alloc_request(ep, 0); |
510 | if (!req) | 500 | if (!req) |
511 | return req; | 501 | return req; |
512 | 502 | ||
513 | req->length = length; | 503 | req->length = length; |
514 | req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, length); | 504 | req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, length); |
515 | if (!req->buf) { | 505 | if (!req->buf) { |
516 | usb_ep_free_request(ep, req); | 506 | usb_ep_free_request(ep, req); |
517 | req = NULL; | 507 | req = NULL; |
518 | } | 508 | } |
519 | 509 | ||
520 | return req; | 510 | return req; |
521 | } | 511 | } |
522 | 512 | ||
523 | static int thor_rx_data(void) | 513 | static int thor_rx_data(void) |
524 | { | 514 | { |
525 | struct thor_dev *dev = thor_func->dev; | 515 | struct thor_dev *dev = thor_func->dev; |
526 | int data_to_rx, tmp, status; | 516 | int data_to_rx, tmp, status; |
527 | 517 | ||
528 | data_to_rx = dev->out_req->length; | 518 | data_to_rx = dev->out_req->length; |
529 | tmp = data_to_rx; | 519 | tmp = data_to_rx; |
530 | do { | 520 | do { |
531 | dev->out_req->length = data_to_rx; | 521 | dev->out_req->length = data_to_rx; |
532 | debug("dev->out_req->length:%d dev->rxdata:%d\n", | 522 | debug("dev->out_req->length:%d dev->rxdata:%d\n", |
533 | dev->out_req->length, dev->rxdata); | 523 | dev->out_req->length, dev->rxdata); |
534 | 524 | ||
535 | status = usb_ep_queue(dev->out_ep, dev->out_req, 0); | 525 | status = usb_ep_queue(dev->out_ep, dev->out_req, 0); |
536 | if (status) { | 526 | if (status) { |
537 | error("kill %s: resubmit %d bytes --> %d", | 527 | error("kill %s: resubmit %d bytes --> %d", |
538 | dev->out_ep->name, dev->out_req->length, status); | 528 | dev->out_ep->name, dev->out_req->length, status); |
539 | usb_ep_set_halt(dev->out_ep); | 529 | usb_ep_set_halt(dev->out_ep); |
540 | return -EAGAIN; | 530 | return -EAGAIN; |
541 | } | 531 | } |
542 | 532 | ||
543 | while (!dev->rxdata) { | 533 | while (!dev->rxdata) { |
544 | usb_gadget_handle_interrupts(); | 534 | usb_gadget_handle_interrupts(); |
545 | if (ctrlc()) | 535 | if (ctrlc()) |
546 | return -1; | 536 | return -1; |
547 | } | 537 | } |
548 | dev->rxdata = 0; | 538 | dev->rxdata = 0; |
549 | data_to_rx -= dev->out_req->actual; | 539 | data_to_rx -= dev->out_req->actual; |
550 | } while (data_to_rx); | 540 | } while (data_to_rx); |
551 | 541 | ||
552 | return tmp; | 542 | return tmp; |
553 | } | 543 | } |
554 | 544 | ||
555 | static void thor_tx_data(unsigned char *data, int len) | 545 | static void thor_tx_data(unsigned char *data, int len) |
556 | { | 546 | { |
557 | struct thor_dev *dev = thor_func->dev; | 547 | struct thor_dev *dev = thor_func->dev; |
558 | unsigned char *ptr = dev->in_req->buf; | 548 | unsigned char *ptr = dev->in_req->buf; |
559 | int status; | 549 | int status; |
560 | 550 | ||
561 | memset(ptr, 0, len); | 551 | memset(ptr, 0, len); |
562 | memcpy(ptr, data, len); | 552 | memcpy(ptr, data, len); |
563 | 553 | ||
564 | dev->in_req->length = len; | 554 | dev->in_req->length = len; |
565 | 555 | ||
566 | debug("%s: dev->in_req->length:%d to_cpy:%d\n", __func__, | 556 | debug("%s: dev->in_req->length:%d to_cpy:%d\n", __func__, |
567 | dev->in_req->length, sizeof(data)); | 557 | dev->in_req->length, sizeof(data)); |
568 | 558 | ||
569 | status = usb_ep_queue(dev->in_ep, dev->in_req, 0); | 559 | status = usb_ep_queue(dev->in_ep, dev->in_req, 0); |
570 | if (status) { | 560 | if (status) { |
571 | error("kill %s: resubmit %d bytes --> %d", | 561 | error("kill %s: resubmit %d bytes --> %d", |
572 | dev->in_ep->name, dev->in_req->length, status); | 562 | dev->in_ep->name, dev->in_req->length, status); |
573 | usb_ep_set_halt(dev->in_ep); | 563 | usb_ep_set_halt(dev->in_ep); |
574 | } | 564 | } |
575 | 565 | ||
576 | /* Wait until tx interrupt received */ | 566 | /* Wait until tx interrupt received */ |
577 | while (!dev->txdata) | 567 | while (!dev->txdata) |
578 | usb_gadget_handle_interrupts(); | 568 | usb_gadget_handle_interrupts(); |
579 | 569 | ||
580 | dev->txdata = 0; | 570 | dev->txdata = 0; |
581 | } | 571 | } |
582 | 572 | ||
583 | static void thor_rx_tx_complete(struct usb_ep *ep, struct usb_request *req) | 573 | static void thor_rx_tx_complete(struct usb_ep *ep, struct usb_request *req) |
584 | { | 574 | { |
585 | struct thor_dev *dev = thor_func->dev; | 575 | struct thor_dev *dev = thor_func->dev; |
586 | int status = req->status; | 576 | int status = req->status; |
587 | 577 | ||
588 | debug("%s: ep_ptr:%p, req_ptr:%p\n", __func__, ep, req); | 578 | debug("%s: ep_ptr:%p, req_ptr:%p\n", __func__, ep, req); |
589 | switch (status) { | 579 | switch (status) { |
590 | case 0: | 580 | case 0: |
591 | if (ep == dev->out_ep) | 581 | if (ep == dev->out_ep) |
592 | dev->rxdata = 1; | 582 | dev->rxdata = 1; |
593 | else | 583 | else |
594 | dev->txdata = 1; | 584 | dev->txdata = 1; |
595 | 585 | ||
596 | break; | 586 | break; |
597 | 587 | ||
598 | /* this endpoint is normally active while we're configured */ | 588 | /* this endpoint is normally active while we're configured */ |
599 | case -ECONNABORTED: /* hardware forced ep reset */ | 589 | case -ECONNABORTED: /* hardware forced ep reset */ |
600 | case -ECONNRESET: /* request dequeued */ | 590 | case -ECONNRESET: /* request dequeued */ |
601 | case -ESHUTDOWN: /* disconnect from host */ | 591 | case -ESHUTDOWN: /* disconnect from host */ |
602 | case -EREMOTEIO: /* short read */ | 592 | case -EREMOTEIO: /* short read */ |
603 | case -EOVERFLOW: | 593 | case -EOVERFLOW: |
604 | error("ERROR:%d", status); | 594 | error("ERROR:%d", status); |
605 | break; | 595 | break; |
606 | } | 596 | } |
607 | 597 | ||
608 | debug("%s complete --> %d, %d/%d\n", ep->name, | 598 | debug("%s complete --> %d, %d/%d\n", ep->name, |
609 | status, req->actual, req->length); | 599 | status, req->actual, req->length); |
610 | } | 600 | } |
611 | 601 | ||
612 | static struct usb_request *thor_start_ep(struct usb_ep *ep) | 602 | static struct usb_request *thor_start_ep(struct usb_ep *ep) |
613 | { | 603 | { |
614 | struct usb_request *req; | 604 | struct usb_request *req; |
615 | 605 | ||
616 | req = alloc_ep_req(ep, THOR_PACKET_SIZE); | 606 | req = alloc_ep_req(ep, THOR_PACKET_SIZE); |
617 | debug("%s: ep:%p req:%p\n", __func__, ep, req); | 607 | debug("%s: ep:%p req:%p\n", __func__, ep, req); |
618 | 608 | ||
619 | if (!req) | 609 | if (!req) |
620 | return NULL; | 610 | return NULL; |
621 | 611 | ||
622 | memset(req->buf, 0, req->length); | 612 | memset(req->buf, 0, req->length); |
623 | req->complete = thor_rx_tx_complete; | 613 | req->complete = thor_rx_tx_complete; |
624 | 614 | ||
625 | return req; | 615 | return req; |
626 | } | 616 | } |
627 | 617 | ||
628 | static void thor_setup_complete(struct usb_ep *ep, struct usb_request *req) | 618 | static void thor_setup_complete(struct usb_ep *ep, struct usb_request *req) |
629 | { | 619 | { |
630 | if (req->status || req->actual != req->length) | 620 | if (req->status || req->actual != req->length) |
631 | debug("setup complete --> %d, %d/%d\n", | 621 | debug("setup complete --> %d, %d/%d\n", |
632 | req->status, req->actual, req->length); | 622 | req->status, req->actual, req->length); |
633 | } | 623 | } |
634 | 624 | ||
635 | static int | 625 | static int |
636 | thor_func_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) | 626 | thor_func_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) |
637 | { | 627 | { |
638 | struct thor_dev *dev = thor_func->dev; | 628 | struct thor_dev *dev = thor_func->dev; |
639 | struct usb_request *req = dev->req; | 629 | struct usb_request *req = dev->req; |
640 | struct usb_gadget *gadget = dev->gadget; | 630 | struct usb_gadget *gadget = dev->gadget; |
641 | int value = 0; | 631 | int value = 0; |
642 | 632 | ||
643 | u16 len = le16_to_cpu(ctrl->wLength); | 633 | u16 len = le16_to_cpu(ctrl->wLength); |
644 | 634 | ||
645 | debug("Req_Type: 0x%x Req: 0x%x wValue: 0x%x wIndex: 0x%x wLen: 0x%x\n", | 635 | debug("Req_Type: 0x%x Req: 0x%x wValue: 0x%x wIndex: 0x%x wLen: 0x%x\n", |
646 | ctrl->bRequestType, ctrl->bRequest, ctrl->wValue, ctrl->wIndex, | 636 | ctrl->bRequestType, ctrl->bRequest, ctrl->wValue, ctrl->wIndex, |
647 | ctrl->wLength); | 637 | ctrl->wLength); |
648 | 638 | ||
649 | switch (ctrl->bRequest) { | 639 | switch (ctrl->bRequest) { |
650 | case USB_CDC_REQ_SET_CONTROL_LINE_STATE: | 640 | case USB_CDC_REQ_SET_CONTROL_LINE_STATE: |
651 | value = 0; | 641 | value = 0; |
652 | break; | 642 | break; |
653 | case USB_CDC_REQ_SET_LINE_CODING: | 643 | case USB_CDC_REQ_SET_LINE_CODING: |
654 | value = len; | 644 | value = len; |
655 | /* Line Coding set done = configuration done */ | 645 | /* Line Coding set done = configuration done */ |
656 | thor_func->dev->configuration_done = 1; | 646 | thor_func->dev->configuration_done = 1; |
657 | break; | 647 | break; |
658 | 648 | ||
659 | default: | 649 | default: |
660 | error("thor_setup: unknown request: %d", ctrl->bRequest); | 650 | error("thor_setup: unknown request: %d", ctrl->bRequest); |
661 | } | 651 | } |
662 | 652 | ||
663 | if (value >= 0) { | 653 | if (value >= 0) { |
664 | req->length = value; | 654 | req->length = value; |
665 | req->zero = value < len; | 655 | req->zero = value < len; |
666 | value = usb_ep_queue(gadget->ep0, req, 0); | 656 | value = usb_ep_queue(gadget->ep0, req, 0); |
667 | if (value < 0) { | 657 | if (value < 0) { |
668 | debug("%s: ep_queue: %d\n", __func__, value); | 658 | debug("%s: ep_queue: %d\n", __func__, value); |
669 | req->status = 0; | 659 | req->status = 0; |
670 | } | 660 | } |
671 | } | 661 | } |
672 | 662 | ||
673 | return value; | 663 | return value; |
674 | } | 664 | } |
675 | 665 | ||
676 | /* Specific to the THOR protocol */ | 666 | /* Specific to the THOR protocol */ |
677 | static void thor_set_dma(void *addr, int len) | 667 | static void thor_set_dma(void *addr, int len) |
678 | { | 668 | { |
679 | struct thor_dev *dev = thor_func->dev; | 669 | struct thor_dev *dev = thor_func->dev; |
680 | 670 | ||
681 | debug("in_req:%p, out_req:%p\n", dev->in_req, dev->out_req); | 671 | debug("in_req:%p, out_req:%p\n", dev->in_req, dev->out_req); |
682 | debug("addr:%p, len:%d\n", addr, len); | 672 | debug("addr:%p, len:%d\n", addr, len); |
683 | 673 | ||
684 | dev->out_req->buf = addr; | 674 | dev->out_req->buf = addr; |
685 | dev->out_req->length = len; | 675 | dev->out_req->length = len; |
686 | } | 676 | } |
687 | 677 | ||
688 | int thor_init(void) | 678 | int thor_init(void) |
689 | { | 679 | { |
690 | struct thor_dev *dev = thor_func->dev; | 680 | struct thor_dev *dev = thor_func->dev; |
691 | 681 | ||
692 | /* Wait for a device enumeration and configuration settings */ | 682 | /* Wait for a device enumeration and configuration settings */ |
693 | debug("THOR enumeration/configuration setting....\n"); | 683 | debug("THOR enumeration/configuration setting....\n"); |
694 | while (!dev->configuration_done) | 684 | while (!dev->configuration_done) |
695 | usb_gadget_handle_interrupts(); | 685 | usb_gadget_handle_interrupts(); |
696 | 686 | ||
697 | thor_set_dma(thor_rx_data_buf, strlen("THOR")); | 687 | thor_set_dma(thor_rx_data_buf, strlen("THOR")); |
698 | /* detect the download request from Host PC */ | 688 | /* detect the download request from Host PC */ |
699 | if (thor_rx_data() < 0) { | 689 | if (thor_rx_data() < 0) { |
700 | printf("%s: Data not received!\n", __func__); | 690 | printf("%s: Data not received!\n", __func__); |
701 | return -1; | 691 | return -1; |
702 | } | 692 | } |
703 | 693 | ||
704 | if (!strncmp((char *)thor_rx_data_buf, "THOR", strlen("THOR"))) { | 694 | if (!strncmp((char *)thor_rx_data_buf, "THOR", strlen("THOR"))) { |
705 | puts("Download request from the Host PC\n"); | 695 | puts("Download request from the Host PC\n"); |
706 | udelay(30 * 1000); /* 30 ms */ | 696 | udelay(30 * 1000); /* 30 ms */ |
707 | 697 | ||
708 | strcpy((char *)thor_tx_data_buf, "ROHT"); | 698 | strcpy((char *)thor_tx_data_buf, "ROHT"); |
709 | thor_tx_data(thor_tx_data_buf, strlen("ROHT")); | 699 | thor_tx_data(thor_tx_data_buf, strlen("ROHT")); |
710 | } else { | 700 | } else { |
711 | puts("Wrong reply information\n"); | 701 | puts("Wrong reply information\n"); |
712 | return -1; | 702 | return -1; |
713 | } | 703 | } |
714 | 704 | ||
715 | return 0; | 705 | return 0; |
716 | } | 706 | } |
717 | 707 | ||
718 | int thor_handle(void) | 708 | int thor_handle(void) |
719 | { | 709 | { |
720 | int ret; | 710 | int ret; |
721 | 711 | ||
722 | /* receive the data from Host PC */ | 712 | /* receive the data from Host PC */ |
723 | while (1) { | 713 | while (1) { |
724 | thor_set_dma(thor_rx_data_buf, sizeof(struct rqt_box)); | 714 | thor_set_dma(thor_rx_data_buf, sizeof(struct rqt_box)); |
725 | ret = thor_rx_data(); | 715 | ret = thor_rx_data(); |
726 | 716 | ||
727 | if (ret > 0) { | 717 | if (ret > 0) { |
728 | ret = process_data(); | 718 | ret = process_data(); |
729 | if (ret < 0) | 719 | if (ret < 0) |
730 | return ret; | 720 | return ret; |
731 | } else { | 721 | } else { |
732 | printf("%s: No data received!\n", __func__); | 722 | printf("%s: No data received!\n", __func__); |
733 | break; | 723 | break; |
734 | } | 724 | } |
735 | } | 725 | } |
736 | 726 | ||
737 | return 0; | 727 | return 0; |
738 | } | 728 | } |
739 | 729 | ||
740 | static int thor_func_bind(struct usb_configuration *c, struct usb_function *f) | 730 | static int thor_func_bind(struct usb_configuration *c, struct usb_function *f) |
741 | { | 731 | { |
742 | struct usb_gadget *gadget = c->cdev->gadget; | 732 | struct usb_gadget *gadget = c->cdev->gadget; |
743 | struct f_thor *f_thor = func_to_thor(f); | 733 | struct f_thor *f_thor = func_to_thor(f); |
744 | struct thor_dev *dev; | 734 | struct thor_dev *dev; |
745 | struct usb_ep *ep; | 735 | struct usb_ep *ep; |
746 | int status; | 736 | int status; |
747 | 737 | ||
748 | thor_func = f_thor; | 738 | thor_func = f_thor; |
749 | dev = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*dev)); | 739 | dev = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*dev)); |
750 | if (!dev) | 740 | if (!dev) |
751 | return -ENOMEM; | 741 | return -ENOMEM; |
752 | 742 | ||
753 | memset(dev, 0, sizeof(*dev)); | 743 | memset(dev, 0, sizeof(*dev)); |
754 | dev->gadget = gadget; | 744 | dev->gadget = gadget; |
755 | f_thor->dev = dev; | 745 | f_thor->dev = dev; |
756 | 746 | ||
757 | debug("%s: usb_configuration: 0x%p usb_function: 0x%p\n", | 747 | debug("%s: usb_configuration: 0x%p usb_function: 0x%p\n", |
758 | __func__, c, f); | 748 | __func__, c, f); |
759 | debug("f_thor: 0x%p thor: 0x%p\n", f_thor, dev); | 749 | debug("f_thor: 0x%p thor: 0x%p\n", f_thor, dev); |
760 | 750 | ||
761 | /* EP0 */ | 751 | /* EP0 */ |
762 | /* preallocate control response and buffer */ | 752 | /* preallocate control response and buffer */ |
763 | dev->req = usb_ep_alloc_request(gadget->ep0, 0); | 753 | dev->req = usb_ep_alloc_request(gadget->ep0, 0); |
764 | if (!dev->req) { | 754 | if (!dev->req) { |
765 | status = -ENOMEM; | 755 | status = -ENOMEM; |
766 | goto fail; | 756 | goto fail; |
767 | } | 757 | } |
768 | dev->req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, | 758 | dev->req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, |
769 | gadget->ep0->maxpacket); | 759 | gadget->ep0->maxpacket); |
770 | if (!dev->req->buf) { | 760 | if (!dev->req->buf) { |
771 | status = -ENOMEM; | 761 | status = -ENOMEM; |
772 | goto fail; | 762 | goto fail; |
773 | } | 763 | } |
774 | 764 | ||
775 | dev->req->complete = thor_setup_complete; | 765 | dev->req->complete = thor_setup_complete; |
776 | 766 | ||
777 | /* DYNAMIC interface numbers assignments */ | 767 | /* DYNAMIC interface numbers assignments */ |
778 | status = usb_interface_id(c, f); | 768 | status = usb_interface_id(c, f); |
779 | 769 | ||
780 | if (status < 0) | 770 | if (status < 0) |
781 | goto fail; | 771 | goto fail; |
782 | 772 | ||
783 | thor_downloader_intf_int.bInterfaceNumber = status; | 773 | thor_downloader_intf_int.bInterfaceNumber = status; |
784 | thor_downloader_cdc_union.bMasterInterface0 = status; | 774 | thor_downloader_cdc_union.bMasterInterface0 = status; |
785 | 775 | ||
786 | status = usb_interface_id(c, f); | 776 | status = usb_interface_id(c, f); |
787 | 777 | ||
788 | if (status < 0) | 778 | if (status < 0) |
789 | goto fail; | 779 | goto fail; |
790 | 780 | ||
791 | thor_downloader_intf_data.bInterfaceNumber = status; | 781 | thor_downloader_intf_data.bInterfaceNumber = status; |
792 | thor_downloader_cdc_union.bSlaveInterface0 = status; | 782 | thor_downloader_cdc_union.bSlaveInterface0 = status; |
793 | 783 | ||
794 | /* allocate instance-specific endpoints */ | 784 | /* allocate instance-specific endpoints */ |
795 | ep = usb_ep_autoconfig(gadget, &fs_in_desc); | 785 | ep = usb_ep_autoconfig(gadget, &fs_in_desc); |
796 | if (!ep) { | 786 | if (!ep) { |
797 | status = -ENODEV; | 787 | status = -ENODEV; |
798 | goto fail; | 788 | goto fail; |
799 | } | 789 | } |
800 | 790 | ||
801 | if (gadget_is_dualspeed(gadget)) { | 791 | if (gadget_is_dualspeed(gadget)) { |
802 | hs_in_desc.bEndpointAddress = | 792 | hs_in_desc.bEndpointAddress = |
803 | fs_in_desc.bEndpointAddress; | 793 | fs_in_desc.bEndpointAddress; |
804 | } | 794 | } |
805 | 795 | ||
806 | dev->in_ep = ep; /* Store IN EP for enabling @ setup */ | 796 | dev->in_ep = ep; /* Store IN EP for enabling @ setup */ |
807 | 797 | ||
808 | ep = usb_ep_autoconfig(gadget, &fs_out_desc); | 798 | ep = usb_ep_autoconfig(gadget, &fs_out_desc); |
809 | if (!ep) { | 799 | if (!ep) { |
810 | status = -ENODEV; | 800 | status = -ENODEV; |
811 | goto fail; | 801 | goto fail; |
812 | } | 802 | } |
813 | 803 | ||
814 | if (gadget_is_dualspeed(gadget)) | 804 | if (gadget_is_dualspeed(gadget)) |
815 | hs_out_desc.bEndpointAddress = | 805 | hs_out_desc.bEndpointAddress = |
816 | fs_out_desc.bEndpointAddress; | 806 | fs_out_desc.bEndpointAddress; |
817 | 807 | ||
818 | dev->out_ep = ep; /* Store OUT EP for enabling @ setup */ | 808 | dev->out_ep = ep; /* Store OUT EP for enabling @ setup */ |
819 | 809 | ||
820 | ep = usb_ep_autoconfig(gadget, &fs_int_desc); | 810 | ep = usb_ep_autoconfig(gadget, &fs_int_desc); |
821 | if (!ep) { | 811 | if (!ep) { |
822 | status = -ENODEV; | 812 | status = -ENODEV; |
823 | goto fail; | 813 | goto fail; |
824 | } | 814 | } |
825 | 815 | ||
826 | dev->int_ep = ep; | 816 | dev->int_ep = ep; |
827 | 817 | ||
828 | if (gadget_is_dualspeed(gadget)) { | 818 | if (gadget_is_dualspeed(gadget)) { |
829 | hs_int_desc.bEndpointAddress = | 819 | hs_int_desc.bEndpointAddress = |
830 | fs_int_desc.bEndpointAddress; | 820 | fs_int_desc.bEndpointAddress; |
831 | 821 | ||
832 | f->hs_descriptors = (struct usb_descriptor_header **) | 822 | f->hs_descriptors = (struct usb_descriptor_header **) |
833 | &hs_thor_downloader_function; | 823 | &hs_thor_downloader_function; |
834 | 824 | ||
835 | if (!f->hs_descriptors) | 825 | if (!f->hs_descriptors) |
836 | goto fail; | 826 | goto fail; |
837 | } | 827 | } |
838 | 828 | ||
839 | debug("%s: out_ep:%p out_req:%p\n", __func__, | 829 | debug("%s: out_ep:%p out_req:%p\n", __func__, |
840 | dev->out_ep, dev->out_req); | 830 | dev->out_ep, dev->out_req); |
841 | 831 | ||
842 | return 0; | 832 | return 0; |
843 | 833 | ||
844 | fail: | 834 | fail: |
845 | free(dev); | 835 | free(dev); |
846 | return status; | 836 | return status; |
847 | } | 837 | } |
848 | 838 | ||
849 | static void free_ep_req(struct usb_ep *ep, struct usb_request *req) | 839 | static void free_ep_req(struct usb_ep *ep, struct usb_request *req) |
850 | { | 840 | { |
851 | free(req->buf); | 841 | free(req->buf); |
852 | usb_ep_free_request(ep, req); | 842 | usb_ep_free_request(ep, req); |
853 | } | 843 | } |
854 | 844 | ||
855 | static void thor_unbind(struct usb_configuration *c, struct usb_function *f) | 845 | static void thor_unbind(struct usb_configuration *c, struct usb_function *f) |
856 | { | 846 | { |
857 | struct f_thor *f_thor = func_to_thor(f); | 847 | struct f_thor *f_thor = func_to_thor(f); |
858 | struct thor_dev *dev = f_thor->dev; | 848 | struct thor_dev *dev = f_thor->dev; |
859 | 849 | ||
860 | free(dev); | 850 | free(dev); |
861 | memset(thor_func, 0, sizeof(*thor_func)); | 851 | memset(thor_func, 0, sizeof(*thor_func)); |
862 | thor_func = NULL; | 852 | thor_func = NULL; |
863 | } | 853 | } |
864 | 854 | ||
865 | static void thor_func_disable(struct usb_function *f) | 855 | static void thor_func_disable(struct usb_function *f) |
866 | { | 856 | { |
867 | struct f_thor *f_thor = func_to_thor(f); | 857 | struct f_thor *f_thor = func_to_thor(f); |
868 | struct thor_dev *dev = f_thor->dev; | 858 | struct thor_dev *dev = f_thor->dev; |
869 | 859 | ||
870 | debug("%s:\n", __func__); | 860 | debug("%s:\n", __func__); |
871 | 861 | ||
872 | /* Avoid freeing memory when ep is still claimed */ | 862 | /* Avoid freeing memory when ep is still claimed */ |
873 | if (dev->in_ep->driver_data) { | 863 | if (dev->in_ep->driver_data) { |
874 | free_ep_req(dev->in_ep, dev->in_req); | 864 | free_ep_req(dev->in_ep, dev->in_req); |
875 | usb_ep_disable(dev->in_ep); | 865 | usb_ep_disable(dev->in_ep); |
876 | dev->in_ep->driver_data = NULL; | 866 | dev->in_ep->driver_data = NULL; |
877 | } | 867 | } |
878 | 868 | ||
879 | if (dev->out_ep->driver_data) { | 869 | if (dev->out_ep->driver_data) { |
880 | dev->out_req->buf = NULL; | 870 | dev->out_req->buf = NULL; |
881 | usb_ep_free_request(dev->out_ep, dev->out_req); | 871 | usb_ep_free_request(dev->out_ep, dev->out_req); |
882 | usb_ep_disable(dev->out_ep); | 872 | usb_ep_disable(dev->out_ep); |
883 | dev->out_ep->driver_data = NULL; | 873 | dev->out_ep->driver_data = NULL; |
884 | } | 874 | } |
885 | 875 | ||
886 | if (dev->int_ep->driver_data) { | 876 | if (dev->int_ep->driver_data) { |
887 | usb_ep_disable(dev->int_ep); | 877 | usb_ep_disable(dev->int_ep); |
888 | dev->int_ep->driver_data = NULL; | 878 | dev->int_ep->driver_data = NULL; |
889 | } | 879 | } |
890 | } | 880 | } |
891 | 881 | ||
892 | static int thor_eps_setup(struct usb_function *f) | 882 | static int thor_eps_setup(struct usb_function *f) |
893 | { | 883 | { |
894 | struct usb_composite_dev *cdev = f->config->cdev; | 884 | struct usb_composite_dev *cdev = f->config->cdev; |
895 | struct usb_gadget *gadget = cdev->gadget; | 885 | struct usb_gadget *gadget = cdev->gadget; |
896 | struct thor_dev *dev = thor_func->dev; | 886 | struct thor_dev *dev = thor_func->dev; |
897 | struct usb_endpoint_descriptor *d; | 887 | struct usb_endpoint_descriptor *d; |
898 | struct usb_request *req; | 888 | struct usb_request *req; |
899 | struct usb_ep *ep; | 889 | struct usb_ep *ep; |
900 | int result; | 890 | int result; |
901 | 891 | ||
902 | ep = dev->in_ep; | 892 | ep = dev->in_ep; |
903 | d = ep_desc(gadget, &hs_in_desc, &fs_in_desc); | 893 | d = ep_desc(gadget, &hs_in_desc, &fs_in_desc); |
904 | debug("(d)bEndpointAddress: 0x%x\n", d->bEndpointAddress); | 894 | debug("(d)bEndpointAddress: 0x%x\n", d->bEndpointAddress); |
905 | 895 | ||
906 | result = usb_ep_enable(ep, d); | 896 | result = usb_ep_enable(ep, d); |
907 | if (result) | 897 | if (result) |
908 | goto exit; | 898 | goto exit; |
909 | 899 | ||
910 | ep->driver_data = cdev; /* claim */ | 900 | ep->driver_data = cdev; /* claim */ |
911 | req = thor_start_ep(ep); | 901 | req = thor_start_ep(ep); |
912 | if (!req) { | 902 | if (!req) { |
913 | usb_ep_disable(ep); | 903 | usb_ep_disable(ep); |
914 | result = -EIO; | 904 | result = -EIO; |
915 | goto exit; | 905 | goto exit; |
916 | } | 906 | } |
917 | 907 | ||
918 | dev->in_req = req; | 908 | dev->in_req = req; |
919 | ep = dev->out_ep; | 909 | ep = dev->out_ep; |
920 | d = ep_desc(gadget, &hs_out_desc, &fs_out_desc); | 910 | d = ep_desc(gadget, &hs_out_desc, &fs_out_desc); |
921 | debug("(d)bEndpointAddress: 0x%x\n", d->bEndpointAddress); | 911 | debug("(d)bEndpointAddress: 0x%x\n", d->bEndpointAddress); |
922 | 912 | ||
923 | result = usb_ep_enable(ep, d); | 913 | result = usb_ep_enable(ep, d); |
924 | if (result) | 914 | if (result) |
925 | goto exit; | 915 | goto exit; |
926 | 916 | ||
927 | ep->driver_data = cdev; /* claim */ | 917 | ep->driver_data = cdev; /* claim */ |
928 | req = thor_start_ep(ep); | 918 | req = thor_start_ep(ep); |
929 | if (!req) { | 919 | if (!req) { |
930 | usb_ep_disable(ep); | 920 | usb_ep_disable(ep); |
931 | result = -EIO; | 921 | result = -EIO; |
932 | goto exit; | 922 | goto exit; |
933 | } | 923 | } |
934 | 924 | ||
935 | dev->out_req = req; | 925 | dev->out_req = req; |
936 | /* ACM control EP */ | 926 | /* ACM control EP */ |
937 | ep = dev->int_ep; | 927 | ep = dev->int_ep; |
938 | ep->driver_data = cdev; /* claim */ | 928 | ep->driver_data = cdev; /* claim */ |
939 | 929 | ||
940 | exit: | 930 | exit: |
941 | return result; | 931 | return result; |
942 | } | 932 | } |
943 | 933 | ||
944 | static int thor_func_set_alt(struct usb_function *f, | 934 | static int thor_func_set_alt(struct usb_function *f, |
945 | unsigned intf, unsigned alt) | 935 | unsigned intf, unsigned alt) |
946 | { | 936 | { |
947 | struct thor_dev *dev = thor_func->dev; | 937 | struct thor_dev *dev = thor_func->dev; |
948 | int result; | 938 | int result; |
949 | 939 | ||
950 | debug("%s: func: %s intf: %d alt: %d\n", | 940 | debug("%s: func: %s intf: %d alt: %d\n", |
951 | __func__, f->name, intf, alt); | 941 | __func__, f->name, intf, alt); |
952 | 942 | ||
953 | switch (intf) { | 943 | switch (intf) { |
954 | case 0: | 944 | case 0: |
955 | debug("ACM INTR interface\n"); | 945 | debug("ACM INTR interface\n"); |
956 | break; | 946 | break; |
957 | case 1: | 947 | case 1: |
958 | debug("Communication Data interface\n"); | 948 | debug("Communication Data interface\n"); |
959 | result = thor_eps_setup(f); | 949 | result = thor_eps_setup(f); |
960 | if (result) | 950 | if (result) |
961 | error("%s: EPs setup failed!", __func__); | 951 | error("%s: EPs setup failed!", __func__); |
962 | dev->configuration_done = 1; | 952 | dev->configuration_done = 1; |
963 | break; | 953 | break; |
964 | } | 954 | } |
965 | 955 | ||
966 | return 0; | 956 | return 0; |
967 | } | 957 | } |
968 | 958 | ||
969 | static int thor_func_init(struct usb_configuration *c) | 959 | static int thor_func_init(struct usb_configuration *c) |
970 | { | 960 | { |
971 | struct f_thor *f_thor; | 961 | struct f_thor *f_thor; |
972 | int status; | 962 | int status; |
973 | 963 | ||
974 | debug("%s: cdev: 0x%p\n", __func__, c->cdev); | 964 | debug("%s: cdev: 0x%p\n", __func__, c->cdev); |
975 | 965 | ||
976 | f_thor = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*f_thor)); | 966 | f_thor = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*f_thor)); |
977 | if (!f_thor) | 967 | if (!f_thor) |
978 | return -ENOMEM; | 968 | return -ENOMEM; |
979 | 969 | ||
980 | memset(f_thor, 0, sizeof(*f_thor)); | 970 | memset(f_thor, 0, sizeof(*f_thor)); |
981 | 971 | ||
982 | f_thor->usb_function.name = "f_thor"; | 972 | f_thor->usb_function.name = "f_thor"; |
983 | f_thor->usb_function.bind = thor_func_bind; | 973 | f_thor->usb_function.bind = thor_func_bind; |
984 | f_thor->usb_function.unbind = thor_unbind; | 974 | f_thor->usb_function.unbind = thor_unbind; |
985 | f_thor->usb_function.setup = thor_func_setup; | 975 | f_thor->usb_function.setup = thor_func_setup; |
986 | f_thor->usb_function.set_alt = thor_func_set_alt; | 976 | f_thor->usb_function.set_alt = thor_func_set_alt; |
987 | f_thor->usb_function.disable = thor_func_disable; | 977 | f_thor->usb_function.disable = thor_func_disable; |
988 | 978 | ||
989 | status = usb_add_function(c, &f_thor->usb_function); | 979 | status = usb_add_function(c, &f_thor->usb_function); |
990 | if (status) | 980 | if (status) |
991 | free(f_thor); | 981 | free(f_thor); |
992 | 982 | ||
993 | return status; | 983 | return status; |
994 | } | 984 | } |
995 | 985 | ||
996 | int thor_add(struct usb_configuration *c) | 986 | int thor_add(struct usb_configuration *c) |
997 | { | 987 | { |
998 | debug("%s:\n", __func__); | 988 | debug("%s:\n", __func__); |
999 | return thor_func_init(c); | 989 | return thor_func_init(c); |
1000 | } | 990 | } |
1001 | 991 | ||
1002 | DECLARE_GADGET_BIND_CALLBACK(usb_dnl_thor, thor_add); | 992 | DECLARE_GADGET_BIND_CALLBACK(usb_dnl_thor, thor_add); |
1003 | 993 |
drivers/usb/host/ehci-hcd.c
1 | /*- | 1 | /*- |
2 | * Copyright (c) 2007-2008, Juniper Networks, Inc. | 2 | * Copyright (c) 2007-2008, Juniper Networks, Inc. |
3 | * Copyright (c) 2008, Excito Elektronik i Skรฅne AB | 3 | * Copyright (c) 2008, Excito Elektronik i Skรฅne AB |
4 | * Copyright (c) 2008, Michael Trimarchi <trimarchimichael@yahoo.it> | 4 | * Copyright (c) 2008, Michael Trimarchi <trimarchimichael@yahoo.it> |
5 | * | 5 | * |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU General Public License as | 9 | * modify it under the terms of the GNU General Public License as |
10 | * published by the Free Software Foundation version 2 of | 10 | * published by the Free Software Foundation version 2 of |
11 | * the License. | 11 | * the License. |
12 | * | 12 | * |
13 | * This program is distributed in the hope that it will be useful, | 13 | * This program is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
17 | * | 17 | * |
18 | * You should have received a copy of the GNU General Public License | 18 | * You should have received a copy of the GNU General Public License |
19 | * along with this program; if not, write to the Free Software | 19 | * along with this program; if not, write to the Free Software |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
21 | * MA 02111-1307 USA | 21 | * MA 02111-1307 USA |
22 | */ | 22 | */ |
23 | #include <common.h> | 23 | #include <common.h> |
24 | #include <errno.h> | 24 | #include <errno.h> |
25 | #include <asm/byteorder.h> | 25 | #include <asm/byteorder.h> |
26 | #include <asm/unaligned.h> | 26 | #include <asm/unaligned.h> |
27 | #include <usb.h> | 27 | #include <usb.h> |
28 | #include <asm/io.h> | 28 | #include <asm/io.h> |
29 | #include <malloc.h> | 29 | #include <malloc.h> |
30 | #include <watchdog.h> | 30 | #include <watchdog.h> |
31 | #include <linux/compiler.h> | 31 | #include <linux/compiler.h> |
32 | 32 | ||
33 | #include "ehci.h" | 33 | #include "ehci.h" |
34 | 34 | ||
35 | #ifndef CONFIG_USB_MAX_CONTROLLER_COUNT | 35 | #ifndef CONFIG_USB_MAX_CONTROLLER_COUNT |
36 | #define CONFIG_USB_MAX_CONTROLLER_COUNT 1 | 36 | #define CONFIG_USB_MAX_CONTROLLER_COUNT 1 |
37 | #endif | 37 | #endif |
38 | 38 | ||
39 | /* | 39 | /* |
40 | * EHCI spec page 20 says that the HC may take up to 16 uFrames (= 4ms) to halt. | 40 | * EHCI spec page 20 says that the HC may take up to 16 uFrames (= 4ms) to halt. |
41 | * Let's time out after 8 to have a little safety margin on top of that. | 41 | * Let's time out after 8 to have a little safety margin on top of that. |
42 | */ | 42 | */ |
43 | #define HCHALT_TIMEOUT (8 * 1000) | 43 | #define HCHALT_TIMEOUT (8 * 1000) |
44 | 44 | ||
45 | static struct ehci_ctrl ehcic[CONFIG_USB_MAX_CONTROLLER_COUNT]; | 45 | static struct ehci_ctrl ehcic[CONFIG_USB_MAX_CONTROLLER_COUNT]; |
46 | 46 | ||
47 | #define ALIGN_END_ADDR(type, ptr, size) \ | 47 | #define ALIGN_END_ADDR(type, ptr, size) \ |
48 | ((uint32_t)(ptr) + roundup((size) * sizeof(type), USB_DMA_MINALIGN)) | 48 | ((uint32_t)(ptr) + roundup((size) * sizeof(type), USB_DMA_MINALIGN)) |
49 | 49 | ||
50 | static struct descriptor { | 50 | static struct descriptor { |
51 | struct usb_hub_descriptor hub; | 51 | struct usb_hub_descriptor hub; |
52 | struct usb_device_descriptor device; | 52 | struct usb_device_descriptor device; |
53 | struct usb_linux_config_descriptor config; | 53 | struct usb_linux_config_descriptor config; |
54 | struct usb_linux_interface_descriptor interface; | 54 | struct usb_linux_interface_descriptor interface; |
55 | struct usb_endpoint_descriptor endpoint; | 55 | struct usb_endpoint_descriptor endpoint; |
56 | } __attribute__ ((packed)) descriptor = { | 56 | } __attribute__ ((packed)) descriptor = { |
57 | { | 57 | { |
58 | 0x8, /* bDescLength */ | 58 | 0x8, /* bDescLength */ |
59 | 0x29, /* bDescriptorType: hub descriptor */ | 59 | 0x29, /* bDescriptorType: hub descriptor */ |
60 | 2, /* bNrPorts -- runtime modified */ | 60 | 2, /* bNrPorts -- runtime modified */ |
61 | 0, /* wHubCharacteristics */ | 61 | 0, /* wHubCharacteristics */ |
62 | 10, /* bPwrOn2PwrGood */ | 62 | 10, /* bPwrOn2PwrGood */ |
63 | 0, /* bHubCntrCurrent */ | 63 | 0, /* bHubCntrCurrent */ |
64 | {}, /* Device removable */ | 64 | {}, /* Device removable */ |
65 | {} /* at most 7 ports! XXX */ | 65 | {} /* at most 7 ports! XXX */ |
66 | }, | 66 | }, |
67 | { | 67 | { |
68 | 0x12, /* bLength */ | 68 | 0x12, /* bLength */ |
69 | 1, /* bDescriptorType: UDESC_DEVICE */ | 69 | 1, /* bDescriptorType: UDESC_DEVICE */ |
70 | cpu_to_le16(0x0200), /* bcdUSB: v2.0 */ | 70 | cpu_to_le16(0x0200), /* bcdUSB: v2.0 */ |
71 | 9, /* bDeviceClass: UDCLASS_HUB */ | 71 | 9, /* bDeviceClass: UDCLASS_HUB */ |
72 | 0, /* bDeviceSubClass: UDSUBCLASS_HUB */ | 72 | 0, /* bDeviceSubClass: UDSUBCLASS_HUB */ |
73 | 1, /* bDeviceProtocol: UDPROTO_HSHUBSTT */ | 73 | 1, /* bDeviceProtocol: UDPROTO_HSHUBSTT */ |
74 | 64, /* bMaxPacketSize: 64 bytes */ | 74 | 64, /* bMaxPacketSize: 64 bytes */ |
75 | 0x0000, /* idVendor */ | 75 | 0x0000, /* idVendor */ |
76 | 0x0000, /* idProduct */ | 76 | 0x0000, /* idProduct */ |
77 | cpu_to_le16(0x0100), /* bcdDevice */ | 77 | cpu_to_le16(0x0100), /* bcdDevice */ |
78 | 1, /* iManufacturer */ | 78 | 1, /* iManufacturer */ |
79 | 2, /* iProduct */ | 79 | 2, /* iProduct */ |
80 | 0, /* iSerialNumber */ | 80 | 0, /* iSerialNumber */ |
81 | 1 /* bNumConfigurations: 1 */ | 81 | 1 /* bNumConfigurations: 1 */ |
82 | }, | 82 | }, |
83 | { | 83 | { |
84 | 0x9, | 84 | 0x9, |
85 | 2, /* bDescriptorType: UDESC_CONFIG */ | 85 | 2, /* bDescriptorType: UDESC_CONFIG */ |
86 | cpu_to_le16(0x19), | 86 | cpu_to_le16(0x19), |
87 | 1, /* bNumInterface */ | 87 | 1, /* bNumInterface */ |
88 | 1, /* bConfigurationValue */ | 88 | 1, /* bConfigurationValue */ |
89 | 0, /* iConfiguration */ | 89 | 0, /* iConfiguration */ |
90 | 0x40, /* bmAttributes: UC_SELF_POWER */ | 90 | 0x40, /* bmAttributes: UC_SELF_POWER */ |
91 | 0 /* bMaxPower */ | 91 | 0 /* bMaxPower */ |
92 | }, | 92 | }, |
93 | { | 93 | { |
94 | 0x9, /* bLength */ | 94 | 0x9, /* bLength */ |
95 | 4, /* bDescriptorType: UDESC_INTERFACE */ | 95 | 4, /* bDescriptorType: UDESC_INTERFACE */ |
96 | 0, /* bInterfaceNumber */ | 96 | 0, /* bInterfaceNumber */ |
97 | 0, /* bAlternateSetting */ | 97 | 0, /* bAlternateSetting */ |
98 | 1, /* bNumEndpoints */ | 98 | 1, /* bNumEndpoints */ |
99 | 9, /* bInterfaceClass: UICLASS_HUB */ | 99 | 9, /* bInterfaceClass: UICLASS_HUB */ |
100 | 0, /* bInterfaceSubClass: UISUBCLASS_HUB */ | 100 | 0, /* bInterfaceSubClass: UISUBCLASS_HUB */ |
101 | 0, /* bInterfaceProtocol: UIPROTO_HSHUBSTT */ | 101 | 0, /* bInterfaceProtocol: UIPROTO_HSHUBSTT */ |
102 | 0 /* iInterface */ | 102 | 0 /* iInterface */ |
103 | }, | 103 | }, |
104 | { | 104 | { |
105 | 0x7, /* bLength */ | 105 | 0x7, /* bLength */ |
106 | 5, /* bDescriptorType: UDESC_ENDPOINT */ | 106 | 5, /* bDescriptorType: UDESC_ENDPOINT */ |
107 | 0x81, /* bEndpointAddress: | 107 | 0x81, /* bEndpointAddress: |
108 | * UE_DIR_IN | EHCI_INTR_ENDPT | 108 | * UE_DIR_IN | EHCI_INTR_ENDPT |
109 | */ | 109 | */ |
110 | 3, /* bmAttributes: UE_INTERRUPT */ | 110 | 3, /* bmAttributes: UE_INTERRUPT */ |
111 | 8, /* wMaxPacketSize */ | 111 | 8, /* wMaxPacketSize */ |
112 | 255 /* bInterval */ | 112 | 255 /* bInterval */ |
113 | }, | 113 | }, |
114 | }; | 114 | }; |
115 | 115 | ||
116 | #if defined(CONFIG_EHCI_IS_TDI) | 116 | #if defined(CONFIG_EHCI_IS_TDI) |
117 | #define ehci_is_TDI() (1) | 117 | #define ehci_is_TDI() (1) |
118 | #else | 118 | #else |
119 | #define ehci_is_TDI() (0) | 119 | #define ehci_is_TDI() (0) |
120 | #endif | 120 | #endif |
121 | 121 | ||
122 | int __ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg) | 122 | int __ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg) |
123 | { | 123 | { |
124 | return PORTSC_PSPD(reg); | 124 | return PORTSC_PSPD(reg); |
125 | } | 125 | } |
126 | 126 | ||
127 | int ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg) | 127 | int ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg) |
128 | __attribute__((weak, alias("__ehci_get_port_speed"))); | 128 | __attribute__((weak, alias("__ehci_get_port_speed"))); |
129 | 129 | ||
130 | void __ehci_set_usbmode(int index) | 130 | void __ehci_set_usbmode(int index) |
131 | { | 131 | { |
132 | uint32_t tmp; | 132 | uint32_t tmp; |
133 | uint32_t *reg_ptr; | 133 | uint32_t *reg_ptr; |
134 | 134 | ||
135 | reg_ptr = (uint32_t *)((u8 *)&ehcic[index].hcor->or_usbcmd + USBMODE); | 135 | reg_ptr = (uint32_t *)((u8 *)&ehcic[index].hcor->or_usbcmd + USBMODE); |
136 | tmp = ehci_readl(reg_ptr); | 136 | tmp = ehci_readl(reg_ptr); |
137 | tmp |= USBMODE_CM_HC; | 137 | tmp |= USBMODE_CM_HC; |
138 | #if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN) | 138 | #if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN) |
139 | tmp |= USBMODE_BE; | 139 | tmp |= USBMODE_BE; |
140 | #endif | 140 | #endif |
141 | ehci_writel(reg_ptr, tmp); | 141 | ehci_writel(reg_ptr, tmp); |
142 | } | 142 | } |
143 | 143 | ||
144 | void ehci_set_usbmode(int index) | 144 | void ehci_set_usbmode(int index) |
145 | __attribute__((weak, alias("__ehci_set_usbmode"))); | 145 | __attribute__((weak, alias("__ehci_set_usbmode"))); |
146 | 146 | ||
147 | void __ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg) | 147 | void __ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg) |
148 | { | 148 | { |
149 | mdelay(50); | 149 | mdelay(50); |
150 | } | 150 | } |
151 | 151 | ||
152 | void ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg) | 152 | void ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg) |
153 | __attribute__((weak, alias("__ehci_powerup_fixup"))); | 153 | __attribute__((weak, alias("__ehci_powerup_fixup"))); |
154 | 154 | ||
155 | static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec) | 155 | static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec) |
156 | { | 156 | { |
157 | uint32_t result; | 157 | uint32_t result; |
158 | do { | 158 | do { |
159 | result = ehci_readl(ptr); | 159 | result = ehci_readl(ptr); |
160 | udelay(5); | 160 | udelay(5); |
161 | if (result == ~(uint32_t)0) | 161 | if (result == ~(uint32_t)0) |
162 | return -1; | 162 | return -1; |
163 | result &= mask; | 163 | result &= mask; |
164 | if (result == done) | 164 | if (result == done) |
165 | return 0; | 165 | return 0; |
166 | usec--; | 166 | usec--; |
167 | } while (usec > 0); | 167 | } while (usec > 0); |
168 | return -1; | 168 | return -1; |
169 | } | 169 | } |
170 | 170 | ||
171 | static int ehci_reset(int index) | 171 | static int ehci_reset(int index) |
172 | { | 172 | { |
173 | uint32_t cmd; | 173 | uint32_t cmd; |
174 | int ret = 0; | 174 | int ret = 0; |
175 | 175 | ||
176 | cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd); | 176 | cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd); |
177 | cmd = (cmd & ~CMD_RUN) | CMD_RESET; | 177 | cmd = (cmd & ~CMD_RUN) | CMD_RESET; |
178 | ehci_writel(&ehcic[index].hcor->or_usbcmd, cmd); | 178 | ehci_writel(&ehcic[index].hcor->or_usbcmd, cmd); |
179 | ret = handshake((uint32_t *)&ehcic[index].hcor->or_usbcmd, | 179 | ret = handshake((uint32_t *)&ehcic[index].hcor->or_usbcmd, |
180 | CMD_RESET, 0, 250 * 1000); | 180 | CMD_RESET, 0, 250 * 1000); |
181 | if (ret < 0) { | 181 | if (ret < 0) { |
182 | printf("EHCI fail to reset\n"); | 182 | printf("EHCI fail to reset\n"); |
183 | goto out; | 183 | goto out; |
184 | } | 184 | } |
185 | 185 | ||
186 | if (ehci_is_TDI()) | 186 | if (ehci_is_TDI()) |
187 | ehci_set_usbmode(index); | 187 | ehci_set_usbmode(index); |
188 | 188 | ||
189 | #ifdef CONFIG_USB_EHCI_TXFIFO_THRESH | 189 | #ifdef CONFIG_USB_EHCI_TXFIFO_THRESH |
190 | cmd = ehci_readl(&ehcic[index].hcor->or_txfilltuning); | 190 | cmd = ehci_readl(&ehcic[index].hcor->or_txfilltuning); |
191 | cmd &= ~TXFIFO_THRESH_MASK; | 191 | cmd &= ~TXFIFO_THRESH_MASK; |
192 | cmd |= TXFIFO_THRESH(CONFIG_USB_EHCI_TXFIFO_THRESH); | 192 | cmd |= TXFIFO_THRESH(CONFIG_USB_EHCI_TXFIFO_THRESH); |
193 | ehci_writel(&ehcic[index].hcor->or_txfilltuning, cmd); | 193 | ehci_writel(&ehcic[index].hcor->or_txfilltuning, cmd); |
194 | #endif | 194 | #endif |
195 | out: | 195 | out: |
196 | return ret; | 196 | return ret; |
197 | } | 197 | } |
198 | 198 | ||
199 | static int ehci_shutdown(struct ehci_ctrl *ctrl) | 199 | static int ehci_shutdown(struct ehci_ctrl *ctrl) |
200 | { | 200 | { |
201 | int i, ret = 0; | 201 | int i, ret = 0; |
202 | uint32_t cmd, reg; | 202 | uint32_t cmd, reg; |
203 | 203 | ||
204 | if (!ctrl || !ctrl->hcor) | 204 | if (!ctrl || !ctrl->hcor) |
205 | return -EINVAL; | 205 | return -EINVAL; |
206 | 206 | ||
207 | cmd = ehci_readl(&ctrl->hcor->or_usbcmd); | 207 | cmd = ehci_readl(&ctrl->hcor->or_usbcmd); |
208 | cmd &= ~(CMD_PSE | CMD_ASE); | 208 | cmd &= ~(CMD_PSE | CMD_ASE); |
209 | ehci_writel(&ctrl->hcor->or_usbcmd, cmd); | 209 | ehci_writel(&ctrl->hcor->or_usbcmd, cmd); |
210 | ret = handshake(&ctrl->hcor->or_usbsts, STS_ASS | STS_PSS, 0, | 210 | ret = handshake(&ctrl->hcor->or_usbsts, STS_ASS | STS_PSS, 0, |
211 | 100 * 1000); | 211 | 100 * 1000); |
212 | 212 | ||
213 | if (!ret) { | 213 | if (!ret) { |
214 | for (i = 0; i < CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS; i++) { | 214 | for (i = 0; i < CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS; i++) { |
215 | reg = ehci_readl(&ctrl->hcor->or_portsc[i]); | 215 | reg = ehci_readl(&ctrl->hcor->or_portsc[i]); |
216 | reg |= EHCI_PS_SUSP; | 216 | reg |= EHCI_PS_SUSP; |
217 | ehci_writel(&ctrl->hcor->or_portsc[i], reg); | 217 | ehci_writel(&ctrl->hcor->or_portsc[i], reg); |
218 | } | 218 | } |
219 | 219 | ||
220 | cmd &= ~CMD_RUN; | 220 | cmd &= ~CMD_RUN; |
221 | ehci_writel(&ctrl->hcor->or_usbcmd, cmd); | 221 | ehci_writel(&ctrl->hcor->or_usbcmd, cmd); |
222 | ret = handshake(&ctrl->hcor->or_usbsts, STS_HALT, STS_HALT, | 222 | ret = handshake(&ctrl->hcor->or_usbsts, STS_HALT, STS_HALT, |
223 | HCHALT_TIMEOUT); | 223 | HCHALT_TIMEOUT); |
224 | } | 224 | } |
225 | 225 | ||
226 | if (ret) | 226 | if (ret) |
227 | puts("EHCI failed to shut down host controller.\n"); | 227 | puts("EHCI failed to shut down host controller.\n"); |
228 | 228 | ||
229 | return ret; | 229 | return ret; |
230 | } | 230 | } |
231 | 231 | ||
232 | static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz) | 232 | static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz) |
233 | { | 233 | { |
234 | uint32_t delta, next; | 234 | uint32_t delta, next; |
235 | uint32_t addr = (uint32_t)buf; | 235 | uint32_t addr = (uint32_t)buf; |
236 | int idx; | 236 | int idx; |
237 | 237 | ||
238 | if (addr != ALIGN(addr, ARCH_DMA_MINALIGN)) | 238 | if (addr != ALIGN(addr, ARCH_DMA_MINALIGN)) |
239 | debug("EHCI-HCD: Misaligned buffer address (%p)\n", buf); | 239 | debug("EHCI-HCD: Misaligned buffer address (%p)\n", buf); |
240 | 240 | ||
241 | flush_dcache_range(addr, ALIGN(addr + sz, ARCH_DMA_MINALIGN)); | 241 | flush_dcache_range(addr, ALIGN(addr + sz, ARCH_DMA_MINALIGN)); |
242 | 242 | ||
243 | idx = 0; | 243 | idx = 0; |
244 | while (idx < QT_BUFFER_CNT) { | 244 | while (idx < QT_BUFFER_CNT) { |
245 | td->qt_buffer[idx] = cpu_to_hc32(addr); | 245 | td->qt_buffer[idx] = cpu_to_hc32(addr); |
246 | td->qt_buffer_hi[idx] = 0; | 246 | td->qt_buffer_hi[idx] = 0; |
247 | next = (addr + EHCI_PAGE_SIZE) & ~(EHCI_PAGE_SIZE - 1); | 247 | next = (addr + EHCI_PAGE_SIZE) & ~(EHCI_PAGE_SIZE - 1); |
248 | delta = next - addr; | 248 | delta = next - addr; |
249 | if (delta >= sz) | 249 | if (delta >= sz) |
250 | break; | 250 | break; |
251 | sz -= delta; | 251 | sz -= delta; |
252 | addr = next; | 252 | addr = next; |
253 | idx++; | 253 | idx++; |
254 | } | 254 | } |
255 | 255 | ||
256 | if (idx == QT_BUFFER_CNT) { | 256 | if (idx == QT_BUFFER_CNT) { |
257 | printf("out of buffer pointers (%u bytes left)\n", sz); | 257 | printf("out of buffer pointers (%u bytes left)\n", sz); |
258 | return -1; | 258 | return -1; |
259 | } | 259 | } |
260 | 260 | ||
261 | return 0; | 261 | return 0; |
262 | } | 262 | } |
263 | 263 | ||
264 | static inline u8 ehci_encode_speed(enum usb_device_speed speed) | 264 | static inline u8 ehci_encode_speed(enum usb_device_speed speed) |
265 | { | 265 | { |
266 | #define QH_HIGH_SPEED 2 | 266 | #define QH_HIGH_SPEED 2 |
267 | #define QH_FULL_SPEED 0 | 267 | #define QH_FULL_SPEED 0 |
268 | #define QH_LOW_SPEED 1 | 268 | #define QH_LOW_SPEED 1 |
269 | if (speed == USB_SPEED_HIGH) | 269 | if (speed == USB_SPEED_HIGH) |
270 | return QH_HIGH_SPEED; | 270 | return QH_HIGH_SPEED; |
271 | if (speed == USB_SPEED_LOW) | 271 | if (speed == USB_SPEED_LOW) |
272 | return QH_LOW_SPEED; | 272 | return QH_LOW_SPEED; |
273 | return QH_FULL_SPEED; | 273 | return QH_FULL_SPEED; |
274 | } | 274 | } |
275 | 275 | ||
276 | static void ehci_update_endpt2_dev_n_port(struct usb_device *dev, | ||
277 | struct QH *qh) | ||
278 | { | ||
279 | struct usb_device *ttdev; | ||
280 | |||
281 | if (dev->speed != USB_SPEED_LOW && dev->speed != USB_SPEED_FULL) | ||
282 | return; | ||
283 | |||
284 | /* | ||
285 | * For full / low speed devices we need to get the devnum and portnr of | ||
286 | * the tt, so of the first upstream usb-2 hub, there may be usb-1 hubs | ||
287 | * in the tree before that one! | ||
288 | */ | ||
289 | ttdev = dev; | ||
290 | while (ttdev->parent && ttdev->parent->speed != USB_SPEED_HIGH) | ||
291 | ttdev = ttdev->parent; | ||
292 | if (!ttdev->parent) | ||
293 | return; | ||
294 | |||
295 | qh->qh_endpt2 |= cpu_to_hc32(QH_ENDPT2_PORTNUM(ttdev->portnr) | | ||
296 | QH_ENDPT2_HUBADDR(ttdev->parent->devnum)); | ||
297 | } | ||
298 | |||
276 | static int | 299 | static int |
277 | ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, | 300 | ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, |
278 | int length, struct devrequest *req) | 301 | int length, struct devrequest *req) |
279 | { | 302 | { |
280 | ALLOC_ALIGN_BUFFER(struct QH, qh, 1, USB_DMA_MINALIGN); | 303 | ALLOC_ALIGN_BUFFER(struct QH, qh, 1, USB_DMA_MINALIGN); |
281 | struct qTD *qtd; | 304 | struct qTD *qtd; |
282 | int qtd_count = 0; | 305 | int qtd_count = 0; |
283 | int qtd_counter = 0; | 306 | int qtd_counter = 0; |
284 | volatile struct qTD *vtd; | 307 | volatile struct qTD *vtd; |
285 | unsigned long ts; | 308 | unsigned long ts; |
286 | uint32_t *tdp; | 309 | uint32_t *tdp; |
287 | uint32_t endpt, maxpacket, token, usbsts; | 310 | uint32_t endpt, maxpacket, token, usbsts; |
288 | uint32_t c, toggle; | 311 | uint32_t c, toggle; |
289 | uint32_t cmd; | 312 | uint32_t cmd; |
290 | int timeout; | 313 | int timeout; |
291 | int ret = 0; | 314 | int ret = 0; |
292 | struct ehci_ctrl *ctrl = dev->controller; | 315 | struct ehci_ctrl *ctrl = dev->controller; |
293 | 316 | ||
294 | debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe, | 317 | debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe, |
295 | buffer, length, req); | 318 | buffer, length, req); |
296 | if (req != NULL) | 319 | if (req != NULL) |
297 | debug("req=%u (%#x), type=%u (%#x), value=%u (%#x), index=%u\n", | 320 | debug("req=%u (%#x), type=%u (%#x), value=%u (%#x), index=%u\n", |
298 | req->request, req->request, | 321 | req->request, req->request, |
299 | req->requesttype, req->requesttype, | 322 | req->requesttype, req->requesttype, |
300 | le16_to_cpu(req->value), le16_to_cpu(req->value), | 323 | le16_to_cpu(req->value), le16_to_cpu(req->value), |
301 | le16_to_cpu(req->index)); | 324 | le16_to_cpu(req->index)); |
302 | 325 | ||
303 | #define PKT_ALIGN 512 | 326 | #define PKT_ALIGN 512 |
304 | /* | 327 | /* |
305 | * The USB transfer is split into qTD transfers. Eeach qTD transfer is | 328 | * The USB transfer is split into qTD transfers. Eeach qTD transfer is |
306 | * described by a transfer descriptor (the qTD). The qTDs form a linked | 329 | * described by a transfer descriptor (the qTD). The qTDs form a linked |
307 | * list with a queue head (QH). | 330 | * list with a queue head (QH). |
308 | * | 331 | * |
309 | * Each qTD transfer starts with a new USB packet, i.e. a packet cannot | 332 | * Each qTD transfer starts with a new USB packet, i.e. a packet cannot |
310 | * have its beginning in a qTD transfer and its end in the following | 333 | * have its beginning in a qTD transfer and its end in the following |
311 | * one, so the qTD transfer lengths have to be chosen accordingly. | 334 | * one, so the qTD transfer lengths have to be chosen accordingly. |
312 | * | 335 | * |
313 | * Each qTD transfer uses up to QT_BUFFER_CNT data buffers, mapped to | 336 | * Each qTD transfer uses up to QT_BUFFER_CNT data buffers, mapped to |
314 | * single pages. The first data buffer can start at any offset within a | 337 | * single pages. The first data buffer can start at any offset within a |
315 | * page (not considering the cache-line alignment issues), while the | 338 | * page (not considering the cache-line alignment issues), while the |
316 | * following buffers must be page-aligned. There is no alignment | 339 | * following buffers must be page-aligned. There is no alignment |
317 | * constraint on the size of a qTD transfer. | 340 | * constraint on the size of a qTD transfer. |
318 | */ | 341 | */ |
319 | if (req != NULL) | 342 | if (req != NULL) |
320 | /* 1 qTD will be needed for SETUP, and 1 for ACK. */ | 343 | /* 1 qTD will be needed for SETUP, and 1 for ACK. */ |
321 | qtd_count += 1 + 1; | 344 | qtd_count += 1 + 1; |
322 | if (length > 0 || req == NULL) { | 345 | if (length > 0 || req == NULL) { |
323 | /* | 346 | /* |
324 | * Determine the qTD transfer size that will be used for the | 347 | * Determine the qTD transfer size that will be used for the |
325 | * data payload (not considering the first qTD transfer, which | 348 | * data payload (not considering the first qTD transfer, which |
326 | * may be longer or shorter, and the final one, which may be | 349 | * may be longer or shorter, and the final one, which may be |
327 | * shorter). | 350 | * shorter). |
328 | * | 351 | * |
329 | * In order to keep each packet within a qTD transfer, the qTD | 352 | * In order to keep each packet within a qTD transfer, the qTD |
330 | * transfer size is aligned to PKT_ALIGN, which is a multiple of | 353 | * transfer size is aligned to PKT_ALIGN, which is a multiple of |
331 | * wMaxPacketSize (except in some cases for interrupt transfers, | 354 | * wMaxPacketSize (except in some cases for interrupt transfers, |
332 | * see comment in submit_int_msg()). | 355 | * see comment in submit_int_msg()). |
333 | * | 356 | * |
334 | * By default, i.e. if the input buffer is aligned to PKT_ALIGN, | 357 | * By default, i.e. if the input buffer is aligned to PKT_ALIGN, |
335 | * QT_BUFFER_CNT full pages will be used. | 358 | * QT_BUFFER_CNT full pages will be used. |
336 | */ | 359 | */ |
337 | int xfr_sz = QT_BUFFER_CNT; | 360 | int xfr_sz = QT_BUFFER_CNT; |
338 | /* | 361 | /* |
339 | * However, if the input buffer is not aligned to PKT_ALIGN, the | 362 | * However, if the input buffer is not aligned to PKT_ALIGN, the |
340 | * qTD transfer size will be one page shorter, and the first qTD | 363 | * qTD transfer size will be one page shorter, and the first qTD |
341 | * data buffer of each transfer will be page-unaligned. | 364 | * data buffer of each transfer will be page-unaligned. |
342 | */ | 365 | */ |
343 | if ((uint32_t)buffer & (PKT_ALIGN - 1)) | 366 | if ((uint32_t)buffer & (PKT_ALIGN - 1)) |
344 | xfr_sz--; | 367 | xfr_sz--; |
345 | /* Convert the qTD transfer size to bytes. */ | 368 | /* Convert the qTD transfer size to bytes. */ |
346 | xfr_sz *= EHCI_PAGE_SIZE; | 369 | xfr_sz *= EHCI_PAGE_SIZE; |
347 | /* | 370 | /* |
348 | * Approximate by excess the number of qTDs that will be | 371 | * Approximate by excess the number of qTDs that will be |
349 | * required for the data payload. The exact formula is way more | 372 | * required for the data payload. The exact formula is way more |
350 | * complicated and saves at most 2 qTDs, i.e. a total of 128 | 373 | * complicated and saves at most 2 qTDs, i.e. a total of 128 |
351 | * bytes. | 374 | * bytes. |
352 | */ | 375 | */ |
353 | qtd_count += 2 + length / xfr_sz; | 376 | qtd_count += 2 + length / xfr_sz; |
354 | } | 377 | } |
355 | /* | 378 | /* |
356 | * Threshold value based on the worst-case total size of the allocated qTDs for | 379 | * Threshold value based on the worst-case total size of the allocated qTDs for |
357 | * a mass-storage transfer of 65535 blocks of 512 bytes. | 380 | * a mass-storage transfer of 65535 blocks of 512 bytes. |
358 | */ | 381 | */ |
359 | #if CONFIG_SYS_MALLOC_LEN <= 64 + 128 * 1024 | 382 | #if CONFIG_SYS_MALLOC_LEN <= 64 + 128 * 1024 |
360 | #warning CONFIG_SYS_MALLOC_LEN may be too small for EHCI | 383 | #warning CONFIG_SYS_MALLOC_LEN may be too small for EHCI |
361 | #endif | 384 | #endif |
362 | qtd = memalign(USB_DMA_MINALIGN, qtd_count * sizeof(struct qTD)); | 385 | qtd = memalign(USB_DMA_MINALIGN, qtd_count * sizeof(struct qTD)); |
363 | if (qtd == NULL) { | 386 | if (qtd == NULL) { |
364 | printf("unable to allocate TDs\n"); | 387 | printf("unable to allocate TDs\n"); |
365 | return -1; | 388 | return -1; |
366 | } | 389 | } |
367 | 390 | ||
368 | memset(qh, 0, sizeof(struct QH)); | 391 | memset(qh, 0, sizeof(struct QH)); |
369 | memset(qtd, 0, qtd_count * sizeof(*qtd)); | 392 | memset(qtd, 0, qtd_count * sizeof(*qtd)); |
370 | 393 | ||
371 | toggle = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); | 394 | toggle = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); |
372 | 395 | ||
373 | /* | 396 | /* |
374 | * Setup QH (3.6 in ehci-r10.pdf) | 397 | * Setup QH (3.6 in ehci-r10.pdf) |
375 | * | 398 | * |
376 | * qh_link ................. 03-00 H | 399 | * qh_link ................. 03-00 H |
377 | * qh_endpt1 ............... 07-04 H | 400 | * qh_endpt1 ............... 07-04 H |
378 | * qh_endpt2 ............... 0B-08 H | 401 | * qh_endpt2 ............... 0B-08 H |
379 | * - qh_curtd | 402 | * - qh_curtd |
380 | * qh_overlay.qt_next ...... 13-10 H | 403 | * qh_overlay.qt_next ...... 13-10 H |
381 | * - qh_overlay.qt_altnext | 404 | * - qh_overlay.qt_altnext |
382 | */ | 405 | */ |
383 | qh->qh_link = cpu_to_hc32((uint32_t)&ctrl->qh_list | QH_LINK_TYPE_QH); | 406 | qh->qh_link = cpu_to_hc32((uint32_t)&ctrl->qh_list | QH_LINK_TYPE_QH); |
384 | c = (dev->speed != USB_SPEED_HIGH) && !usb_pipeendpoint(pipe); | 407 | c = (dev->speed != USB_SPEED_HIGH) && !usb_pipeendpoint(pipe); |
385 | maxpacket = usb_maxpacket(dev, pipe); | 408 | maxpacket = usb_maxpacket(dev, pipe); |
386 | endpt = QH_ENDPT1_RL(8) | QH_ENDPT1_C(c) | | 409 | endpt = QH_ENDPT1_RL(8) | QH_ENDPT1_C(c) | |
387 | QH_ENDPT1_MAXPKTLEN(maxpacket) | QH_ENDPT1_H(0) | | 410 | QH_ENDPT1_MAXPKTLEN(maxpacket) | QH_ENDPT1_H(0) | |
388 | QH_ENDPT1_DTC(QH_ENDPT1_DTC_DT_FROM_QTD) | | 411 | QH_ENDPT1_DTC(QH_ENDPT1_DTC_DT_FROM_QTD) | |
389 | QH_ENDPT1_EPS(ehci_encode_speed(dev->speed)) | | 412 | QH_ENDPT1_EPS(ehci_encode_speed(dev->speed)) | |
390 | QH_ENDPT1_ENDPT(usb_pipeendpoint(pipe)) | QH_ENDPT1_I(0) | | 413 | QH_ENDPT1_ENDPT(usb_pipeendpoint(pipe)) | QH_ENDPT1_I(0) | |
391 | QH_ENDPT1_DEVADDR(usb_pipedevice(pipe)); | 414 | QH_ENDPT1_DEVADDR(usb_pipedevice(pipe)); |
392 | qh->qh_endpt1 = cpu_to_hc32(endpt); | 415 | qh->qh_endpt1 = cpu_to_hc32(endpt); |
393 | endpt = QH_ENDPT2_MULT(1) | QH_ENDPT2_PORTNUM(dev->portnr) | | 416 | endpt = QH_ENDPT2_MULT(1) | QH_ENDPT2_UFCMASK(0) | QH_ENDPT2_UFSMASK(0); |
394 | QH_ENDPT2_HUBADDR(dev->parent->devnum) | | ||
395 | QH_ENDPT2_UFCMASK(0) | QH_ENDPT2_UFSMASK(0); | ||
396 | qh->qh_endpt2 = cpu_to_hc32(endpt); | 417 | qh->qh_endpt2 = cpu_to_hc32(endpt); |
418 | ehci_update_endpt2_dev_n_port(dev, qh); | ||
397 | qh->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); | 419 | qh->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); |
398 | qh->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); | 420 | qh->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); |
399 | 421 | ||
400 | tdp = &qh->qh_overlay.qt_next; | 422 | tdp = &qh->qh_overlay.qt_next; |
401 | 423 | ||
402 | if (req != NULL) { | 424 | if (req != NULL) { |
403 | /* | 425 | /* |
404 | * Setup request qTD (3.5 in ehci-r10.pdf) | 426 | * Setup request qTD (3.5 in ehci-r10.pdf) |
405 | * | 427 | * |
406 | * qt_next ................ 03-00 H | 428 | * qt_next ................ 03-00 H |
407 | * qt_altnext ............. 07-04 H | 429 | * qt_altnext ............. 07-04 H |
408 | * qt_token ............... 0B-08 H | 430 | * qt_token ............... 0B-08 H |
409 | * | 431 | * |
410 | * [ buffer, buffer_hi ] loaded with "req". | 432 | * [ buffer, buffer_hi ] loaded with "req". |
411 | */ | 433 | */ |
412 | qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); | 434 | qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); |
413 | qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); | 435 | qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); |
414 | token = QT_TOKEN_DT(0) | QT_TOKEN_TOTALBYTES(sizeof(*req)) | | 436 | token = QT_TOKEN_DT(0) | QT_TOKEN_TOTALBYTES(sizeof(*req)) | |
415 | QT_TOKEN_IOC(0) | QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) | | 437 | QT_TOKEN_IOC(0) | QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) | |
416 | QT_TOKEN_PID(QT_TOKEN_PID_SETUP) | | 438 | QT_TOKEN_PID(QT_TOKEN_PID_SETUP) | |
417 | QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE); | 439 | QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE); |
418 | qtd[qtd_counter].qt_token = cpu_to_hc32(token); | 440 | qtd[qtd_counter].qt_token = cpu_to_hc32(token); |
419 | if (ehci_td_buffer(&qtd[qtd_counter], req, sizeof(*req))) { | 441 | if (ehci_td_buffer(&qtd[qtd_counter], req, sizeof(*req))) { |
420 | printf("unable to construct SETUP TD\n"); | 442 | printf("unable to construct SETUP TD\n"); |
421 | goto fail; | 443 | goto fail; |
422 | } | 444 | } |
423 | /* Update previous qTD! */ | 445 | /* Update previous qTD! */ |
424 | *tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]); | 446 | *tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]); |
425 | tdp = &qtd[qtd_counter++].qt_next; | 447 | tdp = &qtd[qtd_counter++].qt_next; |
426 | toggle = 1; | 448 | toggle = 1; |
427 | } | 449 | } |
428 | 450 | ||
429 | if (length > 0 || req == NULL) { | 451 | if (length > 0 || req == NULL) { |
430 | uint8_t *buf_ptr = buffer; | 452 | uint8_t *buf_ptr = buffer; |
431 | int left_length = length; | 453 | int left_length = length; |
432 | 454 | ||
433 | do { | 455 | do { |
434 | /* | 456 | /* |
435 | * Determine the size of this qTD transfer. By default, | 457 | * Determine the size of this qTD transfer. By default, |
436 | * QT_BUFFER_CNT full pages can be used. | 458 | * QT_BUFFER_CNT full pages can be used. |
437 | */ | 459 | */ |
438 | int xfr_bytes = QT_BUFFER_CNT * EHCI_PAGE_SIZE; | 460 | int xfr_bytes = QT_BUFFER_CNT * EHCI_PAGE_SIZE; |
439 | /* | 461 | /* |
440 | * However, if the input buffer is not page-aligned, the | 462 | * However, if the input buffer is not page-aligned, the |
441 | * portion of the first page before the buffer start | 463 | * portion of the first page before the buffer start |
442 | * offset within that page is unusable. | 464 | * offset within that page is unusable. |
443 | */ | 465 | */ |
444 | xfr_bytes -= (uint32_t)buf_ptr & (EHCI_PAGE_SIZE - 1); | 466 | xfr_bytes -= (uint32_t)buf_ptr & (EHCI_PAGE_SIZE - 1); |
445 | /* | 467 | /* |
446 | * In order to keep each packet within a qTD transfer, | 468 | * In order to keep each packet within a qTD transfer, |
447 | * align the qTD transfer size to PKT_ALIGN. | 469 | * align the qTD transfer size to PKT_ALIGN. |
448 | */ | 470 | */ |
449 | xfr_bytes &= ~(PKT_ALIGN - 1); | 471 | xfr_bytes &= ~(PKT_ALIGN - 1); |
450 | /* | 472 | /* |
451 | * This transfer may be shorter than the available qTD | 473 | * This transfer may be shorter than the available qTD |
452 | * transfer size that has just been computed. | 474 | * transfer size that has just been computed. |
453 | */ | 475 | */ |
454 | xfr_bytes = min(xfr_bytes, left_length); | 476 | xfr_bytes = min(xfr_bytes, left_length); |
455 | 477 | ||
456 | /* | 478 | /* |
457 | * Setup request qTD (3.5 in ehci-r10.pdf) | 479 | * Setup request qTD (3.5 in ehci-r10.pdf) |
458 | * | 480 | * |
459 | * qt_next ................ 03-00 H | 481 | * qt_next ................ 03-00 H |
460 | * qt_altnext ............. 07-04 H | 482 | * qt_altnext ............. 07-04 H |
461 | * qt_token ............... 0B-08 H | 483 | * qt_token ............... 0B-08 H |
462 | * | 484 | * |
463 | * [ buffer, buffer_hi ] loaded with "buffer". | 485 | * [ buffer, buffer_hi ] loaded with "buffer". |
464 | */ | 486 | */ |
465 | qtd[qtd_counter].qt_next = | 487 | qtd[qtd_counter].qt_next = |
466 | cpu_to_hc32(QT_NEXT_TERMINATE); | 488 | cpu_to_hc32(QT_NEXT_TERMINATE); |
467 | qtd[qtd_counter].qt_altnext = | 489 | qtd[qtd_counter].qt_altnext = |
468 | cpu_to_hc32(QT_NEXT_TERMINATE); | 490 | cpu_to_hc32(QT_NEXT_TERMINATE); |
469 | token = QT_TOKEN_DT(toggle) | | 491 | token = QT_TOKEN_DT(toggle) | |
470 | QT_TOKEN_TOTALBYTES(xfr_bytes) | | 492 | QT_TOKEN_TOTALBYTES(xfr_bytes) | |
471 | QT_TOKEN_IOC(req == NULL) | QT_TOKEN_CPAGE(0) | | 493 | QT_TOKEN_IOC(req == NULL) | QT_TOKEN_CPAGE(0) | |
472 | QT_TOKEN_CERR(3) | | 494 | QT_TOKEN_CERR(3) | |
473 | QT_TOKEN_PID(usb_pipein(pipe) ? | 495 | QT_TOKEN_PID(usb_pipein(pipe) ? |
474 | QT_TOKEN_PID_IN : QT_TOKEN_PID_OUT) | | 496 | QT_TOKEN_PID_IN : QT_TOKEN_PID_OUT) | |
475 | QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE); | 497 | QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE); |
476 | qtd[qtd_counter].qt_token = cpu_to_hc32(token); | 498 | qtd[qtd_counter].qt_token = cpu_to_hc32(token); |
477 | if (ehci_td_buffer(&qtd[qtd_counter], buf_ptr, | 499 | if (ehci_td_buffer(&qtd[qtd_counter], buf_ptr, |
478 | xfr_bytes)) { | 500 | xfr_bytes)) { |
479 | printf("unable to construct DATA TD\n"); | 501 | printf("unable to construct DATA TD\n"); |
480 | goto fail; | 502 | goto fail; |
481 | } | 503 | } |
482 | /* Update previous qTD! */ | 504 | /* Update previous qTD! */ |
483 | *tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]); | 505 | *tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]); |
484 | tdp = &qtd[qtd_counter++].qt_next; | 506 | tdp = &qtd[qtd_counter++].qt_next; |
485 | /* | 507 | /* |
486 | * Data toggle has to be adjusted since the qTD transfer | 508 | * Data toggle has to be adjusted since the qTD transfer |
487 | * size is not always an even multiple of | 509 | * size is not always an even multiple of |
488 | * wMaxPacketSize. | 510 | * wMaxPacketSize. |
489 | */ | 511 | */ |
490 | if ((xfr_bytes / maxpacket) & 1) | 512 | if ((xfr_bytes / maxpacket) & 1) |
491 | toggle ^= 1; | 513 | toggle ^= 1; |
492 | buf_ptr += xfr_bytes; | 514 | buf_ptr += xfr_bytes; |
493 | left_length -= xfr_bytes; | 515 | left_length -= xfr_bytes; |
494 | } while (left_length > 0); | 516 | } while (left_length > 0); |
495 | } | 517 | } |
496 | 518 | ||
497 | if (req != NULL) { | 519 | if (req != NULL) { |
498 | /* | 520 | /* |
499 | * Setup request qTD (3.5 in ehci-r10.pdf) | 521 | * Setup request qTD (3.5 in ehci-r10.pdf) |
500 | * | 522 | * |
501 | * qt_next ................ 03-00 H | 523 | * qt_next ................ 03-00 H |
502 | * qt_altnext ............. 07-04 H | 524 | * qt_altnext ............. 07-04 H |
503 | * qt_token ............... 0B-08 H | 525 | * qt_token ............... 0B-08 H |
504 | */ | 526 | */ |
505 | qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); | 527 | qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); |
506 | qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); | 528 | qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); |
507 | token = QT_TOKEN_DT(1) | QT_TOKEN_TOTALBYTES(0) | | 529 | token = QT_TOKEN_DT(1) | QT_TOKEN_TOTALBYTES(0) | |
508 | QT_TOKEN_IOC(1) | QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) | | 530 | QT_TOKEN_IOC(1) | QT_TOKEN_CPAGE(0) | QT_TOKEN_CERR(3) | |
509 | QT_TOKEN_PID(usb_pipein(pipe) ? | 531 | QT_TOKEN_PID(usb_pipein(pipe) ? |
510 | QT_TOKEN_PID_OUT : QT_TOKEN_PID_IN) | | 532 | QT_TOKEN_PID_OUT : QT_TOKEN_PID_IN) | |
511 | QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE); | 533 | QT_TOKEN_STATUS(QT_TOKEN_STATUS_ACTIVE); |
512 | qtd[qtd_counter].qt_token = cpu_to_hc32(token); | 534 | qtd[qtd_counter].qt_token = cpu_to_hc32(token); |
513 | /* Update previous qTD! */ | 535 | /* Update previous qTD! */ |
514 | *tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]); | 536 | *tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]); |
515 | tdp = &qtd[qtd_counter++].qt_next; | 537 | tdp = &qtd[qtd_counter++].qt_next; |
516 | } | 538 | } |
517 | 539 | ||
518 | ctrl->qh_list.qh_link = cpu_to_hc32((uint32_t)qh | QH_LINK_TYPE_QH); | 540 | ctrl->qh_list.qh_link = cpu_to_hc32((uint32_t)qh | QH_LINK_TYPE_QH); |
519 | 541 | ||
520 | /* Flush dcache */ | 542 | /* Flush dcache */ |
521 | flush_dcache_range((uint32_t)&ctrl->qh_list, | 543 | flush_dcache_range((uint32_t)&ctrl->qh_list, |
522 | ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1)); | 544 | ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1)); |
523 | flush_dcache_range((uint32_t)qh, ALIGN_END_ADDR(struct QH, qh, 1)); | 545 | flush_dcache_range((uint32_t)qh, ALIGN_END_ADDR(struct QH, qh, 1)); |
524 | flush_dcache_range((uint32_t)qtd, | 546 | flush_dcache_range((uint32_t)qtd, |
525 | ALIGN_END_ADDR(struct qTD, qtd, qtd_count)); | 547 | ALIGN_END_ADDR(struct qTD, qtd, qtd_count)); |
526 | 548 | ||
527 | /* Set async. queue head pointer. */ | 549 | /* Set async. queue head pointer. */ |
528 | ehci_writel(&ctrl->hcor->or_asynclistaddr, (uint32_t)&ctrl->qh_list); | 550 | ehci_writel(&ctrl->hcor->or_asynclistaddr, (uint32_t)&ctrl->qh_list); |
529 | 551 | ||
530 | usbsts = ehci_readl(&ctrl->hcor->or_usbsts); | 552 | usbsts = ehci_readl(&ctrl->hcor->or_usbsts); |
531 | ehci_writel(&ctrl->hcor->or_usbsts, (usbsts & 0x3f)); | 553 | ehci_writel(&ctrl->hcor->or_usbsts, (usbsts & 0x3f)); |
532 | 554 | ||
533 | /* Enable async. schedule. */ | 555 | /* Enable async. schedule. */ |
534 | cmd = ehci_readl(&ctrl->hcor->or_usbcmd); | 556 | cmd = ehci_readl(&ctrl->hcor->or_usbcmd); |
535 | cmd |= CMD_ASE; | 557 | cmd |= CMD_ASE; |
536 | ehci_writel(&ctrl->hcor->or_usbcmd, cmd); | 558 | ehci_writel(&ctrl->hcor->or_usbcmd, cmd); |
537 | 559 | ||
538 | ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, STS_ASS, | 560 | ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, STS_ASS, |
539 | 100 * 1000); | 561 | 100 * 1000); |
540 | if (ret < 0) { | 562 | if (ret < 0) { |
541 | printf("EHCI fail timeout STS_ASS set\n"); | 563 | printf("EHCI fail timeout STS_ASS set\n"); |
542 | goto fail; | 564 | goto fail; |
543 | } | 565 | } |
544 | 566 | ||
545 | /* Wait for TDs to be processed. */ | 567 | /* Wait for TDs to be processed. */ |
546 | ts = get_timer(0); | 568 | ts = get_timer(0); |
547 | vtd = &qtd[qtd_counter - 1]; | 569 | vtd = &qtd[qtd_counter - 1]; |
548 | timeout = USB_TIMEOUT_MS(pipe); | 570 | timeout = USB_TIMEOUT_MS(pipe); |
549 | do { | 571 | do { |
550 | /* Invalidate dcache */ | 572 | /* Invalidate dcache */ |
551 | invalidate_dcache_range((uint32_t)&ctrl->qh_list, | 573 | invalidate_dcache_range((uint32_t)&ctrl->qh_list, |
552 | ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1)); | 574 | ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1)); |
553 | invalidate_dcache_range((uint32_t)qh, | 575 | invalidate_dcache_range((uint32_t)qh, |
554 | ALIGN_END_ADDR(struct QH, qh, 1)); | 576 | ALIGN_END_ADDR(struct QH, qh, 1)); |
555 | invalidate_dcache_range((uint32_t)qtd, | 577 | invalidate_dcache_range((uint32_t)qtd, |
556 | ALIGN_END_ADDR(struct qTD, qtd, qtd_count)); | 578 | ALIGN_END_ADDR(struct qTD, qtd, qtd_count)); |
557 | 579 | ||
558 | token = hc32_to_cpu(vtd->qt_token); | 580 | token = hc32_to_cpu(vtd->qt_token); |
559 | if (!(QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE)) | 581 | if (!(QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE)) |
560 | break; | 582 | break; |
561 | WATCHDOG_RESET(); | 583 | WATCHDOG_RESET(); |
562 | } while (get_timer(ts) < timeout); | 584 | } while (get_timer(ts) < timeout); |
563 | 585 | ||
564 | /* | 586 | /* |
565 | * Invalidate the memory area occupied by buffer | 587 | * Invalidate the memory area occupied by buffer |
566 | * Don't try to fix the buffer alignment, if it isn't properly | 588 | * Don't try to fix the buffer alignment, if it isn't properly |
567 | * aligned it's upper layer's fault so let invalidate_dcache_range() | 589 | * aligned it's upper layer's fault so let invalidate_dcache_range() |
568 | * vow about it. But we have to fix the length as it's actual | 590 | * vow about it. But we have to fix the length as it's actual |
569 | * transfer length and can be unaligned. This is potentially | 591 | * transfer length and can be unaligned. This is potentially |
570 | * dangerous operation, it's responsibility of the calling | 592 | * dangerous operation, it's responsibility of the calling |
571 | * code to make sure enough space is reserved. | 593 | * code to make sure enough space is reserved. |
572 | */ | 594 | */ |
573 | invalidate_dcache_range((uint32_t)buffer, | 595 | invalidate_dcache_range((uint32_t)buffer, |
574 | ALIGN((uint32_t)buffer + length, ARCH_DMA_MINALIGN)); | 596 | ALIGN((uint32_t)buffer + length, ARCH_DMA_MINALIGN)); |
575 | 597 | ||
576 | /* Check that the TD processing happened */ | 598 | /* Check that the TD processing happened */ |
577 | if (QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE) | 599 | if (QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE) |
578 | printf("EHCI timed out on TD - token=%#x\n", token); | 600 | printf("EHCI timed out on TD - token=%#x\n", token); |
579 | 601 | ||
580 | /* Disable async schedule. */ | 602 | /* Disable async schedule. */ |
581 | cmd = ehci_readl(&ctrl->hcor->or_usbcmd); | 603 | cmd = ehci_readl(&ctrl->hcor->or_usbcmd); |
582 | cmd &= ~CMD_ASE; | 604 | cmd &= ~CMD_ASE; |
583 | ehci_writel(&ctrl->hcor->or_usbcmd, cmd); | 605 | ehci_writel(&ctrl->hcor->or_usbcmd, cmd); |
584 | 606 | ||
585 | ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, 0, | 607 | ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, 0, |
586 | 100 * 1000); | 608 | 100 * 1000); |
587 | if (ret < 0) { | 609 | if (ret < 0) { |
588 | printf("EHCI fail timeout STS_ASS reset\n"); | 610 | printf("EHCI fail timeout STS_ASS reset\n"); |
589 | goto fail; | 611 | goto fail; |
590 | } | 612 | } |
591 | 613 | ||
592 | token = hc32_to_cpu(qh->qh_overlay.qt_token); | 614 | token = hc32_to_cpu(qh->qh_overlay.qt_token); |
593 | if (!(QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE)) { | 615 | if (!(QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE)) { |
594 | debug("TOKEN=%#x\n", token); | 616 | debug("TOKEN=%#x\n", token); |
595 | switch (QT_TOKEN_GET_STATUS(token) & | 617 | switch (QT_TOKEN_GET_STATUS(token) & |
596 | ~(QT_TOKEN_STATUS_SPLITXSTATE | QT_TOKEN_STATUS_PERR)) { | 618 | ~(QT_TOKEN_STATUS_SPLITXSTATE | QT_TOKEN_STATUS_PERR)) { |
597 | case 0: | 619 | case 0: |
598 | toggle = QT_TOKEN_GET_DT(token); | 620 | toggle = QT_TOKEN_GET_DT(token); |
599 | usb_settoggle(dev, usb_pipeendpoint(pipe), | 621 | usb_settoggle(dev, usb_pipeendpoint(pipe), |
600 | usb_pipeout(pipe), toggle); | 622 | usb_pipeout(pipe), toggle); |
601 | dev->status = 0; | 623 | dev->status = 0; |
602 | break; | 624 | break; |
603 | case QT_TOKEN_STATUS_HALTED: | 625 | case QT_TOKEN_STATUS_HALTED: |
604 | dev->status = USB_ST_STALLED; | 626 | dev->status = USB_ST_STALLED; |
605 | break; | 627 | break; |
606 | case QT_TOKEN_STATUS_ACTIVE | QT_TOKEN_STATUS_DATBUFERR: | 628 | case QT_TOKEN_STATUS_ACTIVE | QT_TOKEN_STATUS_DATBUFERR: |
607 | case QT_TOKEN_STATUS_DATBUFERR: | 629 | case QT_TOKEN_STATUS_DATBUFERR: |
608 | dev->status = USB_ST_BUF_ERR; | 630 | dev->status = USB_ST_BUF_ERR; |
609 | break; | 631 | break; |
610 | case QT_TOKEN_STATUS_HALTED | QT_TOKEN_STATUS_BABBLEDET: | 632 | case QT_TOKEN_STATUS_HALTED | QT_TOKEN_STATUS_BABBLEDET: |
611 | case QT_TOKEN_STATUS_BABBLEDET: | 633 | case QT_TOKEN_STATUS_BABBLEDET: |
612 | dev->status = USB_ST_BABBLE_DET; | 634 | dev->status = USB_ST_BABBLE_DET; |
613 | break; | 635 | break; |
614 | default: | 636 | default: |
615 | dev->status = USB_ST_CRC_ERR; | 637 | dev->status = USB_ST_CRC_ERR; |
616 | if (QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_HALTED) | 638 | if (QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_HALTED) |
617 | dev->status |= USB_ST_STALLED; | 639 | dev->status |= USB_ST_STALLED; |
618 | break; | 640 | break; |
619 | } | 641 | } |
620 | dev->act_len = length - QT_TOKEN_GET_TOTALBYTES(token); | 642 | dev->act_len = length - QT_TOKEN_GET_TOTALBYTES(token); |
621 | } else { | 643 | } else { |
622 | dev->act_len = 0; | 644 | dev->act_len = 0; |
623 | #ifndef CONFIG_USB_EHCI_FARADAY | 645 | #ifndef CONFIG_USB_EHCI_FARADAY |
624 | debug("dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\n", | 646 | debug("dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\n", |
625 | dev->devnum, ehci_readl(&ctrl->hcor->or_usbsts), | 647 | dev->devnum, ehci_readl(&ctrl->hcor->or_usbsts), |
626 | ehci_readl(&ctrl->hcor->or_portsc[0]), | 648 | ehci_readl(&ctrl->hcor->or_portsc[0]), |
627 | ehci_readl(&ctrl->hcor->or_portsc[1])); | 649 | ehci_readl(&ctrl->hcor->or_portsc[1])); |
628 | #endif | 650 | #endif |
629 | } | 651 | } |
630 | 652 | ||
631 | free(qtd); | 653 | free(qtd); |
632 | return (dev->status != USB_ST_NOT_PROC) ? 0 : -1; | 654 | return (dev->status != USB_ST_NOT_PROC) ? 0 : -1; |
633 | 655 | ||
634 | fail: | 656 | fail: |
635 | free(qtd); | 657 | free(qtd); |
636 | return -1; | 658 | return -1; |
637 | } | 659 | } |
638 | 660 | ||
639 | __weak uint32_t *ehci_get_portsc_register(struct ehci_hcor *hcor, int port) | 661 | __weak uint32_t *ehci_get_portsc_register(struct ehci_hcor *hcor, int port) |
640 | { | 662 | { |
641 | if (port < 0 || port >= CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) { | 663 | if (port < 0 || port >= CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) { |
642 | /* Printing the message would cause a scan failure! */ | 664 | /* Printing the message would cause a scan failure! */ |
643 | debug("The request port(%u) is not configured\n", port); | 665 | debug("The request port(%u) is not configured\n", port); |
644 | return NULL; | 666 | return NULL; |
645 | } | 667 | } |
646 | 668 | ||
647 | return (uint32_t *)&hcor->or_portsc[port]; | 669 | return (uint32_t *)&hcor->or_portsc[port]; |
648 | } | 670 | } |
649 | 671 | ||
650 | int | 672 | int |
651 | ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, | 673 | ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, |
652 | int length, struct devrequest *req) | 674 | int length, struct devrequest *req) |
653 | { | 675 | { |
654 | uint8_t tmpbuf[4]; | 676 | uint8_t tmpbuf[4]; |
655 | u16 typeReq; | 677 | u16 typeReq; |
656 | void *srcptr = NULL; | 678 | void *srcptr = NULL; |
657 | int len, srclen; | 679 | int len, srclen; |
658 | uint32_t reg; | 680 | uint32_t reg; |
659 | uint32_t *status_reg; | 681 | uint32_t *status_reg; |
660 | int port = le16_to_cpu(req->index) & 0xff; | 682 | int port = le16_to_cpu(req->index) & 0xff; |
661 | struct ehci_ctrl *ctrl = dev->controller; | 683 | struct ehci_ctrl *ctrl = dev->controller; |
662 | 684 | ||
663 | srclen = 0; | 685 | srclen = 0; |
664 | 686 | ||
665 | debug("req=%u (%#x), type=%u (%#x), value=%u, index=%u\n", | 687 | debug("req=%u (%#x), type=%u (%#x), value=%u, index=%u\n", |
666 | req->request, req->request, | 688 | req->request, req->request, |
667 | req->requesttype, req->requesttype, | 689 | req->requesttype, req->requesttype, |
668 | le16_to_cpu(req->value), le16_to_cpu(req->index)); | 690 | le16_to_cpu(req->value), le16_to_cpu(req->index)); |
669 | 691 | ||
670 | typeReq = req->request | req->requesttype << 8; | 692 | typeReq = req->request | req->requesttype << 8; |
671 | 693 | ||
672 | switch (typeReq) { | 694 | switch (typeReq) { |
673 | case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8): | 695 | case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8): |
674 | case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): | 696 | case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): |
675 | case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): | 697 | case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): |
676 | status_reg = ehci_get_portsc_register(ctrl->hcor, port - 1); | 698 | status_reg = ehci_get_portsc_register(ctrl->hcor, port - 1); |
677 | if (!status_reg) | 699 | if (!status_reg) |
678 | return -1; | 700 | return -1; |
679 | break; | 701 | break; |
680 | default: | 702 | default: |
681 | status_reg = NULL; | 703 | status_reg = NULL; |
682 | break; | 704 | break; |
683 | } | 705 | } |
684 | 706 | ||
685 | switch (typeReq) { | 707 | switch (typeReq) { |
686 | case DeviceRequest | USB_REQ_GET_DESCRIPTOR: | 708 | case DeviceRequest | USB_REQ_GET_DESCRIPTOR: |
687 | switch (le16_to_cpu(req->value) >> 8) { | 709 | switch (le16_to_cpu(req->value) >> 8) { |
688 | case USB_DT_DEVICE: | 710 | case USB_DT_DEVICE: |
689 | debug("USB_DT_DEVICE request\n"); | 711 | debug("USB_DT_DEVICE request\n"); |
690 | srcptr = &descriptor.device; | 712 | srcptr = &descriptor.device; |
691 | srclen = descriptor.device.bLength; | 713 | srclen = descriptor.device.bLength; |
692 | break; | 714 | break; |
693 | case USB_DT_CONFIG: | 715 | case USB_DT_CONFIG: |
694 | debug("USB_DT_CONFIG config\n"); | 716 | debug("USB_DT_CONFIG config\n"); |
695 | srcptr = &descriptor.config; | 717 | srcptr = &descriptor.config; |
696 | srclen = descriptor.config.bLength + | 718 | srclen = descriptor.config.bLength + |
697 | descriptor.interface.bLength + | 719 | descriptor.interface.bLength + |
698 | descriptor.endpoint.bLength; | 720 | descriptor.endpoint.bLength; |
699 | break; | 721 | break; |
700 | case USB_DT_STRING: | 722 | case USB_DT_STRING: |
701 | debug("USB_DT_STRING config\n"); | 723 | debug("USB_DT_STRING config\n"); |
702 | switch (le16_to_cpu(req->value) & 0xff) { | 724 | switch (le16_to_cpu(req->value) & 0xff) { |
703 | case 0: /* Language */ | 725 | case 0: /* Language */ |
704 | srcptr = "\4\3\1\0"; | 726 | srcptr = "\4\3\1\0"; |
705 | srclen = 4; | 727 | srclen = 4; |
706 | break; | 728 | break; |
707 | case 1: /* Vendor */ | 729 | case 1: /* Vendor */ |
708 | srcptr = "\16\3u\0-\0b\0o\0o\0t\0"; | 730 | srcptr = "\16\3u\0-\0b\0o\0o\0t\0"; |
709 | srclen = 14; | 731 | srclen = 14; |
710 | break; | 732 | break; |
711 | case 2: /* Product */ | 733 | case 2: /* Product */ |
712 | srcptr = "\52\3E\0H\0C\0I\0 " | 734 | srcptr = "\52\3E\0H\0C\0I\0 " |
713 | "\0H\0o\0s\0t\0 " | 735 | "\0H\0o\0s\0t\0 " |
714 | "\0C\0o\0n\0t\0r\0o\0l\0l\0e\0r\0"; | 736 | "\0C\0o\0n\0t\0r\0o\0l\0l\0e\0r\0"; |
715 | srclen = 42; | 737 | srclen = 42; |
716 | break; | 738 | break; |
717 | default: | 739 | default: |
718 | debug("unknown value DT_STRING %x\n", | 740 | debug("unknown value DT_STRING %x\n", |
719 | le16_to_cpu(req->value)); | 741 | le16_to_cpu(req->value)); |
720 | goto unknown; | 742 | goto unknown; |
721 | } | 743 | } |
722 | break; | 744 | break; |
723 | default: | 745 | default: |
724 | debug("unknown value %x\n", le16_to_cpu(req->value)); | 746 | debug("unknown value %x\n", le16_to_cpu(req->value)); |
725 | goto unknown; | 747 | goto unknown; |
726 | } | 748 | } |
727 | break; | 749 | break; |
728 | case USB_REQ_GET_DESCRIPTOR | ((USB_DIR_IN | USB_RT_HUB) << 8): | 750 | case USB_REQ_GET_DESCRIPTOR | ((USB_DIR_IN | USB_RT_HUB) << 8): |
729 | switch (le16_to_cpu(req->value) >> 8) { | 751 | switch (le16_to_cpu(req->value) >> 8) { |
730 | case USB_DT_HUB: | 752 | case USB_DT_HUB: |
731 | debug("USB_DT_HUB config\n"); | 753 | debug("USB_DT_HUB config\n"); |
732 | srcptr = &descriptor.hub; | 754 | srcptr = &descriptor.hub; |
733 | srclen = descriptor.hub.bLength; | 755 | srclen = descriptor.hub.bLength; |
734 | break; | 756 | break; |
735 | default: | 757 | default: |
736 | debug("unknown value %x\n", le16_to_cpu(req->value)); | 758 | debug("unknown value %x\n", le16_to_cpu(req->value)); |
737 | goto unknown; | 759 | goto unknown; |
738 | } | 760 | } |
739 | break; | 761 | break; |
740 | case USB_REQ_SET_ADDRESS | (USB_RECIP_DEVICE << 8): | 762 | case USB_REQ_SET_ADDRESS | (USB_RECIP_DEVICE << 8): |
741 | debug("USB_REQ_SET_ADDRESS\n"); | 763 | debug("USB_REQ_SET_ADDRESS\n"); |
742 | ctrl->rootdev = le16_to_cpu(req->value); | 764 | ctrl->rootdev = le16_to_cpu(req->value); |
743 | break; | 765 | break; |
744 | case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: | 766 | case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: |
745 | debug("USB_REQ_SET_CONFIGURATION\n"); | 767 | debug("USB_REQ_SET_CONFIGURATION\n"); |
746 | /* Nothing to do */ | 768 | /* Nothing to do */ |
747 | break; | 769 | break; |
748 | case USB_REQ_GET_STATUS | ((USB_DIR_IN | USB_RT_HUB) << 8): | 770 | case USB_REQ_GET_STATUS | ((USB_DIR_IN | USB_RT_HUB) << 8): |
749 | tmpbuf[0] = 1; /* USB_STATUS_SELFPOWERED */ | 771 | tmpbuf[0] = 1; /* USB_STATUS_SELFPOWERED */ |
750 | tmpbuf[1] = 0; | 772 | tmpbuf[1] = 0; |
751 | srcptr = tmpbuf; | 773 | srcptr = tmpbuf; |
752 | srclen = 2; | 774 | srclen = 2; |
753 | break; | 775 | break; |
754 | case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8): | 776 | case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8): |
755 | memset(tmpbuf, 0, 4); | 777 | memset(tmpbuf, 0, 4); |
756 | reg = ehci_readl(status_reg); | 778 | reg = ehci_readl(status_reg); |
757 | if (reg & EHCI_PS_CS) | 779 | if (reg & EHCI_PS_CS) |
758 | tmpbuf[0] |= USB_PORT_STAT_CONNECTION; | 780 | tmpbuf[0] |= USB_PORT_STAT_CONNECTION; |
759 | if (reg & EHCI_PS_PE) | 781 | if (reg & EHCI_PS_PE) |
760 | tmpbuf[0] |= USB_PORT_STAT_ENABLE; | 782 | tmpbuf[0] |= USB_PORT_STAT_ENABLE; |
761 | if (reg & EHCI_PS_SUSP) | 783 | if (reg & EHCI_PS_SUSP) |
762 | tmpbuf[0] |= USB_PORT_STAT_SUSPEND; | 784 | tmpbuf[0] |= USB_PORT_STAT_SUSPEND; |
763 | if (reg & EHCI_PS_OCA) | 785 | if (reg & EHCI_PS_OCA) |
764 | tmpbuf[0] |= USB_PORT_STAT_OVERCURRENT; | 786 | tmpbuf[0] |= USB_PORT_STAT_OVERCURRENT; |
765 | if (reg & EHCI_PS_PR) | 787 | if (reg & EHCI_PS_PR) |
766 | tmpbuf[0] |= USB_PORT_STAT_RESET; | 788 | tmpbuf[0] |= USB_PORT_STAT_RESET; |
767 | if (reg & EHCI_PS_PP) | 789 | if (reg & EHCI_PS_PP) |
768 | tmpbuf[1] |= USB_PORT_STAT_POWER >> 8; | 790 | tmpbuf[1] |= USB_PORT_STAT_POWER >> 8; |
769 | 791 | ||
770 | if (ehci_is_TDI()) { | 792 | if (ehci_is_TDI()) { |
771 | switch (ehci_get_port_speed(ctrl->hcor, reg)) { | 793 | switch (ehci_get_port_speed(ctrl->hcor, reg)) { |
772 | case PORTSC_PSPD_FS: | 794 | case PORTSC_PSPD_FS: |
773 | break; | 795 | break; |
774 | case PORTSC_PSPD_LS: | 796 | case PORTSC_PSPD_LS: |
775 | tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8; | 797 | tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8; |
776 | break; | 798 | break; |
777 | case PORTSC_PSPD_HS: | 799 | case PORTSC_PSPD_HS: |
778 | default: | 800 | default: |
779 | tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; | 801 | tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; |
780 | break; | 802 | break; |
781 | } | 803 | } |
782 | } else { | 804 | } else { |
783 | tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; | 805 | tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; |
784 | } | 806 | } |
785 | 807 | ||
786 | if (reg & EHCI_PS_CSC) | 808 | if (reg & EHCI_PS_CSC) |
787 | tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION; | 809 | tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION; |
788 | if (reg & EHCI_PS_PEC) | 810 | if (reg & EHCI_PS_PEC) |
789 | tmpbuf[2] |= USB_PORT_STAT_C_ENABLE; | 811 | tmpbuf[2] |= USB_PORT_STAT_C_ENABLE; |
790 | if (reg & EHCI_PS_OCC) | 812 | if (reg & EHCI_PS_OCC) |
791 | tmpbuf[2] |= USB_PORT_STAT_C_OVERCURRENT; | 813 | tmpbuf[2] |= USB_PORT_STAT_C_OVERCURRENT; |
792 | if (ctrl->portreset & (1 << port)) | 814 | if (ctrl->portreset & (1 << port)) |
793 | tmpbuf[2] |= USB_PORT_STAT_C_RESET; | 815 | tmpbuf[2] |= USB_PORT_STAT_C_RESET; |
794 | 816 | ||
795 | srcptr = tmpbuf; | 817 | srcptr = tmpbuf; |
796 | srclen = 4; | 818 | srclen = 4; |
797 | break; | 819 | break; |
798 | case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): | 820 | case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): |
799 | reg = ehci_readl(status_reg); | 821 | reg = ehci_readl(status_reg); |
800 | reg &= ~EHCI_PS_CLEAR; | 822 | reg &= ~EHCI_PS_CLEAR; |
801 | switch (le16_to_cpu(req->value)) { | 823 | switch (le16_to_cpu(req->value)) { |
802 | case USB_PORT_FEAT_ENABLE: | 824 | case USB_PORT_FEAT_ENABLE: |
803 | reg |= EHCI_PS_PE; | 825 | reg |= EHCI_PS_PE; |
804 | ehci_writel(status_reg, reg); | 826 | ehci_writel(status_reg, reg); |
805 | break; | 827 | break; |
806 | case USB_PORT_FEAT_POWER: | 828 | case USB_PORT_FEAT_POWER: |
807 | if (HCS_PPC(ehci_readl(&ctrl->hccr->cr_hcsparams))) { | 829 | if (HCS_PPC(ehci_readl(&ctrl->hccr->cr_hcsparams))) { |
808 | reg |= EHCI_PS_PP; | 830 | reg |= EHCI_PS_PP; |
809 | ehci_writel(status_reg, reg); | 831 | ehci_writel(status_reg, reg); |
810 | } | 832 | } |
811 | break; | 833 | break; |
812 | case USB_PORT_FEAT_RESET: | 834 | case USB_PORT_FEAT_RESET: |
813 | if ((reg & (EHCI_PS_PE | EHCI_PS_CS)) == EHCI_PS_CS && | 835 | if ((reg & (EHCI_PS_PE | EHCI_PS_CS)) == EHCI_PS_CS && |
814 | !ehci_is_TDI() && | 836 | !ehci_is_TDI() && |
815 | EHCI_PS_IS_LOWSPEED(reg)) { | 837 | EHCI_PS_IS_LOWSPEED(reg)) { |
816 | /* Low speed device, give up ownership. */ | 838 | /* Low speed device, give up ownership. */ |
817 | debug("port %d low speed --> companion\n", | 839 | debug("port %d low speed --> companion\n", |
818 | port - 1); | 840 | port - 1); |
819 | reg |= EHCI_PS_PO; | 841 | reg |= EHCI_PS_PO; |
820 | ehci_writel(status_reg, reg); | 842 | ehci_writel(status_reg, reg); |
821 | break; | 843 | break; |
822 | } else { | 844 | } else { |
823 | int ret; | 845 | int ret; |
824 | 846 | ||
825 | reg |= EHCI_PS_PR; | 847 | reg |= EHCI_PS_PR; |
826 | reg &= ~EHCI_PS_PE; | 848 | reg &= ~EHCI_PS_PE; |
827 | ehci_writel(status_reg, reg); | 849 | ehci_writel(status_reg, reg); |
828 | /* | 850 | /* |
829 | * caller must wait, then call GetPortStatus | 851 | * caller must wait, then call GetPortStatus |
830 | * usb 2.0 specification say 50 ms resets on | 852 | * usb 2.0 specification say 50 ms resets on |
831 | * root | 853 | * root |
832 | */ | 854 | */ |
833 | ehci_powerup_fixup(status_reg, ®); | 855 | ehci_powerup_fixup(status_reg, ®); |
834 | 856 | ||
835 | ehci_writel(status_reg, reg & ~EHCI_PS_PR); | 857 | ehci_writel(status_reg, reg & ~EHCI_PS_PR); |
836 | /* | 858 | /* |
837 | * A host controller must terminate the reset | 859 | * A host controller must terminate the reset |
838 | * and stabilize the state of the port within | 860 | * and stabilize the state of the port within |
839 | * 2 milliseconds | 861 | * 2 milliseconds |
840 | */ | 862 | */ |
841 | ret = handshake(status_reg, EHCI_PS_PR, 0, | 863 | ret = handshake(status_reg, EHCI_PS_PR, 0, |
842 | 2 * 1000); | 864 | 2 * 1000); |
843 | if (!ret) | 865 | if (!ret) |
844 | ctrl->portreset |= 1 << port; | 866 | ctrl->portreset |= 1 << port; |
845 | else | 867 | else |
846 | printf("port(%d) reset error\n", | 868 | printf("port(%d) reset error\n", |
847 | port - 1); | 869 | port - 1); |
848 | } | 870 | } |
849 | break; | 871 | break; |
850 | case USB_PORT_FEAT_TEST: | 872 | case USB_PORT_FEAT_TEST: |
851 | ehci_shutdown(ctrl); | 873 | ehci_shutdown(ctrl); |
852 | reg &= ~(0xf << 16); | 874 | reg &= ~(0xf << 16); |
853 | reg |= ((le16_to_cpu(req->index) >> 8) & 0xf) << 16; | 875 | reg |= ((le16_to_cpu(req->index) >> 8) & 0xf) << 16; |
854 | ehci_writel(status_reg, reg); | 876 | ehci_writel(status_reg, reg); |
855 | break; | 877 | break; |
856 | default: | 878 | default: |
857 | debug("unknown feature %x\n", le16_to_cpu(req->value)); | 879 | debug("unknown feature %x\n", le16_to_cpu(req->value)); |
858 | goto unknown; | 880 | goto unknown; |
859 | } | 881 | } |
860 | /* unblock posted writes */ | 882 | /* unblock posted writes */ |
861 | (void) ehci_readl(&ctrl->hcor->or_usbcmd); | 883 | (void) ehci_readl(&ctrl->hcor->or_usbcmd); |
862 | break; | 884 | break; |
863 | case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): | 885 | case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): |
864 | reg = ehci_readl(status_reg); | 886 | reg = ehci_readl(status_reg); |
865 | reg &= ~EHCI_PS_CLEAR; | 887 | reg &= ~EHCI_PS_CLEAR; |
866 | switch (le16_to_cpu(req->value)) { | 888 | switch (le16_to_cpu(req->value)) { |
867 | case USB_PORT_FEAT_ENABLE: | 889 | case USB_PORT_FEAT_ENABLE: |
868 | reg &= ~EHCI_PS_PE; | 890 | reg &= ~EHCI_PS_PE; |
869 | break; | 891 | break; |
870 | case USB_PORT_FEAT_C_ENABLE: | 892 | case USB_PORT_FEAT_C_ENABLE: |
871 | reg |= EHCI_PS_PE; | 893 | reg |= EHCI_PS_PE; |
872 | break; | 894 | break; |
873 | case USB_PORT_FEAT_POWER: | 895 | case USB_PORT_FEAT_POWER: |
874 | if (HCS_PPC(ehci_readl(&ctrl->hccr->cr_hcsparams))) | 896 | if (HCS_PPC(ehci_readl(&ctrl->hccr->cr_hcsparams))) |
875 | reg &= ~EHCI_PS_PP; | 897 | reg &= ~EHCI_PS_PP; |
876 | break; | 898 | break; |
877 | case USB_PORT_FEAT_C_CONNECTION: | 899 | case USB_PORT_FEAT_C_CONNECTION: |
878 | reg |= EHCI_PS_CSC; | 900 | reg |= EHCI_PS_CSC; |
879 | break; | 901 | break; |
880 | case USB_PORT_FEAT_OVER_CURRENT: | 902 | case USB_PORT_FEAT_OVER_CURRENT: |
881 | reg |= EHCI_PS_OCC; | 903 | reg |= EHCI_PS_OCC; |
882 | break; | 904 | break; |
883 | case USB_PORT_FEAT_C_RESET: | 905 | case USB_PORT_FEAT_C_RESET: |
884 | ctrl->portreset &= ~(1 << port); | 906 | ctrl->portreset &= ~(1 << port); |
885 | break; | 907 | break; |
886 | default: | 908 | default: |
887 | debug("unknown feature %x\n", le16_to_cpu(req->value)); | 909 | debug("unknown feature %x\n", le16_to_cpu(req->value)); |
888 | goto unknown; | 910 | goto unknown; |
889 | } | 911 | } |
890 | ehci_writel(status_reg, reg); | 912 | ehci_writel(status_reg, reg); |
891 | /* unblock posted write */ | 913 | /* unblock posted write */ |
892 | (void) ehci_readl(&ctrl->hcor->or_usbcmd); | 914 | (void) ehci_readl(&ctrl->hcor->or_usbcmd); |
893 | break; | 915 | break; |
894 | default: | 916 | default: |
895 | debug("Unknown request\n"); | 917 | debug("Unknown request\n"); |
896 | goto unknown; | 918 | goto unknown; |
897 | } | 919 | } |
898 | 920 | ||
899 | mdelay(1); | 921 | mdelay(1); |
900 | len = min3(srclen, le16_to_cpu(req->length), length); | 922 | len = min3(srclen, le16_to_cpu(req->length), length); |
901 | if (srcptr != NULL && len > 0) | 923 | if (srcptr != NULL && len > 0) |
902 | memcpy(buffer, srcptr, len); | 924 | memcpy(buffer, srcptr, len); |
903 | else | 925 | else |
904 | debug("Len is 0\n"); | 926 | debug("Len is 0\n"); |
905 | 927 | ||
906 | dev->act_len = len; | 928 | dev->act_len = len; |
907 | dev->status = 0; | 929 | dev->status = 0; |
908 | return 0; | 930 | return 0; |
909 | 931 | ||
910 | unknown: | 932 | unknown: |
911 | debug("requesttype=%x, request=%x, value=%x, index=%x, length=%x\n", | 933 | debug("requesttype=%x, request=%x, value=%x, index=%x, length=%x\n", |
912 | req->requesttype, req->request, le16_to_cpu(req->value), | 934 | req->requesttype, req->request, le16_to_cpu(req->value), |
913 | le16_to_cpu(req->index), le16_to_cpu(req->length)); | 935 | le16_to_cpu(req->index), le16_to_cpu(req->length)); |
914 | 936 | ||
915 | dev->act_len = 0; | 937 | dev->act_len = 0; |
916 | dev->status = USB_ST_STALLED; | 938 | dev->status = USB_ST_STALLED; |
917 | return -1; | 939 | return -1; |
918 | } | 940 | } |
919 | 941 | ||
920 | int usb_lowlevel_stop(int index) | 942 | int usb_lowlevel_stop(int index) |
921 | { | 943 | { |
922 | ehci_shutdown(&ehcic[index]); | 944 | ehci_shutdown(&ehcic[index]); |
923 | return ehci_hcd_stop(index); | 945 | return ehci_hcd_stop(index); |
924 | } | 946 | } |
925 | 947 | ||
926 | int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) | 948 | int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) |
927 | { | 949 | { |
928 | uint32_t reg; | 950 | uint32_t reg; |
929 | uint32_t cmd; | 951 | uint32_t cmd; |
930 | struct QH *qh_list; | 952 | struct QH *qh_list; |
931 | struct QH *periodic; | 953 | struct QH *periodic; |
932 | int i; | 954 | int i; |
933 | int rc; | 955 | int rc; |
934 | 956 | ||
935 | rc = ehci_hcd_init(index, init, &ehcic[index].hccr, &ehcic[index].hcor); | 957 | rc = ehci_hcd_init(index, init, &ehcic[index].hccr, &ehcic[index].hcor); |
936 | if (rc) | 958 | if (rc) |
937 | return rc; | 959 | return rc; |
938 | if (init == USB_INIT_DEVICE) | 960 | if (init == USB_INIT_DEVICE) |
939 | goto done; | 961 | goto done; |
940 | 962 | ||
941 | /* EHCI spec section 4.1 */ | 963 | /* EHCI spec section 4.1 */ |
942 | if (ehci_reset(index)) | 964 | if (ehci_reset(index)) |
943 | return -1; | 965 | return -1; |
944 | 966 | ||
945 | #if defined(CONFIG_EHCI_HCD_INIT_AFTER_RESET) | 967 | #if defined(CONFIG_EHCI_HCD_INIT_AFTER_RESET) |
946 | rc = ehci_hcd_init(index, init, &ehcic[index].hccr, &ehcic[index].hcor); | 968 | rc = ehci_hcd_init(index, init, &ehcic[index].hccr, &ehcic[index].hcor); |
947 | if (rc) | 969 | if (rc) |
948 | return rc; | 970 | return rc; |
949 | #endif | 971 | #endif |
950 | /* Set the high address word (aka segment) for 64-bit controller */ | 972 | /* Set the high address word (aka segment) for 64-bit controller */ |
951 | if (ehci_readl(&ehcic[index].hccr->cr_hccparams) & 1) | 973 | if (ehci_readl(&ehcic[index].hccr->cr_hccparams) & 1) |
952 | ehci_writel(&ehcic[index].hcor->or_ctrldssegment, 0); | 974 | ehci_writel(&ehcic[index].hcor->or_ctrldssegment, 0); |
953 | 975 | ||
954 | qh_list = &ehcic[index].qh_list; | 976 | qh_list = &ehcic[index].qh_list; |
955 | 977 | ||
956 | /* Set head of reclaim list */ | 978 | /* Set head of reclaim list */ |
957 | memset(qh_list, 0, sizeof(*qh_list)); | 979 | memset(qh_list, 0, sizeof(*qh_list)); |
958 | qh_list->qh_link = cpu_to_hc32((uint32_t)qh_list | QH_LINK_TYPE_QH); | 980 | qh_list->qh_link = cpu_to_hc32((uint32_t)qh_list | QH_LINK_TYPE_QH); |
959 | qh_list->qh_endpt1 = cpu_to_hc32(QH_ENDPT1_H(1) | | 981 | qh_list->qh_endpt1 = cpu_to_hc32(QH_ENDPT1_H(1) | |
960 | QH_ENDPT1_EPS(USB_SPEED_HIGH)); | 982 | QH_ENDPT1_EPS(USB_SPEED_HIGH)); |
961 | qh_list->qh_curtd = cpu_to_hc32(QT_NEXT_TERMINATE); | 983 | qh_list->qh_curtd = cpu_to_hc32(QT_NEXT_TERMINATE); |
962 | qh_list->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); | 984 | qh_list->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); |
963 | qh_list->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); | 985 | qh_list->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); |
964 | qh_list->qh_overlay.qt_token = | 986 | qh_list->qh_overlay.qt_token = |
965 | cpu_to_hc32(QT_TOKEN_STATUS(QT_TOKEN_STATUS_HALTED)); | 987 | cpu_to_hc32(QT_TOKEN_STATUS(QT_TOKEN_STATUS_HALTED)); |
966 | 988 | ||
967 | flush_dcache_range((uint32_t)qh_list, | 989 | flush_dcache_range((uint32_t)qh_list, |
968 | ALIGN_END_ADDR(struct QH, qh_list, 1)); | 990 | ALIGN_END_ADDR(struct QH, qh_list, 1)); |
969 | 991 | ||
970 | /* Set async. queue head pointer. */ | 992 | /* Set async. queue head pointer. */ |
971 | ehci_writel(&ehcic[index].hcor->or_asynclistaddr, (uint32_t)qh_list); | 993 | ehci_writel(&ehcic[index].hcor->or_asynclistaddr, (uint32_t)qh_list); |
972 | 994 | ||
973 | /* | 995 | /* |
974 | * Set up periodic list | 996 | * Set up periodic list |
975 | * Step 1: Parent QH for all periodic transfers. | 997 | * Step 1: Parent QH for all periodic transfers. |
976 | */ | 998 | */ |
999 | ehcic[index].periodic_schedules = 0; | ||
977 | periodic = &ehcic[index].periodic_queue; | 1000 | periodic = &ehcic[index].periodic_queue; |
978 | memset(periodic, 0, sizeof(*periodic)); | 1001 | memset(periodic, 0, sizeof(*periodic)); |
979 | periodic->qh_link = cpu_to_hc32(QH_LINK_TERMINATE); | 1002 | periodic->qh_link = cpu_to_hc32(QH_LINK_TERMINATE); |
980 | periodic->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); | 1003 | periodic->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); |
981 | periodic->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); | 1004 | periodic->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); |
982 | 1005 | ||
983 | flush_dcache_range((uint32_t)periodic, | 1006 | flush_dcache_range((uint32_t)periodic, |
984 | ALIGN_END_ADDR(struct QH, periodic, 1)); | 1007 | ALIGN_END_ADDR(struct QH, periodic, 1)); |
985 | 1008 | ||
986 | /* | 1009 | /* |
987 | * Step 2: Setup frame-list: Every microframe, USB tries the same list. | 1010 | * Step 2: Setup frame-list: Every microframe, USB tries the same list. |
988 | * In particular, device specifications on polling frequency | 1011 | * In particular, device specifications on polling frequency |
989 | * are disregarded. Keyboards seem to send NAK/NYet reliably | 1012 | * are disregarded. Keyboards seem to send NAK/NYet reliably |
990 | * when polled with an empty buffer. | 1013 | * when polled with an empty buffer. |
991 | * | 1014 | * |
992 | * Split Transactions will be spread across microframes using | 1015 | * Split Transactions will be spread across microframes using |
993 | * S-mask and C-mask. | 1016 | * S-mask and C-mask. |
994 | */ | 1017 | */ |
995 | if (ehcic[index].periodic_list == NULL) | 1018 | if (ehcic[index].periodic_list == NULL) |
996 | ehcic[index].periodic_list = memalign(4096, 1024 * 4); | 1019 | ehcic[index].periodic_list = memalign(4096, 1024 * 4); |
997 | 1020 | ||
998 | if (!ehcic[index].periodic_list) | 1021 | if (!ehcic[index].periodic_list) |
999 | return -ENOMEM; | 1022 | return -ENOMEM; |
1000 | for (i = 0; i < 1024; i++) { | 1023 | for (i = 0; i < 1024; i++) { |
1001 | ehcic[index].periodic_list[i] = cpu_to_hc32((uint32_t)periodic | 1024 | ehcic[index].periodic_list[i] = cpu_to_hc32((uint32_t)periodic |
1002 | | QH_LINK_TYPE_QH); | 1025 | | QH_LINK_TYPE_QH); |
1003 | } | 1026 | } |
1004 | 1027 | ||
1005 | flush_dcache_range((uint32_t)ehcic[index].periodic_list, | 1028 | flush_dcache_range((uint32_t)ehcic[index].periodic_list, |
1006 | ALIGN_END_ADDR(uint32_t, ehcic[index].periodic_list, | 1029 | ALIGN_END_ADDR(uint32_t, ehcic[index].periodic_list, |
1007 | 1024)); | 1030 | 1024)); |
1008 | 1031 | ||
1009 | /* Set periodic list base address */ | 1032 | /* Set periodic list base address */ |
1010 | ehci_writel(&ehcic[index].hcor->or_periodiclistbase, | 1033 | ehci_writel(&ehcic[index].hcor->or_periodiclistbase, |
1011 | (uint32_t)ehcic[index].periodic_list); | 1034 | (uint32_t)ehcic[index].periodic_list); |
1012 | 1035 | ||
1013 | reg = ehci_readl(&ehcic[index].hccr->cr_hcsparams); | 1036 | reg = ehci_readl(&ehcic[index].hccr->cr_hcsparams); |
1014 | descriptor.hub.bNbrPorts = HCS_N_PORTS(reg); | 1037 | descriptor.hub.bNbrPorts = HCS_N_PORTS(reg); |
1015 | debug("Register %x NbrPorts %d\n", reg, descriptor.hub.bNbrPorts); | 1038 | debug("Register %x NbrPorts %d\n", reg, descriptor.hub.bNbrPorts); |
1016 | /* Port Indicators */ | 1039 | /* Port Indicators */ |
1017 | if (HCS_INDICATOR(reg)) | 1040 | if (HCS_INDICATOR(reg)) |
1018 | put_unaligned(get_unaligned(&descriptor.hub.wHubCharacteristics) | 1041 | put_unaligned(get_unaligned(&descriptor.hub.wHubCharacteristics) |
1019 | | 0x80, &descriptor.hub.wHubCharacteristics); | 1042 | | 0x80, &descriptor.hub.wHubCharacteristics); |
1020 | /* Port Power Control */ | 1043 | /* Port Power Control */ |
1021 | if (HCS_PPC(reg)) | 1044 | if (HCS_PPC(reg)) |
1022 | put_unaligned(get_unaligned(&descriptor.hub.wHubCharacteristics) | 1045 | put_unaligned(get_unaligned(&descriptor.hub.wHubCharacteristics) |
1023 | | 0x01, &descriptor.hub.wHubCharacteristics); | 1046 | | 0x01, &descriptor.hub.wHubCharacteristics); |
1024 | 1047 | ||
1025 | /* Start the host controller. */ | 1048 | /* Start the host controller. */ |
1026 | cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd); | 1049 | cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd); |
1027 | /* | 1050 | /* |
1028 | * Philips, Intel, and maybe others need CMD_RUN before the | 1051 | * Philips, Intel, and maybe others need CMD_RUN before the |
1029 | * root hub will detect new devices (why?); NEC doesn't | 1052 | * root hub will detect new devices (why?); NEC doesn't |
1030 | */ | 1053 | */ |
1031 | cmd &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET); | 1054 | cmd &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET); |
1032 | cmd |= CMD_RUN; | 1055 | cmd |= CMD_RUN; |
1033 | ehci_writel(&ehcic[index].hcor->or_usbcmd, cmd); | 1056 | ehci_writel(&ehcic[index].hcor->or_usbcmd, cmd); |
1034 | 1057 | ||
1035 | #ifndef CONFIG_USB_EHCI_FARADAY | 1058 | #ifndef CONFIG_USB_EHCI_FARADAY |
1036 | /* take control over the ports */ | 1059 | /* take control over the ports */ |
1037 | cmd = ehci_readl(&ehcic[index].hcor->or_configflag); | 1060 | cmd = ehci_readl(&ehcic[index].hcor->or_configflag); |
1038 | cmd |= FLAG_CF; | 1061 | cmd |= FLAG_CF; |
1039 | ehci_writel(&ehcic[index].hcor->or_configflag, cmd); | 1062 | ehci_writel(&ehcic[index].hcor->or_configflag, cmd); |
1040 | #endif | 1063 | #endif |
1041 | 1064 | ||
1042 | /* unblock posted write */ | 1065 | /* unblock posted write */ |
1043 | cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd); | 1066 | cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd); |
1044 | mdelay(5); | 1067 | mdelay(5); |
1045 | reg = HC_VERSION(ehci_readl(&ehcic[index].hccr->cr_capbase)); | 1068 | reg = HC_VERSION(ehci_readl(&ehcic[index].hccr->cr_capbase)); |
1046 | printf("USB EHCI %x.%02x\n", reg >> 8, reg & 0xff); | 1069 | printf("USB EHCI %x.%02x\n", reg >> 8, reg & 0xff); |
1047 | 1070 | ||
1048 | ehcic[index].rootdev = 0; | 1071 | ehcic[index].rootdev = 0; |
1049 | done: | 1072 | done: |
1050 | *controller = &ehcic[index]; | 1073 | *controller = &ehcic[index]; |
1051 | return 0; | 1074 | return 0; |
1052 | } | 1075 | } |
1053 | 1076 | ||
1054 | int | 1077 | int |
1055 | submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, | 1078 | submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, |
1056 | int length) | 1079 | int length) |
1057 | { | 1080 | { |
1058 | 1081 | ||
1059 | if (usb_pipetype(pipe) != PIPE_BULK) { | 1082 | if (usb_pipetype(pipe) != PIPE_BULK) { |
1060 | debug("non-bulk pipe (type=%lu)", usb_pipetype(pipe)); | 1083 | debug("non-bulk pipe (type=%lu)", usb_pipetype(pipe)); |
1061 | return -1; | 1084 | return -1; |
1062 | } | 1085 | } |
1063 | return ehci_submit_async(dev, pipe, buffer, length, NULL); | 1086 | return ehci_submit_async(dev, pipe, buffer, length, NULL); |
1064 | } | 1087 | } |
1065 | 1088 | ||
1066 | int | 1089 | int |
1067 | submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, | 1090 | submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, |
1068 | int length, struct devrequest *setup) | 1091 | int length, struct devrequest *setup) |
1069 | { | 1092 | { |
1070 | struct ehci_ctrl *ctrl = dev->controller; | 1093 | struct ehci_ctrl *ctrl = dev->controller; |
1071 | 1094 | ||
1072 | if (usb_pipetype(pipe) != PIPE_CONTROL) { | 1095 | if (usb_pipetype(pipe) != PIPE_CONTROL) { |
1073 | debug("non-control pipe (type=%lu)", usb_pipetype(pipe)); | 1096 | debug("non-control pipe (type=%lu)", usb_pipetype(pipe)); |
1074 | return -1; | 1097 | return -1; |
1075 | } | 1098 | } |
1076 | 1099 | ||
1077 | if (usb_pipedevice(pipe) == ctrl->rootdev) { | 1100 | if (usb_pipedevice(pipe) == ctrl->rootdev) { |
1078 | if (!ctrl->rootdev) | 1101 | if (!ctrl->rootdev) |
1079 | dev->speed = USB_SPEED_HIGH; | 1102 | dev->speed = USB_SPEED_HIGH; |
1080 | return ehci_submit_root(dev, pipe, buffer, length, setup); | 1103 | return ehci_submit_root(dev, pipe, buffer, length, setup); |
1081 | } | 1104 | } |
1082 | return ehci_submit_async(dev, pipe, buffer, length, setup); | 1105 | return ehci_submit_async(dev, pipe, buffer, length, setup); |
1083 | } | 1106 | } |
1084 | 1107 | ||
1085 | struct int_queue { | 1108 | struct int_queue { |
1086 | struct QH *first; | 1109 | struct QH *first; |
1087 | struct QH *current; | 1110 | struct QH *current; |
1088 | struct QH *last; | 1111 | struct QH *last; |
1089 | struct qTD *tds; | 1112 | struct qTD *tds; |
1090 | }; | 1113 | }; |
1091 | 1114 | ||
1092 | #define NEXT_QH(qh) (struct QH *)(hc32_to_cpu((qh)->qh_link) & ~0x1f) | 1115 | #define NEXT_QH(qh) (struct QH *)(hc32_to_cpu((qh)->qh_link) & ~0x1f) |
1093 | 1116 | ||
1094 | static int | 1117 | static int |
1095 | enable_periodic(struct ehci_ctrl *ctrl) | 1118 | enable_periodic(struct ehci_ctrl *ctrl) |
1096 | { | 1119 | { |
1097 | uint32_t cmd; | 1120 | uint32_t cmd; |
1098 | struct ehci_hcor *hcor = ctrl->hcor; | 1121 | struct ehci_hcor *hcor = ctrl->hcor; |
1099 | int ret; | 1122 | int ret; |
1100 | 1123 | ||
1101 | cmd = ehci_readl(&hcor->or_usbcmd); | 1124 | cmd = ehci_readl(&hcor->or_usbcmd); |
1102 | cmd |= CMD_PSE; | 1125 | cmd |= CMD_PSE; |
1103 | ehci_writel(&hcor->or_usbcmd, cmd); | 1126 | ehci_writel(&hcor->or_usbcmd, cmd); |
1104 | 1127 | ||
1105 | ret = handshake((uint32_t *)&hcor->or_usbsts, | 1128 | ret = handshake((uint32_t *)&hcor->or_usbsts, |
1106 | STS_PSS, STS_PSS, 100 * 1000); | 1129 | STS_PSS, STS_PSS, 100 * 1000); |
1107 | if (ret < 0) { | 1130 | if (ret < 0) { |
1108 | printf("EHCI failed: timeout when enabling periodic list\n"); | 1131 | printf("EHCI failed: timeout when enabling periodic list\n"); |
1109 | return -ETIMEDOUT; | 1132 | return -ETIMEDOUT; |
1110 | } | 1133 | } |
1111 | udelay(1000); | 1134 | udelay(1000); |
1112 | return 0; | 1135 | return 0; |
1113 | } | 1136 | } |
1114 | 1137 | ||
1115 | static int | 1138 | static int |
1116 | disable_periodic(struct ehci_ctrl *ctrl) | 1139 | disable_periodic(struct ehci_ctrl *ctrl) |
1117 | { | 1140 | { |
1118 | uint32_t cmd; | 1141 | uint32_t cmd; |
1119 | struct ehci_hcor *hcor = ctrl->hcor; | 1142 | struct ehci_hcor *hcor = ctrl->hcor; |
1120 | int ret; | 1143 | int ret; |
1121 | 1144 | ||
1122 | cmd = ehci_readl(&hcor->or_usbcmd); | 1145 | cmd = ehci_readl(&hcor->or_usbcmd); |
1123 | cmd &= ~CMD_PSE; | 1146 | cmd &= ~CMD_PSE; |
1124 | ehci_writel(&hcor->or_usbcmd, cmd); | 1147 | ehci_writel(&hcor->or_usbcmd, cmd); |
1125 | 1148 | ||
1126 | ret = handshake((uint32_t *)&hcor->or_usbsts, | 1149 | ret = handshake((uint32_t *)&hcor->or_usbsts, |
1127 | STS_PSS, 0, 100 * 1000); | 1150 | STS_PSS, 0, 100 * 1000); |
1128 | if (ret < 0) { | 1151 | if (ret < 0) { |
1129 | printf("EHCI failed: timeout when disabling periodic list\n"); | 1152 | printf("EHCI failed: timeout when disabling periodic list\n"); |
1130 | return -ETIMEDOUT; | 1153 | return -ETIMEDOUT; |
1131 | } | 1154 | } |
1132 | return 0; | 1155 | return 0; |
1133 | } | 1156 | } |
1134 | 1157 | ||
1135 | static int periodic_schedules; | ||
1136 | |||
1137 | struct int_queue * | 1158 | struct int_queue * |
1138 | create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize, | 1159 | create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize, |
1139 | int elementsize, void *buffer) | 1160 | int elementsize, void *buffer) |
1140 | { | 1161 | { |
1141 | struct ehci_ctrl *ctrl = dev->controller; | 1162 | struct ehci_ctrl *ctrl = dev->controller; |
1142 | struct int_queue *result = NULL; | 1163 | struct int_queue *result = NULL; |
1143 | int i; | 1164 | int i; |
1144 | 1165 | ||
1145 | debug("Enter create_int_queue\n"); | 1166 | debug("Enter create_int_queue\n"); |
1146 | if (usb_pipetype(pipe) != PIPE_INTERRUPT) { | 1167 | if (usb_pipetype(pipe) != PIPE_INTERRUPT) { |
1147 | debug("non-interrupt pipe (type=%lu)", usb_pipetype(pipe)); | 1168 | debug("non-interrupt pipe (type=%lu)", usb_pipetype(pipe)); |
1148 | return NULL; | 1169 | return NULL; |
1149 | } | 1170 | } |
1150 | 1171 | ||
1151 | /* limit to 4 full pages worth of data - | 1172 | /* limit to 4 full pages worth of data - |
1152 | * we can safely fit them in a single TD, | 1173 | * we can safely fit them in a single TD, |
1153 | * no matter the alignment | 1174 | * no matter the alignment |
1154 | */ | 1175 | */ |
1155 | if (elementsize >= 16384) { | 1176 | if (elementsize >= 16384) { |
1156 | debug("too large elements for interrupt transfers\n"); | 1177 | debug("too large elements for interrupt transfers\n"); |
1157 | return NULL; | 1178 | return NULL; |
1158 | } | 1179 | } |
1159 | 1180 | ||
1160 | result = malloc(sizeof(*result)); | 1181 | result = malloc(sizeof(*result)); |
1161 | if (!result) { | 1182 | if (!result) { |
1162 | debug("ehci intr queue: out of memory\n"); | 1183 | debug("ehci intr queue: out of memory\n"); |
1163 | goto fail1; | 1184 | goto fail1; |
1164 | } | 1185 | } |
1165 | result->first = memalign(USB_DMA_MINALIGN, | 1186 | result->first = memalign(USB_DMA_MINALIGN, |
1166 | sizeof(struct QH) * queuesize); | 1187 | sizeof(struct QH) * queuesize); |
1167 | if (!result->first) { | 1188 | if (!result->first) { |
1168 | debug("ehci intr queue: out of memory\n"); | 1189 | debug("ehci intr queue: out of memory\n"); |
1169 | goto fail2; | 1190 | goto fail2; |
1170 | } | 1191 | } |
1171 | result->current = result->first; | 1192 | result->current = result->first; |
1172 | result->last = result->first + queuesize - 1; | 1193 | result->last = result->first + queuesize - 1; |
1173 | result->tds = memalign(USB_DMA_MINALIGN, | 1194 | result->tds = memalign(USB_DMA_MINALIGN, |
1174 | sizeof(struct qTD) * queuesize); | 1195 | sizeof(struct qTD) * queuesize); |
1175 | if (!result->tds) { | 1196 | if (!result->tds) { |
1176 | debug("ehci intr queue: out of memory\n"); | 1197 | debug("ehci intr queue: out of memory\n"); |
1177 | goto fail3; | 1198 | goto fail3; |
1178 | } | 1199 | } |
1179 | memset(result->first, 0, sizeof(struct QH) * queuesize); | 1200 | memset(result->first, 0, sizeof(struct QH) * queuesize); |
1180 | memset(result->tds, 0, sizeof(struct qTD) * queuesize); | 1201 | memset(result->tds, 0, sizeof(struct qTD) * queuesize); |
1181 | 1202 | ||
1182 | for (i = 0; i < queuesize; i++) { | 1203 | for (i = 0; i < queuesize; i++) { |
1183 | struct QH *qh = result->first + i; | 1204 | struct QH *qh = result->first + i; |
1184 | struct qTD *td = result->tds + i; | 1205 | struct qTD *td = result->tds + i; |
1185 | void **buf = &qh->buffer; | 1206 | void **buf = &qh->buffer; |
1186 | 1207 | ||
1187 | qh->qh_link = cpu_to_hc32((uint32_t)(qh+1) | QH_LINK_TYPE_QH); | 1208 | qh->qh_link = cpu_to_hc32((uint32_t)(qh+1) | QH_LINK_TYPE_QH); |
1188 | if (i == queuesize - 1) | 1209 | if (i == queuesize - 1) |
1189 | qh->qh_link = cpu_to_hc32(QH_LINK_TERMINATE); | 1210 | qh->qh_link = cpu_to_hc32(QH_LINK_TERMINATE); |
1190 | 1211 | ||
1191 | qh->qh_overlay.qt_next = cpu_to_hc32((uint32_t)td); | 1212 | qh->qh_overlay.qt_next = cpu_to_hc32((uint32_t)td); |
1192 | qh->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); | 1213 | qh->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); |
1193 | qh->qh_endpt1 = | 1214 | qh->qh_endpt1 = |
1194 | cpu_to_hc32((0 << 28) | /* No NAK reload (ehci 4.9) */ | 1215 | cpu_to_hc32((0 << 28) | /* No NAK reload (ehci 4.9) */ |
1195 | (usb_maxpacket(dev, pipe) << 16) | /* MPS */ | 1216 | (usb_maxpacket(dev, pipe) << 16) | /* MPS */ |
1196 | (1 << 14) | | 1217 | (1 << 14) | |
1197 | QH_ENDPT1_EPS(ehci_encode_speed(dev->speed)) | | 1218 | QH_ENDPT1_EPS(ehci_encode_speed(dev->speed)) | |
1198 | (usb_pipeendpoint(pipe) << 8) | /* Endpoint Number */ | 1219 | (usb_pipeendpoint(pipe) << 8) | /* Endpoint Number */ |
1199 | (usb_pipedevice(pipe) << 0)); | 1220 | (usb_pipedevice(pipe) << 0)); |
1200 | qh->qh_endpt2 = cpu_to_hc32((1 << 30) | /* 1 Tx per mframe */ | 1221 | qh->qh_endpt2 = cpu_to_hc32((1 << 30) | /* 1 Tx per mframe */ |
1201 | (1 << 0)); /* S-mask: microframe 0 */ | 1222 | (1 << 0)); /* S-mask: microframe 0 */ |
1202 | if (dev->speed == USB_SPEED_LOW || | 1223 | if (dev->speed == USB_SPEED_LOW || |
1203 | dev->speed == USB_SPEED_FULL) { | 1224 | dev->speed == USB_SPEED_FULL) { |
1204 | debug("TT: port: %d, hub address: %d\n", | 1225 | /* C-mask: microframes 2-4 */ |
1205 | dev->portnr, dev->parent->devnum); | 1226 | qh->qh_endpt2 |= cpu_to_hc32((0x1c << 8)); |
1206 | qh->qh_endpt2 |= cpu_to_hc32((dev->portnr << 23) | | ||
1207 | (dev->parent->devnum << 16) | | ||
1208 | (0x1c << 8)); /* C-mask: microframes 2-4 */ | ||
1209 | } | 1227 | } |
1228 | ehci_update_endpt2_dev_n_port(dev, qh); | ||
1210 | 1229 | ||
1211 | td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); | 1230 | td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); |
1212 | td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); | 1231 | td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); |
1213 | debug("communication direction is '%s'\n", | 1232 | debug("communication direction is '%s'\n", |
1214 | usb_pipein(pipe) ? "in" : "out"); | 1233 | usb_pipein(pipe) ? "in" : "out"); |
1215 | td->qt_token = cpu_to_hc32((elementsize << 16) | | 1234 | td->qt_token = cpu_to_hc32((elementsize << 16) | |
1216 | ((usb_pipein(pipe) ? 1 : 0) << 8) | /* IN/OUT token */ | 1235 | ((usb_pipein(pipe) ? 1 : 0) << 8) | /* IN/OUT token */ |
1217 | 0x80); /* active */ | 1236 | 0x80); /* active */ |
1218 | td->qt_buffer[0] = | 1237 | td->qt_buffer[0] = |
1219 | cpu_to_hc32((uint32_t)buffer + i * elementsize); | 1238 | cpu_to_hc32((uint32_t)buffer + i * elementsize); |
1220 | td->qt_buffer[1] = | 1239 | td->qt_buffer[1] = |
1221 | cpu_to_hc32((td->qt_buffer[0] + 0x1000) & ~0xfff); | 1240 | cpu_to_hc32((td->qt_buffer[0] + 0x1000) & ~0xfff); |
1222 | td->qt_buffer[2] = | 1241 | td->qt_buffer[2] = |
1223 | cpu_to_hc32((td->qt_buffer[0] + 0x2000) & ~0xfff); | 1242 | cpu_to_hc32((td->qt_buffer[0] + 0x2000) & ~0xfff); |
1224 | td->qt_buffer[3] = | 1243 | td->qt_buffer[3] = |
1225 | cpu_to_hc32((td->qt_buffer[0] + 0x3000) & ~0xfff); | 1244 | cpu_to_hc32((td->qt_buffer[0] + 0x3000) & ~0xfff); |
1226 | td->qt_buffer[4] = | 1245 | td->qt_buffer[4] = |
1227 | cpu_to_hc32((td->qt_buffer[0] + 0x4000) & ~0xfff); | 1246 | cpu_to_hc32((td->qt_buffer[0] + 0x4000) & ~0xfff); |
1228 | 1247 | ||
1229 | *buf = buffer + i * elementsize; | 1248 | *buf = buffer + i * elementsize; |
1230 | } | 1249 | } |
1231 | 1250 | ||
1232 | flush_dcache_range((uint32_t)buffer, | 1251 | flush_dcache_range((uint32_t)buffer, |
1233 | ALIGN_END_ADDR(char, buffer, | 1252 | ALIGN_END_ADDR(char, buffer, |
1234 | queuesize * elementsize)); | 1253 | queuesize * elementsize)); |
1235 | flush_dcache_range((uint32_t)result->first, | 1254 | flush_dcache_range((uint32_t)result->first, |
1236 | ALIGN_END_ADDR(struct QH, result->first, | 1255 | ALIGN_END_ADDR(struct QH, result->first, |
1237 | queuesize)); | 1256 | queuesize)); |
1238 | flush_dcache_range((uint32_t)result->tds, | 1257 | flush_dcache_range((uint32_t)result->tds, |
1239 | ALIGN_END_ADDR(struct qTD, result->tds, | 1258 | ALIGN_END_ADDR(struct qTD, result->tds, |
1240 | queuesize)); | 1259 | queuesize)); |
1241 | 1260 | ||
1242 | if (disable_periodic(ctrl) < 0) { | 1261 | if (disable_periodic(ctrl) < 0) { |
1243 | debug("FATAL: periodic should never fail, but did"); | 1262 | debug("FATAL: periodic should never fail, but did"); |
1244 | goto fail3; | 1263 | goto fail3; |
1245 | } | 1264 | } |
1246 | 1265 | ||
1247 | /* hook up to periodic list */ | 1266 | /* hook up to periodic list */ |
1248 | struct QH *list = &ctrl->periodic_queue; | 1267 | struct QH *list = &ctrl->periodic_queue; |
1249 | result->last->qh_link = list->qh_link; | 1268 | result->last->qh_link = list->qh_link; |
1250 | list->qh_link = cpu_to_hc32((uint32_t)result->first | QH_LINK_TYPE_QH); | 1269 | list->qh_link = cpu_to_hc32((uint32_t)result->first | QH_LINK_TYPE_QH); |
1251 | 1270 | ||
1252 | flush_dcache_range((uint32_t)result->last, | 1271 | flush_dcache_range((uint32_t)result->last, |
1253 | ALIGN_END_ADDR(struct QH, result->last, 1)); | 1272 | ALIGN_END_ADDR(struct QH, result->last, 1)); |
1254 | flush_dcache_range((uint32_t)list, | 1273 | flush_dcache_range((uint32_t)list, |
1255 | ALIGN_END_ADDR(struct QH, list, 1)); | 1274 | ALIGN_END_ADDR(struct QH, list, 1)); |
1256 | 1275 | ||
1257 | if (enable_periodic(ctrl) < 0) { | 1276 | if (enable_periodic(ctrl) < 0) { |
1258 | debug("FATAL: periodic should never fail, but did"); | 1277 | debug("FATAL: periodic should never fail, but did"); |
1259 | goto fail3; | 1278 | goto fail3; |
1260 | } | 1279 | } |
1261 | periodic_schedules++; | 1280 | ctrl->periodic_schedules++; |
1262 | 1281 | ||
1263 | debug("Exit create_int_queue\n"); | 1282 | debug("Exit create_int_queue\n"); |
1264 | return result; | 1283 | return result; |
1265 | fail3: | 1284 | fail3: |
1266 | if (result->tds) | 1285 | if (result->tds) |
1267 | free(result->tds); | 1286 | free(result->tds); |
1268 | fail2: | 1287 | fail2: |
1269 | if (result->first) | 1288 | if (result->first) |
1270 | free(result->first); | 1289 | free(result->first); |
1271 | if (result) | 1290 | if (result) |
1272 | free(result); | 1291 | free(result); |
1273 | fail1: | 1292 | fail1: |
1274 | return NULL; | 1293 | return NULL; |
1275 | } | 1294 | } |
1276 | 1295 | ||
1277 | void *poll_int_queue(struct usb_device *dev, struct int_queue *queue) | 1296 | void *poll_int_queue(struct usb_device *dev, struct int_queue *queue) |
1278 | { | 1297 | { |
1279 | struct QH *cur = queue->current; | 1298 | struct QH *cur = queue->current; |
1299 | struct qTD *cur_td; | ||
1280 | 1300 | ||
1281 | /* depleted queue */ | 1301 | /* depleted queue */ |
1282 | if (cur == NULL) { | 1302 | if (cur == NULL) { |
1283 | debug("Exit poll_int_queue with completed queue\n"); | 1303 | debug("Exit poll_int_queue with completed queue\n"); |
1284 | return NULL; | 1304 | return NULL; |
1285 | } | 1305 | } |
1286 | /* still active */ | 1306 | /* still active */ |
1287 | invalidate_dcache_range((uint32_t)cur, | 1307 | cur_td = &queue->tds[queue->current - queue->first]; |
1288 | ALIGN_END_ADDR(struct QH, cur, 1)); | 1308 | invalidate_dcache_range((uint32_t)cur_td, |
1289 | if (cur->qh_overlay.qt_token & cpu_to_hc32(0x80)) { | 1309 | ALIGN_END_ADDR(struct qTD, cur_td, 1)); |
1290 | debug("Exit poll_int_queue with no completed intr transfer. " | 1310 | if (QT_TOKEN_GET_STATUS(hc32_to_cpu(cur_td->qt_token)) & |
1291 | "token is %x\n", cur->qh_overlay.qt_token); | 1311 | QT_TOKEN_STATUS_ACTIVE) { |
1312 | debug("Exit poll_int_queue with no completed intr transfer. token is %x\n", | ||
1313 | hc32_to_cpu(cur_td->qt_token)); | ||
1292 | return NULL; | 1314 | return NULL; |
1293 | } | 1315 | } |
1294 | if (!(cur->qh_link & QH_LINK_TERMINATE)) | 1316 | if (!(cur->qh_link & QH_LINK_TERMINATE)) |
1295 | queue->current++; | 1317 | queue->current++; |
1296 | else | 1318 | else |
1297 | queue->current = NULL; | 1319 | queue->current = NULL; |
1298 | debug("Exit poll_int_queue with completed intr transfer. " | 1320 | debug("Exit poll_int_queue with completed intr transfer. token is %x at %p (first at %p)\n", |
1299 | "token is %x at %p (first at %p)\n", cur->qh_overlay.qt_token, | 1321 | hc32_to_cpu(cur_td->qt_token), cur, queue->first); |
1300 | &cur->qh_overlay.qt_token, queue->first); | ||
1301 | return cur->buffer; | 1322 | return cur->buffer; |
1302 | } | 1323 | } |
1303 | 1324 | ||
1304 | /* Do not free buffers associated with QHs, they're owned by someone else */ | 1325 | /* Do not free buffers associated with QHs, they're owned by someone else */ |
1305 | int | 1326 | int |
1306 | destroy_int_queue(struct usb_device *dev, struct int_queue *queue) | 1327 | destroy_int_queue(struct usb_device *dev, struct int_queue *queue) |
1307 | { | 1328 | { |
1308 | struct ehci_ctrl *ctrl = dev->controller; | 1329 | struct ehci_ctrl *ctrl = dev->controller; |
1309 | int result = -1; | 1330 | int result = -1; |
1310 | unsigned long timeout; | 1331 | unsigned long timeout; |
1311 | 1332 | ||
1312 | if (disable_periodic(ctrl) < 0) { | 1333 | if (disable_periodic(ctrl) < 0) { |
1313 | debug("FATAL: periodic should never fail, but did"); | 1334 | debug("FATAL: periodic should never fail, but did"); |
1314 | goto out; | 1335 | goto out; |
1315 | } | 1336 | } |
1316 | periodic_schedules--; | 1337 | ctrl->periodic_schedules--; |
1317 | 1338 | ||
1318 | struct QH *cur = &ctrl->periodic_queue; | 1339 | struct QH *cur = &ctrl->periodic_queue; |
1319 | timeout = get_timer(0) + 500; /* abort after 500ms */ | 1340 | timeout = get_timer(0) + 500; /* abort after 500ms */ |
1320 | while (!(cur->qh_link & cpu_to_hc32(QH_LINK_TERMINATE))) { | 1341 | while (!(cur->qh_link & cpu_to_hc32(QH_LINK_TERMINATE))) { |
1321 | debug("considering %p, with qh_link %x\n", cur, cur->qh_link); | 1342 | debug("considering %p, with qh_link %x\n", cur, cur->qh_link); |
1322 | if (NEXT_QH(cur) == queue->first) { | 1343 | if (NEXT_QH(cur) == queue->first) { |
1323 | debug("found candidate. removing from chain\n"); | 1344 | debug("found candidate. removing from chain\n"); |
1324 | cur->qh_link = queue->last->qh_link; | 1345 | cur->qh_link = queue->last->qh_link; |
1346 | flush_dcache_range((uint32_t)cur, | ||
1347 | ALIGN_END_ADDR(struct QH, cur, 1)); | ||
1325 | result = 0; | 1348 | result = 0; |
1326 | break; | 1349 | break; |
1327 | } | 1350 | } |
1328 | cur = NEXT_QH(cur); | 1351 | cur = NEXT_QH(cur); |
1329 | if (get_timer(0) > timeout) { | 1352 | if (get_timer(0) > timeout) { |
1330 | printf("Timeout destroying interrupt endpoint queue\n"); | 1353 | printf("Timeout destroying interrupt endpoint queue\n"); |
1331 | result = -1; | 1354 | result = -1; |
1332 | goto out; | 1355 | goto out; |
1333 | } | 1356 | } |
1334 | } | 1357 | } |
1335 | 1358 | ||
1336 | if (periodic_schedules > 0) { | 1359 | if (ctrl->periodic_schedules > 0) { |
1337 | result = enable_periodic(ctrl); | 1360 | result = enable_periodic(ctrl); |
1338 | if (result < 0) | 1361 | if (result < 0) |
1339 | debug("FATAL: periodic should never fail, but did"); | 1362 | debug("FATAL: periodic should never fail, but did"); |
1340 | } | 1363 | } |
1341 | 1364 | ||
1342 | out: | 1365 | out: |
1343 | free(queue->tds); | 1366 | free(queue->tds); |
1344 | free(queue->first); | 1367 | free(queue->first); |
1345 | free(queue); | 1368 | free(queue); |
1346 | 1369 | ||
1347 | return result; | 1370 | return result; |
1348 | } | 1371 | } |
1349 | 1372 | ||
1350 | int | 1373 | int |
1351 | submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, | 1374 | submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, |
1352 | int length, int interval) | 1375 | int length, int interval) |
1353 | { | 1376 | { |
1354 | void *backbuffer; | 1377 | void *backbuffer; |
1355 | struct int_queue *queue; | 1378 | struct int_queue *queue; |
1356 | unsigned long timeout; | 1379 | unsigned long timeout; |
1357 | int result = 0, ret; | 1380 | int result = 0, ret; |
1358 | 1381 | ||
1359 | debug("dev=%p, pipe=%lu, buffer=%p, length=%d, interval=%d", | 1382 | debug("dev=%p, pipe=%lu, buffer=%p, length=%d, interval=%d", |
1360 | dev, pipe, buffer, length, interval); | 1383 | dev, pipe, buffer, length, interval); |
1361 | 1384 | ||
1362 | /* | 1385 | /* |
1363 | * Interrupt transfers requiring several transactions are not supported | 1386 | * Interrupt transfers requiring several transactions are not supported |
1364 | * because bInterval is ignored. | 1387 | * because bInterval is ignored. |
1365 | * | 1388 | * |
1366 | * Also, ehci_submit_async() relies on wMaxPacketSize being a power of 2 | 1389 | * Also, ehci_submit_async() relies on wMaxPacketSize being a power of 2 |
1367 | * <= PKT_ALIGN if several qTDs are required, while the USB | 1390 | * <= PKT_ALIGN if several qTDs are required, while the USB |
1368 | * specification does not constrain this for interrupt transfers. That | 1391 | * specification does not constrain this for interrupt transfers. That |
1369 | * means that ehci_submit_async() would support interrupt transfers | 1392 | * means that ehci_submit_async() would support interrupt transfers |
1370 | * requiring several transactions only as long as the transfer size does | 1393 | * requiring several transactions only as long as the transfer size does |
1371 | * not require more than a single qTD. | 1394 | * not require more than a single qTD. |
1372 | */ | 1395 | */ |
1373 | if (length > usb_maxpacket(dev, pipe)) { | 1396 | if (length > usb_maxpacket(dev, pipe)) { |
1374 | printf("%s: Interrupt transfers requiring several " | 1397 | printf("%s: Interrupt transfers requiring several " |
1375 | "transactions are not supported.\n", __func__); | 1398 | "transactions are not supported.\n", __func__); |
1376 | return -1; | 1399 | return -1; |
1377 | } | 1400 | } |
1378 | 1401 | ||
1379 | queue = create_int_queue(dev, pipe, 1, length, buffer); | 1402 | queue = create_int_queue(dev, pipe, 1, length, buffer); |
1380 | 1403 | ||
1381 | timeout = get_timer(0) + USB_TIMEOUT_MS(pipe); | 1404 | timeout = get_timer(0) + USB_TIMEOUT_MS(pipe); |
1382 | while ((backbuffer = poll_int_queue(dev, queue)) == NULL) | 1405 | while ((backbuffer = poll_int_queue(dev, queue)) == NULL) |
1383 | if (get_timer(0) > timeout) { | 1406 | if (get_timer(0) > timeout) { |
1384 | printf("Timeout poll on interrupt endpoint\n"); | 1407 | printf("Timeout poll on interrupt endpoint\n"); |
1385 | result = -ETIMEDOUT; | 1408 | result = -ETIMEDOUT; |
1386 | break; | 1409 | break; |
1387 | } | 1410 | } |
1388 | 1411 | ||
1389 | if (backbuffer != buffer) { | 1412 | if (backbuffer != buffer) { |
1390 | debug("got wrong buffer back (%x instead of %x)\n", | 1413 | debug("got wrong buffer back (%x instead of %x)\n", |
1391 | (uint32_t)backbuffer, (uint32_t)buffer); | 1414 | (uint32_t)backbuffer, (uint32_t)buffer); |
1392 | return -EINVAL; | 1415 | return -EINVAL; |
1393 | } | 1416 | } |
1394 | 1417 | ||
1395 | invalidate_dcache_range((uint32_t)buffer, | 1418 | invalidate_dcache_range((uint32_t)buffer, |
1396 | ALIGN_END_ADDR(char, buffer, length)); | 1419 | ALIGN_END_ADDR(char, buffer, length)); |
1397 | 1420 |
drivers/usb/host/ehci-tegra.c
1 | /* | 1 | /* |
2 | * Copyright (c) 2011 The Chromium OS Authors. | 2 | * Copyright (c) 2011 The Chromium OS Authors. |
3 | * Copyright (c) 2009-2013 NVIDIA Corporation | 3 | * Copyright (c) 2009-2013 NVIDIA Corporation |
4 | * Copyright (c) 2013 Lucas Stach | 4 | * Copyright (c) 2013 Lucas Stach |
5 | * | 5 | * |
6 | * SPDX-License-Identifier: GPL-2.0+ | 6 | * SPDX-License-Identifier: GPL-2.0+ |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <common.h> | 9 | #include <common.h> |
10 | #include <asm/errno.h> | 10 | #include <asm/errno.h> |
11 | #include <asm/io.h> | 11 | #include <asm/io.h> |
12 | #include <asm-generic/gpio.h> | 12 | #include <asm-generic/gpio.h> |
13 | #include <asm/arch/clock.h> | 13 | #include <asm/arch/clock.h> |
14 | #include <asm/arch-tegra/usb.h> | 14 | #include <asm/arch-tegra/usb.h> |
15 | #include <asm/arch-tegra/clk_rst.h> | 15 | #include <asm/arch-tegra/clk_rst.h> |
16 | #include <usb.h> | 16 | #include <usb.h> |
17 | #include <usb/ulpi.h> | 17 | #include <usb/ulpi.h> |
18 | #include <libfdt.h> | 18 | #include <libfdt.h> |
19 | #include <fdtdec.h> | 19 | #include <fdtdec.h> |
20 | 20 | ||
21 | #include "ehci.h" | 21 | #include "ehci.h" |
22 | 22 | ||
23 | #define USB1_ADDR_MASK 0xFFFF0000 | 23 | #define USB1_ADDR_MASK 0xFFFF0000 |
24 | 24 | ||
25 | #define HOSTPC1_DEVLC 0x84 | 25 | #define HOSTPC1_DEVLC 0x84 |
26 | #define HOSTPC1_PSPD(x) (((x) >> 25) & 0x3) | 26 | #define HOSTPC1_PSPD(x) (((x) >> 25) & 0x3) |
27 | 27 | ||
28 | #ifdef CONFIG_USB_ULPI | 28 | #ifdef CONFIG_USB_ULPI |
29 | #ifndef CONFIG_USB_ULPI_VIEWPORT | 29 | #ifndef CONFIG_USB_ULPI_VIEWPORT |
30 | #error "To use CONFIG_USB_ULPI on Tegra Boards you have to also \ | 30 | #error "To use CONFIG_USB_ULPI on Tegra Boards you have to also \ |
31 | define CONFIG_USB_ULPI_VIEWPORT" | 31 | define CONFIG_USB_ULPI_VIEWPORT" |
32 | #endif | 32 | #endif |
33 | #endif | 33 | #endif |
34 | 34 | ||
35 | enum { | 35 | enum { |
36 | USB_PORTS_MAX = 3, /* Maximum ports we allow */ | 36 | USB_PORTS_MAX = 3, /* Maximum ports we allow */ |
37 | }; | 37 | }; |
38 | 38 | ||
39 | /* Parameters we need for USB */ | 39 | /* Parameters we need for USB */ |
40 | enum { | 40 | enum { |
41 | PARAM_DIVN, /* PLL FEEDBACK DIVIDer */ | 41 | PARAM_DIVN, /* PLL FEEDBACK DIVIDer */ |
42 | PARAM_DIVM, /* PLL INPUT DIVIDER */ | 42 | PARAM_DIVM, /* PLL INPUT DIVIDER */ |
43 | PARAM_DIVP, /* POST DIVIDER (2^N) */ | 43 | PARAM_DIVP, /* POST DIVIDER (2^N) */ |
44 | PARAM_CPCON, /* BASE PLLC CHARGE Pump setup ctrl */ | 44 | PARAM_CPCON, /* BASE PLLC CHARGE Pump setup ctrl */ |
45 | PARAM_LFCON, /* BASE PLLC LOOP FILter setup ctrl */ | 45 | PARAM_LFCON, /* BASE PLLC LOOP FILter setup ctrl */ |
46 | PARAM_ENABLE_DELAY_COUNT, /* PLL-U Enable Delay Count */ | 46 | PARAM_ENABLE_DELAY_COUNT, /* PLL-U Enable Delay Count */ |
47 | PARAM_STABLE_COUNT, /* PLL-U STABLE count */ | 47 | PARAM_STABLE_COUNT, /* PLL-U STABLE count */ |
48 | PARAM_ACTIVE_DELAY_COUNT, /* PLL-U Active delay count */ | 48 | PARAM_ACTIVE_DELAY_COUNT, /* PLL-U Active delay count */ |
49 | PARAM_XTAL_FREQ_COUNT, /* PLL-U XTAL frequency count */ | 49 | PARAM_XTAL_FREQ_COUNT, /* PLL-U XTAL frequency count */ |
50 | PARAM_DEBOUNCE_A_TIME, /* 10MS DELAY for BIAS_DEBOUNCE_A */ | 50 | PARAM_DEBOUNCE_A_TIME, /* 10MS DELAY for BIAS_DEBOUNCE_A */ |
51 | PARAM_BIAS_TIME, /* 20US DELAY AFter bias cell op */ | 51 | PARAM_BIAS_TIME, /* 20US DELAY AFter bias cell op */ |
52 | 52 | ||
53 | PARAM_COUNT | 53 | PARAM_COUNT |
54 | }; | 54 | }; |
55 | 55 | ||
56 | /* Possible port types (dual role mode) */ | 56 | /* Possible port types (dual role mode) */ |
57 | enum dr_mode { | 57 | enum dr_mode { |
58 | DR_MODE_NONE = 0, | 58 | DR_MODE_NONE = 0, |
59 | DR_MODE_HOST, /* supports host operation */ | 59 | DR_MODE_HOST, /* supports host operation */ |
60 | DR_MODE_DEVICE, /* supports device operation */ | 60 | DR_MODE_DEVICE, /* supports device operation */ |
61 | DR_MODE_OTG, /* supports both */ | 61 | DR_MODE_OTG, /* supports both */ |
62 | }; | 62 | }; |
63 | 63 | ||
64 | /* Information about a USB port */ | 64 | /* Information about a USB port */ |
65 | struct fdt_usb { | 65 | struct fdt_usb { |
66 | struct usb_ctlr *reg; /* address of registers in physical memory */ | 66 | struct usb_ctlr *reg; /* address of registers in physical memory */ |
67 | unsigned utmi:1; /* 1 if port has external tranceiver, else 0 */ | 67 | unsigned utmi:1; /* 1 if port has external tranceiver, else 0 */ |
68 | unsigned ulpi:1; /* 1 if port has external ULPI transceiver */ | 68 | unsigned ulpi:1; /* 1 if port has external ULPI transceiver */ |
69 | unsigned enabled:1; /* 1 to enable, 0 to disable */ | 69 | unsigned enabled:1; /* 1 to enable, 0 to disable */ |
70 | unsigned has_legacy_mode:1; /* 1 if this port has legacy mode */ | 70 | unsigned has_legacy_mode:1; /* 1 if this port has legacy mode */ |
71 | unsigned initialized:1; /* has this port already been initialized? */ | 71 | unsigned initialized:1; /* has this port already been initialized? */ |
72 | enum usb_init_type init_type; | 72 | enum usb_init_type init_type; |
73 | enum dr_mode dr_mode; /* dual role mode */ | 73 | enum dr_mode dr_mode; /* dual role mode */ |
74 | enum periph_id periph_id;/* peripheral id */ | 74 | enum periph_id periph_id;/* peripheral id */ |
75 | struct fdt_gpio_state vbus_gpio; /* GPIO for vbus enable */ | 75 | struct fdt_gpio_state vbus_gpio; /* GPIO for vbus enable */ |
76 | struct fdt_gpio_state phy_reset_gpio; /* GPIO to reset ULPI phy */ | 76 | struct fdt_gpio_state phy_reset_gpio; /* GPIO to reset ULPI phy */ |
77 | }; | 77 | }; |
78 | 78 | ||
79 | static struct fdt_usb port[USB_PORTS_MAX]; /* List of valid USB ports */ | 79 | static struct fdt_usb port[USB_PORTS_MAX]; /* List of valid USB ports */ |
80 | static unsigned port_count; /* Number of available ports */ | 80 | static unsigned port_count; /* Number of available ports */ |
81 | /* Port that needs to clear CSC after Port Reset */ | 81 | /* Port that needs to clear CSC after Port Reset */ |
82 | static u32 port_addr_clear_csc; | 82 | static u32 port_addr_clear_csc; |
83 | 83 | ||
84 | /* | 84 | /* |
85 | * This table has USB timing parameters for each Oscillator frequency we | 85 | * This table has USB timing parameters for each Oscillator frequency we |
86 | * support. There are four sets of values: | 86 | * support. There are four sets of values: |
87 | * | 87 | * |
88 | * 1. PLLU configuration information (reference clock is osc/clk_m and | 88 | * 1. PLLU configuration information (reference clock is osc/clk_m and |
89 | * PLLU-FOs are fixed at 12MHz/60MHz/480MHz). | 89 | * PLLU-FOs are fixed at 12MHz/60MHz/480MHz). |
90 | * | 90 | * |
91 | * Reference frequency 13.0MHz 19.2MHz 12.0MHz 26.0MHz | 91 | * Reference frequency 13.0MHz 19.2MHz 12.0MHz 26.0MHz |
92 | * ---------------------------------------------------------------------- | 92 | * ---------------------------------------------------------------------- |
93 | * DIVN 960 (0x3c0) 200 (0c8) 960 (3c0h) 960 (3c0) | 93 | * DIVN 960 (0x3c0) 200 (0c8) 960 (3c0h) 960 (3c0) |
94 | * DIVM 13 (0d) 4 (04) 12 (0c) 26 (1a) | 94 | * DIVM 13 (0d) 4 (04) 12 (0c) 26 (1a) |
95 | * Filter frequency (MHz) 1 4.8 6 2 | 95 | * Filter frequency (MHz) 1 4.8 6 2 |
96 | * CPCON 1100b 0011b 1100b 1100b | 96 | * CPCON 1100b 0011b 1100b 1100b |
97 | * LFCON0 0 0 0 0 | 97 | * LFCON0 0 0 0 0 |
98 | * | 98 | * |
99 | * 2. PLL CONFIGURATION & PARAMETERS for different clock generators: | 99 | * 2. PLL CONFIGURATION & PARAMETERS for different clock generators: |
100 | * | 100 | * |
101 | * Reference frequency 13.0MHz 19.2MHz 12.0MHz 26.0MHz | 101 | * Reference frequency 13.0MHz 19.2MHz 12.0MHz 26.0MHz |
102 | * --------------------------------------------------------------------------- | 102 | * --------------------------------------------------------------------------- |
103 | * PLLU_ENABLE_DLY_COUNT 02 (0x02) 03 (03) 02 (02) 04 (04) | 103 | * PLLU_ENABLE_DLY_COUNT 02 (0x02) 03 (03) 02 (02) 04 (04) |
104 | * PLLU_STABLE_COUNT 51 (33) 75 (4B) 47 (2F) 102 (66) | 104 | * PLLU_STABLE_COUNT 51 (33) 75 (4B) 47 (2F) 102 (66) |
105 | * PLL_ACTIVE_DLY_COUNT 05 (05) 06 (06) 04 (04) 09 (09) | 105 | * PLL_ACTIVE_DLY_COUNT 05 (05) 06 (06) 04 (04) 09 (09) |
106 | * XTAL_FREQ_COUNT 127 (7F) 187 (BB) 118 (76) 254 (FE) | 106 | * XTAL_FREQ_COUNT 127 (7F) 187 (BB) 118 (76) 254 (FE) |
107 | * | 107 | * |
108 | * 3. Debounce values IdDig, Avalid, Bvalid, VbusValid, VbusWakeUp, and | 108 | * 3. Debounce values IdDig, Avalid, Bvalid, VbusValid, VbusWakeUp, and |
109 | * SessEnd. Each of these signals have their own debouncer and for each of | 109 | * SessEnd. Each of these signals have their own debouncer and for each of |
110 | * those one out of two debouncing times can be chosen (BIAS_DEBOUNCE_A or | 110 | * those one out of two debouncing times can be chosen (BIAS_DEBOUNCE_A or |
111 | * BIAS_DEBOUNCE_B). | 111 | * BIAS_DEBOUNCE_B). |
112 | * | 112 | * |
113 | * The values of DEBOUNCE_A and DEBOUNCE_B are calculated as follows: | 113 | * The values of DEBOUNCE_A and DEBOUNCE_B are calculated as follows: |
114 | * 0xffff -> No debouncing at all | 114 | * 0xffff -> No debouncing at all |
115 | * <n> ms = <n> *1000 / (1/19.2MHz) / 4 | 115 | * <n> ms = <n> *1000 / (1/19.2MHz) / 4 |
116 | * | 116 | * |
117 | * So to program a 1 ms debounce for BIAS_DEBOUNCE_A, we have: | 117 | * So to program a 1 ms debounce for BIAS_DEBOUNCE_A, we have: |
118 | * BIAS_DEBOUNCE_A[15:0] = 1000 * 19.2 / 4 = 4800 = 0x12c0 | 118 | * BIAS_DEBOUNCE_A[15:0] = 1000 * 19.2 / 4 = 4800 = 0x12c0 |
119 | * | 119 | * |
120 | * We need to use only DebounceA for BOOTROM. We don't need the DebounceB | 120 | * We need to use only DebounceA for BOOTROM. We don't need the DebounceB |
121 | * values, so we can keep those to default. | 121 | * values, so we can keep those to default. |
122 | * | 122 | * |
123 | * 4. The 20 microsecond delay after bias cell operation. | 123 | * 4. The 20 microsecond delay after bias cell operation. |
124 | */ | 124 | */ |
125 | static const unsigned T20_usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = { | 125 | static const unsigned T20_usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = { |
126 | /* DivN, DivM, DivP, CPCON, LFCON, Delays Debounce, Bias */ | 126 | /* DivN, DivM, DivP, CPCON, LFCON, Delays Debounce, Bias */ |
127 | { 0x3C0, 0x0D, 0x00, 0xC, 0, 0x02, 0x33, 0x05, 0x7F, 0x7EF4, 5 }, | 127 | { 0x3C0, 0x0D, 0x00, 0xC, 0, 0x02, 0x33, 0x05, 0x7F, 0x7EF4, 5 }, |
128 | { 0x0C8, 0x04, 0x00, 0x3, 0, 0x03, 0x4B, 0x06, 0xBB, 0xBB80, 7 }, | 128 | { 0x0C8, 0x04, 0x00, 0x3, 0, 0x03, 0x4B, 0x06, 0xBB, 0xBB80, 7 }, |
129 | { 0x3C0, 0x0C, 0x00, 0xC, 0, 0x02, 0x2F, 0x04, 0x76, 0x7530, 5 }, | 129 | { 0x3C0, 0x0C, 0x00, 0xC, 0, 0x02, 0x2F, 0x04, 0x76, 0x7530, 5 }, |
130 | { 0x3C0, 0x1A, 0x00, 0xC, 0, 0x04, 0x66, 0x09, 0xFE, 0xFDE8, 9 } | 130 | { 0x3C0, 0x1A, 0x00, 0xC, 0, 0x04, 0x66, 0x09, 0xFE, 0xFDE8, 9 } |
131 | }; | 131 | }; |
132 | 132 | ||
133 | static const unsigned T30_usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = { | 133 | static const unsigned T30_usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = { |
134 | /* DivN, DivM, DivP, CPCON, LFCON, Delays Debounce, Bias */ | 134 | /* DivN, DivM, DivP, CPCON, LFCON, Delays Debounce, Bias */ |
135 | { 0x3C0, 0x0D, 0x00, 0xC, 1, 0x02, 0x33, 0x09, 0x7F, 0x7EF4, 5 }, | 135 | { 0x3C0, 0x0D, 0x00, 0xC, 1, 0x02, 0x33, 0x09, 0x7F, 0x7EF4, 5 }, |
136 | { 0x0C8, 0x04, 0x00, 0x3, 0, 0x03, 0x4B, 0x0C, 0xBB, 0xBB80, 7 }, | 136 | { 0x0C8, 0x04, 0x00, 0x3, 0, 0x03, 0x4B, 0x0C, 0xBB, 0xBB80, 7 }, |
137 | { 0x3C0, 0x0C, 0x00, 0xC, 1, 0x02, 0x2F, 0x08, 0x76, 0x7530, 5 }, | 137 | { 0x3C0, 0x0C, 0x00, 0xC, 1, 0x02, 0x2F, 0x08, 0x76, 0x7530, 5 }, |
138 | { 0x3C0, 0x1A, 0x00, 0xC, 1, 0x04, 0x66, 0x09, 0xFE, 0xFDE8, 9 } | 138 | { 0x3C0, 0x1A, 0x00, 0xC, 1, 0x04, 0x66, 0x09, 0xFE, 0xFDE8, 9 } |
139 | }; | 139 | }; |
140 | 140 | ||
141 | static const unsigned T114_usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = { | 141 | static const unsigned T114_usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = { |
142 | /* DivN, DivM, DivP, CPCON, LFCON, Delays Debounce, Bias */ | 142 | /* DivN, DivM, DivP, CPCON, LFCON, Delays Debounce, Bias */ |
143 | { 0x3C0, 0x0D, 0x00, 0xC, 2, 0x02, 0x33, 0x09, 0x7F, 0x7EF4, 6 }, | 143 | { 0x3C0, 0x0D, 0x00, 0xC, 2, 0x02, 0x33, 0x09, 0x7F, 0x7EF4, 6 }, |
144 | { 0x0C8, 0x04, 0x00, 0x3, 2, 0x03, 0x4B, 0x0C, 0xBB, 0xBB80, 8 }, | 144 | { 0x0C8, 0x04, 0x00, 0x3, 2, 0x03, 0x4B, 0x0C, 0xBB, 0xBB80, 8 }, |
145 | { 0x3C0, 0x0C, 0x00, 0xC, 2, 0x02, 0x2F, 0x08, 0x76, 0x7530, 5 }, | 145 | { 0x3C0, 0x0C, 0x00, 0xC, 2, 0x02, 0x2F, 0x08, 0x76, 0x7530, 5 }, |
146 | { 0x3C0, 0x1A, 0x00, 0xC, 2, 0x04, 0x66, 0x09, 0xFE, 0xFDE8, 0xB } | 146 | { 0x3C0, 0x1A, 0x00, 0xC, 2, 0x04, 0x66, 0x09, 0xFE, 0xFDE8, 0xB } |
147 | }; | 147 | }; |
148 | 148 | ||
149 | /* UTMIP Idle Wait Delay */ | 149 | /* UTMIP Idle Wait Delay */ |
150 | static const u8 utmip_idle_wait_delay = 17; | 150 | static const u8 utmip_idle_wait_delay = 17; |
151 | 151 | ||
152 | /* UTMIP Elastic limit */ | 152 | /* UTMIP Elastic limit */ |
153 | static const u8 utmip_elastic_limit = 16; | 153 | static const u8 utmip_elastic_limit = 16; |
154 | 154 | ||
155 | /* UTMIP High Speed Sync Start Delay */ | 155 | /* UTMIP High Speed Sync Start Delay */ |
156 | static const u8 utmip_hs_sync_start_delay = 9; | 156 | static const u8 utmip_hs_sync_start_delay = 9; |
157 | 157 | ||
158 | struct fdt_usb_controller { | 158 | struct fdt_usb_controller { |
159 | int compat; | 159 | int compat; |
160 | /* flag to determine whether controller supports hostpc register */ | 160 | /* flag to determine whether controller supports hostpc register */ |
161 | u32 has_hostpc:1; | 161 | u32 has_hostpc:1; |
162 | const unsigned *pll_parameter; | 162 | const unsigned *pll_parameter; |
163 | }; | 163 | }; |
164 | 164 | ||
165 | static struct fdt_usb_controller fdt_usb_controllers[] = { | 165 | static struct fdt_usb_controller fdt_usb_controllers[] = { |
166 | { | 166 | { |
167 | .compat = COMPAT_NVIDIA_TEGRA20_USB, | 167 | .compat = COMPAT_NVIDIA_TEGRA20_USB, |
168 | .has_hostpc = 0, | 168 | .has_hostpc = 0, |
169 | .pll_parameter = (const unsigned *)T20_usb_pll, | 169 | .pll_parameter = (const unsigned *)T20_usb_pll, |
170 | }, | 170 | }, |
171 | { | 171 | { |
172 | .compat = COMPAT_NVIDIA_TEGRA30_USB, | 172 | .compat = COMPAT_NVIDIA_TEGRA30_USB, |
173 | .has_hostpc = 1, | 173 | .has_hostpc = 1, |
174 | .pll_parameter = (const unsigned *)T30_usb_pll, | 174 | .pll_parameter = (const unsigned *)T30_usb_pll, |
175 | }, | 175 | }, |
176 | { | 176 | { |
177 | .compat = COMPAT_NVIDIA_TEGRA114_USB, | 177 | .compat = COMPAT_NVIDIA_TEGRA114_USB, |
178 | .has_hostpc = 1, | 178 | .has_hostpc = 1, |
179 | .pll_parameter = (const unsigned *)T114_usb_pll, | 179 | .pll_parameter = (const unsigned *)T114_usb_pll, |
180 | }, | 180 | }, |
181 | }; | 181 | }; |
182 | 182 | ||
183 | static struct fdt_usb_controller *controller; | 183 | static struct fdt_usb_controller *controller; |
184 | 184 | ||
185 | /* | 185 | /* |
186 | * A known hardware issue where Connect Status Change bit of PORTSC register | 186 | * A known hardware issue where Connect Status Change bit of PORTSC register |
187 | * of USB1 controller will be set after Port Reset. | 187 | * of USB1 controller will be set after Port Reset. |
188 | * We have to clear it in order for later device enumeration to proceed. | 188 | * We have to clear it in order for later device enumeration to proceed. |
189 | * This ehci_powerup_fixup overrides the weak function ehci_powerup_fixup | 189 | * This ehci_powerup_fixup overrides the weak function ehci_powerup_fixup |
190 | * in "ehci-hcd.c". | 190 | * in "ehci-hcd.c". |
191 | */ | 191 | */ |
192 | void ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg) | 192 | void ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg) |
193 | { | 193 | { |
194 | mdelay(50); | 194 | mdelay(50); |
195 | /* This is to avoid PORT_ENABLE bit to be cleared in "ehci-hcd.c". */ | 195 | /* This is to avoid PORT_ENABLE bit to be cleared in "ehci-hcd.c". */ |
196 | if (controller->has_hostpc) | 196 | if (controller->has_hostpc) |
197 | *reg |= EHCI_PS_PE; | 197 | *reg |= EHCI_PS_PE; |
198 | 198 | ||
199 | if (((u32)status_reg & TEGRA_USB_ADDR_MASK) != port_addr_clear_csc) | 199 | if (((u32)status_reg & TEGRA_USB_ADDR_MASK) != port_addr_clear_csc) |
200 | return; | 200 | return; |
201 | /* For EHCI_PS_CSC to be cleared in ehci_hcd.c */ | 201 | /* For EHCI_PS_CSC to be cleared in ehci_hcd.c */ |
202 | if (ehci_readl(status_reg) & EHCI_PS_CSC) | 202 | if (ehci_readl(status_reg) & EHCI_PS_CSC) |
203 | *reg |= EHCI_PS_CSC; | 203 | *reg |= EHCI_PS_CSC; |
204 | } | 204 | } |
205 | 205 | ||
206 | /* | 206 | /* |
207 | * This ehci_set_usbmode overrides the weak function ehci_set_usbmode | 207 | * This ehci_set_usbmode overrides the weak function ehci_set_usbmode |
208 | * in "ehci-hcd.c". | 208 | * in "ehci-hcd.c". |
209 | */ | 209 | */ |
210 | void ehci_set_usbmode(int index) | 210 | void ehci_set_usbmode(int index) |
211 | { | 211 | { |
212 | struct fdt_usb *config; | 212 | struct fdt_usb *config; |
213 | struct usb_ctlr *usbctlr; | 213 | struct usb_ctlr *usbctlr; |
214 | uint32_t tmp; | 214 | uint32_t tmp; |
215 | 215 | ||
216 | config = &port[index]; | 216 | config = &port[index]; |
217 | usbctlr = config->reg; | 217 | usbctlr = config->reg; |
218 | 218 | ||
219 | tmp = ehci_readl(&usbctlr->usb_mode); | 219 | tmp = ehci_readl(&usbctlr->usb_mode); |
220 | tmp |= USBMODE_CM_HC; | 220 | tmp |= USBMODE_CM_HC; |
221 | ehci_writel(&usbctlr->usb_mode, tmp); | 221 | ehci_writel(&usbctlr->usb_mode, tmp); |
222 | } | 222 | } |
223 | 223 | ||
224 | /* | 224 | /* |
225 | * This ehci_get_port_speed overrides the weak function ehci_get_port_speed | 225 | * This ehci_get_port_speed overrides the weak function ehci_get_port_speed |
226 | * in "ehci-hcd.c". | 226 | * in "ehci-hcd.c". |
227 | */ | 227 | */ |
228 | int ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg) | 228 | int ehci_get_port_speed(struct ehci_hcor *hcor, uint32_t reg) |
229 | { | 229 | { |
230 | uint32_t tmp; | 230 | uint32_t tmp; |
231 | uint32_t *reg_ptr; | 231 | uint32_t *reg_ptr; |
232 | 232 | ||
233 | if (controller->has_hostpc) { | 233 | if (controller->has_hostpc) { |
234 | reg_ptr = (uint32_t *)((u8 *)&hcor->or_usbcmd + HOSTPC1_DEVLC); | 234 | reg_ptr = (uint32_t *)((u8 *)&hcor->or_usbcmd + HOSTPC1_DEVLC); |
235 | tmp = ehci_readl(reg_ptr); | 235 | tmp = ehci_readl(reg_ptr); |
236 | return HOSTPC1_PSPD(tmp); | 236 | return HOSTPC1_PSPD(tmp); |
237 | } else | 237 | } else |
238 | return PORTSC_PSPD(reg); | 238 | return PORTSC_PSPD(reg); |
239 | } | 239 | } |
240 | 240 | ||
241 | /* Set up VBUS for host/device mode */ | 241 | /* Set up VBUS for host/device mode */ |
242 | static void set_up_vbus(struct fdt_usb *config, enum usb_init_type init) | 242 | static void set_up_vbus(struct fdt_usb *config, enum usb_init_type init) |
243 | { | 243 | { |
244 | /* | 244 | /* |
245 | * If we are an OTG port initializing in host mode, | 245 | * If we are an OTG port initializing in host mode, |
246 | * check if remote host is driving VBus and bail out in this case. | 246 | * check if remote host is driving VBus and bail out in this case. |
247 | */ | 247 | */ |
248 | if (init == USB_INIT_HOST && | 248 | if (init == USB_INIT_HOST && |
249 | config->dr_mode == DR_MODE_OTG && | 249 | config->dr_mode == DR_MODE_OTG && |
250 | (readl(&config->reg->phy_vbus_sensors) & VBUS_VLD_STS)) { | 250 | (readl(&config->reg->phy_vbus_sensors) & VBUS_VLD_STS)) { |
251 | printf("tegrausb: VBUS input active; not enabling as host\n"); | 251 | printf("tegrausb: VBUS input active; not enabling as host\n"); |
252 | return; | 252 | return; |
253 | } | 253 | } |
254 | 254 | ||
255 | if (fdt_gpio_isvalid(&config->vbus_gpio)) { | 255 | if (fdt_gpio_isvalid(&config->vbus_gpio)) { |
256 | int vbus_value; | 256 | int vbus_value; |
257 | 257 | ||
258 | fdtdec_setup_gpio(&config->vbus_gpio); | 258 | fdtdec_setup_gpio(&config->vbus_gpio); |
259 | 259 | ||
260 | vbus_value = (init == USB_INIT_HOST) ^ | 260 | vbus_value = (init == USB_INIT_HOST) ^ |
261 | !!(config->vbus_gpio.flags & FDT_GPIO_ACTIVE_LOW); | 261 | !!(config->vbus_gpio.flags & FDT_GPIO_ACTIVE_LOW); |
262 | gpio_direction_output(config->vbus_gpio.gpio, vbus_value); | 262 | gpio_direction_output(config->vbus_gpio.gpio, vbus_value); |
263 | 263 | ||
264 | debug("set_up_vbus: GPIO %d %d\n", config->vbus_gpio.gpio, | 264 | debug("set_up_vbus: GPIO %d %d\n", config->vbus_gpio.gpio, |
265 | vbus_value); | 265 | vbus_value); |
266 | } | 266 | } |
267 | } | 267 | } |
268 | 268 | ||
269 | void usbf_reset_controller(struct fdt_usb *config, struct usb_ctlr *usbctlr) | 269 | void usbf_reset_controller(struct fdt_usb *config, struct usb_ctlr *usbctlr) |
270 | { | 270 | { |
271 | /* Reset the USB controller with 2us delay */ | 271 | /* Reset the USB controller with 2us delay */ |
272 | reset_periph(config->periph_id, 2); | 272 | reset_periph(config->periph_id, 2); |
273 | 273 | ||
274 | /* | 274 | /* |
275 | * Set USB1_NO_LEGACY_MODE to 1, Registers are accessible under | 275 | * Set USB1_NO_LEGACY_MODE to 1, Registers are accessible under |
276 | * base address | 276 | * base address |
277 | */ | 277 | */ |
278 | if (config->has_legacy_mode) | 278 | if (config->has_legacy_mode) |
279 | setbits_le32(&usbctlr->usb1_legacy_ctrl, USB1_NO_LEGACY_MODE); | 279 | setbits_le32(&usbctlr->usb1_legacy_ctrl, USB1_NO_LEGACY_MODE); |
280 | 280 | ||
281 | /* Put UTMIP1/3 in reset */ | 281 | /* Put UTMIP1/3 in reset */ |
282 | setbits_le32(&usbctlr->susp_ctrl, UTMIP_RESET); | 282 | setbits_le32(&usbctlr->susp_ctrl, UTMIP_RESET); |
283 | 283 | ||
284 | /* Enable the UTMIP PHY */ | 284 | /* Enable the UTMIP PHY */ |
285 | if (config->utmi) | 285 | if (config->utmi) |
286 | setbits_le32(&usbctlr->susp_ctrl, UTMIP_PHY_ENB); | 286 | setbits_le32(&usbctlr->susp_ctrl, UTMIP_PHY_ENB); |
287 | } | 287 | } |
288 | 288 | ||
289 | static const unsigned *get_pll_timing(void) | 289 | static const unsigned *get_pll_timing(void) |
290 | { | 290 | { |
291 | const unsigned *timing; | 291 | const unsigned *timing; |
292 | 292 | ||
293 | timing = controller->pll_parameter + | 293 | timing = controller->pll_parameter + |
294 | clock_get_osc_freq() * PARAM_COUNT; | 294 | clock_get_osc_freq() * PARAM_COUNT; |
295 | 295 | ||
296 | return timing; | 296 | return timing; |
297 | } | 297 | } |
298 | 298 | ||
299 | /* select the PHY to use with a USB controller */ | 299 | /* select the PHY to use with a USB controller */ |
300 | static void init_phy_mux(struct fdt_usb *config, uint pts, | 300 | static void init_phy_mux(struct fdt_usb *config, uint pts, |
301 | enum usb_init_type init) | 301 | enum usb_init_type init) |
302 | { | 302 | { |
303 | struct usb_ctlr *usbctlr = config->reg; | 303 | struct usb_ctlr *usbctlr = config->reg; |
304 | 304 | ||
305 | #if defined(CONFIG_TEGRA20) | 305 | #if defined(CONFIG_TEGRA20) |
306 | if (config->periph_id == PERIPH_ID_USBD) { | 306 | if (config->periph_id == PERIPH_ID_USBD) { |
307 | clrsetbits_le32(&usbctlr->port_sc1, PTS1_MASK, | 307 | clrsetbits_le32(&usbctlr->port_sc1, PTS1_MASK, |
308 | PTS_UTMI << PTS1_SHIFT); | 308 | pts << PTS1_SHIFT); |
309 | clrbits_le32(&usbctlr->port_sc1, STS1); | 309 | clrbits_le32(&usbctlr->port_sc1, STS1); |
310 | } else { | 310 | } else { |
311 | clrsetbits_le32(&usbctlr->port_sc1, PTS_MASK, | 311 | clrsetbits_le32(&usbctlr->port_sc1, PTS_MASK, |
312 | PTS_UTMI << PTS_SHIFT); | 312 | pts << PTS_SHIFT); |
313 | clrbits_le32(&usbctlr->port_sc1, STS); | 313 | clrbits_le32(&usbctlr->port_sc1, STS); |
314 | } | 314 | } |
315 | #else | 315 | #else |
316 | /* Set to Host mode (if applicable) after Controller Reset was done */ | 316 | /* Set to Host mode (if applicable) after Controller Reset was done */ |
317 | clrsetbits_le32(&usbctlr->usb_mode, USBMODE_CM_HC, | 317 | clrsetbits_le32(&usbctlr->usb_mode, USBMODE_CM_HC, |
318 | (init == USB_INIT_HOST) ? USBMODE_CM_HC : 0); | 318 | (init == USB_INIT_HOST) ? USBMODE_CM_HC : 0); |
319 | /* | 319 | /* |
320 | * Select PHY interface after setting host mode. | 320 | * Select PHY interface after setting host mode. |
321 | * For device mode, the ordering requirement is not an issue, since | 321 | * For device mode, the ordering requirement is not an issue, since |
322 | * only the first USB controller supports device mode, and that USB | 322 | * only the first USB controller supports device mode, and that USB |
323 | * controller can only talk to a UTMI PHY, so the PHY selection is | 323 | * controller can only talk to a UTMI PHY, so the PHY selection is |
324 | * already made at reset time, so this write is a no-op. | 324 | * already made at reset time, so this write is a no-op. |
325 | */ | 325 | */ |
326 | clrsetbits_le32(&usbctlr->hostpc1_devlc, PTS_MASK, | 326 | clrsetbits_le32(&usbctlr->hostpc1_devlc, PTS_MASK, |
327 | pts << PTS_SHIFT); | 327 | pts << PTS_SHIFT); |
328 | clrbits_le32(&usbctlr->hostpc1_devlc, STS); | 328 | clrbits_le32(&usbctlr->hostpc1_devlc, STS); |
329 | #endif | 329 | #endif |
330 | } | 330 | } |
331 | 331 | ||
332 | /* set up the UTMI USB controller with the parameters provided */ | 332 | /* set up the UTMI USB controller with the parameters provided */ |
333 | static int init_utmi_usb_controller(struct fdt_usb *config, | 333 | static int init_utmi_usb_controller(struct fdt_usb *config, |
334 | enum usb_init_type init) | 334 | enum usb_init_type init) |
335 | { | 335 | { |
336 | u32 b_sess_valid_mask, val; | 336 | u32 b_sess_valid_mask, val; |
337 | int loop_count; | 337 | int loop_count; |
338 | const unsigned *timing; | 338 | const unsigned *timing; |
339 | struct usb_ctlr *usbctlr = config->reg; | 339 | struct usb_ctlr *usbctlr = config->reg; |
340 | struct clk_rst_ctlr *clkrst; | 340 | struct clk_rst_ctlr *clkrst; |
341 | struct usb_ctlr *usb1ctlr; | 341 | struct usb_ctlr *usb1ctlr; |
342 | 342 | ||
343 | clock_enable(config->periph_id); | 343 | clock_enable(config->periph_id); |
344 | 344 | ||
345 | /* Reset the usb controller */ | 345 | /* Reset the usb controller */ |
346 | usbf_reset_controller(config, usbctlr); | 346 | usbf_reset_controller(config, usbctlr); |
347 | 347 | ||
348 | /* Stop crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN low */ | 348 | /* Stop crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN low */ |
349 | clrbits_le32(&usbctlr->utmip_misc_cfg1, UTMIP_PHY_XTAL_CLOCKEN); | 349 | clrbits_le32(&usbctlr->utmip_misc_cfg1, UTMIP_PHY_XTAL_CLOCKEN); |
350 | 350 | ||
351 | /* Follow the crystal clock disable by >100ns delay */ | 351 | /* Follow the crystal clock disable by >100ns delay */ |
352 | udelay(1); | 352 | udelay(1); |
353 | 353 | ||
354 | b_sess_valid_mask = (VBUS_B_SESS_VLD_SW_VALUE | VBUS_B_SESS_VLD_SW_EN); | 354 | b_sess_valid_mask = (VBUS_B_SESS_VLD_SW_VALUE | VBUS_B_SESS_VLD_SW_EN); |
355 | clrsetbits_le32(&usbctlr->phy_vbus_sensors, b_sess_valid_mask, | 355 | clrsetbits_le32(&usbctlr->phy_vbus_sensors, b_sess_valid_mask, |
356 | (init == USB_INIT_DEVICE) ? b_sess_valid_mask : 0); | 356 | (init == USB_INIT_DEVICE) ? b_sess_valid_mask : 0); |
357 | 357 | ||
358 | /* | 358 | /* |
359 | * To Use the A Session Valid for cable detection logic, VBUS_WAKEUP | 359 | * To Use the A Session Valid for cable detection logic, VBUS_WAKEUP |
360 | * mux must be switched to actually use a_sess_vld threshold. | 360 | * mux must be switched to actually use a_sess_vld threshold. |
361 | */ | 361 | */ |
362 | if (config->dr_mode == DR_MODE_OTG && | 362 | if (config->dr_mode == DR_MODE_OTG && |
363 | fdt_gpio_isvalid(&config->vbus_gpio)) | 363 | fdt_gpio_isvalid(&config->vbus_gpio)) |
364 | clrsetbits_le32(&usbctlr->usb1_legacy_ctrl, | 364 | clrsetbits_le32(&usbctlr->usb1_legacy_ctrl, |
365 | VBUS_SENSE_CTL_MASK, | 365 | VBUS_SENSE_CTL_MASK, |
366 | VBUS_SENSE_CTL_A_SESS_VLD << VBUS_SENSE_CTL_SHIFT); | 366 | VBUS_SENSE_CTL_A_SESS_VLD << VBUS_SENSE_CTL_SHIFT); |
367 | 367 | ||
368 | /* | 368 | /* |
369 | * PLL Delay CONFIGURATION settings. The following parameters control | 369 | * PLL Delay CONFIGURATION settings. The following parameters control |
370 | * the bring up of the plls. | 370 | * the bring up of the plls. |
371 | */ | 371 | */ |
372 | timing = get_pll_timing(); | 372 | timing = get_pll_timing(); |
373 | 373 | ||
374 | if (!controller->has_hostpc) { | 374 | if (!controller->has_hostpc) { |
375 | val = readl(&usbctlr->utmip_misc_cfg1); | 375 | val = readl(&usbctlr->utmip_misc_cfg1); |
376 | clrsetbits_le32(&val, UTMIP_PLLU_STABLE_COUNT_MASK, | 376 | clrsetbits_le32(&val, UTMIP_PLLU_STABLE_COUNT_MASK, |
377 | timing[PARAM_STABLE_COUNT] << | 377 | timing[PARAM_STABLE_COUNT] << |
378 | UTMIP_PLLU_STABLE_COUNT_SHIFT); | 378 | UTMIP_PLLU_STABLE_COUNT_SHIFT); |
379 | clrsetbits_le32(&val, UTMIP_PLL_ACTIVE_DLY_COUNT_MASK, | 379 | clrsetbits_le32(&val, UTMIP_PLL_ACTIVE_DLY_COUNT_MASK, |
380 | timing[PARAM_ACTIVE_DELAY_COUNT] << | 380 | timing[PARAM_ACTIVE_DELAY_COUNT] << |
381 | UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT); | 381 | UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT); |
382 | writel(val, &usbctlr->utmip_misc_cfg1); | 382 | writel(val, &usbctlr->utmip_misc_cfg1); |
383 | 383 | ||
384 | /* Set PLL enable delay count and crystal frequency count */ | 384 | /* Set PLL enable delay count and crystal frequency count */ |
385 | val = readl(&usbctlr->utmip_pll_cfg1); | 385 | val = readl(&usbctlr->utmip_pll_cfg1); |
386 | clrsetbits_le32(&val, UTMIP_PLLU_ENABLE_DLY_COUNT_MASK, | 386 | clrsetbits_le32(&val, UTMIP_PLLU_ENABLE_DLY_COUNT_MASK, |
387 | timing[PARAM_ENABLE_DELAY_COUNT] << | 387 | timing[PARAM_ENABLE_DELAY_COUNT] << |
388 | UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT); | 388 | UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT); |
389 | clrsetbits_le32(&val, UTMIP_XTAL_FREQ_COUNT_MASK, | 389 | clrsetbits_le32(&val, UTMIP_XTAL_FREQ_COUNT_MASK, |
390 | timing[PARAM_XTAL_FREQ_COUNT] << | 390 | timing[PARAM_XTAL_FREQ_COUNT] << |
391 | UTMIP_XTAL_FREQ_COUNT_SHIFT); | 391 | UTMIP_XTAL_FREQ_COUNT_SHIFT); |
392 | writel(val, &usbctlr->utmip_pll_cfg1); | 392 | writel(val, &usbctlr->utmip_pll_cfg1); |
393 | } else { | 393 | } else { |
394 | clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; | 394 | clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; |
395 | 395 | ||
396 | val = readl(&clkrst->crc_utmip_pll_cfg2); | 396 | val = readl(&clkrst->crc_utmip_pll_cfg2); |
397 | clrsetbits_le32(&val, UTMIP_PLLU_STABLE_COUNT_MASK, | 397 | clrsetbits_le32(&val, UTMIP_PLLU_STABLE_COUNT_MASK, |
398 | timing[PARAM_STABLE_COUNT] << | 398 | timing[PARAM_STABLE_COUNT] << |
399 | UTMIP_PLLU_STABLE_COUNT_SHIFT); | 399 | UTMIP_PLLU_STABLE_COUNT_SHIFT); |
400 | clrsetbits_le32(&val, UTMIP_PLL_ACTIVE_DLY_COUNT_MASK, | 400 | clrsetbits_le32(&val, UTMIP_PLL_ACTIVE_DLY_COUNT_MASK, |
401 | timing[PARAM_ACTIVE_DELAY_COUNT] << | 401 | timing[PARAM_ACTIVE_DELAY_COUNT] << |
402 | UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT); | 402 | UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT); |
403 | writel(val, &clkrst->crc_utmip_pll_cfg2); | 403 | writel(val, &clkrst->crc_utmip_pll_cfg2); |
404 | 404 | ||
405 | /* Set PLL enable delay count and crystal frequency count */ | 405 | /* Set PLL enable delay count and crystal frequency count */ |
406 | val = readl(&clkrst->crc_utmip_pll_cfg1); | 406 | val = readl(&clkrst->crc_utmip_pll_cfg1); |
407 | clrsetbits_le32(&val, UTMIP_PLLU_ENABLE_DLY_COUNT_MASK, | 407 | clrsetbits_le32(&val, UTMIP_PLLU_ENABLE_DLY_COUNT_MASK, |
408 | timing[PARAM_ENABLE_DELAY_COUNT] << | 408 | timing[PARAM_ENABLE_DELAY_COUNT] << |
409 | UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT); | 409 | UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT); |
410 | clrsetbits_le32(&val, UTMIP_XTAL_FREQ_COUNT_MASK, | 410 | clrsetbits_le32(&val, UTMIP_XTAL_FREQ_COUNT_MASK, |
411 | timing[PARAM_XTAL_FREQ_COUNT] << | 411 | timing[PARAM_XTAL_FREQ_COUNT] << |
412 | UTMIP_XTAL_FREQ_COUNT_SHIFT); | 412 | UTMIP_XTAL_FREQ_COUNT_SHIFT); |
413 | writel(val, &clkrst->crc_utmip_pll_cfg1); | 413 | writel(val, &clkrst->crc_utmip_pll_cfg1); |
414 | 414 | ||
415 | /* Disable Power Down state for PLL */ | 415 | /* Disable Power Down state for PLL */ |
416 | clrbits_le32(&clkrst->crc_utmip_pll_cfg1, | 416 | clrbits_le32(&clkrst->crc_utmip_pll_cfg1, |
417 | PLLU_POWERDOWN | PLL_ENABLE_POWERDOWN | | 417 | PLLU_POWERDOWN | PLL_ENABLE_POWERDOWN | |
418 | PLL_ACTIVE_POWERDOWN); | 418 | PLL_ACTIVE_POWERDOWN); |
419 | 419 | ||
420 | /* Recommended PHY settings for EYE diagram */ | 420 | /* Recommended PHY settings for EYE diagram */ |
421 | val = readl(&usbctlr->utmip_xcvr_cfg0); | 421 | val = readl(&usbctlr->utmip_xcvr_cfg0); |
422 | clrsetbits_le32(&val, UTMIP_XCVR_SETUP_MASK, | 422 | clrsetbits_le32(&val, UTMIP_XCVR_SETUP_MASK, |
423 | 0x4 << UTMIP_XCVR_SETUP_SHIFT); | 423 | 0x4 << UTMIP_XCVR_SETUP_SHIFT); |
424 | clrsetbits_le32(&val, UTMIP_XCVR_SETUP_MSB_MASK, | 424 | clrsetbits_le32(&val, UTMIP_XCVR_SETUP_MSB_MASK, |
425 | 0x3 << UTMIP_XCVR_SETUP_MSB_SHIFT); | 425 | 0x3 << UTMIP_XCVR_SETUP_MSB_SHIFT); |
426 | clrsetbits_le32(&val, UTMIP_XCVR_HSSLEW_MSB_MASK, | 426 | clrsetbits_le32(&val, UTMIP_XCVR_HSSLEW_MSB_MASK, |
427 | 0x8 << UTMIP_XCVR_HSSLEW_MSB_SHIFT); | 427 | 0x8 << UTMIP_XCVR_HSSLEW_MSB_SHIFT); |
428 | writel(val, &usbctlr->utmip_xcvr_cfg0); | 428 | writel(val, &usbctlr->utmip_xcvr_cfg0); |
429 | clrsetbits_le32(&usbctlr->utmip_xcvr_cfg1, | 429 | clrsetbits_le32(&usbctlr->utmip_xcvr_cfg1, |
430 | UTMIP_XCVR_TERM_RANGE_ADJ_MASK, | 430 | UTMIP_XCVR_TERM_RANGE_ADJ_MASK, |
431 | 0x7 << UTMIP_XCVR_TERM_RANGE_ADJ_SHIFT); | 431 | 0x7 << UTMIP_XCVR_TERM_RANGE_ADJ_SHIFT); |
432 | 432 | ||
433 | /* Some registers can be controlled from USB1 only. */ | 433 | /* Some registers can be controlled from USB1 only. */ |
434 | if (config->periph_id != PERIPH_ID_USBD) { | 434 | if (config->periph_id != PERIPH_ID_USBD) { |
435 | clock_enable(PERIPH_ID_USBD); | 435 | clock_enable(PERIPH_ID_USBD); |
436 | /* Disable Reset if in Reset state */ | 436 | /* Disable Reset if in Reset state */ |
437 | reset_set_enable(PERIPH_ID_USBD, 0); | 437 | reset_set_enable(PERIPH_ID_USBD, 0); |
438 | } | 438 | } |
439 | usb1ctlr = (struct usb_ctlr *) | 439 | usb1ctlr = (struct usb_ctlr *) |
440 | ((u32)config->reg & USB1_ADDR_MASK); | 440 | ((u32)config->reg & USB1_ADDR_MASK); |
441 | val = readl(&usb1ctlr->utmip_bias_cfg0); | 441 | val = readl(&usb1ctlr->utmip_bias_cfg0); |
442 | setbits_le32(&val, UTMIP_HSDISCON_LEVEL_MSB); | 442 | setbits_le32(&val, UTMIP_HSDISCON_LEVEL_MSB); |
443 | clrsetbits_le32(&val, UTMIP_HSDISCON_LEVEL_MASK, | 443 | clrsetbits_le32(&val, UTMIP_HSDISCON_LEVEL_MASK, |
444 | 0x1 << UTMIP_HSDISCON_LEVEL_SHIFT); | 444 | 0x1 << UTMIP_HSDISCON_LEVEL_SHIFT); |
445 | clrsetbits_le32(&val, UTMIP_HSSQUELCH_LEVEL_MASK, | 445 | clrsetbits_le32(&val, UTMIP_HSSQUELCH_LEVEL_MASK, |
446 | 0x2 << UTMIP_HSSQUELCH_LEVEL_SHIFT); | 446 | 0x2 << UTMIP_HSSQUELCH_LEVEL_SHIFT); |
447 | writel(val, &usb1ctlr->utmip_bias_cfg0); | 447 | writel(val, &usb1ctlr->utmip_bias_cfg0); |
448 | 448 | ||
449 | /* Miscellaneous setting mentioned in Programming Guide */ | 449 | /* Miscellaneous setting mentioned in Programming Guide */ |
450 | clrbits_le32(&usbctlr->utmip_misc_cfg0, | 450 | clrbits_le32(&usbctlr->utmip_misc_cfg0, |
451 | UTMIP_SUSPEND_EXIT_ON_EDGE); | 451 | UTMIP_SUSPEND_EXIT_ON_EDGE); |
452 | } | 452 | } |
453 | 453 | ||
454 | /* Setting the tracking length time */ | 454 | /* Setting the tracking length time */ |
455 | clrsetbits_le32(&usbctlr->utmip_bias_cfg1, | 455 | clrsetbits_le32(&usbctlr->utmip_bias_cfg1, |
456 | UTMIP_BIAS_PDTRK_COUNT_MASK, | 456 | UTMIP_BIAS_PDTRK_COUNT_MASK, |
457 | timing[PARAM_BIAS_TIME] << UTMIP_BIAS_PDTRK_COUNT_SHIFT); | 457 | timing[PARAM_BIAS_TIME] << UTMIP_BIAS_PDTRK_COUNT_SHIFT); |
458 | 458 | ||
459 | /* Program debounce time for VBUS to become valid */ | 459 | /* Program debounce time for VBUS to become valid */ |
460 | clrsetbits_le32(&usbctlr->utmip_debounce_cfg0, | 460 | clrsetbits_le32(&usbctlr->utmip_debounce_cfg0, |
461 | UTMIP_DEBOUNCE_CFG0_MASK, | 461 | UTMIP_DEBOUNCE_CFG0_MASK, |
462 | timing[PARAM_DEBOUNCE_A_TIME] << UTMIP_DEBOUNCE_CFG0_SHIFT); | 462 | timing[PARAM_DEBOUNCE_A_TIME] << UTMIP_DEBOUNCE_CFG0_SHIFT); |
463 | 463 | ||
464 | setbits_le32(&usbctlr->utmip_tx_cfg0, UTMIP_FS_PREAMBLE_J); | 464 | setbits_le32(&usbctlr->utmip_tx_cfg0, UTMIP_FS_PREAMBLE_J); |
465 | 465 | ||
466 | /* Disable battery charge enabling bit */ | 466 | /* Disable battery charge enabling bit */ |
467 | setbits_le32(&usbctlr->utmip_bat_chrg_cfg0, UTMIP_PD_CHRG); | 467 | setbits_le32(&usbctlr->utmip_bat_chrg_cfg0, UTMIP_PD_CHRG); |
468 | 468 | ||
469 | clrbits_le32(&usbctlr->utmip_xcvr_cfg0, UTMIP_XCVR_LSBIAS_SE); | 469 | clrbits_le32(&usbctlr->utmip_xcvr_cfg0, UTMIP_XCVR_LSBIAS_SE); |
470 | setbits_le32(&usbctlr->utmip_spare_cfg0, FUSE_SETUP_SEL); | 470 | setbits_le32(&usbctlr->utmip_spare_cfg0, FUSE_SETUP_SEL); |
471 | 471 | ||
472 | /* | 472 | /* |
473 | * Configure the UTMIP_IDLE_WAIT and UTMIP_ELASTIC_LIMIT | 473 | * Configure the UTMIP_IDLE_WAIT and UTMIP_ELASTIC_LIMIT |
474 | * Setting these fields, together with default values of the | 474 | * Setting these fields, together with default values of the |
475 | * other fields, results in programming the registers below as | 475 | * other fields, results in programming the registers below as |
476 | * follows: | 476 | * follows: |
477 | * UTMIP_HSRX_CFG0 = 0x9168c000 | 477 | * UTMIP_HSRX_CFG0 = 0x9168c000 |
478 | * UTMIP_HSRX_CFG1 = 0x13 | 478 | * UTMIP_HSRX_CFG1 = 0x13 |
479 | */ | 479 | */ |
480 | 480 | ||
481 | /* Set PLL enable delay count and Crystal frequency count */ | 481 | /* Set PLL enable delay count and Crystal frequency count */ |
482 | val = readl(&usbctlr->utmip_hsrx_cfg0); | 482 | val = readl(&usbctlr->utmip_hsrx_cfg0); |
483 | clrsetbits_le32(&val, UTMIP_IDLE_WAIT_MASK, | 483 | clrsetbits_le32(&val, UTMIP_IDLE_WAIT_MASK, |
484 | utmip_idle_wait_delay << UTMIP_IDLE_WAIT_SHIFT); | 484 | utmip_idle_wait_delay << UTMIP_IDLE_WAIT_SHIFT); |
485 | clrsetbits_le32(&val, UTMIP_ELASTIC_LIMIT_MASK, | 485 | clrsetbits_le32(&val, UTMIP_ELASTIC_LIMIT_MASK, |
486 | utmip_elastic_limit << UTMIP_ELASTIC_LIMIT_SHIFT); | 486 | utmip_elastic_limit << UTMIP_ELASTIC_LIMIT_SHIFT); |
487 | writel(val, &usbctlr->utmip_hsrx_cfg0); | 487 | writel(val, &usbctlr->utmip_hsrx_cfg0); |
488 | 488 | ||
489 | /* Configure the UTMIP_HS_SYNC_START_DLY */ | 489 | /* Configure the UTMIP_HS_SYNC_START_DLY */ |
490 | clrsetbits_le32(&usbctlr->utmip_hsrx_cfg1, | 490 | clrsetbits_le32(&usbctlr->utmip_hsrx_cfg1, |
491 | UTMIP_HS_SYNC_START_DLY_MASK, | 491 | UTMIP_HS_SYNC_START_DLY_MASK, |
492 | utmip_hs_sync_start_delay << UTMIP_HS_SYNC_START_DLY_SHIFT); | 492 | utmip_hs_sync_start_delay << UTMIP_HS_SYNC_START_DLY_SHIFT); |
493 | 493 | ||
494 | /* Preceed the crystal clock disable by >100ns delay. */ | 494 | /* Preceed the crystal clock disable by >100ns delay. */ |
495 | udelay(1); | 495 | udelay(1); |
496 | 496 | ||
497 | /* Resuscitate crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN */ | 497 | /* Resuscitate crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN */ |
498 | setbits_le32(&usbctlr->utmip_misc_cfg1, UTMIP_PHY_XTAL_CLOCKEN); | 498 | setbits_le32(&usbctlr->utmip_misc_cfg1, UTMIP_PHY_XTAL_CLOCKEN); |
499 | 499 | ||
500 | if (controller->has_hostpc) { | 500 | if (controller->has_hostpc) { |
501 | if (config->periph_id == PERIPH_ID_USBD) | 501 | if (config->periph_id == PERIPH_ID_USBD) |
502 | clrbits_le32(&clkrst->crc_utmip_pll_cfg2, | 502 | clrbits_le32(&clkrst->crc_utmip_pll_cfg2, |
503 | UTMIP_FORCE_PD_SAMP_A_POWERDOWN); | 503 | UTMIP_FORCE_PD_SAMP_A_POWERDOWN); |
504 | if (config->periph_id == PERIPH_ID_USB2) | 504 | if (config->periph_id == PERIPH_ID_USB2) |
505 | clrbits_le32(&clkrst->crc_utmip_pll_cfg2, | 505 | clrbits_le32(&clkrst->crc_utmip_pll_cfg2, |
506 | UTMIP_FORCE_PD_SAMP_B_POWERDOWN); | 506 | UTMIP_FORCE_PD_SAMP_B_POWERDOWN); |
507 | if (config->periph_id == PERIPH_ID_USB3) | 507 | if (config->periph_id == PERIPH_ID_USB3) |
508 | clrbits_le32(&clkrst->crc_utmip_pll_cfg2, | 508 | clrbits_le32(&clkrst->crc_utmip_pll_cfg2, |
509 | UTMIP_FORCE_PD_SAMP_C_POWERDOWN); | 509 | UTMIP_FORCE_PD_SAMP_C_POWERDOWN); |
510 | } | 510 | } |
511 | /* Finished the per-controller init. */ | 511 | /* Finished the per-controller init. */ |
512 | 512 | ||
513 | /* De-assert UTMIP_RESET to bring out of reset. */ | 513 | /* De-assert UTMIP_RESET to bring out of reset. */ |
514 | clrbits_le32(&usbctlr->susp_ctrl, UTMIP_RESET); | 514 | clrbits_le32(&usbctlr->susp_ctrl, UTMIP_RESET); |
515 | 515 | ||
516 | /* Wait for the phy clock to become valid in 100 ms */ | 516 | /* Wait for the phy clock to become valid in 100 ms */ |
517 | for (loop_count = 100000; loop_count != 0; loop_count--) { | 517 | for (loop_count = 100000; loop_count != 0; loop_count--) { |
518 | if (readl(&usbctlr->susp_ctrl) & USB_PHY_CLK_VALID) | 518 | if (readl(&usbctlr->susp_ctrl) & USB_PHY_CLK_VALID) |
519 | break; | 519 | break; |
520 | udelay(1); | 520 | udelay(1); |
521 | } | 521 | } |
522 | if (!loop_count) | 522 | if (!loop_count) |
523 | return -1; | 523 | return -1; |
524 | 524 | ||
525 | /* Disable ICUSB FS/LS transceiver */ | 525 | /* Disable ICUSB FS/LS transceiver */ |
526 | clrbits_le32(&usbctlr->icusb_ctrl, IC_ENB1); | 526 | clrbits_le32(&usbctlr->icusb_ctrl, IC_ENB1); |
527 | 527 | ||
528 | /* Select UTMI parallel interface */ | 528 | /* Select UTMI parallel interface */ |
529 | init_phy_mux(config, PTS_UTMI, init); | 529 | init_phy_mux(config, PTS_UTMI, init); |
530 | 530 | ||
531 | /* Deassert power down state */ | 531 | /* Deassert power down state */ |
532 | clrbits_le32(&usbctlr->utmip_xcvr_cfg0, UTMIP_FORCE_PD_POWERDOWN | | 532 | clrbits_le32(&usbctlr->utmip_xcvr_cfg0, UTMIP_FORCE_PD_POWERDOWN | |
533 | UTMIP_FORCE_PD2_POWERDOWN | UTMIP_FORCE_PDZI_POWERDOWN); | 533 | UTMIP_FORCE_PD2_POWERDOWN | UTMIP_FORCE_PDZI_POWERDOWN); |
534 | clrbits_le32(&usbctlr->utmip_xcvr_cfg1, UTMIP_FORCE_PDDISC_POWERDOWN | | 534 | clrbits_le32(&usbctlr->utmip_xcvr_cfg1, UTMIP_FORCE_PDDISC_POWERDOWN | |
535 | UTMIP_FORCE_PDCHRP_POWERDOWN | UTMIP_FORCE_PDDR_POWERDOWN); | 535 | UTMIP_FORCE_PDCHRP_POWERDOWN | UTMIP_FORCE_PDDR_POWERDOWN); |
536 | 536 | ||
537 | if (controller->has_hostpc) { | 537 | if (controller->has_hostpc) { |
538 | /* | 538 | /* |
539 | * BIAS Pad Power Down is common among all 3 USB | 539 | * BIAS Pad Power Down is common among all 3 USB |
540 | * controllers and can be controlled from USB1 only. | 540 | * controllers and can be controlled from USB1 only. |
541 | */ | 541 | */ |
542 | usb1ctlr = (struct usb_ctlr *) | 542 | usb1ctlr = (struct usb_ctlr *) |
543 | ((u32)config->reg & USB1_ADDR_MASK); | 543 | ((u32)config->reg & USB1_ADDR_MASK); |
544 | clrbits_le32(&usb1ctlr->utmip_bias_cfg0, UTMIP_BIASPD); | 544 | clrbits_le32(&usb1ctlr->utmip_bias_cfg0, UTMIP_BIASPD); |
545 | udelay(25); | 545 | udelay(25); |
546 | clrbits_le32(&usb1ctlr->utmip_bias_cfg1, | 546 | clrbits_le32(&usb1ctlr->utmip_bias_cfg1, |
547 | UTMIP_FORCE_PDTRK_POWERDOWN); | 547 | UTMIP_FORCE_PDTRK_POWERDOWN); |
548 | } | 548 | } |
549 | return 0; | 549 | return 0; |
550 | } | 550 | } |
551 | 551 | ||
552 | #ifdef CONFIG_USB_ULPI | 552 | #ifdef CONFIG_USB_ULPI |
553 | /* if board file does not set a ULPI reference frequency we default to 24MHz */ | 553 | /* if board file does not set a ULPI reference frequency we default to 24MHz */ |
554 | #ifndef CONFIG_ULPI_REF_CLK | 554 | #ifndef CONFIG_ULPI_REF_CLK |
555 | #define CONFIG_ULPI_REF_CLK 24000000 | 555 | #define CONFIG_ULPI_REF_CLK 24000000 |
556 | #endif | 556 | #endif |
557 | 557 | ||
558 | /* set up the ULPI USB controller with the parameters provided */ | 558 | /* set up the ULPI USB controller with the parameters provided */ |
559 | static int init_ulpi_usb_controller(struct fdt_usb *config, | 559 | static int init_ulpi_usb_controller(struct fdt_usb *config, |
560 | enum usb_init_type init) | 560 | enum usb_init_type init) |
561 | { | 561 | { |
562 | u32 val; | 562 | u32 val; |
563 | int loop_count; | 563 | int loop_count; |
564 | struct ulpi_viewport ulpi_vp; | 564 | struct ulpi_viewport ulpi_vp; |
565 | struct usb_ctlr *usbctlr = config->reg; | 565 | struct usb_ctlr *usbctlr = config->reg; |
566 | 566 | ||
567 | /* set up ULPI reference clock on pllp_out4 */ | 567 | /* set up ULPI reference clock on pllp_out4 */ |
568 | clock_enable(PERIPH_ID_DEV2_OUT); | 568 | clock_enable(PERIPH_ID_DEV2_OUT); |
569 | clock_set_pllout(CLOCK_ID_PERIPH, PLL_OUT4, CONFIG_ULPI_REF_CLK); | 569 | clock_set_pllout(CLOCK_ID_PERIPH, PLL_OUT4, CONFIG_ULPI_REF_CLK); |
570 | 570 | ||
571 | /* reset ULPI phy */ | 571 | /* reset ULPI phy */ |
572 | if (fdt_gpio_isvalid(&config->phy_reset_gpio)) { | 572 | if (fdt_gpio_isvalid(&config->phy_reset_gpio)) { |
573 | fdtdec_setup_gpio(&config->phy_reset_gpio); | 573 | fdtdec_setup_gpio(&config->phy_reset_gpio); |
574 | gpio_direction_output(config->phy_reset_gpio.gpio, 0); | 574 | gpio_direction_output(config->phy_reset_gpio.gpio, 0); |
575 | mdelay(5); | 575 | mdelay(5); |
576 | gpio_set_value(config->phy_reset_gpio.gpio, 1); | 576 | gpio_set_value(config->phy_reset_gpio.gpio, 1); |
577 | } | 577 | } |
578 | 578 | ||
579 | /* Reset the usb controller */ | 579 | /* Reset the usb controller */ |
580 | clock_enable(config->periph_id); | 580 | clock_enable(config->periph_id); |
581 | usbf_reset_controller(config, usbctlr); | 581 | usbf_reset_controller(config, usbctlr); |
582 | 582 | ||
583 | /* enable pinmux bypass */ | 583 | /* enable pinmux bypass */ |
584 | setbits_le32(&usbctlr->ulpi_timing_ctrl_0, | 584 | setbits_le32(&usbctlr->ulpi_timing_ctrl_0, |
585 | ULPI_CLKOUT_PINMUX_BYP | ULPI_OUTPUT_PINMUX_BYP); | 585 | ULPI_CLKOUT_PINMUX_BYP | ULPI_OUTPUT_PINMUX_BYP); |
586 | 586 | ||
587 | /* Select ULPI parallel interface */ | 587 | /* Select ULPI parallel interface */ |
588 | init_phy_mux(config, PTS_ULPI, init); | 588 | init_phy_mux(config, PTS_ULPI, init); |
589 | 589 | ||
590 | /* enable ULPI transceiver */ | 590 | /* enable ULPI transceiver */ |
591 | setbits_le32(&usbctlr->susp_ctrl, ULPI_PHY_ENB); | 591 | setbits_le32(&usbctlr->susp_ctrl, ULPI_PHY_ENB); |
592 | 592 | ||
593 | /* configure ULPI transceiver timings */ | 593 | /* configure ULPI transceiver timings */ |
594 | val = 0; | 594 | val = 0; |
595 | writel(val, &usbctlr->ulpi_timing_ctrl_1); | 595 | writel(val, &usbctlr->ulpi_timing_ctrl_1); |
596 | 596 | ||
597 | val |= ULPI_DATA_TRIMMER_SEL(4); | 597 | val |= ULPI_DATA_TRIMMER_SEL(4); |
598 | val |= ULPI_STPDIRNXT_TRIMMER_SEL(4); | 598 | val |= ULPI_STPDIRNXT_TRIMMER_SEL(4); |
599 | val |= ULPI_DIR_TRIMMER_SEL(4); | 599 | val |= ULPI_DIR_TRIMMER_SEL(4); |
600 | writel(val, &usbctlr->ulpi_timing_ctrl_1); | 600 | writel(val, &usbctlr->ulpi_timing_ctrl_1); |
601 | udelay(10); | 601 | udelay(10); |
602 | 602 | ||
603 | val |= ULPI_DATA_TRIMMER_LOAD; | 603 | val |= ULPI_DATA_TRIMMER_LOAD; |
604 | val |= ULPI_STPDIRNXT_TRIMMER_LOAD; | 604 | val |= ULPI_STPDIRNXT_TRIMMER_LOAD; |
605 | val |= ULPI_DIR_TRIMMER_LOAD; | 605 | val |= ULPI_DIR_TRIMMER_LOAD; |
606 | writel(val, &usbctlr->ulpi_timing_ctrl_1); | 606 | writel(val, &usbctlr->ulpi_timing_ctrl_1); |
607 | 607 | ||
608 | /* set up phy for host operation with external vbus supply */ | 608 | /* set up phy for host operation with external vbus supply */ |
609 | ulpi_vp.port_num = 0; | 609 | ulpi_vp.port_num = 0; |
610 | ulpi_vp.viewport_addr = (u32)&usbctlr->ulpi_viewport; | 610 | ulpi_vp.viewport_addr = (u32)&usbctlr->ulpi_viewport; |
611 | 611 | ||
612 | if (ulpi_init(&ulpi_vp)) { | 612 | if (ulpi_init(&ulpi_vp)) { |
613 | printf("Tegra ULPI viewport init failed\n"); | 613 | printf("Tegra ULPI viewport init failed\n"); |
614 | return -1; | 614 | return -1; |
615 | } | 615 | } |
616 | 616 | ||
617 | ulpi_set_vbus(&ulpi_vp, 1, 1); | 617 | ulpi_set_vbus(&ulpi_vp, 1, 1); |
618 | ulpi_set_vbus_indicator(&ulpi_vp, 1, 1, 0); | 618 | ulpi_set_vbus_indicator(&ulpi_vp, 1, 1, 0); |
619 | 619 | ||
620 | /* enable wakeup events */ | 620 | /* enable wakeup events */ |
621 | setbits_le32(&usbctlr->port_sc1, WKCN | WKDS | WKOC); | 621 | setbits_le32(&usbctlr->port_sc1, WKCN | WKDS | WKOC); |
622 | 622 | ||
623 | /* Enable and wait for the phy clock to become valid in 100 ms */ | 623 | /* Enable and wait for the phy clock to become valid in 100 ms */ |
624 | setbits_le32(&usbctlr->susp_ctrl, USB_SUSP_CLR); | 624 | setbits_le32(&usbctlr->susp_ctrl, USB_SUSP_CLR); |
625 | for (loop_count = 100000; loop_count != 0; loop_count--) { | 625 | for (loop_count = 100000; loop_count != 0; loop_count--) { |
626 | if (readl(&usbctlr->susp_ctrl) & USB_PHY_CLK_VALID) | 626 | if (readl(&usbctlr->susp_ctrl) & USB_PHY_CLK_VALID) |
627 | break; | 627 | break; |
628 | udelay(1); | 628 | udelay(1); |
629 | } | 629 | } |
630 | if (!loop_count) | 630 | if (!loop_count) |
631 | return -1; | 631 | return -1; |
632 | clrbits_le32(&usbctlr->susp_ctrl, USB_SUSP_CLR); | 632 | clrbits_le32(&usbctlr->susp_ctrl, USB_SUSP_CLR); |
633 | 633 | ||
634 | return 0; | 634 | return 0; |
635 | } | 635 | } |
636 | #else | 636 | #else |
637 | static int init_ulpi_usb_controller(struct fdt_usb *config, | 637 | static int init_ulpi_usb_controller(struct fdt_usb *config, |
638 | enum usb_init_type init) | 638 | enum usb_init_type init) |
639 | { | 639 | { |
640 | printf("No code to set up ULPI controller, please enable" | 640 | printf("No code to set up ULPI controller, please enable" |
641 | "CONFIG_USB_ULPI and CONFIG_USB_ULPI_VIEWPORT"); | 641 | "CONFIG_USB_ULPI and CONFIG_USB_ULPI_VIEWPORT"); |
642 | return -1; | 642 | return -1; |
643 | } | 643 | } |
644 | #endif | 644 | #endif |
645 | 645 | ||
646 | static void config_clock(const u32 timing[]) | 646 | static void config_clock(const u32 timing[]) |
647 | { | 647 | { |
648 | clock_start_pll(CLOCK_ID_USB, | 648 | clock_start_pll(CLOCK_ID_USB, |
649 | timing[PARAM_DIVM], timing[PARAM_DIVN], timing[PARAM_DIVP], | 649 | timing[PARAM_DIVM], timing[PARAM_DIVN], timing[PARAM_DIVP], |
650 | timing[PARAM_CPCON], timing[PARAM_LFCON]); | 650 | timing[PARAM_CPCON], timing[PARAM_LFCON]); |
651 | } | 651 | } |
652 | 652 | ||
653 | static int fdt_decode_usb(const void *blob, int node, struct fdt_usb *config) | 653 | static int fdt_decode_usb(const void *blob, int node, struct fdt_usb *config) |
654 | { | 654 | { |
655 | const char *phy, *mode; | 655 | const char *phy, *mode; |
656 | 656 | ||
657 | config->reg = (struct usb_ctlr *)fdtdec_get_addr(blob, node, "reg"); | 657 | config->reg = (struct usb_ctlr *)fdtdec_get_addr(blob, node, "reg"); |
658 | mode = fdt_getprop(blob, node, "dr_mode", NULL); | 658 | mode = fdt_getprop(blob, node, "dr_mode", NULL); |
659 | if (mode) { | 659 | if (mode) { |
660 | if (0 == strcmp(mode, "host")) | 660 | if (0 == strcmp(mode, "host")) |
661 | config->dr_mode = DR_MODE_HOST; | 661 | config->dr_mode = DR_MODE_HOST; |
662 | else if (0 == strcmp(mode, "peripheral")) | 662 | else if (0 == strcmp(mode, "peripheral")) |
663 | config->dr_mode = DR_MODE_DEVICE; | 663 | config->dr_mode = DR_MODE_DEVICE; |
664 | else if (0 == strcmp(mode, "otg")) | 664 | else if (0 == strcmp(mode, "otg")) |
665 | config->dr_mode = DR_MODE_OTG; | 665 | config->dr_mode = DR_MODE_OTG; |
666 | else { | 666 | else { |
667 | debug("%s: Cannot decode dr_mode '%s'\n", __func__, | 667 | debug("%s: Cannot decode dr_mode '%s'\n", __func__, |
668 | mode); | 668 | mode); |
669 | return -FDT_ERR_NOTFOUND; | 669 | return -FDT_ERR_NOTFOUND; |
670 | } | 670 | } |
671 | } else { | 671 | } else { |
672 | config->dr_mode = DR_MODE_HOST; | 672 | config->dr_mode = DR_MODE_HOST; |
673 | } | 673 | } |
674 | 674 | ||
675 | phy = fdt_getprop(blob, node, "phy_type", NULL); | 675 | phy = fdt_getprop(blob, node, "phy_type", NULL); |
676 | config->utmi = phy && 0 == strcmp("utmi", phy); | 676 | config->utmi = phy && 0 == strcmp("utmi", phy); |
677 | config->ulpi = phy && 0 == strcmp("ulpi", phy); | 677 | config->ulpi = phy && 0 == strcmp("ulpi", phy); |
678 | config->enabled = fdtdec_get_is_enabled(blob, node); | 678 | config->enabled = fdtdec_get_is_enabled(blob, node); |
679 | config->has_legacy_mode = fdtdec_get_bool(blob, node, | 679 | config->has_legacy_mode = fdtdec_get_bool(blob, node, |
680 | "nvidia,has-legacy-mode"); | 680 | "nvidia,has-legacy-mode"); |
681 | if (config->has_legacy_mode) | 681 | if (config->has_legacy_mode) |
682 | port_addr_clear_csc = (u32) config->reg; | 682 | port_addr_clear_csc = (u32) config->reg; |
683 | config->periph_id = clock_decode_periph_id(blob, node); | 683 | config->periph_id = clock_decode_periph_id(blob, node); |
684 | if (config->periph_id == PERIPH_ID_NONE) { | 684 | if (config->periph_id == PERIPH_ID_NONE) { |
685 | debug("%s: Missing/invalid peripheral ID\n", __func__); | 685 | debug("%s: Missing/invalid peripheral ID\n", __func__); |
686 | return -FDT_ERR_NOTFOUND; | 686 | return -FDT_ERR_NOTFOUND; |
687 | } | 687 | } |
688 | fdtdec_decode_gpio(blob, node, "nvidia,vbus-gpio", &config->vbus_gpio); | 688 | fdtdec_decode_gpio(blob, node, "nvidia,vbus-gpio", &config->vbus_gpio); |
689 | fdtdec_decode_gpio(blob, node, "nvidia,phy-reset-gpio", | 689 | fdtdec_decode_gpio(blob, node, "nvidia,phy-reset-gpio", |
690 | &config->phy_reset_gpio); | 690 | &config->phy_reset_gpio); |
691 | debug("enabled=%d, legacy_mode=%d, utmi=%d, ulpi=%d, periph_id=%d, " | 691 | debug("enabled=%d, legacy_mode=%d, utmi=%d, ulpi=%d, periph_id=%d, " |
692 | "vbus=%d, phy_reset=%d, dr_mode=%d\n", | 692 | "vbus=%d, phy_reset=%d, dr_mode=%d\n", |
693 | config->enabled, config->has_legacy_mode, config->utmi, | 693 | config->enabled, config->has_legacy_mode, config->utmi, |
694 | config->ulpi, config->periph_id, config->vbus_gpio.gpio, | 694 | config->ulpi, config->periph_id, config->vbus_gpio.gpio, |
695 | config->phy_reset_gpio.gpio, config->dr_mode); | 695 | config->phy_reset_gpio.gpio, config->dr_mode); |
696 | 696 | ||
697 | return 0; | 697 | return 0; |
698 | } | 698 | } |
699 | 699 | ||
700 | /* | 700 | /* |
701 | * process_usb_nodes() - Process a list of USB nodes, adding them to our list | 701 | * process_usb_nodes() - Process a list of USB nodes, adding them to our list |
702 | * of USB ports. | 702 | * of USB ports. |
703 | * @blob: fdt blob | 703 | * @blob: fdt blob |
704 | * @node_list: list of nodes to process (any <=0 are ignored) | 704 | * @node_list: list of nodes to process (any <=0 are ignored) |
705 | * @count: number of nodes to process | 705 | * @count: number of nodes to process |
706 | * | 706 | * |
707 | * Return: 0 - ok, -1 - error | 707 | * Return: 0 - ok, -1 - error |
708 | */ | 708 | */ |
709 | static int process_usb_nodes(const void *blob, int node_list[], int count) | 709 | static int process_usb_nodes(const void *blob, int node_list[], int count) |
710 | { | 710 | { |
711 | struct fdt_usb config; | 711 | struct fdt_usb config; |
712 | int node, i; | 712 | int node, i; |
713 | int clk_done = 0; | 713 | int clk_done = 0; |
714 | 714 | ||
715 | port_count = 0; | 715 | port_count = 0; |
716 | for (i = 0; i < count; i++) { | 716 | for (i = 0; i < count; i++) { |
717 | if (port_count == USB_PORTS_MAX) { | 717 | if (port_count == USB_PORTS_MAX) { |
718 | printf("tegrausb: Cannot register more than %d ports\n", | 718 | printf("tegrausb: Cannot register more than %d ports\n", |
719 | USB_PORTS_MAX); | 719 | USB_PORTS_MAX); |
720 | return -1; | 720 | return -1; |
721 | } | 721 | } |
722 | 722 | ||
723 | debug("USB %d: ", i); | 723 | debug("USB %d: ", i); |
724 | node = node_list[i]; | 724 | node = node_list[i]; |
725 | if (!node) | 725 | if (!node) |
726 | continue; | 726 | continue; |
727 | if (fdt_decode_usb(blob, node, &config)) { | 727 | if (fdt_decode_usb(blob, node, &config)) { |
728 | debug("Cannot decode USB node %s\n", | 728 | debug("Cannot decode USB node %s\n", |
729 | fdt_get_name(blob, node, NULL)); | 729 | fdt_get_name(blob, node, NULL)); |
730 | return -1; | 730 | return -1; |
731 | } | 731 | } |
732 | if (!clk_done) { | 732 | if (!clk_done) { |
733 | config_clock(get_pll_timing()); | 733 | config_clock(get_pll_timing()); |
734 | clk_done = 1; | 734 | clk_done = 1; |
735 | } | 735 | } |
736 | config.initialized = 0; | 736 | config.initialized = 0; |
737 | 737 | ||
738 | /* add new USB port to the list of available ports */ | 738 | /* add new USB port to the list of available ports */ |
739 | port[port_count++] = config; | 739 | port[port_count++] = config; |
740 | } | 740 | } |
741 | 741 | ||
742 | return 0; | 742 | return 0; |
743 | } | 743 | } |
744 | 744 | ||
745 | int usb_process_devicetree(const void *blob) | 745 | int usb_process_devicetree(const void *blob) |
746 | { | 746 | { |
747 | int node_list[USB_PORTS_MAX]; | 747 | int node_list[USB_PORTS_MAX]; |
748 | int count, err = 0; | 748 | int count, err = 0; |
749 | int i; | 749 | int i; |
750 | 750 | ||
751 | for (i = 0; i < ARRAY_SIZE(fdt_usb_controllers); i++) { | 751 | for (i = 0; i < ARRAY_SIZE(fdt_usb_controllers); i++) { |
752 | controller = &fdt_usb_controllers[i]; | 752 | controller = &fdt_usb_controllers[i]; |
753 | 753 | ||
754 | count = fdtdec_find_aliases_for_id(blob, "usb", | 754 | count = fdtdec_find_aliases_for_id(blob, "usb", |
755 | controller->compat, node_list, USB_PORTS_MAX); | 755 | controller->compat, node_list, USB_PORTS_MAX); |
756 | if (count) { | 756 | if (count) { |
757 | err = process_usb_nodes(blob, node_list, count); | 757 | err = process_usb_nodes(blob, node_list, count); |
758 | if (err) | 758 | if (err) |
759 | printf("%s: Error processing USB node!\n", | 759 | printf("%s: Error processing USB node!\n", |
760 | __func__); | 760 | __func__); |
761 | return err; | 761 | return err; |
762 | } | 762 | } |
763 | } | 763 | } |
764 | if (i == ARRAY_SIZE(fdt_usb_controllers)) | 764 | if (i == ARRAY_SIZE(fdt_usb_controllers)) |
765 | controller = NULL; | 765 | controller = NULL; |
766 | 766 | ||
767 | return err; | 767 | return err; |
768 | } | 768 | } |
769 | 769 | ||
770 | /** | 770 | /** |
771 | * Start up the given port number (ports are numbered from 0 on each board). | 771 | * Start up the given port number (ports are numbered from 0 on each board). |
772 | * This returns values for the appropriate hccr and hcor addresses to use for | 772 | * This returns values for the appropriate hccr and hcor addresses to use for |
773 | * USB EHCI operations. | 773 | * USB EHCI operations. |
774 | * | 774 | * |
775 | * @param index port number to start | 775 | * @param index port number to start |
776 | * @param hccr returns start address of EHCI HCCR registers | 776 | * @param hccr returns start address of EHCI HCCR registers |
777 | * @param hcor returns start address of EHCI HCOR registers | 777 | * @param hcor returns start address of EHCI HCOR registers |
778 | * @return 0 if ok, -1 on error (generally invalid port number) | 778 | * @return 0 if ok, -1 on error (generally invalid port number) |
779 | */ | 779 | */ |
780 | int ehci_hcd_init(int index, enum usb_init_type init, | 780 | int ehci_hcd_init(int index, enum usb_init_type init, |
781 | struct ehci_hccr **hccr, struct ehci_hcor **hcor) | 781 | struct ehci_hccr **hccr, struct ehci_hcor **hcor) |
782 | { | 782 | { |
783 | struct fdt_usb *config; | 783 | struct fdt_usb *config; |
784 | struct usb_ctlr *usbctlr; | 784 | struct usb_ctlr *usbctlr; |
785 | 785 | ||
786 | if (index >= port_count) | 786 | if (index >= port_count) |
787 | return -1; | 787 | return -1; |
788 | 788 | ||
789 | config = &port[index]; | 789 | config = &port[index]; |
790 | 790 | ||
791 | switch (init) { | 791 | switch (init) { |
792 | case USB_INIT_HOST: | 792 | case USB_INIT_HOST: |
793 | switch (config->dr_mode) { | 793 | switch (config->dr_mode) { |
794 | case DR_MODE_HOST: | 794 | case DR_MODE_HOST: |
795 | case DR_MODE_OTG: | 795 | case DR_MODE_OTG: |
796 | break; | 796 | break; |
797 | default: | 797 | default: |
798 | printf("tegrausb: Invalid dr_mode %d for host mode\n", | 798 | printf("tegrausb: Invalid dr_mode %d for host mode\n", |
799 | config->dr_mode); | 799 | config->dr_mode); |
800 | return -1; | 800 | return -1; |
801 | } | 801 | } |
802 | break; | 802 | break; |
803 | case USB_INIT_DEVICE: | 803 | case USB_INIT_DEVICE: |
804 | if (config->periph_id != PERIPH_ID_USBD) { | 804 | if (config->periph_id != PERIPH_ID_USBD) { |
805 | printf("tegrausb: Device mode only supported on first USB controller\n"); | 805 | printf("tegrausb: Device mode only supported on first USB controller\n"); |
806 | return -1; | 806 | return -1; |
807 | } | 807 | } |
808 | if (!config->utmi) { | 808 | if (!config->utmi) { |
809 | printf("tegrausb: Device mode only supported with UTMI PHY\n"); | 809 | printf("tegrausb: Device mode only supported with UTMI PHY\n"); |
810 | return -1; | 810 | return -1; |
811 | } | 811 | } |
812 | switch (config->dr_mode) { | 812 | switch (config->dr_mode) { |
813 | case DR_MODE_DEVICE: | 813 | case DR_MODE_DEVICE: |
814 | case DR_MODE_OTG: | 814 | case DR_MODE_OTG: |
815 | break; | 815 | break; |
816 | default: | 816 | default: |
817 | printf("tegrausb: Invalid dr_mode %d for device mode\n", | 817 | printf("tegrausb: Invalid dr_mode %d for device mode\n", |
818 | config->dr_mode); | 818 | config->dr_mode); |
819 | return -1; | 819 | return -1; |
820 | } | 820 | } |
821 | break; | 821 | break; |
822 | default: | 822 | default: |
823 | printf("tegrausb: Unknown USB_INIT_* %d\n", init); | 823 | printf("tegrausb: Unknown USB_INIT_* %d\n", init); |
824 | return -1; | 824 | return -1; |
825 | } | 825 | } |
826 | 826 | ||
827 | /* skip init, if the port is already initialized */ | 827 | /* skip init, if the port is already initialized */ |
828 | if (config->initialized && config->init_type == init) | 828 | if (config->initialized && config->init_type == init) |
829 | goto success; | 829 | goto success; |
830 | 830 | ||
831 | if (config->utmi && init_utmi_usb_controller(config, init)) { | 831 | if (config->utmi && init_utmi_usb_controller(config, init)) { |
832 | printf("tegrausb: Cannot init port %d\n", index); | 832 | printf("tegrausb: Cannot init port %d\n", index); |
833 | return -1; | 833 | return -1; |
834 | } | 834 | } |
835 | 835 | ||
836 | if (config->ulpi && init_ulpi_usb_controller(config, init)) { | 836 | if (config->ulpi && init_ulpi_usb_controller(config, init)) { |
837 | printf("tegrausb: Cannot init port %d\n", index); | 837 | printf("tegrausb: Cannot init port %d\n", index); |
838 | return -1; | 838 | return -1; |
839 | } | 839 | } |
840 | 840 | ||
841 | set_up_vbus(config, init); | 841 | set_up_vbus(config, init); |
842 | 842 | ||
843 | config->initialized = 1; | 843 | config->initialized = 1; |
844 | config->init_type = init; | 844 | config->init_type = init; |
845 | 845 | ||
846 | success: | 846 | success: |
847 | usbctlr = config->reg; | 847 | usbctlr = config->reg; |
848 | *hccr = (struct ehci_hccr *)&usbctlr->cap_length; | 848 | *hccr = (struct ehci_hccr *)&usbctlr->cap_length; |
849 | *hcor = (struct ehci_hcor *)&usbctlr->usb_cmd; | 849 | *hcor = (struct ehci_hcor *)&usbctlr->usb_cmd; |
850 | 850 | ||
851 | return 0; | 851 | return 0; |
852 | } | 852 | } |
853 | 853 | ||
854 | /* | 854 | /* |
855 | * Bring down the specified USB controller | 855 | * Bring down the specified USB controller |
856 | */ | 856 | */ |
857 | int ehci_hcd_stop(int index) | 857 | int ehci_hcd_stop(int index) |
858 | { | 858 | { |
859 | struct usb_ctlr *usbctlr; | 859 | struct usb_ctlr *usbctlr; |
860 | 860 | ||
861 | usbctlr = port[index].reg; | 861 | usbctlr = port[index].reg; |
862 | 862 | ||
863 | /* Stop controller */ | 863 | /* Stop controller */ |
864 | writel(0, &usbctlr->usb_cmd); | 864 | writel(0, &usbctlr->usb_cmd); |
865 | udelay(1000); | 865 | udelay(1000); |
866 | 866 | ||
867 | /* Initiate controller reset */ | 867 | /* Initiate controller reset */ |
868 | writel(2, &usbctlr->usb_cmd); | 868 | writel(2, &usbctlr->usb_cmd); |
869 | udelay(1000); | 869 | udelay(1000); |
870 | 870 | ||
871 | port[index].initialized = 0; | 871 | port[index].initialized = 0; |
872 | 872 | ||
873 | return 0; | 873 | return 0; |
874 | } | 874 | } |
875 | 875 |
drivers/usb/host/ehci.h
1 | /*- | 1 | /*- |
2 | * Copyright (c) 2007-2008, Juniper Networks, Inc. | 2 | * Copyright (c) 2007-2008, Juniper Networks, Inc. |
3 | * Copyright (c) 2008, Michael Trimarchi <trimarchimichael@yahoo.it> | 3 | * Copyright (c) 2008, Michael Trimarchi <trimarchimichael@yahoo.it> |
4 | * All rights reserved. | 4 | * All rights reserved. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License as | 7 | * modify it under the terms of the GNU General Public License as |
8 | * published by the Free Software Foundation version 2 of | 8 | * published by the Free Software Foundation version 2 of |
9 | * the License. | 9 | * the License. |
10 | * | 10 | * |
11 | * This program is distributed in the hope that it will be useful, | 11 | * This program is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. | 14 | * GNU General Public License for more details. |
15 | * | 15 | * |
16 | * You should have received a copy of the GNU General Public License | 16 | * You should have received a copy of the GNU General Public License |
17 | * along with this program; if not, write to the Free Software | 17 | * along with this program; if not, write to the Free Software |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
19 | * MA 02111-1307 USA | 19 | * MA 02111-1307 USA |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #ifndef USB_EHCI_H | 22 | #ifndef USB_EHCI_H |
23 | #define USB_EHCI_H | 23 | #define USB_EHCI_H |
24 | 24 | ||
25 | #include <usb.h> | 25 | #include <usb.h> |
26 | 26 | ||
27 | #if !defined(CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) | 27 | #if !defined(CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) |
28 | #define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 2 | 28 | #define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 2 |
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | /* | 31 | /* |
32 | * Register Space. | 32 | * Register Space. |
33 | */ | 33 | */ |
34 | struct ehci_hccr { | 34 | struct ehci_hccr { |
35 | uint32_t cr_capbase; | 35 | uint32_t cr_capbase; |
36 | #define HC_LENGTH(p) (((p) >> 0) & 0x00ff) | 36 | #define HC_LENGTH(p) (((p) >> 0) & 0x00ff) |
37 | #define HC_VERSION(p) (((p) >> 16) & 0xffff) | 37 | #define HC_VERSION(p) (((p) >> 16) & 0xffff) |
38 | uint32_t cr_hcsparams; | 38 | uint32_t cr_hcsparams; |
39 | #define HCS_PPC(p) ((p) & (1 << 4)) | 39 | #define HCS_PPC(p) ((p) & (1 << 4)) |
40 | #define HCS_INDICATOR(p) ((p) & (1 << 16)) /* Port indicators */ | 40 | #define HCS_INDICATOR(p) ((p) & (1 << 16)) /* Port indicators */ |
41 | #define HCS_N_PORTS(p) (((p) >> 0) & 0xf) | 41 | #define HCS_N_PORTS(p) (((p) >> 0) & 0xf) |
42 | uint32_t cr_hccparams; | 42 | uint32_t cr_hccparams; |
43 | uint8_t cr_hcsp_portrt[8]; | 43 | uint8_t cr_hcsp_portrt[8]; |
44 | } __attribute__ ((packed, aligned(4))); | 44 | } __attribute__ ((packed, aligned(4))); |
45 | 45 | ||
46 | struct ehci_hcor { | 46 | struct ehci_hcor { |
47 | uint32_t or_usbcmd; | 47 | uint32_t or_usbcmd; |
48 | #define CMD_PARK (1 << 11) /* enable "park" */ | 48 | #define CMD_PARK (1 << 11) /* enable "park" */ |
49 | #define CMD_PARK_CNT(c) (((c) >> 8) & 3) /* how many transfers to park */ | 49 | #define CMD_PARK_CNT(c) (((c) >> 8) & 3) /* how many transfers to park */ |
50 | #define CMD_ASE (1 << 5) /* async schedule enable */ | 50 | #define CMD_ASE (1 << 5) /* async schedule enable */ |
51 | #define CMD_LRESET (1 << 7) /* partial reset */ | 51 | #define CMD_LRESET (1 << 7) /* partial reset */ |
52 | #define CMD_IAAD (1 << 5) /* "doorbell" interrupt */ | 52 | #define CMD_IAAD (1 << 5) /* "doorbell" interrupt */ |
53 | #define CMD_PSE (1 << 4) /* periodic schedule enable */ | 53 | #define CMD_PSE (1 << 4) /* periodic schedule enable */ |
54 | #define CMD_RESET (1 << 1) /* reset HC not bus */ | 54 | #define CMD_RESET (1 << 1) /* reset HC not bus */ |
55 | #define CMD_RUN (1 << 0) /* start/stop HC */ | 55 | #define CMD_RUN (1 << 0) /* start/stop HC */ |
56 | uint32_t or_usbsts; | 56 | uint32_t or_usbsts; |
57 | #define STS_ASS (1 << 15) | 57 | #define STS_ASS (1 << 15) |
58 | #define STS_PSS (1 << 14) | 58 | #define STS_PSS (1 << 14) |
59 | #define STS_HALT (1 << 12) | 59 | #define STS_HALT (1 << 12) |
60 | uint32_t or_usbintr; | 60 | uint32_t or_usbintr; |
61 | #define INTR_UE (1 << 0) /* USB interrupt enable */ | 61 | #define INTR_UE (1 << 0) /* USB interrupt enable */ |
62 | #define INTR_UEE (1 << 1) /* USB error interrupt enable */ | 62 | #define INTR_UEE (1 << 1) /* USB error interrupt enable */ |
63 | #define INTR_PCE (1 << 2) /* Port change detect enable */ | 63 | #define INTR_PCE (1 << 2) /* Port change detect enable */ |
64 | #define INTR_SEE (1 << 4) /* system error enable */ | 64 | #define INTR_SEE (1 << 4) /* system error enable */ |
65 | #define INTR_AAE (1 << 5) /* Interrupt on async adavance enable */ | 65 | #define INTR_AAE (1 << 5) /* Interrupt on async adavance enable */ |
66 | uint32_t or_frindex; | 66 | uint32_t or_frindex; |
67 | uint32_t or_ctrldssegment; | 67 | uint32_t or_ctrldssegment; |
68 | uint32_t or_periodiclistbase; | 68 | uint32_t or_periodiclistbase; |
69 | uint32_t or_asynclistaddr; | 69 | uint32_t or_asynclistaddr; |
70 | uint32_t _reserved_0_; | 70 | uint32_t _reserved_0_; |
71 | uint32_t or_burstsize; | 71 | uint32_t or_burstsize; |
72 | uint32_t or_txfilltuning; | 72 | uint32_t or_txfilltuning; |
73 | #define TXFIFO_THRESH_MASK (0x3f << 16) | 73 | #define TXFIFO_THRESH_MASK (0x3f << 16) |
74 | #define TXFIFO_THRESH(p) ((p & 0x3f) << 16) | 74 | #define TXFIFO_THRESH(p) ((p & 0x3f) << 16) |
75 | uint32_t _reserved_1_[6]; | 75 | uint32_t _reserved_1_[6]; |
76 | uint32_t or_configflag; | 76 | uint32_t or_configflag; |
77 | #define FLAG_CF (1 << 0) /* true: we'll support "high speed" */ | 77 | #define FLAG_CF (1 << 0) /* true: we'll support "high speed" */ |
78 | uint32_t or_portsc[CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS]; | 78 | uint32_t or_portsc[CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS]; |
79 | #define PORTSC_PSPD(x) (((x) >> 26) & 0x3) | 79 | #define PORTSC_PSPD(x) (((x) >> 26) & 0x3) |
80 | #define PORTSC_PSPD_FS 0x0 | 80 | #define PORTSC_PSPD_FS 0x0 |
81 | #define PORTSC_PSPD_LS 0x1 | 81 | #define PORTSC_PSPD_LS 0x1 |
82 | #define PORTSC_PSPD_HS 0x2 | 82 | #define PORTSC_PSPD_HS 0x2 |
83 | uint32_t or_systune; | 83 | uint32_t or_systune; |
84 | } __attribute__ ((packed, aligned(4))); | 84 | } __attribute__ ((packed, aligned(4))); |
85 | 85 | ||
86 | #define USBMODE 0x68 /* USB Device mode */ | 86 | #define USBMODE 0x68 /* USB Device mode */ |
87 | #define USBMODE_SDIS (1 << 3) /* Stream disable */ | 87 | #define USBMODE_SDIS (1 << 3) /* Stream disable */ |
88 | #define USBMODE_BE (1 << 2) /* BE/LE endiannes select */ | 88 | #define USBMODE_BE (1 << 2) /* BE/LE endiannes select */ |
89 | #define USBMODE_CM_HC (3 << 0) /* host controller mode */ | 89 | #define USBMODE_CM_HC (3 << 0) /* host controller mode */ |
90 | #define USBMODE_CM_IDLE (0 << 0) /* idle state */ | 90 | #define USBMODE_CM_IDLE (0 << 0) /* idle state */ |
91 | 91 | ||
92 | /* Interface descriptor */ | 92 | /* Interface descriptor */ |
93 | struct usb_linux_interface_descriptor { | 93 | struct usb_linux_interface_descriptor { |
94 | unsigned char bLength; | 94 | unsigned char bLength; |
95 | unsigned char bDescriptorType; | 95 | unsigned char bDescriptorType; |
96 | unsigned char bInterfaceNumber; | 96 | unsigned char bInterfaceNumber; |
97 | unsigned char bAlternateSetting; | 97 | unsigned char bAlternateSetting; |
98 | unsigned char bNumEndpoints; | 98 | unsigned char bNumEndpoints; |
99 | unsigned char bInterfaceClass; | 99 | unsigned char bInterfaceClass; |
100 | unsigned char bInterfaceSubClass; | 100 | unsigned char bInterfaceSubClass; |
101 | unsigned char bInterfaceProtocol; | 101 | unsigned char bInterfaceProtocol; |
102 | unsigned char iInterface; | 102 | unsigned char iInterface; |
103 | } __attribute__ ((packed)); | 103 | } __attribute__ ((packed)); |
104 | 104 | ||
105 | /* Configuration descriptor information.. */ | 105 | /* Configuration descriptor information.. */ |
106 | struct usb_linux_config_descriptor { | 106 | struct usb_linux_config_descriptor { |
107 | unsigned char bLength; | 107 | unsigned char bLength; |
108 | unsigned char bDescriptorType; | 108 | unsigned char bDescriptorType; |
109 | unsigned short wTotalLength; | 109 | unsigned short wTotalLength; |
110 | unsigned char bNumInterfaces; | 110 | unsigned char bNumInterfaces; |
111 | unsigned char bConfigurationValue; | 111 | unsigned char bConfigurationValue; |
112 | unsigned char iConfiguration; | 112 | unsigned char iConfiguration; |
113 | unsigned char bmAttributes; | 113 | unsigned char bmAttributes; |
114 | unsigned char MaxPower; | 114 | unsigned char MaxPower; |
115 | } __attribute__ ((packed)); | 115 | } __attribute__ ((packed)); |
116 | 116 | ||
117 | #if defined CONFIG_EHCI_DESC_BIG_ENDIAN | 117 | #if defined CONFIG_EHCI_DESC_BIG_ENDIAN |
118 | #define ehci_readl(x) (*((volatile u32 *)(x))) | 118 | #define ehci_readl(x) (*((volatile u32 *)(x))) |
119 | #define ehci_writel(a, b) (*((volatile u32 *)(a)) = ((volatile u32)b)) | 119 | #define ehci_writel(a, b) (*((volatile u32 *)(a)) = ((volatile u32)b)) |
120 | #else | 120 | #else |
121 | #define ehci_readl(x) cpu_to_le32((*((volatile u32 *)(x)))) | 121 | #define ehci_readl(x) cpu_to_le32((*((volatile u32 *)(x)))) |
122 | #define ehci_writel(a, b) (*((volatile u32 *)(a)) = \ | 122 | #define ehci_writel(a, b) (*((volatile u32 *)(a)) = \ |
123 | cpu_to_le32(((volatile u32)b))) | 123 | cpu_to_le32(((volatile u32)b))) |
124 | #endif | 124 | #endif |
125 | 125 | ||
126 | #if defined CONFIG_EHCI_MMIO_BIG_ENDIAN | 126 | #if defined CONFIG_EHCI_MMIO_BIG_ENDIAN |
127 | #define hc32_to_cpu(x) be32_to_cpu((x)) | 127 | #define hc32_to_cpu(x) be32_to_cpu((x)) |
128 | #define cpu_to_hc32(x) cpu_to_be32((x)) | 128 | #define cpu_to_hc32(x) cpu_to_be32((x)) |
129 | #else | 129 | #else |
130 | #define hc32_to_cpu(x) le32_to_cpu((x)) | 130 | #define hc32_to_cpu(x) le32_to_cpu((x)) |
131 | #define cpu_to_hc32(x) cpu_to_le32((x)) | 131 | #define cpu_to_hc32(x) cpu_to_le32((x)) |
132 | #endif | 132 | #endif |
133 | 133 | ||
134 | #define EHCI_PS_WKOC_E (1 << 22) /* RW wake on over current */ | 134 | #define EHCI_PS_WKOC_E (1 << 22) /* RW wake on over current */ |
135 | #define EHCI_PS_WKDSCNNT_E (1 << 21) /* RW wake on disconnect */ | 135 | #define EHCI_PS_WKDSCNNT_E (1 << 21) /* RW wake on disconnect */ |
136 | #define EHCI_PS_WKCNNT_E (1 << 20) /* RW wake on connect */ | 136 | #define EHCI_PS_WKCNNT_E (1 << 20) /* RW wake on connect */ |
137 | #define EHCI_PS_PO (1 << 13) /* RW port owner */ | 137 | #define EHCI_PS_PO (1 << 13) /* RW port owner */ |
138 | #define EHCI_PS_PP (1 << 12) /* RW,RO port power */ | 138 | #define EHCI_PS_PP (1 << 12) /* RW,RO port power */ |
139 | #define EHCI_PS_LS (3 << 10) /* RO line status */ | 139 | #define EHCI_PS_LS (3 << 10) /* RO line status */ |
140 | #define EHCI_PS_PR (1 << 8) /* RW port reset */ | 140 | #define EHCI_PS_PR (1 << 8) /* RW port reset */ |
141 | #define EHCI_PS_SUSP (1 << 7) /* RW suspend */ | 141 | #define EHCI_PS_SUSP (1 << 7) /* RW suspend */ |
142 | #define EHCI_PS_FPR (1 << 6) /* RW force port resume */ | 142 | #define EHCI_PS_FPR (1 << 6) /* RW force port resume */ |
143 | #define EHCI_PS_OCC (1 << 5) /* RWC over current change */ | 143 | #define EHCI_PS_OCC (1 << 5) /* RWC over current change */ |
144 | #define EHCI_PS_OCA (1 << 4) /* RO over current active */ | 144 | #define EHCI_PS_OCA (1 << 4) /* RO over current active */ |
145 | #define EHCI_PS_PEC (1 << 3) /* RWC port enable change */ | 145 | #define EHCI_PS_PEC (1 << 3) /* RWC port enable change */ |
146 | #define EHCI_PS_PE (1 << 2) /* RW port enable */ | 146 | #define EHCI_PS_PE (1 << 2) /* RW port enable */ |
147 | #define EHCI_PS_CSC (1 << 1) /* RWC connect status change */ | 147 | #define EHCI_PS_CSC (1 << 1) /* RWC connect status change */ |
148 | #define EHCI_PS_CS (1 << 0) /* RO connect status */ | 148 | #define EHCI_PS_CS (1 << 0) /* RO connect status */ |
149 | #define EHCI_PS_CLEAR (EHCI_PS_OCC | EHCI_PS_PEC | EHCI_PS_CSC) | 149 | #define EHCI_PS_CLEAR (EHCI_PS_OCC | EHCI_PS_PEC | EHCI_PS_CSC) |
150 | 150 | ||
151 | #define EHCI_PS_IS_LOWSPEED(x) (((x) & EHCI_PS_LS) == (1 << 10)) | 151 | #define EHCI_PS_IS_LOWSPEED(x) (((x) & EHCI_PS_LS) == (1 << 10)) |
152 | 152 | ||
153 | /* | 153 | /* |
154 | * Schedule Interface Space. | 154 | * Schedule Interface Space. |
155 | * | 155 | * |
156 | * IMPORTANT: Software must ensure that no interface data structure | 156 | * IMPORTANT: Software must ensure that no interface data structure |
157 | * reachable by the EHCI host controller spans a 4K page boundary! | 157 | * reachable by the EHCI host controller spans a 4K page boundary! |
158 | * | 158 | * |
159 | * Periodic transfers (i.e. isochronous and interrupt transfers) are | 159 | * Periodic transfers (i.e. isochronous and interrupt transfers) are |
160 | * not supported. | 160 | * not supported. |
161 | */ | 161 | */ |
162 | 162 | ||
163 | /* Queue Element Transfer Descriptor (qTD). */ | 163 | /* Queue Element Transfer Descriptor (qTD). */ |
164 | struct qTD { | 164 | struct qTD { |
165 | /* this part defined by EHCI spec */ | 165 | /* this part defined by EHCI spec */ |
166 | uint32_t qt_next; /* see EHCI 3.5.1 */ | 166 | uint32_t qt_next; /* see EHCI 3.5.1 */ |
167 | #define QT_NEXT_TERMINATE 1 | 167 | #define QT_NEXT_TERMINATE 1 |
168 | uint32_t qt_altnext; /* see EHCI 3.5.2 */ | 168 | uint32_t qt_altnext; /* see EHCI 3.5.2 */ |
169 | uint32_t qt_token; /* see EHCI 3.5.3 */ | 169 | uint32_t qt_token; /* see EHCI 3.5.3 */ |
170 | #define QT_TOKEN_DT(x) (((x) & 0x1) << 31) /* Data Toggle */ | 170 | #define QT_TOKEN_DT(x) (((x) & 0x1) << 31) /* Data Toggle */ |
171 | #define QT_TOKEN_GET_DT(x) (((x) >> 31) & 0x1) | 171 | #define QT_TOKEN_GET_DT(x) (((x) >> 31) & 0x1) |
172 | #define QT_TOKEN_TOTALBYTES(x) (((x) & 0x7fff) << 16) /* Total Bytes to Transfer */ | 172 | #define QT_TOKEN_TOTALBYTES(x) (((x) & 0x7fff) << 16) /* Total Bytes to Transfer */ |
173 | #define QT_TOKEN_GET_TOTALBYTES(x) (((x) >> 16) & 0x7fff) | 173 | #define QT_TOKEN_GET_TOTALBYTES(x) (((x) >> 16) & 0x7fff) |
174 | #define QT_TOKEN_IOC(x) (((x) & 0x1) << 15) /* Interrupt On Complete */ | 174 | #define QT_TOKEN_IOC(x) (((x) & 0x1) << 15) /* Interrupt On Complete */ |
175 | #define QT_TOKEN_CPAGE(x) (((x) & 0x7) << 12) /* Current Page */ | 175 | #define QT_TOKEN_CPAGE(x) (((x) & 0x7) << 12) /* Current Page */ |
176 | #define QT_TOKEN_CERR(x) (((x) & 0x3) << 10) /* Error Counter */ | 176 | #define QT_TOKEN_CERR(x) (((x) & 0x3) << 10) /* Error Counter */ |
177 | #define QT_TOKEN_PID(x) (((x) & 0x3) << 8) /* PID Code */ | 177 | #define QT_TOKEN_PID(x) (((x) & 0x3) << 8) /* PID Code */ |
178 | #define QT_TOKEN_PID_OUT 0x0 | 178 | #define QT_TOKEN_PID_OUT 0x0 |
179 | #define QT_TOKEN_PID_IN 0x1 | 179 | #define QT_TOKEN_PID_IN 0x1 |
180 | #define QT_TOKEN_PID_SETUP 0x2 | 180 | #define QT_TOKEN_PID_SETUP 0x2 |
181 | #define QT_TOKEN_STATUS(x) (((x) & 0xff) << 0) /* Status */ | 181 | #define QT_TOKEN_STATUS(x) (((x) & 0xff) << 0) /* Status */ |
182 | #define QT_TOKEN_GET_STATUS(x) (((x) >> 0) & 0xff) | 182 | #define QT_TOKEN_GET_STATUS(x) (((x) >> 0) & 0xff) |
183 | #define QT_TOKEN_STATUS_ACTIVE 0x80 | 183 | #define QT_TOKEN_STATUS_ACTIVE 0x80 |
184 | #define QT_TOKEN_STATUS_HALTED 0x40 | 184 | #define QT_TOKEN_STATUS_HALTED 0x40 |
185 | #define QT_TOKEN_STATUS_DATBUFERR 0x20 | 185 | #define QT_TOKEN_STATUS_DATBUFERR 0x20 |
186 | #define QT_TOKEN_STATUS_BABBLEDET 0x10 | 186 | #define QT_TOKEN_STATUS_BABBLEDET 0x10 |
187 | #define QT_TOKEN_STATUS_XACTERR 0x08 | 187 | #define QT_TOKEN_STATUS_XACTERR 0x08 |
188 | #define QT_TOKEN_STATUS_MISSEDUFRAME 0x04 | 188 | #define QT_TOKEN_STATUS_MISSEDUFRAME 0x04 |
189 | #define QT_TOKEN_STATUS_SPLITXSTATE 0x02 | 189 | #define QT_TOKEN_STATUS_SPLITXSTATE 0x02 |
190 | #define QT_TOKEN_STATUS_PERR 0x01 | 190 | #define QT_TOKEN_STATUS_PERR 0x01 |
191 | #define QT_BUFFER_CNT 5 | 191 | #define QT_BUFFER_CNT 5 |
192 | uint32_t qt_buffer[QT_BUFFER_CNT]; /* see EHCI 3.5.4 */ | 192 | uint32_t qt_buffer[QT_BUFFER_CNT]; /* see EHCI 3.5.4 */ |
193 | uint32_t qt_buffer_hi[QT_BUFFER_CNT]; /* Appendix B */ | 193 | uint32_t qt_buffer_hi[QT_BUFFER_CNT]; /* Appendix B */ |
194 | /* pad struct for 32 byte alignment */ | 194 | /* pad struct for 32 byte alignment */ |
195 | uint32_t unused[3]; | 195 | uint32_t unused[3]; |
196 | }; | 196 | }; |
197 | 197 | ||
198 | #define EHCI_PAGE_SIZE 4096 | 198 | #define EHCI_PAGE_SIZE 4096 |
199 | 199 | ||
200 | /* Queue Head (QH). */ | 200 | /* Queue Head (QH). */ |
201 | struct QH { | 201 | struct QH { |
202 | uint32_t qh_link; | 202 | uint32_t qh_link; |
203 | #define QH_LINK_TERMINATE 1 | 203 | #define QH_LINK_TERMINATE 1 |
204 | #define QH_LINK_TYPE_ITD 0 | 204 | #define QH_LINK_TYPE_ITD 0 |
205 | #define QH_LINK_TYPE_QH 2 | 205 | #define QH_LINK_TYPE_QH 2 |
206 | #define QH_LINK_TYPE_SITD 4 | 206 | #define QH_LINK_TYPE_SITD 4 |
207 | #define QH_LINK_TYPE_FSTN 6 | 207 | #define QH_LINK_TYPE_FSTN 6 |
208 | uint32_t qh_endpt1; | 208 | uint32_t qh_endpt1; |
209 | #define QH_ENDPT1_RL(x) (((x) & 0xf) << 28) /* NAK Count Reload */ | 209 | #define QH_ENDPT1_RL(x) (((x) & 0xf) << 28) /* NAK Count Reload */ |
210 | #define QH_ENDPT1_C(x) (((x) & 0x1) << 27) /* Control Endpoint Flag */ | 210 | #define QH_ENDPT1_C(x) (((x) & 0x1) << 27) /* Control Endpoint Flag */ |
211 | #define QH_ENDPT1_MAXPKTLEN(x) (((x) & 0x7ff) << 16) /* Maximum Packet Length */ | 211 | #define QH_ENDPT1_MAXPKTLEN(x) (((x) & 0x7ff) << 16) /* Maximum Packet Length */ |
212 | #define QH_ENDPT1_H(x) (((x) & 0x1) << 15) /* Head of Reclamation List Flag */ | 212 | #define QH_ENDPT1_H(x) (((x) & 0x1) << 15) /* Head of Reclamation List Flag */ |
213 | #define QH_ENDPT1_DTC(x) (((x) & 0x1) << 14) /* Data Toggle Control */ | 213 | #define QH_ENDPT1_DTC(x) (((x) & 0x1) << 14) /* Data Toggle Control */ |
214 | #define QH_ENDPT1_DTC_IGNORE_QTD_TD 0x0 | 214 | #define QH_ENDPT1_DTC_IGNORE_QTD_TD 0x0 |
215 | #define QH_ENDPT1_DTC_DT_FROM_QTD 0x1 | 215 | #define QH_ENDPT1_DTC_DT_FROM_QTD 0x1 |
216 | #define QH_ENDPT1_EPS(x) (((x) & 0x3) << 12) /* Endpoint Speed */ | 216 | #define QH_ENDPT1_EPS(x) (((x) & 0x3) << 12) /* Endpoint Speed */ |
217 | #define QH_ENDPT1_EPS_FS 0x0 | 217 | #define QH_ENDPT1_EPS_FS 0x0 |
218 | #define QH_ENDPT1_EPS_LS 0x1 | 218 | #define QH_ENDPT1_EPS_LS 0x1 |
219 | #define QH_ENDPT1_EPS_HS 0x2 | 219 | #define QH_ENDPT1_EPS_HS 0x2 |
220 | #define QH_ENDPT1_ENDPT(x) (((x) & 0xf) << 8) /* Endpoint Number */ | 220 | #define QH_ENDPT1_ENDPT(x) (((x) & 0xf) << 8) /* Endpoint Number */ |
221 | #define QH_ENDPT1_I(x) (((x) & 0x1) << 7) /* Inactivate on Next Transaction */ | 221 | #define QH_ENDPT1_I(x) (((x) & 0x1) << 7) /* Inactivate on Next Transaction */ |
222 | #define QH_ENDPT1_DEVADDR(x) (((x) & 0x7f) << 0) /* Device Address */ | 222 | #define QH_ENDPT1_DEVADDR(x) (((x) & 0x7f) << 0) /* Device Address */ |
223 | uint32_t qh_endpt2; | 223 | uint32_t qh_endpt2; |
224 | #define QH_ENDPT2_MULT(x) (((x) & 0x3) << 30) /* High-Bandwidth Pipe Multiplier */ | 224 | #define QH_ENDPT2_MULT(x) (((x) & 0x3) << 30) /* High-Bandwidth Pipe Multiplier */ |
225 | #define QH_ENDPT2_PORTNUM(x) (((x) & 0x7f) << 23) /* Port Number */ | 225 | #define QH_ENDPT2_PORTNUM(x) (((x) & 0x7f) << 23) /* Port Number */ |
226 | #define QH_ENDPT2_HUBADDR(x) (((x) & 0x7f) << 16) /* Hub Address */ | 226 | #define QH_ENDPT2_HUBADDR(x) (((x) & 0x7f) << 16) /* Hub Address */ |
227 | #define QH_ENDPT2_UFCMASK(x) (((x) & 0xff) << 8) /* Split Completion Mask */ | 227 | #define QH_ENDPT2_UFCMASK(x) (((x) & 0xff) << 8) /* Split Completion Mask */ |
228 | #define QH_ENDPT2_UFSMASK(x) (((x) & 0xff) << 0) /* Interrupt Schedule Mask */ | 228 | #define QH_ENDPT2_UFSMASK(x) (((x) & 0xff) << 0) /* Interrupt Schedule Mask */ |
229 | uint32_t qh_curtd; | 229 | uint32_t qh_curtd; |
230 | struct qTD qh_overlay; | 230 | struct qTD qh_overlay; |
231 | /* | 231 | /* |
232 | * Add dummy fill value to make the size of this struct | 232 | * Add dummy fill value to make the size of this struct |
233 | * aligned to 32 bytes | 233 | * aligned to 32 bytes |
234 | */ | 234 | */ |
235 | union { | 235 | union { |
236 | uint32_t fill[4]; | 236 | uint32_t fill[4]; |
237 | void *buffer; | 237 | void *buffer; |
238 | }; | 238 | }; |
239 | }; | 239 | }; |
240 | 240 | ||
241 | struct ehci_ctrl { | 241 | struct ehci_ctrl { |
242 | struct ehci_hccr *hccr; /* R/O registers, not need for volatile */ | 242 | struct ehci_hccr *hccr; /* R/O registers, not need for volatile */ |
243 | struct ehci_hcor *hcor; | 243 | struct ehci_hcor *hcor; |
244 | int rootdev; | 244 | int rootdev; |
245 | uint16_t portreset; | 245 | uint16_t portreset; |
246 | struct QH qh_list __aligned(USB_DMA_MINALIGN); | 246 | struct QH qh_list __aligned(USB_DMA_MINALIGN); |
247 | struct QH periodic_queue __aligned(USB_DMA_MINALIGN); | 247 | struct QH periodic_queue __aligned(USB_DMA_MINALIGN); |
248 | uint32_t *periodic_list; | 248 | uint32_t *periodic_list; |
249 | int periodic_schedules; | ||
249 | int ntds; | 250 | int ntds; |
250 | }; | 251 | }; |
251 | 252 | ||
252 | /* Low level init functions */ | 253 | /* Low level init functions */ |
253 | int ehci_hcd_init(int index, enum usb_init_type init, | 254 | int ehci_hcd_init(int index, enum usb_init_type init, |
254 | struct ehci_hccr **hccr, struct ehci_hcor **hcor); | 255 | struct ehci_hccr **hccr, struct ehci_hcor **hcor); |
255 | int ehci_hcd_stop(int index); | 256 | int ehci_hcd_stop(int index); |
256 | 257 | ||
257 | #endif /* USB_EHCI_H */ | 258 | #endif /* USB_EHCI_H */ |
258 | 259 |
drivers/usb/musb-new/musb_core.c
1 | /* | 1 | /* |
2 | * MUSB OTG driver core code | 2 | * MUSB OTG driver core code |
3 | * | 3 | * |
4 | * Copyright 2005 Mentor Graphics Corporation | 4 | * Copyright 2005 Mentor Graphics Corporation |
5 | * Copyright (C) 2005-2006 by Texas Instruments | 5 | * Copyright (C) 2005-2006 by Texas Instruments |
6 | * Copyright (C) 2006-2007 Nokia Corporation | 6 | * Copyright (C) 2006-2007 Nokia Corporation |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU General Public License | 9 | * modify it under the terms of the GNU General Public License |
10 | * version 2 as published by the Free Software Foundation. | 10 | * version 2 as published by the Free Software Foundation. |
11 | * | 11 | * |
12 | * This program is distributed in the hope that it will be useful, but | 12 | * This program is distributed in the hope that it will be useful, but |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * General Public License for more details. | 15 | * General Public License for more details. |
16 | * | 16 | * |
17 | * You should have received a copy of the GNU General Public License | 17 | * You should have received a copy of the GNU General Public License |
18 | * along with this program; if not, write to the Free Software | 18 | * along with this program; if not, write to the Free Software |
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA |
20 | * 02110-1301 USA | 20 | * 02110-1301 USA |
21 | * | 21 | * |
22 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED | 22 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED |
23 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 23 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
24 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | 24 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN |
25 | * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, | 25 | * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | 27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
28 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | 28 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
29 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 29 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
32 | * | 32 | * |
33 | */ | 33 | */ |
34 | 34 | ||
35 | /* | 35 | /* |
36 | * Inventra (Multipoint) Dual-Role Controller Driver for Linux. | 36 | * Inventra (Multipoint) Dual-Role Controller Driver for Linux. |
37 | * | 37 | * |
38 | * This consists of a Host Controller Driver (HCD) and a peripheral | 38 | * This consists of a Host Controller Driver (HCD) and a peripheral |
39 | * controller driver implementing the "Gadget" API; OTG support is | 39 | * controller driver implementing the "Gadget" API; OTG support is |
40 | * in the works. These are normal Linux-USB controller drivers which | 40 | * in the works. These are normal Linux-USB controller drivers which |
41 | * use IRQs and have no dedicated thread. | 41 | * use IRQs and have no dedicated thread. |
42 | * | 42 | * |
43 | * This version of the driver has only been used with products from | 43 | * This version of the driver has only been used with products from |
44 | * Texas Instruments. Those products integrate the Inventra logic | 44 | * Texas Instruments. Those products integrate the Inventra logic |
45 | * with other DMA, IRQ, and bus modules, as well as other logic that | 45 | * with other DMA, IRQ, and bus modules, as well as other logic that |
46 | * needs to be reflected in this driver. | 46 | * needs to be reflected in this driver. |
47 | * | 47 | * |
48 | * | 48 | * |
49 | * NOTE: the original Mentor code here was pretty much a collection | 49 | * NOTE: the original Mentor code here was pretty much a collection |
50 | * of mechanisms that don't seem to have been fully integrated/working | 50 | * of mechanisms that don't seem to have been fully integrated/working |
51 | * for *any* Linux kernel version. This version aims at Linux 2.6.now, | 51 | * for *any* Linux kernel version. This version aims at Linux 2.6.now, |
52 | * Key open issues include: | 52 | * Key open issues include: |
53 | * | 53 | * |
54 | * - Lack of host-side transaction scheduling, for all transfer types. | 54 | * - Lack of host-side transaction scheduling, for all transfer types. |
55 | * The hardware doesn't do it; instead, software must. | 55 | * The hardware doesn't do it; instead, software must. |
56 | * | 56 | * |
57 | * This is not an issue for OTG devices that don't support external | 57 | * This is not an issue for OTG devices that don't support external |
58 | * hubs, but for more "normal" USB hosts it's a user issue that the | 58 | * hubs, but for more "normal" USB hosts it's a user issue that the |
59 | * "multipoint" support doesn't scale in the expected ways. That | 59 | * "multipoint" support doesn't scale in the expected ways. That |
60 | * includes DaVinci EVM in a common non-OTG mode. | 60 | * includes DaVinci EVM in a common non-OTG mode. |
61 | * | 61 | * |
62 | * * Control and bulk use dedicated endpoints, and there's as | 62 | * * Control and bulk use dedicated endpoints, and there's as |
63 | * yet no mechanism to either (a) reclaim the hardware when | 63 | * yet no mechanism to either (a) reclaim the hardware when |
64 | * peripherals are NAKing, which gets complicated with bulk | 64 | * peripherals are NAKing, which gets complicated with bulk |
65 | * endpoints, or (b) use more than a single bulk endpoint in | 65 | * endpoints, or (b) use more than a single bulk endpoint in |
66 | * each direction. | 66 | * each direction. |
67 | * | 67 | * |
68 | * RESULT: one device may be perceived as blocking another one. | 68 | * RESULT: one device may be perceived as blocking another one. |
69 | * | 69 | * |
70 | * * Interrupt and isochronous will dynamically allocate endpoint | 70 | * * Interrupt and isochronous will dynamically allocate endpoint |
71 | * hardware, but (a) there's no record keeping for bandwidth; | 71 | * hardware, but (a) there's no record keeping for bandwidth; |
72 | * (b) in the common case that few endpoints are available, there | 72 | * (b) in the common case that few endpoints are available, there |
73 | * is no mechanism to reuse endpoints to talk to multiple devices. | 73 | * is no mechanism to reuse endpoints to talk to multiple devices. |
74 | * | 74 | * |
75 | * RESULT: At one extreme, bandwidth can be overcommitted in | 75 | * RESULT: At one extreme, bandwidth can be overcommitted in |
76 | * some hardware configurations, no faults will be reported. | 76 | * some hardware configurations, no faults will be reported. |
77 | * At the other extreme, the bandwidth capabilities which do | 77 | * At the other extreme, the bandwidth capabilities which do |
78 | * exist tend to be severely undercommitted. You can't yet hook | 78 | * exist tend to be severely undercommitted. You can't yet hook |
79 | * up both a keyboard and a mouse to an external USB hub. | 79 | * up both a keyboard and a mouse to an external USB hub. |
80 | */ | 80 | */ |
81 | 81 | ||
82 | /* | 82 | /* |
83 | * This gets many kinds of configuration information: | 83 | * This gets many kinds of configuration information: |
84 | * - Kconfig for everything user-configurable | 84 | * - Kconfig for everything user-configurable |
85 | * - platform_device for addressing, irq, and platform_data | 85 | * - platform_device for addressing, irq, and platform_data |
86 | * - platform_data is mostly for board-specific informarion | 86 | * - platform_data is mostly for board-specific informarion |
87 | * (plus recentrly, SOC or family details) | 87 | * (plus recentrly, SOC or family details) |
88 | * | 88 | * |
89 | * Most of the conditional compilation will (someday) vanish. | 89 | * Most of the conditional compilation will (someday) vanish. |
90 | */ | 90 | */ |
91 | 91 | ||
92 | #ifndef __UBOOT__ | 92 | #ifndef __UBOOT__ |
93 | #include <linux/module.h> | 93 | #include <linux/module.h> |
94 | #include <linux/kernel.h> | 94 | #include <linux/kernel.h> |
95 | #include <linux/sched.h> | 95 | #include <linux/sched.h> |
96 | #include <linux/slab.h> | 96 | #include <linux/slab.h> |
97 | #include <linux/init.h> | 97 | #include <linux/init.h> |
98 | #include <linux/list.h> | 98 | #include <linux/list.h> |
99 | #include <linux/kobject.h> | 99 | #include <linux/kobject.h> |
100 | #include <linux/prefetch.h> | 100 | #include <linux/prefetch.h> |
101 | #include <linux/platform_device.h> | 101 | #include <linux/platform_device.h> |
102 | #include <linux/io.h> | 102 | #include <linux/io.h> |
103 | #else | 103 | #else |
104 | #include <common.h> | 104 | #include <common.h> |
105 | #include <usb.h> | 105 | #include <usb.h> |
106 | #include <asm/errno.h> | 106 | #include <asm/errno.h> |
107 | #include <linux/usb/ch9.h> | 107 | #include <linux/usb/ch9.h> |
108 | #include <linux/usb/gadget.h> | 108 | #include <linux/usb/gadget.h> |
109 | #include <linux/usb/musb.h> | 109 | #include <linux/usb/musb.h> |
110 | #include <asm/io.h> | 110 | #include <asm/io.h> |
111 | #include "linux-compat.h" | 111 | #include "linux-compat.h" |
112 | #include "usb-compat.h" | 112 | #include "usb-compat.h" |
113 | #endif | 113 | #endif |
114 | 114 | ||
115 | #include "musb_core.h" | 115 | #include "musb_core.h" |
116 | 116 | ||
117 | #define TA_WAIT_BCON(m) max_t(int, (m)->a_wait_bcon, OTG_TIME_A_WAIT_BCON) | 117 | #define TA_WAIT_BCON(m) max_t(int, (m)->a_wait_bcon, OTG_TIME_A_WAIT_BCON) |
118 | 118 | ||
119 | 119 | ||
120 | #define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia" | 120 | #define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia" |
121 | #define DRIVER_DESC "Inventra Dual-Role USB Controller Driver" | 121 | #define DRIVER_DESC "Inventra Dual-Role USB Controller Driver" |
122 | 122 | ||
123 | #define MUSB_VERSION "6.0" | 123 | #define MUSB_VERSION "6.0" |
124 | 124 | ||
125 | #define DRIVER_INFO DRIVER_DESC ", v" MUSB_VERSION | 125 | #define DRIVER_INFO DRIVER_DESC ", v" MUSB_VERSION |
126 | 126 | ||
127 | #define MUSB_DRIVER_NAME "musb-hdrc" | 127 | #define MUSB_DRIVER_NAME "musb-hdrc" |
128 | const char musb_driver_name[] = MUSB_DRIVER_NAME; | 128 | const char musb_driver_name[] = MUSB_DRIVER_NAME; |
129 | 129 | ||
130 | MODULE_DESCRIPTION(DRIVER_INFO); | 130 | MODULE_DESCRIPTION(DRIVER_INFO); |
131 | MODULE_AUTHOR(DRIVER_AUTHOR); | 131 | MODULE_AUTHOR(DRIVER_AUTHOR); |
132 | MODULE_LICENSE("GPL"); | 132 | MODULE_LICENSE("GPL"); |
133 | MODULE_ALIAS("platform:" MUSB_DRIVER_NAME); | 133 | MODULE_ALIAS("platform:" MUSB_DRIVER_NAME); |
134 | 134 | ||
135 | 135 | ||
136 | #ifndef __UBOOT__ | 136 | #ifndef __UBOOT__ |
137 | /*-------------------------------------------------------------------------*/ | 137 | /*-------------------------------------------------------------------------*/ |
138 | 138 | ||
139 | static inline struct musb *dev_to_musb(struct device *dev) | 139 | static inline struct musb *dev_to_musb(struct device *dev) |
140 | { | 140 | { |
141 | return dev_get_drvdata(dev); | 141 | return dev_get_drvdata(dev); |
142 | } | 142 | } |
143 | #endif | 143 | #endif |
144 | 144 | ||
145 | /*-------------------------------------------------------------------------*/ | 145 | /*-------------------------------------------------------------------------*/ |
146 | 146 | ||
147 | #ifndef __UBOOT__ | 147 | #ifndef __UBOOT__ |
148 | #ifndef CONFIG_BLACKFIN | 148 | #ifndef CONFIG_BLACKFIN |
149 | static int musb_ulpi_read(struct usb_phy *phy, u32 offset) | 149 | static int musb_ulpi_read(struct usb_phy *phy, u32 offset) |
150 | { | 150 | { |
151 | void __iomem *addr = phy->io_priv; | 151 | void __iomem *addr = phy->io_priv; |
152 | int i = 0; | 152 | int i = 0; |
153 | u8 r; | 153 | u8 r; |
154 | u8 power; | 154 | u8 power; |
155 | int ret; | 155 | int ret; |
156 | 156 | ||
157 | pm_runtime_get_sync(phy->io_dev); | 157 | pm_runtime_get_sync(phy->io_dev); |
158 | 158 | ||
159 | /* Make sure the transceiver is not in low power mode */ | 159 | /* Make sure the transceiver is not in low power mode */ |
160 | power = musb_readb(addr, MUSB_POWER); | 160 | power = musb_readb(addr, MUSB_POWER); |
161 | power &= ~MUSB_POWER_SUSPENDM; | 161 | power &= ~MUSB_POWER_SUSPENDM; |
162 | musb_writeb(addr, MUSB_POWER, power); | 162 | musb_writeb(addr, MUSB_POWER, power); |
163 | 163 | ||
164 | /* REVISIT: musbhdrc_ulpi_an.pdf recommends setting the | 164 | /* REVISIT: musbhdrc_ulpi_an.pdf recommends setting the |
165 | * ULPICarKitControlDisableUTMI after clearing POWER_SUSPENDM. | 165 | * ULPICarKitControlDisableUTMI after clearing POWER_SUSPENDM. |
166 | */ | 166 | */ |
167 | 167 | ||
168 | musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)offset); | 168 | musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)offset); |
169 | musb_writeb(addr, MUSB_ULPI_REG_CONTROL, | 169 | musb_writeb(addr, MUSB_ULPI_REG_CONTROL, |
170 | MUSB_ULPI_REG_REQ | MUSB_ULPI_RDN_WR); | 170 | MUSB_ULPI_REG_REQ | MUSB_ULPI_RDN_WR); |
171 | 171 | ||
172 | while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL) | 172 | while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL) |
173 | & MUSB_ULPI_REG_CMPLT)) { | 173 | & MUSB_ULPI_REG_CMPLT)) { |
174 | i++; | 174 | i++; |
175 | if (i == 10000) { | 175 | if (i == 10000) { |
176 | ret = -ETIMEDOUT; | 176 | ret = -ETIMEDOUT; |
177 | goto out; | 177 | goto out; |
178 | } | 178 | } |
179 | 179 | ||
180 | } | 180 | } |
181 | r = musb_readb(addr, MUSB_ULPI_REG_CONTROL); | 181 | r = musb_readb(addr, MUSB_ULPI_REG_CONTROL); |
182 | r &= ~MUSB_ULPI_REG_CMPLT; | 182 | r &= ~MUSB_ULPI_REG_CMPLT; |
183 | musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r); | 183 | musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r); |
184 | 184 | ||
185 | ret = musb_readb(addr, MUSB_ULPI_REG_DATA); | 185 | ret = musb_readb(addr, MUSB_ULPI_REG_DATA); |
186 | 186 | ||
187 | out: | 187 | out: |
188 | pm_runtime_put(phy->io_dev); | 188 | pm_runtime_put(phy->io_dev); |
189 | 189 | ||
190 | return ret; | 190 | return ret; |
191 | } | 191 | } |
192 | 192 | ||
193 | static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data) | 193 | static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data) |
194 | { | 194 | { |
195 | void __iomem *addr = phy->io_priv; | 195 | void __iomem *addr = phy->io_priv; |
196 | int i = 0; | 196 | int i = 0; |
197 | u8 r = 0; | 197 | u8 r = 0; |
198 | u8 power; | 198 | u8 power; |
199 | int ret = 0; | 199 | int ret = 0; |
200 | 200 | ||
201 | pm_runtime_get_sync(phy->io_dev); | 201 | pm_runtime_get_sync(phy->io_dev); |
202 | 202 | ||
203 | /* Make sure the transceiver is not in low power mode */ | 203 | /* Make sure the transceiver is not in low power mode */ |
204 | power = musb_readb(addr, MUSB_POWER); | 204 | power = musb_readb(addr, MUSB_POWER); |
205 | power &= ~MUSB_POWER_SUSPENDM; | 205 | power &= ~MUSB_POWER_SUSPENDM; |
206 | musb_writeb(addr, MUSB_POWER, power); | 206 | musb_writeb(addr, MUSB_POWER, power); |
207 | 207 | ||
208 | musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)offset); | 208 | musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)offset); |
209 | musb_writeb(addr, MUSB_ULPI_REG_DATA, (u8)data); | 209 | musb_writeb(addr, MUSB_ULPI_REG_DATA, (u8)data); |
210 | musb_writeb(addr, MUSB_ULPI_REG_CONTROL, MUSB_ULPI_REG_REQ); | 210 | musb_writeb(addr, MUSB_ULPI_REG_CONTROL, MUSB_ULPI_REG_REQ); |
211 | 211 | ||
212 | while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL) | 212 | while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL) |
213 | & MUSB_ULPI_REG_CMPLT)) { | 213 | & MUSB_ULPI_REG_CMPLT)) { |
214 | i++; | 214 | i++; |
215 | if (i == 10000) { | 215 | if (i == 10000) { |
216 | ret = -ETIMEDOUT; | 216 | ret = -ETIMEDOUT; |
217 | goto out; | 217 | goto out; |
218 | } | 218 | } |
219 | } | 219 | } |
220 | 220 | ||
221 | r = musb_readb(addr, MUSB_ULPI_REG_CONTROL); | 221 | r = musb_readb(addr, MUSB_ULPI_REG_CONTROL); |
222 | r &= ~MUSB_ULPI_REG_CMPLT; | 222 | r &= ~MUSB_ULPI_REG_CMPLT; |
223 | musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r); | 223 | musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r); |
224 | 224 | ||
225 | out: | 225 | out: |
226 | pm_runtime_put(phy->io_dev); | 226 | pm_runtime_put(phy->io_dev); |
227 | 227 | ||
228 | return ret; | 228 | return ret; |
229 | } | 229 | } |
230 | #else | 230 | #else |
231 | #define musb_ulpi_read NULL | 231 | #define musb_ulpi_read NULL |
232 | #define musb_ulpi_write NULL | 232 | #define musb_ulpi_write NULL |
233 | #endif | 233 | #endif |
234 | 234 | ||
235 | static struct usb_phy_io_ops musb_ulpi_access = { | 235 | static struct usb_phy_io_ops musb_ulpi_access = { |
236 | .read = musb_ulpi_read, | 236 | .read = musb_ulpi_read, |
237 | .write = musb_ulpi_write, | 237 | .write = musb_ulpi_write, |
238 | }; | 238 | }; |
239 | #endif | 239 | #endif |
240 | 240 | ||
241 | /*-------------------------------------------------------------------------*/ | 241 | /*-------------------------------------------------------------------------*/ |
242 | 242 | ||
243 | #if !defined(CONFIG_USB_MUSB_TUSB6010) && !defined(CONFIG_USB_MUSB_BLACKFIN) | 243 | #if !defined(CONFIG_USB_MUSB_TUSB6010) && !defined(CONFIG_USB_MUSB_BLACKFIN) |
244 | 244 | ||
245 | /* | 245 | /* |
246 | * Load an endpoint's FIFO | 246 | * Load an endpoint's FIFO |
247 | */ | 247 | */ |
248 | void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) | 248 | void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) |
249 | { | 249 | { |
250 | struct musb *musb = hw_ep->musb; | 250 | struct musb *musb = hw_ep->musb; |
251 | void __iomem *fifo = hw_ep->fifo; | 251 | void __iomem *fifo = hw_ep->fifo; |
252 | 252 | ||
253 | prefetch((u8 *)src); | 253 | prefetch((u8 *)src); |
254 | 254 | ||
255 | dev_dbg(musb->controller, "%cX ep%d fifo %p count %d buf %p\n", | 255 | dev_dbg(musb->controller, "%cX ep%d fifo %p count %d buf %p\n", |
256 | 'T', hw_ep->epnum, fifo, len, src); | 256 | 'T', hw_ep->epnum, fifo, len, src); |
257 | 257 | ||
258 | /* we can't assume unaligned reads work */ | 258 | /* we can't assume unaligned reads work */ |
259 | if (likely((0x01 & (unsigned long) src) == 0)) { | 259 | if (likely((0x01 & (unsigned long) src) == 0)) { |
260 | u16 index = 0; | 260 | u16 index = 0; |
261 | 261 | ||
262 | /* best case is 32bit-aligned source address */ | 262 | /* best case is 32bit-aligned source address */ |
263 | if ((0x02 & (unsigned long) src) == 0) { | 263 | if ((0x02 & (unsigned long) src) == 0) { |
264 | if (len >= 4) { | 264 | if (len >= 4) { |
265 | writesl(fifo, src + index, len >> 2); | 265 | writesl(fifo, src + index, len >> 2); |
266 | index += len & ~0x03; | 266 | index += len & ~0x03; |
267 | } | 267 | } |
268 | if (len & 0x02) { | 268 | if (len & 0x02) { |
269 | musb_writew(fifo, 0, *(u16 *)&src[index]); | 269 | musb_writew(fifo, 0, *(u16 *)&src[index]); |
270 | index += 2; | 270 | index += 2; |
271 | } | 271 | } |
272 | } else { | 272 | } else { |
273 | if (len >= 2) { | 273 | if (len >= 2) { |
274 | writesw(fifo, src + index, len >> 1); | 274 | writesw(fifo, src + index, len >> 1); |
275 | index += len & ~0x01; | 275 | index += len & ~0x01; |
276 | } | 276 | } |
277 | } | 277 | } |
278 | if (len & 0x01) | 278 | if (len & 0x01) |
279 | musb_writeb(fifo, 0, src[index]); | 279 | musb_writeb(fifo, 0, src[index]); |
280 | } else { | 280 | } else { |
281 | /* byte aligned */ | 281 | /* byte aligned */ |
282 | writesb(fifo, src, len); | 282 | writesb(fifo, src, len); |
283 | } | 283 | } |
284 | } | 284 | } |
285 | 285 | ||
286 | #if !defined(CONFIG_USB_MUSB_AM35X) | 286 | #if !defined(CONFIG_USB_MUSB_AM35X) |
287 | /* | 287 | /* |
288 | * Unload an endpoint's FIFO | 288 | * Unload an endpoint's FIFO |
289 | */ | 289 | */ |
290 | void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) | 290 | void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) |
291 | { | 291 | { |
292 | struct musb *musb = hw_ep->musb; | 292 | struct musb *musb = hw_ep->musb; |
293 | void __iomem *fifo = hw_ep->fifo; | 293 | void __iomem *fifo = hw_ep->fifo; |
294 | 294 | ||
295 | dev_dbg(musb->controller, "%cX ep%d fifo %p count %d buf %p\n", | 295 | dev_dbg(musb->controller, "%cX ep%d fifo %p count %d buf %p\n", |
296 | 'R', hw_ep->epnum, fifo, len, dst); | 296 | 'R', hw_ep->epnum, fifo, len, dst); |
297 | 297 | ||
298 | /* we can't assume unaligned writes work */ | 298 | /* we can't assume unaligned writes work */ |
299 | if (likely((0x01 & (unsigned long) dst) == 0)) { | 299 | if (likely((0x01 & (unsigned long) dst) == 0)) { |
300 | u16 index = 0; | 300 | u16 index = 0; |
301 | 301 | ||
302 | /* best case is 32bit-aligned destination address */ | 302 | /* best case is 32bit-aligned destination address */ |
303 | if ((0x02 & (unsigned long) dst) == 0) { | 303 | if ((0x02 & (unsigned long) dst) == 0) { |
304 | if (len >= 4) { | 304 | if (len >= 4) { |
305 | readsl(fifo, dst, len >> 2); | 305 | readsl(fifo, dst, len >> 2); |
306 | index = len & ~0x03; | 306 | index = len & ~0x03; |
307 | } | 307 | } |
308 | if (len & 0x02) { | 308 | if (len & 0x02) { |
309 | *(u16 *)&dst[index] = musb_readw(fifo, 0); | 309 | *(u16 *)&dst[index] = musb_readw(fifo, 0); |
310 | index += 2; | 310 | index += 2; |
311 | } | 311 | } |
312 | } else { | 312 | } else { |
313 | if (len >= 2) { | 313 | if (len >= 2) { |
314 | readsw(fifo, dst, len >> 1); | 314 | readsw(fifo, dst, len >> 1); |
315 | index = len & ~0x01; | 315 | index = len & ~0x01; |
316 | } | 316 | } |
317 | } | 317 | } |
318 | if (len & 0x01) | 318 | if (len & 0x01) |
319 | dst[index] = musb_readb(fifo, 0); | 319 | dst[index] = musb_readb(fifo, 0); |
320 | } else { | 320 | } else { |
321 | /* byte aligned */ | 321 | /* byte aligned */ |
322 | readsb(fifo, dst, len); | 322 | readsb(fifo, dst, len); |
323 | } | 323 | } |
324 | } | 324 | } |
325 | #endif | 325 | #endif |
326 | 326 | ||
327 | #endif /* normal PIO */ | 327 | #endif /* normal PIO */ |
328 | 328 | ||
329 | 329 | ||
330 | /*-------------------------------------------------------------------------*/ | 330 | /*-------------------------------------------------------------------------*/ |
331 | 331 | ||
332 | /* for high speed test mode; see USB 2.0 spec 7.1.20 */ | 332 | /* for high speed test mode; see USB 2.0 spec 7.1.20 */ |
333 | static const u8 musb_test_packet[53] = { | 333 | static const u8 musb_test_packet[53] = { |
334 | /* implicit SYNC then DATA0 to start */ | 334 | /* implicit SYNC then DATA0 to start */ |
335 | 335 | ||
336 | /* JKJKJKJK x9 */ | 336 | /* JKJKJKJK x9 */ |
337 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 337 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
338 | /* JJKKJJKK x8 */ | 338 | /* JJKKJJKK x8 */ |
339 | 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, | 339 | 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, |
340 | /* JJJJKKKK x8 */ | 340 | /* JJJJKKKK x8 */ |
341 | 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, | 341 | 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, |
342 | /* JJJJJJJKKKKKKK x8 */ | 342 | /* JJJJJJJKKKKKKK x8 */ |
343 | 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | 343 | 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
344 | /* JJJJJJJK x8 */ | 344 | /* JJJJJJJK x8 */ |
345 | 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, | 345 | 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, |
346 | /* JKKKKKKK x10, JK */ | 346 | /* JKKKKKKK x10, JK */ |
347 | 0xfc, 0x7e, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0x7e | 347 | 0xfc, 0x7e, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0x7e |
348 | 348 | ||
349 | /* implicit CRC16 then EOP to end */ | 349 | /* implicit CRC16 then EOP to end */ |
350 | }; | 350 | }; |
351 | 351 | ||
352 | void musb_load_testpacket(struct musb *musb) | 352 | void musb_load_testpacket(struct musb *musb) |
353 | { | 353 | { |
354 | void __iomem *regs = musb->endpoints[0].regs; | 354 | void __iomem *regs = musb->endpoints[0].regs; |
355 | 355 | ||
356 | musb_ep_select(musb->mregs, 0); | 356 | musb_ep_select(musb->mregs, 0); |
357 | musb_write_fifo(musb->control_ep, | 357 | musb_write_fifo(musb->control_ep, |
358 | sizeof(musb_test_packet), musb_test_packet); | 358 | sizeof(musb_test_packet), musb_test_packet); |
359 | musb_writew(regs, MUSB_CSR0, MUSB_CSR0_TXPKTRDY); | 359 | musb_writew(regs, MUSB_CSR0, MUSB_CSR0_TXPKTRDY); |
360 | } | 360 | } |
361 | 361 | ||
362 | #ifndef __UBOOT__ | 362 | #ifndef __UBOOT__ |
363 | /*-------------------------------------------------------------------------*/ | 363 | /*-------------------------------------------------------------------------*/ |
364 | 364 | ||
365 | /* | 365 | /* |
366 | * Handles OTG hnp timeouts, such as b_ase0_brst | 366 | * Handles OTG hnp timeouts, such as b_ase0_brst |
367 | */ | 367 | */ |
368 | void musb_otg_timer_func(unsigned long data) | 368 | void musb_otg_timer_func(unsigned long data) |
369 | { | 369 | { |
370 | struct musb *musb = (struct musb *)data; | 370 | struct musb *musb = (struct musb *)data; |
371 | unsigned long flags; | 371 | unsigned long flags; |
372 | 372 | ||
373 | spin_lock_irqsave(&musb->lock, flags); | 373 | spin_lock_irqsave(&musb->lock, flags); |
374 | switch (musb->xceiv->state) { | 374 | switch (musb->xceiv->state) { |
375 | case OTG_STATE_B_WAIT_ACON: | 375 | case OTG_STATE_B_WAIT_ACON: |
376 | dev_dbg(musb->controller, "HNP: b_wait_acon timeout; back to b_peripheral\n"); | 376 | dev_dbg(musb->controller, "HNP: b_wait_acon timeout; back to b_peripheral\n"); |
377 | musb_g_disconnect(musb); | 377 | musb_g_disconnect(musb); |
378 | musb->xceiv->state = OTG_STATE_B_PERIPHERAL; | 378 | musb->xceiv->state = OTG_STATE_B_PERIPHERAL; |
379 | musb->is_active = 0; | 379 | musb->is_active = 0; |
380 | break; | 380 | break; |
381 | case OTG_STATE_A_SUSPEND: | 381 | case OTG_STATE_A_SUSPEND: |
382 | case OTG_STATE_A_WAIT_BCON: | 382 | case OTG_STATE_A_WAIT_BCON: |
383 | dev_dbg(musb->controller, "HNP: %s timeout\n", | 383 | dev_dbg(musb->controller, "HNP: %s timeout\n", |
384 | otg_state_string(musb->xceiv->state)); | 384 | otg_state_string(musb->xceiv->state)); |
385 | musb_platform_set_vbus(musb, 0); | 385 | musb_platform_set_vbus(musb, 0); |
386 | musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; | 386 | musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; |
387 | break; | 387 | break; |
388 | default: | 388 | default: |
389 | dev_dbg(musb->controller, "HNP: Unhandled mode %s\n", | 389 | dev_dbg(musb->controller, "HNP: Unhandled mode %s\n", |
390 | otg_state_string(musb->xceiv->state)); | 390 | otg_state_string(musb->xceiv->state)); |
391 | } | 391 | } |
392 | musb->ignore_disconnect = 0; | 392 | musb->ignore_disconnect = 0; |
393 | spin_unlock_irqrestore(&musb->lock, flags); | 393 | spin_unlock_irqrestore(&musb->lock, flags); |
394 | } | 394 | } |
395 | 395 | ||
396 | /* | 396 | /* |
397 | * Stops the HNP transition. Caller must take care of locking. | 397 | * Stops the HNP transition. Caller must take care of locking. |
398 | */ | 398 | */ |
399 | void musb_hnp_stop(struct musb *musb) | 399 | void musb_hnp_stop(struct musb *musb) |
400 | { | 400 | { |
401 | struct usb_hcd *hcd = musb_to_hcd(musb); | 401 | struct usb_hcd *hcd = musb_to_hcd(musb); |
402 | void __iomem *mbase = musb->mregs; | 402 | void __iomem *mbase = musb->mregs; |
403 | u8 reg; | 403 | u8 reg; |
404 | 404 | ||
405 | dev_dbg(musb->controller, "HNP: stop from %s\n", otg_state_string(musb->xceiv->state)); | 405 | dev_dbg(musb->controller, "HNP: stop from %s\n", otg_state_string(musb->xceiv->state)); |
406 | 406 | ||
407 | switch (musb->xceiv->state) { | 407 | switch (musb->xceiv->state) { |
408 | case OTG_STATE_A_PERIPHERAL: | 408 | case OTG_STATE_A_PERIPHERAL: |
409 | musb_g_disconnect(musb); | 409 | musb_g_disconnect(musb); |
410 | dev_dbg(musb->controller, "HNP: back to %s\n", | 410 | dev_dbg(musb->controller, "HNP: back to %s\n", |
411 | otg_state_string(musb->xceiv->state)); | 411 | otg_state_string(musb->xceiv->state)); |
412 | break; | 412 | break; |
413 | case OTG_STATE_B_HOST: | 413 | case OTG_STATE_B_HOST: |
414 | dev_dbg(musb->controller, "HNP: Disabling HR\n"); | 414 | dev_dbg(musb->controller, "HNP: Disabling HR\n"); |
415 | hcd->self.is_b_host = 0; | 415 | hcd->self.is_b_host = 0; |
416 | musb->xceiv->state = OTG_STATE_B_PERIPHERAL; | 416 | musb->xceiv->state = OTG_STATE_B_PERIPHERAL; |
417 | MUSB_DEV_MODE(musb); | 417 | MUSB_DEV_MODE(musb); |
418 | reg = musb_readb(mbase, MUSB_POWER); | 418 | reg = musb_readb(mbase, MUSB_POWER); |
419 | reg |= MUSB_POWER_SUSPENDM; | 419 | reg |= MUSB_POWER_SUSPENDM; |
420 | musb_writeb(mbase, MUSB_POWER, reg); | 420 | musb_writeb(mbase, MUSB_POWER, reg); |
421 | /* REVISIT: Start SESSION_REQUEST here? */ | 421 | /* REVISIT: Start SESSION_REQUEST here? */ |
422 | break; | 422 | break; |
423 | default: | 423 | default: |
424 | dev_dbg(musb->controller, "HNP: Stopping in unknown state %s\n", | 424 | dev_dbg(musb->controller, "HNP: Stopping in unknown state %s\n", |
425 | otg_state_string(musb->xceiv->state)); | 425 | otg_state_string(musb->xceiv->state)); |
426 | } | 426 | } |
427 | 427 | ||
428 | /* | 428 | /* |
429 | * When returning to A state after HNP, avoid hub_port_rebounce(), | 429 | * When returning to A state after HNP, avoid hub_port_rebounce(), |
430 | * which cause occasional OPT A "Did not receive reset after connect" | 430 | * which cause occasional OPT A "Did not receive reset after connect" |
431 | * errors. | 431 | * errors. |
432 | */ | 432 | */ |
433 | musb->port1_status &= ~(USB_PORT_STAT_C_CONNECTION << 16); | 433 | musb->port1_status &= ~(USB_PORT_STAT_C_CONNECTION << 16); |
434 | } | 434 | } |
435 | #endif | 435 | #endif |
436 | 436 | ||
437 | /* | 437 | /* |
438 | * Interrupt Service Routine to record USB "global" interrupts. | 438 | * Interrupt Service Routine to record USB "global" interrupts. |
439 | * Since these do not happen often and signify things of | 439 | * Since these do not happen often and signify things of |
440 | * paramount importance, it seems OK to check them individually; | 440 | * paramount importance, it seems OK to check them individually; |
441 | * the order of the tests is specified in the manual | 441 | * the order of the tests is specified in the manual |
442 | * | 442 | * |
443 | * @param musb instance pointer | 443 | * @param musb instance pointer |
444 | * @param int_usb register contents | 444 | * @param int_usb register contents |
445 | * @param devctl | 445 | * @param devctl |
446 | * @param power | 446 | * @param power |
447 | */ | 447 | */ |
448 | 448 | ||
449 | static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | 449 | static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, |
450 | u8 devctl, u8 power) | 450 | u8 devctl, u8 power) |
451 | { | 451 | { |
452 | #ifndef __UBOOT__ | 452 | #ifndef __UBOOT__ |
453 | struct usb_otg *otg = musb->xceiv->otg; | 453 | struct usb_otg *otg = musb->xceiv->otg; |
454 | #endif | 454 | #endif |
455 | irqreturn_t handled = IRQ_NONE; | 455 | irqreturn_t handled = IRQ_NONE; |
456 | 456 | ||
457 | dev_dbg(musb->controller, "<== Power=%02x, DevCtl=%02x, int_usb=0x%x\n", power, devctl, | 457 | dev_dbg(musb->controller, "<== Power=%02x, DevCtl=%02x, int_usb=0x%x\n", power, devctl, |
458 | int_usb); | 458 | int_usb); |
459 | 459 | ||
460 | #ifndef __UBOOT__ | 460 | #ifndef __UBOOT__ |
461 | /* in host mode, the peripheral may issue remote wakeup. | 461 | /* in host mode, the peripheral may issue remote wakeup. |
462 | * in peripheral mode, the host may resume the link. | 462 | * in peripheral mode, the host may resume the link. |
463 | * spurious RESUME irqs happen too, paired with SUSPEND. | 463 | * spurious RESUME irqs happen too, paired with SUSPEND. |
464 | */ | 464 | */ |
465 | if (int_usb & MUSB_INTR_RESUME) { | 465 | if (int_usb & MUSB_INTR_RESUME) { |
466 | handled = IRQ_HANDLED; | 466 | handled = IRQ_HANDLED; |
467 | dev_dbg(musb->controller, "RESUME (%s)\n", otg_state_string(musb->xceiv->state)); | 467 | dev_dbg(musb->controller, "RESUME (%s)\n", otg_state_string(musb->xceiv->state)); |
468 | 468 | ||
469 | if (devctl & MUSB_DEVCTL_HM) { | 469 | if (devctl & MUSB_DEVCTL_HM) { |
470 | void __iomem *mbase = musb->mregs; | 470 | void __iomem *mbase = musb->mregs; |
471 | 471 | ||
472 | switch (musb->xceiv->state) { | 472 | switch (musb->xceiv->state) { |
473 | case OTG_STATE_A_SUSPEND: | 473 | case OTG_STATE_A_SUSPEND: |
474 | /* remote wakeup? later, GetPortStatus | 474 | /* remote wakeup? later, GetPortStatus |
475 | * will stop RESUME signaling | 475 | * will stop RESUME signaling |
476 | */ | 476 | */ |
477 | 477 | ||
478 | if (power & MUSB_POWER_SUSPENDM) { | 478 | if (power & MUSB_POWER_SUSPENDM) { |
479 | /* spurious */ | 479 | /* spurious */ |
480 | musb->int_usb &= ~MUSB_INTR_SUSPEND; | 480 | musb->int_usb &= ~MUSB_INTR_SUSPEND; |
481 | dev_dbg(musb->controller, "Spurious SUSPENDM\n"); | 481 | dev_dbg(musb->controller, "Spurious SUSPENDM\n"); |
482 | break; | 482 | break; |
483 | } | 483 | } |
484 | 484 | ||
485 | power &= ~MUSB_POWER_SUSPENDM; | 485 | power &= ~MUSB_POWER_SUSPENDM; |
486 | musb_writeb(mbase, MUSB_POWER, | 486 | musb_writeb(mbase, MUSB_POWER, |
487 | power | MUSB_POWER_RESUME); | 487 | power | MUSB_POWER_RESUME); |
488 | 488 | ||
489 | musb->port1_status |= | 489 | musb->port1_status |= |
490 | (USB_PORT_STAT_C_SUSPEND << 16) | 490 | (USB_PORT_STAT_C_SUSPEND << 16) |
491 | | MUSB_PORT_STAT_RESUME; | 491 | | MUSB_PORT_STAT_RESUME; |
492 | musb->rh_timer = jiffies | 492 | musb->rh_timer = jiffies |
493 | + msecs_to_jiffies(20); | 493 | + msecs_to_jiffies(20); |
494 | 494 | ||
495 | musb->xceiv->state = OTG_STATE_A_HOST; | 495 | musb->xceiv->state = OTG_STATE_A_HOST; |
496 | musb->is_active = 1; | 496 | musb->is_active = 1; |
497 | usb_hcd_resume_root_hub(musb_to_hcd(musb)); | 497 | usb_hcd_resume_root_hub(musb_to_hcd(musb)); |
498 | break; | 498 | break; |
499 | case OTG_STATE_B_WAIT_ACON: | 499 | case OTG_STATE_B_WAIT_ACON: |
500 | musb->xceiv->state = OTG_STATE_B_PERIPHERAL; | 500 | musb->xceiv->state = OTG_STATE_B_PERIPHERAL; |
501 | musb->is_active = 1; | 501 | musb->is_active = 1; |
502 | MUSB_DEV_MODE(musb); | 502 | MUSB_DEV_MODE(musb); |
503 | break; | 503 | break; |
504 | default: | 504 | default: |
505 | WARNING("bogus %s RESUME (%s)\n", | 505 | WARNING("bogus %s RESUME (%s)\n", |
506 | "host", | 506 | "host", |
507 | otg_state_string(musb->xceiv->state)); | 507 | otg_state_string(musb->xceiv->state)); |
508 | } | 508 | } |
509 | } else { | 509 | } else { |
510 | switch (musb->xceiv->state) { | 510 | switch (musb->xceiv->state) { |
511 | case OTG_STATE_A_SUSPEND: | 511 | case OTG_STATE_A_SUSPEND: |
512 | /* possibly DISCONNECT is upcoming */ | 512 | /* possibly DISCONNECT is upcoming */ |
513 | musb->xceiv->state = OTG_STATE_A_HOST; | 513 | musb->xceiv->state = OTG_STATE_A_HOST; |
514 | usb_hcd_resume_root_hub(musb_to_hcd(musb)); | 514 | usb_hcd_resume_root_hub(musb_to_hcd(musb)); |
515 | break; | 515 | break; |
516 | case OTG_STATE_B_WAIT_ACON: | 516 | case OTG_STATE_B_WAIT_ACON: |
517 | case OTG_STATE_B_PERIPHERAL: | 517 | case OTG_STATE_B_PERIPHERAL: |
518 | /* disconnect while suspended? we may | 518 | /* disconnect while suspended? we may |
519 | * not get a disconnect irq... | 519 | * not get a disconnect irq... |
520 | */ | 520 | */ |
521 | if ((devctl & MUSB_DEVCTL_VBUS) | 521 | if ((devctl & MUSB_DEVCTL_VBUS) |
522 | != (3 << MUSB_DEVCTL_VBUS_SHIFT) | 522 | != (3 << MUSB_DEVCTL_VBUS_SHIFT) |
523 | ) { | 523 | ) { |
524 | musb->int_usb |= MUSB_INTR_DISCONNECT; | 524 | musb->int_usb |= MUSB_INTR_DISCONNECT; |
525 | musb->int_usb &= ~MUSB_INTR_SUSPEND; | 525 | musb->int_usb &= ~MUSB_INTR_SUSPEND; |
526 | break; | 526 | break; |
527 | } | 527 | } |
528 | musb_g_resume(musb); | 528 | musb_g_resume(musb); |
529 | break; | 529 | break; |
530 | case OTG_STATE_B_IDLE: | 530 | case OTG_STATE_B_IDLE: |
531 | musb->int_usb &= ~MUSB_INTR_SUSPEND; | 531 | musb->int_usb &= ~MUSB_INTR_SUSPEND; |
532 | break; | 532 | break; |
533 | default: | 533 | default: |
534 | WARNING("bogus %s RESUME (%s)\n", | 534 | WARNING("bogus %s RESUME (%s)\n", |
535 | "peripheral", | 535 | "peripheral", |
536 | otg_state_string(musb->xceiv->state)); | 536 | otg_state_string(musb->xceiv->state)); |
537 | } | 537 | } |
538 | } | 538 | } |
539 | } | 539 | } |
540 | 540 | ||
541 | /* see manual for the order of the tests */ | 541 | /* see manual for the order of the tests */ |
542 | if (int_usb & MUSB_INTR_SESSREQ) { | 542 | if (int_usb & MUSB_INTR_SESSREQ) { |
543 | void __iomem *mbase = musb->mregs; | 543 | void __iomem *mbase = musb->mregs; |
544 | 544 | ||
545 | if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS | 545 | if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS |
546 | && (devctl & MUSB_DEVCTL_BDEVICE)) { | 546 | && (devctl & MUSB_DEVCTL_BDEVICE)) { |
547 | dev_dbg(musb->controller, "SessReq while on B state\n"); | 547 | dev_dbg(musb->controller, "SessReq while on B state\n"); |
548 | return IRQ_HANDLED; | 548 | return IRQ_HANDLED; |
549 | } | 549 | } |
550 | 550 | ||
551 | dev_dbg(musb->controller, "SESSION_REQUEST (%s)\n", | 551 | dev_dbg(musb->controller, "SESSION_REQUEST (%s)\n", |
552 | otg_state_string(musb->xceiv->state)); | 552 | otg_state_string(musb->xceiv->state)); |
553 | 553 | ||
554 | /* IRQ arrives from ID pin sense or (later, if VBUS power | 554 | /* IRQ arrives from ID pin sense or (later, if VBUS power |
555 | * is removed) SRP. responses are time critical: | 555 | * is removed) SRP. responses are time critical: |
556 | * - turn on VBUS (with silicon-specific mechanism) | 556 | * - turn on VBUS (with silicon-specific mechanism) |
557 | * - go through A_WAIT_VRISE | 557 | * - go through A_WAIT_VRISE |
558 | * - ... to A_WAIT_BCON. | 558 | * - ... to A_WAIT_BCON. |
559 | * a_wait_vrise_tmout triggers VBUS_ERROR transitions | 559 | * a_wait_vrise_tmout triggers VBUS_ERROR transitions |
560 | */ | 560 | */ |
561 | musb_writeb(mbase, MUSB_DEVCTL, MUSB_DEVCTL_SESSION); | 561 | musb_writeb(mbase, MUSB_DEVCTL, MUSB_DEVCTL_SESSION); |
562 | musb->ep0_stage = MUSB_EP0_START; | 562 | musb->ep0_stage = MUSB_EP0_START; |
563 | musb->xceiv->state = OTG_STATE_A_IDLE; | 563 | musb->xceiv->state = OTG_STATE_A_IDLE; |
564 | MUSB_HST_MODE(musb); | 564 | MUSB_HST_MODE(musb); |
565 | musb_platform_set_vbus(musb, 1); | 565 | musb_platform_set_vbus(musb, 1); |
566 | 566 | ||
567 | handled = IRQ_HANDLED; | 567 | handled = IRQ_HANDLED; |
568 | } | 568 | } |
569 | 569 | ||
570 | if (int_usb & MUSB_INTR_VBUSERROR) { | 570 | if (int_usb & MUSB_INTR_VBUSERROR) { |
571 | int ignore = 0; | 571 | int ignore = 0; |
572 | 572 | ||
573 | /* During connection as an A-Device, we may see a short | 573 | /* During connection as an A-Device, we may see a short |
574 | * current spikes causing voltage drop, because of cable | 574 | * current spikes causing voltage drop, because of cable |
575 | * and peripheral capacitance combined with vbus draw. | 575 | * and peripheral capacitance combined with vbus draw. |
576 | * (So: less common with truly self-powered devices, where | 576 | * (So: less common with truly self-powered devices, where |
577 | * vbus doesn't act like a power supply.) | 577 | * vbus doesn't act like a power supply.) |
578 | * | 578 | * |
579 | * Such spikes are short; usually less than ~500 usec, max | 579 | * Such spikes are short; usually less than ~500 usec, max |
580 | * of ~2 msec. That is, they're not sustained overcurrent | 580 | * of ~2 msec. That is, they're not sustained overcurrent |
581 | * errors, though they're reported using VBUSERROR irqs. | 581 | * errors, though they're reported using VBUSERROR irqs. |
582 | * | 582 | * |
583 | * Workarounds: (a) hardware: use self powered devices. | 583 | * Workarounds: (a) hardware: use self powered devices. |
584 | * (b) software: ignore non-repeated VBUS errors. | 584 | * (b) software: ignore non-repeated VBUS errors. |
585 | * | 585 | * |
586 | * REVISIT: do delays from lots of DEBUG_KERNEL checks | 586 | * REVISIT: do delays from lots of DEBUG_KERNEL checks |
587 | * make trouble here, keeping VBUS < 4.4V ? | 587 | * make trouble here, keeping VBUS < 4.4V ? |
588 | */ | 588 | */ |
589 | switch (musb->xceiv->state) { | 589 | switch (musb->xceiv->state) { |
590 | case OTG_STATE_A_HOST: | 590 | case OTG_STATE_A_HOST: |
591 | /* recovery is dicey once we've gotten past the | 591 | /* recovery is dicey once we've gotten past the |
592 | * initial stages of enumeration, but if VBUS | 592 | * initial stages of enumeration, but if VBUS |
593 | * stayed ok at the other end of the link, and | 593 | * stayed ok at the other end of the link, and |
594 | * another reset is due (at least for high speed, | 594 | * another reset is due (at least for high speed, |
595 | * to redo the chirp etc), it might work OK... | 595 | * to redo the chirp etc), it might work OK... |
596 | */ | 596 | */ |
597 | case OTG_STATE_A_WAIT_BCON: | 597 | case OTG_STATE_A_WAIT_BCON: |
598 | case OTG_STATE_A_WAIT_VRISE: | 598 | case OTG_STATE_A_WAIT_VRISE: |
599 | if (musb->vbuserr_retry) { | 599 | if (musb->vbuserr_retry) { |
600 | void __iomem *mbase = musb->mregs; | 600 | void __iomem *mbase = musb->mregs; |
601 | 601 | ||
602 | musb->vbuserr_retry--; | 602 | musb->vbuserr_retry--; |
603 | ignore = 1; | 603 | ignore = 1; |
604 | devctl |= MUSB_DEVCTL_SESSION; | 604 | devctl |= MUSB_DEVCTL_SESSION; |
605 | musb_writeb(mbase, MUSB_DEVCTL, devctl); | 605 | musb_writeb(mbase, MUSB_DEVCTL, devctl); |
606 | } else { | 606 | } else { |
607 | musb->port1_status |= | 607 | musb->port1_status |= |
608 | USB_PORT_STAT_OVERCURRENT | 608 | USB_PORT_STAT_OVERCURRENT |
609 | | (USB_PORT_STAT_C_OVERCURRENT << 16); | 609 | | (USB_PORT_STAT_C_OVERCURRENT << 16); |
610 | } | 610 | } |
611 | break; | 611 | break; |
612 | default: | 612 | default: |
613 | break; | 613 | break; |
614 | } | 614 | } |
615 | 615 | ||
616 | dev_dbg(musb->controller, "VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n", | 616 | dev_dbg(musb->controller, "VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n", |
617 | otg_state_string(musb->xceiv->state), | 617 | otg_state_string(musb->xceiv->state), |
618 | devctl, | 618 | devctl, |
619 | ({ char *s; | 619 | ({ char *s; |
620 | switch (devctl & MUSB_DEVCTL_VBUS) { | 620 | switch (devctl & MUSB_DEVCTL_VBUS) { |
621 | case 0 << MUSB_DEVCTL_VBUS_SHIFT: | 621 | case 0 << MUSB_DEVCTL_VBUS_SHIFT: |
622 | s = "<SessEnd"; break; | 622 | s = "<SessEnd"; break; |
623 | case 1 << MUSB_DEVCTL_VBUS_SHIFT: | 623 | case 1 << MUSB_DEVCTL_VBUS_SHIFT: |
624 | s = "<AValid"; break; | 624 | s = "<AValid"; break; |
625 | case 2 << MUSB_DEVCTL_VBUS_SHIFT: | 625 | case 2 << MUSB_DEVCTL_VBUS_SHIFT: |
626 | s = "<VBusValid"; break; | 626 | s = "<VBusValid"; break; |
627 | /* case 3 << MUSB_DEVCTL_VBUS_SHIFT: */ | 627 | /* case 3 << MUSB_DEVCTL_VBUS_SHIFT: */ |
628 | default: | 628 | default: |
629 | s = "VALID"; break; | 629 | s = "VALID"; break; |
630 | }; s; }), | 630 | }; s; }), |
631 | VBUSERR_RETRY_COUNT - musb->vbuserr_retry, | 631 | VBUSERR_RETRY_COUNT - musb->vbuserr_retry, |
632 | musb->port1_status); | 632 | musb->port1_status); |
633 | 633 | ||
634 | /* go through A_WAIT_VFALL then start a new session */ | 634 | /* go through A_WAIT_VFALL then start a new session */ |
635 | if (!ignore) | 635 | if (!ignore) |
636 | musb_platform_set_vbus(musb, 0); | 636 | musb_platform_set_vbus(musb, 0); |
637 | handled = IRQ_HANDLED; | 637 | handled = IRQ_HANDLED; |
638 | } | 638 | } |
639 | 639 | ||
640 | if (int_usb & MUSB_INTR_SUSPEND) { | 640 | if (int_usb & MUSB_INTR_SUSPEND) { |
641 | dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x power %02x\n", | 641 | dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x power %02x\n", |
642 | otg_state_string(musb->xceiv->state), devctl, power); | 642 | otg_state_string(musb->xceiv->state), devctl, power); |
643 | handled = IRQ_HANDLED; | 643 | handled = IRQ_HANDLED; |
644 | 644 | ||
645 | switch (musb->xceiv->state) { | 645 | switch (musb->xceiv->state) { |
646 | case OTG_STATE_A_PERIPHERAL: | 646 | case OTG_STATE_A_PERIPHERAL: |
647 | /* We also come here if the cable is removed, since | 647 | /* We also come here if the cable is removed, since |
648 | * this silicon doesn't report ID-no-longer-grounded. | 648 | * this silicon doesn't report ID-no-longer-grounded. |
649 | * | 649 | * |
650 | * We depend on T(a_wait_bcon) to shut us down, and | 650 | * We depend on T(a_wait_bcon) to shut us down, and |
651 | * hope users don't do anything dicey during this | 651 | * hope users don't do anything dicey during this |
652 | * undesired detour through A_WAIT_BCON. | 652 | * undesired detour through A_WAIT_BCON. |
653 | */ | 653 | */ |
654 | musb_hnp_stop(musb); | 654 | musb_hnp_stop(musb); |
655 | usb_hcd_resume_root_hub(musb_to_hcd(musb)); | 655 | usb_hcd_resume_root_hub(musb_to_hcd(musb)); |
656 | musb_root_disconnect(musb); | 656 | musb_root_disconnect(musb); |
657 | musb_platform_try_idle(musb, jiffies | 657 | musb_platform_try_idle(musb, jiffies |
658 | + msecs_to_jiffies(musb->a_wait_bcon | 658 | + msecs_to_jiffies(musb->a_wait_bcon |
659 | ? : OTG_TIME_A_WAIT_BCON)); | 659 | ? : OTG_TIME_A_WAIT_BCON)); |
660 | 660 | ||
661 | break; | 661 | break; |
662 | case OTG_STATE_B_IDLE: | 662 | case OTG_STATE_B_IDLE: |
663 | if (!musb->is_active) | 663 | if (!musb->is_active) |
664 | break; | 664 | break; |
665 | case OTG_STATE_B_PERIPHERAL: | 665 | case OTG_STATE_B_PERIPHERAL: |
666 | musb_g_suspend(musb); | 666 | musb_g_suspend(musb); |
667 | musb->is_active = is_otg_enabled(musb) | 667 | musb->is_active = is_otg_enabled(musb) |
668 | && otg->gadget->b_hnp_enable; | 668 | && otg->gadget->b_hnp_enable; |
669 | if (musb->is_active) { | 669 | if (musb->is_active) { |
670 | musb->xceiv->state = OTG_STATE_B_WAIT_ACON; | 670 | musb->xceiv->state = OTG_STATE_B_WAIT_ACON; |
671 | dev_dbg(musb->controller, "HNP: Setting timer for b_ase0_brst\n"); | 671 | dev_dbg(musb->controller, "HNP: Setting timer for b_ase0_brst\n"); |
672 | mod_timer(&musb->otg_timer, jiffies | 672 | mod_timer(&musb->otg_timer, jiffies |
673 | + msecs_to_jiffies( | 673 | + msecs_to_jiffies( |
674 | OTG_TIME_B_ASE0_BRST)); | 674 | OTG_TIME_B_ASE0_BRST)); |
675 | } | 675 | } |
676 | break; | 676 | break; |
677 | case OTG_STATE_A_WAIT_BCON: | 677 | case OTG_STATE_A_WAIT_BCON: |
678 | if (musb->a_wait_bcon != 0) | 678 | if (musb->a_wait_bcon != 0) |
679 | musb_platform_try_idle(musb, jiffies | 679 | musb_platform_try_idle(musb, jiffies |
680 | + msecs_to_jiffies(musb->a_wait_bcon)); | 680 | + msecs_to_jiffies(musb->a_wait_bcon)); |
681 | break; | 681 | break; |
682 | case OTG_STATE_A_HOST: | 682 | case OTG_STATE_A_HOST: |
683 | musb->xceiv->state = OTG_STATE_A_SUSPEND; | 683 | musb->xceiv->state = OTG_STATE_A_SUSPEND; |
684 | musb->is_active = is_otg_enabled(musb) | 684 | musb->is_active = is_otg_enabled(musb) |
685 | && otg->host->b_hnp_enable; | 685 | && otg->host->b_hnp_enable; |
686 | break; | 686 | break; |
687 | case OTG_STATE_B_HOST: | 687 | case OTG_STATE_B_HOST: |
688 | /* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */ | 688 | /* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */ |
689 | dev_dbg(musb->controller, "REVISIT: SUSPEND as B_HOST\n"); | 689 | dev_dbg(musb->controller, "REVISIT: SUSPEND as B_HOST\n"); |
690 | break; | 690 | break; |
691 | default: | 691 | default: |
692 | /* "should not happen" */ | 692 | /* "should not happen" */ |
693 | musb->is_active = 0; | 693 | musb->is_active = 0; |
694 | break; | 694 | break; |
695 | } | 695 | } |
696 | } | 696 | } |
697 | #endif | 697 | #endif |
698 | 698 | ||
699 | if (int_usb & MUSB_INTR_CONNECT) { | 699 | if (int_usb & MUSB_INTR_CONNECT) { |
700 | struct usb_hcd *hcd = musb_to_hcd(musb); | 700 | struct usb_hcd *hcd = musb_to_hcd(musb); |
701 | 701 | ||
702 | handled = IRQ_HANDLED; | 702 | handled = IRQ_HANDLED; |
703 | musb->is_active = 1; | 703 | musb->is_active = 1; |
704 | 704 | ||
705 | musb->ep0_stage = MUSB_EP0_START; | 705 | musb->ep0_stage = MUSB_EP0_START; |
706 | 706 | ||
707 | /* flush endpoints when transitioning from Device Mode */ | 707 | /* flush endpoints when transitioning from Device Mode */ |
708 | if (is_peripheral_active(musb)) { | 708 | if (is_peripheral_active(musb)) { |
709 | /* REVISIT HNP; just force disconnect */ | 709 | /* REVISIT HNP; just force disconnect */ |
710 | } | 710 | } |
711 | musb_writew(musb->mregs, MUSB_INTRTXE, musb->epmask); | 711 | musb_writew(musb->mregs, MUSB_INTRTXE, musb->epmask); |
712 | musb_writew(musb->mregs, MUSB_INTRRXE, musb->epmask & 0xfffe); | 712 | musb_writew(musb->mregs, MUSB_INTRRXE, musb->epmask & 0xfffe); |
713 | musb_writeb(musb->mregs, MUSB_INTRUSBE, 0xf7); | 713 | musb_writeb(musb->mregs, MUSB_INTRUSBE, 0xf7); |
714 | #ifndef __UBOOT__ | 714 | #ifndef __UBOOT__ |
715 | musb->port1_status &= ~(USB_PORT_STAT_LOW_SPEED | 715 | musb->port1_status &= ~(USB_PORT_STAT_LOW_SPEED |
716 | |USB_PORT_STAT_HIGH_SPEED | 716 | |USB_PORT_STAT_HIGH_SPEED |
717 | |USB_PORT_STAT_ENABLE | 717 | |USB_PORT_STAT_ENABLE |
718 | ); | 718 | ); |
719 | musb->port1_status |= USB_PORT_STAT_CONNECTION | 719 | musb->port1_status |= USB_PORT_STAT_CONNECTION |
720 | |(USB_PORT_STAT_C_CONNECTION << 16); | 720 | |(USB_PORT_STAT_C_CONNECTION << 16); |
721 | 721 | ||
722 | /* high vs full speed is just a guess until after reset */ | 722 | /* high vs full speed is just a guess until after reset */ |
723 | if (devctl & MUSB_DEVCTL_LSDEV) | 723 | if (devctl & MUSB_DEVCTL_LSDEV) |
724 | musb->port1_status |= USB_PORT_STAT_LOW_SPEED; | 724 | musb->port1_status |= USB_PORT_STAT_LOW_SPEED; |
725 | 725 | ||
726 | /* indicate new connection to OTG machine */ | 726 | /* indicate new connection to OTG machine */ |
727 | switch (musb->xceiv->state) { | 727 | switch (musb->xceiv->state) { |
728 | case OTG_STATE_B_PERIPHERAL: | 728 | case OTG_STATE_B_PERIPHERAL: |
729 | if (int_usb & MUSB_INTR_SUSPEND) { | 729 | if (int_usb & MUSB_INTR_SUSPEND) { |
730 | dev_dbg(musb->controller, "HNP: SUSPEND+CONNECT, now b_host\n"); | 730 | dev_dbg(musb->controller, "HNP: SUSPEND+CONNECT, now b_host\n"); |
731 | int_usb &= ~MUSB_INTR_SUSPEND; | 731 | int_usb &= ~MUSB_INTR_SUSPEND; |
732 | goto b_host; | 732 | goto b_host; |
733 | } else | 733 | } else |
734 | dev_dbg(musb->controller, "CONNECT as b_peripheral???\n"); | 734 | dev_dbg(musb->controller, "CONNECT as b_peripheral???\n"); |
735 | break; | 735 | break; |
736 | case OTG_STATE_B_WAIT_ACON: | 736 | case OTG_STATE_B_WAIT_ACON: |
737 | dev_dbg(musb->controller, "HNP: CONNECT, now b_host\n"); | 737 | dev_dbg(musb->controller, "HNP: CONNECT, now b_host\n"); |
738 | b_host: | 738 | b_host: |
739 | musb->xceiv->state = OTG_STATE_B_HOST; | 739 | musb->xceiv->state = OTG_STATE_B_HOST; |
740 | hcd->self.is_b_host = 1; | 740 | hcd->self.is_b_host = 1; |
741 | musb->ignore_disconnect = 0; | 741 | musb->ignore_disconnect = 0; |
742 | del_timer(&musb->otg_timer); | 742 | del_timer(&musb->otg_timer); |
743 | break; | 743 | break; |
744 | default: | 744 | default: |
745 | if ((devctl & MUSB_DEVCTL_VBUS) | 745 | if ((devctl & MUSB_DEVCTL_VBUS) |
746 | == (3 << MUSB_DEVCTL_VBUS_SHIFT)) { | 746 | == (3 << MUSB_DEVCTL_VBUS_SHIFT)) { |
747 | musb->xceiv->state = OTG_STATE_A_HOST; | 747 | musb->xceiv->state = OTG_STATE_A_HOST; |
748 | hcd->self.is_b_host = 0; | 748 | hcd->self.is_b_host = 0; |
749 | } | 749 | } |
750 | break; | 750 | break; |
751 | } | 751 | } |
752 | 752 | ||
753 | /* poke the root hub */ | 753 | /* poke the root hub */ |
754 | MUSB_HST_MODE(musb); | 754 | MUSB_HST_MODE(musb); |
755 | if (hcd->status_urb) | 755 | if (hcd->status_urb) |
756 | usb_hcd_poll_rh_status(hcd); | 756 | usb_hcd_poll_rh_status(hcd); |
757 | else | 757 | else |
758 | usb_hcd_resume_root_hub(hcd); | 758 | usb_hcd_resume_root_hub(hcd); |
759 | 759 | ||
760 | dev_dbg(musb->controller, "CONNECT (%s) devctl %02x\n", | 760 | dev_dbg(musb->controller, "CONNECT (%s) devctl %02x\n", |
761 | otg_state_string(musb->xceiv->state), devctl); | 761 | otg_state_string(musb->xceiv->state), devctl); |
762 | #endif | 762 | #endif |
763 | } | 763 | } |
764 | 764 | ||
765 | #ifndef __UBOOT__ | 765 | #ifndef __UBOOT__ |
766 | if ((int_usb & MUSB_INTR_DISCONNECT) && !musb->ignore_disconnect) { | 766 | if ((int_usb & MUSB_INTR_DISCONNECT) && !musb->ignore_disconnect) { |
767 | dev_dbg(musb->controller, "DISCONNECT (%s) as %s, devctl %02x\n", | 767 | dev_dbg(musb->controller, "DISCONNECT (%s) as %s, devctl %02x\n", |
768 | otg_state_string(musb->xceiv->state), | 768 | otg_state_string(musb->xceiv->state), |
769 | MUSB_MODE(musb), devctl); | 769 | MUSB_MODE(musb), devctl); |
770 | handled = IRQ_HANDLED; | 770 | handled = IRQ_HANDLED; |
771 | 771 | ||
772 | switch (musb->xceiv->state) { | 772 | switch (musb->xceiv->state) { |
773 | case OTG_STATE_A_HOST: | 773 | case OTG_STATE_A_HOST: |
774 | case OTG_STATE_A_SUSPEND: | 774 | case OTG_STATE_A_SUSPEND: |
775 | usb_hcd_resume_root_hub(musb_to_hcd(musb)); | 775 | usb_hcd_resume_root_hub(musb_to_hcd(musb)); |
776 | musb_root_disconnect(musb); | 776 | musb_root_disconnect(musb); |
777 | if (musb->a_wait_bcon != 0 && is_otg_enabled(musb)) | 777 | if (musb->a_wait_bcon != 0 && is_otg_enabled(musb)) |
778 | musb_platform_try_idle(musb, jiffies | 778 | musb_platform_try_idle(musb, jiffies |
779 | + msecs_to_jiffies(musb->a_wait_bcon)); | 779 | + msecs_to_jiffies(musb->a_wait_bcon)); |
780 | break; | 780 | break; |
781 | case OTG_STATE_B_HOST: | 781 | case OTG_STATE_B_HOST: |
782 | /* REVISIT this behaves for "real disconnect" | 782 | /* REVISIT this behaves for "real disconnect" |
783 | * cases; make sure the other transitions from | 783 | * cases; make sure the other transitions from |
784 | * from B_HOST act right too. The B_HOST code | 784 | * from B_HOST act right too. The B_HOST code |
785 | * in hnp_stop() is currently not used... | 785 | * in hnp_stop() is currently not used... |
786 | */ | 786 | */ |
787 | musb_root_disconnect(musb); | 787 | musb_root_disconnect(musb); |
788 | musb_to_hcd(musb)->self.is_b_host = 0; | 788 | musb_to_hcd(musb)->self.is_b_host = 0; |
789 | musb->xceiv->state = OTG_STATE_B_PERIPHERAL; | 789 | musb->xceiv->state = OTG_STATE_B_PERIPHERAL; |
790 | MUSB_DEV_MODE(musb); | 790 | MUSB_DEV_MODE(musb); |
791 | musb_g_disconnect(musb); | 791 | musb_g_disconnect(musb); |
792 | break; | 792 | break; |
793 | case OTG_STATE_A_PERIPHERAL: | 793 | case OTG_STATE_A_PERIPHERAL: |
794 | musb_hnp_stop(musb); | 794 | musb_hnp_stop(musb); |
795 | musb_root_disconnect(musb); | 795 | musb_root_disconnect(musb); |
796 | /* FALLTHROUGH */ | 796 | /* FALLTHROUGH */ |
797 | case OTG_STATE_B_WAIT_ACON: | 797 | case OTG_STATE_B_WAIT_ACON: |
798 | /* FALLTHROUGH */ | 798 | /* FALLTHROUGH */ |
799 | case OTG_STATE_B_PERIPHERAL: | 799 | case OTG_STATE_B_PERIPHERAL: |
800 | case OTG_STATE_B_IDLE: | 800 | case OTG_STATE_B_IDLE: |
801 | musb_g_disconnect(musb); | 801 | musb_g_disconnect(musb); |
802 | break; | 802 | break; |
803 | default: | 803 | default: |
804 | WARNING("unhandled DISCONNECT transition (%s)\n", | 804 | WARNING("unhandled DISCONNECT transition (%s)\n", |
805 | otg_state_string(musb->xceiv->state)); | 805 | otg_state_string(musb->xceiv->state)); |
806 | break; | 806 | break; |
807 | } | 807 | } |
808 | } | 808 | } |
809 | 809 | ||
810 | /* mentor saves a bit: bus reset and babble share the same irq. | 810 | /* mentor saves a bit: bus reset and babble share the same irq. |
811 | * only host sees babble; only peripheral sees bus reset. | 811 | * only host sees babble; only peripheral sees bus reset. |
812 | */ | 812 | */ |
813 | if (int_usb & MUSB_INTR_RESET) { | 813 | if (int_usb & MUSB_INTR_RESET) { |
814 | handled = IRQ_HANDLED; | 814 | handled = IRQ_HANDLED; |
815 | if (is_host_capable() && (devctl & MUSB_DEVCTL_HM) != 0) { | 815 | if (is_host_capable() && (devctl & MUSB_DEVCTL_HM) != 0) { |
816 | /* | 816 | /* |
817 | * Looks like non-HS BABBLE can be ignored, but | 817 | * Looks like non-HS BABBLE can be ignored, but |
818 | * HS BABBLE is an error condition. For HS the solution | 818 | * HS BABBLE is an error condition. For HS the solution |
819 | * is to avoid babble in the first place and fix what | 819 | * is to avoid babble in the first place and fix what |
820 | * caused BABBLE. When HS BABBLE happens we can only | 820 | * caused BABBLE. When HS BABBLE happens we can only |
821 | * stop the session. | 821 | * stop the session. |
822 | */ | 822 | */ |
823 | if (devctl & (MUSB_DEVCTL_FSDEV | MUSB_DEVCTL_LSDEV)) | 823 | if (devctl & (MUSB_DEVCTL_FSDEV | MUSB_DEVCTL_LSDEV)) |
824 | dev_dbg(musb->controller, "BABBLE devctl: %02x\n", devctl); | 824 | dev_dbg(musb->controller, "BABBLE devctl: %02x\n", devctl); |
825 | else { | 825 | else { |
826 | ERR("Stopping host session -- babble\n"); | 826 | ERR("Stopping host session -- babble\n"); |
827 | musb_writeb(musb->mregs, MUSB_DEVCTL, 0); | 827 | musb_writeb(musb->mregs, MUSB_DEVCTL, 0); |
828 | } | 828 | } |
829 | } else if (is_peripheral_capable()) { | 829 | } else if (is_peripheral_capable()) { |
830 | dev_dbg(musb->controller, "BUS RESET as %s\n", | 830 | dev_dbg(musb->controller, "BUS RESET as %s\n", |
831 | otg_state_string(musb->xceiv->state)); | 831 | otg_state_string(musb->xceiv->state)); |
832 | switch (musb->xceiv->state) { | 832 | switch (musb->xceiv->state) { |
833 | case OTG_STATE_A_SUSPEND: | 833 | case OTG_STATE_A_SUSPEND: |
834 | /* We need to ignore disconnect on suspend | 834 | /* We need to ignore disconnect on suspend |
835 | * otherwise tusb 2.0 won't reconnect after a | 835 | * otherwise tusb 2.0 won't reconnect after a |
836 | * power cycle, which breaks otg compliance. | 836 | * power cycle, which breaks otg compliance. |
837 | */ | 837 | */ |
838 | musb->ignore_disconnect = 1; | 838 | musb->ignore_disconnect = 1; |
839 | musb_g_reset(musb); | 839 | musb_g_reset(musb); |
840 | /* FALLTHROUGH */ | 840 | /* FALLTHROUGH */ |
841 | case OTG_STATE_A_WAIT_BCON: /* OPT TD.4.7-900ms */ | 841 | case OTG_STATE_A_WAIT_BCON: /* OPT TD.4.7-900ms */ |
842 | /* never use invalid T(a_wait_bcon) */ | 842 | /* never use invalid T(a_wait_bcon) */ |
843 | dev_dbg(musb->controller, "HNP: in %s, %d msec timeout\n", | 843 | dev_dbg(musb->controller, "HNP: in %s, %d msec timeout\n", |
844 | otg_state_string(musb->xceiv->state), | 844 | otg_state_string(musb->xceiv->state), |
845 | TA_WAIT_BCON(musb)); | 845 | TA_WAIT_BCON(musb)); |
846 | mod_timer(&musb->otg_timer, jiffies | 846 | mod_timer(&musb->otg_timer, jiffies |
847 | + msecs_to_jiffies(TA_WAIT_BCON(musb))); | 847 | + msecs_to_jiffies(TA_WAIT_BCON(musb))); |
848 | break; | 848 | break; |
849 | case OTG_STATE_A_PERIPHERAL: | 849 | case OTG_STATE_A_PERIPHERAL: |
850 | musb->ignore_disconnect = 0; | 850 | musb->ignore_disconnect = 0; |
851 | del_timer(&musb->otg_timer); | 851 | del_timer(&musb->otg_timer); |
852 | musb_g_reset(musb); | 852 | musb_g_reset(musb); |
853 | break; | 853 | break; |
854 | case OTG_STATE_B_WAIT_ACON: | 854 | case OTG_STATE_B_WAIT_ACON: |
855 | dev_dbg(musb->controller, "HNP: RESET (%s), to b_peripheral\n", | 855 | dev_dbg(musb->controller, "HNP: RESET (%s), to b_peripheral\n", |
856 | otg_state_string(musb->xceiv->state)); | 856 | otg_state_string(musb->xceiv->state)); |
857 | musb->xceiv->state = OTG_STATE_B_PERIPHERAL; | 857 | musb->xceiv->state = OTG_STATE_B_PERIPHERAL; |
858 | musb_g_reset(musb); | 858 | musb_g_reset(musb); |
859 | break; | 859 | break; |
860 | case OTG_STATE_B_IDLE: | 860 | case OTG_STATE_B_IDLE: |
861 | musb->xceiv->state = OTG_STATE_B_PERIPHERAL; | 861 | musb->xceiv->state = OTG_STATE_B_PERIPHERAL; |
862 | /* FALLTHROUGH */ | 862 | /* FALLTHROUGH */ |
863 | case OTG_STATE_B_PERIPHERAL: | 863 | case OTG_STATE_B_PERIPHERAL: |
864 | musb_g_reset(musb); | 864 | musb_g_reset(musb); |
865 | break; | 865 | break; |
866 | default: | 866 | default: |
867 | dev_dbg(musb->controller, "Unhandled BUS RESET as %s\n", | 867 | dev_dbg(musb->controller, "Unhandled BUS RESET as %s\n", |
868 | otg_state_string(musb->xceiv->state)); | 868 | otg_state_string(musb->xceiv->state)); |
869 | } | 869 | } |
870 | } | 870 | } |
871 | } | 871 | } |
872 | #endif | 872 | #endif |
873 | 873 | ||
874 | #if 0 | 874 | #if 0 |
875 | /* REVISIT ... this would be for multiplexing periodic endpoints, or | 875 | /* REVISIT ... this would be for multiplexing periodic endpoints, or |
876 | * supporting transfer phasing to prevent exceeding ISO bandwidth | 876 | * supporting transfer phasing to prevent exceeding ISO bandwidth |
877 | * limits of a given frame or microframe. | 877 | * limits of a given frame or microframe. |
878 | * | 878 | * |
879 | * It's not needed for peripheral side, which dedicates endpoints; | 879 | * It's not needed for peripheral side, which dedicates endpoints; |
880 | * though it _might_ use SOF irqs for other purposes. | 880 | * though it _might_ use SOF irqs for other purposes. |
881 | * | 881 | * |
882 | * And it's not currently needed for host side, which also dedicates | 882 | * And it's not currently needed for host side, which also dedicates |
883 | * endpoints, relies on TX/RX interval registers, and isn't claimed | 883 | * endpoints, relies on TX/RX interval registers, and isn't claimed |
884 | * to support ISO transfers yet. | 884 | * to support ISO transfers yet. |
885 | */ | 885 | */ |
886 | if (int_usb & MUSB_INTR_SOF) { | 886 | if (int_usb & MUSB_INTR_SOF) { |
887 | void __iomem *mbase = musb->mregs; | 887 | void __iomem *mbase = musb->mregs; |
888 | struct musb_hw_ep *ep; | 888 | struct musb_hw_ep *ep; |
889 | u8 epnum; | 889 | u8 epnum; |
890 | u16 frame; | 890 | u16 frame; |
891 | 891 | ||
892 | dev_dbg(musb->controller, "START_OF_FRAME\n"); | 892 | dev_dbg(musb->controller, "START_OF_FRAME\n"); |
893 | handled = IRQ_HANDLED; | 893 | handled = IRQ_HANDLED; |
894 | 894 | ||
895 | /* start any periodic Tx transfers waiting for current frame */ | 895 | /* start any periodic Tx transfers waiting for current frame */ |
896 | frame = musb_readw(mbase, MUSB_FRAME); | 896 | frame = musb_readw(mbase, MUSB_FRAME); |
897 | ep = musb->endpoints; | 897 | ep = musb->endpoints; |
898 | for (epnum = 1; (epnum < musb->nr_endpoints) | 898 | for (epnum = 1; (epnum < musb->nr_endpoints) |
899 | && (musb->epmask >= (1 << epnum)); | 899 | && (musb->epmask >= (1 << epnum)); |
900 | epnum++, ep++) { | 900 | epnum++, ep++) { |
901 | /* | 901 | /* |
902 | * FIXME handle framecounter wraps (12 bits) | 902 | * FIXME handle framecounter wraps (12 bits) |
903 | * eliminate duplicated StartUrb logic | 903 | * eliminate duplicated StartUrb logic |
904 | */ | 904 | */ |
905 | if (ep->dwWaitFrame >= frame) { | 905 | if (ep->dwWaitFrame >= frame) { |
906 | ep->dwWaitFrame = 0; | 906 | ep->dwWaitFrame = 0; |
907 | pr_debug("SOF --> periodic TX%s on %d\n", | 907 | pr_debug("SOF --> periodic TX%s on %d\n", |
908 | ep->tx_channel ? " DMA" : "", | 908 | ep->tx_channel ? " DMA" : "", |
909 | epnum); | 909 | epnum); |
910 | if (!ep->tx_channel) | 910 | if (!ep->tx_channel) |
911 | musb_h_tx_start(musb, epnum); | 911 | musb_h_tx_start(musb, epnum); |
912 | else | 912 | else |
913 | cppi_hostdma_start(musb, epnum); | 913 | cppi_hostdma_start(musb, epnum); |
914 | } | 914 | } |
915 | } /* end of for loop */ | 915 | } /* end of for loop */ |
916 | } | 916 | } |
917 | #endif | 917 | #endif |
918 | 918 | ||
919 | schedule_work(&musb->irq_work); | 919 | schedule_work(&musb->irq_work); |
920 | 920 | ||
921 | return handled; | 921 | return handled; |
922 | } | 922 | } |
923 | 923 | ||
924 | /*-------------------------------------------------------------------------*/ | 924 | /*-------------------------------------------------------------------------*/ |
925 | 925 | ||
926 | /* | 926 | /* |
927 | * Program the HDRC to start (enable interrupts, dma, etc.). | 927 | * Program the HDRC to start (enable interrupts, dma, etc.). |
928 | */ | 928 | */ |
929 | void musb_start(struct musb *musb) | 929 | void musb_start(struct musb *musb) |
930 | { | 930 | { |
931 | void __iomem *regs = musb->mregs; | 931 | void __iomem *regs = musb->mregs; |
932 | u8 devctl = musb_readb(regs, MUSB_DEVCTL); | 932 | u8 devctl = musb_readb(regs, MUSB_DEVCTL); |
933 | 933 | ||
934 | dev_dbg(musb->controller, "<== devctl %02x\n", devctl); | 934 | dev_dbg(musb->controller, "<== devctl %02x\n", devctl); |
935 | 935 | ||
936 | /* Set INT enable registers, enable interrupts */ | 936 | /* Set INT enable registers, enable interrupts */ |
937 | musb_writew(regs, MUSB_INTRTXE, musb->epmask); | 937 | musb_writew(regs, MUSB_INTRTXE, musb->epmask); |
938 | musb_writew(regs, MUSB_INTRRXE, musb->epmask & 0xfffe); | 938 | musb_writew(regs, MUSB_INTRRXE, musb->epmask & 0xfffe); |
939 | musb_writeb(regs, MUSB_INTRUSBE, 0xf7); | 939 | musb_writeb(regs, MUSB_INTRUSBE, 0xf7); |
940 | 940 | ||
941 | musb_writeb(regs, MUSB_TESTMODE, 0); | 941 | musb_writeb(regs, MUSB_TESTMODE, 0); |
942 | 942 | ||
943 | /* put into basic highspeed mode and start session */ | 943 | /* put into basic highspeed mode and start session */ |
944 | musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE | 944 | musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE |
945 | #ifdef CONFIG_USB_GADGET_DUALSPEED | ||
946 | | MUSB_POWER_HSENAB | 945 | | MUSB_POWER_HSENAB |
947 | #endif | ||
948 | /* ENSUSPEND wedges tusb */ | 946 | /* ENSUSPEND wedges tusb */ |
949 | /* | MUSB_POWER_ENSUSPEND */ | 947 | /* | MUSB_POWER_ENSUSPEND */ |
950 | ); | 948 | ); |
951 | 949 | ||
952 | musb->is_active = 0; | 950 | musb->is_active = 0; |
953 | devctl = musb_readb(regs, MUSB_DEVCTL); | 951 | devctl = musb_readb(regs, MUSB_DEVCTL); |
954 | devctl &= ~MUSB_DEVCTL_SESSION; | 952 | devctl &= ~MUSB_DEVCTL_SESSION; |
955 | 953 | ||
956 | if (is_otg_enabled(musb)) { | 954 | if (is_otg_enabled(musb)) { |
957 | #ifndef __UBOOT__ | 955 | #ifndef __UBOOT__ |
958 | /* session started after: | 956 | /* session started after: |
959 | * (a) ID-grounded irq, host mode; | 957 | * (a) ID-grounded irq, host mode; |
960 | * (b) vbus present/connect IRQ, peripheral mode; | 958 | * (b) vbus present/connect IRQ, peripheral mode; |
961 | * (c) peripheral initiates, using SRP | 959 | * (c) peripheral initiates, using SRP |
962 | */ | 960 | */ |
963 | if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) | 961 | if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) |
964 | musb->is_active = 1; | 962 | musb->is_active = 1; |
965 | else | 963 | else |
966 | devctl |= MUSB_DEVCTL_SESSION; | 964 | devctl |= MUSB_DEVCTL_SESSION; |
967 | #endif | 965 | #endif |
968 | 966 | ||
969 | } else if (is_host_enabled(musb)) { | 967 | } else if (is_host_enabled(musb)) { |
970 | /* assume ID pin is hard-wired to ground */ | 968 | /* assume ID pin is hard-wired to ground */ |
971 | devctl |= MUSB_DEVCTL_SESSION; | 969 | devctl |= MUSB_DEVCTL_SESSION; |
972 | 970 | ||
973 | } else /* peripheral is enabled */ { | 971 | } else /* peripheral is enabled */ { |
974 | if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) | 972 | if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) |
975 | musb->is_active = 1; | 973 | musb->is_active = 1; |
976 | } | 974 | } |
977 | musb_platform_enable(musb); | 975 | musb_platform_enable(musb); |
978 | musb_writeb(regs, MUSB_DEVCTL, devctl); | 976 | musb_writeb(regs, MUSB_DEVCTL, devctl); |
979 | } | 977 | } |
980 | 978 | ||
981 | 979 | ||
982 | static void musb_generic_disable(struct musb *musb) | 980 | static void musb_generic_disable(struct musb *musb) |
983 | { | 981 | { |
984 | void __iomem *mbase = musb->mregs; | 982 | void __iomem *mbase = musb->mregs; |
985 | u16 temp; | 983 | u16 temp; |
986 | 984 | ||
987 | /* disable interrupts */ | 985 | /* disable interrupts */ |
988 | musb_writeb(mbase, MUSB_INTRUSBE, 0); | 986 | musb_writeb(mbase, MUSB_INTRUSBE, 0); |
989 | musb_writew(mbase, MUSB_INTRTXE, 0); | 987 | musb_writew(mbase, MUSB_INTRTXE, 0); |
990 | musb_writew(mbase, MUSB_INTRRXE, 0); | 988 | musb_writew(mbase, MUSB_INTRRXE, 0); |
991 | 989 | ||
992 | /* off */ | 990 | /* off */ |
993 | musb_writeb(mbase, MUSB_DEVCTL, 0); | 991 | musb_writeb(mbase, MUSB_DEVCTL, 0); |
994 | 992 | ||
995 | /* flush pending interrupts */ | 993 | /* flush pending interrupts */ |
996 | temp = musb_readb(mbase, MUSB_INTRUSB); | 994 | temp = musb_readb(mbase, MUSB_INTRUSB); |
997 | temp = musb_readw(mbase, MUSB_INTRTX); | 995 | temp = musb_readw(mbase, MUSB_INTRTX); |
998 | temp = musb_readw(mbase, MUSB_INTRRX); | 996 | temp = musb_readw(mbase, MUSB_INTRRX); |
999 | 997 | ||
1000 | } | 998 | } |
1001 | 999 | ||
1002 | /* | 1000 | /* |
1003 | * Make the HDRC stop (disable interrupts, etc.); | 1001 | * Make the HDRC stop (disable interrupts, etc.); |
1004 | * reversible by musb_start | 1002 | * reversible by musb_start |
1005 | * called on gadget driver unregister | 1003 | * called on gadget driver unregister |
1006 | * with controller locked, irqs blocked | 1004 | * with controller locked, irqs blocked |
1007 | * acts as a NOP unless some role activated the hardware | 1005 | * acts as a NOP unless some role activated the hardware |
1008 | */ | 1006 | */ |
1009 | void musb_stop(struct musb *musb) | 1007 | void musb_stop(struct musb *musb) |
1010 | { | 1008 | { |
1011 | /* stop IRQs, timers, ... */ | 1009 | /* stop IRQs, timers, ... */ |
1012 | musb_platform_disable(musb); | 1010 | musb_platform_disable(musb); |
1013 | musb_generic_disable(musb); | 1011 | musb_generic_disable(musb); |
1014 | dev_dbg(musb->controller, "HDRC disabled\n"); | 1012 | dev_dbg(musb->controller, "HDRC disabled\n"); |
1015 | 1013 | ||
1016 | /* FIXME | 1014 | /* FIXME |
1017 | * - mark host and/or peripheral drivers unusable/inactive | 1015 | * - mark host and/or peripheral drivers unusable/inactive |
1018 | * - disable DMA (and enable it in HdrcStart) | 1016 | * - disable DMA (and enable it in HdrcStart) |
1019 | * - make sure we can musb_start() after musb_stop(); with | 1017 | * - make sure we can musb_start() after musb_stop(); with |
1020 | * OTG mode, gadget driver module rmmod/modprobe cycles that | 1018 | * OTG mode, gadget driver module rmmod/modprobe cycles that |
1021 | * - ... | 1019 | * - ... |
1022 | */ | 1020 | */ |
1023 | musb_platform_try_idle(musb, 0); | 1021 | musb_platform_try_idle(musb, 0); |
1024 | } | 1022 | } |
1025 | 1023 | ||
1026 | #ifndef __UBOOT__ | 1024 | #ifndef __UBOOT__ |
1027 | static void musb_shutdown(struct platform_device *pdev) | 1025 | static void musb_shutdown(struct platform_device *pdev) |
1028 | { | 1026 | { |
1029 | struct musb *musb = dev_to_musb(&pdev->dev); | 1027 | struct musb *musb = dev_to_musb(&pdev->dev); |
1030 | unsigned long flags; | 1028 | unsigned long flags; |
1031 | 1029 | ||
1032 | pm_runtime_get_sync(musb->controller); | 1030 | pm_runtime_get_sync(musb->controller); |
1033 | 1031 | ||
1034 | musb_gadget_cleanup(musb); | 1032 | musb_gadget_cleanup(musb); |
1035 | 1033 | ||
1036 | spin_lock_irqsave(&musb->lock, flags); | 1034 | spin_lock_irqsave(&musb->lock, flags); |
1037 | musb_platform_disable(musb); | 1035 | musb_platform_disable(musb); |
1038 | musb_generic_disable(musb); | 1036 | musb_generic_disable(musb); |
1039 | spin_unlock_irqrestore(&musb->lock, flags); | 1037 | spin_unlock_irqrestore(&musb->lock, flags); |
1040 | 1038 | ||
1041 | if (!is_otg_enabled(musb) && is_host_enabled(musb)) | 1039 | if (!is_otg_enabled(musb) && is_host_enabled(musb)) |
1042 | usb_remove_hcd(musb_to_hcd(musb)); | 1040 | usb_remove_hcd(musb_to_hcd(musb)); |
1043 | musb_writeb(musb->mregs, MUSB_DEVCTL, 0); | 1041 | musb_writeb(musb->mregs, MUSB_DEVCTL, 0); |
1044 | musb_platform_exit(musb); | 1042 | musb_platform_exit(musb); |
1045 | 1043 | ||
1046 | pm_runtime_put(musb->controller); | 1044 | pm_runtime_put(musb->controller); |
1047 | /* FIXME power down */ | 1045 | /* FIXME power down */ |
1048 | } | 1046 | } |
1049 | #endif | 1047 | #endif |
1050 | 1048 | ||
1051 | 1049 | ||
1052 | /*-------------------------------------------------------------------------*/ | 1050 | /*-------------------------------------------------------------------------*/ |
1053 | 1051 | ||
1054 | /* | 1052 | /* |
1055 | * The silicon either has hard-wired endpoint configurations, or else | 1053 | * The silicon either has hard-wired endpoint configurations, or else |
1056 | * "dynamic fifo" sizing. The driver has support for both, though at this | 1054 | * "dynamic fifo" sizing. The driver has support for both, though at this |
1057 | * writing only the dynamic sizing is very well tested. Since we switched | 1055 | * writing only the dynamic sizing is very well tested. Since we switched |
1058 | * away from compile-time hardware parameters, we can no longer rely on | 1056 | * away from compile-time hardware parameters, we can no longer rely on |
1059 | * dead code elimination to leave only the relevant one in the object file. | 1057 | * dead code elimination to leave only the relevant one in the object file. |
1060 | * | 1058 | * |
1061 | * We don't currently use dynamic fifo setup capability to do anything | 1059 | * We don't currently use dynamic fifo setup capability to do anything |
1062 | * more than selecting one of a bunch of predefined configurations. | 1060 | * more than selecting one of a bunch of predefined configurations. |
1063 | */ | 1061 | */ |
1064 | #if defined(CONFIG_USB_MUSB_TUSB6010) \ | 1062 | #if defined(CONFIG_USB_MUSB_TUSB6010) \ |
1065 | || defined(CONFIG_USB_MUSB_TUSB6010_MODULE) \ | 1063 | || defined(CONFIG_USB_MUSB_TUSB6010_MODULE) \ |
1066 | || defined(CONFIG_USB_MUSB_OMAP2PLUS) \ | 1064 | || defined(CONFIG_USB_MUSB_OMAP2PLUS) \ |
1067 | || defined(CONFIG_USB_MUSB_OMAP2PLUS_MODULE) \ | 1065 | || defined(CONFIG_USB_MUSB_OMAP2PLUS_MODULE) \ |
1068 | || defined(CONFIG_USB_MUSB_AM35X) \ | 1066 | || defined(CONFIG_USB_MUSB_AM35X) \ |
1069 | || defined(CONFIG_USB_MUSB_AM35X_MODULE) \ | 1067 | || defined(CONFIG_USB_MUSB_AM35X_MODULE) \ |
1070 | || defined(CONFIG_USB_MUSB_DSPS) \ | 1068 | || defined(CONFIG_USB_MUSB_DSPS) \ |
1071 | || defined(CONFIG_USB_MUSB_DSPS_MODULE) | 1069 | || defined(CONFIG_USB_MUSB_DSPS_MODULE) |
1072 | static ushort __devinitdata fifo_mode = 4; | 1070 | static ushort __devinitdata fifo_mode = 4; |
1073 | #elif defined(CONFIG_USB_MUSB_UX500) \ | 1071 | #elif defined(CONFIG_USB_MUSB_UX500) \ |
1074 | || defined(CONFIG_USB_MUSB_UX500_MODULE) | 1072 | || defined(CONFIG_USB_MUSB_UX500_MODULE) |
1075 | static ushort __devinitdata fifo_mode = 5; | 1073 | static ushort __devinitdata fifo_mode = 5; |
1076 | #else | 1074 | #else |
1077 | static ushort __devinitdata fifo_mode = 2; | 1075 | static ushort __devinitdata fifo_mode = 2; |
1078 | #endif | 1076 | #endif |
1079 | 1077 | ||
1080 | /* "modprobe ... fifo_mode=1" etc */ | 1078 | /* "modprobe ... fifo_mode=1" etc */ |
1081 | module_param(fifo_mode, ushort, 0); | 1079 | module_param(fifo_mode, ushort, 0); |
1082 | MODULE_PARM_DESC(fifo_mode, "initial endpoint configuration"); | 1080 | MODULE_PARM_DESC(fifo_mode, "initial endpoint configuration"); |
1083 | 1081 | ||
1084 | /* | 1082 | /* |
1085 | * tables defining fifo_mode values. define more if you like. | 1083 | * tables defining fifo_mode values. define more if you like. |
1086 | * for host side, make sure both halves of ep1 are set up. | 1084 | * for host side, make sure both halves of ep1 are set up. |
1087 | */ | 1085 | */ |
1088 | 1086 | ||
1089 | /* mode 0 - fits in 2KB */ | 1087 | /* mode 0 - fits in 2KB */ |
1090 | static struct musb_fifo_cfg __devinitdata mode_0_cfg[] = { | 1088 | static struct musb_fifo_cfg __devinitdata mode_0_cfg[] = { |
1091 | { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, | 1089 | { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, |
1092 | { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, | 1090 | { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, |
1093 | { .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, }, | 1091 | { .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, }, |
1094 | { .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, }, | 1092 | { .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, }, |
1095 | { .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, }, | 1093 | { .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, }, |
1096 | }; | 1094 | }; |
1097 | 1095 | ||
1098 | /* mode 1 - fits in 4KB */ | 1096 | /* mode 1 - fits in 4KB */ |
1099 | static struct musb_fifo_cfg __devinitdata mode_1_cfg[] = { | 1097 | static struct musb_fifo_cfg __devinitdata mode_1_cfg[] = { |
1100 | { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, .mode = BUF_DOUBLE, }, | 1098 | { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, .mode = BUF_DOUBLE, }, |
1101 | { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, .mode = BUF_DOUBLE, }, | 1099 | { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, .mode = BUF_DOUBLE, }, |
1102 | { .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, .mode = BUF_DOUBLE, }, | 1100 | { .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, .mode = BUF_DOUBLE, }, |
1103 | { .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, }, | 1101 | { .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, }, |
1104 | { .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, }, | 1102 | { .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, }, |
1105 | }; | 1103 | }; |
1106 | 1104 | ||
1107 | /* mode 2 - fits in 4KB */ | 1105 | /* mode 2 - fits in 4KB */ |
1108 | static struct musb_fifo_cfg __devinitdata mode_2_cfg[] = { | 1106 | static struct musb_fifo_cfg __devinitdata mode_2_cfg[] = { |
1109 | { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, | 1107 | { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, |
1110 | { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, | 1108 | { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, |
1111 | { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, | 1109 | { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, |
1112 | { .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, }, | 1110 | { .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, }, |
1113 | { .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, }, | 1111 | { .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, }, |
1114 | { .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, }, | 1112 | { .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, }, |
1115 | }; | 1113 | }; |
1116 | 1114 | ||
1117 | /* mode 3 - fits in 4KB */ | 1115 | /* mode 3 - fits in 4KB */ |
1118 | static struct musb_fifo_cfg __devinitdata mode_3_cfg[] = { | 1116 | static struct musb_fifo_cfg __devinitdata mode_3_cfg[] = { |
1119 | { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, .mode = BUF_DOUBLE, }, | 1117 | { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, .mode = BUF_DOUBLE, }, |
1120 | { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, .mode = BUF_DOUBLE, }, | 1118 | { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, .mode = BUF_DOUBLE, }, |
1121 | { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, | 1119 | { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, |
1122 | { .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, }, | 1120 | { .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, }, |
1123 | { .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, }, | 1121 | { .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, }, |
1124 | { .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, }, | 1122 | { .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, }, |
1125 | }; | 1123 | }; |
1126 | 1124 | ||
1127 | /* mode 4 - fits in 16KB */ | 1125 | /* mode 4 - fits in 16KB */ |
1128 | static struct musb_fifo_cfg __devinitdata mode_4_cfg[] = { | 1126 | static struct musb_fifo_cfg __devinitdata mode_4_cfg[] = { |
1129 | { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, | 1127 | { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, |
1130 | { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, | 1128 | { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, |
1131 | { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, | 1129 | { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, |
1132 | { .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, }, | 1130 | { .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, }, |
1133 | { .hw_ep_num = 3, .style = FIFO_TX, .maxpacket = 512, }, | 1131 | { .hw_ep_num = 3, .style = FIFO_TX, .maxpacket = 512, }, |
1134 | { .hw_ep_num = 3, .style = FIFO_RX, .maxpacket = 512, }, | 1132 | { .hw_ep_num = 3, .style = FIFO_RX, .maxpacket = 512, }, |
1135 | { .hw_ep_num = 4, .style = FIFO_TX, .maxpacket = 512, }, | 1133 | { .hw_ep_num = 4, .style = FIFO_TX, .maxpacket = 512, }, |
1136 | { .hw_ep_num = 4, .style = FIFO_RX, .maxpacket = 512, }, | 1134 | { .hw_ep_num = 4, .style = FIFO_RX, .maxpacket = 512, }, |
1137 | { .hw_ep_num = 5, .style = FIFO_TX, .maxpacket = 512, }, | 1135 | { .hw_ep_num = 5, .style = FIFO_TX, .maxpacket = 512, }, |
1138 | { .hw_ep_num = 5, .style = FIFO_RX, .maxpacket = 512, }, | 1136 | { .hw_ep_num = 5, .style = FIFO_RX, .maxpacket = 512, }, |
1139 | { .hw_ep_num = 6, .style = FIFO_TX, .maxpacket = 512, }, | 1137 | { .hw_ep_num = 6, .style = FIFO_TX, .maxpacket = 512, }, |
1140 | { .hw_ep_num = 6, .style = FIFO_RX, .maxpacket = 512, }, | 1138 | { .hw_ep_num = 6, .style = FIFO_RX, .maxpacket = 512, }, |
1141 | { .hw_ep_num = 7, .style = FIFO_TX, .maxpacket = 512, }, | 1139 | { .hw_ep_num = 7, .style = FIFO_TX, .maxpacket = 512, }, |
1142 | { .hw_ep_num = 7, .style = FIFO_RX, .maxpacket = 512, }, | 1140 | { .hw_ep_num = 7, .style = FIFO_RX, .maxpacket = 512, }, |
1143 | { .hw_ep_num = 8, .style = FIFO_TX, .maxpacket = 512, }, | 1141 | { .hw_ep_num = 8, .style = FIFO_TX, .maxpacket = 512, }, |
1144 | { .hw_ep_num = 8, .style = FIFO_RX, .maxpacket = 512, }, | 1142 | { .hw_ep_num = 8, .style = FIFO_RX, .maxpacket = 512, }, |
1145 | { .hw_ep_num = 9, .style = FIFO_TX, .maxpacket = 512, }, | 1143 | { .hw_ep_num = 9, .style = FIFO_TX, .maxpacket = 512, }, |
1146 | { .hw_ep_num = 9, .style = FIFO_RX, .maxpacket = 512, }, | 1144 | { .hw_ep_num = 9, .style = FIFO_RX, .maxpacket = 512, }, |
1147 | { .hw_ep_num = 10, .style = FIFO_TX, .maxpacket = 256, }, | 1145 | { .hw_ep_num = 10, .style = FIFO_TX, .maxpacket = 256, }, |
1148 | { .hw_ep_num = 10, .style = FIFO_RX, .maxpacket = 64, }, | 1146 | { .hw_ep_num = 10, .style = FIFO_RX, .maxpacket = 64, }, |
1149 | { .hw_ep_num = 11, .style = FIFO_TX, .maxpacket = 256, }, | 1147 | { .hw_ep_num = 11, .style = FIFO_TX, .maxpacket = 256, }, |
1150 | { .hw_ep_num = 11, .style = FIFO_RX, .maxpacket = 64, }, | 1148 | { .hw_ep_num = 11, .style = FIFO_RX, .maxpacket = 64, }, |
1151 | { .hw_ep_num = 12, .style = FIFO_TX, .maxpacket = 256, }, | 1149 | { .hw_ep_num = 12, .style = FIFO_TX, .maxpacket = 256, }, |
1152 | { .hw_ep_num = 12, .style = FIFO_RX, .maxpacket = 64, }, | 1150 | { .hw_ep_num = 12, .style = FIFO_RX, .maxpacket = 64, }, |
1153 | { .hw_ep_num = 13, .style = FIFO_RXTX, .maxpacket = 4096, }, | 1151 | { .hw_ep_num = 13, .style = FIFO_RXTX, .maxpacket = 4096, }, |
1154 | { .hw_ep_num = 14, .style = FIFO_RXTX, .maxpacket = 1024, }, | 1152 | { .hw_ep_num = 14, .style = FIFO_RXTX, .maxpacket = 1024, }, |
1155 | { .hw_ep_num = 15, .style = FIFO_RXTX, .maxpacket = 1024, }, | 1153 | { .hw_ep_num = 15, .style = FIFO_RXTX, .maxpacket = 1024, }, |
1156 | }; | 1154 | }; |
1157 | 1155 | ||
1158 | /* mode 5 - fits in 8KB */ | 1156 | /* mode 5 - fits in 8KB */ |
1159 | static struct musb_fifo_cfg __devinitdata mode_5_cfg[] = { | 1157 | static struct musb_fifo_cfg __devinitdata mode_5_cfg[] = { |
1160 | { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, | 1158 | { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, |
1161 | { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, | 1159 | { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, |
1162 | { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, | 1160 | { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, |
1163 | { .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, }, | 1161 | { .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, }, |
1164 | { .hw_ep_num = 3, .style = FIFO_TX, .maxpacket = 512, }, | 1162 | { .hw_ep_num = 3, .style = FIFO_TX, .maxpacket = 512, }, |
1165 | { .hw_ep_num = 3, .style = FIFO_RX, .maxpacket = 512, }, | 1163 | { .hw_ep_num = 3, .style = FIFO_RX, .maxpacket = 512, }, |
1166 | { .hw_ep_num = 4, .style = FIFO_TX, .maxpacket = 512, }, | 1164 | { .hw_ep_num = 4, .style = FIFO_TX, .maxpacket = 512, }, |
1167 | { .hw_ep_num = 4, .style = FIFO_RX, .maxpacket = 512, }, | 1165 | { .hw_ep_num = 4, .style = FIFO_RX, .maxpacket = 512, }, |
1168 | { .hw_ep_num = 5, .style = FIFO_TX, .maxpacket = 512, }, | 1166 | { .hw_ep_num = 5, .style = FIFO_TX, .maxpacket = 512, }, |
1169 | { .hw_ep_num = 5, .style = FIFO_RX, .maxpacket = 512, }, | 1167 | { .hw_ep_num = 5, .style = FIFO_RX, .maxpacket = 512, }, |
1170 | { .hw_ep_num = 6, .style = FIFO_TX, .maxpacket = 32, }, | 1168 | { .hw_ep_num = 6, .style = FIFO_TX, .maxpacket = 32, }, |
1171 | { .hw_ep_num = 6, .style = FIFO_RX, .maxpacket = 32, }, | 1169 | { .hw_ep_num = 6, .style = FIFO_RX, .maxpacket = 32, }, |
1172 | { .hw_ep_num = 7, .style = FIFO_TX, .maxpacket = 32, }, | 1170 | { .hw_ep_num = 7, .style = FIFO_TX, .maxpacket = 32, }, |
1173 | { .hw_ep_num = 7, .style = FIFO_RX, .maxpacket = 32, }, | 1171 | { .hw_ep_num = 7, .style = FIFO_RX, .maxpacket = 32, }, |
1174 | { .hw_ep_num = 8, .style = FIFO_TX, .maxpacket = 32, }, | 1172 | { .hw_ep_num = 8, .style = FIFO_TX, .maxpacket = 32, }, |
1175 | { .hw_ep_num = 8, .style = FIFO_RX, .maxpacket = 32, }, | 1173 | { .hw_ep_num = 8, .style = FIFO_RX, .maxpacket = 32, }, |
1176 | { .hw_ep_num = 9, .style = FIFO_TX, .maxpacket = 32, }, | 1174 | { .hw_ep_num = 9, .style = FIFO_TX, .maxpacket = 32, }, |
1177 | { .hw_ep_num = 9, .style = FIFO_RX, .maxpacket = 32, }, | 1175 | { .hw_ep_num = 9, .style = FIFO_RX, .maxpacket = 32, }, |
1178 | { .hw_ep_num = 10, .style = FIFO_TX, .maxpacket = 32, }, | 1176 | { .hw_ep_num = 10, .style = FIFO_TX, .maxpacket = 32, }, |
1179 | { .hw_ep_num = 10, .style = FIFO_RX, .maxpacket = 32, }, | 1177 | { .hw_ep_num = 10, .style = FIFO_RX, .maxpacket = 32, }, |
1180 | { .hw_ep_num = 11, .style = FIFO_TX, .maxpacket = 32, }, | 1178 | { .hw_ep_num = 11, .style = FIFO_TX, .maxpacket = 32, }, |
1181 | { .hw_ep_num = 11, .style = FIFO_RX, .maxpacket = 32, }, | 1179 | { .hw_ep_num = 11, .style = FIFO_RX, .maxpacket = 32, }, |
1182 | { .hw_ep_num = 12, .style = FIFO_TX, .maxpacket = 32, }, | 1180 | { .hw_ep_num = 12, .style = FIFO_TX, .maxpacket = 32, }, |
1183 | { .hw_ep_num = 12, .style = FIFO_RX, .maxpacket = 32, }, | 1181 | { .hw_ep_num = 12, .style = FIFO_RX, .maxpacket = 32, }, |
1184 | { .hw_ep_num = 13, .style = FIFO_RXTX, .maxpacket = 512, }, | 1182 | { .hw_ep_num = 13, .style = FIFO_RXTX, .maxpacket = 512, }, |
1185 | { .hw_ep_num = 14, .style = FIFO_RXTX, .maxpacket = 1024, }, | 1183 | { .hw_ep_num = 14, .style = FIFO_RXTX, .maxpacket = 1024, }, |
1186 | { .hw_ep_num = 15, .style = FIFO_RXTX, .maxpacket = 1024, }, | 1184 | { .hw_ep_num = 15, .style = FIFO_RXTX, .maxpacket = 1024, }, |
1187 | }; | 1185 | }; |
1188 | 1186 | ||
1189 | /* | 1187 | /* |
1190 | * configure a fifo; for non-shared endpoints, this may be called | 1188 | * configure a fifo; for non-shared endpoints, this may be called |
1191 | * once for a tx fifo and once for an rx fifo. | 1189 | * once for a tx fifo and once for an rx fifo. |
1192 | * | 1190 | * |
1193 | * returns negative errno or offset for next fifo. | 1191 | * returns negative errno or offset for next fifo. |
1194 | */ | 1192 | */ |
1195 | static int __devinit | 1193 | static int __devinit |
1196 | fifo_setup(struct musb *musb, struct musb_hw_ep *hw_ep, | 1194 | fifo_setup(struct musb *musb, struct musb_hw_ep *hw_ep, |
1197 | const struct musb_fifo_cfg *cfg, u16 offset) | 1195 | const struct musb_fifo_cfg *cfg, u16 offset) |
1198 | { | 1196 | { |
1199 | void __iomem *mbase = musb->mregs; | 1197 | void __iomem *mbase = musb->mregs; |
1200 | int size = 0; | 1198 | int size = 0; |
1201 | u16 maxpacket = cfg->maxpacket; | 1199 | u16 maxpacket = cfg->maxpacket; |
1202 | u16 c_off = offset >> 3; | 1200 | u16 c_off = offset >> 3; |
1203 | u8 c_size; | 1201 | u8 c_size; |
1204 | 1202 | ||
1205 | /* expect hw_ep has already been zero-initialized */ | 1203 | /* expect hw_ep has already been zero-initialized */ |
1206 | 1204 | ||
1207 | size = ffs(max(maxpacket, (u16) 8)) - 1; | 1205 | size = ffs(max(maxpacket, (u16) 8)) - 1; |
1208 | maxpacket = 1 << size; | 1206 | maxpacket = 1 << size; |
1209 | 1207 | ||
1210 | c_size = size - 3; | 1208 | c_size = size - 3; |
1211 | if (cfg->mode == BUF_DOUBLE) { | 1209 | if (cfg->mode == BUF_DOUBLE) { |
1212 | if ((offset + (maxpacket << 1)) > | 1210 | if ((offset + (maxpacket << 1)) > |
1213 | (1 << (musb->config->ram_bits + 2))) | 1211 | (1 << (musb->config->ram_bits + 2))) |
1214 | return -EMSGSIZE; | 1212 | return -EMSGSIZE; |
1215 | c_size |= MUSB_FIFOSZ_DPB; | 1213 | c_size |= MUSB_FIFOSZ_DPB; |
1216 | } else { | 1214 | } else { |
1217 | if ((offset + maxpacket) > (1 << (musb->config->ram_bits + 2))) | 1215 | if ((offset + maxpacket) > (1 << (musb->config->ram_bits + 2))) |
1218 | return -EMSGSIZE; | 1216 | return -EMSGSIZE; |
1219 | } | 1217 | } |
1220 | 1218 | ||
1221 | /* configure the FIFO */ | 1219 | /* configure the FIFO */ |
1222 | musb_writeb(mbase, MUSB_INDEX, hw_ep->epnum); | 1220 | musb_writeb(mbase, MUSB_INDEX, hw_ep->epnum); |
1223 | 1221 | ||
1224 | /* EP0 reserved endpoint for control, bidirectional; | 1222 | /* EP0 reserved endpoint for control, bidirectional; |
1225 | * EP1 reserved for bulk, two unidirection halves. | 1223 | * EP1 reserved for bulk, two unidirection halves. |
1226 | */ | 1224 | */ |
1227 | if (hw_ep->epnum == 1) | 1225 | if (hw_ep->epnum == 1) |
1228 | musb->bulk_ep = hw_ep; | 1226 | musb->bulk_ep = hw_ep; |
1229 | /* REVISIT error check: be sure ep0 can both rx and tx ... */ | 1227 | /* REVISIT error check: be sure ep0 can both rx and tx ... */ |
1230 | switch (cfg->style) { | 1228 | switch (cfg->style) { |
1231 | case FIFO_TX: | 1229 | case FIFO_TX: |
1232 | musb_write_txfifosz(mbase, c_size); | 1230 | musb_write_txfifosz(mbase, c_size); |
1233 | musb_write_txfifoadd(mbase, c_off); | 1231 | musb_write_txfifoadd(mbase, c_off); |
1234 | hw_ep->tx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB); | 1232 | hw_ep->tx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB); |
1235 | hw_ep->max_packet_sz_tx = maxpacket; | 1233 | hw_ep->max_packet_sz_tx = maxpacket; |
1236 | break; | 1234 | break; |
1237 | case FIFO_RX: | 1235 | case FIFO_RX: |
1238 | musb_write_rxfifosz(mbase, c_size); | 1236 | musb_write_rxfifosz(mbase, c_size); |
1239 | musb_write_rxfifoadd(mbase, c_off); | 1237 | musb_write_rxfifoadd(mbase, c_off); |
1240 | hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB); | 1238 | hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB); |
1241 | hw_ep->max_packet_sz_rx = maxpacket; | 1239 | hw_ep->max_packet_sz_rx = maxpacket; |
1242 | break; | 1240 | break; |
1243 | case FIFO_RXTX: | 1241 | case FIFO_RXTX: |
1244 | musb_write_txfifosz(mbase, c_size); | 1242 | musb_write_txfifosz(mbase, c_size); |
1245 | musb_write_txfifoadd(mbase, c_off); | 1243 | musb_write_txfifoadd(mbase, c_off); |
1246 | hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB); | 1244 | hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB); |
1247 | hw_ep->max_packet_sz_rx = maxpacket; | 1245 | hw_ep->max_packet_sz_rx = maxpacket; |
1248 | 1246 | ||
1249 | musb_write_rxfifosz(mbase, c_size); | 1247 | musb_write_rxfifosz(mbase, c_size); |
1250 | musb_write_rxfifoadd(mbase, c_off); | 1248 | musb_write_rxfifoadd(mbase, c_off); |
1251 | hw_ep->tx_double_buffered = hw_ep->rx_double_buffered; | 1249 | hw_ep->tx_double_buffered = hw_ep->rx_double_buffered; |
1252 | hw_ep->max_packet_sz_tx = maxpacket; | 1250 | hw_ep->max_packet_sz_tx = maxpacket; |
1253 | 1251 | ||
1254 | hw_ep->is_shared_fifo = true; | 1252 | hw_ep->is_shared_fifo = true; |
1255 | break; | 1253 | break; |
1256 | } | 1254 | } |
1257 | 1255 | ||
1258 | /* NOTE rx and tx endpoint irqs aren't managed separately, | 1256 | /* NOTE rx and tx endpoint irqs aren't managed separately, |
1259 | * which happens to be ok | 1257 | * which happens to be ok |
1260 | */ | 1258 | */ |
1261 | musb->epmask |= (1 << hw_ep->epnum); | 1259 | musb->epmask |= (1 << hw_ep->epnum); |
1262 | 1260 | ||
1263 | return offset + (maxpacket << ((c_size & MUSB_FIFOSZ_DPB) ? 1 : 0)); | 1261 | return offset + (maxpacket << ((c_size & MUSB_FIFOSZ_DPB) ? 1 : 0)); |
1264 | } | 1262 | } |
1265 | 1263 | ||
1266 | static struct musb_fifo_cfg __devinitdata ep0_cfg = { | 1264 | static struct musb_fifo_cfg __devinitdata ep0_cfg = { |
1267 | .style = FIFO_RXTX, .maxpacket = 64, | 1265 | .style = FIFO_RXTX, .maxpacket = 64, |
1268 | }; | 1266 | }; |
1269 | 1267 | ||
1270 | static int __devinit ep_config_from_table(struct musb *musb) | 1268 | static int __devinit ep_config_from_table(struct musb *musb) |
1271 | { | 1269 | { |
1272 | const struct musb_fifo_cfg *cfg; | 1270 | const struct musb_fifo_cfg *cfg; |
1273 | unsigned i, n; | 1271 | unsigned i, n; |
1274 | int offset; | 1272 | int offset; |
1275 | struct musb_hw_ep *hw_ep = musb->endpoints; | 1273 | struct musb_hw_ep *hw_ep = musb->endpoints; |
1276 | 1274 | ||
1277 | if (musb->config->fifo_cfg) { | 1275 | if (musb->config->fifo_cfg) { |
1278 | cfg = musb->config->fifo_cfg; | 1276 | cfg = musb->config->fifo_cfg; |
1279 | n = musb->config->fifo_cfg_size; | 1277 | n = musb->config->fifo_cfg_size; |
1280 | goto done; | 1278 | goto done; |
1281 | } | 1279 | } |
1282 | 1280 | ||
1283 | switch (fifo_mode) { | 1281 | switch (fifo_mode) { |
1284 | default: | 1282 | default: |
1285 | fifo_mode = 0; | 1283 | fifo_mode = 0; |
1286 | /* FALLTHROUGH */ | 1284 | /* FALLTHROUGH */ |
1287 | case 0: | 1285 | case 0: |
1288 | cfg = mode_0_cfg; | 1286 | cfg = mode_0_cfg; |
1289 | n = ARRAY_SIZE(mode_0_cfg); | 1287 | n = ARRAY_SIZE(mode_0_cfg); |
1290 | break; | 1288 | break; |
1291 | case 1: | 1289 | case 1: |
1292 | cfg = mode_1_cfg; | 1290 | cfg = mode_1_cfg; |
1293 | n = ARRAY_SIZE(mode_1_cfg); | 1291 | n = ARRAY_SIZE(mode_1_cfg); |
1294 | break; | 1292 | break; |
1295 | case 2: | 1293 | case 2: |
1296 | cfg = mode_2_cfg; | 1294 | cfg = mode_2_cfg; |
1297 | n = ARRAY_SIZE(mode_2_cfg); | 1295 | n = ARRAY_SIZE(mode_2_cfg); |
1298 | break; | 1296 | break; |
1299 | case 3: | 1297 | case 3: |
1300 | cfg = mode_3_cfg; | 1298 | cfg = mode_3_cfg; |
1301 | n = ARRAY_SIZE(mode_3_cfg); | 1299 | n = ARRAY_SIZE(mode_3_cfg); |
1302 | break; | 1300 | break; |
1303 | case 4: | 1301 | case 4: |
1304 | cfg = mode_4_cfg; | 1302 | cfg = mode_4_cfg; |
1305 | n = ARRAY_SIZE(mode_4_cfg); | 1303 | n = ARRAY_SIZE(mode_4_cfg); |
1306 | break; | 1304 | break; |
1307 | case 5: | 1305 | case 5: |
1308 | cfg = mode_5_cfg; | 1306 | cfg = mode_5_cfg; |
1309 | n = ARRAY_SIZE(mode_5_cfg); | 1307 | n = ARRAY_SIZE(mode_5_cfg); |
1310 | break; | 1308 | break; |
1311 | } | 1309 | } |
1312 | 1310 | ||
1313 | pr_debug("%s: setup fifo_mode %d\n", musb_driver_name, fifo_mode); | 1311 | pr_debug("%s: setup fifo_mode %d\n", musb_driver_name, fifo_mode); |
1314 | 1312 | ||
1315 | done: | 1313 | done: |
1316 | offset = fifo_setup(musb, hw_ep, &ep0_cfg, 0); | 1314 | offset = fifo_setup(musb, hw_ep, &ep0_cfg, 0); |
1317 | /* assert(offset > 0) */ | 1315 | /* assert(offset > 0) */ |
1318 | 1316 | ||
1319 | /* NOTE: for RTL versions >= 1.400 EPINFO and RAMINFO would | 1317 | /* NOTE: for RTL versions >= 1.400 EPINFO and RAMINFO would |
1320 | * be better than static musb->config->num_eps and DYN_FIFO_SIZE... | 1318 | * be better than static musb->config->num_eps and DYN_FIFO_SIZE... |
1321 | */ | 1319 | */ |
1322 | 1320 | ||
1323 | for (i = 0; i < n; i++) { | 1321 | for (i = 0; i < n; i++) { |
1324 | u8 epn = cfg->hw_ep_num; | 1322 | u8 epn = cfg->hw_ep_num; |
1325 | 1323 | ||
1326 | if (epn >= musb->config->num_eps) { | 1324 | if (epn >= musb->config->num_eps) { |
1327 | pr_debug("%s: invalid ep %d\n", | 1325 | pr_debug("%s: invalid ep %d\n", |
1328 | musb_driver_name, epn); | 1326 | musb_driver_name, epn); |
1329 | return -EINVAL; | 1327 | return -EINVAL; |
1330 | } | 1328 | } |
1331 | offset = fifo_setup(musb, hw_ep + epn, cfg++, offset); | 1329 | offset = fifo_setup(musb, hw_ep + epn, cfg++, offset); |
1332 | if (offset < 0) { | 1330 | if (offset < 0) { |
1333 | pr_debug("%s: mem overrun, ep %d\n", | 1331 | pr_debug("%s: mem overrun, ep %d\n", |
1334 | musb_driver_name, epn); | 1332 | musb_driver_name, epn); |
1335 | return -EINVAL; | 1333 | return -EINVAL; |
1336 | } | 1334 | } |
1337 | epn++; | 1335 | epn++; |
1338 | musb->nr_endpoints = max(epn, musb->nr_endpoints); | 1336 | musb->nr_endpoints = max(epn, musb->nr_endpoints); |
1339 | } | 1337 | } |
1340 | 1338 | ||
1341 | pr_debug("%s: %d/%d max ep, %d/%d memory\n", musb_driver_name, n + 1, | 1339 | pr_debug("%s: %d/%d max ep, %d/%d memory\n", musb_driver_name, n + 1, |
1342 | musb->config->num_eps * 2 - 1, offset, | 1340 | musb->config->num_eps * 2 - 1, offset, |
1343 | (1 << (musb->config->ram_bits + 2))); | 1341 | (1 << (musb->config->ram_bits + 2))); |
1344 | 1342 | ||
1345 | if (!musb->bulk_ep) { | 1343 | if (!musb->bulk_ep) { |
1346 | pr_debug("%s: missing bulk\n", musb_driver_name); | 1344 | pr_debug("%s: missing bulk\n", musb_driver_name); |
1347 | return -EINVAL; | 1345 | return -EINVAL; |
1348 | } | 1346 | } |
1349 | 1347 | ||
1350 | return 0; | 1348 | return 0; |
1351 | } | 1349 | } |
1352 | 1350 | ||
1353 | 1351 | ||
1354 | /* | 1352 | /* |
1355 | * ep_config_from_hw - when MUSB_C_DYNFIFO_DEF is false | 1353 | * ep_config_from_hw - when MUSB_C_DYNFIFO_DEF is false |
1356 | * @param musb the controller | 1354 | * @param musb the controller |
1357 | */ | 1355 | */ |
1358 | static int __devinit ep_config_from_hw(struct musb *musb) | 1356 | static int __devinit ep_config_from_hw(struct musb *musb) |
1359 | { | 1357 | { |
1360 | u8 epnum = 0; | 1358 | u8 epnum = 0; |
1361 | struct musb_hw_ep *hw_ep; | 1359 | struct musb_hw_ep *hw_ep; |
1362 | void *mbase = musb->mregs; | 1360 | void *mbase = musb->mregs; |
1363 | int ret = 0; | 1361 | int ret = 0; |
1364 | 1362 | ||
1365 | dev_dbg(musb->controller, "<== static silicon ep config\n"); | 1363 | dev_dbg(musb->controller, "<== static silicon ep config\n"); |
1366 | 1364 | ||
1367 | /* FIXME pick up ep0 maxpacket size */ | 1365 | /* FIXME pick up ep0 maxpacket size */ |
1368 | 1366 | ||
1369 | for (epnum = 1; epnum < musb->config->num_eps; epnum++) { | 1367 | for (epnum = 1; epnum < musb->config->num_eps; epnum++) { |
1370 | musb_ep_select(mbase, epnum); | 1368 | musb_ep_select(mbase, epnum); |
1371 | hw_ep = musb->endpoints + epnum; | 1369 | hw_ep = musb->endpoints + epnum; |
1372 | 1370 | ||
1373 | ret = musb_read_fifosize(musb, hw_ep, epnum); | 1371 | ret = musb_read_fifosize(musb, hw_ep, epnum); |
1374 | if (ret < 0) | 1372 | if (ret < 0) |
1375 | break; | 1373 | break; |
1376 | 1374 | ||
1377 | /* FIXME set up hw_ep->{rx,tx}_double_buffered */ | 1375 | /* FIXME set up hw_ep->{rx,tx}_double_buffered */ |
1378 | 1376 | ||
1379 | /* pick an RX/TX endpoint for bulk */ | 1377 | /* pick an RX/TX endpoint for bulk */ |
1380 | if (hw_ep->max_packet_sz_tx < 512 | 1378 | if (hw_ep->max_packet_sz_tx < 512 |
1381 | || hw_ep->max_packet_sz_rx < 512) | 1379 | || hw_ep->max_packet_sz_rx < 512) |
1382 | continue; | 1380 | continue; |
1383 | 1381 | ||
1384 | /* REVISIT: this algorithm is lazy, we should at least | 1382 | /* REVISIT: this algorithm is lazy, we should at least |
1385 | * try to pick a double buffered endpoint. | 1383 | * try to pick a double buffered endpoint. |
1386 | */ | 1384 | */ |
1387 | if (musb->bulk_ep) | 1385 | if (musb->bulk_ep) |
1388 | continue; | 1386 | continue; |
1389 | musb->bulk_ep = hw_ep; | 1387 | musb->bulk_ep = hw_ep; |
1390 | } | 1388 | } |
1391 | 1389 | ||
1392 | if (!musb->bulk_ep) { | 1390 | if (!musb->bulk_ep) { |
1393 | pr_debug("%s: missing bulk\n", musb_driver_name); | 1391 | pr_debug("%s: missing bulk\n", musb_driver_name); |
1394 | return -EINVAL; | 1392 | return -EINVAL; |
1395 | } | 1393 | } |
1396 | 1394 | ||
1397 | return 0; | 1395 | return 0; |
1398 | } | 1396 | } |
1399 | 1397 | ||
1400 | enum { MUSB_CONTROLLER_MHDRC, MUSB_CONTROLLER_HDRC, }; | 1398 | enum { MUSB_CONTROLLER_MHDRC, MUSB_CONTROLLER_HDRC, }; |
1401 | 1399 | ||
1402 | /* Initialize MUSB (M)HDRC part of the USB hardware subsystem; | 1400 | /* Initialize MUSB (M)HDRC part of the USB hardware subsystem; |
1403 | * configure endpoints, or take their config from silicon | 1401 | * configure endpoints, or take their config from silicon |
1404 | */ | 1402 | */ |
1405 | static int __devinit musb_core_init(u16 musb_type, struct musb *musb) | 1403 | static int __devinit musb_core_init(u16 musb_type, struct musb *musb) |
1406 | { | 1404 | { |
1407 | u8 reg; | 1405 | u8 reg; |
1408 | char *type; | 1406 | char *type; |
1409 | char aInfo[90], aRevision[32], aDate[12]; | 1407 | char aInfo[90], aRevision[32], aDate[12]; |
1410 | void __iomem *mbase = musb->mregs; | 1408 | void __iomem *mbase = musb->mregs; |
1411 | int status = 0; | 1409 | int status = 0; |
1412 | int i; | 1410 | int i; |
1413 | 1411 | ||
1414 | /* log core options (read using indexed model) */ | 1412 | /* log core options (read using indexed model) */ |
1415 | reg = musb_read_configdata(mbase); | 1413 | reg = musb_read_configdata(mbase); |
1416 | 1414 | ||
1417 | strcpy(aInfo, (reg & MUSB_CONFIGDATA_UTMIDW) ? "UTMI-16" : "UTMI-8"); | 1415 | strcpy(aInfo, (reg & MUSB_CONFIGDATA_UTMIDW) ? "UTMI-16" : "UTMI-8"); |
1418 | if (reg & MUSB_CONFIGDATA_DYNFIFO) { | 1416 | if (reg & MUSB_CONFIGDATA_DYNFIFO) { |
1419 | strcat(aInfo, ", dyn FIFOs"); | 1417 | strcat(aInfo, ", dyn FIFOs"); |
1420 | musb->dyn_fifo = true; | 1418 | musb->dyn_fifo = true; |
1421 | } | 1419 | } |
1422 | #ifndef CONFIG_MUSB_DISABLE_BULK_COMBINE_SPLIT | 1420 | #ifndef CONFIG_MUSB_DISABLE_BULK_COMBINE_SPLIT |
1423 | if (reg & MUSB_CONFIGDATA_MPRXE) { | 1421 | if (reg & MUSB_CONFIGDATA_MPRXE) { |
1424 | strcat(aInfo, ", bulk combine"); | 1422 | strcat(aInfo, ", bulk combine"); |
1425 | musb->bulk_combine = true; | 1423 | musb->bulk_combine = true; |
1426 | } | 1424 | } |
1427 | if (reg & MUSB_CONFIGDATA_MPTXE) { | 1425 | if (reg & MUSB_CONFIGDATA_MPTXE) { |
1428 | strcat(aInfo, ", bulk split"); | 1426 | strcat(aInfo, ", bulk split"); |
1429 | musb->bulk_split = true; | 1427 | musb->bulk_split = true; |
1430 | } | 1428 | } |
1431 | #else | 1429 | #else |
1432 | musb->bulk_combine = false; | 1430 | musb->bulk_combine = false; |
1433 | musb->bulk_split = false; | 1431 | musb->bulk_split = false; |
1434 | #endif | 1432 | #endif |
1435 | if (reg & MUSB_CONFIGDATA_HBRXE) { | 1433 | if (reg & MUSB_CONFIGDATA_HBRXE) { |
1436 | strcat(aInfo, ", HB-ISO Rx"); | 1434 | strcat(aInfo, ", HB-ISO Rx"); |
1437 | musb->hb_iso_rx = true; | 1435 | musb->hb_iso_rx = true; |
1438 | } | 1436 | } |
1439 | if (reg & MUSB_CONFIGDATA_HBTXE) { | 1437 | if (reg & MUSB_CONFIGDATA_HBTXE) { |
1440 | strcat(aInfo, ", HB-ISO Tx"); | 1438 | strcat(aInfo, ", HB-ISO Tx"); |
1441 | musb->hb_iso_tx = true; | 1439 | musb->hb_iso_tx = true; |
1442 | } | 1440 | } |
1443 | if (reg & MUSB_CONFIGDATA_SOFTCONE) | 1441 | if (reg & MUSB_CONFIGDATA_SOFTCONE) |
1444 | strcat(aInfo, ", SoftConn"); | 1442 | strcat(aInfo, ", SoftConn"); |
1445 | 1443 | ||
1446 | pr_debug("%s:ConfigData=0x%02x (%s)\n", musb_driver_name, reg, aInfo); | 1444 | pr_debug("%s:ConfigData=0x%02x (%s)\n", musb_driver_name, reg, aInfo); |
1447 | 1445 | ||
1448 | aDate[0] = 0; | 1446 | aDate[0] = 0; |
1449 | if (MUSB_CONTROLLER_MHDRC == musb_type) { | 1447 | if (MUSB_CONTROLLER_MHDRC == musb_type) { |
1450 | musb->is_multipoint = 1; | 1448 | musb->is_multipoint = 1; |
1451 | type = "M"; | 1449 | type = "M"; |
1452 | } else { | 1450 | } else { |
1453 | musb->is_multipoint = 0; | 1451 | musb->is_multipoint = 0; |
1454 | type = ""; | 1452 | type = ""; |
1455 | #ifndef CONFIG_USB_OTG_BLACKLIST_HUB | 1453 | #ifndef CONFIG_USB_OTG_BLACKLIST_HUB |
1456 | printk(KERN_ERR | 1454 | printk(KERN_ERR |
1457 | "%s: kernel must blacklist external hubs\n", | 1455 | "%s: kernel must blacklist external hubs\n", |
1458 | musb_driver_name); | 1456 | musb_driver_name); |
1459 | #endif | 1457 | #endif |
1460 | } | 1458 | } |
1461 | 1459 | ||
1462 | /* log release info */ | 1460 | /* log release info */ |
1463 | musb->hwvers = musb_read_hwvers(mbase); | 1461 | musb->hwvers = musb_read_hwvers(mbase); |
1464 | snprintf(aRevision, 32, "%d.%d%s", MUSB_HWVERS_MAJOR(musb->hwvers), | 1462 | snprintf(aRevision, 32, "%d.%d%s", MUSB_HWVERS_MAJOR(musb->hwvers), |
1465 | MUSB_HWVERS_MINOR(musb->hwvers), | 1463 | MUSB_HWVERS_MINOR(musb->hwvers), |
1466 | (musb->hwvers & MUSB_HWVERS_RC) ? "RC" : ""); | 1464 | (musb->hwvers & MUSB_HWVERS_RC) ? "RC" : ""); |
1467 | pr_debug("%s: %sHDRC RTL version %s %s\n", musb_driver_name, type, | 1465 | pr_debug("%s: %sHDRC RTL version %s %s\n", musb_driver_name, type, |
1468 | aRevision, aDate); | 1466 | aRevision, aDate); |
1469 | 1467 | ||
1470 | /* configure ep0 */ | 1468 | /* configure ep0 */ |
1471 | musb_configure_ep0(musb); | 1469 | musb_configure_ep0(musb); |
1472 | 1470 | ||
1473 | /* discover endpoint configuration */ | 1471 | /* discover endpoint configuration */ |
1474 | musb->nr_endpoints = 1; | 1472 | musb->nr_endpoints = 1; |
1475 | musb->epmask = 1; | 1473 | musb->epmask = 1; |
1476 | 1474 | ||
1477 | if (musb->dyn_fifo) | 1475 | if (musb->dyn_fifo) |
1478 | status = ep_config_from_table(musb); | 1476 | status = ep_config_from_table(musb); |
1479 | else | 1477 | else |
1480 | status = ep_config_from_hw(musb); | 1478 | status = ep_config_from_hw(musb); |
1481 | 1479 | ||
1482 | if (status < 0) | 1480 | if (status < 0) |
1483 | return status; | 1481 | return status; |
1484 | 1482 | ||
1485 | /* finish init, and print endpoint config */ | 1483 | /* finish init, and print endpoint config */ |
1486 | for (i = 0; i < musb->nr_endpoints; i++) { | 1484 | for (i = 0; i < musb->nr_endpoints; i++) { |
1487 | struct musb_hw_ep *hw_ep = musb->endpoints + i; | 1485 | struct musb_hw_ep *hw_ep = musb->endpoints + i; |
1488 | 1486 | ||
1489 | hw_ep->fifo = MUSB_FIFO_OFFSET(i) + mbase; | 1487 | hw_ep->fifo = MUSB_FIFO_OFFSET(i) + mbase; |
1490 | #if defined(CONFIG_USB_MUSB_TUSB6010) || defined (CONFIG_USB_MUSB_TUSB6010_MODULE) | 1488 | #if defined(CONFIG_USB_MUSB_TUSB6010) || defined (CONFIG_USB_MUSB_TUSB6010_MODULE) |
1491 | hw_ep->fifo_async = musb->async + 0x400 + MUSB_FIFO_OFFSET(i); | 1489 | hw_ep->fifo_async = musb->async + 0x400 + MUSB_FIFO_OFFSET(i); |
1492 | hw_ep->fifo_sync = musb->sync + 0x400 + MUSB_FIFO_OFFSET(i); | 1490 | hw_ep->fifo_sync = musb->sync + 0x400 + MUSB_FIFO_OFFSET(i); |
1493 | hw_ep->fifo_sync_va = | 1491 | hw_ep->fifo_sync_va = |
1494 | musb->sync_va + 0x400 + MUSB_FIFO_OFFSET(i); | 1492 | musb->sync_va + 0x400 + MUSB_FIFO_OFFSET(i); |
1495 | 1493 | ||
1496 | if (i == 0) | 1494 | if (i == 0) |
1497 | hw_ep->conf = mbase - 0x400 + TUSB_EP0_CONF; | 1495 | hw_ep->conf = mbase - 0x400 + TUSB_EP0_CONF; |
1498 | else | 1496 | else |
1499 | hw_ep->conf = mbase + 0x400 + (((i - 1) & 0xf) << 2); | 1497 | hw_ep->conf = mbase + 0x400 + (((i - 1) & 0xf) << 2); |
1500 | #endif | 1498 | #endif |
1501 | 1499 | ||
1502 | hw_ep->regs = MUSB_EP_OFFSET(i, 0) + mbase; | 1500 | hw_ep->regs = MUSB_EP_OFFSET(i, 0) + mbase; |
1503 | hw_ep->target_regs = musb_read_target_reg_base(i, mbase); | 1501 | hw_ep->target_regs = musb_read_target_reg_base(i, mbase); |
1504 | hw_ep->rx_reinit = 1; | 1502 | hw_ep->rx_reinit = 1; |
1505 | hw_ep->tx_reinit = 1; | 1503 | hw_ep->tx_reinit = 1; |
1506 | 1504 | ||
1507 | if (hw_ep->max_packet_sz_tx) { | 1505 | if (hw_ep->max_packet_sz_tx) { |
1508 | dev_dbg(musb->controller, | 1506 | dev_dbg(musb->controller, |
1509 | "%s: hw_ep %d%s, %smax %d\n", | 1507 | "%s: hw_ep %d%s, %smax %d\n", |
1510 | musb_driver_name, i, | 1508 | musb_driver_name, i, |
1511 | hw_ep->is_shared_fifo ? "shared" : "tx", | 1509 | hw_ep->is_shared_fifo ? "shared" : "tx", |
1512 | hw_ep->tx_double_buffered | 1510 | hw_ep->tx_double_buffered |
1513 | ? "doublebuffer, " : "", | 1511 | ? "doublebuffer, " : "", |
1514 | hw_ep->max_packet_sz_tx); | 1512 | hw_ep->max_packet_sz_tx); |
1515 | } | 1513 | } |
1516 | if (hw_ep->max_packet_sz_rx && !hw_ep->is_shared_fifo) { | 1514 | if (hw_ep->max_packet_sz_rx && !hw_ep->is_shared_fifo) { |
1517 | dev_dbg(musb->controller, | 1515 | dev_dbg(musb->controller, |
1518 | "%s: hw_ep %d%s, %smax %d\n", | 1516 | "%s: hw_ep %d%s, %smax %d\n", |
1519 | musb_driver_name, i, | 1517 | musb_driver_name, i, |
1520 | "rx", | 1518 | "rx", |
1521 | hw_ep->rx_double_buffered | 1519 | hw_ep->rx_double_buffered |
1522 | ? "doublebuffer, " : "", | 1520 | ? "doublebuffer, " : "", |
1523 | hw_ep->max_packet_sz_rx); | 1521 | hw_ep->max_packet_sz_rx); |
1524 | } | 1522 | } |
1525 | if (!(hw_ep->max_packet_sz_tx || hw_ep->max_packet_sz_rx)) | 1523 | if (!(hw_ep->max_packet_sz_tx || hw_ep->max_packet_sz_rx)) |
1526 | dev_dbg(musb->controller, "hw_ep %d not configured\n", i); | 1524 | dev_dbg(musb->controller, "hw_ep %d not configured\n", i); |
1527 | } | 1525 | } |
1528 | 1526 | ||
1529 | return 0; | 1527 | return 0; |
1530 | } | 1528 | } |
1531 | 1529 | ||
1532 | /*-------------------------------------------------------------------------*/ | 1530 | /*-------------------------------------------------------------------------*/ |
1533 | 1531 | ||
1534 | #if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430) || \ | 1532 | #if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430) || \ |
1535 | defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500) | 1533 | defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500) |
1536 | 1534 | ||
1537 | static irqreturn_t generic_interrupt(int irq, void *__hci) | 1535 | static irqreturn_t generic_interrupt(int irq, void *__hci) |
1538 | { | 1536 | { |
1539 | unsigned long flags; | 1537 | unsigned long flags; |
1540 | irqreturn_t retval = IRQ_NONE; | 1538 | irqreturn_t retval = IRQ_NONE; |
1541 | struct musb *musb = __hci; | 1539 | struct musb *musb = __hci; |
1542 | 1540 | ||
1543 | spin_lock_irqsave(&musb->lock, flags); | 1541 | spin_lock_irqsave(&musb->lock, flags); |
1544 | 1542 | ||
1545 | musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB); | 1543 | musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB); |
1546 | musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX); | 1544 | musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX); |
1547 | musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX); | 1545 | musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX); |
1548 | 1546 | ||
1549 | if (musb->int_usb || musb->int_tx || musb->int_rx) | 1547 | if (musb->int_usb || musb->int_tx || musb->int_rx) |
1550 | retval = musb_interrupt(musb); | 1548 | retval = musb_interrupt(musb); |
1551 | 1549 | ||
1552 | spin_unlock_irqrestore(&musb->lock, flags); | 1550 | spin_unlock_irqrestore(&musb->lock, flags); |
1553 | 1551 | ||
1554 | return retval; | 1552 | return retval; |
1555 | } | 1553 | } |
1556 | 1554 | ||
1557 | #else | 1555 | #else |
1558 | #define generic_interrupt NULL | 1556 | #define generic_interrupt NULL |
1559 | #endif | 1557 | #endif |
1560 | 1558 | ||
1561 | /* | 1559 | /* |
1562 | * handle all the irqs defined by the HDRC core. for now we expect: other | 1560 | * handle all the irqs defined by the HDRC core. for now we expect: other |
1563 | * irq sources (phy, dma, etc) will be handled first, musb->int_* values | 1561 | * irq sources (phy, dma, etc) will be handled first, musb->int_* values |
1564 | * will be assigned, and the irq will already have been acked. | 1562 | * will be assigned, and the irq will already have been acked. |
1565 | * | 1563 | * |
1566 | * called in irq context with spinlock held, irqs blocked | 1564 | * called in irq context with spinlock held, irqs blocked |
1567 | */ | 1565 | */ |
1568 | irqreturn_t musb_interrupt(struct musb *musb) | 1566 | irqreturn_t musb_interrupt(struct musb *musb) |
1569 | { | 1567 | { |
1570 | irqreturn_t retval = IRQ_NONE; | 1568 | irqreturn_t retval = IRQ_NONE; |
1571 | u8 devctl, power; | 1569 | u8 devctl, power; |
1572 | int ep_num; | 1570 | int ep_num; |
1573 | u32 reg; | 1571 | u32 reg; |
1574 | 1572 | ||
1575 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | 1573 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); |
1576 | power = musb_readb(musb->mregs, MUSB_POWER); | 1574 | power = musb_readb(musb->mregs, MUSB_POWER); |
1577 | 1575 | ||
1578 | dev_dbg(musb->controller, "** IRQ %s usb%04x tx%04x rx%04x\n", | 1576 | dev_dbg(musb->controller, "** IRQ %s usb%04x tx%04x rx%04x\n", |
1579 | (devctl & MUSB_DEVCTL_HM) ? "host" : "peripheral", | 1577 | (devctl & MUSB_DEVCTL_HM) ? "host" : "peripheral", |
1580 | musb->int_usb, musb->int_tx, musb->int_rx); | 1578 | musb->int_usb, musb->int_tx, musb->int_rx); |
1581 | 1579 | ||
1582 | /* the core can interrupt us for multiple reasons; docs have | 1580 | /* the core can interrupt us for multiple reasons; docs have |
1583 | * a generic interrupt flowchart to follow | 1581 | * a generic interrupt flowchart to follow |
1584 | */ | 1582 | */ |
1585 | if (musb->int_usb) | 1583 | if (musb->int_usb) |
1586 | retval |= musb_stage0_irq(musb, musb->int_usb, | 1584 | retval |= musb_stage0_irq(musb, musb->int_usb, |
1587 | devctl, power); | 1585 | devctl, power); |
1588 | 1586 | ||
1589 | /* "stage 1" is handling endpoint irqs */ | 1587 | /* "stage 1" is handling endpoint irqs */ |
1590 | 1588 | ||
1591 | /* handle endpoint 0 first */ | 1589 | /* handle endpoint 0 first */ |
1592 | if (musb->int_tx & 1) { | 1590 | if (musb->int_tx & 1) { |
1593 | if (devctl & MUSB_DEVCTL_HM) { | 1591 | if (devctl & MUSB_DEVCTL_HM) { |
1594 | if (is_host_capable()) | 1592 | if (is_host_capable()) |
1595 | retval |= musb_h_ep0_irq(musb); | 1593 | retval |= musb_h_ep0_irq(musb); |
1596 | } else { | 1594 | } else { |
1597 | if (is_peripheral_capable()) | 1595 | if (is_peripheral_capable()) |
1598 | retval |= musb_g_ep0_irq(musb); | 1596 | retval |= musb_g_ep0_irq(musb); |
1599 | } | 1597 | } |
1600 | } | 1598 | } |
1601 | 1599 | ||
1602 | /* RX on endpoints 1-15 */ | 1600 | /* RX on endpoints 1-15 */ |
1603 | reg = musb->int_rx >> 1; | 1601 | reg = musb->int_rx >> 1; |
1604 | ep_num = 1; | 1602 | ep_num = 1; |
1605 | while (reg) { | 1603 | while (reg) { |
1606 | if (reg & 1) { | 1604 | if (reg & 1) { |
1607 | /* musb_ep_select(musb->mregs, ep_num); */ | 1605 | /* musb_ep_select(musb->mregs, ep_num); */ |
1608 | /* REVISIT just retval = ep->rx_irq(...) */ | 1606 | /* REVISIT just retval = ep->rx_irq(...) */ |
1609 | retval = IRQ_HANDLED; | 1607 | retval = IRQ_HANDLED; |
1610 | if (devctl & MUSB_DEVCTL_HM) { | 1608 | if (devctl & MUSB_DEVCTL_HM) { |
1611 | if (is_host_capable()) | 1609 | if (is_host_capable()) |
1612 | musb_host_rx(musb, ep_num); | 1610 | musb_host_rx(musb, ep_num); |
1613 | } else { | 1611 | } else { |
1614 | if (is_peripheral_capable()) | 1612 | if (is_peripheral_capable()) |
1615 | musb_g_rx(musb, ep_num); | 1613 | musb_g_rx(musb, ep_num); |
1616 | } | 1614 | } |
1617 | } | 1615 | } |
1618 | 1616 | ||
1619 | reg >>= 1; | 1617 | reg >>= 1; |
1620 | ep_num++; | 1618 | ep_num++; |
1621 | } | 1619 | } |
1622 | 1620 | ||
1623 | /* TX on endpoints 1-15 */ | 1621 | /* TX on endpoints 1-15 */ |
1624 | reg = musb->int_tx >> 1; | 1622 | reg = musb->int_tx >> 1; |
1625 | ep_num = 1; | 1623 | ep_num = 1; |
1626 | while (reg) { | 1624 | while (reg) { |
1627 | if (reg & 1) { | 1625 | if (reg & 1) { |
1628 | /* musb_ep_select(musb->mregs, ep_num); */ | 1626 | /* musb_ep_select(musb->mregs, ep_num); */ |
1629 | /* REVISIT just retval |= ep->tx_irq(...) */ | 1627 | /* REVISIT just retval |= ep->tx_irq(...) */ |
1630 | retval = IRQ_HANDLED; | 1628 | retval = IRQ_HANDLED; |
1631 | if (devctl & MUSB_DEVCTL_HM) { | 1629 | if (devctl & MUSB_DEVCTL_HM) { |
1632 | if (is_host_capable()) | 1630 | if (is_host_capable()) |
1633 | musb_host_tx(musb, ep_num); | 1631 | musb_host_tx(musb, ep_num); |
1634 | } else { | 1632 | } else { |
1635 | if (is_peripheral_capable()) | 1633 | if (is_peripheral_capable()) |
1636 | musb_g_tx(musb, ep_num); | 1634 | musb_g_tx(musb, ep_num); |
1637 | } | 1635 | } |
1638 | } | 1636 | } |
1639 | reg >>= 1; | 1637 | reg >>= 1; |
1640 | ep_num++; | 1638 | ep_num++; |
1641 | } | 1639 | } |
1642 | 1640 | ||
1643 | return retval; | 1641 | return retval; |
1644 | } | 1642 | } |
1645 | EXPORT_SYMBOL_GPL(musb_interrupt); | 1643 | EXPORT_SYMBOL_GPL(musb_interrupt); |
1646 | 1644 | ||
1647 | #ifndef CONFIG_MUSB_PIO_ONLY | 1645 | #ifndef CONFIG_MUSB_PIO_ONLY |
1648 | static bool __devinitdata use_dma = 1; | 1646 | static bool __devinitdata use_dma = 1; |
1649 | 1647 | ||
1650 | /* "modprobe ... use_dma=0" etc */ | 1648 | /* "modprobe ... use_dma=0" etc */ |
1651 | module_param(use_dma, bool, 0); | 1649 | module_param(use_dma, bool, 0); |
1652 | MODULE_PARM_DESC(use_dma, "enable/disable use of DMA"); | 1650 | MODULE_PARM_DESC(use_dma, "enable/disable use of DMA"); |
1653 | 1651 | ||
1654 | void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit) | 1652 | void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit) |
1655 | { | 1653 | { |
1656 | u8 devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | 1654 | u8 devctl = musb_readb(musb->mregs, MUSB_DEVCTL); |
1657 | 1655 | ||
1658 | /* called with controller lock already held */ | 1656 | /* called with controller lock already held */ |
1659 | 1657 | ||
1660 | if (!epnum) { | 1658 | if (!epnum) { |
1661 | #ifndef CONFIG_USB_TUSB_OMAP_DMA | 1659 | #ifndef CONFIG_USB_TUSB_OMAP_DMA |
1662 | if (!is_cppi_enabled()) { | 1660 | if (!is_cppi_enabled()) { |
1663 | /* endpoint 0 */ | 1661 | /* endpoint 0 */ |
1664 | if (devctl & MUSB_DEVCTL_HM) | 1662 | if (devctl & MUSB_DEVCTL_HM) |
1665 | musb_h_ep0_irq(musb); | 1663 | musb_h_ep0_irq(musb); |
1666 | else | 1664 | else |
1667 | musb_g_ep0_irq(musb); | 1665 | musb_g_ep0_irq(musb); |
1668 | } | 1666 | } |
1669 | #endif | 1667 | #endif |
1670 | } else { | 1668 | } else { |
1671 | /* endpoints 1..15 */ | 1669 | /* endpoints 1..15 */ |
1672 | if (transmit) { | 1670 | if (transmit) { |
1673 | if (devctl & MUSB_DEVCTL_HM) { | 1671 | if (devctl & MUSB_DEVCTL_HM) { |
1674 | if (is_host_capable()) | 1672 | if (is_host_capable()) |
1675 | musb_host_tx(musb, epnum); | 1673 | musb_host_tx(musb, epnum); |
1676 | } else { | 1674 | } else { |
1677 | if (is_peripheral_capable()) | 1675 | if (is_peripheral_capable()) |
1678 | musb_g_tx(musb, epnum); | 1676 | musb_g_tx(musb, epnum); |
1679 | } | 1677 | } |
1680 | } else { | 1678 | } else { |
1681 | /* receive */ | 1679 | /* receive */ |
1682 | if (devctl & MUSB_DEVCTL_HM) { | 1680 | if (devctl & MUSB_DEVCTL_HM) { |
1683 | if (is_host_capable()) | 1681 | if (is_host_capable()) |
1684 | musb_host_rx(musb, epnum); | 1682 | musb_host_rx(musb, epnum); |
1685 | } else { | 1683 | } else { |
1686 | if (is_peripheral_capable()) | 1684 | if (is_peripheral_capable()) |
1687 | musb_g_rx(musb, epnum); | 1685 | musb_g_rx(musb, epnum); |
1688 | } | 1686 | } |
1689 | } | 1687 | } |
1690 | } | 1688 | } |
1691 | } | 1689 | } |
1692 | EXPORT_SYMBOL_GPL(musb_dma_completion); | 1690 | EXPORT_SYMBOL_GPL(musb_dma_completion); |
1693 | 1691 | ||
1694 | #else | 1692 | #else |
1695 | #define use_dma 0 | 1693 | #define use_dma 0 |
1696 | #endif | 1694 | #endif |
1697 | 1695 | ||
1698 | /*-------------------------------------------------------------------------*/ | 1696 | /*-------------------------------------------------------------------------*/ |
1699 | 1697 | ||
1700 | #ifdef CONFIG_SYSFS | 1698 | #ifdef CONFIG_SYSFS |
1701 | 1699 | ||
1702 | static ssize_t | 1700 | static ssize_t |
1703 | musb_mode_show(struct device *dev, struct device_attribute *attr, char *buf) | 1701 | musb_mode_show(struct device *dev, struct device_attribute *attr, char *buf) |
1704 | { | 1702 | { |
1705 | struct musb *musb = dev_to_musb(dev); | 1703 | struct musb *musb = dev_to_musb(dev); |
1706 | unsigned long flags; | 1704 | unsigned long flags; |
1707 | int ret = -EINVAL; | 1705 | int ret = -EINVAL; |
1708 | 1706 | ||
1709 | spin_lock_irqsave(&musb->lock, flags); | 1707 | spin_lock_irqsave(&musb->lock, flags); |
1710 | ret = sprintf(buf, "%s\n", otg_state_string(musb->xceiv->state)); | 1708 | ret = sprintf(buf, "%s\n", otg_state_string(musb->xceiv->state)); |
1711 | spin_unlock_irqrestore(&musb->lock, flags); | 1709 | spin_unlock_irqrestore(&musb->lock, flags); |
1712 | 1710 | ||
1713 | return ret; | 1711 | return ret; |
1714 | } | 1712 | } |
1715 | 1713 | ||
1716 | static ssize_t | 1714 | static ssize_t |
1717 | musb_mode_store(struct device *dev, struct device_attribute *attr, | 1715 | musb_mode_store(struct device *dev, struct device_attribute *attr, |
1718 | const char *buf, size_t n) | 1716 | const char *buf, size_t n) |
1719 | { | 1717 | { |
1720 | struct musb *musb = dev_to_musb(dev); | 1718 | struct musb *musb = dev_to_musb(dev); |
1721 | unsigned long flags; | 1719 | unsigned long flags; |
1722 | int status; | 1720 | int status; |
1723 | 1721 | ||
1724 | spin_lock_irqsave(&musb->lock, flags); | 1722 | spin_lock_irqsave(&musb->lock, flags); |
1725 | if (sysfs_streq(buf, "host")) | 1723 | if (sysfs_streq(buf, "host")) |
1726 | status = musb_platform_set_mode(musb, MUSB_HOST); | 1724 | status = musb_platform_set_mode(musb, MUSB_HOST); |
1727 | else if (sysfs_streq(buf, "peripheral")) | 1725 | else if (sysfs_streq(buf, "peripheral")) |
1728 | status = musb_platform_set_mode(musb, MUSB_PERIPHERAL); | 1726 | status = musb_platform_set_mode(musb, MUSB_PERIPHERAL); |
1729 | else if (sysfs_streq(buf, "otg")) | 1727 | else if (sysfs_streq(buf, "otg")) |
1730 | status = musb_platform_set_mode(musb, MUSB_OTG); | 1728 | status = musb_platform_set_mode(musb, MUSB_OTG); |
1731 | else | 1729 | else |
1732 | status = -EINVAL; | 1730 | status = -EINVAL; |
1733 | spin_unlock_irqrestore(&musb->lock, flags); | 1731 | spin_unlock_irqrestore(&musb->lock, flags); |
1734 | 1732 | ||
1735 | return (status == 0) ? n : status; | 1733 | return (status == 0) ? n : status; |
1736 | } | 1734 | } |
1737 | static DEVICE_ATTR(mode, 0644, musb_mode_show, musb_mode_store); | 1735 | static DEVICE_ATTR(mode, 0644, musb_mode_show, musb_mode_store); |
1738 | 1736 | ||
1739 | static ssize_t | 1737 | static ssize_t |
1740 | musb_vbus_store(struct device *dev, struct device_attribute *attr, | 1738 | musb_vbus_store(struct device *dev, struct device_attribute *attr, |
1741 | const char *buf, size_t n) | 1739 | const char *buf, size_t n) |
1742 | { | 1740 | { |
1743 | struct musb *musb = dev_to_musb(dev); | 1741 | struct musb *musb = dev_to_musb(dev); |
1744 | unsigned long flags; | 1742 | unsigned long flags; |
1745 | unsigned long val; | 1743 | unsigned long val; |
1746 | 1744 | ||
1747 | if (sscanf(buf, "%lu", &val) < 1) { | 1745 | if (sscanf(buf, "%lu", &val) < 1) { |
1748 | dev_err(dev, "Invalid VBUS timeout ms value\n"); | 1746 | dev_err(dev, "Invalid VBUS timeout ms value\n"); |
1749 | return -EINVAL; | 1747 | return -EINVAL; |
1750 | } | 1748 | } |
1751 | 1749 | ||
1752 | spin_lock_irqsave(&musb->lock, flags); | 1750 | spin_lock_irqsave(&musb->lock, flags); |
1753 | /* force T(a_wait_bcon) to be zero/unlimited *OR* valid */ | 1751 | /* force T(a_wait_bcon) to be zero/unlimited *OR* valid */ |
1754 | musb->a_wait_bcon = val ? max_t(int, val, OTG_TIME_A_WAIT_BCON) : 0 ; | 1752 | musb->a_wait_bcon = val ? max_t(int, val, OTG_TIME_A_WAIT_BCON) : 0 ; |
1755 | if (musb->xceiv->state == OTG_STATE_A_WAIT_BCON) | 1753 | if (musb->xceiv->state == OTG_STATE_A_WAIT_BCON) |
1756 | musb->is_active = 0; | 1754 | musb->is_active = 0; |
1757 | musb_platform_try_idle(musb, jiffies + msecs_to_jiffies(val)); | 1755 | musb_platform_try_idle(musb, jiffies + msecs_to_jiffies(val)); |
1758 | spin_unlock_irqrestore(&musb->lock, flags); | 1756 | spin_unlock_irqrestore(&musb->lock, flags); |
1759 | 1757 | ||
1760 | return n; | 1758 | return n; |
1761 | } | 1759 | } |
1762 | 1760 | ||
1763 | static ssize_t | 1761 | static ssize_t |
1764 | musb_vbus_show(struct device *dev, struct device_attribute *attr, char *buf) | 1762 | musb_vbus_show(struct device *dev, struct device_attribute *attr, char *buf) |
1765 | { | 1763 | { |
1766 | struct musb *musb = dev_to_musb(dev); | 1764 | struct musb *musb = dev_to_musb(dev); |
1767 | unsigned long flags; | 1765 | unsigned long flags; |
1768 | unsigned long val; | 1766 | unsigned long val; |
1769 | int vbus; | 1767 | int vbus; |
1770 | 1768 | ||
1771 | spin_lock_irqsave(&musb->lock, flags); | 1769 | spin_lock_irqsave(&musb->lock, flags); |
1772 | val = musb->a_wait_bcon; | 1770 | val = musb->a_wait_bcon; |
1773 | /* FIXME get_vbus_status() is normally #defined as false... | 1771 | /* FIXME get_vbus_status() is normally #defined as false... |
1774 | * and is effectively TUSB-specific. | 1772 | * and is effectively TUSB-specific. |
1775 | */ | 1773 | */ |
1776 | vbus = musb_platform_get_vbus_status(musb); | 1774 | vbus = musb_platform_get_vbus_status(musb); |
1777 | spin_unlock_irqrestore(&musb->lock, flags); | 1775 | spin_unlock_irqrestore(&musb->lock, flags); |
1778 | 1776 | ||
1779 | return sprintf(buf, "Vbus %s, timeout %lu msec\n", | 1777 | return sprintf(buf, "Vbus %s, timeout %lu msec\n", |
1780 | vbus ? "on" : "off", val); | 1778 | vbus ? "on" : "off", val); |
1781 | } | 1779 | } |
1782 | static DEVICE_ATTR(vbus, 0644, musb_vbus_show, musb_vbus_store); | 1780 | static DEVICE_ATTR(vbus, 0644, musb_vbus_show, musb_vbus_store); |
1783 | 1781 | ||
1784 | /* Gadget drivers can't know that a host is connected so they might want | 1782 | /* Gadget drivers can't know that a host is connected so they might want |
1785 | * to start SRP, but users can. This allows userspace to trigger SRP. | 1783 | * to start SRP, but users can. This allows userspace to trigger SRP. |
1786 | */ | 1784 | */ |
1787 | static ssize_t | 1785 | static ssize_t |
1788 | musb_srp_store(struct device *dev, struct device_attribute *attr, | 1786 | musb_srp_store(struct device *dev, struct device_attribute *attr, |
1789 | const char *buf, size_t n) | 1787 | const char *buf, size_t n) |
1790 | { | 1788 | { |
1791 | struct musb *musb = dev_to_musb(dev); | 1789 | struct musb *musb = dev_to_musb(dev); |
1792 | unsigned short srp; | 1790 | unsigned short srp; |
1793 | 1791 | ||
1794 | if (sscanf(buf, "%hu", &srp) != 1 | 1792 | if (sscanf(buf, "%hu", &srp) != 1 |
1795 | || (srp != 1)) { | 1793 | || (srp != 1)) { |
1796 | dev_err(dev, "SRP: Value must be 1\n"); | 1794 | dev_err(dev, "SRP: Value must be 1\n"); |
1797 | return -EINVAL; | 1795 | return -EINVAL; |
1798 | } | 1796 | } |
1799 | 1797 | ||
1800 | if (srp == 1) | 1798 | if (srp == 1) |
1801 | musb_g_wakeup(musb); | 1799 | musb_g_wakeup(musb); |
1802 | 1800 | ||
1803 | return n; | 1801 | return n; |
1804 | } | 1802 | } |
1805 | static DEVICE_ATTR(srp, 0644, NULL, musb_srp_store); | 1803 | static DEVICE_ATTR(srp, 0644, NULL, musb_srp_store); |
1806 | 1804 | ||
1807 | static struct attribute *musb_attributes[] = { | 1805 | static struct attribute *musb_attributes[] = { |
1808 | &dev_attr_mode.attr, | 1806 | &dev_attr_mode.attr, |
1809 | &dev_attr_vbus.attr, | 1807 | &dev_attr_vbus.attr, |
1810 | &dev_attr_srp.attr, | 1808 | &dev_attr_srp.attr, |
1811 | NULL | 1809 | NULL |
1812 | }; | 1810 | }; |
1813 | 1811 | ||
1814 | static const struct attribute_group musb_attr_group = { | 1812 | static const struct attribute_group musb_attr_group = { |
1815 | .attrs = musb_attributes, | 1813 | .attrs = musb_attributes, |
1816 | }; | 1814 | }; |
1817 | 1815 | ||
1818 | #endif /* sysfs */ | 1816 | #endif /* sysfs */ |
1819 | 1817 | ||
1820 | #ifndef __UBOOT__ | 1818 | #ifndef __UBOOT__ |
1821 | /* Only used to provide driver mode change events */ | 1819 | /* Only used to provide driver mode change events */ |
1822 | static void musb_irq_work(struct work_struct *data) | 1820 | static void musb_irq_work(struct work_struct *data) |
1823 | { | 1821 | { |
1824 | struct musb *musb = container_of(data, struct musb, irq_work); | 1822 | struct musb *musb = container_of(data, struct musb, irq_work); |
1825 | static int old_state; | 1823 | static int old_state; |
1826 | 1824 | ||
1827 | if (musb->xceiv->state != old_state) { | 1825 | if (musb->xceiv->state != old_state) { |
1828 | old_state = musb->xceiv->state; | 1826 | old_state = musb->xceiv->state; |
1829 | sysfs_notify(&musb->controller->kobj, NULL, "mode"); | 1827 | sysfs_notify(&musb->controller->kobj, NULL, "mode"); |
1830 | } | 1828 | } |
1831 | } | 1829 | } |
1832 | #endif | 1830 | #endif |
1833 | 1831 | ||
1834 | /* -------------------------------------------------------------------------- | 1832 | /* -------------------------------------------------------------------------- |
1835 | * Init support | 1833 | * Init support |
1836 | */ | 1834 | */ |
1837 | 1835 | ||
1838 | static struct musb *__devinit | 1836 | static struct musb *__devinit |
1839 | allocate_instance(struct device *dev, | 1837 | allocate_instance(struct device *dev, |
1840 | struct musb_hdrc_config *config, void __iomem *mbase) | 1838 | struct musb_hdrc_config *config, void __iomem *mbase) |
1841 | { | 1839 | { |
1842 | struct musb *musb; | 1840 | struct musb *musb; |
1843 | struct musb_hw_ep *ep; | 1841 | struct musb_hw_ep *ep; |
1844 | int epnum; | 1842 | int epnum; |
1845 | #ifndef __UBOOT__ | 1843 | #ifndef __UBOOT__ |
1846 | struct usb_hcd *hcd; | 1844 | struct usb_hcd *hcd; |
1847 | 1845 | ||
1848 | hcd = usb_create_hcd(&musb_hc_driver, dev, dev_name(dev)); | 1846 | hcd = usb_create_hcd(&musb_hc_driver, dev, dev_name(dev)); |
1849 | if (!hcd) | 1847 | if (!hcd) |
1850 | return NULL; | 1848 | return NULL; |
1851 | /* usbcore sets dev->driver_data to hcd, and sometimes uses that... */ | 1849 | /* usbcore sets dev->driver_data to hcd, and sometimes uses that... */ |
1852 | 1850 | ||
1853 | musb = hcd_to_musb(hcd); | 1851 | musb = hcd_to_musb(hcd); |
1854 | #else | 1852 | #else |
1855 | musb = calloc(1, sizeof(*musb)); | 1853 | musb = calloc(1, sizeof(*musb)); |
1856 | if (!musb) | 1854 | if (!musb) |
1857 | return NULL; | 1855 | return NULL; |
1858 | #endif | 1856 | #endif |
1859 | INIT_LIST_HEAD(&musb->control); | 1857 | INIT_LIST_HEAD(&musb->control); |
1860 | INIT_LIST_HEAD(&musb->in_bulk); | 1858 | INIT_LIST_HEAD(&musb->in_bulk); |
1861 | INIT_LIST_HEAD(&musb->out_bulk); | 1859 | INIT_LIST_HEAD(&musb->out_bulk); |
1862 | 1860 | ||
1863 | #ifndef __UBOOT__ | 1861 | #ifndef __UBOOT__ |
1864 | hcd->uses_new_polling = 1; | 1862 | hcd->uses_new_polling = 1; |
1865 | hcd->has_tt = 1; | 1863 | hcd->has_tt = 1; |
1866 | #endif | 1864 | #endif |
1867 | 1865 | ||
1868 | musb->vbuserr_retry = VBUSERR_RETRY_COUNT; | 1866 | musb->vbuserr_retry = VBUSERR_RETRY_COUNT; |
1869 | musb->a_wait_bcon = OTG_TIME_A_WAIT_BCON; | 1867 | musb->a_wait_bcon = OTG_TIME_A_WAIT_BCON; |
1870 | dev_set_drvdata(dev, musb); | 1868 | dev_set_drvdata(dev, musb); |
1871 | musb->mregs = mbase; | 1869 | musb->mregs = mbase; |
1872 | musb->ctrl_base = mbase; | 1870 | musb->ctrl_base = mbase; |
1873 | musb->nIrq = -ENODEV; | 1871 | musb->nIrq = -ENODEV; |
1874 | musb->config = config; | 1872 | musb->config = config; |
1875 | BUG_ON(musb->config->num_eps > MUSB_C_NUM_EPS); | 1873 | BUG_ON(musb->config->num_eps > MUSB_C_NUM_EPS); |
1876 | for (epnum = 0, ep = musb->endpoints; | 1874 | for (epnum = 0, ep = musb->endpoints; |
1877 | epnum < musb->config->num_eps; | 1875 | epnum < musb->config->num_eps; |
1878 | epnum++, ep++) { | 1876 | epnum++, ep++) { |
1879 | ep->musb = musb; | 1877 | ep->musb = musb; |
1880 | ep->epnum = epnum; | 1878 | ep->epnum = epnum; |
1881 | } | 1879 | } |
1882 | 1880 | ||
1883 | musb->controller = dev; | 1881 | musb->controller = dev; |
1884 | 1882 | ||
1885 | return musb; | 1883 | return musb; |
1886 | } | 1884 | } |
1887 | 1885 | ||
1888 | static void musb_free(struct musb *musb) | 1886 | static void musb_free(struct musb *musb) |
1889 | { | 1887 | { |
1890 | /* this has multiple entry modes. it handles fault cleanup after | 1888 | /* this has multiple entry modes. it handles fault cleanup after |
1891 | * probe(), where things may be partially set up, as well as rmmod | 1889 | * probe(), where things may be partially set up, as well as rmmod |
1892 | * cleanup after everything's been de-activated. | 1890 | * cleanup after everything's been de-activated. |
1893 | */ | 1891 | */ |
1894 | 1892 | ||
1895 | #ifdef CONFIG_SYSFS | 1893 | #ifdef CONFIG_SYSFS |
1896 | sysfs_remove_group(&musb->controller->kobj, &musb_attr_group); | 1894 | sysfs_remove_group(&musb->controller->kobj, &musb_attr_group); |
1897 | #endif | 1895 | #endif |
1898 | 1896 | ||
1899 | if (musb->nIrq >= 0) { | 1897 | if (musb->nIrq >= 0) { |
1900 | if (musb->irq_wake) | 1898 | if (musb->irq_wake) |
1901 | disable_irq_wake(musb->nIrq); | 1899 | disable_irq_wake(musb->nIrq); |
1902 | free_irq(musb->nIrq, musb); | 1900 | free_irq(musb->nIrq, musb); |
1903 | } | 1901 | } |
1904 | if (is_dma_capable() && musb->dma_controller) { | 1902 | if (is_dma_capable() && musb->dma_controller) { |
1905 | struct dma_controller *c = musb->dma_controller; | 1903 | struct dma_controller *c = musb->dma_controller; |
1906 | 1904 | ||
1907 | (void) c->stop(c); | 1905 | (void) c->stop(c); |
1908 | dma_controller_destroy(c); | 1906 | dma_controller_destroy(c); |
1909 | } | 1907 | } |
1910 | 1908 | ||
1911 | kfree(musb); | 1909 | kfree(musb); |
1912 | } | 1910 | } |
1913 | 1911 | ||
1914 | /* | 1912 | /* |
1915 | * Perform generic per-controller initialization. | 1913 | * Perform generic per-controller initialization. |
1916 | * | 1914 | * |
1917 | * @pDevice: the controller (already clocked, etc) | 1915 | * @pDevice: the controller (already clocked, etc) |
1918 | * @nIrq: irq | 1916 | * @nIrq: irq |
1919 | * @mregs: virtual address of controller registers, | 1917 | * @mregs: virtual address of controller registers, |
1920 | * not yet corrected for platform-specific offsets | 1918 | * not yet corrected for platform-specific offsets |
1921 | */ | 1919 | */ |
1922 | #ifndef __UBOOT__ | 1920 | #ifndef __UBOOT__ |
1923 | static int __devinit | 1921 | static int __devinit |
1924 | musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) | 1922 | musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) |
1925 | #else | 1923 | #else |
1926 | struct musb * | 1924 | struct musb * |
1927 | musb_init_controller(struct musb_hdrc_platform_data *plat, struct device *dev, | 1925 | musb_init_controller(struct musb_hdrc_platform_data *plat, struct device *dev, |
1928 | void *ctrl) | 1926 | void *ctrl) |
1929 | #endif | 1927 | #endif |
1930 | { | 1928 | { |
1931 | int status; | 1929 | int status; |
1932 | struct musb *musb; | 1930 | struct musb *musb; |
1933 | #ifndef __UBOOT__ | 1931 | #ifndef __UBOOT__ |
1934 | struct musb_hdrc_platform_data *plat = dev->platform_data; | 1932 | struct musb_hdrc_platform_data *plat = dev->platform_data; |
1935 | #else | 1933 | #else |
1936 | int nIrq = 0; | 1934 | int nIrq = 0; |
1937 | #endif | 1935 | #endif |
1938 | 1936 | ||
1939 | /* The driver might handle more features than the board; OK. | 1937 | /* The driver might handle more features than the board; OK. |
1940 | * Fail when the board needs a feature that's not enabled. | 1938 | * Fail when the board needs a feature that's not enabled. |
1941 | */ | 1939 | */ |
1942 | if (!plat) { | 1940 | if (!plat) { |
1943 | dev_dbg(dev, "no platform_data?\n"); | 1941 | dev_dbg(dev, "no platform_data?\n"); |
1944 | status = -ENODEV; | 1942 | status = -ENODEV; |
1945 | goto fail0; | 1943 | goto fail0; |
1946 | } | 1944 | } |
1947 | 1945 | ||
1948 | /* allocate */ | 1946 | /* allocate */ |
1949 | musb = allocate_instance(dev, plat->config, ctrl); | 1947 | musb = allocate_instance(dev, plat->config, ctrl); |
1950 | if (!musb) { | 1948 | if (!musb) { |
1951 | status = -ENOMEM; | 1949 | status = -ENOMEM; |
1952 | goto fail0; | 1950 | goto fail0; |
1953 | } | 1951 | } |
1954 | 1952 | ||
1955 | pm_runtime_use_autosuspend(musb->controller); | 1953 | pm_runtime_use_autosuspend(musb->controller); |
1956 | pm_runtime_set_autosuspend_delay(musb->controller, 200); | 1954 | pm_runtime_set_autosuspend_delay(musb->controller, 200); |
1957 | pm_runtime_enable(musb->controller); | 1955 | pm_runtime_enable(musb->controller); |
1958 | 1956 | ||
1959 | spin_lock_init(&musb->lock); | 1957 | spin_lock_init(&musb->lock); |
1960 | musb->board_mode = plat->mode; | 1958 | musb->board_mode = plat->mode; |
1961 | musb->board_set_power = plat->set_power; | 1959 | musb->board_set_power = plat->set_power; |
1962 | musb->min_power = plat->min_power; | 1960 | musb->min_power = plat->min_power; |
1963 | musb->ops = plat->platform_ops; | 1961 | musb->ops = plat->platform_ops; |
1964 | 1962 | ||
1965 | /* The musb_platform_init() call: | 1963 | /* The musb_platform_init() call: |
1966 | * - adjusts musb->mregs and musb->isr if needed, | 1964 | * - adjusts musb->mregs and musb->isr if needed, |
1967 | * - may initialize an integrated tranceiver | 1965 | * - may initialize an integrated tranceiver |
1968 | * - initializes musb->xceiv, usually by otg_get_phy() | 1966 | * - initializes musb->xceiv, usually by otg_get_phy() |
1969 | * - stops powering VBUS | 1967 | * - stops powering VBUS |
1970 | * | 1968 | * |
1971 | * There are various transceiver configurations. Blackfin, | 1969 | * There are various transceiver configurations. Blackfin, |
1972 | * DaVinci, TUSB60x0, and others integrate them. OMAP3 uses | 1970 | * DaVinci, TUSB60x0, and others integrate them. OMAP3 uses |
1973 | * external/discrete ones in various flavors (twl4030 family, | 1971 | * external/discrete ones in various flavors (twl4030 family, |
1974 | * isp1504, non-OTG, etc) mostly hooking up through ULPI. | 1972 | * isp1504, non-OTG, etc) mostly hooking up through ULPI. |
1975 | */ | 1973 | */ |
1976 | musb->isr = generic_interrupt; | 1974 | musb->isr = generic_interrupt; |
1977 | status = musb_platform_init(musb); | 1975 | status = musb_platform_init(musb); |
1978 | if (status < 0) | 1976 | if (status < 0) |
1979 | goto fail1; | 1977 | goto fail1; |
1980 | 1978 | ||
1981 | if (!musb->isr) { | 1979 | if (!musb->isr) { |
1982 | status = -ENODEV; | 1980 | status = -ENODEV; |
1983 | goto fail2; | 1981 | goto fail2; |
1984 | } | 1982 | } |
1985 | 1983 | ||
1986 | #ifndef __UBOOT__ | 1984 | #ifndef __UBOOT__ |
1987 | if (!musb->xceiv->io_ops) { | 1985 | if (!musb->xceiv->io_ops) { |
1988 | musb->xceiv->io_dev = musb->controller; | 1986 | musb->xceiv->io_dev = musb->controller; |
1989 | musb->xceiv->io_priv = musb->mregs; | 1987 | musb->xceiv->io_priv = musb->mregs; |
1990 | musb->xceiv->io_ops = &musb_ulpi_access; | 1988 | musb->xceiv->io_ops = &musb_ulpi_access; |
1991 | } | 1989 | } |
1992 | #endif | 1990 | #endif |
1993 | 1991 | ||
1994 | pm_runtime_get_sync(musb->controller); | 1992 | pm_runtime_get_sync(musb->controller); |
1995 | 1993 | ||
1996 | #ifndef CONFIG_MUSB_PIO_ONLY | 1994 | #ifndef CONFIG_MUSB_PIO_ONLY |
1997 | if (use_dma && dev->dma_mask) { | 1995 | if (use_dma && dev->dma_mask) { |
1998 | struct dma_controller *c; | 1996 | struct dma_controller *c; |
1999 | 1997 | ||
2000 | c = dma_controller_create(musb, musb->mregs); | 1998 | c = dma_controller_create(musb, musb->mregs); |
2001 | musb->dma_controller = c; | 1999 | musb->dma_controller = c; |
2002 | if (c) | 2000 | if (c) |
2003 | (void) c->start(c); | 2001 | (void) c->start(c); |
2004 | } | 2002 | } |
2005 | #endif | 2003 | #endif |
2006 | #ifndef __UBOOT__ | 2004 | #ifndef __UBOOT__ |
2007 | /* ideally this would be abstracted in platform setup */ | 2005 | /* ideally this would be abstracted in platform setup */ |
2008 | if (!is_dma_capable() || !musb->dma_controller) | 2006 | if (!is_dma_capable() || !musb->dma_controller) |
2009 | dev->dma_mask = NULL; | 2007 | dev->dma_mask = NULL; |
2010 | #endif | 2008 | #endif |
2011 | 2009 | ||
2012 | /* be sure interrupts are disabled before connecting ISR */ | 2010 | /* be sure interrupts are disabled before connecting ISR */ |
2013 | musb_platform_disable(musb); | 2011 | musb_platform_disable(musb); |
2014 | musb_generic_disable(musb); | 2012 | musb_generic_disable(musb); |
2015 | 2013 | ||
2016 | /* setup musb parts of the core (especially endpoints) */ | 2014 | /* setup musb parts of the core (especially endpoints) */ |
2017 | status = musb_core_init(plat->config->multipoint | 2015 | status = musb_core_init(plat->config->multipoint |
2018 | ? MUSB_CONTROLLER_MHDRC | 2016 | ? MUSB_CONTROLLER_MHDRC |
2019 | : MUSB_CONTROLLER_HDRC, musb); | 2017 | : MUSB_CONTROLLER_HDRC, musb); |
2020 | if (status < 0) | 2018 | if (status < 0) |
2021 | goto fail3; | 2019 | goto fail3; |
2022 | 2020 | ||
2023 | setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb); | 2021 | setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb); |
2024 | 2022 | ||
2025 | /* Init IRQ workqueue before request_irq */ | 2023 | /* Init IRQ workqueue before request_irq */ |
2026 | INIT_WORK(&musb->irq_work, musb_irq_work); | 2024 | INIT_WORK(&musb->irq_work, musb_irq_work); |
2027 | 2025 | ||
2028 | /* attach to the IRQ */ | 2026 | /* attach to the IRQ */ |
2029 | if (request_irq(nIrq, musb->isr, 0, dev_name(dev), musb)) { | 2027 | if (request_irq(nIrq, musb->isr, 0, dev_name(dev), musb)) { |
2030 | dev_err(dev, "request_irq %d failed!\n", nIrq); | 2028 | dev_err(dev, "request_irq %d failed!\n", nIrq); |
2031 | status = -ENODEV; | 2029 | status = -ENODEV; |
2032 | goto fail3; | 2030 | goto fail3; |
2033 | } | 2031 | } |
2034 | musb->nIrq = nIrq; | 2032 | musb->nIrq = nIrq; |
2035 | /* FIXME this handles wakeup irqs wrong */ | 2033 | /* FIXME this handles wakeup irqs wrong */ |
2036 | if (enable_irq_wake(nIrq) == 0) { | 2034 | if (enable_irq_wake(nIrq) == 0) { |
2037 | musb->irq_wake = 1; | 2035 | musb->irq_wake = 1; |
2038 | device_init_wakeup(dev, 1); | 2036 | device_init_wakeup(dev, 1); |
2039 | } else { | 2037 | } else { |
2040 | musb->irq_wake = 0; | 2038 | musb->irq_wake = 0; |
2041 | } | 2039 | } |
2042 | 2040 | ||
2043 | #ifndef __UBOOT__ | 2041 | #ifndef __UBOOT__ |
2044 | /* host side needs more setup */ | 2042 | /* host side needs more setup */ |
2045 | if (is_host_enabled(musb)) { | 2043 | if (is_host_enabled(musb)) { |
2046 | struct usb_hcd *hcd = musb_to_hcd(musb); | 2044 | struct usb_hcd *hcd = musb_to_hcd(musb); |
2047 | 2045 | ||
2048 | otg_set_host(musb->xceiv->otg, &hcd->self); | 2046 | otg_set_host(musb->xceiv->otg, &hcd->self); |
2049 | 2047 | ||
2050 | if (is_otg_enabled(musb)) | 2048 | if (is_otg_enabled(musb)) |
2051 | hcd->self.otg_port = 1; | 2049 | hcd->self.otg_port = 1; |
2052 | musb->xceiv->otg->host = &hcd->self; | 2050 | musb->xceiv->otg->host = &hcd->self; |
2053 | hcd->power_budget = 2 * (plat->power ? : 250); | 2051 | hcd->power_budget = 2 * (plat->power ? : 250); |
2054 | 2052 | ||
2055 | /* program PHY to use external vBus if required */ | 2053 | /* program PHY to use external vBus if required */ |
2056 | if (plat->extvbus) { | 2054 | if (plat->extvbus) { |
2057 | u8 busctl = musb_read_ulpi_buscontrol(musb->mregs); | 2055 | u8 busctl = musb_read_ulpi_buscontrol(musb->mregs); |
2058 | busctl |= MUSB_ULPI_USE_EXTVBUS; | 2056 | busctl |= MUSB_ULPI_USE_EXTVBUS; |
2059 | musb_write_ulpi_buscontrol(musb->mregs, busctl); | 2057 | musb_write_ulpi_buscontrol(musb->mregs, busctl); |
2060 | } | 2058 | } |
2061 | } | 2059 | } |
2062 | #endif | 2060 | #endif |
2063 | 2061 | ||
2064 | /* For the host-only role, we can activate right away. | 2062 | /* For the host-only role, we can activate right away. |
2065 | * (We expect the ID pin to be forcibly grounded!!) | 2063 | * (We expect the ID pin to be forcibly grounded!!) |
2066 | * Otherwise, wait till the gadget driver hooks up. | 2064 | * Otherwise, wait till the gadget driver hooks up. |
2067 | */ | 2065 | */ |
2068 | if (!is_otg_enabled(musb) && is_host_enabled(musb)) { | 2066 | if (!is_otg_enabled(musb) && is_host_enabled(musb)) { |
2069 | struct usb_hcd *hcd = musb_to_hcd(musb); | 2067 | struct usb_hcd *hcd = musb_to_hcd(musb); |
2070 | 2068 | ||
2071 | MUSB_HST_MODE(musb); | 2069 | MUSB_HST_MODE(musb); |
2072 | #ifndef __UBOOT__ | 2070 | #ifndef __UBOOT__ |
2073 | musb->xceiv->otg->default_a = 1; | 2071 | musb->xceiv->otg->default_a = 1; |
2074 | musb->xceiv->state = OTG_STATE_A_IDLE; | 2072 | musb->xceiv->state = OTG_STATE_A_IDLE; |
2075 | 2073 | ||
2076 | status = usb_add_hcd(musb_to_hcd(musb), 0, 0); | 2074 | status = usb_add_hcd(musb_to_hcd(musb), 0, 0); |
2077 | 2075 | ||
2078 | hcd->self.uses_pio_for_control = 1; | 2076 | hcd->self.uses_pio_for_control = 1; |
2079 | dev_dbg(musb->controller, "%s mode, status %d, devctl %02x %c\n", | 2077 | dev_dbg(musb->controller, "%s mode, status %d, devctl %02x %c\n", |
2080 | "HOST", status, | 2078 | "HOST", status, |
2081 | musb_readb(musb->mregs, MUSB_DEVCTL), | 2079 | musb_readb(musb->mregs, MUSB_DEVCTL), |
2082 | (musb_readb(musb->mregs, MUSB_DEVCTL) | 2080 | (musb_readb(musb->mregs, MUSB_DEVCTL) |
2083 | & MUSB_DEVCTL_BDEVICE | 2081 | & MUSB_DEVCTL_BDEVICE |
2084 | ? 'B' : 'A')); | 2082 | ? 'B' : 'A')); |
2085 | #endif | 2083 | #endif |
2086 | 2084 | ||
2087 | } else /* peripheral is enabled */ { | 2085 | } else /* peripheral is enabled */ { |
2088 | MUSB_DEV_MODE(musb); | 2086 | MUSB_DEV_MODE(musb); |
2089 | #ifndef __UBOOT__ | 2087 | #ifndef __UBOOT__ |
2090 | musb->xceiv->otg->default_a = 0; | 2088 | musb->xceiv->otg->default_a = 0; |
2091 | musb->xceiv->state = OTG_STATE_B_IDLE; | 2089 | musb->xceiv->state = OTG_STATE_B_IDLE; |
2092 | #endif | 2090 | #endif |
2093 | 2091 | ||
2094 | if (is_peripheral_capable()) | 2092 | if (is_peripheral_capable()) |
2095 | status = musb_gadget_setup(musb); | 2093 | status = musb_gadget_setup(musb); |
2096 | 2094 | ||
2097 | #ifndef __UBOOT__ | 2095 | #ifndef __UBOOT__ |
2098 | dev_dbg(musb->controller, "%s mode, status %d, dev%02x\n", | 2096 | dev_dbg(musb->controller, "%s mode, status %d, dev%02x\n", |
2099 | is_otg_enabled(musb) ? "OTG" : "PERIPHERAL", | 2097 | is_otg_enabled(musb) ? "OTG" : "PERIPHERAL", |
2100 | status, | 2098 | status, |
2101 | musb_readb(musb->mregs, MUSB_DEVCTL)); | 2099 | musb_readb(musb->mregs, MUSB_DEVCTL)); |
2102 | #endif | 2100 | #endif |
2103 | 2101 | ||
2104 | } | 2102 | } |
2105 | if (status < 0) | 2103 | if (status < 0) |
2106 | goto fail3; | 2104 | goto fail3; |
2107 | 2105 | ||
2108 | status = musb_init_debugfs(musb); | 2106 | status = musb_init_debugfs(musb); |
2109 | if (status < 0) | 2107 | if (status < 0) |
2110 | goto fail4; | 2108 | goto fail4; |
2111 | 2109 | ||
2112 | #ifdef CONFIG_SYSFS | 2110 | #ifdef CONFIG_SYSFS |
2113 | status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group); | 2111 | status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group); |
2114 | if (status) | 2112 | if (status) |
2115 | goto fail5; | 2113 | goto fail5; |
2116 | #endif | 2114 | #endif |
2117 | 2115 | ||
2118 | pm_runtime_put(musb->controller); | 2116 | pm_runtime_put(musb->controller); |
2119 | 2117 | ||
2120 | pr_debug("USB %s mode controller at %p using %s, IRQ %d\n", | 2118 | pr_debug("USB %s mode controller at %p using %s, IRQ %d\n", |
2121 | ({char *s; | 2119 | ({char *s; |
2122 | switch (musb->board_mode) { | 2120 | switch (musb->board_mode) { |
2123 | case MUSB_HOST: s = "Host"; break; | 2121 | case MUSB_HOST: s = "Host"; break; |
2124 | case MUSB_PERIPHERAL: s = "Peripheral"; break; | 2122 | case MUSB_PERIPHERAL: s = "Peripheral"; break; |
2125 | default: s = "OTG"; break; | 2123 | default: s = "OTG"; break; |
2126 | }; s; }), | 2124 | }; s; }), |
2127 | ctrl, | 2125 | ctrl, |
2128 | (is_dma_capable() && musb->dma_controller) | 2126 | (is_dma_capable() && musb->dma_controller) |
2129 | ? "DMA" : "PIO", | 2127 | ? "DMA" : "PIO", |
2130 | musb->nIrq); | 2128 | musb->nIrq); |
2131 | 2129 | ||
2132 | #ifndef __UBOOT__ | 2130 | #ifndef __UBOOT__ |
2133 | return 0; | 2131 | return 0; |
2134 | #else | 2132 | #else |
2135 | return status == 0 ? musb : NULL; | 2133 | return status == 0 ? musb : NULL; |
2136 | #endif | 2134 | #endif |
2137 | 2135 | ||
2138 | fail5: | 2136 | fail5: |
2139 | musb_exit_debugfs(musb); | 2137 | musb_exit_debugfs(musb); |
2140 | 2138 | ||
2141 | fail4: | 2139 | fail4: |
2142 | #ifndef __UBOOT__ | 2140 | #ifndef __UBOOT__ |
2143 | if (!is_otg_enabled(musb) && is_host_enabled(musb)) | 2141 | if (!is_otg_enabled(musb) && is_host_enabled(musb)) |
2144 | usb_remove_hcd(musb_to_hcd(musb)); | 2142 | usb_remove_hcd(musb_to_hcd(musb)); |
2145 | else | 2143 | else |
2146 | #endif | 2144 | #endif |
2147 | musb_gadget_cleanup(musb); | 2145 | musb_gadget_cleanup(musb); |
2148 | 2146 | ||
2149 | fail3: | 2147 | fail3: |
2150 | pm_runtime_put_sync(musb->controller); | 2148 | pm_runtime_put_sync(musb->controller); |
2151 | 2149 | ||
2152 | fail2: | 2150 | fail2: |
2153 | if (musb->irq_wake) | 2151 | if (musb->irq_wake) |
2154 | device_init_wakeup(dev, 0); | 2152 | device_init_wakeup(dev, 0); |
2155 | musb_platform_exit(musb); | 2153 | musb_platform_exit(musb); |
2156 | 2154 | ||
2157 | fail1: | 2155 | fail1: |
2158 | dev_err(musb->controller, | 2156 | dev_err(musb->controller, |
2159 | "musb_init_controller failed with status %d\n", status); | 2157 | "musb_init_controller failed with status %d\n", status); |
2160 | 2158 | ||
2161 | musb_free(musb); | 2159 | musb_free(musb); |
2162 | 2160 | ||
2163 | fail0: | 2161 | fail0: |
2164 | 2162 | ||
2165 | #ifndef __UBOOT__ | 2163 | #ifndef __UBOOT__ |
2166 | return status; | 2164 | return status; |
2167 | #else | 2165 | #else |
2168 | return status == 0 ? musb : NULL; | 2166 | return status == 0 ? musb : NULL; |
2169 | #endif | 2167 | #endif |
2170 | 2168 | ||
2171 | } | 2169 | } |
2172 | 2170 | ||
2173 | /*-------------------------------------------------------------------------*/ | 2171 | /*-------------------------------------------------------------------------*/ |
2174 | 2172 | ||
2175 | /* all implementations (PCI bridge to FPGA, VLYNQ, etc) should just | 2173 | /* all implementations (PCI bridge to FPGA, VLYNQ, etc) should just |
2176 | * bridge to a platform device; this driver then suffices. | 2174 | * bridge to a platform device; this driver then suffices. |
2177 | */ | 2175 | */ |
2178 | 2176 | ||
2179 | #ifndef CONFIG_MUSB_PIO_ONLY | 2177 | #ifndef CONFIG_MUSB_PIO_ONLY |
2180 | static u64 *orig_dma_mask; | 2178 | static u64 *orig_dma_mask; |
2181 | #endif | 2179 | #endif |
2182 | 2180 | ||
2183 | #ifndef __UBOOT__ | 2181 | #ifndef __UBOOT__ |
2184 | static int __devinit musb_probe(struct platform_device *pdev) | 2182 | static int __devinit musb_probe(struct platform_device *pdev) |
2185 | { | 2183 | { |
2186 | struct device *dev = &pdev->dev; | 2184 | struct device *dev = &pdev->dev; |
2187 | int irq = platform_get_irq_byname(pdev, "mc"); | 2185 | int irq = platform_get_irq_byname(pdev, "mc"); |
2188 | int status; | 2186 | int status; |
2189 | struct resource *iomem; | 2187 | struct resource *iomem; |
2190 | void __iomem *base; | 2188 | void __iomem *base; |
2191 | 2189 | ||
2192 | iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 2190 | iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
2193 | if (!iomem || irq <= 0) | 2191 | if (!iomem || irq <= 0) |
2194 | return -ENODEV; | 2192 | return -ENODEV; |
2195 | 2193 | ||
2196 | base = ioremap(iomem->start, resource_size(iomem)); | 2194 | base = ioremap(iomem->start, resource_size(iomem)); |
2197 | if (!base) { | 2195 | if (!base) { |
2198 | dev_err(dev, "ioremap failed\n"); | 2196 | dev_err(dev, "ioremap failed\n"); |
2199 | return -ENOMEM; | 2197 | return -ENOMEM; |
2200 | } | 2198 | } |
2201 | 2199 | ||
2202 | #ifndef CONFIG_MUSB_PIO_ONLY | 2200 | #ifndef CONFIG_MUSB_PIO_ONLY |
2203 | /* clobbered by use_dma=n */ | 2201 | /* clobbered by use_dma=n */ |
2204 | orig_dma_mask = dev->dma_mask; | 2202 | orig_dma_mask = dev->dma_mask; |
2205 | #endif | 2203 | #endif |
2206 | status = musb_init_controller(dev, irq, base); | 2204 | status = musb_init_controller(dev, irq, base); |
2207 | if (status < 0) | 2205 | if (status < 0) |
2208 | iounmap(base); | 2206 | iounmap(base); |
2209 | 2207 | ||
2210 | return status; | 2208 | return status; |
2211 | } | 2209 | } |
2212 | 2210 | ||
2213 | static int __devexit musb_remove(struct platform_device *pdev) | 2211 | static int __devexit musb_remove(struct platform_device *pdev) |
2214 | { | 2212 | { |
2215 | struct musb *musb = dev_to_musb(&pdev->dev); | 2213 | struct musb *musb = dev_to_musb(&pdev->dev); |
2216 | void __iomem *ctrl_base = musb->ctrl_base; | 2214 | void __iomem *ctrl_base = musb->ctrl_base; |
2217 | 2215 | ||
2218 | /* this gets called on rmmod. | 2216 | /* this gets called on rmmod. |
2219 | * - Host mode: host may still be active | 2217 | * - Host mode: host may still be active |
2220 | * - Peripheral mode: peripheral is deactivated (or never-activated) | 2218 | * - Peripheral mode: peripheral is deactivated (or never-activated) |
2221 | * - OTG mode: both roles are deactivated (or never-activated) | 2219 | * - OTG mode: both roles are deactivated (or never-activated) |
2222 | */ | 2220 | */ |
2223 | musb_exit_debugfs(musb); | 2221 | musb_exit_debugfs(musb); |
2224 | musb_shutdown(pdev); | 2222 | musb_shutdown(pdev); |
2225 | 2223 | ||
2226 | musb_free(musb); | 2224 | musb_free(musb); |
2227 | iounmap(ctrl_base); | 2225 | iounmap(ctrl_base); |
2228 | device_init_wakeup(&pdev->dev, 0); | 2226 | device_init_wakeup(&pdev->dev, 0); |
2229 | #ifndef CONFIG_MUSB_PIO_ONLY | 2227 | #ifndef CONFIG_MUSB_PIO_ONLY |
2230 | pdev->dev.dma_mask = orig_dma_mask; | 2228 | pdev->dev.dma_mask = orig_dma_mask; |
2231 | #endif | 2229 | #endif |
2232 | return 0; | 2230 | return 0; |
2233 | } | 2231 | } |
2234 | 2232 | ||
2235 | #ifdef CONFIG_PM | 2233 | #ifdef CONFIG_PM |
2236 | 2234 | ||
2237 | static void musb_save_context(struct musb *musb) | 2235 | static void musb_save_context(struct musb *musb) |
2238 | { | 2236 | { |
2239 | int i; | 2237 | int i; |
2240 | void __iomem *musb_base = musb->mregs; | 2238 | void __iomem *musb_base = musb->mregs; |
2241 | void __iomem *epio; | 2239 | void __iomem *epio; |
2242 | 2240 | ||
2243 | if (is_host_enabled(musb)) { | 2241 | if (is_host_enabled(musb)) { |
2244 | musb->context.frame = musb_readw(musb_base, MUSB_FRAME); | 2242 | musb->context.frame = musb_readw(musb_base, MUSB_FRAME); |
2245 | musb->context.testmode = musb_readb(musb_base, MUSB_TESTMODE); | 2243 | musb->context.testmode = musb_readb(musb_base, MUSB_TESTMODE); |
2246 | musb->context.busctl = musb_read_ulpi_buscontrol(musb->mregs); | 2244 | musb->context.busctl = musb_read_ulpi_buscontrol(musb->mregs); |
2247 | } | 2245 | } |
2248 | musb->context.power = musb_readb(musb_base, MUSB_POWER); | 2246 | musb->context.power = musb_readb(musb_base, MUSB_POWER); |
2249 | musb->context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE); | 2247 | musb->context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE); |
2250 | musb->context.intrrxe = musb_readw(musb_base, MUSB_INTRRXE); | 2248 | musb->context.intrrxe = musb_readw(musb_base, MUSB_INTRRXE); |
2251 | musb->context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE); | 2249 | musb->context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE); |
2252 | musb->context.index = musb_readb(musb_base, MUSB_INDEX); | 2250 | musb->context.index = musb_readb(musb_base, MUSB_INDEX); |
2253 | musb->context.devctl = musb_readb(musb_base, MUSB_DEVCTL); | 2251 | musb->context.devctl = musb_readb(musb_base, MUSB_DEVCTL); |
2254 | 2252 | ||
2255 | for (i = 0; i < musb->config->num_eps; ++i) { | 2253 | for (i = 0; i < musb->config->num_eps; ++i) { |
2256 | struct musb_hw_ep *hw_ep; | 2254 | struct musb_hw_ep *hw_ep; |
2257 | 2255 | ||
2258 | hw_ep = &musb->endpoints[i]; | 2256 | hw_ep = &musb->endpoints[i]; |
2259 | if (!hw_ep) | 2257 | if (!hw_ep) |
2260 | continue; | 2258 | continue; |
2261 | 2259 | ||
2262 | epio = hw_ep->regs; | 2260 | epio = hw_ep->regs; |
2263 | if (!epio) | 2261 | if (!epio) |
2264 | continue; | 2262 | continue; |
2265 | 2263 | ||
2266 | musb_writeb(musb_base, MUSB_INDEX, i); | 2264 | musb_writeb(musb_base, MUSB_INDEX, i); |
2267 | musb->context.index_regs[i].txmaxp = | 2265 | musb->context.index_regs[i].txmaxp = |
2268 | musb_readw(epio, MUSB_TXMAXP); | 2266 | musb_readw(epio, MUSB_TXMAXP); |
2269 | musb->context.index_regs[i].txcsr = | 2267 | musb->context.index_regs[i].txcsr = |
2270 | musb_readw(epio, MUSB_TXCSR); | 2268 | musb_readw(epio, MUSB_TXCSR); |
2271 | musb->context.index_regs[i].rxmaxp = | 2269 | musb->context.index_regs[i].rxmaxp = |
2272 | musb_readw(epio, MUSB_RXMAXP); | 2270 | musb_readw(epio, MUSB_RXMAXP); |
2273 | musb->context.index_regs[i].rxcsr = | 2271 | musb->context.index_regs[i].rxcsr = |
2274 | musb_readw(epio, MUSB_RXCSR); | 2272 | musb_readw(epio, MUSB_RXCSR); |
2275 | 2273 | ||
2276 | if (musb->dyn_fifo) { | 2274 | if (musb->dyn_fifo) { |
2277 | musb->context.index_regs[i].txfifoadd = | 2275 | musb->context.index_regs[i].txfifoadd = |
2278 | musb_read_txfifoadd(musb_base); | 2276 | musb_read_txfifoadd(musb_base); |
2279 | musb->context.index_regs[i].rxfifoadd = | 2277 | musb->context.index_regs[i].rxfifoadd = |
2280 | musb_read_rxfifoadd(musb_base); | 2278 | musb_read_rxfifoadd(musb_base); |
2281 | musb->context.index_regs[i].txfifosz = | 2279 | musb->context.index_regs[i].txfifosz = |
2282 | musb_read_txfifosz(musb_base); | 2280 | musb_read_txfifosz(musb_base); |
2283 | musb->context.index_regs[i].rxfifosz = | 2281 | musb->context.index_regs[i].rxfifosz = |
2284 | musb_read_rxfifosz(musb_base); | 2282 | musb_read_rxfifosz(musb_base); |
2285 | } | 2283 | } |
2286 | if (is_host_enabled(musb)) { | 2284 | if (is_host_enabled(musb)) { |
2287 | musb->context.index_regs[i].txtype = | 2285 | musb->context.index_regs[i].txtype = |
2288 | musb_readb(epio, MUSB_TXTYPE); | 2286 | musb_readb(epio, MUSB_TXTYPE); |
2289 | musb->context.index_regs[i].txinterval = | 2287 | musb->context.index_regs[i].txinterval = |
2290 | musb_readb(epio, MUSB_TXINTERVAL); | 2288 | musb_readb(epio, MUSB_TXINTERVAL); |
2291 | musb->context.index_regs[i].rxtype = | 2289 | musb->context.index_regs[i].rxtype = |
2292 | musb_readb(epio, MUSB_RXTYPE); | 2290 | musb_readb(epio, MUSB_RXTYPE); |
2293 | musb->context.index_regs[i].rxinterval = | 2291 | musb->context.index_regs[i].rxinterval = |
2294 | musb_readb(epio, MUSB_RXINTERVAL); | 2292 | musb_readb(epio, MUSB_RXINTERVAL); |
2295 | 2293 | ||
2296 | musb->context.index_regs[i].txfunaddr = | 2294 | musb->context.index_regs[i].txfunaddr = |
2297 | musb_read_txfunaddr(musb_base, i); | 2295 | musb_read_txfunaddr(musb_base, i); |
2298 | musb->context.index_regs[i].txhubaddr = | 2296 | musb->context.index_regs[i].txhubaddr = |
2299 | musb_read_txhubaddr(musb_base, i); | 2297 | musb_read_txhubaddr(musb_base, i); |
2300 | musb->context.index_regs[i].txhubport = | 2298 | musb->context.index_regs[i].txhubport = |
2301 | musb_read_txhubport(musb_base, i); | 2299 | musb_read_txhubport(musb_base, i); |
2302 | 2300 | ||
2303 | musb->context.index_regs[i].rxfunaddr = | 2301 | musb->context.index_regs[i].rxfunaddr = |
2304 | musb_read_rxfunaddr(musb_base, i); | 2302 | musb_read_rxfunaddr(musb_base, i); |
2305 | musb->context.index_regs[i].rxhubaddr = | 2303 | musb->context.index_regs[i].rxhubaddr = |
2306 | musb_read_rxhubaddr(musb_base, i); | 2304 | musb_read_rxhubaddr(musb_base, i); |
2307 | musb->context.index_regs[i].rxhubport = | 2305 | musb->context.index_regs[i].rxhubport = |
2308 | musb_read_rxhubport(musb_base, i); | 2306 | musb_read_rxhubport(musb_base, i); |
2309 | } | 2307 | } |
2310 | } | 2308 | } |
2311 | } | 2309 | } |
2312 | 2310 | ||
2313 | static void musb_restore_context(struct musb *musb) | 2311 | static void musb_restore_context(struct musb *musb) |
2314 | { | 2312 | { |
2315 | int i; | 2313 | int i; |
2316 | void __iomem *musb_base = musb->mregs; | 2314 | void __iomem *musb_base = musb->mregs; |
2317 | void __iomem *ep_target_regs; | 2315 | void __iomem *ep_target_regs; |
2318 | void __iomem *epio; | 2316 | void __iomem *epio; |
2319 | 2317 | ||
2320 | if (is_host_enabled(musb)) { | 2318 | if (is_host_enabled(musb)) { |
2321 | musb_writew(musb_base, MUSB_FRAME, musb->context.frame); | 2319 | musb_writew(musb_base, MUSB_FRAME, musb->context.frame); |
2322 | musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode); | 2320 | musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode); |
2323 | musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl); | 2321 | musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl); |
2324 | } | 2322 | } |
2325 | musb_writeb(musb_base, MUSB_POWER, musb->context.power); | 2323 | musb_writeb(musb_base, MUSB_POWER, musb->context.power); |
2326 | musb_writew(musb_base, MUSB_INTRTXE, musb->context.intrtxe); | 2324 | musb_writew(musb_base, MUSB_INTRTXE, musb->context.intrtxe); |
2327 | musb_writew(musb_base, MUSB_INTRRXE, musb->context.intrrxe); | 2325 | musb_writew(musb_base, MUSB_INTRRXE, musb->context.intrrxe); |
2328 | musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe); | 2326 | musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe); |
2329 | musb_writeb(musb_base, MUSB_DEVCTL, musb->context.devctl); | 2327 | musb_writeb(musb_base, MUSB_DEVCTL, musb->context.devctl); |
2330 | 2328 | ||
2331 | for (i = 0; i < musb->config->num_eps; ++i) { | 2329 | for (i = 0; i < musb->config->num_eps; ++i) { |
2332 | struct musb_hw_ep *hw_ep; | 2330 | struct musb_hw_ep *hw_ep; |
2333 | 2331 | ||
2334 | hw_ep = &musb->endpoints[i]; | 2332 | hw_ep = &musb->endpoints[i]; |
2335 | if (!hw_ep) | 2333 | if (!hw_ep) |
2336 | continue; | 2334 | continue; |
2337 | 2335 | ||
2338 | epio = hw_ep->regs; | 2336 | epio = hw_ep->regs; |
2339 | if (!epio) | 2337 | if (!epio) |
2340 | continue; | 2338 | continue; |
2341 | 2339 | ||
2342 | musb_writeb(musb_base, MUSB_INDEX, i); | 2340 | musb_writeb(musb_base, MUSB_INDEX, i); |
2343 | musb_writew(epio, MUSB_TXMAXP, | 2341 | musb_writew(epio, MUSB_TXMAXP, |
2344 | musb->context.index_regs[i].txmaxp); | 2342 | musb->context.index_regs[i].txmaxp); |
2345 | musb_writew(epio, MUSB_TXCSR, | 2343 | musb_writew(epio, MUSB_TXCSR, |
2346 | musb->context.index_regs[i].txcsr); | 2344 | musb->context.index_regs[i].txcsr); |
2347 | musb_writew(epio, MUSB_RXMAXP, | 2345 | musb_writew(epio, MUSB_RXMAXP, |
2348 | musb->context.index_regs[i].rxmaxp); | 2346 | musb->context.index_regs[i].rxmaxp); |
2349 | musb_writew(epio, MUSB_RXCSR, | 2347 | musb_writew(epio, MUSB_RXCSR, |
2350 | musb->context.index_regs[i].rxcsr); | 2348 | musb->context.index_regs[i].rxcsr); |
2351 | 2349 | ||
2352 | if (musb->dyn_fifo) { | 2350 | if (musb->dyn_fifo) { |
2353 | musb_write_txfifosz(musb_base, | 2351 | musb_write_txfifosz(musb_base, |
2354 | musb->context.index_regs[i].txfifosz); | 2352 | musb->context.index_regs[i].txfifosz); |
2355 | musb_write_rxfifosz(musb_base, | 2353 | musb_write_rxfifosz(musb_base, |
2356 | musb->context.index_regs[i].rxfifosz); | 2354 | musb->context.index_regs[i].rxfifosz); |
2357 | musb_write_txfifoadd(musb_base, | 2355 | musb_write_txfifoadd(musb_base, |
2358 | musb->context.index_regs[i].txfifoadd); | 2356 | musb->context.index_regs[i].txfifoadd); |
2359 | musb_write_rxfifoadd(musb_base, | 2357 | musb_write_rxfifoadd(musb_base, |
2360 | musb->context.index_regs[i].rxfifoadd); | 2358 | musb->context.index_regs[i].rxfifoadd); |
2361 | } | 2359 | } |
2362 | 2360 | ||
2363 | if (is_host_enabled(musb)) { | 2361 | if (is_host_enabled(musb)) { |
2364 | musb_writeb(epio, MUSB_TXTYPE, | 2362 | musb_writeb(epio, MUSB_TXTYPE, |
2365 | musb->context.index_regs[i].txtype); | 2363 | musb->context.index_regs[i].txtype); |
2366 | musb_writeb(epio, MUSB_TXINTERVAL, | 2364 | musb_writeb(epio, MUSB_TXINTERVAL, |
2367 | musb->context.index_regs[i].txinterval); | 2365 | musb->context.index_regs[i].txinterval); |
2368 | musb_writeb(epio, MUSB_RXTYPE, | 2366 | musb_writeb(epio, MUSB_RXTYPE, |
2369 | musb->context.index_regs[i].rxtype); | 2367 | musb->context.index_regs[i].rxtype); |
2370 | musb_writeb(epio, MUSB_RXINTERVAL, | 2368 | musb_writeb(epio, MUSB_RXINTERVAL, |
2371 | 2369 | ||
2372 | musb->context.index_regs[i].rxinterval); | 2370 | musb->context.index_regs[i].rxinterval); |
2373 | musb_write_txfunaddr(musb_base, i, | 2371 | musb_write_txfunaddr(musb_base, i, |
2374 | musb->context.index_regs[i].txfunaddr); | 2372 | musb->context.index_regs[i].txfunaddr); |
2375 | musb_write_txhubaddr(musb_base, i, | 2373 | musb_write_txhubaddr(musb_base, i, |
2376 | musb->context.index_regs[i].txhubaddr); | 2374 | musb->context.index_regs[i].txhubaddr); |
2377 | musb_write_txhubport(musb_base, i, | 2375 | musb_write_txhubport(musb_base, i, |
2378 | musb->context.index_regs[i].txhubport); | 2376 | musb->context.index_regs[i].txhubport); |
2379 | 2377 | ||
2380 | ep_target_regs = | 2378 | ep_target_regs = |
2381 | musb_read_target_reg_base(i, musb_base); | 2379 | musb_read_target_reg_base(i, musb_base); |
2382 | 2380 | ||
2383 | musb_write_rxfunaddr(ep_target_regs, | 2381 | musb_write_rxfunaddr(ep_target_regs, |
2384 | musb->context.index_regs[i].rxfunaddr); | 2382 | musb->context.index_regs[i].rxfunaddr); |
2385 | musb_write_rxhubaddr(ep_target_regs, | 2383 | musb_write_rxhubaddr(ep_target_regs, |
2386 | musb->context.index_regs[i].rxhubaddr); | 2384 | musb->context.index_regs[i].rxhubaddr); |
2387 | musb_write_rxhubport(ep_target_regs, | 2385 | musb_write_rxhubport(ep_target_regs, |
2388 | musb->context.index_regs[i].rxhubport); | 2386 | musb->context.index_regs[i].rxhubport); |
2389 | } | 2387 | } |
2390 | } | 2388 | } |
2391 | musb_writeb(musb_base, MUSB_INDEX, musb->context.index); | 2389 | musb_writeb(musb_base, MUSB_INDEX, musb->context.index); |
2392 | } | 2390 | } |
2393 | 2391 | ||
2394 | static int musb_suspend(struct device *dev) | 2392 | static int musb_suspend(struct device *dev) |
2395 | { | 2393 | { |
2396 | struct musb *musb = dev_to_musb(dev); | 2394 | struct musb *musb = dev_to_musb(dev); |
2397 | unsigned long flags; | 2395 | unsigned long flags; |
2398 | 2396 | ||
2399 | spin_lock_irqsave(&musb->lock, flags); | 2397 | spin_lock_irqsave(&musb->lock, flags); |
2400 | 2398 | ||
2401 | if (is_peripheral_active(musb)) { | 2399 | if (is_peripheral_active(musb)) { |
2402 | /* FIXME force disconnect unless we know USB will wake | 2400 | /* FIXME force disconnect unless we know USB will wake |
2403 | * the system up quickly enough to respond ... | 2401 | * the system up quickly enough to respond ... |
2404 | */ | 2402 | */ |
2405 | } else if (is_host_active(musb)) { | 2403 | } else if (is_host_active(musb)) { |
2406 | /* we know all the children are suspended; sometimes | 2404 | /* we know all the children are suspended; sometimes |
2407 | * they will even be wakeup-enabled. | 2405 | * they will even be wakeup-enabled. |
2408 | */ | 2406 | */ |
2409 | } | 2407 | } |
2410 | 2408 | ||
2411 | spin_unlock_irqrestore(&musb->lock, flags); | 2409 | spin_unlock_irqrestore(&musb->lock, flags); |
2412 | return 0; | 2410 | return 0; |
2413 | } | 2411 | } |
2414 | 2412 | ||
2415 | static int musb_resume_noirq(struct device *dev) | 2413 | static int musb_resume_noirq(struct device *dev) |
2416 | { | 2414 | { |
2417 | /* for static cmos like DaVinci, register values were preserved | 2415 | /* for static cmos like DaVinci, register values were preserved |
2418 | * unless for some reason the whole soc powered down or the USB | 2416 | * unless for some reason the whole soc powered down or the USB |
2419 | * module got reset through the PSC (vs just being disabled). | 2417 | * module got reset through the PSC (vs just being disabled). |
2420 | */ | 2418 | */ |
2421 | return 0; | 2419 | return 0; |
2422 | } | 2420 | } |
2423 | 2421 | ||
2424 | static int musb_runtime_suspend(struct device *dev) | 2422 | static int musb_runtime_suspend(struct device *dev) |
2425 | { | 2423 | { |
2426 | struct musb *musb = dev_to_musb(dev); | 2424 | struct musb *musb = dev_to_musb(dev); |
2427 | 2425 | ||
2428 | musb_save_context(musb); | 2426 | musb_save_context(musb); |
2429 | 2427 | ||
2430 | return 0; | 2428 | return 0; |
2431 | } | 2429 | } |
2432 | 2430 | ||
2433 | static int musb_runtime_resume(struct device *dev) | 2431 | static int musb_runtime_resume(struct device *dev) |
2434 | { | 2432 | { |
2435 | struct musb *musb = dev_to_musb(dev); | 2433 | struct musb *musb = dev_to_musb(dev); |
2436 | static int first = 1; | 2434 | static int first = 1; |
2437 | 2435 | ||
2438 | /* | 2436 | /* |
2439 | * When pm_runtime_get_sync called for the first time in driver | 2437 | * When pm_runtime_get_sync called for the first time in driver |
2440 | * init, some of the structure is still not initialized which is | 2438 | * init, some of the structure is still not initialized which is |
2441 | * used in restore function. But clock needs to be | 2439 | * used in restore function. But clock needs to be |
2442 | * enabled before any register access, so | 2440 | * enabled before any register access, so |
2443 | * pm_runtime_get_sync has to be called. | 2441 | * pm_runtime_get_sync has to be called. |
2444 | * Also context restore without save does not make | 2442 | * Also context restore without save does not make |
2445 | * any sense | 2443 | * any sense |
2446 | */ | 2444 | */ |
2447 | if (!first) | 2445 | if (!first) |
2448 | musb_restore_context(musb); | 2446 | musb_restore_context(musb); |
2449 | first = 0; | 2447 | first = 0; |
2450 | 2448 | ||
2451 | return 0; | 2449 | return 0; |
2452 | } | 2450 | } |
2453 | 2451 | ||
2454 | static const struct dev_pm_ops musb_dev_pm_ops = { | 2452 | static const struct dev_pm_ops musb_dev_pm_ops = { |
2455 | .suspend = musb_suspend, | 2453 | .suspend = musb_suspend, |
2456 | .resume_noirq = musb_resume_noirq, | 2454 | .resume_noirq = musb_resume_noirq, |
2457 | .runtime_suspend = musb_runtime_suspend, | 2455 | .runtime_suspend = musb_runtime_suspend, |
2458 | .runtime_resume = musb_runtime_resume, | 2456 | .runtime_resume = musb_runtime_resume, |
2459 | }; | 2457 | }; |
2460 | 2458 | ||
2461 | #define MUSB_DEV_PM_OPS (&musb_dev_pm_ops) | 2459 | #define MUSB_DEV_PM_OPS (&musb_dev_pm_ops) |
2462 | #else | 2460 | #else |
2463 | #define MUSB_DEV_PM_OPS NULL | 2461 | #define MUSB_DEV_PM_OPS NULL |
2464 | #endif | 2462 | #endif |
2465 | 2463 | ||
2466 | static struct platform_driver musb_driver = { | 2464 | static struct platform_driver musb_driver = { |
2467 | .driver = { | 2465 | .driver = { |
2468 | .name = (char *)musb_driver_name, | 2466 | .name = (char *)musb_driver_name, |
2469 | .bus = &platform_bus_type, | 2467 | .bus = &platform_bus_type, |
2470 | .owner = THIS_MODULE, | 2468 | .owner = THIS_MODULE, |
2471 | .pm = MUSB_DEV_PM_OPS, | 2469 | .pm = MUSB_DEV_PM_OPS, |
2472 | }, | 2470 | }, |
2473 | .probe = musb_probe, | 2471 | .probe = musb_probe, |
2474 | .remove = __devexit_p(musb_remove), | 2472 | .remove = __devexit_p(musb_remove), |
2475 | .shutdown = musb_shutdown, | 2473 | .shutdown = musb_shutdown, |
2476 | }; | 2474 | }; |
2477 | 2475 | ||
2478 | /*-------------------------------------------------------------------------*/ | 2476 | /*-------------------------------------------------------------------------*/ |
2479 | 2477 | ||
2480 | static int __init musb_init(void) | 2478 | static int __init musb_init(void) |
2481 | { | 2479 | { |
2482 | if (usb_disabled()) | 2480 | if (usb_disabled()) |
2483 | return 0; | 2481 | return 0; |
2484 | 2482 | ||
2485 | pr_info("%s: version " MUSB_VERSION ", " | 2483 | pr_info("%s: version " MUSB_VERSION ", " |
2486 | "?dma?" | 2484 | "?dma?" |
2487 | ", " | 2485 | ", " |
2488 | "otg (peripheral+host)", | 2486 | "otg (peripheral+host)", |
2489 | musb_driver_name); | 2487 | musb_driver_name); |
2490 | return platform_driver_register(&musb_driver); | 2488 | return platform_driver_register(&musb_driver); |
2491 | } | 2489 | } |
2492 | module_init(musb_init); | 2490 | module_init(musb_init); |
2493 | 2491 | ||
2494 | static void __exit musb_cleanup(void) | 2492 | static void __exit musb_cleanup(void) |
2495 | { | 2493 | { |
2496 | platform_driver_unregister(&musb_driver); | 2494 | platform_driver_unregister(&musb_driver); |
2497 | } | 2495 | } |
2498 | module_exit(musb_cleanup); | 2496 | module_exit(musb_cleanup); |
2499 | #endif | 2497 | #endif |
2500 | 2498 |
include/configs/siemens-am33x-common.h
1 | /* | 1 | /* |
2 | * siemens am33x common board options | 2 | * siemens am33x common board options |
3 | * (C) Copyright 2013 Siemens Schweiz AG | 3 | * (C) Copyright 2013 Siemens Schweiz AG |
4 | * (C) Heiko Schocher, DENX Software Engineering, hs@denx.de. | 4 | * (C) Heiko Schocher, DENX Software Engineering, hs@denx.de. |
5 | * | 5 | * |
6 | * Based on: | 6 | * Based on: |
7 | * U-Boot file:/include/configs/am335x_evm.h | 7 | * U-Boot file:/include/configs/am335x_evm.h |
8 | * | 8 | * |
9 | * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ | 9 | * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ |
10 | * | 10 | * |
11 | * SPDX-License-Identifier: GPL-2.0+ | 11 | * SPDX-License-Identifier: GPL-2.0+ |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #ifndef __CONFIG_SIEMENS_AM33X_COMMON_H | 14 | #ifndef __CONFIG_SIEMENS_AM33X_COMMON_H |
15 | #define __CONFIG_SIEMENS_AM33X_COMMON_H | 15 | #define __CONFIG_SIEMENS_AM33X_COMMON_H |
16 | 16 | ||
17 | #define CONFIG_AM33XX | 17 | #define CONFIG_AM33XX |
18 | #define CONFIG_OMAP | 18 | #define CONFIG_OMAP |
19 | #define CONFIG_OMAP_COMMON | 19 | #define CONFIG_OMAP_COMMON |
20 | 20 | ||
21 | #include <asm/arch/omap.h> | 21 | #include <asm/arch/omap.h> |
22 | 22 | ||
23 | #define CONFIG_DMA_COHERENT | 23 | #define CONFIG_DMA_COHERENT |
24 | #define CONFIG_DMA_COHERENT_SIZE (1 << 20) | 24 | #define CONFIG_DMA_COHERENT_SIZE (1 << 20) |
25 | 25 | ||
26 | #define CONFIG_ENV_SIZE (0x2000) | 26 | #define CONFIG_ENV_SIZE (0x2000) |
27 | #define CONFIG_SYS_MALLOC_LEN (16 * 1024 * 1024) | 27 | #define CONFIG_SYS_MALLOC_LEN (16 * 1024 * 1024) |
28 | #define CONFIG_SYS_LONGHELP /* undef to save memory */ | 28 | #define CONFIG_SYS_LONGHELP /* undef to save memory */ |
29 | #define CONFIG_SYS_HUSH_PARSER /* use "hush" command parser */ | 29 | #define CONFIG_SYS_HUSH_PARSER /* use "hush" command parser */ |
30 | #define CONFIG_SYS_PROMPT "U-Boot# " | 30 | #define CONFIG_SYS_PROMPT "U-Boot# " |
31 | #define CONFIG_SYS_PROMPT_HUSH_PS2 "> " | 31 | #define CONFIG_SYS_PROMPT_HUSH_PS2 "> " |
32 | #define CONFIG_BOARD_LATE_INIT | 32 | #define CONFIG_BOARD_LATE_INIT |
33 | #define CONFIG_SYS_NO_FLASH | 33 | #define CONFIG_SYS_NO_FLASH |
34 | #define CONFIG_MACH_TYPE CONFIG_SIEMENS_MACH_TYPE | 34 | #define CONFIG_MACH_TYPE CONFIG_SIEMENS_MACH_TYPE |
35 | 35 | ||
36 | #define CONFIG_CMDLINE_TAG /* enable passing of ATAGs */ | 36 | #define CONFIG_CMDLINE_TAG /* enable passing of ATAGs */ |
37 | #define CONFIG_SETUP_MEMORY_TAGS | 37 | #define CONFIG_SETUP_MEMORY_TAGS |
38 | #define CONFIG_INITRD_TAG | 38 | #define CONFIG_INITRD_TAG |
39 | 39 | ||
40 | #define CONFIG_SYS_CACHELINE_SIZE 64 | 40 | #define CONFIG_SYS_CACHELINE_SIZE 64 |
41 | 41 | ||
42 | /* commands to include */ | 42 | /* commands to include */ |
43 | #include <config_cmd_default.h> | 43 | #include <config_cmd_default.h> |
44 | 44 | ||
45 | #define CONFIG_CMD_ASKENV | 45 | #define CONFIG_CMD_ASKENV |
46 | #define CONFIG_CMD_ECHO | 46 | #define CONFIG_CMD_ECHO |
47 | #define CONFIG_CMD_CACHE | 47 | #define CONFIG_CMD_CACHE |
48 | 48 | ||
49 | #define CONFIG_SYS_GENERIC_BOARD | 49 | #define CONFIG_SYS_GENERIC_BOARD |
50 | 50 | ||
51 | #define CONFIG_ENV_VARS_UBOOT_CONFIG | 51 | #define CONFIG_ENV_VARS_UBOOT_CONFIG |
52 | #ifndef CONFIG_SPL_BUILD | 52 | #ifndef CONFIG_SPL_BUILD |
53 | #define CONFIG_ROOTPATH "/opt/eldk" | 53 | #define CONFIG_ROOTPATH "/opt/eldk" |
54 | #endif | 54 | #endif |
55 | 55 | ||
56 | #define CONFIG_ENV_OVERWRITE 1 | 56 | #define CONFIG_ENV_OVERWRITE 1 |
57 | #define CONFIG_ENV_IS_NOWHERE | 57 | #define CONFIG_ENV_IS_NOWHERE |
58 | 58 | ||
59 | #define CONFIG_SYS_LONGHELP | 59 | #define CONFIG_SYS_LONGHELP |
60 | #define CONFIG_CMDLINE_EDITING | 60 | #define CONFIG_CMDLINE_EDITING |
61 | #define CONFIG_AUTO_COMPLETE | 61 | #define CONFIG_AUTO_COMPLETE |
62 | #define CONFIG_SYS_AUTOLOAD "yes" | 62 | #define CONFIG_SYS_AUTOLOAD "yes" |
63 | 63 | ||
64 | /* Clock Defines */ | 64 | /* Clock Defines */ |
65 | #define V_OSCK 24000000 /* Clock output from T2 */ | 65 | #define V_OSCK 24000000 /* Clock output from T2 */ |
66 | #define V_SCLK (V_OSCK) | 66 | #define V_SCLK (V_OSCK) |
67 | 67 | ||
68 | /* We set the max number of command args high to avoid HUSH bugs. */ | 68 | /* We set the max number of command args high to avoid HUSH bugs. */ |
69 | #define CONFIG_SYS_MAXARGS 32 | 69 | #define CONFIG_SYS_MAXARGS 32 |
70 | 70 | ||
71 | /* Console I/O Buffer Size */ | 71 | /* Console I/O Buffer Size */ |
72 | #define CONFIG_SYS_CBSIZE 512 | 72 | #define CONFIG_SYS_CBSIZE 512 |
73 | 73 | ||
74 | /* Print Buffer Size */ | 74 | /* Print Buffer Size */ |
75 | #define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE \ | 75 | #define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE \ |
76 | + sizeof(CONFIG_SYS_PROMPT) + 16) | 76 | + sizeof(CONFIG_SYS_PROMPT) + 16) |
77 | 77 | ||
78 | /* Boot Argument Buffer Size */ | 78 | /* Boot Argument Buffer Size */ |
79 | #define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE | 79 | #define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE |
80 | 80 | ||
81 | /* | 81 | /* |
82 | * memtest works on 8 MB in DRAM after skipping 32MB from | 82 | * memtest works on 8 MB in DRAM after skipping 32MB from |
83 | * start addr of ram disk | 83 | * start addr of ram disk |
84 | */ | 84 | */ |
85 | #define CONFIG_SYS_MEMTEST_START (PHYS_DRAM_1 + (64 * 1024 * 1024)) | 85 | #define CONFIG_SYS_MEMTEST_START (PHYS_DRAM_1 + (64 * 1024 * 1024)) |
86 | #define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_MEMTEST_START \ | 86 | #define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_MEMTEST_START \ |
87 | + (8 * 1024 * 1024)) | 87 | + (8 * 1024 * 1024)) |
88 | 88 | ||
89 | #define CONFIG_SYS_LOAD_ADDR 0x81000000 /* Default load address */ | 89 | #define CONFIG_SYS_LOAD_ADDR 0x81000000 /* Default load address */ |
90 | 90 | ||
91 | #define CONFIG_MMC | 91 | #define CONFIG_MMC |
92 | #define CONFIG_GENERIC_MMC | 92 | #define CONFIG_GENERIC_MMC |
93 | #define CONFIG_OMAP_HSMMC | 93 | #define CONFIG_OMAP_HSMMC |
94 | #define CONFIG_CMD_MMC | 94 | #define CONFIG_CMD_MMC |
95 | #define CONFIG_DOS_PARTITION | 95 | #define CONFIG_DOS_PARTITION |
96 | #define CONFIG_CMD_FAT | 96 | #define CONFIG_CMD_FAT |
97 | #define CONFIG_CMD_EXT2 | 97 | #define CONFIG_CMD_EXT2 |
98 | 98 | ||
99 | #define CONFIG_SPI | 99 | #define CONFIG_SPI |
100 | #define CONFIG_OMAP3_SPI | 100 | #define CONFIG_OMAP3_SPI |
101 | #define CONFIG_MTD_DEVICE | 101 | #define CONFIG_MTD_DEVICE |
102 | #define CONFIG_SPI_FLASH | 102 | #define CONFIG_SPI_FLASH |
103 | #define CONFIG_SPI_FLASH_WINBOND | 103 | #define CONFIG_SPI_FLASH_WINBOND |
104 | #define CONFIG_CMD_SF | 104 | #define CONFIG_CMD_SF |
105 | #define CONFIG_SF_DEFAULT_SPEED (75000000) | 105 | #define CONFIG_SF_DEFAULT_SPEED (75000000) |
106 | 106 | ||
107 | /* Physical Memory Map */ | 107 | /* Physical Memory Map */ |
108 | #define CONFIG_NR_DRAM_BANKS 1 /* 1 bank of DRAM */ | 108 | #define CONFIG_NR_DRAM_BANKS 1 /* 1 bank of DRAM */ |
109 | #define PHYS_DRAM_1 0x80000000 /* DRAM Bank #1 */ | 109 | #define PHYS_DRAM_1 0x80000000 /* DRAM Bank #1 */ |
110 | 110 | ||
111 | #define CONFIG_SYS_SDRAM_BASE PHYS_DRAM_1 | 111 | #define CONFIG_SYS_SDRAM_BASE PHYS_DRAM_1 |
112 | #define CONFIG_SYS_INIT_SP_ADDR (NON_SECURE_SRAM_END - \ | 112 | #define CONFIG_SYS_INIT_SP_ADDR (NON_SECURE_SRAM_END - \ |
113 | GENERATED_GBL_DATA_SIZE) | 113 | GENERATED_GBL_DATA_SIZE) |
114 | /* Platform/Board specific defs */ | 114 | /* Platform/Board specific defs */ |
115 | #define CONFIG_SYS_TIMERBASE 0x48040000 /* Use Timer2 */ | 115 | #define CONFIG_SYS_TIMERBASE 0x48040000 /* Use Timer2 */ |
116 | #define CONFIG_SYS_PTV 2 /* Divisor: 2^(PTV+1) => 8 */ | 116 | #define CONFIG_SYS_PTV 2 /* Divisor: 2^(PTV+1) => 8 */ |
117 | 117 | ||
118 | /* NS16550 Configuration */ | 118 | /* NS16550 Configuration */ |
119 | #define CONFIG_SYS_NS16550 | 119 | #define CONFIG_SYS_NS16550 |
120 | #define CONFIG_SYS_NS16550_SERIAL | 120 | #define CONFIG_SYS_NS16550_SERIAL |
121 | #define CONFIG_SERIAL_MULTI | 121 | #define CONFIG_SERIAL_MULTI |
122 | #define CONFIG_SYS_NS16550_REG_SIZE (-4) | 122 | #define CONFIG_SYS_NS16550_REG_SIZE (-4) |
123 | #define CONFIG_SYS_NS16550_CLK (48000000) | 123 | #define CONFIG_SYS_NS16550_CLK (48000000) |
124 | #define CONFIG_SYS_NS16550_COM1 0x44e09000 | 124 | #define CONFIG_SYS_NS16550_COM1 0x44e09000 |
125 | #define CONFIG_SYS_NS16550_COM4 0x481a6000 | 125 | #define CONFIG_SYS_NS16550_COM4 0x481a6000 |
126 | 126 | ||
127 | #define CONFIG_BAUDRATE 115200 | 127 | #define CONFIG_BAUDRATE 115200 |
128 | 128 | ||
129 | #define CONFIG_SYS_CONSOLE_INFO_QUIET | 129 | #define CONFIG_SYS_CONSOLE_INFO_QUIET |
130 | #define CONFIG_SERIAL1 1 | 130 | #define CONFIG_SERIAL1 1 |
131 | #define CONFIG_CONS_INDEX 1 | 131 | #define CONFIG_CONS_INDEX 1 |
132 | 132 | ||
133 | /* I2C Configuration */ | 133 | /* I2C Configuration */ |
134 | #define CONFIG_I2C | 134 | #define CONFIG_I2C |
135 | #define CONFIG_CMD_I2C | 135 | #define CONFIG_CMD_I2C |
136 | #define CONFIG_SYS_I2C | 136 | #define CONFIG_SYS_I2C |
137 | #define CONFIG_SYS_OMAP24_I2C_SPEED OMAP_I2C_STANDARD | 137 | #define CONFIG_SYS_OMAP24_I2C_SPEED OMAP_I2C_STANDARD |
138 | #define CONFIG_SYS_OMAP24_I2C_SLAVE 1 | 138 | #define CONFIG_SYS_OMAP24_I2C_SLAVE 1 |
139 | #define CONFIG_SYS_I2C_OMAP24XX | 139 | #define CONFIG_SYS_I2C_OMAP24XX |
140 | 140 | ||
141 | /* Defines for SPL */ | 141 | /* Defines for SPL */ |
142 | #define CONFIG_SPL_FRAMEWORK | 142 | #define CONFIG_SPL_FRAMEWORK |
143 | #define CONFIG_SPL_TEXT_BASE 0x402F0400 | 143 | #define CONFIG_SPL_TEXT_BASE 0x402F0400 |
144 | #define CONFIG_SPL_MAX_SIZE (101 * 1024) | 144 | #define CONFIG_SPL_MAX_SIZE (101 * 1024) |
145 | #define CONFIG_SPL_STACK CONFIG_SYS_INIT_SP_ADDR | 145 | #define CONFIG_SPL_STACK CONFIG_SYS_INIT_SP_ADDR |
146 | 146 | ||
147 | #define CONFIG_SPL_BSS_START_ADDR 0x80000000 | 147 | #define CONFIG_SPL_BSS_START_ADDR 0x80000000 |
148 | #define CONFIG_SPL_BSS_MAX_SIZE 0x80000 /* 512 KB */ | 148 | #define CONFIG_SPL_BSS_MAX_SIZE 0x80000 /* 512 KB */ |
149 | 149 | ||
150 | #define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x300 /* address 0x60000 */ | 150 | #define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x300 /* address 0x60000 */ |
151 | #define CONFIG_SYS_MMC_SD_FAT_BOOT_PARTITION 1 | 151 | #define CONFIG_SYS_MMC_SD_FAT_BOOT_PARTITION 1 |
152 | #define CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME "u-boot.img" | 152 | #define CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME "u-boot.img" |
153 | #define CONFIG_SPL_MMC_SUPPORT | 153 | #define CONFIG_SPL_MMC_SUPPORT |
154 | #define CONFIG_SPL_FAT_SUPPORT | 154 | #define CONFIG_SPL_FAT_SUPPORT |
155 | #define CONFIG_FS_FAT | 155 | #define CONFIG_FS_FAT |
156 | #define CONFIG_SPL_I2C_SUPPORT | 156 | #define CONFIG_SPL_I2C_SUPPORT |
157 | 157 | ||
158 | #define CONFIG_SPL_LIBCOMMON_SUPPORT | 158 | #define CONFIG_SPL_LIBCOMMON_SUPPORT |
159 | #define CONFIG_SPL_LIBDISK_SUPPORT | 159 | #define CONFIG_SPL_LIBDISK_SUPPORT |
160 | #define CONFIG_SPL_LIBGENERIC_SUPPORT | 160 | #define CONFIG_SPL_LIBGENERIC_SUPPORT |
161 | #define CONFIG_SPL_SERIAL_SUPPORT | 161 | #define CONFIG_SPL_SERIAL_SUPPORT |
162 | #define CONFIG_SPL_YMODEM_SUPPORT | 162 | #define CONFIG_SPL_YMODEM_SUPPORT |
163 | 163 | ||
164 | #define CONFIG_SPL_GPIO_SUPPORT | 164 | #define CONFIG_SPL_GPIO_SUPPORT |
165 | #define CONFIG_SPL_WATCHDOG_SUPPORT | 165 | #define CONFIG_SPL_WATCHDOG_SUPPORT |
166 | 166 | ||
167 | #define CONFIG_SPL_SPI_SUPPORT | 167 | #define CONFIG_SPL_SPI_SUPPORT |
168 | #define CONFIG_SPL_SPI_FLASH_SUPPORT | 168 | #define CONFIG_SPL_SPI_FLASH_SUPPORT |
169 | #define CONFIG_SPL_SPI_LOAD | 169 | #define CONFIG_SPL_SPI_LOAD |
170 | #define CONFIG_SYS_SPI_U_BOOT_OFFS 0x20000 | 170 | #define CONFIG_SYS_SPI_U_BOOT_OFFS 0x20000 |
171 | 171 | ||
172 | #define CONFIG_SPL_LDSCRIPT "$(CPUDIR)/am33xx/u-boot-spl.lds" | 172 | #define CONFIG_SPL_LDSCRIPT "$(CPUDIR)/am33xx/u-boot-spl.lds" |
173 | 173 | ||
174 | #define CONFIG_SPL_BOARD_INIT | 174 | #define CONFIG_SPL_BOARD_INIT |
175 | #define CONFIG_SPL_NAND_AM33XX_BCH | 175 | #define CONFIG_SPL_NAND_AM33XX_BCH |
176 | #define CONFIG_SPL_NAND_SUPPORT | 176 | #define CONFIG_SPL_NAND_SUPPORT |
177 | #define CONFIG_SPL_NAND_BASE | 177 | #define CONFIG_SPL_NAND_BASE |
178 | #define CONFIG_SPL_NAND_DRIVERS | 178 | #define CONFIG_SPL_NAND_DRIVERS |
179 | #define CONFIG_SPL_NAND_ECC | 179 | #define CONFIG_SPL_NAND_ECC |
180 | #define CONFIG_SYS_NAND_5_ADDR_CYCLE | 180 | #define CONFIG_SYS_NAND_5_ADDR_CYCLE |
181 | #define CONFIG_SYS_NAND_PAGE_COUNT (CONFIG_SYS_NAND_BLOCK_SIZE / \ | 181 | #define CONFIG_SYS_NAND_PAGE_COUNT (CONFIG_SYS_NAND_BLOCK_SIZE / \ |
182 | CONFIG_SYS_NAND_PAGE_SIZE) | 182 | CONFIG_SYS_NAND_PAGE_SIZE) |
183 | #define CONFIG_SYS_NAND_PAGE_SIZE 2048 | 183 | #define CONFIG_SYS_NAND_PAGE_SIZE 2048 |
184 | #define CONFIG_SYS_NAND_OOBSIZE 64 | 184 | #define CONFIG_SYS_NAND_OOBSIZE 64 |
185 | #define CONFIG_SYS_NAND_BLOCK_SIZE (128*1024) | 185 | #define CONFIG_SYS_NAND_BLOCK_SIZE (128*1024) |
186 | #define CONFIG_SYS_NAND_BAD_BLOCK_POS NAND_LARGE_BADBLOCK_POS | 186 | #define CONFIG_SYS_NAND_BAD_BLOCK_POS NAND_LARGE_BADBLOCK_POS |
187 | #define CONFIG_SYS_NAND_ECCPOS { 2, 3, 4, 5, 6, 7, 8, 9, \ | 187 | #define CONFIG_SYS_NAND_ECCPOS { 2, 3, 4, 5, 6, 7, 8, 9, \ |
188 | 10, 11, 12, 13, 14, 15, 16, 17, \ | 188 | 10, 11, 12, 13, 14, 15, 16, 17, \ |
189 | 18, 19, 20, 21, 22, 23, 24, 25, \ | 189 | 18, 19, 20, 21, 22, 23, 24, 25, \ |
190 | 26, 27, 28, 29, 30, 31, 32, 33, \ | 190 | 26, 27, 28, 29, 30, 31, 32, 33, \ |
191 | 34, 35, 36, 37, 38, 39, 40, 41, \ | 191 | 34, 35, 36, 37, 38, 39, 40, 41, \ |
192 | 42, 43, 44, 45, 46, 47, 48, 49, \ | 192 | 42, 43, 44, 45, 46, 47, 48, 49, \ |
193 | 50, 51, 52, 53, 54, 55, 56, 57, } | 193 | 50, 51, 52, 53, 54, 55, 56, 57, } |
194 | 194 | ||
195 | #define CONFIG_SYS_NAND_ECCSIZE 512 | 195 | #define CONFIG_SYS_NAND_ECCSIZE 512 |
196 | #define CONFIG_SYS_NAND_ECCBYTES 14 | 196 | #define CONFIG_SYS_NAND_ECCBYTES 14 |
197 | #define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_BCH8_CODE_HW | 197 | #define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_BCH8_CODE_HW |
198 | 198 | ||
199 | #define CONFIG_SYS_NAND_ECCSTEPS 4 | 199 | #define CONFIG_SYS_NAND_ECCSTEPS 4 |
200 | #define CONFIG_SYS_NAND_ECCTOTAL (CONFIG_SYS_NAND_ECCBYTES * \ | 200 | #define CONFIG_SYS_NAND_ECCTOTAL (CONFIG_SYS_NAND_ECCBYTES * \ |
201 | CONFIG_SYS_NAND_ECCSTEPS) | 201 | CONFIG_SYS_NAND_ECCSTEPS) |
202 | 202 | ||
203 | #define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE | 203 | #define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE |
204 | 204 | ||
205 | #define CONFIG_SYS_NAND_U_BOOT_OFFS 0x80000 | 205 | #define CONFIG_SYS_NAND_U_BOOT_OFFS 0x80000 |
206 | 206 | ||
207 | /* | 207 | /* |
208 | * 1MB into the SDRAM to allow for SPL's bss at the beginning of SDRAM | 208 | * 1MB into the SDRAM to allow for SPL's bss at the beginning of SDRAM |
209 | * 64 bytes before this address should be set aside for u-boot.img's | 209 | * 64 bytes before this address should be set aside for u-boot.img's |
210 | * header. That is 0x800FFFC0--0x80100000 should not be used for any | 210 | * header. That is 0x800FFFC0--0x80100000 should not be used for any |
211 | * other needs. | 211 | * other needs. |
212 | */ | 212 | */ |
213 | #define CONFIG_SYS_TEXT_BASE 0x80100000 | 213 | #define CONFIG_SYS_TEXT_BASE 0x80100000 |
214 | #define CONFIG_SYS_SPL_MALLOC_START 0x80208000 | 214 | #define CONFIG_SYS_SPL_MALLOC_START 0x80208000 |
215 | #define CONFIG_SYS_SPL_MALLOC_SIZE 0x100000 | 215 | #define CONFIG_SYS_SPL_MALLOC_SIZE 0x100000 |
216 | 216 | ||
217 | /* | 217 | /* |
218 | * Since SPL did pll and ddr initialization for us, | 218 | * Since SPL did pll and ddr initialization for us, |
219 | * we don't need to do it twice. | 219 | * we don't need to do it twice. |
220 | */ | 220 | */ |
221 | #ifndef CONFIG_SPL_BUILD | 221 | #ifndef CONFIG_SPL_BUILD |
222 | #define CONFIG_SKIP_LOWLEVEL_INIT | 222 | #define CONFIG_SKIP_LOWLEVEL_INIT |
223 | #endif | 223 | #endif |
224 | 224 | ||
225 | #ifndef CONFIG_SPL_BUILD | 225 | #ifndef CONFIG_SPL_BUILD |
226 | /* | 226 | /* |
227 | * USB configuration | 227 | * USB configuration |
228 | */ | 228 | */ |
229 | #define CONFIG_USB_MUSB_DSPS | 229 | #define CONFIG_USB_MUSB_DSPS |
230 | #define CONFIG_ARCH_MISC_INIT | 230 | #define CONFIG_ARCH_MISC_INIT |
231 | #define CONFIG_MUSB_GADGET | 231 | #define CONFIG_MUSB_GADGET |
232 | #define CONFIG_MUSB_PIO_ONLY | 232 | #define CONFIG_MUSB_PIO_ONLY |
233 | #define CONFIG_MUSB_DISABLE_BULK_COMBINE_SPLIT | 233 | #define CONFIG_MUSB_DISABLE_BULK_COMBINE_SPLIT |
234 | #define CONFIG_USB_GADGET_DUALSPEED | 234 | #undef CONFIG_USB_GADGET_DUALSPEED |
235 | #define CONFIG_USB_GADGET_VBUS_DRAW 2 | 235 | #define CONFIG_USB_GADGET_VBUS_DRAW 2 |
236 | #define CONFIG_MUSB_HOST | 236 | #define CONFIG_MUSB_HOST |
237 | 237 | ||
238 | #define CONFIG_AM335X_USB0 | 238 | #define CONFIG_AM335X_USB0 |
239 | #define CONFIG_AM335X_USB0_MODE MUSB_PERIPHERAL | 239 | #define CONFIG_AM335X_USB0_MODE MUSB_PERIPHERAL |
240 | #define CONFIG_AM335X_USB1 | 240 | #define CONFIG_AM335X_USB1 |
241 | #define CONFIG_AM335X_USB1_MODE MUSB_HOST | 241 | #define CONFIG_AM335X_USB1_MODE MUSB_HOST |
242 | #ifdef CONFIG_MUSB_HOST | 242 | #ifdef CONFIG_MUSB_HOST |
243 | #define CONFIG_CMD_USB | 243 | #define CONFIG_CMD_USB |
244 | #define CONFIG_USB_STORAGE | 244 | #define CONFIG_USB_STORAGE |
245 | #endif | 245 | #endif |
246 | 246 | ||
247 | #ifdef CONFIG_MUSB_GADGET | 247 | #ifdef CONFIG_MUSB_GADGET |
248 | #define CONFIG_USB_ETHER | 248 | #define CONFIG_USB_ETHER |
249 | #define CONFIG_USB_ETH_RNDIS | 249 | #define CONFIG_USB_ETH_RNDIS |
250 | #define CONFIG_USBNET_HOST_ADDR "de:ad:be:af:00:00" | 250 | #define CONFIG_USBNET_HOST_ADDR "de:ad:be:af:00:00" |
251 | #endif /* CONFIG_MUSB_GADGET */ | 251 | #endif /* CONFIG_MUSB_GADGET */ |
252 | 252 | ||
253 | #define CONFIG_USB_GADGET | 253 | #define CONFIG_USB_GADGET |
254 | #define CONFIG_USBDOWNLOAD_GADGET | 254 | #define CONFIG_USBDOWNLOAD_GADGET |
255 | 255 | ||
256 | /* USB DRACO ID as default */ | 256 | /* USB DRACO ID as default */ |
257 | #define CONFIG_USBD_HS | 257 | #define CONFIG_USBD_HS |
258 | #define CONFIG_G_DNL_VENDOR_NUM 0x0908 | 258 | #define CONFIG_G_DNL_VENDOR_NUM 0x0908 |
259 | #define CONFIG_G_DNL_PRODUCT_NUM 0x02d2 | 259 | #define CONFIG_G_DNL_PRODUCT_NUM 0x02d2 |
260 | #define CONFIG_G_DNL_MANUFACTURER "Siemens AG" | 260 | #define CONFIG_G_DNL_MANUFACTURER "Siemens AG" |
261 | 261 | ||
262 | /* USB Device Firmware Update support */ | 262 | /* USB Device Firmware Update support */ |
263 | #define CONFIG_DFU_FUNCTION | 263 | #define CONFIG_DFU_FUNCTION |
264 | #define CONFIG_DFU_NAND | 264 | #define CONFIG_DFU_NAND |
265 | #define CONFIG_CMD_DFU | 265 | #define CONFIG_CMD_DFU |
266 | #define CONFIG_SYS_DFU_DATA_BUF_SIZE (1 << 20) | 266 | #define CONFIG_SYS_DFU_DATA_BUF_SIZE (1 << 20) |
267 | #define DFU_MANIFEST_POLL_TIMEOUT 25000 | 267 | #define DFU_MANIFEST_POLL_TIMEOUT 25000 |
268 | 268 | ||
269 | #endif /* CONFIG_SPL_BUILD */ | 269 | #endif /* CONFIG_SPL_BUILD */ |
270 | 270 | ||
271 | /* | 271 | /* |
272 | * Default to using SPI for environment, etc. We have multiple copies | 272 | * Default to using SPI for environment, etc. We have multiple copies |
273 | * of SPL as the ROM will check these locations. | 273 | * of SPL as the ROM will check these locations. |
274 | * 0x0 - 0x20000 : First copy of SPL | 274 | * 0x0 - 0x20000 : First copy of SPL |
275 | * 0x20000 - 0x40000 : Second copy of SPL | 275 | * 0x20000 - 0x40000 : Second copy of SPL |
276 | * 0x40000 - 0x60000 : Third copy of SPL | 276 | * 0x40000 - 0x60000 : Third copy of SPL |
277 | * 0x60000 - 0x80000 : Fourth copy of SPL | 277 | * 0x60000 - 0x80000 : Fourth copy of SPL |
278 | * 0x80000 - 0xDF000 : U-Boot | 278 | * 0x80000 - 0xDF000 : U-Boot |
279 | * 0xDF000 - 0xE0000 : U-Boot Environment | 279 | * 0xDF000 - 0xE0000 : U-Boot Environment |
280 | * 0xE0000 - 0x442000 : Linux Kernel | 280 | * 0xE0000 - 0x442000 : Linux Kernel |
281 | * 0x442000 - 0x800000 : Userland | 281 | * 0x442000 - 0x800000 : Userland |
282 | */ | 282 | */ |
283 | #if defined(CONFIG_SPI_BOOT) | 283 | #if defined(CONFIG_SPI_BOOT) |
284 | # undef CONFIG_ENV_IS_NOWHERE | 284 | # undef CONFIG_ENV_IS_NOWHERE |
285 | # define CONFIG_ENV_IS_IN_SPI_FLASH | 285 | # define CONFIG_ENV_IS_IN_SPI_FLASH |
286 | # define CONFIG_ENV_SPI_MAX_HZ CONFIG_SF_DEFAULT_SPEED | 286 | # define CONFIG_ENV_SPI_MAX_HZ CONFIG_SF_DEFAULT_SPEED |
287 | # define CONFIG_ENV_OFFSET (892 << 10) /* 892 KiB in */ | 287 | # define CONFIG_ENV_OFFSET (892 << 10) /* 892 KiB in */ |
288 | # define CONFIG_ENV_SECT_SIZE (4 << 10) /* 4 KB sectors */ | 288 | # define CONFIG_ENV_SECT_SIZE (4 << 10) /* 4 KB sectors */ |
289 | #endif /* SPI support */ | 289 | #endif /* SPI support */ |
290 | 290 | ||
291 | /* Unsupported features */ | 291 | /* Unsupported features */ |
292 | #undef CONFIG_USE_IRQ | 292 | #undef CONFIG_USE_IRQ |
293 | 293 | ||
294 | #define CONFIG_CMD_NET | 294 | #define CONFIG_CMD_NET |
295 | #define CONFIG_CMD_DHCP | 295 | #define CONFIG_CMD_DHCP |
296 | #define CONFIG_CMD_PING | 296 | #define CONFIG_CMD_PING |
297 | #define CONFIG_DRIVER_TI_CPSW | 297 | #define CONFIG_DRIVER_TI_CPSW |
298 | #define CONFIG_MII | 298 | #define CONFIG_MII |
299 | #define CONFIG_PHY_GIGE | 299 | #define CONFIG_PHY_GIGE |
300 | #define CONFIG_PHYLIB | 300 | #define CONFIG_PHYLIB |
301 | #define CONFIG_CMD_MII | 301 | #define CONFIG_CMD_MII |
302 | #define CONFIG_BOOTP_DEFAULT | 302 | #define CONFIG_BOOTP_DEFAULT |
303 | #define CONFIG_BOOTP_DNS | 303 | #define CONFIG_BOOTP_DNS |
304 | #define CONFIG_BOOTP_DNS2 | 304 | #define CONFIG_BOOTP_DNS2 |
305 | #define CONFIG_BOOTP_SEND_HOSTNAME | 305 | #define CONFIG_BOOTP_SEND_HOSTNAME |
306 | #define CONFIG_BOOTP_GATEWAY | 306 | #define CONFIG_BOOTP_GATEWAY |
307 | #define CONFIG_BOOTP_SUBNETMASK | 307 | #define CONFIG_BOOTP_SUBNETMASK |
308 | #define CONFIG_NET_RETRY_COUNT 10 | 308 | #define CONFIG_NET_RETRY_COUNT 10 |
309 | #define CONFIG_NET_MULTI | 309 | #define CONFIG_NET_MULTI |
310 | 310 | ||
311 | #define CONFIG_NAND | 311 | #define CONFIG_NAND |
312 | /* NAND support */ | 312 | /* NAND support */ |
313 | #ifdef CONFIG_NAND | 313 | #ifdef CONFIG_NAND |
314 | #define CONFIG_CMD_NAND | 314 | #define CONFIG_CMD_NAND |
315 | #define CONFIG_CMD_MTDPARTS | 315 | #define CONFIG_CMD_MTDPARTS |
316 | 316 | ||
317 | #define MTDIDS_NAME_STR "omap2-nand.0" | 317 | #define MTDIDS_NAME_STR "omap2-nand.0" |
318 | #define MTDIDS_DEFAULT "nand0=" MTDIDS_NAME_STR | 318 | #define MTDIDS_DEFAULT "nand0=" MTDIDS_NAME_STR |
319 | #define MTDPARTS_DEFAULT "mtdparts=" MTDIDS_NAME_STR ":" \ | 319 | #define MTDPARTS_DEFAULT "mtdparts=" MTDIDS_NAME_STR ":" \ |
320 | "128k(spl)," \ | 320 | "128k(spl)," \ |
321 | "128k(spl.backup1)," \ | 321 | "128k(spl.backup1)," \ |
322 | "128k(spl.backup2)," \ | 322 | "128k(spl.backup2)," \ |
323 | "128k(spl.backup3)," \ | 323 | "128k(spl.backup3)," \ |
324 | "1920k(u-boot)," \ | 324 | "1920k(u-boot)," \ |
325 | "128k(uboot.env)," \ | 325 | "128k(uboot.env)," \ |
326 | "5120k(kernel_a)," \ | 326 | "5120k(kernel_a)," \ |
327 | "5120k(kernel_b)," \ | 327 | "5120k(kernel_b)," \ |
328 | "8192k(mtdoops)," \ | 328 | "8192k(mtdoops)," \ |
329 | "-(rootfs)" | 329 | "-(rootfs)" |
330 | /* | 330 | /* |
331 | * chip-size = 256MiB | 331 | * chip-size = 256MiB |
332 | *| name | size | address area | | 332 | *| name | size | address area | |
333 | *------------------------------------------------------- | 333 | *------------------------------------------------------- |
334 | *| spl | 128.000 KiB | 0x 0..0x 1ffff | | 334 | *| spl | 128.000 KiB | 0x 0..0x 1ffff | |
335 | *| spl.backup1 | 128.000 KiB | 0x 20000..0x 3ffff | | 335 | *| spl.backup1 | 128.000 KiB | 0x 20000..0x 3ffff | |
336 | *| spl.backup2 | 128.000 KiB | 0x 40000..0x 5ffff | | 336 | *| spl.backup2 | 128.000 KiB | 0x 40000..0x 5ffff | |
337 | *| spl.backup3 | 128.000 KiB | 0x 60000..0x 7ffff | | 337 | *| spl.backup3 | 128.000 KiB | 0x 60000..0x 7ffff | |
338 | *| u-boot | 1.875 MiB | 0x 80000..0x 25ffff | | 338 | *| u-boot | 1.875 MiB | 0x 80000..0x 25ffff | |
339 | *| uboot.env | 128.000 KiB | 0x 260000..0x 27ffff | | 339 | *| uboot.env | 128.000 KiB | 0x 260000..0x 27ffff | |
340 | *| kernel_a | 5.000 MiB | 0x 280000..0x 77ffff | | 340 | *| kernel_a | 5.000 MiB | 0x 280000..0x 77ffff | |
341 | *| kernel_b | 5.000 MiB | 0x 780000..0x c7ffff | | 341 | *| kernel_b | 5.000 MiB | 0x 780000..0x c7ffff | |
342 | *| mtdoops | 8.000 MiB | 0x c80000..0x 147ffff | | 342 | *| mtdoops | 8.000 MiB | 0x c80000..0x 147ffff | |
343 | *| rootfs | 235.500 MiB | 0x 1480000..0x fffffff | | 343 | *| rootfs | 235.500 MiB | 0x 1480000..0x fffffff | |
344 | *------------------------------------------------------- | 344 | *------------------------------------------------------- |
345 | */ | 345 | */ |
346 | 346 | ||
347 | #define DFU_ALT_INFO_NAND \ | 347 | #define DFU_ALT_INFO_NAND \ |
348 | "spl part 0 1;" \ | 348 | "spl part 0 1;" \ |
349 | "spl.backup1 part 0 2;" \ | 349 | "spl.backup1 part 0 2;" \ |
350 | "spl.backup2 part 0 3;" \ | 350 | "spl.backup2 part 0 3;" \ |
351 | "spl.backup3 part 0 4;" \ | 351 | "spl.backup3 part 0 4;" \ |
352 | "u-boot part 0 5;" \ | 352 | "u-boot part 0 5;" \ |
353 | "u-boot.env part 0 6;" \ | 353 | "u-boot.env part 0 6;" \ |
354 | "kernel_a part 0 7;" \ | 354 | "kernel_a part 0 7;" \ |
355 | "kernel_b part 0 8;" \ | 355 | "kernel_b part 0 8;" \ |
356 | "rootfs partubi 0 10" | 356 | "rootfs partubi 0 10" |
357 | 357 | ||
358 | #define CONFIG_COMMON_ENV_SETTINGS \ | 358 | #define CONFIG_COMMON_ENV_SETTINGS \ |
359 | "verify=no \0" \ | 359 | "verify=no \0" \ |
360 | "project_dir=targetdir\0" \ | 360 | "project_dir=targetdir\0" \ |
361 | "upgrade_available=0\0" \ | 361 | "upgrade_available=0\0" \ |
362 | "altbootcmd=run bootcmd\0" \ | 362 | "altbootcmd=run bootcmd\0" \ |
363 | "bootlimit=3\0" \ | 363 | "bootlimit=3\0" \ |
364 | "partitionset_active=A\0" \ | 364 | "partitionset_active=A\0" \ |
365 | "loadaddr=0x82000000\0" \ | 365 | "loadaddr=0x82000000\0" \ |
366 | "kloadaddr=0x81000000\0" \ | 366 | "kloadaddr=0x81000000\0" \ |
367 | "script_addr=0x81900000\0" \ | 367 | "script_addr=0x81900000\0" \ |
368 | "console=console=ttyMTD,mtdoops console=ttyO0,115200n8 panic=5\0" \ | 368 | "console=console=ttyMTD,mtdoops console=ttyO0,115200n8 panic=5\0" \ |
369 | "nand_active_ubi_vol=rootfs_a\0" \ | 369 | "nand_active_ubi_vol=rootfs_a\0" \ |
370 | "nand_active_ubi_vol_A=rootfs_a\0" \ | 370 | "nand_active_ubi_vol_A=rootfs_a\0" \ |
371 | "nand_active_ubi_vol_B=rootfs_b\0" \ | 371 | "nand_active_ubi_vol_B=rootfs_b\0" \ |
372 | "nand_root_fs_type=ubifs rootwait=1\0" \ | 372 | "nand_root_fs_type=ubifs rootwait=1\0" \ |
373 | "nand_src_addr=0x280000\0" \ | 373 | "nand_src_addr=0x280000\0" \ |
374 | "nand_src_addr_A=0x280000\0" \ | 374 | "nand_src_addr_A=0x280000\0" \ |
375 | "nand_src_addr_B=0x780000\0" \ | 375 | "nand_src_addr_B=0x780000\0" \ |
376 | "nfsopts=nolock rw mem=128M\0" \ | 376 | "nfsopts=nolock rw mem=128M\0" \ |
377 | "ip_method=none\0" \ | 377 | "ip_method=none\0" \ |
378 | "bootenv=uEnv.txt\0" \ | 378 | "bootenv=uEnv.txt\0" \ |
379 | "bootargs_defaults=setenv bootargs " \ | 379 | "bootargs_defaults=setenv bootargs " \ |
380 | "console=${console} " \ | 380 | "console=${console} " \ |
381 | "${testargs} " \ | 381 | "${testargs} " \ |
382 | "${optargs}\0" \ | 382 | "${optargs}\0" \ |
383 | "nand_args=run bootargs_defaults;" \ | 383 | "nand_args=run bootargs_defaults;" \ |
384 | "mtdparts default;" \ | 384 | "mtdparts default;" \ |
385 | "setenv ${partitionset_active} true;" \ | 385 | "setenv ${partitionset_active} true;" \ |
386 | "if test -n ${A}; then " \ | 386 | "if test -n ${A}; then " \ |
387 | "setenv nand_active_ubi_vol ${nand_active_ubi_vol_A};" \ | 387 | "setenv nand_active_ubi_vol ${nand_active_ubi_vol_A};" \ |
388 | "setenv nand_src_addr ${nand_src_addr_A};" \ | 388 | "setenv nand_src_addr ${nand_src_addr_A};" \ |
389 | "fi;" \ | 389 | "fi;" \ |
390 | "if test -n ${B}; then " \ | 390 | "if test -n ${B}; then " \ |
391 | "setenv nand_active_ubi_vol ${nand_active_ubi_vol_B};" \ | 391 | "setenv nand_active_ubi_vol ${nand_active_ubi_vol_B};" \ |
392 | "setenv nand_src_addr ${nand_src_addr_B};" \ | 392 | "setenv nand_src_addr ${nand_src_addr_B};" \ |
393 | "fi;" \ | 393 | "fi;" \ |
394 | "setenv nand_root ubi0:${nand_active_ubi_vol} rw " \ | 394 | "setenv nand_root ubi0:${nand_active_ubi_vol} rw " \ |
395 | "ubi.mtd=9,2048;" \ | 395 | "ubi.mtd=9,2048;" \ |
396 | "setenv bootargs ${bootargs} " \ | 396 | "setenv bootargs ${bootargs} " \ |
397 | "root=${nand_root} noinitrd ${mtdparts} " \ | 397 | "root=${nand_root} noinitrd ${mtdparts} " \ |
398 | "rootfstype=${nand_root_fs_type} ip=${ip_method} " \ | 398 | "rootfstype=${nand_root_fs_type} ip=${ip_method} " \ |
399 | "console=ttyMTD,mtdoops console=ttyO0,115200n8 mtdoops.mtddev" \ | 399 | "console=ttyMTD,mtdoops console=ttyO0,115200n8 mtdoops.mtddev" \ |
400 | "=mtdoops\0" \ | 400 | "=mtdoops\0" \ |
401 | "dfu_args=run bootargs_defaults;" \ | 401 | "dfu_args=run bootargs_defaults;" \ |
402 | "setenv bootargs ${bootargs} ;" \ | 402 | "setenv bootargs ${bootargs} ;" \ |
403 | "mtdparts default; " \ | 403 | "mtdparts default; " \ |
404 | "led dfu 1;" \ | 404 | "led dfu 1;" \ |
405 | "led stat 0;" \ | 405 | "led stat 0;" \ |
406 | "dfu 0 nand 0;" \ | 406 | "dfu 0 nand 0;" \ |
407 | "led dfu 0;" \ | 407 | "led dfu 0;" \ |
408 | "led stat 1;\0" \ | 408 | "led stat 1;\0" \ |
409 | "dfu_alt_info=" DFU_ALT_INFO_NAND "\0" \ | 409 | "dfu_alt_info=" DFU_ALT_INFO_NAND "\0" \ |
410 | "net_args=run bootargs_defaults;" \ | 410 | "net_args=run bootargs_defaults;" \ |
411 | "mtdparts default;" \ | 411 | "mtdparts default;" \ |
412 | "setenv bootfile ${project_dir}/kernel/uImage;" \ | 412 | "setenv bootfile ${project_dir}/kernel/uImage;" \ |
413 | "setenv rootpath /home/projects/${project_dir}/rootfs;" \ | 413 | "setenv rootpath /home/projects/${project_dir}/rootfs;" \ |
414 | "setenv bootargs ${bootargs} " \ | 414 | "setenv bootargs ${bootargs} " \ |
415 | "root=/dev/nfs ${mtdparts} " \ | 415 | "root=/dev/nfs ${mtdparts} " \ |
416 | "nfsroot=${serverip}:${rootpath},${nfsopts} " \ | 416 | "nfsroot=${serverip}:${rootpath},${nfsopts} " \ |
417 | "ip=${ipaddr}:${serverip}:" \ | 417 | "ip=${ipaddr}:${serverip}:" \ |
418 | "${gatewayip}:${netmask}:${hostname}:eth0:off\0" \ | 418 | "${gatewayip}:${netmask}:${hostname}:eth0:off\0" \ |
419 | "nand_boot=echo Booting from nand; " \ | 419 | "nand_boot=echo Booting from nand; " \ |
420 | "if test ${upgrade_available} -eq 1; then " \ | 420 | "if test ${upgrade_available} -eq 1; then " \ |
421 | "if test ${bootcount} -gt ${bootlimit}; " \ | 421 | "if test ${bootcount} -gt ${bootlimit}; " \ |
422 | "then " \ | 422 | "then " \ |
423 | "setenv upgrade_available 0;" \ | 423 | "setenv upgrade_available 0;" \ |
424 | "setenv ${partitionset_active} true;" \ | 424 | "setenv ${partitionset_active} true;" \ |
425 | "if test -n ${A}; then " \ | 425 | "if test -n ${A}; then " \ |
426 | "setenv partitionset_active B; " \ | 426 | "setenv partitionset_active B; " \ |
427 | "env delete A; " \ | 427 | "env delete A; " \ |
428 | "fi;" \ | 428 | "fi;" \ |
429 | "if test -n ${B}; then " \ | 429 | "if test -n ${B}; then " \ |
430 | "setenv partitionset_active A; " \ | 430 | "setenv partitionset_active A; " \ |
431 | "env delete B; " \ | 431 | "env delete B; " \ |
432 | "fi;" \ | 432 | "fi;" \ |
433 | "saveenv; " \ | 433 | "saveenv; " \ |
434 | "fi;" \ | 434 | "fi;" \ |
435 | "fi;" \ | 435 | "fi;" \ |
436 | "echo set ${partitionset_active}...;" \ | 436 | "echo set ${partitionset_active}...;" \ |
437 | "run nand_args; " \ | 437 | "run nand_args; " \ |
438 | "nand read.i ${kloadaddr} ${nand_src_addr} " \ | 438 | "nand read.i ${kloadaddr} ${nand_src_addr} " \ |
439 | "${nand_img_size}; bootm ${kloadaddr}\0" \ | 439 | "${nand_img_size}; bootm ${kloadaddr}\0" \ |
440 | "net_nfs=echo Booting from network ...; " \ | 440 | "net_nfs=echo Booting from network ...; " \ |
441 | "run net_args; " \ | 441 | "run net_args; " \ |
442 | "tftpboot ${kloadaddr} ${serverip}:${bootfile}; " \ | 442 | "tftpboot ${kloadaddr} ${serverip}:${bootfile}; " \ |
443 | "bootm ${kloadaddr}\0" \ | 443 | "bootm ${kloadaddr}\0" \ |
444 | "flash_self=run nand_boot\0" \ | 444 | "flash_self=run nand_boot\0" \ |
445 | "flash_self_test=setenv testargs test; " \ | 445 | "flash_self_test=setenv testargs test; " \ |
446 | "run nand_boot\0" \ | 446 | "run nand_boot\0" \ |
447 | "dfu_start=echo Preparing for dfu mode ...; " \ | 447 | "dfu_start=echo Preparing for dfu mode ...; " \ |
448 | "run dfu_args; \0" \ | 448 | "run dfu_args; \0" \ |
449 | "preboot=echo; "\ | 449 | "preboot=echo; "\ |
450 | "echo Type 'run flash_self' to use kernel and root " \ | 450 | "echo Type 'run flash_self' to use kernel and root " \ |
451 | "filesystem on memory; echo Type 'run flash_self_test' to " \ | 451 | "filesystem on memory; echo Type 'run flash_self_test' to " \ |
452 | "use kernel and root filesystem on memory, boot in test " \ | 452 | "use kernel and root filesystem on memory, boot in test " \ |
453 | "mode; echo Not ready yet: 'run flash_nfs' to use kernel " \ | 453 | "mode; echo Not ready yet: 'run flash_nfs' to use kernel " \ |
454 | "from memory and root filesystem over NFS; echo Type " \ | 454 | "from memory and root filesystem over NFS; echo Type " \ |
455 | "'run net_nfs' to get Kernel over TFTP and mount root " \ | 455 | "'run net_nfs' to get Kernel over TFTP and mount root " \ |
456 | "filesystem over NFS; " \ | 456 | "filesystem over NFS; " \ |
457 | "echo Set partitionset_active variable to 'A' " \ | 457 | "echo Set partitionset_active variable to 'A' " \ |
458 | "or 'B' to select kernel and rootfs partition; " \ | 458 | "or 'B' to select kernel and rootfs partition; " \ |
459 | "echo" \ | 459 | "echo" \ |
460 | "\0" | 460 | "\0" |
461 | 461 | ||
462 | #define CONFIG_NAND_OMAP_GPMC | 462 | #define CONFIG_NAND_OMAP_GPMC |
463 | #define CONFIG_NAND_OMAP_ELM | 463 | #define CONFIG_NAND_OMAP_ELM |
464 | #define CONFIG_SYS_NAND_BASE (0x08000000) /* physical address */ | 464 | #define CONFIG_SYS_NAND_BASE (0x08000000) /* physical address */ |
465 | /* to access nand at */ | 465 | /* to access nand at */ |
466 | /* CS0 */ | 466 | /* CS0 */ |
467 | #define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND | 467 | #define CONFIG_SYS_MAX_NAND_DEVICE 1 /* Max number of NAND |
468 | devices */ | 468 | devices */ |
469 | #if !defined(CONFIG_SPI_BOOT) | 469 | #if !defined(CONFIG_SPI_BOOT) |
470 | #undef CONFIG_ENV_IS_NOWHERE | 470 | #undef CONFIG_ENV_IS_NOWHERE |
471 | #define CONFIG_ENV_IS_IN_NAND | 471 | #define CONFIG_ENV_IS_IN_NAND |
472 | #define CONFIG_ENV_OFFSET 0x260000 /* environment starts here */ | 472 | #define CONFIG_ENV_OFFSET 0x260000 /* environment starts here */ |
473 | #define CONFIG_SYS_ENV_SECT_SIZE (128 << 10) /* 128 KiB */ | 473 | #define CONFIG_SYS_ENV_SECT_SIZE (128 << 10) /* 128 KiB */ |
474 | #endif | 474 | #endif |
475 | #endif | 475 | #endif |
476 | 476 | ||
477 | #define CONFIG_OMAP_GPIO | 477 | #define CONFIG_OMAP_GPIO |
478 | 478 | ||
479 | /* Watchdog */ | 479 | /* Watchdog */ |
480 | #define CONFIG_HW_WATCHDOG | 480 | #define CONFIG_HW_WATCHDOG |
481 | 481 | ||
482 | /* Stop autoboot with ESC ESC key detected */ | 482 | /* Stop autoboot with ESC ESC key detected */ |
483 | #define CONFIG_AUTOBOOT_KEYED | 483 | #define CONFIG_AUTOBOOT_KEYED |
484 | #define CONFIG_AUTOBOOT_STOP_STR "\x1b\x1b" | 484 | #define CONFIG_AUTOBOOT_STOP_STR "\x1b\x1b" |
485 | #define CONFIG_AUTOBOOT_PROMPT "Autobooting in %d seconds, " \ | 485 | #define CONFIG_AUTOBOOT_PROMPT "Autobooting in %d seconds, " \ |
486 | "press \"<Esc><Esc>\" to stop\n", bootdelay | 486 | "press \"<Esc><Esc>\" to stop\n", bootdelay |
487 | 487 | ||
488 | /* Reboot after 60 sec if bootcmd fails */ | 488 | /* Reboot after 60 sec if bootcmd fails */ |
489 | #define CONFIG_RESET_TO_RETRY | 489 | #define CONFIG_RESET_TO_RETRY |
490 | #define CONFIG_BOOT_RETRY_TIME 60 | 490 | #define CONFIG_BOOT_RETRY_TIME 60 |
491 | 491 | ||
492 | #define CONFIG_BOOTCOUNT_LIMIT | 492 | #define CONFIG_BOOTCOUNT_LIMIT |
493 | #define CONFIG_BOOTCOUNT_ENV | 493 | #define CONFIG_BOOTCOUNT_ENV |
494 | 494 | ||
495 | /* Enable Device-Tree (FDT) support */ | 495 | /* Enable Device-Tree (FDT) support */ |
496 | #define CONFIG_OF_LIBFDT | 496 | #define CONFIG_OF_LIBFDT |
497 | #define CONFIG_CMD_FDT | 497 | #define CONFIG_CMD_FDT |
498 | 498 | ||
499 | #endif /* ! __CONFIG_SIEMENS_AM33X_COMMON_H */ | 499 | #endif /* ! __CONFIG_SIEMENS_AM33X_COMMON_H */ |
500 | 500 |
include/stdio_dev.h
1 | /* | 1 | /* |
2 | * (C) Copyright 2000 | 2 | * (C) Copyright 2000 |
3 | * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it | 3 | * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it |
4 | * | 4 | * |
5 | * SPDX-License-Identifier: GPL-2.0+ | 5 | * SPDX-License-Identifier: GPL-2.0+ |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #ifndef _STDIO_DEV_H_ | 8 | #ifndef _STDIO_DEV_H_ |
9 | #define _STDIO_DEV_H_ | 9 | #define _STDIO_DEV_H_ |
10 | 10 | ||
11 | #include <linux/list.h> | 11 | #include <linux/list.h> |
12 | 12 | ||
13 | /* | 13 | /* |
14 | * STDIO DEVICES | 14 | * STDIO DEVICES |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #define DEV_FLAGS_INPUT 0x00000001 /* Device can be used as input console */ | 17 | #define DEV_FLAGS_INPUT 0x00000001 /* Device can be used as input console */ |
18 | #define DEV_FLAGS_OUTPUT 0x00000002 /* Device can be used as output console */ | 18 | #define DEV_FLAGS_OUTPUT 0x00000002 /* Device can be used as output console */ |
19 | #define DEV_FLAGS_SYSTEM 0x80000000 /* Device is a system device */ | 19 | #define DEV_FLAGS_SYSTEM 0x80000000 /* Device is a system device */ |
20 | #define DEV_EXT_VIDEO 0x00000001 /* Video extensions supported */ | 20 | #define DEV_EXT_VIDEO 0x00000001 /* Video extensions supported */ |
21 | 21 | ||
22 | /* Device information */ | 22 | /* Device information */ |
23 | struct stdio_dev { | 23 | struct stdio_dev { |
24 | int flags; /* Device flags: input/output/system */ | 24 | int flags; /* Device flags: input/output/system */ |
25 | int ext; /* Supported extensions */ | 25 | int ext; /* Supported extensions */ |
26 | char name[16]; /* Device name */ | 26 | char name[16]; /* Device name */ |
27 | 27 | ||
28 | /* GENERAL functions */ | 28 | /* GENERAL functions */ |
29 | 29 | ||
30 | int (*start)(struct stdio_dev *dev); /* To start the device */ | 30 | int (*start)(struct stdio_dev *dev); /* To start the device */ |
31 | int (*stop)(struct stdio_dev *dev); /* To stop the device */ | 31 | int (*stop)(struct stdio_dev *dev); /* To stop the device */ |
32 | 32 | ||
33 | /* OUTPUT functions */ | 33 | /* OUTPUT functions */ |
34 | 34 | ||
35 | /* To put a char */ | 35 | /* To put a char */ |
36 | void (*putc)(struct stdio_dev *dev, const char c); | 36 | void (*putc)(struct stdio_dev *dev, const char c); |
37 | /* To put a string (accelerator) */ | 37 | /* To put a string (accelerator) */ |
38 | void (*puts)(struct stdio_dev *dev, const char *s); | 38 | void (*puts)(struct stdio_dev *dev, const char *s); |
39 | 39 | ||
40 | /* INPUT functions */ | 40 | /* INPUT functions */ |
41 | 41 | ||
42 | /* To test if a char is ready... */ | 42 | /* To test if a char is ready... */ |
43 | int (*tstc)(struct stdio_dev *dev); | 43 | int (*tstc)(struct stdio_dev *dev); |
44 | int (*getc)(struct stdio_dev *dev); /* To get that char */ | 44 | int (*getc)(struct stdio_dev *dev); /* To get that char */ |
45 | 45 | ||
46 | /* Other functions */ | 46 | /* Other functions */ |
47 | 47 | ||
48 | void *priv; /* Private extensions */ | 48 | void *priv; /* Private extensions */ |
49 | struct list_head list; | 49 | struct list_head list; |
50 | }; | 50 | }; |
51 | 51 | ||
52 | /* | 52 | /* |
53 | * VIDEO EXTENSIONS | 53 | * VIDEO EXTENSIONS |
54 | */ | 54 | */ |
55 | #define VIDEO_FORMAT_RGB_INDEXED 0x0000 | 55 | #define VIDEO_FORMAT_RGB_INDEXED 0x0000 |
56 | #define VIDEO_FORMAT_RGB_DIRECTCOLOR 0x0001 | 56 | #define VIDEO_FORMAT_RGB_DIRECTCOLOR 0x0001 |
57 | #define VIDEO_FORMAT_YUYV_4_4_4 0x0010 | 57 | #define VIDEO_FORMAT_YUYV_4_4_4 0x0010 |
58 | #define VIDEO_FORMAT_YUYV_4_2_2 0x0011 | 58 | #define VIDEO_FORMAT_YUYV_4_2_2 0x0011 |
59 | 59 | ||
60 | typedef struct { | 60 | typedef struct { |
61 | void *address; /* Address of framebuffer */ | 61 | void *address; /* Address of framebuffer */ |
62 | ushort width; /* Horizontal resolution */ | 62 | ushort width; /* Horizontal resolution */ |
63 | ushort height; /* Vertical resolution */ | 63 | ushort height; /* Vertical resolution */ |
64 | uchar format; /* Format */ | 64 | uchar format; /* Format */ |
65 | uchar colors; /* Colors number or color depth */ | 65 | uchar colors; /* Colors number or color depth */ |
66 | void (*setcolreg) (int, int, int, int); | 66 | void (*setcolreg) (int, int, int, int); |
67 | void (*getcolreg) (int, void *); | 67 | void (*getcolreg) (int, void *); |
68 | } video_ext_t; | 68 | } video_ext_t; |
69 | 69 | ||
70 | /* | 70 | /* |
71 | * VARIABLES | 71 | * VARIABLES |
72 | */ | 72 | */ |
73 | extern struct stdio_dev *stdio_devices[]; | 73 | extern struct stdio_dev *stdio_devices[]; |
74 | extern char *stdio_names[MAX_FILES]; | 74 | extern char *stdio_names[MAX_FILES]; |
75 | 75 | ||
76 | /* | 76 | /* |
77 | * PROTOTYPES | 77 | * PROTOTYPES |
78 | */ | 78 | */ |
79 | int stdio_register (struct stdio_dev * dev); | 79 | int stdio_register (struct stdio_dev * dev); |
80 | int stdio_register_dev(struct stdio_dev *dev, struct stdio_dev **devp); | 80 | int stdio_register_dev(struct stdio_dev *dev, struct stdio_dev **devp); |
81 | 81 | ||
82 | /** | 82 | /** |
83 | * stdio_init_tables() - set up stdio tables ready for devices | 83 | * stdio_init_tables() - set up stdio tables ready for devices |
84 | * | 84 | * |
85 | * This does not add any devices, but just prepares stdio for use. | 85 | * This does not add any devices, but just prepares stdio for use. |
86 | */ | 86 | */ |
87 | int stdio_init_tables(void); | 87 | int stdio_init_tables(void); |
88 | 88 | ||
89 | /** | 89 | /** |
90 | * stdio_add_devices() - Add stdio devices to the table | 90 | * stdio_add_devices() - Add stdio devices to the table |
91 | * | 91 | * |
92 | * This makes calls to all the various subsystems that use stdio, to make | 92 | * This makes calls to all the various subsystems that use stdio, to make |
93 | * them register with stdio. | 93 | * them register with stdio. |
94 | */ | 94 | */ |
95 | int stdio_add_devices(void); | 95 | int stdio_add_devices(void); |
96 | 96 | ||
97 | /** | 97 | /** |
98 | * stdio_init() - Sets up stdio ready for use | 98 | * stdio_init() - Sets up stdio ready for use |
99 | * | 99 | * |
100 | * This calls stdio_init_tables() and stdio_add_devices() | 100 | * This calls stdio_init_tables() and stdio_add_devices() |
101 | */ | 101 | */ |
102 | int stdio_init(void); | 102 | int stdio_init(void); |
103 | 103 | ||
104 | void stdio_print_current_devices(void); | 104 | void stdio_print_current_devices(void); |
105 | #ifdef CONFIG_SYS_STDIO_DEREGISTER | 105 | #ifdef CONFIG_SYS_STDIO_DEREGISTER |
106 | int stdio_deregister(const char *devname); | 106 | int stdio_deregister(const char *devname, int force); |
107 | int stdio_deregister_dev(struct stdio_dev *dev); | 107 | int stdio_deregister_dev(struct stdio_dev *dev, int force); |
108 | #endif | 108 | #endif |
109 | struct list_head* stdio_get_list(void); | 109 | struct list_head* stdio_get_list(void); |
110 | struct stdio_dev* stdio_get_by_name(const char* name); | 110 | struct stdio_dev* stdio_get_by_name(const char* name); |
111 | struct stdio_dev* stdio_clone(struct stdio_dev *dev); | 111 | struct stdio_dev* stdio_clone(struct stdio_dev *dev); |
112 | 112 | ||
113 | #ifdef CONFIG_LCD | 113 | #ifdef CONFIG_LCD |
114 | int drv_lcd_init (void); | 114 | int drv_lcd_init (void); |
115 | #endif | 115 | #endif |
116 | #if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE) | 116 | #if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE) |
117 | int drv_video_init (void); | 117 | int drv_video_init (void); |
118 | #endif | 118 | #endif |
119 | #ifdef CONFIG_KEYBOARD | 119 | #ifdef CONFIG_KEYBOARD |
120 | int drv_keyboard_init (void); | 120 | int drv_keyboard_init (void); |
121 | #endif | 121 | #endif |
122 | #ifdef CONFIG_USB_TTY | 122 | #ifdef CONFIG_USB_TTY |
123 | int drv_usbtty_init (void); | 123 | int drv_usbtty_init (void); |
124 | #endif | 124 | #endif |
125 | #ifdef CONFIG_NETCONSOLE | 125 | #ifdef CONFIG_NETCONSOLE |
126 | int drv_nc_init (void); | 126 | int drv_nc_init (void); |
127 | #endif | 127 | #endif |
128 | #ifdef CONFIG_JTAG_CONSOLE | 128 | #ifdef CONFIG_JTAG_CONSOLE |
129 | int drv_jtag_console_init (void); | 129 | int drv_jtag_console_init (void); |
130 | #endif | 130 | #endif |
131 | #ifdef CONFIG_CBMEM_CONSOLE | 131 | #ifdef CONFIG_CBMEM_CONSOLE |
132 | int cbmemc_init(void); | 132 | int cbmemc_init(void); |
133 | #endif | 133 | #endif |
134 | 134 | ||
135 | #endif | 135 | #endif |
136 | 136 |
include/usb.h
1 | /* | 1 | /* |
2 | * (C) Copyright 2001 | 2 | * (C) Copyright 2001 |
3 | * Denis Peter, MPL AG Switzerland | 3 | * Denis Peter, MPL AG Switzerland |
4 | * | 4 | * |
5 | * SPDX-License-Identifier: GPL-2.0+ | 5 | * SPDX-License-Identifier: GPL-2.0+ |
6 | * Note: Part of this code has been derived from linux | 6 | * Note: Part of this code has been derived from linux |
7 | * | 7 | * |
8 | */ | 8 | */ |
9 | #ifndef _USB_H_ | 9 | #ifndef _USB_H_ |
10 | #define _USB_H_ | 10 | #define _USB_H_ |
11 | 11 | ||
12 | #include <usb_defs.h> | 12 | #include <usb_defs.h> |
13 | #include <linux/usb/ch9.h> | 13 | #include <linux/usb/ch9.h> |
14 | 14 | ||
15 | /* | 15 | /* |
16 | * The EHCI spec says that we must align to at least 32 bytes. However, | 16 | * The EHCI spec says that we must align to at least 32 bytes. However, |
17 | * some platforms require larger alignment. | 17 | * some platforms require larger alignment. |
18 | */ | 18 | */ |
19 | #if ARCH_DMA_MINALIGN > 32 | 19 | #if ARCH_DMA_MINALIGN > 32 |
20 | #define USB_DMA_MINALIGN ARCH_DMA_MINALIGN | 20 | #define USB_DMA_MINALIGN ARCH_DMA_MINALIGN |
21 | #else | 21 | #else |
22 | #define USB_DMA_MINALIGN 32 | 22 | #define USB_DMA_MINALIGN 32 |
23 | #endif | 23 | #endif |
24 | 24 | ||
25 | /* Everything is aribtrary */ | 25 | /* Everything is aribtrary */ |
26 | #define USB_ALTSETTINGALLOC 4 | 26 | #define USB_ALTSETTINGALLOC 4 |
27 | #define USB_MAXALTSETTING 128 /* Hard limit */ | 27 | #define USB_MAXALTSETTING 128 /* Hard limit */ |
28 | 28 | ||
29 | #define USB_MAX_DEVICE 32 | 29 | #define USB_MAX_DEVICE 32 |
30 | #define USB_MAXCONFIG 8 | 30 | #define USB_MAXCONFIG 8 |
31 | #define USB_MAXINTERFACES 8 | 31 | #define USB_MAXINTERFACES 8 |
32 | #define USB_MAXENDPOINTS 16 | 32 | #define USB_MAXENDPOINTS 16 |
33 | #define USB_MAXCHILDREN 8 /* This is arbitrary */ | 33 | #define USB_MAXCHILDREN 8 /* This is arbitrary */ |
34 | #define USB_MAX_HUB 16 | 34 | #define USB_MAX_HUB 16 |
35 | 35 | ||
36 | #define USB_CNTL_TIMEOUT 100 /* 100ms timeout */ | 36 | #define USB_CNTL_TIMEOUT 100 /* 100ms timeout */ |
37 | 37 | ||
38 | /* | 38 | /* |
39 | * This is the timeout to allow for submitting an urb in ms. We allow more | 39 | * This is the timeout to allow for submitting an urb in ms. We allow more |
40 | * time for a BULK device to react - some are slow. | 40 | * time for a BULK device to react - some are slow. |
41 | */ | 41 | */ |
42 | #define USB_TIMEOUT_MS(pipe) (usb_pipebulk(pipe) ? 5000 : 1000) | 42 | #define USB_TIMEOUT_MS(pipe) (usb_pipebulk(pipe) ? 5000 : 1000) |
43 | 43 | ||
44 | /* device request (setup) */ | 44 | /* device request (setup) */ |
45 | struct devrequest { | 45 | struct devrequest { |
46 | unsigned char requesttype; | 46 | unsigned char requesttype; |
47 | unsigned char request; | 47 | unsigned char request; |
48 | unsigned short value; | 48 | unsigned short value; |
49 | unsigned short index; | 49 | unsigned short index; |
50 | unsigned short length; | 50 | unsigned short length; |
51 | } __attribute__ ((packed)); | 51 | } __attribute__ ((packed)); |
52 | 52 | ||
53 | /* Interface */ | 53 | /* Interface */ |
54 | struct usb_interface { | 54 | struct usb_interface { |
55 | struct usb_interface_descriptor desc; | 55 | struct usb_interface_descriptor desc; |
56 | 56 | ||
57 | unsigned char no_of_ep; | 57 | unsigned char no_of_ep; |
58 | unsigned char num_altsetting; | 58 | unsigned char num_altsetting; |
59 | unsigned char act_altsetting; | 59 | unsigned char act_altsetting; |
60 | 60 | ||
61 | struct usb_endpoint_descriptor ep_desc[USB_MAXENDPOINTS]; | 61 | struct usb_endpoint_descriptor ep_desc[USB_MAXENDPOINTS]; |
62 | /* | 62 | /* |
63 | * Super Speed Device will have Super Speed Endpoint | 63 | * Super Speed Device will have Super Speed Endpoint |
64 | * Companion Descriptor (section 9.6.7 of usb 3.0 spec) | 64 | * Companion Descriptor (section 9.6.7 of usb 3.0 spec) |
65 | * Revision 1.0 June 6th 2011 | 65 | * Revision 1.0 June 6th 2011 |
66 | */ | 66 | */ |
67 | struct usb_ss_ep_comp_descriptor ss_ep_comp_desc[USB_MAXENDPOINTS]; | 67 | struct usb_ss_ep_comp_descriptor ss_ep_comp_desc[USB_MAXENDPOINTS]; |
68 | } __attribute__ ((packed)); | 68 | } __attribute__ ((packed)); |
69 | 69 | ||
70 | /* Configuration information.. */ | 70 | /* Configuration information.. */ |
71 | struct usb_config { | 71 | struct usb_config { |
72 | struct usb_config_descriptor desc; | 72 | struct usb_config_descriptor desc; |
73 | 73 | ||
74 | unsigned char no_of_if; /* number of interfaces */ | 74 | unsigned char no_of_if; /* number of interfaces */ |
75 | struct usb_interface if_desc[USB_MAXINTERFACES]; | 75 | struct usb_interface if_desc[USB_MAXINTERFACES]; |
76 | } __attribute__ ((packed)); | 76 | } __attribute__ ((packed)); |
77 | 77 | ||
78 | enum { | 78 | enum { |
79 | /* Maximum packet size; encoded as 0,1,2,3 = 8,16,32,64 */ | 79 | /* Maximum packet size; encoded as 0,1,2,3 = 8,16,32,64 */ |
80 | PACKET_SIZE_8 = 0, | 80 | PACKET_SIZE_8 = 0, |
81 | PACKET_SIZE_16 = 1, | 81 | PACKET_SIZE_16 = 1, |
82 | PACKET_SIZE_32 = 2, | 82 | PACKET_SIZE_32 = 2, |
83 | PACKET_SIZE_64 = 3, | 83 | PACKET_SIZE_64 = 3, |
84 | }; | 84 | }; |
85 | 85 | ||
86 | struct usb_device { | 86 | struct usb_device { |
87 | int devnum; /* Device number on USB bus */ | 87 | int devnum; /* Device number on USB bus */ |
88 | int speed; /* full/low/high */ | 88 | int speed; /* full/low/high */ |
89 | char mf[32]; /* manufacturer */ | 89 | char mf[32]; /* manufacturer */ |
90 | char prod[32]; /* product */ | 90 | char prod[32]; /* product */ |
91 | char serial[32]; /* serial number */ | 91 | char serial[32]; /* serial number */ |
92 | 92 | ||
93 | /* Maximum packet size; one of: PACKET_SIZE_* */ | 93 | /* Maximum packet size; one of: PACKET_SIZE_* */ |
94 | int maxpacketsize; | 94 | int maxpacketsize; |
95 | /* one bit for each endpoint ([0] = IN, [1] = OUT) */ | 95 | /* one bit for each endpoint ([0] = IN, [1] = OUT) */ |
96 | unsigned int toggle[2]; | 96 | unsigned int toggle[2]; |
97 | /* endpoint halts; one bit per endpoint # & direction; | 97 | /* endpoint halts; one bit per endpoint # & direction; |
98 | * [0] = IN, [1] = OUT | 98 | * [0] = IN, [1] = OUT |
99 | */ | 99 | */ |
100 | unsigned int halted[2]; | 100 | unsigned int halted[2]; |
101 | int epmaxpacketin[16]; /* INput endpoint specific maximums */ | 101 | int epmaxpacketin[16]; /* INput endpoint specific maximums */ |
102 | int epmaxpacketout[16]; /* OUTput endpoint specific maximums */ | 102 | int epmaxpacketout[16]; /* OUTput endpoint specific maximums */ |
103 | 103 | ||
104 | int configno; /* selected config number */ | 104 | int configno; /* selected config number */ |
105 | /* Device Descriptor */ | 105 | /* Device Descriptor */ |
106 | struct usb_device_descriptor descriptor | 106 | struct usb_device_descriptor descriptor |
107 | __attribute__((aligned(ARCH_DMA_MINALIGN))); | 107 | __attribute__((aligned(ARCH_DMA_MINALIGN))); |
108 | struct usb_config config; /* config descriptor */ | 108 | struct usb_config config; /* config descriptor */ |
109 | 109 | ||
110 | int have_langid; /* whether string_langid is valid yet */ | 110 | int have_langid; /* whether string_langid is valid yet */ |
111 | int string_langid; /* language ID for strings */ | 111 | int string_langid; /* language ID for strings */ |
112 | int (*irq_handle)(struct usb_device *dev); | 112 | int (*irq_handle)(struct usb_device *dev); |
113 | unsigned long irq_status; | 113 | unsigned long irq_status; |
114 | int irq_act_len; /* transfered bytes */ | 114 | int irq_act_len; /* transfered bytes */ |
115 | void *privptr; | 115 | void *privptr; |
116 | /* | 116 | /* |
117 | * Child devices - if this is a hub device | 117 | * Child devices - if this is a hub device |
118 | * Each instance needs its own set of data structures. | 118 | * Each instance needs its own set of data structures. |
119 | */ | 119 | */ |
120 | unsigned long status; | 120 | unsigned long status; |
121 | int act_len; /* transfered bytes */ | 121 | int act_len; /* transfered bytes */ |
122 | int maxchild; /* Number of ports if hub */ | 122 | int maxchild; /* Number of ports if hub */ |
123 | int portnr; | 123 | int portnr; |
124 | struct usb_device *parent; | 124 | struct usb_device *parent; |
125 | struct usb_device *children[USB_MAXCHILDREN]; | 125 | struct usb_device *children[USB_MAXCHILDREN]; |
126 | 126 | ||
127 | void *controller; /* hardware controller private data */ | 127 | void *controller; /* hardware controller private data */ |
128 | /* slot_id - for xHCI enabled devices */ | 128 | /* slot_id - for xHCI enabled devices */ |
129 | unsigned int slot_id; | 129 | unsigned int slot_id; |
130 | }; | 130 | }; |
131 | 131 | ||
132 | /* | 132 | /* |
133 | * You can initialize platform's USB host or device | 133 | * You can initialize platform's USB host or device |
134 | * ports by passing this enum as an argument to | 134 | * ports by passing this enum as an argument to |
135 | * board_usb_init(). | 135 | * board_usb_init(). |
136 | */ | 136 | */ |
137 | enum usb_init_type { | 137 | enum usb_init_type { |
138 | USB_INIT_HOST, | 138 | USB_INIT_HOST, |
139 | USB_INIT_DEVICE | 139 | USB_INIT_DEVICE |
140 | }; | 140 | }; |
141 | 141 | ||
142 | /********************************************************************** | 142 | /********************************************************************** |
143 | * this is how the lowlevel part communicate with the outer world | 143 | * this is how the lowlevel part communicate with the outer world |
144 | */ | 144 | */ |
145 | 145 | ||
146 | #if defined(CONFIG_USB_UHCI) || defined(CONFIG_USB_OHCI) || \ | 146 | #if defined(CONFIG_USB_UHCI) || defined(CONFIG_USB_OHCI) || \ |
147 | defined(CONFIG_USB_EHCI) || defined(CONFIG_USB_OHCI_NEW) || \ | 147 | defined(CONFIG_USB_EHCI) || defined(CONFIG_USB_OHCI_NEW) || \ |
148 | defined(CONFIG_USB_SL811HS) || defined(CONFIG_USB_ISP116X_HCD) || \ | 148 | defined(CONFIG_USB_SL811HS) || defined(CONFIG_USB_ISP116X_HCD) || \ |
149 | defined(CONFIG_USB_R8A66597_HCD) || defined(CONFIG_USB_DAVINCI) || \ | 149 | defined(CONFIG_USB_R8A66597_HCD) || defined(CONFIG_USB_DAVINCI) || \ |
150 | defined(CONFIG_USB_OMAP3) || defined(CONFIG_USB_DA8XX) || \ | 150 | defined(CONFIG_USB_OMAP3) || defined(CONFIG_USB_DA8XX) || \ |
151 | defined(CONFIG_USB_BLACKFIN) || defined(CONFIG_USB_AM35X) || \ | 151 | defined(CONFIG_USB_BLACKFIN) || defined(CONFIG_USB_AM35X) || \ |
152 | defined(CONFIG_USB_MUSB_DSPS) || defined(CONFIG_USB_MUSB_AM35X) || \ | 152 | defined(CONFIG_USB_MUSB_DSPS) || defined(CONFIG_USB_MUSB_AM35X) || \ |
153 | defined(CONFIG_USB_MUSB_OMAP2PLUS) || defined(CONFIG_USB_XHCI) | 153 | defined(CONFIG_USB_MUSB_OMAP2PLUS) || defined(CONFIG_USB_XHCI) |
154 | 154 | ||
155 | int usb_lowlevel_init(int index, enum usb_init_type init, void **controller); | 155 | int usb_lowlevel_init(int index, enum usb_init_type init, void **controller); |
156 | int usb_lowlevel_stop(int index); | 156 | int usb_lowlevel_stop(int index); |
157 | 157 | ||
158 | int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, | 158 | int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, |
159 | void *buffer, int transfer_len); | 159 | void *buffer, int transfer_len); |
160 | int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, | 160 | int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, |
161 | int transfer_len, struct devrequest *setup); | 161 | int transfer_len, struct devrequest *setup); |
162 | int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, | 162 | int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, |
163 | int transfer_len, int interval); | 163 | int transfer_len, int interval); |
164 | 164 | ||
165 | /* Defines */ | 165 | /* Defines */ |
166 | #define USB_UHCI_VEND_ID 0x8086 | 166 | #define USB_UHCI_VEND_ID 0x8086 |
167 | #define USB_UHCI_DEV_ID 0x7112 | 167 | #define USB_UHCI_DEV_ID 0x7112 |
168 | 168 | ||
169 | /* | 169 | /* |
170 | * PXA25x can only act as USB device. There are drivers | 170 | * PXA25x can only act as USB device. There are drivers |
171 | * which works with USB CDC gadgets implementations. | 171 | * which works with USB CDC gadgets implementations. |
172 | * Some of them have common routines which can be used | 172 | * Some of them have common routines which can be used |
173 | * in boards init functions e.g. udc_disconnect() used for | 173 | * in boards init functions e.g. udc_disconnect() used for |
174 | * forced device disconnection from host. | 174 | * forced device disconnection from host. |
175 | */ | 175 | */ |
176 | #elif defined(CONFIG_USB_GADGET_PXA2XX) | 176 | #elif defined(CONFIG_USB_GADGET_PXA2XX) |
177 | 177 | ||
178 | extern void udc_disconnect(void); | 178 | extern void udc_disconnect(void); |
179 | 179 | ||
180 | #endif | 180 | #endif |
181 | 181 | ||
182 | /* | 182 | /* |
183 | * board-specific hardware initialization, called by | 183 | * board-specific hardware initialization, called by |
184 | * usb drivers and u-boot commands | 184 | * usb drivers and u-boot commands |
185 | * | 185 | * |
186 | * @param index USB controller number | 186 | * @param index USB controller number |
187 | * @param init initializes controller as USB host or device | 187 | * @param init initializes controller as USB host or device |
188 | */ | 188 | */ |
189 | int board_usb_init(int index, enum usb_init_type init); | 189 | int board_usb_init(int index, enum usb_init_type init); |
190 | 190 | ||
191 | /* | 191 | /* |
192 | * can be used to clean up after failed USB initialization attempt | 192 | * can be used to clean up after failed USB initialization attempt |
193 | * vide: board_usb_init() | 193 | * vide: board_usb_init() |
194 | * | 194 | * |
195 | * @param index USB controller number for selective cleanup | 195 | * @param index USB controller number for selective cleanup |
196 | * @param init usb_init_type passed to board_usb_init() | 196 | * @param init usb_init_type passed to board_usb_init() |
197 | */ | 197 | */ |
198 | int board_usb_cleanup(int index, enum usb_init_type init); | 198 | int board_usb_cleanup(int index, enum usb_init_type init); |
199 | 199 | ||
200 | #ifdef CONFIG_USB_STORAGE | 200 | #ifdef CONFIG_USB_STORAGE |
201 | 201 | ||
202 | #define USB_MAX_STOR_DEV 5 | 202 | #define USB_MAX_STOR_DEV 5 |
203 | block_dev_desc_t *usb_stor_get_dev(int index); | 203 | block_dev_desc_t *usb_stor_get_dev(int index); |
204 | int usb_stor_scan(int mode); | 204 | int usb_stor_scan(int mode); |
205 | int usb_stor_info(void); | 205 | int usb_stor_info(void); |
206 | 206 | ||
207 | #endif | 207 | #endif |
208 | 208 | ||
209 | #ifdef CONFIG_USB_HOST_ETHER | 209 | #ifdef CONFIG_USB_HOST_ETHER |
210 | 210 | ||
211 | #define USB_MAX_ETH_DEV 5 | 211 | #define USB_MAX_ETH_DEV 5 |
212 | int usb_host_eth_scan(int mode); | 212 | int usb_host_eth_scan(int mode); |
213 | 213 | ||
214 | #endif | 214 | #endif |
215 | 215 | ||
216 | #ifdef CONFIG_USB_KEYBOARD | 216 | #ifdef CONFIG_USB_KEYBOARD |
217 | 217 | ||
218 | int drv_usb_kbd_init(void); | 218 | int drv_usb_kbd_init(void); |
219 | int usb_kbd_deregister(void); | 219 | int usb_kbd_deregister(int force); |
220 | 220 | ||
221 | #endif | 221 | #endif |
222 | /* routines */ | 222 | /* routines */ |
223 | int usb_init(void); /* initialize the USB Controller */ | 223 | int usb_init(void); /* initialize the USB Controller */ |
224 | int usb_stop(void); /* stop the USB Controller */ | 224 | int usb_stop(void); /* stop the USB Controller */ |
225 | 225 | ||
226 | 226 | ||
227 | int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol); | 227 | int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol); |
228 | int usb_set_idle(struct usb_device *dev, int ifnum, int duration, | 228 | int usb_set_idle(struct usb_device *dev, int ifnum, int duration, |
229 | int report_id); | 229 | int report_id); |
230 | struct usb_device *usb_get_dev_index(int index); | 230 | struct usb_device *usb_get_dev_index(int index); |
231 | int usb_control_msg(struct usb_device *dev, unsigned int pipe, | 231 | int usb_control_msg(struct usb_device *dev, unsigned int pipe, |
232 | unsigned char request, unsigned char requesttype, | 232 | unsigned char request, unsigned char requesttype, |
233 | unsigned short value, unsigned short index, | 233 | unsigned short value, unsigned short index, |
234 | void *data, unsigned short size, int timeout); | 234 | void *data, unsigned short size, int timeout); |
235 | int usb_bulk_msg(struct usb_device *dev, unsigned int pipe, | 235 | int usb_bulk_msg(struct usb_device *dev, unsigned int pipe, |
236 | void *data, int len, int *actual_length, int timeout); | 236 | void *data, int len, int *actual_length, int timeout); |
237 | int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe, | 237 | int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe, |
238 | void *buffer, int transfer_len, int interval); | 238 | void *buffer, int transfer_len, int interval); |
239 | int usb_disable_asynch(int disable); | 239 | int usb_disable_asynch(int disable); |
240 | int usb_maxpacket(struct usb_device *dev, unsigned long pipe); | 240 | int usb_maxpacket(struct usb_device *dev, unsigned long pipe); |
241 | int usb_get_configuration_no(struct usb_device *dev, unsigned char *buffer, | 241 | int usb_get_configuration_no(struct usb_device *dev, unsigned char *buffer, |
242 | int cfgno); | 242 | int cfgno); |
243 | int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type, | 243 | int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type, |
244 | unsigned char id, void *buf, int size); | 244 | unsigned char id, void *buf, int size); |
245 | int usb_get_class_descriptor(struct usb_device *dev, int ifnum, | 245 | int usb_get_class_descriptor(struct usb_device *dev, int ifnum, |
246 | unsigned char type, unsigned char id, void *buf, | 246 | unsigned char type, unsigned char id, void *buf, |
247 | int size); | 247 | int size); |
248 | int usb_clear_halt(struct usb_device *dev, int pipe); | 248 | int usb_clear_halt(struct usb_device *dev, int pipe); |
249 | int usb_string(struct usb_device *dev, int index, char *buf, size_t size); | 249 | int usb_string(struct usb_device *dev, int index, char *buf, size_t size); |
250 | int usb_set_interface(struct usb_device *dev, int interface, int alternate); | 250 | int usb_set_interface(struct usb_device *dev, int interface, int alternate); |
251 | 251 | ||
252 | /* big endian -> little endian conversion */ | 252 | /* big endian -> little endian conversion */ |
253 | /* some CPUs are already little endian e.g. the ARM920T */ | 253 | /* some CPUs are already little endian e.g. the ARM920T */ |
254 | #define __swap_16(x) \ | 254 | #define __swap_16(x) \ |
255 | ({ unsigned short x_ = (unsigned short)x; \ | 255 | ({ unsigned short x_ = (unsigned short)x; \ |
256 | (unsigned short)( \ | 256 | (unsigned short)( \ |
257 | ((x_ & 0x00FFU) << 8) | ((x_ & 0xFF00U) >> 8)); \ | 257 | ((x_ & 0x00FFU) << 8) | ((x_ & 0xFF00U) >> 8)); \ |
258 | }) | 258 | }) |
259 | #define __swap_32(x) \ | 259 | #define __swap_32(x) \ |
260 | ({ unsigned long x_ = (unsigned long)x; \ | 260 | ({ unsigned long x_ = (unsigned long)x; \ |
261 | (unsigned long)( \ | 261 | (unsigned long)( \ |
262 | ((x_ & 0x000000FFUL) << 24) | \ | 262 | ((x_ & 0x000000FFUL) << 24) | \ |
263 | ((x_ & 0x0000FF00UL) << 8) | \ | 263 | ((x_ & 0x0000FF00UL) << 8) | \ |
264 | ((x_ & 0x00FF0000UL) >> 8) | \ | 264 | ((x_ & 0x00FF0000UL) >> 8) | \ |
265 | ((x_ & 0xFF000000UL) >> 24)); \ | 265 | ((x_ & 0xFF000000UL) >> 24)); \ |
266 | }) | 266 | }) |
267 | 267 | ||
268 | #ifdef __LITTLE_ENDIAN | 268 | #ifdef __LITTLE_ENDIAN |
269 | # define swap_16(x) (x) | 269 | # define swap_16(x) (x) |
270 | # define swap_32(x) (x) | 270 | # define swap_32(x) (x) |
271 | #else | 271 | #else |
272 | # define swap_16(x) __swap_16(x) | 272 | # define swap_16(x) __swap_16(x) |
273 | # define swap_32(x) __swap_32(x) | 273 | # define swap_32(x) __swap_32(x) |
274 | #endif | 274 | #endif |
275 | 275 | ||
276 | /* | 276 | /* |
277 | * Calling this entity a "pipe" is glorifying it. A USB pipe | 277 | * Calling this entity a "pipe" is glorifying it. A USB pipe |
278 | * is something embarrassingly simple: it basically consists | 278 | * is something embarrassingly simple: it basically consists |
279 | * of the following information: | 279 | * of the following information: |
280 | * - device number (7 bits) | 280 | * - device number (7 bits) |
281 | * - endpoint number (4 bits) | 281 | * - endpoint number (4 bits) |
282 | * - current Data0/1 state (1 bit) | 282 | * - current Data0/1 state (1 bit) |
283 | * - direction (1 bit) | 283 | * - direction (1 bit) |
284 | * - speed (2 bits) | 284 | * - speed (2 bits) |
285 | * - max packet size (2 bits: 8, 16, 32 or 64) | 285 | * - max packet size (2 bits: 8, 16, 32 or 64) |
286 | * - pipe type (2 bits: control, interrupt, bulk, isochronous) | 286 | * - pipe type (2 bits: control, interrupt, bulk, isochronous) |
287 | * | 287 | * |
288 | * That's 18 bits. Really. Nothing more. And the USB people have | 288 | * That's 18 bits. Really. Nothing more. And the USB people have |
289 | * documented these eighteen bits as some kind of glorious | 289 | * documented these eighteen bits as some kind of glorious |
290 | * virtual data structure. | 290 | * virtual data structure. |
291 | * | 291 | * |
292 | * Let's not fall in that trap. We'll just encode it as a simple | 292 | * Let's not fall in that trap. We'll just encode it as a simple |
293 | * unsigned int. The encoding is: | 293 | * unsigned int. The encoding is: |
294 | * | 294 | * |
295 | * - max size: bits 0-1 (00 = 8, 01 = 16, 10 = 32, 11 = 64) | 295 | * - max size: bits 0-1 (00 = 8, 01 = 16, 10 = 32, 11 = 64) |
296 | * - direction: bit 7 (0 = Host-to-Device [Out], | 296 | * - direction: bit 7 (0 = Host-to-Device [Out], |
297 | * (1 = Device-to-Host [In]) | 297 | * (1 = Device-to-Host [In]) |
298 | * - device: bits 8-14 | 298 | * - device: bits 8-14 |
299 | * - endpoint: bits 15-18 | 299 | * - endpoint: bits 15-18 |
300 | * - Data0/1: bit 19 | 300 | * - Data0/1: bit 19 |
301 | * - pipe type: bits 30-31 (00 = isochronous, 01 = interrupt, | 301 | * - pipe type: bits 30-31 (00 = isochronous, 01 = interrupt, |
302 | * 10 = control, 11 = bulk) | 302 | * 10 = control, 11 = bulk) |
303 | * | 303 | * |
304 | * Why? Because it's arbitrary, and whatever encoding we select is really | 304 | * Why? Because it's arbitrary, and whatever encoding we select is really |
305 | * up to us. This one happens to share a lot of bit positions with the UHCI | 305 | * up to us. This one happens to share a lot of bit positions with the UHCI |
306 | * specification, so that much of the uhci driver can just mask the bits | 306 | * specification, so that much of the uhci driver can just mask the bits |
307 | * appropriately. | 307 | * appropriately. |
308 | */ | 308 | */ |
309 | /* Create various pipes... */ | 309 | /* Create various pipes... */ |
310 | #define create_pipe(dev,endpoint) \ | 310 | #define create_pipe(dev,endpoint) \ |
311 | (((dev)->devnum << 8) | ((endpoint) << 15) | \ | 311 | (((dev)->devnum << 8) | ((endpoint) << 15) | \ |
312 | (dev)->maxpacketsize) | 312 | (dev)->maxpacketsize) |
313 | #define default_pipe(dev) ((dev)->speed << 26) | 313 | #define default_pipe(dev) ((dev)->speed << 26) |
314 | 314 | ||
315 | #define usb_sndctrlpipe(dev, endpoint) ((PIPE_CONTROL << 30) | \ | 315 | #define usb_sndctrlpipe(dev, endpoint) ((PIPE_CONTROL << 30) | \ |
316 | create_pipe(dev, endpoint)) | 316 | create_pipe(dev, endpoint)) |
317 | #define usb_rcvctrlpipe(dev, endpoint) ((PIPE_CONTROL << 30) | \ | 317 | #define usb_rcvctrlpipe(dev, endpoint) ((PIPE_CONTROL << 30) | \ |
318 | create_pipe(dev, endpoint) | \ | 318 | create_pipe(dev, endpoint) | \ |
319 | USB_DIR_IN) | 319 | USB_DIR_IN) |
320 | #define usb_sndisocpipe(dev, endpoint) ((PIPE_ISOCHRONOUS << 30) | \ | 320 | #define usb_sndisocpipe(dev, endpoint) ((PIPE_ISOCHRONOUS << 30) | \ |
321 | create_pipe(dev, endpoint)) | 321 | create_pipe(dev, endpoint)) |
322 | #define usb_rcvisocpipe(dev, endpoint) ((PIPE_ISOCHRONOUS << 30) | \ | 322 | #define usb_rcvisocpipe(dev, endpoint) ((PIPE_ISOCHRONOUS << 30) | \ |
323 | create_pipe(dev, endpoint) | \ | 323 | create_pipe(dev, endpoint) | \ |
324 | USB_DIR_IN) | 324 | USB_DIR_IN) |
325 | #define usb_sndbulkpipe(dev, endpoint) ((PIPE_BULK << 30) | \ | 325 | #define usb_sndbulkpipe(dev, endpoint) ((PIPE_BULK << 30) | \ |
326 | create_pipe(dev, endpoint)) | 326 | create_pipe(dev, endpoint)) |
327 | #define usb_rcvbulkpipe(dev, endpoint) ((PIPE_BULK << 30) | \ | 327 | #define usb_rcvbulkpipe(dev, endpoint) ((PIPE_BULK << 30) | \ |
328 | create_pipe(dev, endpoint) | \ | 328 | create_pipe(dev, endpoint) | \ |
329 | USB_DIR_IN) | 329 | USB_DIR_IN) |
330 | #define usb_sndintpipe(dev, endpoint) ((PIPE_INTERRUPT << 30) | \ | 330 | #define usb_sndintpipe(dev, endpoint) ((PIPE_INTERRUPT << 30) | \ |
331 | create_pipe(dev, endpoint)) | 331 | create_pipe(dev, endpoint)) |
332 | #define usb_rcvintpipe(dev, endpoint) ((PIPE_INTERRUPT << 30) | \ | 332 | #define usb_rcvintpipe(dev, endpoint) ((PIPE_INTERRUPT << 30) | \ |
333 | create_pipe(dev, endpoint) | \ | 333 | create_pipe(dev, endpoint) | \ |
334 | USB_DIR_IN) | 334 | USB_DIR_IN) |
335 | #define usb_snddefctrl(dev) ((PIPE_CONTROL << 30) | \ | 335 | #define usb_snddefctrl(dev) ((PIPE_CONTROL << 30) | \ |
336 | default_pipe(dev)) | 336 | default_pipe(dev)) |
337 | #define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | \ | 337 | #define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | \ |
338 | default_pipe(dev) | \ | 338 | default_pipe(dev) | \ |
339 | USB_DIR_IN) | 339 | USB_DIR_IN) |
340 | 340 | ||
341 | /* The D0/D1 toggle bits */ | 341 | /* The D0/D1 toggle bits */ |
342 | #define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> ep) & 1) | 342 | #define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> ep) & 1) |
343 | #define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << ep)) | 343 | #define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << ep)) |
344 | #define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = \ | 344 | #define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = \ |
345 | ((dev)->toggle[out] & \ | 345 | ((dev)->toggle[out] & \ |
346 | ~(1 << ep)) | ((bit) << ep)) | 346 | ~(1 << ep)) | ((bit) << ep)) |
347 | 347 | ||
348 | /* Endpoint halt control/status */ | 348 | /* Endpoint halt control/status */ |
349 | #define usb_endpoint_out(ep_dir) (((ep_dir >> 7) & 1) ^ 1) | 349 | #define usb_endpoint_out(ep_dir) (((ep_dir >> 7) & 1) ^ 1) |
350 | #define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep))) | 350 | #define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep))) |
351 | #define usb_endpoint_running(dev, ep, out) ((dev)->halted[out] &= ~(1 << (ep))) | 351 | #define usb_endpoint_running(dev, ep, out) ((dev)->halted[out] &= ~(1 << (ep))) |
352 | #define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep))) | 352 | #define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep))) |
353 | 353 | ||
354 | #define usb_packetid(pipe) (((pipe) & USB_DIR_IN) ? USB_PID_IN : \ | 354 | #define usb_packetid(pipe) (((pipe) & USB_DIR_IN) ? USB_PID_IN : \ |
355 | USB_PID_OUT) | 355 | USB_PID_OUT) |
356 | 356 | ||
357 | #define usb_pipeout(pipe) ((((pipe) >> 7) & 1) ^ 1) | 357 | #define usb_pipeout(pipe) ((((pipe) >> 7) & 1) ^ 1) |
358 | #define usb_pipein(pipe) (((pipe) >> 7) & 1) | 358 | #define usb_pipein(pipe) (((pipe) >> 7) & 1) |
359 | #define usb_pipedevice(pipe) (((pipe) >> 8) & 0x7f) | 359 | #define usb_pipedevice(pipe) (((pipe) >> 8) & 0x7f) |
360 | #define usb_pipe_endpdev(pipe) (((pipe) >> 8) & 0x7ff) | 360 | #define usb_pipe_endpdev(pipe) (((pipe) >> 8) & 0x7ff) |
361 | #define usb_pipeendpoint(pipe) (((pipe) >> 15) & 0xf) | 361 | #define usb_pipeendpoint(pipe) (((pipe) >> 15) & 0xf) |
362 | #define usb_pipedata(pipe) (((pipe) >> 19) & 1) | 362 | #define usb_pipedata(pipe) (((pipe) >> 19) & 1) |
363 | #define usb_pipetype(pipe) (((pipe) >> 30) & 3) | 363 | #define usb_pipetype(pipe) (((pipe) >> 30) & 3) |
364 | #define usb_pipeisoc(pipe) (usb_pipetype((pipe)) == PIPE_ISOCHRONOUS) | 364 | #define usb_pipeisoc(pipe) (usb_pipetype((pipe)) == PIPE_ISOCHRONOUS) |
365 | #define usb_pipeint(pipe) (usb_pipetype((pipe)) == PIPE_INTERRUPT) | 365 | #define usb_pipeint(pipe) (usb_pipetype((pipe)) == PIPE_INTERRUPT) |
366 | #define usb_pipecontrol(pipe) (usb_pipetype((pipe)) == PIPE_CONTROL) | 366 | #define usb_pipecontrol(pipe) (usb_pipetype((pipe)) == PIPE_CONTROL) |
367 | #define usb_pipebulk(pipe) (usb_pipetype((pipe)) == PIPE_BULK) | 367 | #define usb_pipebulk(pipe) (usb_pipetype((pipe)) == PIPE_BULK) |
368 | 368 | ||
369 | #define usb_pipe_ep_index(pipe) \ | 369 | #define usb_pipe_ep_index(pipe) \ |
370 | usb_pipecontrol(pipe) ? (usb_pipeendpoint(pipe) * 2) : \ | 370 | usb_pipecontrol(pipe) ? (usb_pipeendpoint(pipe) * 2) : \ |
371 | ((usb_pipeendpoint(pipe) * 2) - \ | 371 | ((usb_pipeendpoint(pipe) * 2) - \ |
372 | (usb_pipein(pipe) ? 0 : 1)) | 372 | (usb_pipein(pipe) ? 0 : 1)) |
373 | 373 | ||
374 | /************************************************************************* | 374 | /************************************************************************* |
375 | * Hub Stuff | 375 | * Hub Stuff |
376 | */ | 376 | */ |
377 | struct usb_port_status { | 377 | struct usb_port_status { |
378 | unsigned short wPortStatus; | 378 | unsigned short wPortStatus; |
379 | unsigned short wPortChange; | 379 | unsigned short wPortChange; |
380 | } __attribute__ ((packed)); | 380 | } __attribute__ ((packed)); |
381 | 381 | ||
382 | struct usb_hub_status { | 382 | struct usb_hub_status { |
383 | unsigned short wHubStatus; | 383 | unsigned short wHubStatus; |
384 | unsigned short wHubChange; | 384 | unsigned short wHubChange; |
385 | } __attribute__ ((packed)); | 385 | } __attribute__ ((packed)); |
386 | 386 | ||
387 | 387 | ||
388 | /* Hub descriptor */ | 388 | /* Hub descriptor */ |
389 | struct usb_hub_descriptor { | 389 | struct usb_hub_descriptor { |
390 | unsigned char bLength; | 390 | unsigned char bLength; |
391 | unsigned char bDescriptorType; | 391 | unsigned char bDescriptorType; |
392 | unsigned char bNbrPorts; | 392 | unsigned char bNbrPorts; |
393 | unsigned short wHubCharacteristics; | 393 | unsigned short wHubCharacteristics; |
394 | unsigned char bPwrOn2PwrGood; | 394 | unsigned char bPwrOn2PwrGood; |
395 | unsigned char bHubContrCurrent; | 395 | unsigned char bHubContrCurrent; |
396 | unsigned char DeviceRemovable[(USB_MAXCHILDREN+1+7)/8]; | 396 | unsigned char DeviceRemovable[(USB_MAXCHILDREN+1+7)/8]; |
397 | unsigned char PortPowerCtrlMask[(USB_MAXCHILDREN+1+7)/8]; | 397 | unsigned char PortPowerCtrlMask[(USB_MAXCHILDREN+1+7)/8]; |
398 | /* DeviceRemovable and PortPwrCtrlMask want to be variable-length | 398 | /* DeviceRemovable and PortPwrCtrlMask want to be variable-length |
399 | bitmaps that hold max 255 entries. (bit0 is ignored) */ | 399 | bitmaps that hold max 255 entries. (bit0 is ignored) */ |
400 | } __attribute__ ((packed)); | 400 | } __attribute__ ((packed)); |
401 | 401 | ||
402 | 402 | ||
403 | struct usb_hub_device { | 403 | struct usb_hub_device { |
404 | struct usb_device *pusb_dev; | 404 | struct usb_device *pusb_dev; |
405 | struct usb_hub_descriptor desc; | 405 | struct usb_hub_descriptor desc; |
406 | }; | 406 | }; |
407 | 407 | ||
408 | int usb_hub_probe(struct usb_device *dev, int ifnum); | 408 | int usb_hub_probe(struct usb_device *dev, int ifnum); |
409 | void usb_hub_reset(void); | 409 | void usb_hub_reset(void); |
410 | int hub_port_reset(struct usb_device *dev, int port, | 410 | int hub_port_reset(struct usb_device *dev, int port, |
411 | unsigned short *portstat); | 411 | unsigned short *portstat); |
412 | 412 | ||
413 | struct usb_device *usb_alloc_new_device(void *controller); | 413 | struct usb_device *usb_alloc_new_device(void *controller); |
414 | 414 | ||
415 | int usb_new_device(struct usb_device *dev); | 415 | int usb_new_device(struct usb_device *dev); |
416 | void usb_free_device(void); | 416 | void usb_free_device(void); |
417 | int usb_alloc_device(struct usb_device *dev); | 417 | int usb_alloc_device(struct usb_device *dev); |
418 | 418 | ||
419 | #endif /*_USB_H_ */ | 419 | #endif /*_USB_H_ */ |
420 | 420 |