Blame view

common/usb.c 34 KB
affae2bff   wdenk   Initial revision
1
  /*
affae2bff   wdenk   Initial revision
2
   * Most of this source has been derived from the Linux USB
460c322f1   Wolfgang Denk   (re)enabled scsi ...
3
4
5
6
7
8
9
10
11
12
13
14
15
   * project:
   * (C) Copyright Linus Torvalds 1999
   * (C) Copyright Johannes Erdfelt 1999-2001
   * (C) Copyright Andreas Gal 1999
   * (C) Copyright Gregory P. Smith 1999
   * (C) Copyright Deti Fliegl 1999 (new USB architecture)
   * (C) Copyright Randy Dunlap 2000
   * (C) Copyright David Brownell 2000 (kernel hotplug, usb_device_id)
   * (C) Copyright Yggdrasil Computing, Inc. 2000
   *     (usb_device_id matching changes by Adam J. Richter)
   *
   * Adapted for U-Boot:
   * (C) Copyright 2001 Denis Peter, MPL AG Switzerland
affae2bff   wdenk   Initial revision
16
   *
1a4596601   Wolfgang Denk   Add GPL-2.0+ SPDX...
17
   * SPDX-License-Identifier:	GPL-2.0+
affae2bff   wdenk   Initial revision
18
   */
affae2bff   wdenk   Initial revision
19
20
21
22
23
24
25
26
27
28
29
  /*
   * How it works:
   *
   * Since this is a bootloader, the devices will not be automatic
   * (re)configured on hotplug, but after a restart of the USB the
   * device should work.
   *
   * For each transfer (except "Interrupt") we wait for completion.
   */
  #include <common.h>
  #include <command.h>
95fbfe429   Simon Glass   dm: usb: Convert ...
30
  #include <dm.h>
cf92e05c0   Simon Glass   Move ALLOC_CACHE_...
31
  #include <memalign.h>
affae2bff   wdenk   Initial revision
32
  #include <asm/processor.h>
66cf64107   Mike Frysinger   usb: use noinline...
33
  #include <linux/compiler.h>
9c998aa83   Wolfgang Denk   Fix low-level OHC...
34
  #include <linux/ctype.h>
c918261c6   Christian Eggers   USB: replace old ...
35
  #include <asm/byteorder.h>
b2fb47f18   Tom Rini   USB: Use (get|put...
36
  #include <asm/unaligned.h>
97b9eb9e6   Marek Vasut   usb: Handle -ENOD...
37
  #include <errno.h>
affae2bff   wdenk   Initial revision
38
  #include <usb.h>
affae2bff   wdenk   Initial revision
39

cd0a9de68   wdenk   * Patch by Lauren...
40
  #define USB_BUFSIZ	512
affae2bff   wdenk   Initial revision
41
  static int asynch_allowed;
e51aae382   Bartlomiej Sieka   Prevent USB comma...
42
  char usb_started; /* flag for the started/stopped USB status */
95fbfe429   Simon Glass   dm: usb: Convert ...
43
44
45
  #ifndef CONFIG_DM_USB
  static struct usb_device usb_dev[USB_MAX_DEVICE];
  static int dev_index;
93c2582fe   Lucas Stach   usb: add support ...
46
47
48
  #ifndef CONFIG_USB_MAX_CONTROLLER_COUNT
  #define CONFIG_USB_MAX_CONTROLLER_COUNT 1
  #endif
affae2bff   wdenk   Initial revision
49

affae2bff   wdenk   Initial revision
50
51
52
  /***************************************************************************
   * Init USB Device
   */
affae2bff   wdenk   Initial revision
53
54
  int usb_init(void)
  {
93c2582fe   Lucas Stach   usb: add support ...
55
56
57
  	void *ctrl;
  	struct usb_device *dev;
  	int i, start_index = 0;
d906bbc26   Hans de Goede   usb: Do not log a...
58
  	int controllers_initialized = 0;
97b9eb9e6   Marek Vasut   usb: Handle -ENOD...
59
  	int ret;
affae2bff   wdenk   Initial revision
60

6f5794a6f   Remy Bohmer   Refactoring parts...
61
62
  	dev_index = 0;
  	asynch_allowed = 1;
affae2bff   wdenk   Initial revision
63
  	usb_hub_reset();
93c2582fe   Lucas Stach   usb: add support ...
64
65
66
67
68
69
  
  	/* first make all devices unknown */
  	for (i = 0; i < USB_MAX_DEVICE; i++) {
  		memset(&usb_dev[i], 0, sizeof(struct usb_device));
  		usb_dev[i].devnum = -1;
  	}
affae2bff   wdenk   Initial revision
70
  	/* init low_level USB */
93c2582fe   Lucas Stach   usb: add support ...
71
72
73
  	for (i = 0; i < CONFIG_USB_MAX_CONTROLLER_COUNT; i++) {
  		/* init low_level USB */
  		printf("USB%d:   ", i);
97b9eb9e6   Marek Vasut   usb: Handle -ENOD...
74
75
76
77
  		ret = usb_lowlevel_init(i, USB_INIT_HOST, &ctrl);
  		if (ret == -ENODEV) {	/* No such device. */
  			puts("Port not available.
  ");
d906bbc26   Hans de Goede   usb: Do not log a...
78
  			controllers_initialized++;
97b9eb9e6   Marek Vasut   usb: Handle -ENOD...
79
80
81
82
  			continue;
  		}
  
  		if (ret) {		/* Other error. */
93c2582fe   Lucas Stach   usb: add support ...
83
84
85
86
87
88
89
90
  			puts("lowlevel init failed
  ");
  			continue;
  		}
  		/*
  		 * lowlevel init is OK, now scan the bus for devices
  		 * i.e. search HUBs and configure them
  		 */
d906bbc26   Hans de Goede   usb: Do not log a...
91
  		controllers_initialized++;
93c2582fe   Lucas Stach   usb: add support ...
92
93
  		start_index = dev_index;
  		printf("scanning bus %d for devices... ", i);
79b588872   Simon Glass   dm: usb: Adjust u...
94
95
  		ret = usb_alloc_new_device(ctrl, &dev);
  		if (ret)
8879be885   Paul Kocialkowski   usb: Check usb_ne...
96
  			break;
93c2582fe   Lucas Stach   usb: add support ...
97
98
99
100
  		/*
  		 * device 0 is always present
  		 * (root hub, so let it analyze)
  		 */
8879be885   Paul Kocialkowski   usb: Check usb_ne...
101
102
  		ret = usb_new_device(dev);
  		if (ret)
79b588872   Simon Glass   dm: usb: Adjust u...
103
  			usb_free_device(dev->controller);
93c2582fe   Lucas Stach   usb: add support ...
104

8879be885   Paul Kocialkowski   usb: Check usb_ne...
105
  		if (start_index == dev_index) {
93c2582fe   Lucas Stach   usb: add support ...
106
107
  			puts("No USB Device found
  ");
8879be885   Paul Kocialkowski   usb: Check usb_ne...
108
109
  			continue;
  		} else {
93c2582fe   Lucas Stach   usb: add support ...
110
111
112
  			printf("%d USB Device(s) found
  ",
  				dev_index - start_index);
8879be885   Paul Kocialkowski   usb: Check usb_ne...
113
  		}
93c2582fe   Lucas Stach   usb: add support ...
114

e51aae382   Bartlomiej Sieka   Prevent USB comma...
115
  		usb_started = 1;
93c2582fe   Lucas Stach   usb: add support ...
116
  	}
ceb4972a8   Vivek Gautam   usb: common: Weed...
117
118
  	debug("scan end
  ");
93c2582fe   Lucas Stach   usb: add support ...
119
  	/* if we were not able to find at least one working bus, bail out */
d906bbc26   Hans de Goede   usb: Do not log a...
120
  	if (controllers_initialized == 0)
93c2582fe   Lucas Stach   usb: add support ...
121
122
  		puts("USB error: all controllers failed lowlevel init
  ");
93c2582fe   Lucas Stach   usb: add support ...
123

5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
124
  	return usb_started ? 0 : -ENODEV;
affae2bff   wdenk   Initial revision
125
126
127
128
129
130
131
  }
  
  /******************************************************************************
   * Stop USB this stops the LowLevel Part and deregisters USB devices.
   */
  int usb_stop(void)
  {
93c2582fe   Lucas Stach   usb: add support ...
132
  	int i;
eba1f2fc7   Remy Bohmer   Make usb-stop() s...
133
134
135
136
137
  
  	if (usb_started) {
  		asynch_allowed = 1;
  		usb_started = 0;
  		usb_hub_reset();
93c2582fe   Lucas Stach   usb: add support ...
138
139
140
141
142
143
  
  		for (i = 0; i < CONFIG_USB_MAX_CONTROLLER_COUNT; i++) {
  			if (usb_lowlevel_stop(i))
  				printf("failed to stop USB controller %d
  ", i);
  		}
eba1f2fc7   Remy Bohmer   Make usb-stop() s...
144
  	}
93c2582fe   Lucas Stach   usb: add support ...
145
146
  
  	return 0;
affae2bff   wdenk   Initial revision
147
  }
08f3bb0bc   Vincent Palatin   usb: add device c...
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
  /******************************************************************************
   * Detect if a USB device has been plugged or unplugged.
   */
  int usb_detect_change(void)
  {
  	int i, j;
  	int change = 0;
  
  	for (j = 0; j < USB_MAX_DEVICE; j++) {
  		for (i = 0; i < usb_dev[j].maxchild; i++) {
  			struct usb_port_status status;
  
  			if (usb_get_port_status(&usb_dev[j], i + 1,
  						&status) < 0)
  				/* USB request failed */
  				continue;
  
  			if (le16_to_cpu(status.wPortChange) &
  			    USB_PORT_STAT_C_CONNECTION)
  				change++;
  		}
  	}
  
  	return change;
  }
affae2bff   wdenk   Initial revision
173
174
175
  /*
   * disables the asynch behaviour of the control message. This is used for data
   * transfers that uses the exclusiv access to the control and bulk messages.
89d48367e   Simon Glass   Add USB host ethe...
176
   * Returns the old value so it can be restored later.
affae2bff   wdenk   Initial revision
177
   */
89d48367e   Simon Glass   Add USB host ethe...
178
  int usb_disable_asynch(int disable)
affae2bff   wdenk   Initial revision
179
  {
89d48367e   Simon Glass   Add USB host ethe...
180
  	int old_value = asynch_allowed;
6f5794a6f   Remy Bohmer   Refactoring parts...
181
  	asynch_allowed = !disable;
89d48367e   Simon Glass   Add USB host ethe...
182
  	return old_value;
affae2bff   wdenk   Initial revision
183
  }
95fbfe429   Simon Glass   dm: usb: Convert ...
184
  #endif /* !CONFIG_DM_USB */
affae2bff   wdenk   Initial revision
185
186
187
188
189
190
191
192
193
194
195
  
  
  /*-------------------------------------------------------------------
   * Message wrappers.
   *
   */
  
  /*
   * submits an Interrupt Message
   */
  int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe,
6f5794a6f   Remy Bohmer   Refactoring parts...
196
  			void *buffer, int transfer_len, int interval)
affae2bff   wdenk   Initial revision
197
  {
6f5794a6f   Remy Bohmer   Refactoring parts...
198
  	return submit_int_msg(dev, pipe, buffer, transfer_len, interval);
affae2bff   wdenk   Initial revision
199
200
201
202
203
204
205
206
  }
  
  /*
   * submits a control message and waits for comletion (at least timeout * 1ms)
   * If timeout is 0, we don't wait for completion (used as example to set and
   * clear keyboards LEDs). For data transfers, (storage transfers) we don't
   * allow control messages with 0 timeout, by previousely resetting the flag
   * asynch_allowed (usb_disable_asynch(1)).
a6f70a3d1   Vagrant Cascadian   Fix spelling of "...
207
   * returns the transferred length if OK or -1 if error. The transferred length
affae2bff   wdenk   Initial revision
208
209
210
211
212
213
214
   * and the current status are stored in the dev->act_len and dev->status.
   */
  int usb_control_msg(struct usb_device *dev, unsigned int pipe,
  			unsigned char request, unsigned char requesttype,
  			unsigned short value, unsigned short index,
  			void *data, unsigned short size, int timeout)
  {
f57661394   Puneet Saxena   USB: Align buffer...
215
  	ALLOC_CACHE_ALIGN_BUFFER(struct devrequest, setup_packet, 1);
651d95c8e   Hans de Goede   usb: usb_control_...
216
  	int err;
e159e4868   Marek Vasut   USB: Make struct ...
217

6f5794a6f   Remy Bohmer   Refactoring parts...
218
219
  	if ((timeout == 0) && (!asynch_allowed)) {
  		/* request for a asynch control pipe is not allowed */
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
220
  		return -EINVAL;
6f5794a6f   Remy Bohmer   Refactoring parts...
221
  	}
9c998aa83   Wolfgang Denk   Fix low-level OHC...
222

affae2bff   wdenk   Initial revision
223
  	/* set setup command */
f57661394   Puneet Saxena   USB: Align buffer...
224
225
226
227
228
  	setup_packet->requesttype = requesttype;
  	setup_packet->request = request;
  	setup_packet->value = cpu_to_le16(value);
  	setup_packet->index = cpu_to_le16(index);
  	setup_packet->length = cpu_to_le16(size);
ceb4972a8   Vivek Gautam   usb: common: Weed...
229
230
231
232
  	debug("usb_control_msg: request: 0x%X, requesttype: 0x%X, " \
  	      "value 0x%X index 0x%X length 0x%X
  ",
  	      request, requesttype, value, index, size);
6f5794a6f   Remy Bohmer   Refactoring parts...
233
  	dev->status = USB_ST_NOT_PROC; /*not yet processed */
affae2bff   wdenk   Initial revision
234

651d95c8e   Hans de Goede   usb: usb_control_...
235
236
237
  	err = submit_control_msg(dev, pipe, data, size, setup_packet);
  	if (err < 0)
  		return err;
6f5794a6f   Remy Bohmer   Refactoring parts...
238
  	if (timeout == 0)
affae2bff   wdenk   Initial revision
239
  		return (int)size;
6f5794a6f   Remy Bohmer   Refactoring parts...
240

84d36b301   Remy Bohmer   USB: usb_control_...
241
242
243
244
245
246
247
248
  	/*
  	 * Wait for status to update until timeout expires, USB driver
  	 * interrupt handler may set the status when the USB operation has
  	 * been completed.
  	 */
  	while (timeout--) {
  		if (!((volatile unsigned long)dev->status & USB_ST_NOT_PROC))
  			break;
5b84dd67c   Mike Frysinger   usb: replace wait...
249
  		mdelay(1);
488672084   Remy Bohmer   fix USB initialis...
250
  	}
84d36b301   Remy Bohmer   USB: usb_control_...
251
252
  	if (dev->status)
  		return -1;
488672084   Remy Bohmer   fix USB initialis...
253
254
  
  	return dev->act_len;
84d36b301   Remy Bohmer   USB: usb_control_...
255

affae2bff   wdenk   Initial revision
256
257
258
259
  }
  
  /*-------------------------------------------------------------------
   * submits bulk message, and waits for completion. returns 0 if Ok or
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
260
   * negative if Error.
affae2bff   wdenk   Initial revision
261
262
263
264
265
266
   * synchronous behavior
   */
  int usb_bulk_msg(struct usb_device *dev, unsigned int pipe,
  			void *data, int len, int *actual_length, int timeout)
  {
  	if (len < 0)
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
267
  		return -EINVAL;
6f5794a6f   Remy Bohmer   Refactoring parts...
268
  	dev->status = USB_ST_NOT_PROC; /*not yet processed */
fd06028df   Ilya Yanok   usb: check return...
269
  	if (submit_bulk_msg(dev, pipe, data, len) < 0)
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
270
  		return -EIO;
6f5794a6f   Remy Bohmer   Refactoring parts...
271
272
  	while (timeout--) {
  		if (!((volatile unsigned long)dev->status & USB_ST_NOT_PROC))
affae2bff   wdenk   Initial revision
273
  			break;
5b84dd67c   Mike Frysinger   usb: replace wait...
274
  		mdelay(1);
affae2bff   wdenk   Initial revision
275
  	}
6f5794a6f   Remy Bohmer   Refactoring parts...
276
277
  	*actual_length = dev->act_len;
  	if (dev->status == 0)
affae2bff   wdenk   Initial revision
278
279
  		return 0;
  	else
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
280
  		return -EIO;
affae2bff   wdenk   Initial revision
281
282
283
284
285
286
287
288
289
290
291
  }
  
  
  /*-------------------------------------------------------------------
   * Max Packet stuff
   */
  
  /*
   * returns the max packet size, depending on the pipe direction and
   * the configurations values
   */
6f5794a6f   Remy Bohmer   Refactoring parts...
292
  int usb_maxpacket(struct usb_device *dev, unsigned long pipe)
affae2bff   wdenk   Initial revision
293
  {
6f5794a6f   Remy Bohmer   Refactoring parts...
294
295
  	/* direction is out -> use emaxpacket out */
  	if ((pipe & USB_DIR_IN) == 0)
de39f8c19   Michael Trimarchi   USB style patch, ...
296
  		return dev->epmaxpacketout[((pipe>>15) & 0xf)];
affae2bff   wdenk   Initial revision
297
  	else
de39f8c19   Michael Trimarchi   USB style patch, ...
298
  		return dev->epmaxpacketin[((pipe>>15) & 0xf)];
affae2bff   wdenk   Initial revision
299
  }
5e8baf878   Marek Vasut   GCC4.6: Fix commo...
300
301
  /*
   * The routine usb_set_maxpacket_ep() is extracted from the loop of routine
be19d324e   Remy Bohmer   Fix for USB stick...
302
303
304
305
306
307
   * usb_set_maxpacket(), because the optimizer of GCC 4.x chokes on this routine
   * when it is inlined in 1 single routine. What happens is that the register r3
   * is used as loop-count 'i', but gets overwritten later on.
   * This is clearly a compiler bug, but it is easier to workaround it here than
   * to update the compiler (Occurs with at least several GCC 4.{1,2},x
   * CodeSourcery compilers like e.g. 2007q3, 2008q1, 2008q3 lite editions on ARM)
5e8baf878   Marek Vasut   GCC4.6: Fix commo...
308
309
   *
   * NOTE: Similar behaviour was observed with GCC4.6 on ARMv5.
be19d324e   Remy Bohmer   Fix for USB stick...
310
   */
66cf64107   Mike Frysinger   usb: use noinline...
311
  static void noinline
5e8baf878   Marek Vasut   GCC4.6: Fix commo...
312
  usb_set_maxpacket_ep(struct usb_device *dev, int if_idx, int ep_idx)
be19d324e   Remy Bohmer   Fix for USB stick...
313
314
  {
  	int b;
5e8baf878   Marek Vasut   GCC4.6: Fix commo...
315
  	struct usb_endpoint_descriptor *ep;
b2fb47f18   Tom Rini   USB: Use (get|put...
316
  	u16 ep_wMaxPacketSize;
5e8baf878   Marek Vasut   GCC4.6: Fix commo...
317
318
  
  	ep = &dev->config.if_desc[if_idx].ep_desc[ep_idx];
be19d324e   Remy Bohmer   Fix for USB stick...
319
320
  
  	b = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
b2fb47f18   Tom Rini   USB: Use (get|put...
321
  	ep_wMaxPacketSize = get_unaligned(&ep->wMaxPacketSize);
be19d324e   Remy Bohmer   Fix for USB stick...
322
323
324
325
  
  	if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
  						USB_ENDPOINT_XFER_CONTROL) {
  		/* Control => bidirectional */
b2fb47f18   Tom Rini   USB: Use (get|put...
326
327
  		dev->epmaxpacketout[b] = ep_wMaxPacketSize;
  		dev->epmaxpacketin[b] = ep_wMaxPacketSize;
ceb4972a8   Vivek Gautam   usb: common: Weed...
328
329
330
  		debug("##Control EP epmaxpacketout/in[%d] = %d
  ",
  		      b, dev->epmaxpacketin[b]);
be19d324e   Remy Bohmer   Fix for USB stick...
331
332
333
  	} else {
  		if ((ep->bEndpointAddress & 0x80) == 0) {
  			/* OUT Endpoint */
b2fb47f18   Tom Rini   USB: Use (get|put...
334
335
  			if (ep_wMaxPacketSize > dev->epmaxpacketout[b]) {
  				dev->epmaxpacketout[b] = ep_wMaxPacketSize;
ceb4972a8   Vivek Gautam   usb: common: Weed...
336
337
338
  				debug("##EP epmaxpacketout[%d] = %d
  ",
  				      b, dev->epmaxpacketout[b]);
be19d324e   Remy Bohmer   Fix for USB stick...
339
340
341
  			}
  		} else {
  			/* IN Endpoint */
b2fb47f18   Tom Rini   USB: Use (get|put...
342
343
  			if (ep_wMaxPacketSize > dev->epmaxpacketin[b]) {
  				dev->epmaxpacketin[b] = ep_wMaxPacketSize;
ceb4972a8   Vivek Gautam   usb: common: Weed...
344
345
346
  				debug("##EP epmaxpacketin[%d] = %d
  ",
  				      b, dev->epmaxpacketin[b]);
be19d324e   Remy Bohmer   Fix for USB stick...
347
348
349
350
  			}
  		} /* if out */
  	} /* if control */
  }
affae2bff   wdenk   Initial revision
351
352
353
  /*
   * set the max packed value of all endpoints in the given configuration
   */
c08b1b264   Marek Vasut   USB: Staticize in...
354
  static int usb_set_maxpacket(struct usb_device *dev)
affae2bff   wdenk   Initial revision
355
  {
be19d324e   Remy Bohmer   Fix for USB stick...
356
  	int i, ii;
affae2bff   wdenk   Initial revision
357

8f8bd565f   Tom Rix   USB Consolidate d...
358
359
  	for (i = 0; i < dev->config.desc.bNumInterfaces; i++)
  		for (ii = 0; ii < dev->config.if_desc[i].desc.bNumEndpoints; ii++)
5e8baf878   Marek Vasut   GCC4.6: Fix commo...
360
  			usb_set_maxpacket_ep(dev, i, ii);
affae2bff   wdenk   Initial revision
361

affae2bff   wdenk   Initial revision
362
363
364
365
366
367
  	return 0;
  }
  
  /*******************************************************************************
   * Parse the config, located in buffer, and fills the dev->config structure.
   * Note that all little/big endian swapping are done automatically.
eaf3e613e   Julius Werner   usb: Use well-kno...
368
   * (wTotalLength has already been swapped and sanitized when it was read.)
affae2bff   wdenk   Initial revision
369
   */
c08b1b264   Marek Vasut   USB: Staticize in...
370
371
  static int usb_parse_config(struct usb_device *dev,
  			unsigned char *buffer, int cfgno)
affae2bff   wdenk   Initial revision
372
373
  {
  	struct usb_descriptor_header *head;
7455af41d   Bartlomiej Sieka   Add rudimentary h...
374
  	int index, ifno, epno, curr_if_num;
b2fb47f18   Tom Rini   USB: Use (get|put...
375
  	u16 ep_wMaxPacketSize;
605bd75af   Vivek Gautam   USB: Some cleanup...
376
  	struct usb_interface *if_desc = NULL;
7455af41d   Bartlomiej Sieka   Add rudimentary h...
377
378
379
380
381
382
383
  
  	ifno = -1;
  	epno = -1;
  	curr_if_num = -1;
  
  	dev->configno = cfgno;
  	head = (struct usb_descriptor_header *) &buffer[0];
6f5794a6f   Remy Bohmer   Refactoring parts...
384
385
386
387
  	if (head->bDescriptorType != USB_DT_CONFIG) {
  		printf(" ERROR: NOT USB_CONFIG_DESC %x
  ",
  			head->bDescriptorType);
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
388
  		return -EINVAL;
affae2bff   wdenk   Initial revision
389
  	}
eaf3e613e   Julius Werner   usb: Use well-kno...
390
391
392
  	if (head->bLength != USB_DT_CONFIG_SIZE) {
  		printf("ERROR: Invalid USB CFG length (%d)
  ", head->bLength);
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
393
  		return -EINVAL;
eaf3e613e   Julius Werner   usb: Use well-kno...
394
395
  	}
  	memcpy(&dev->config, head, USB_DT_CONFIG_SIZE);
7455af41d   Bartlomiej Sieka   Add rudimentary h...
396
  	dev->config.no_of_if = 0;
affae2bff   wdenk   Initial revision
397

8f8bd565f   Tom Rix   USB Consolidate d...
398
  	index = dev->config.desc.bLength;
6f5794a6f   Remy Bohmer   Refactoring parts...
399
400
  	/* Ok the first entry must be a configuration entry,
  	 * now process the others */
7455af41d   Bartlomiej Sieka   Add rudimentary h...
401
  	head = (struct usb_descriptor_header *) &buffer[index];
eaf3e613e   Julius Werner   usb: Use well-kno...
402
  	while (index + 1 < dev->config.desc.wTotalLength && head->bLength) {
6f5794a6f   Remy Bohmer   Refactoring parts...
403
404
  		switch (head->bDescriptorType) {
  		case USB_DT_INTERFACE:
eaf3e613e   Julius Werner   usb: Use well-kno...
405
406
407
408
409
410
411
412
413
414
415
416
  			if (head->bLength != USB_DT_INTERFACE_SIZE) {
  				printf("ERROR: Invalid USB IF length (%d)
  ",
  					head->bLength);
  				break;
  			}
  			if (index + USB_DT_INTERFACE_SIZE >
  			    dev->config.desc.wTotalLength) {
  				puts("USB IF descriptor overflowed buffer!
  ");
  				break;
  			}
6f5794a6f   Remy Bohmer   Refactoring parts...
417
  			if (((struct usb_interface_descriptor *) \
eaf3e613e   Julius Werner   usb: Use well-kno...
418
  			     head)->bInterfaceNumber != curr_if_num) {
6f5794a6f   Remy Bohmer   Refactoring parts...
419
420
  				/* this is a new interface, copy new desc */
  				ifno = dev->config.no_of_if;
eaf3e613e   Julius Werner   usb: Use well-kno...
421
422
423
424
  				if (ifno >= USB_MAXINTERFACES) {
  					puts("Too many USB interfaces!
  ");
  					/* try to go on with what we have */
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
425
  					return -EINVAL;
eaf3e613e   Julius Werner   usb: Use well-kno...
426
  				}
605bd75af   Vivek Gautam   USB: Some cleanup...
427
  				if_desc = &dev->config.if_desc[ifno];
6f5794a6f   Remy Bohmer   Refactoring parts...
428
  				dev->config.no_of_if++;
eaf3e613e   Julius Werner   usb: Use well-kno...
429
430
  				memcpy(if_desc, head,
  					USB_DT_INTERFACE_SIZE);
605bd75af   Vivek Gautam   USB: Some cleanup...
431
432
  				if_desc->no_of_ep = 0;
  				if_desc->num_altsetting = 1;
6f5794a6f   Remy Bohmer   Refactoring parts...
433
  				curr_if_num =
605bd75af   Vivek Gautam   USB: Some cleanup...
434
  				     if_desc->desc.bInterfaceNumber;
6f5794a6f   Remy Bohmer   Refactoring parts...
435
436
  			} else {
  				/* found alternate setting for the interface */
605bd75af   Vivek Gautam   USB: Some cleanup...
437
438
439
440
  				if (ifno >= 0) {
  					if_desc = &dev->config.if_desc[ifno];
  					if_desc->num_altsetting++;
  				}
6f5794a6f   Remy Bohmer   Refactoring parts...
441
442
443
  			}
  			break;
  		case USB_DT_ENDPOINT:
2f0eb2ac4   Bin Meng   usb: Handle audio...
444
445
  			if (head->bLength != USB_DT_ENDPOINT_SIZE &&
  			    head->bLength != USB_DT_ENDPOINT_AUDIO_SIZE) {
eaf3e613e   Julius Werner   usb: Use well-kno...
446
447
448
449
450
  				printf("ERROR: Invalid USB EP length (%d)
  ",
  					head->bLength);
  				break;
  			}
2f0eb2ac4   Bin Meng   usb: Handle audio...
451
  			if (index + head->bLength >
eaf3e613e   Julius Werner   usb: Use well-kno...
452
453
454
455
456
457
458
459
460
461
  			    dev->config.desc.wTotalLength) {
  				puts("USB EP descriptor overflowed buffer!
  ");
  				break;
  			}
  			if (ifno < 0) {
  				puts("Endpoint descriptor out of order!
  ");
  				break;
  			}
6f5794a6f   Remy Bohmer   Refactoring parts...
462
  			epno = dev->config.if_desc[ifno].no_of_ep;
605bd75af   Vivek Gautam   USB: Some cleanup...
463
  			if_desc = &dev->config.if_desc[ifno];
447b9cdf2   Peng Fan   common: usb: fix ...
464
  			if (epno >= USB_MAXENDPOINTS) {
eaf3e613e   Julius Werner   usb: Use well-kno...
465
466
467
  				printf("Interface %d has too many endpoints!
  ",
  					if_desc->desc.bInterfaceNumber);
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
468
  				return -EINVAL;
eaf3e613e   Julius Werner   usb: Use well-kno...
469
  			}
6f5794a6f   Remy Bohmer   Refactoring parts...
470
  			/* found an endpoint */
605bd75af   Vivek Gautam   USB: Some cleanup...
471
  			if_desc->no_of_ep++;
eaf3e613e   Julius Werner   usb: Use well-kno...
472
473
  			memcpy(&if_desc->ep_desc[epno], head,
  				USB_DT_ENDPOINT_SIZE);
b2fb47f18   Tom Rini   USB: Use (get|put...
474
475
476
477
478
479
480
481
482
  			ep_wMaxPacketSize = get_unaligned(&dev->config.\
  							if_desc[ifno].\
  							ep_desc[epno].\
  							wMaxPacketSize);
  			put_unaligned(le16_to_cpu(ep_wMaxPacketSize),
  					&dev->config.\
  					if_desc[ifno].\
  					ep_desc[epno].\
  					wMaxPacketSize);
ceb4972a8   Vivek Gautam   usb: common: Weed...
483
484
  			debug("if %d, ep %d
  ", ifno, epno);
6f5794a6f   Remy Bohmer   Refactoring parts...
485
  			break;
6497c6670   Vivek Gautam   USB: SS: Add supp...
486
  		case USB_DT_SS_ENDPOINT_COMP:
eaf3e613e   Julius Werner   usb: Use well-kno...
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
  			if (head->bLength != USB_DT_SS_EP_COMP_SIZE) {
  				printf("ERROR: Invalid USB EPC length (%d)
  ",
  					head->bLength);
  				break;
  			}
  			if (index + USB_DT_SS_EP_COMP_SIZE >
  			    dev->config.desc.wTotalLength) {
  				puts("USB EPC descriptor overflowed buffer!
  ");
  				break;
  			}
  			if (ifno < 0 || epno < 0) {
  				puts("EPC descriptor out of order!
  ");
  				break;
  			}
6497c6670   Vivek Gautam   USB: SS: Add supp...
504
  			if_desc = &dev->config.if_desc[ifno];
eaf3e613e   Julius Werner   usb: Use well-kno...
505
506
  			memcpy(&if_desc->ss_ep_comp_desc[epno], head,
  				USB_DT_SS_EP_COMP_SIZE);
6497c6670   Vivek Gautam   USB: SS: Add supp...
507
  			break;
6f5794a6f   Remy Bohmer   Refactoring parts...
508
509
  		default:
  			if (head->bLength == 0)
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
510
  				return -EINVAL;
6f5794a6f   Remy Bohmer   Refactoring parts...
511

ceb4972a8   Vivek Gautam   usb: common: Weed...
512
513
514
  			debug("unknown Description Type : %x
  ",
  			      head->bDescriptorType);
6f5794a6f   Remy Bohmer   Refactoring parts...
515

ceb4972a8   Vivek Gautam   usb: common: Weed...
516
  #ifdef DEBUG
6f5794a6f   Remy Bohmer   Refactoring parts...
517
  			{
fad2e1b06   Wolfgang Denk   common/usb.c: fix...
518
  				unsigned char *ch = (unsigned char *)head;
ceb4972a8   Vivek Gautam   usb: common: Weed...
519
  				int i;
6f5794a6f   Remy Bohmer   Refactoring parts...
520
  				for (i = 0; i < head->bLength; i++)
ceb4972a8   Vivek Gautam   usb: common: Weed...
521
522
523
524
525
  					debug("%02X ", *ch++);
  				debug("
  
  
  ");
6f5794a6f   Remy Bohmer   Refactoring parts...
526
  			}
ceb4972a8   Vivek Gautam   usb: common: Weed...
527
  #endif
6f5794a6f   Remy Bohmer   Refactoring parts...
528
  			break;
affae2bff   wdenk   Initial revision
529
  		}
7455af41d   Bartlomiej Sieka   Add rudimentary h...
530
531
  		index += head->bLength;
  		head = (struct usb_descriptor_header *)&buffer[index];
affae2bff   wdenk   Initial revision
532
  	}
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
533
  	return 0;
affae2bff   wdenk   Initial revision
534
535
536
537
538
539
540
541
542
543
  }
  
  /***********************************************************************
   * Clears an endpoint
   * endp: endpoint number in bits 0-3;
   * direction flag in bit 7 (1 = IN, 0 = OUT)
   */
  int usb_clear_halt(struct usb_device *dev, int pipe)
  {
  	int result;
9c998aa83   Wolfgang Denk   Fix low-level OHC...
544
  	int endp = usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7);
affae2bff   wdenk   Initial revision
545
546
  
  	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
6f5794a6f   Remy Bohmer   Refactoring parts...
547
548
  				 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
  				 endp, NULL, 0, USB_CNTL_TIMEOUT * 3);
affae2bff   wdenk   Initial revision
549
550
551
552
  
  	/* don't clear if failed */
  	if (result < 0)
  		return result;
9c998aa83   Wolfgang Denk   Fix low-level OHC...
553

095b8a379   Wolfgang Denk   Coding style cleanup
554
  	/*
9c998aa83   Wolfgang Denk   Fix low-level OHC...
555
556
557
  	 * NOTE: we do not get status and verify reset was successful
  	 * as some devices are reported to lock up upon this check..
  	 */
affae2bff   wdenk   Initial revision
558
  	usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
9c998aa83   Wolfgang Denk   Fix low-level OHC...
559

affae2bff   wdenk   Initial revision
560
561
562
563
564
565
566
567
568
  	/* toggle is reset on clear */
  	usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
  	return 0;
  }
  
  
  /**********************************************************************
   * get_descriptor type
   */
c08b1b264   Marek Vasut   USB: Staticize in...
569
  static int usb_get_descriptor(struct usb_device *dev, unsigned char type,
6f5794a6f   Remy Bohmer   Refactoring parts...
570
  			unsigned char index, void *buf, int size)
affae2bff   wdenk   Initial revision
571
  {
8319aeb1d   Masahiro Yamada   usb: squash lines...
572
573
574
575
  	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
  			       USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
  			       (type << 8) + index, 0, buf, size,
  			       USB_CNTL_TIMEOUT);
affae2bff   wdenk   Initial revision
576
577
578
  }
  
  /**********************************************************************
c75f57fba   Stefan Brüns   usb: Alloc buffer...
579
   * gets len of configuration cfgno
affae2bff   wdenk   Initial revision
580
   */
c75f57fba   Stefan Brüns   usb: Alloc buffer...
581
  int usb_get_configuration_len(struct usb_device *dev, int cfgno)
affae2bff   wdenk   Initial revision
582
  {
53677ef18   Wolfgang Denk   Big white-space c...
583
  	int result;
c75f57fba   Stefan Brüns   usb: Alloc buffer...
584
  	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, 9);
c60795f41   Ilya Yanok   usb: use linux/us...
585
  	struct usb_config_descriptor *config;
affae2bff   wdenk   Initial revision
586

c60795f41   Ilya Yanok   usb: use linux/us...
587
  	config = (struct usb_config_descriptor *)&buffer[0];
488672084   Remy Bohmer   fix USB initialis...
588
589
  	result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 9);
  	if (result < 9) {
affae2bff   wdenk   Initial revision
590
  		if (result < 0)
6f5794a6f   Remy Bohmer   Refactoring parts...
591
592
593
  			printf("unable to get descriptor, error %lX
  ",
  				dev->status);
affae2bff   wdenk   Initial revision
594
  		else
6f5794a6f   Remy Bohmer   Refactoring parts...
595
  			printf("config descriptor too short " \
488672084   Remy Bohmer   fix USB initialis...
596
597
  				"(expected %i, got %i)
  ", 9, result);
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
598
  		return -EIO;
affae2bff   wdenk   Initial revision
599
  	}
c75f57fba   Stefan Brüns   usb: Alloc buffer...
600
601
  	return le16_to_cpu(config->wTotalLength);
  }
affae2bff   wdenk   Initial revision
602

c75f57fba   Stefan Brüns   usb: Alloc buffer...
603
604
605
606
607
608
609
610
  /**********************************************************************
   * gets configuration cfgno and store it in the buffer
   */
  int usb_get_configuration_no(struct usb_device *dev, int cfgno,
  			     unsigned char *buffer, int length)
  {
  	int result;
  	struct usb_config_descriptor *config;
cd0a9de68   wdenk   * Patch by Lauren...
611

c75f57fba   Stefan Brüns   usb: Alloc buffer...
612
  	config = (struct usb_config_descriptor *)&buffer[0];
eaf3e613e   Julius Werner   usb: Use well-kno...
613
  	result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, length);
c75f57fba   Stefan Brüns   usb: Alloc buffer...
614
615
616
617
  	debug("get_conf_no %d Result %d, wLength %d
  ", cfgno, result,
  	      le16_to_cpu(config->wTotalLength));
  	config->wTotalLength = result; /* validated, with CPU byte order */
eaf3e613e   Julius Werner   usb: Use well-kno...
618

affae2bff   wdenk   Initial revision
619
620
621
622
623
624
625
  	return result;
  }
  
  /********************************************************************
   * set address of a device to the value in dev->devnum.
   * This can only be done by addressing the device via the default address (0)
   */
c08b1b264   Marek Vasut   USB: Staticize in...
626
  static int usb_set_address(struct usb_device *dev)
affae2bff   wdenk   Initial revision
627
  {
ceb4972a8   Vivek Gautam   usb: common: Weed...
628
629
  	debug("set address %d
  ", dev->devnum);
8319aeb1d   Masahiro Yamada   usb: squash lines...
630
631
632
  
  	return usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS,
  			       0, (dev->devnum), 0, NULL, 0, USB_CNTL_TIMEOUT);
affae2bff   wdenk   Initial revision
633
634
635
636
637
638
639
  }
  
  /********************************************************************
   * set interface number to interface
   */
  int usb_set_interface(struct usb_device *dev, int interface, int alternate)
  {
8f8bd565f   Tom Rix   USB Consolidate d...
640
  	struct usb_interface *if_face = NULL;
affae2bff   wdenk   Initial revision
641
  	int ret, i;
8f8bd565f   Tom Rix   USB Consolidate d...
642
643
  	for (i = 0; i < dev->config.desc.bNumInterfaces; i++) {
  		if (dev->config.if_desc[i].desc.bInterfaceNumber == interface) {
affae2bff   wdenk   Initial revision
644
645
646
647
648
649
  			if_face = &dev->config.if_desc[i];
  			break;
  		}
  	}
  	if (!if_face) {
  		printf("selecting invalid interface %d", interface);
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
650
  		return -EINVAL;
affae2bff   wdenk   Initial revision
651
  	}
7455af41d   Bartlomiej Sieka   Add rudimentary h...
652
653
  	/*
  	 * We should return now for devices with only one alternate setting.
6f5794a6f   Remy Bohmer   Refactoring parts...
654
655
656
657
  	 * According to 9.4.10 of the Universal Serial Bus Specification
  	 * Revision 2.0 such devices can return with a STALL. This results in
  	 * some USB sticks timeouting during initialization and then being
  	 * unusable in U-Boot.
7455af41d   Bartlomiej Sieka   Add rudimentary h...
658
659
660
  	 */
  	if (if_face->num_altsetting == 1)
  		return 0;
affae2bff   wdenk   Initial revision
661

6f5794a6f   Remy Bohmer   Refactoring parts...
662
663
664
665
666
  	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
  				USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE,
  				alternate, interface, NULL, 0,
  				USB_CNTL_TIMEOUT * 5);
  	if (ret < 0)
affae2bff   wdenk   Initial revision
667
  		return ret;
affae2bff   wdenk   Initial revision
668
669
670
671
672
673
  	return 0;
  }
  
  /********************************************************************
   * set configuration number to configuration
   */
c08b1b264   Marek Vasut   USB: Staticize in...
674
  static int usb_set_configuration(struct usb_device *dev, int configuration)
affae2bff   wdenk   Initial revision
675
676
  {
  	int res;
ceb4972a8   Vivek Gautam   usb: common: Weed...
677
678
  	debug("set configuration %d
  ", configuration);
affae2bff   wdenk   Initial revision
679
  	/* set setup command */
6f5794a6f   Remy Bohmer   Refactoring parts...
680
681
682
683
684
  	res = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
  				USB_REQ_SET_CONFIGURATION, 0,
  				configuration, 0,
  				NULL, 0, USB_CNTL_TIMEOUT);
  	if (res == 0) {
affae2bff   wdenk   Initial revision
685
686
687
  		dev->toggle[0] = 0;
  		dev->toggle[1] = 0;
  		return 0;
6f5794a6f   Remy Bohmer   Refactoring parts...
688
  	} else
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
689
  		return -EIO;
affae2bff   wdenk   Initial revision
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
  }
  
  /********************************************************************
   * set protocol to protocol
   */
  int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol)
  {
  	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
  		USB_REQ_SET_PROTOCOL, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
  		protocol, ifnum, NULL, 0, USB_CNTL_TIMEOUT);
  }
  
  /********************************************************************
   * set idle
   */
  int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id)
  {
  	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
  		USB_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
  		(duration << 8) | report_id, ifnum, NULL, 0, USB_CNTL_TIMEOUT);
  }
  
  /********************************************************************
   * get report
   */
6f5794a6f   Remy Bohmer   Refactoring parts...
715
716
  int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type,
  		   unsigned char id, void *buf, int size)
affae2bff   wdenk   Initial revision
717
718
  {
  	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
6f5794a6f   Remy Bohmer   Refactoring parts...
719
720
721
  			USB_REQ_GET_REPORT,
  			USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
  			(type << 8) + id, ifnum, buf, size, USB_CNTL_TIMEOUT);
affae2bff   wdenk   Initial revision
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
  }
  
  /********************************************************************
   * get class descriptor
   */
  int usb_get_class_descriptor(struct usb_device *dev, int ifnum,
  		unsigned char type, unsigned char id, void *buf, int size)
  {
  	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
  		USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,
  		(type << 8) + id, ifnum, buf, size, USB_CNTL_TIMEOUT);
  }
  
  /********************************************************************
   * get string index in buffer
   */
c08b1b264   Marek Vasut   USB: Staticize in...
738
  static int usb_get_string(struct usb_device *dev, unsigned short langid,
6f5794a6f   Remy Bohmer   Refactoring parts...
739
  		   unsigned char index, void *buf, int size)
affae2bff   wdenk   Initial revision
740
  {
9c998aa83   Wolfgang Denk   Fix low-level OHC...
741
742
743
744
745
746
747
  	int i;
  	int result;
  
  	for (i = 0; i < 3; ++i) {
  		/* some devices are flaky */
  		result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
  			USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
095b8a379   Wolfgang Denk   Coding style cleanup
748
  			(USB_DT_STRING << 8) + index, langid, buf, size,
9c998aa83   Wolfgang Denk   Fix low-level OHC...
749
750
751
752
  			USB_CNTL_TIMEOUT);
  
  		if (result > 0)
  			break;
095b8a379   Wolfgang Denk   Coding style cleanup
753
  	}
9c998aa83   Wolfgang Denk   Fix low-level OHC...
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
  	return result;
  }
  
  
  static void usb_try_string_workarounds(unsigned char *buf, int *length)
  {
  	int newlength, oldlength = *length;
  
  	for (newlength = 2; newlength + 1 < oldlength; newlength += 2)
  		if (!isprint(buf[newlength]) || buf[newlength + 1])
  			break;
  
  	if (newlength > 2) {
  		buf[0] = newlength;
  		*length = newlength;
  	}
affae2bff   wdenk   Initial revision
770
  }
9c998aa83   Wolfgang Denk   Fix low-level OHC...
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
  
  static int usb_string_sub(struct usb_device *dev, unsigned int langid,
  		unsigned int index, unsigned char *buf)
  {
  	int rc;
  
  	/* Try to read the string descriptor by asking for the maximum
  	 * possible number of bytes */
  	rc = usb_get_string(dev, langid, index, buf, 255);
  
  	/* If that failed try to read the descriptor length, then
  	 * ask for just that many bytes */
  	if (rc < 2) {
  		rc = usb_get_string(dev, langid, index, buf, 2);
  		if (rc == 2)
  			rc = usb_get_string(dev, langid, index, buf, buf[0]);
  	}
  
  	if (rc >= 2) {
  		if (!buf[0] && !buf[1])
  			usb_try_string_workarounds(buf, &rc);
  
  		/* There might be extra junk at the end of the descriptor */
  		if (buf[0] < rc)
  			rc = buf[0];
  
  		rc = rc - (rc & 1); /* force a multiple of two */
  	}
  
  	if (rc < 2)
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
801
  		rc = -EINVAL;
9c998aa83   Wolfgang Denk   Fix low-level OHC...
802
803
804
  
  	return rc;
  }
affae2bff   wdenk   Initial revision
805
806
807
808
809
810
811
  /********************************************************************
   * usb_string:
   * Get string index and translate it to ascii.
   * returns string length (> 0) or error (< 0)
   */
  int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
  {
f57661394   Puneet Saxena   USB: Align buffer...
812
  	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, mybuf, USB_BUFSIZ);
affae2bff   wdenk   Initial revision
813
814
815
816
817
  	unsigned char *tbuf;
  	int err;
  	unsigned int u, idx;
  
  	if (size <= 0 || !buf || !index)
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
818
  		return -EINVAL;
affae2bff   wdenk   Initial revision
819
  	buf[0] = 0;
d0ff51ba5   Wolfgang Denk   Code cleanup: fix...
820
  	tbuf = &mybuf[0];
affae2bff   wdenk   Initial revision
821
822
823
  
  	/* get langid for strings if it's not yet known */
  	if (!dev->have_langid) {
9c998aa83   Wolfgang Denk   Fix low-level OHC...
824
  		err = usb_string_sub(dev, 0, 0, tbuf);
affae2bff   wdenk   Initial revision
825
  		if (err < 0) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
826
827
828
  			debug("error getting string descriptor 0 " \
  			      "(error=%lx)
  ", dev->status);
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
829
  			return -EIO;
affae2bff   wdenk   Initial revision
830
  		} else if (tbuf[0] < 4) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
831
832
  			debug("string descriptor 0 too short
  ");
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
833
  			return -EIO;
affae2bff   wdenk   Initial revision
834
835
  		} else {
  			dev->have_langid = -1;
6f5794a6f   Remy Bohmer   Refactoring parts...
836
  			dev->string_langid = tbuf[2] | (tbuf[3] << 8);
affae2bff   wdenk   Initial revision
837
  				/* always use the first langid listed */
ceb4972a8   Vivek Gautam   usb: common: Weed...
838
839
840
841
  			debug("USB device number %d default " \
  			      "language ID 0x%x
  ",
  			      dev->devnum, dev->string_langid);
affae2bff   wdenk   Initial revision
842
843
  		}
  	}
cd0a9de68   wdenk   * Patch by Lauren...
844

9c998aa83   Wolfgang Denk   Fix low-level OHC...
845
  	err = usb_string_sub(dev, dev->string_langid, index, tbuf);
affae2bff   wdenk   Initial revision
846
847
  	if (err < 0)
  		return err;
9c998aa83   Wolfgang Denk   Fix low-level OHC...
848

affae2bff   wdenk   Initial revision
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
  	size--;		/* leave room for trailing NULL char in output buffer */
  	for (idx = 0, u = 2; u < err; u += 2) {
  		if (idx >= size)
  			break;
  		if (tbuf[u+1])			/* high byte */
  			buf[idx++] = '?';  /* non-ASCII character */
  		else
  			buf[idx++] = tbuf[u];
  	}
  	buf[idx] = 0;
  	err = idx;
  	return err;
  }
  
  
  /********************************************************************
   * USB device handling:
   * the USB device are static allocated [USB_MAX_DEVICE].
   */
95fbfe429   Simon Glass   dm: usb: Convert ...
868
  #ifndef CONFIG_DM_USB
affae2bff   wdenk   Initial revision
869
870
871
872
  
  /* returns a pointer to the device with the index [index].
   * if the device is not assigned (dev->devnum==-1) returns NULL
   */
6f5794a6f   Remy Bohmer   Refactoring parts...
873
  struct usb_device *usb_get_dev_index(int index)
affae2bff   wdenk   Initial revision
874
  {
6f5794a6f   Remy Bohmer   Refactoring parts...
875
  	if (usb_dev[index].devnum == -1)
affae2bff   wdenk   Initial revision
876
877
878
879
  		return NULL;
  	else
  		return &usb_dev[index];
  }
79b588872   Simon Glass   dm: usb: Adjust u...
880
  int usb_alloc_new_device(struct udevice *controller, struct usb_device **devp)
affae2bff   wdenk   Initial revision
881
882
  {
  	int i;
ceb4972a8   Vivek Gautam   usb: common: Weed...
883
884
  	debug("New Device %d
  ", dev_index);
6f5794a6f   Remy Bohmer   Refactoring parts...
885
886
887
  	if (dev_index == USB_MAX_DEVICE) {
  		printf("ERROR, too many USB Devices, max=%d
  ", USB_MAX_DEVICE);
79b588872   Simon Glass   dm: usb: Adjust u...
888
  		return -ENOSPC;
affae2bff   wdenk   Initial revision
889
  	}
6f5794a6f   Remy Bohmer   Refactoring parts...
890
891
892
893
894
895
  	/* default Address is 0, real addresses start with 1 */
  	usb_dev[dev_index].devnum = dev_index + 1;
  	usb_dev[dev_index].maxchild = 0;
  	for (i = 0; i < USB_MAXCHILDREN; i++)
  		usb_dev[dev_index].children[i] = NULL;
  	usb_dev[dev_index].parent = NULL;
c7e3b2b58   Lucas Stach   usb: lowlevel int...
896
  	usb_dev[dev_index].controller = controller;
affae2bff   wdenk   Initial revision
897
  	dev_index++;
79b588872   Simon Glass   dm: usb: Adjust u...
898
899
900
  	*devp = &usb_dev[dev_index - 1];
  
  	return 0;
affae2bff   wdenk   Initial revision
901
  }
359439d28   Milind Choudhary   usb: Clean up new...
902
903
904
905
906
  /*
   * Free the newly created device node.
   * Called in error cases where configuring a newly attached
   * device fails for some reason.
   */
79b588872   Simon Glass   dm: usb: Adjust u...
907
  void usb_free_device(struct udevice *controller)
359439d28   Milind Choudhary   usb: Clean up new...
908
909
  {
  	dev_index--;
ceb4972a8   Vivek Gautam   usb: common: Weed...
910
911
  	debug("Freeing device node: %d
  ", dev_index);
359439d28   Milind Choudhary   usb: Clean up new...
912
913
914
  	memset(&usb_dev[dev_index], 0, sizeof(struct usb_device));
  	usb_dev[dev_index].devnum = -1;
  }
affae2bff   wdenk   Initial revision
915
916
  
  /*
5853e1335   Vivek Gautam   USB: xHCI: Add st...
917
918
919
920
921
922
923
924
925
   * XHCI issues Enable Slot command and thereafter
   * allocates device contexts. Provide a weak alias
   * function for the purpose, so that XHCI overrides it
   * and EHCI/OHCI just work out of the box.
   */
  __weak int usb_alloc_device(struct usb_device *udev)
  {
  	return 0;
  }
95fbfe429   Simon Glass   dm: usb: Convert ...
926
  #endif /* !CONFIG_DM_USB */
862e75c0d   Simon Glass   dm: usb: Refactor...
927

682c9f8df   Hans de Goede   usb: Pass device ...
928
  static int usb_hub_port_reset(struct usb_device *dev, struct usb_device *hub)
862e75c0d   Simon Glass   dm: usb: Refactor...
929
  {
3ed9eb93c   Stefan Roese   usb: Don't reset ...
930
  	if (!hub)
8802f5634   Hans de Goede   usb: Add an usb_d...
931
  		usb_reset_root_port(dev);
862e75c0d   Simon Glass   dm: usb: Refactor...
932
933
934
  
  	return 0;
  }
0ed27905c   Simon Glass   dm: usb: Complete...
935
  static int get_descriptor_len(struct usb_device *dev, int len, int expect_len)
affae2bff   wdenk   Initial revision
936
  {
128fcac08   Simon Glass   dm: usb: Move des...
937
  	__maybe_unused struct usb_device_descriptor *desc;
f57661394   Puneet Saxena   USB: Align buffer...
938
  	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ);
0ed27905c   Simon Glass   dm: usb: Complete...
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
  	int err;
  
  	desc = (struct usb_device_descriptor *)tmpbuf;
  
  	err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, len);
  	if (err < expect_len) {
  		if (err < 0) {
  			printf("unable to get device descriptor (error=%d)
  ",
  				err);
  			return err;
  		} else {
  			printf("USB device descriptor short read (expected %i, got %i)
  ",
  				expect_len, err);
  			return -EIO;
  		}
  	}
  	memcpy(&dev->descriptor, tmpbuf, sizeof(dev->descriptor));
  
  	return 0;
  }
  
  static int usb_setup_descriptor(struct usb_device *dev, bool do_read)
  {
5853e1335   Vivek Gautam   USB: xHCI: Add st...
964
  	/*
53d8aa0f6   Simon Glass   dm: usb: Drop the...
965
  	 * This is a Windows scheme of initialization sequence, with double
488672084   Remy Bohmer   fix USB initialis...
966
  	 * reset of the device (Linux uses the same sequence)
c9e8436b1   Remy Bohmer   USB layer of U-Bo...
967
968
  	 * Some equipment is said to work only with such init sequence; this
  	 * patch is based on the work by Alan Stern:
de39f8c19   Michael Trimarchi   USB style patch, ...
969
970
  	 * http://sourceforge.net/mailarchive/forum.php?
  	 * thread_id=5729457&forum_id=5398
9c998aa83   Wolfgang Denk   Fix low-level OHC...
971
  	 */
9c998aa83   Wolfgang Denk   Fix low-level OHC...
972

53d8aa0f6   Simon Glass   dm: usb: Drop the...
973
974
  	/*
  	 * send 64-byte GET-DEVICE-DESCRIPTOR request.  Since the descriptor is
9c998aa83   Wolfgang Denk   Fix low-level OHC...
975
976
  	 * only 18 bytes long, this will terminate with a short packet.  But if
  	 * the maxpacket size is 8 or 16 the device may be waiting to transmit
2b338ef41   Hans de Goede   usb: Fix maxpacke...
977
978
  	 * some more, or keeps on retransmitting the 8 byte header.
  	 */
9c998aa83   Wolfgang Denk   Fix low-level OHC...
979

2b338ef41   Hans de Goede   usb: Fix maxpacke...
980
981
982
983
984
985
986
987
988
  	if (dev->speed == USB_SPEED_LOW) {
  		dev->descriptor.bMaxPacketSize0 = 8;
  		dev->maxpacketsize = PACKET_SIZE_8;
  	} else {
  		dev->descriptor.bMaxPacketSize0 = 64;
  		dev->maxpacketsize = PACKET_SIZE_64;
  	}
  	dev->epmaxpacketin[0] = dev->descriptor.bMaxPacketSize0;
  	dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
488672084   Remy Bohmer   fix USB initialis...
989

c008faa77   Bin Meng   usb: Only get 64 ...
990
  	if (do_read && dev->speed == USB_SPEED_FULL) {
128fcac08   Simon Glass   dm: usb: Move des...
991
  		int err;
862e75c0d   Simon Glass   dm: usb: Refactor...
992

128fcac08   Simon Glass   dm: usb: Move des...
993
  		/*
c008faa77   Bin Meng   usb: Only get 64 ...
994
995
996
997
998
999
1000
1001
1002
  		 * Validate we've received only at least 8 bytes, not that
  		 * we've received the entire descriptor. The reasoning is:
  		 * - The code only uses fields in the first 8 bytes, so
  		 *   that's all we need to have fetched at this stage.
  		 * - The smallest maxpacket size is 8 bytes. Before we know
  		 *   the actual maxpacket the device uses, the USB controller
  		 *   may only accept a single packet. Consequently we are only
  		 *   guaranteed to receive 1 packet (at least 8 bytes) even in
  		 *   a non-error case.
128fcac08   Simon Glass   dm: usb: Move des...
1003
  		 *
c008faa77   Bin Meng   usb: Only get 64 ...
1004
1005
1006
1007
  		 * At least the DWC2 controller needs to be programmed with
  		 * the number of packets in addition to the number of bytes.
  		 * A request for 64 bytes of data with the maxpacket guessed
  		 * as 64 (above) yields a request for 1 packet.
128fcac08   Simon Glass   dm: usb: Move des...
1008
  		 */
0ed27905c   Simon Glass   dm: usb: Complete...
1009
1010
1011
  		err = get_descriptor_len(dev, 64, 8);
  		if (err)
  			return err;
9c998aa83   Wolfgang Denk   Fix low-level OHC...
1012
  	}
488672084   Remy Bohmer   fix USB initialis...
1013

de39f8c19   Michael Trimarchi   USB style patch, ...
1014
  	dev->epmaxpacketin[0] = dev->descriptor.bMaxPacketSize0;
affae2bff   wdenk   Initial revision
1015
1016
  	dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
  	switch (dev->descriptor.bMaxPacketSize0) {
de39f8c19   Michael Trimarchi   USB style patch, ...
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
  	case 8:
  		dev->maxpacketsize  = PACKET_SIZE_8;
  		break;
  	case 16:
  		dev->maxpacketsize = PACKET_SIZE_16;
  		break;
  	case 32:
  		dev->maxpacketsize = PACKET_SIZE_32;
  		break;
  	case 64:
  		dev->maxpacketsize = PACKET_SIZE_64;
  		break;
04ee6ee2c   Paul Kocialkowski   usb: Early failur...
1029
  	default:
c008faa77   Bin Meng   usb: Only get 64 ...
1030
1031
  		printf("%s: invalid max packet size
  ", __func__);
04ee6ee2c   Paul Kocialkowski   usb: Early failur...
1032
  		return -EIO;
affae2bff   wdenk   Initial revision
1033
  	}
128fcac08   Simon Glass   dm: usb: Move des...
1034
1035
1036
  
  	return 0;
  }
91398f985   Simon Glass   dm: usb: Split ou...
1037
  static int usb_prepare_device(struct usb_device *dev, int addr, bool do_read,
9eb72dd1f   Hans de Goede   usb: usb_setup_de...
1038
  			      struct usb_device *parent)
128fcac08   Simon Glass   dm: usb: Move des...
1039
  {
91398f985   Simon Glass   dm: usb: Split ou...
1040
  	int err;
128fcac08   Simon Glass   dm: usb: Move des...
1041
1042
1043
1044
1045
1046
1047
  
  	/*
  	 * Allocate usb 3.0 device context.
  	 * USB 3.0 (xHCI) protocol tries to allocate device slot
  	 * and related data structures first. This call does that.
  	 * Refer to sec 4.3.2 in xHCI spec rev1.0
  	 */
91398f985   Simon Glass   dm: usb: Split ou...
1048
1049
  	err = usb_alloc_device(dev);
  	if (err) {
128fcac08   Simon Glass   dm: usb: Move des...
1050
1051
  		printf("Cannot allocate device context to get SLOT_ID
  ");
91398f985   Simon Glass   dm: usb: Split ou...
1052
  		return err;
128fcac08   Simon Glass   dm: usb: Move des...
1053
  	}
128fcac08   Simon Glass   dm: usb: Move des...
1054
1055
1056
  	err = usb_setup_descriptor(dev, do_read);
  	if (err)
  		return err;
682c9f8df   Hans de Goede   usb: Pass device ...
1057
  	err = usb_hub_port_reset(dev, parent);
128fcac08   Simon Glass   dm: usb: Move des...
1058
1059
  	if (err)
  		return err;
affae2bff   wdenk   Initial revision
1060
1061
1062
1063
1064
  	dev->devnum = addr;
  
  	err = usb_set_address(dev); /* set address */
  
  	if (err < 0) {
6f5794a6f   Remy Bohmer   Refactoring parts...
1065
1066
1067
1068
  		printf("
        USB device not accepting new address " \
  			"(error=%lX)
  ", dev->status);
91398f985   Simon Glass   dm: usb: Split ou...
1069
  		return err;
affae2bff   wdenk   Initial revision
1070
  	}
5b84dd67c   Mike Frysinger   usb: replace wait...
1071
  	mdelay(10);	/* Let the SET_ADDRESS settle */
affae2bff   wdenk   Initial revision
1072

932bb668b   Bin Meng   usb: Read device ...
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
  	/*
  	 * If we haven't read device descriptor before, read it here
  	 * after device is assigned an address. This is only applicable
  	 * to xHCI so far.
  	 */
  	if (!do_read) {
  		err = usb_setup_descriptor(dev, true);
  		if (err)
  			return err;
  	}
91398f985   Simon Glass   dm: usb: Split ou...
1083
1084
  	return 0;
  }
95fbfe429   Simon Glass   dm: usb: Convert ...
1085
  int usb_select_config(struct usb_device *dev)
91398f985   Simon Glass   dm: usb: Split ou...
1086
  {
2f1b4302e   Marek Vasut   usb: Don't init p...
1087
  	unsigned char *tmpbuf = NULL;
0ed27905c   Simon Glass   dm: usb: Complete...
1088
  	int err;
91398f985   Simon Glass   dm: usb: Split ou...
1089

0ed27905c   Simon Glass   dm: usb: Complete...
1090
1091
1092
  	err = get_descriptor_len(dev, USB_DT_DEVICE_SIZE, USB_DT_DEVICE_SIZE);
  	if (err)
  		return err;
affae2bff   wdenk   Initial revision
1093

affae2bff   wdenk   Initial revision
1094
  	/* correct le values */
c918261c6   Christian Eggers   USB: replace old ...
1095
1096
1097
1098
  	le16_to_cpus(&dev->descriptor.bcdUSB);
  	le16_to_cpus(&dev->descriptor.idVendor);
  	le16_to_cpus(&dev->descriptor.idProduct);
  	le16_to_cpus(&dev->descriptor.bcdDevice);
0ed27905c   Simon Glass   dm: usb: Complete...
1099

ef71290be   Marek Vasut   usb: Assure Get D...
1100
1101
1102
1103
1104
1105
1106
  	/*
  	 * Kingston DT Ultimate 32GB USB 3.0 seems to be extremely sensitive
  	 * about this first Get Descriptor request. If there are any other
  	 * requests in the first microframe, the stick crashes. Wait about
  	 * one microframe duration here (1mS for USB 1.x , 125uS for USB 2.0).
  	 */
  	mdelay(1);
affae2bff   wdenk   Initial revision
1107
  	/* only support for one config for now */
c75f57fba   Stefan Brüns   usb: Alloc buffer...
1108
1109
1110
1111
1112
1113
1114
1115
  	err = usb_get_configuration_len(dev, 0);
  	if (err >= 0) {
  		tmpbuf = (unsigned char *)malloc_cache_aligned(err);
  		if (!tmpbuf)
  			err = -ENOMEM;
  		else
  			err = usb_get_configuration_no(dev, 0, tmpbuf, err);
  	}
8b8d779da   Vincent Palatin   usb: fallback saf...
1116
1117
1118
1119
1120
  	if (err < 0) {
  		printf("usb_new_device: Cannot read configuration, " \
  		       "skipping device %04x:%04x
  ",
  		       dev->descriptor.idVendor, dev->descriptor.idProduct);
c75f57fba   Stefan Brüns   usb: Alloc buffer...
1121
  		free(tmpbuf);
0ed27905c   Simon Glass   dm: usb: Complete...
1122
  		return err;
8b8d779da   Vincent Palatin   usb: fallback saf...
1123
  	}
f57661394   Puneet Saxena   USB: Align buffer...
1124
  	usb_parse_config(dev, tmpbuf, 0);
c75f57fba   Stefan Brüns   usb: Alloc buffer...
1125
  	free(tmpbuf);
affae2bff   wdenk   Initial revision
1126
  	usb_set_maxpacket(dev);
0ed27905c   Simon Glass   dm: usb: Complete...
1127
1128
1129
1130
1131
1132
1133
  	/*
  	 * we set the default configuration here
  	 * This seems premature. If the driver wants a different configuration
  	 * it will need to select itself.
  	 */
  	err = usb_set_configuration(dev, dev->config.desc.bConfigurationValue);
  	if (err < 0) {
6f5794a6f   Remy Bohmer   Refactoring parts...
1134
1135
1136
  		printf("failed to set default configuration " \
  			"len %d, status %lX
  ", dev->act_len, dev->status);
0ed27905c   Simon Glass   dm: usb: Complete...
1137
  		return err;
affae2bff   wdenk   Initial revision
1138
  	}
f647bf0ba   Marek Vasut   usb: Wait after s...
1139
1140
1141
1142
1143
1144
1145
  
  	/*
  	 * Wait until the Set Configuration request gets processed by the
  	 * device. This is required by at least SanDisk Cruzer Pop USB 2.0
  	 * and Kingston DT Ultimate 32GB USB 3.0 on DWC2 OTG controller.
  	 */
  	mdelay(10);
ceb4972a8   Vivek Gautam   usb: common: Weed...
1146
1147
1148
1149
  	debug("new device strings: Mfr=%d, Product=%d, SerialNumber=%d
  ",
  	      dev->descriptor.iManufacturer, dev->descriptor.iProduct,
  	      dev->descriptor.iSerialNumber);
affae2bff   wdenk   Initial revision
1150
1151
1152
1153
  	memset(dev->mf, 0, sizeof(dev->mf));
  	memset(dev->prod, 0, sizeof(dev->prod));
  	memset(dev->serial, 0, sizeof(dev->serial));
  	if (dev->descriptor.iManufacturer)
6f5794a6f   Remy Bohmer   Refactoring parts...
1154
1155
  		usb_string(dev, dev->descriptor.iManufacturer,
  			   dev->mf, sizeof(dev->mf));
affae2bff   wdenk   Initial revision
1156
  	if (dev->descriptor.iProduct)
6f5794a6f   Remy Bohmer   Refactoring parts...
1157
1158
  		usb_string(dev, dev->descriptor.iProduct,
  			   dev->prod, sizeof(dev->prod));
affae2bff   wdenk   Initial revision
1159
  	if (dev->descriptor.iSerialNumber)
6f5794a6f   Remy Bohmer   Refactoring parts...
1160
1161
  		usb_string(dev, dev->descriptor.iSerialNumber,
  			   dev->serial, sizeof(dev->serial));
ceb4972a8   Vivek Gautam   usb: common: Weed...
1162
1163
1164
1165
1166
1167
  	debug("Manufacturer %s
  ", dev->mf);
  	debug("Product      %s
  ", dev->prod);
  	debug("SerialNumber %s
  ", dev->serial);
0ed27905c   Simon Glass   dm: usb: Complete...
1168
1169
1170
  
  	return 0;
  }
95fbfe429   Simon Glass   dm: usb: Convert ...
1171
  int usb_setup_device(struct usb_device *dev, bool do_read,
9eb72dd1f   Hans de Goede   usb: usb_setup_de...
1172
  		     struct usb_device *parent)
0ed27905c   Simon Glass   dm: usb: Complete...
1173
1174
1175
1176
1177
1178
1179
  {
  	int addr;
  	int ret;
  
  	/* We still haven't set the Address yet */
  	addr = dev->devnum;
  	dev->devnum = 0;
9eb72dd1f   Hans de Goede   usb: usb_setup_de...
1180
  	ret = usb_prepare_device(dev, addr, do_read, parent);
0ed27905c   Simon Glass   dm: usb: Complete...
1181
1182
1183
1184
1185
1186
  	if (ret)
  		return ret;
  	ret = usb_select_config(dev);
  
  	return ret;
  }
95fbfe429   Simon Glass   dm: usb: Convert ...
1187
  #ifndef CONFIG_DM_USB
0ed27905c   Simon Glass   dm: usb: Complete...
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
  /*
   * By the time we get here, the device has gotten a new device ID
   * and is in the default state. We need to identify the thing and
   * get the ball rolling..
   *
   * Returns 0 for success, != 0 for error.
   */
  int usb_new_device(struct usb_device *dev)
  {
  	bool do_read = true;
  	int err;
  
  	/*
  	 * XHCI needs to issue a Address device command to setup
  	 * proper device context structures, before it can interact
  	 * with the device. So a get_descriptor will fail before any
  	 * of that is done for XHCI unlike EHCI.
  	 */
0a8cc1a3a   Masahiro Yamada   usb: move CONFIG_...
1206
  #ifdef CONFIG_USB_XHCI_HCD
0ed27905c   Simon Glass   dm: usb: Complete...
1207
1208
  	do_read = false;
  #endif
9eb72dd1f   Hans de Goede   usb: usb_setup_de...
1209
  	err = usb_setup_device(dev, do_read, dev->parent);
0ed27905c   Simon Glass   dm: usb: Complete...
1210
1211
1212
1213
1214
1215
1216
  	if (err)
  		return err;
  
  	/* Now probe if the device is a hub */
  	err = usb_hub_probe(dev, 0);
  	if (err < 0)
  		return err;
affae2bff   wdenk   Initial revision
1217
1218
  	return 0;
  }
95fbfe429   Simon Glass   dm: usb: Convert ...
1219
  #endif
affae2bff   wdenk   Initial revision
1220

16297cfb2   Mateusz Zalega   usb: new board-sp...
1221
  __weak
bba679144   Troy Kisky   usb: rename board...
1222
  int board_usb_init(int index, enum usb_init_type init)
16297cfb2   Mateusz Zalega   usb: new board-sp...
1223
1224
1225
  {
  	return 0;
  }
db378d786   Kishon Vijay Abraham I   common: cmd_dfu: ...
1226
1227
1228
1229
1230
1231
  
  __weak
  int board_usb_cleanup(int index, enum usb_init_type init)
  {
  	return 0;
  }
95fbfe429   Simon Glass   dm: usb: Convert ...
1232
1233
1234
1235
1236
1237
1238
1239
1240
  
  bool usb_device_has_child_on_port(struct usb_device *parent, int port)
  {
  #ifdef CONFIG_DM_USB
  	return false;
  #else
  	return parent->children[port] != NULL;
  #endif
  }
faa7db24a   Stefan Brüns   usb: Move determi...
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
  #ifdef CONFIG_DM_USB
  void usb_find_usb2_hub_address_port(struct usb_device *udev,
  			       uint8_t *hub_address, uint8_t *hub_port)
  {
  	struct udevice *parent;
  	struct usb_device *uparent, *ttdev;
  
  	/*
  	 * When called from usb-uclass.c: usb_scan_device() udev->dev points
  	 * to the parent udevice, not the actual udevice belonging to the
  	 * udev as the device is not instantiated yet. So when searching
  	 * for the first usb-2 parent start with udev->dev not
  	 * udev->dev->parent .
  	 */
  	ttdev = udev;
  	parent = udev->dev;
  	uparent = dev_get_parent_priv(parent);
  
  	while (uparent->speed != USB_SPEED_HIGH) {
  		struct udevice *dev = parent;
  
  		if (device_get_uclass_id(dev->parent) != UCLASS_USB_HUB) {
  			printf("Error: Cannot find high speed parent of usb-1 device
  ");
  			*hub_address = 0;
  			*hub_port = 0;
  			return;
  		}
  
  		ttdev = dev_get_parent_priv(dev);
  		parent = dev->parent;
  		uparent = dev_get_parent_priv(parent);
  	}
  	*hub_address = uparent->devnum;
  	*hub_port = ttdev->portnr;
  }
  #else
  void usb_find_usb2_hub_address_port(struct usb_device *udev,
  			       uint8_t *hub_address, uint8_t *hub_port)
  {
  	/* Find out the nearest parent which is high speed */
  	while (udev->parent->parent != NULL)
  		if (udev->parent->speed != USB_SPEED_HIGH) {
  			udev = udev->parent;
  		} else {
  			*hub_address = udev->parent->devnum;
  			*hub_port = udev->portnr;
  			return;
  		}
  
  	printf("Error: Cannot find high speed parent of usb-1 device
  ");
  	*hub_address = 0;
  	*hub_port = 0;
  }
  #endif
affae2bff   wdenk   Initial revision
1297
  /* EOF */