Commit 6a1b206dc48d435c6394cf3a8acc8a883516dd9d
1 parent
79b5888729
Exists in
v2017.01-smarct4x
and in
34 other branches
dm: usb: Convert 'usb' command to support driver model
Adjust this command to work with the new driver model uclass. It needs to iterate through multiple independent controllers to find hubs, and work through their children recursively in a different way. Otherwise the functionality is much the same. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Marek Vasut <marex@denx.de>
Showing 1 changed file with 145 additions and 2 deletions Side-by-side Diff
common/cmd_usb.c
... | ... | @@ -2,6 +2,9 @@ |
2 | 2 | * (C) Copyright 2001 |
3 | 3 | * Denis Peter, MPL AG Switzerland |
4 | 4 | * |
5 | + * Adapted for U-Boot driver model | |
6 | + * (C) Copyright 2015 Google, Inc | |
7 | + * | |
5 | 8 | * Most of this source has been derived from the Linux USB |
6 | 9 | * project. |
7 | 10 | * |
... | ... | @@ -10,6 +13,7 @@ |
10 | 13 | |
11 | 14 | #include <common.h> |
12 | 15 | #include <command.h> |
16 | +#include <dm.h> | |
13 | 17 | #include <asm/byteorder.h> |
14 | 18 | #include <asm/unaligned.h> |
15 | 19 | #include <part.h> |
16 | 20 | |
17 | 21 | |
... | ... | @@ -252,9 +256,47 @@ |
252 | 256 | printf("\n"); |
253 | 257 | } |
254 | 258 | |
259 | +/* | |
260 | + * With driver model this isn't right since we can have multiple controllers | |
261 | + * and the device numbering starts at 1 on each bus. | |
262 | + * TODO(sjg@chromium.org): Add a way to specify the controller/bus. | |
263 | + */ | |
255 | 264 | static struct usb_device *usb_find_device(int devnum) |
256 | 265 | { |
266 | +#ifdef CONFIG_DM_USB | |
257 | 267 | struct usb_device *udev; |
268 | + struct udevice *hub; | |
269 | + struct uclass *uc; | |
270 | + int ret; | |
271 | + | |
272 | + /* Device addresses start at 1 */ | |
273 | + devnum++; | |
274 | + ret = uclass_get(UCLASS_USB_HUB, &uc); | |
275 | + if (ret) | |
276 | + return NULL; | |
277 | + | |
278 | + uclass_foreach_dev(hub, uc) { | |
279 | + struct udevice *dev; | |
280 | + | |
281 | + if (!device_active(hub)) | |
282 | + continue; | |
283 | + udev = dev_get_parentdata(hub); | |
284 | + if (udev->devnum == devnum) | |
285 | + return udev; | |
286 | + | |
287 | + for (device_find_first_child(hub, &dev); | |
288 | + dev; | |
289 | + device_find_next_child(&dev)) { | |
290 | + if (!device_active(hub)) | |
291 | + continue; | |
292 | + | |
293 | + udev = dev_get_parentdata(dev); | |
294 | + if (udev->devnum == devnum) | |
295 | + return udev; | |
296 | + } | |
297 | + } | |
298 | +#else | |
299 | + struct usb_device *udev; | |
258 | 300 | int d; |
259 | 301 | |
260 | 302 | for (d = 0; d < USB_MAX_DEVICE; d++) { |
... | ... | @@ -264,6 +306,7 @@ |
264 | 306 | if (udev->devnum == devnum) |
265 | 307 | return udev; |
266 | 308 | } |
309 | +#endif | |
267 | 310 | |
268 | 311 | return NULL; |
269 | 312 | } |
270 | 313 | |
271 | 314 | |
272 | 315 | |
273 | 316 | |
274 | 317 | |
275 | 318 | |
... | ... | @@ -293,20 +336,31 @@ |
293 | 336 | /* shows the device tree recursively */ |
294 | 337 | static void usb_show_tree_graph(struct usb_device *dev, char *pre) |
295 | 338 | { |
296 | - int i, index; | |
339 | + int index; | |
297 | 340 | int has_child, last_child; |
298 | 341 | |
299 | 342 | index = strlen(pre); |
300 | 343 | printf(" %s", pre); |
344 | +#ifdef CONFIG_DM_USB | |
345 | + has_child = device_has_active_children(dev->dev); | |
346 | +#else | |
301 | 347 | /* check if the device has connected children */ |
348 | + int i; | |
349 | + | |
302 | 350 | has_child = 0; |
303 | 351 | for (i = 0; i < dev->maxchild; i++) { |
304 | 352 | if (dev->children[i] != NULL) |
305 | 353 | has_child = 1; |
306 | 354 | } |
355 | +#endif | |
307 | 356 | /* check if we are the last one */ |
357 | +#ifdef CONFIG_DM_USB | |
358 | + last_child = device_is_last_sibling(dev->dev); | |
359 | +#else | |
308 | 360 | last_child = (dev->parent != NULL); |
361 | +#endif | |
309 | 362 | if (last_child) { |
363 | +#ifndef CONFIG_DM_USB | |
310 | 364 | for (i = 0; i < dev->parent->maxchild; i++) { |
311 | 365 | /* search for children */ |
312 | 366 | if (dev->parent->children[i] == dev) { |
... | ... | @@ -322,6 +376,7 @@ |
322 | 376 | } /* while */ |
323 | 377 | } /* device found */ |
324 | 378 | } /* for all children of the parent */ |
379 | +#endif | |
325 | 380 | printf("\b+-"); |
326 | 381 | /* correct last child */ |
327 | 382 | if (last_child && index) |
... | ... | @@ -340,6 +395,26 @@ |
340 | 395 | if (strlen(dev->mf) || strlen(dev->prod) || strlen(dev->serial)) |
341 | 396 | printf(" %s %s %s %s\n", pre, dev->mf, dev->prod, dev->serial); |
342 | 397 | printf(" %s\n", pre); |
398 | +#ifdef CONFIG_DM_USB | |
399 | + struct udevice *child; | |
400 | + | |
401 | + for (device_find_first_child(dev->dev, &child); | |
402 | + child; | |
403 | + device_find_next_child(&child)) { | |
404 | + struct usb_device *udev; | |
405 | + | |
406 | + if (!device_active(child)) | |
407 | + continue; | |
408 | + | |
409 | + udev = dev_get_parentdata(child); | |
410 | + | |
411 | + /* Ignore emulators, we only want real devices */ | |
412 | + if (device_get_uclass_id(child) != UCLASS_USB_EMUL) { | |
413 | + usb_show_tree_graph(udev, pre); | |
414 | + pre[index] = 0; | |
415 | + } | |
416 | + } | |
417 | +#else | |
343 | 418 | if (dev->maxchild > 0) { |
344 | 419 | for (i = 0; i < dev->maxchild; i++) { |
345 | 420 | if (dev->children[i] != NULL) { |
... | ... | @@ -348,6 +423,7 @@ |
348 | 423 | } |
349 | 424 | } |
350 | 425 | } |
426 | +#endif | |
351 | 427 | } |
352 | 428 | |
353 | 429 | /* main routine for the tree command */ |
354 | 430 | |
... | ... | @@ -448,10 +524,13 @@ |
448 | 524 | if (usb_init() < 0) |
449 | 525 | return; |
450 | 526 | |
527 | + /* Driver model will probe the devices as they are found */ | |
528 | +#ifndef CONFIG_DM_USB | |
451 | 529 | #ifdef CONFIG_USB_STORAGE |
452 | 530 | /* try to recognize storage devices immediately */ |
453 | 531 | usb_stor_curr_dev = usb_stor_scan(1); |
454 | 532 | #endif |
533 | +#endif | |
455 | 534 | #ifdef CONFIG_USB_HOST_ETHER |
456 | 535 | /* try to recognize ethernet devices immediately */ |
457 | 536 | usb_ether_curr_dev = usb_host_eth_scan(1); |
... | ... | @@ -461,6 +540,43 @@ |
461 | 540 | #endif |
462 | 541 | } |
463 | 542 | |
543 | +#ifdef CONFIG_DM_USB | |
544 | +static void show_info(struct udevice *dev) | |
545 | +{ | |
546 | + struct udevice *child; | |
547 | + struct usb_device *udev; | |
548 | + | |
549 | + udev = dev_get_parentdata(dev); | |
550 | + usb_display_desc(udev); | |
551 | + usb_display_config(udev); | |
552 | + for (device_find_first_child(dev, &child); | |
553 | + child; | |
554 | + device_find_next_child(&child)) { | |
555 | + if (device_active(child)) | |
556 | + show_info(child); | |
557 | + } | |
558 | +} | |
559 | + | |
560 | +static int usb_device_info(void) | |
561 | +{ | |
562 | + struct udevice *bus; | |
563 | + | |
564 | + for (uclass_first_device(UCLASS_USB, &bus); | |
565 | + bus; | |
566 | + uclass_next_device(&bus)) { | |
567 | + struct udevice *hub; | |
568 | + | |
569 | + device_find_first_child(bus, &hub); | |
570 | + if (device_get_uclass_id(hub) == UCLASS_USB_HUB && | |
571 | + device_active(hub)) { | |
572 | + show_info(hub); | |
573 | + } | |
574 | + } | |
575 | + | |
576 | + return 0; | |
577 | +} | |
578 | +#endif | |
579 | + | |
464 | 580 | /****************************************************************************** |
465 | 581 | * usb command intepreter |
466 | 582 | */ |
... | ... | @@ -507,6 +623,23 @@ |
507 | 623 | } |
508 | 624 | if (strncmp(argv[1], "tree", 4) == 0) { |
509 | 625 | puts("USB device tree:\n"); |
626 | +#ifdef CONFIG_DM_USB | |
627 | + struct udevice *bus; | |
628 | + | |
629 | + for (uclass_first_device(UCLASS_USB, &bus); | |
630 | + bus; | |
631 | + uclass_next_device(&bus)) { | |
632 | + struct usb_device *udev; | |
633 | + struct udevice *hub; | |
634 | + | |
635 | + device_find_first_child(bus, &hub); | |
636 | + if (device_get_uclass_id(hub) == UCLASS_USB_HUB && | |
637 | + device_active(hub)) { | |
638 | + udev = dev_get_parentdata(hub); | |
639 | + usb_show_tree(udev); | |
640 | + } | |
641 | + } | |
642 | +#else | |
510 | 643 | for (i = 0; i < USB_MAX_DEVICE; i++) { |
511 | 644 | udev = usb_get_dev_index(i); |
512 | 645 | if (udev == NULL) |
513 | 646 | |
514 | 647 | |
... | ... | @@ -514,11 +647,15 @@ |
514 | 647 | if (udev->parent == NULL) |
515 | 648 | usb_show_tree(udev); |
516 | 649 | } |
650 | +#endif | |
517 | 651 | return 0; |
518 | 652 | } |
519 | 653 | if (strncmp(argv[1], "inf", 3) == 0) { |
520 | - int d; | |
521 | 654 | if (argc == 2) { |
655 | +#ifdef CONFIG_DM_USB | |
656 | + usb_device_info(); | |
657 | +#else | |
658 | + int d; | |
522 | 659 | for (d = 0; d < USB_MAX_DEVICE; d++) { |
523 | 660 | udev = usb_get_dev_index(d); |
524 | 661 | if (udev == NULL) |
525 | 662 | |
... | ... | @@ -526,8 +663,14 @@ |
526 | 663 | usb_display_desc(udev); |
527 | 664 | usb_display_config(udev); |
528 | 665 | } |
666 | +#endif | |
529 | 667 | return 0; |
530 | 668 | } else { |
669 | + /* | |
670 | + * With driver model this isn't right since we can | |
671 | + * have multiple controllers and the device numbering | |
672 | + * starts at 1 on each bus. | |
673 | + */ | |
531 | 674 | i = simple_strtoul(argv[2], NULL, 10); |
532 | 675 | printf("config for device %d\n", i); |
533 | 676 | udev = usb_find_device(i); |