Commit 211aaf309cde193918f9a19b0b010acebfd80a82
Exists in
smarc_8mq_lf_v2020.04
and in
20 other branches
Merge git://git.denx.de/u-boot-usb
Showing 96 changed files Side-by-side Diff
- Documentation/devicetree/bindings/phy/no-op.txt
- arch/arm/include/asm/ehci-omap.h
- arch/x86/dts/minnowmax.dts
- cmd/usb.c
- common/usb_hub.c
- configs/minnowmax_defconfig
- drivers/clk/clk-uclass.c
- drivers/core/of_access.c
- drivers/core/ofnode.c
- drivers/dfu/dfu.c
- drivers/dfu/dfu_mmc.c
- drivers/dfu/dfu_nand.c
- drivers/dfu/dfu_ram.c
- drivers/dfu/dfu_sf.c
- drivers/phy/Kconfig
- drivers/phy/Makefile
- drivers/phy/nop-phy.c
- drivers/phy/phy-uclass.c
- drivers/reset/reset-uclass.c
- drivers/usb/emul/sandbox_hub.c
- drivers/usb/gadget/f_thor.c
- drivers/usb/host/Kconfig
- drivers/usb/host/ehci-generic.c
- drivers/usb/host/ehci-hcd.c
- drivers/usb/host/ehci.h
- drivers/usb/host/ohci-generic.c
- drivers/usb/host/usb-uclass.c
- drivers/usb/host/xhci-dwc3.c
- drivers/usb/host/xhci-mem.c
- drivers/usb/host/xhci-pci.c
- drivers/usb/host/xhci-ring.c
- drivers/usb/host/xhci.c
- drivers/usb/host/xhci.h
- include/clk.h
- include/configs/MPC8572DS.h
- include/configs/am43xx_evm.h
- include/configs/am57xx_evm.h
- include/configs/cl-som-am57x.h
- include/configs/cm_t43.h
- include/configs/cm_t54.h
- include/configs/corvus.h
- include/configs/dra7xx_evm.h
- include/configs/ds414.h
- include/configs/duovero.h
- include/configs/exynos5-common.h
- include/configs/ls1012afrdm.h
- include/configs/ls1012aqds.h
- include/configs/ls1012ardb.h
- include/configs/ls1021aiot.h
- include/configs/ls1021aqds.h
- include/configs/ls1021atwr.h
- include/configs/ls1043aqds.h
- include/configs/ls1043ardb.h
- include/configs/ls1046aqds.h
- include/configs/ls1046ardb.h
- include/configs/ls2080aqds.h
- include/configs/ls2080ardb.h
- include/configs/ma5d4evk.h
- include/configs/mcx.h
- include/configs/minnowmax.h
- include/configs/mvebu_armada-37xx.h
- include/configs/mvebu_armada-8k.h
- include/configs/mx35pdk.h
- include/configs/odroid.h
- include/configs/omap3_beagle.h
- include/configs/omap3_overo.h
- include/configs/omap4_panda.h
- include/configs/omap5_uevm.h
- include/configs/picosam9g45.h
- include/configs/poplar.h
- include/configs/rk3328_common.h
- include/configs/rk3399_common.h
- include/configs/sama5d2_ptc.h
- include/configs/snapper9g45.h
- include/configs/sunxi-common.h
- include/configs/tam3517-common.h
- include/configs/tao3530.h
- include/configs/tegra114-common.h
- include/configs/tegra124-common.h
- include/configs/tegra20-common.h
- include/configs/tegra210-common.h
- include/configs/tegra30-common.h
- include/configs/ti_armv7_keystone2.h
- include/configs/uniphier.h
- include/configs/vinco.h
- include/configs/x86-common.h
- include/configs/xilinx_zynqmp.h
- include/dfu.h
- include/dm/of_access.h
- include/dm/ofnode.h
- include/dm/read.h
- include/generic-phy.h
- include/reset.h
- include/usb.h
- include/usb_defs.h
- scripts/config_whitelist.txt
Documentation/devicetree/bindings/phy/no-op.txt
| 1 | +NOP PHY driver | |
| 2 | + | |
| 3 | +This driver is used to stub PHY operations in a driver (USB, SATA). | |
| 4 | +This is useful when the 'client' driver (USB, SATA, ...) uses the PHY framework | |
| 5 | +and there is no actual PHY harwdare to drive. | |
| 6 | + | |
| 7 | +Required properties: | |
| 8 | +- compatible : must contain "nop-phy" | |
| 9 | +- #phy-cells : must contain <0> | |
| 10 | + | |
| 11 | +Example: | |
| 12 | + | |
| 13 | +nop_phy { | |
| 14 | + compatible = "nop-phy"; | |
| 15 | + #phy-cells = <0>; | |
| 16 | +}; |
arch/arm/include/asm/ehci-omap.h
| ... | ... | @@ -19,11 +19,7 @@ |
| 19 | 19 | OMAP_EHCI_PORT_MODE_HSIC, |
| 20 | 20 | }; |
| 21 | 21 | |
| 22 | -#ifdef CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS | |
| 23 | -#define OMAP_HS_USB_PORTS CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS | |
| 24 | -#else | |
| 25 | 22 | #define OMAP_HS_USB_PORTS 3 |
| 26 | -#endif | |
| 27 | 23 | |
| 28 | 24 | #define is_ehci_phy_mode(x) ((x) == OMAP_EHCI_PORT_MODE_PHY) |
| 29 | 25 | #define is_ehci_tll_mode(x) ((x) == OMAP_EHCI_PORT_MODE_TLL) |
arch/x86/dts/minnowmax.dts
cmd/usb.c
| ... | ... | @@ -150,6 +150,8 @@ |
| 150 | 150 | |
| 151 | 151 | static void usb_display_desc(struct usb_device *dev) |
| 152 | 152 | { |
| 153 | + uint packet_size = dev->descriptor.bMaxPacketSize0; | |
| 154 | + | |
| 153 | 155 | if (dev->descriptor.bDescriptorType == USB_DT_DEVICE) { |
| 154 | 156 | printf("%d: %s, USB Revision %x.%x\n", dev->devnum, |
| 155 | 157 | usb_get_class_desc(dev->config.if_desc[0].desc.bInterfaceClass), |
| 156 | 158 | |
| ... | ... | @@ -171,9 +173,10 @@ |
| 171 | 173 | usb_get_class_desc( |
| 172 | 174 | dev->config.if_desc[0].desc.bInterfaceClass)); |
| 173 | 175 | } |
| 176 | + if (dev->descriptor.bcdUSB >= cpu_to_le16(0x0300)) | |
| 177 | + packet_size = 1 << packet_size; | |
| 174 | 178 | printf(" - PacketSize: %d Configurations: %d\n", |
| 175 | - dev->descriptor.bMaxPacketSize0, | |
| 176 | - dev->descriptor.bNumConfigurations); | |
| 179 | + packet_size, dev->descriptor.bNumConfigurations); | |
| 177 | 180 | printf(" - Vendor: 0x%04x Product 0x%04x Version %d.%d\n", |
| 178 | 181 | dev->descriptor.idVendor, dev->descriptor.idProduct, |
| 179 | 182 | (dev->descriptor.bcdDevice>>8) & 0xff, |
common/usb_hub.c
| ... | ... | @@ -55,9 +55,6 @@ |
| 55 | 55 | struct list_head list; |
| 56 | 56 | }; |
| 57 | 57 | |
| 58 | -/* TODO(sjg@chromium.org): Remove this when CONFIG_DM_USB is defined */ | |
| 59 | -static struct usb_hub_device hub_dev[USB_MAX_HUB]; | |
| 60 | -static int usb_hub_index; | |
| 61 | 58 | static LIST_HEAD(usb_scan_list); |
| 62 | 59 | |
| 63 | 60 | __weak void usb_hub_reset_devices(int port) |
| 64 | 61 | |
| 65 | 62 | |
| ... | ... | @@ -65,11 +62,41 @@ |
| 65 | 62 | return; |
| 66 | 63 | } |
| 67 | 64 | |
| 65 | +static inline bool usb_hub_is_superspeed(struct usb_device *hdev) | |
| 66 | +{ | |
| 67 | + return hdev->descriptor.bDeviceProtocol == 3; | |
| 68 | +} | |
| 69 | + | |
| 70 | +#ifdef CONFIG_DM_USB | |
| 71 | +bool usb_hub_is_root_hub(struct udevice *hub) | |
| 72 | +{ | |
| 73 | + if (device_get_uclass_id(hub->parent) != UCLASS_USB_HUB) | |
| 74 | + return true; | |
| 75 | + | |
| 76 | + return false; | |
| 77 | +} | |
| 78 | + | |
| 79 | +static int usb_set_hub_depth(struct usb_device *dev, int depth) | |
| 80 | +{ | |
| 81 | + if (depth < 0 || depth > 4) | |
| 82 | + return -EINVAL; | |
| 83 | + | |
| 84 | + return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | |
| 85 | + USB_REQ_SET_HUB_DEPTH, USB_DIR_OUT | USB_RT_HUB, | |
| 86 | + depth, 0, NULL, 0, USB_CNTL_TIMEOUT); | |
| 87 | +} | |
| 88 | +#endif | |
| 89 | + | |
| 68 | 90 | static int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size) |
| 69 | 91 | { |
| 92 | + unsigned short dtype = USB_DT_HUB; | |
| 93 | + | |
| 94 | + if (usb_hub_is_superspeed(dev)) | |
| 95 | + dtype = USB_DT_SS_HUB; | |
| 96 | + | |
| 70 | 97 | return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), |
| 71 | 98 | USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB, |
| 72 | - USB_DT_HUB << 8, 0, data, size, USB_CNTL_TIMEOUT); | |
| 99 | + dtype << 8, 0, data, size, USB_CNTL_TIMEOUT); | |
| 73 | 100 | } |
| 74 | 101 | |
| 75 | 102 | static int usb_clear_port_feature(struct usb_device *dev, int port, int feature) |
| 76 | 103 | |
| ... | ... | @@ -95,9 +122,40 @@ |
| 95 | 122 | |
| 96 | 123 | int usb_get_port_status(struct usb_device *dev, int port, void *data) |
| 97 | 124 | { |
| 98 | - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | |
| 125 | + int ret; | |
| 126 | + | |
| 127 | + ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | |
| 99 | 128 | USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port, |
| 100 | - data, sizeof(struct usb_hub_status), USB_CNTL_TIMEOUT); | |
| 129 | + data, sizeof(struct usb_port_status), USB_CNTL_TIMEOUT); | |
| 130 | + | |
| 131 | +#ifdef CONFIG_DM_USB | |
| 132 | + if (ret < 0) | |
| 133 | + return ret; | |
| 134 | + | |
| 135 | + /* | |
| 136 | + * Translate the USB 3.0 hub port status field into the old version | |
| 137 | + * that U-Boot understands. Do this only when the hub is not root hub. | |
| 138 | + * For root hub, the port status field has already been translated | |
| 139 | + * in the host controller driver (see xhci_submit_root() in xhci.c). | |
| 140 | + * | |
| 141 | + * Note: this only supports driver model. | |
| 142 | + */ | |
| 143 | + | |
| 144 | + if (!usb_hub_is_root_hub(dev->dev) && usb_hub_is_superspeed(dev)) { | |
| 145 | + struct usb_port_status *status = (struct usb_port_status *)data; | |
| 146 | + u16 tmp = (status->wPortStatus) & USB_SS_PORT_STAT_MASK; | |
| 147 | + | |
| 148 | + if (status->wPortStatus & USB_SS_PORT_STAT_POWER) | |
| 149 | + tmp |= USB_PORT_STAT_POWER; | |
| 150 | + if ((status->wPortStatus & USB_SS_PORT_STAT_SPEED) == | |
| 151 | + USB_SS_PORT_STAT_SPEED_5GBPS) | |
| 152 | + tmp |= USB_PORT_STAT_SUPER_SPEED; | |
| 153 | + | |
| 154 | + status->wPortStatus = tmp; | |
| 155 | + } | |
| 156 | +#endif | |
| 157 | + | |
| 158 | + return ret; | |
| 101 | 159 | } |
| 102 | 160 | |
| 103 | 161 | |
| ... | ... | @@ -154,6 +212,10 @@ |
| 154 | 212 | max(100, (int)pgood_delay) + 1000); |
| 155 | 213 | } |
| 156 | 214 | |
| 215 | +#ifndef CONFIG_DM_USB | |
| 216 | +static struct usb_hub_device hub_dev[USB_MAX_HUB]; | |
| 217 | +static int usb_hub_index; | |
| 218 | + | |
| 157 | 219 | void usb_hub_reset(void) |
| 158 | 220 | { |
| 159 | 221 | usb_hub_index = 0; |
| ... | ... | @@ -170,6 +232,7 @@ |
| 170 | 232 | printf("ERROR: USB_MAX_HUB (%d) reached\n", USB_MAX_HUB); |
| 171 | 233 | return NULL; |
| 172 | 234 | } |
| 235 | +#endif | |
| 173 | 236 | |
| 174 | 237 | #define MAX_TRIES 5 |
| 175 | 238 | |
| ... | ... | @@ -195,8 +258,18 @@ |
| 195 | 258 | return speed_str; |
| 196 | 259 | } |
| 197 | 260 | |
| 198 | -int legacy_hub_port_reset(struct usb_device *dev, int port, | |
| 199 | - unsigned short *portstat) | |
| 261 | +/** | |
| 262 | + * usb_hub_port_reset() - reset a port given its usb_device pointer | |
| 263 | + * | |
| 264 | + * Reset a hub port and see if a device is present on that port, providing | |
| 265 | + * sufficient time for it to show itself. The port status is returned. | |
| 266 | + * | |
| 267 | + * @dev: USB device to reset | |
| 268 | + * @port: Port number to reset (note ports are numbered from 0 here) | |
| 269 | + * @portstat: Returns port status | |
| 270 | + */ | |
| 271 | +static int usb_hub_port_reset(struct usb_device *dev, int port, | |
| 272 | + unsigned short *portstat) | |
| 200 | 273 | { |
| 201 | 274 | int err, tries; |
| 202 | 275 | ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1); |
| ... | ... | @@ -269,15 +342,6 @@ |
| 269 | 342 | return 0; |
| 270 | 343 | } |
| 271 | 344 | |
| 272 | -#ifdef CONFIG_DM_USB | |
| 273 | -int hub_port_reset(struct udevice *dev, int port, unsigned short *portstat) | |
| 274 | -{ | |
| 275 | - struct usb_device *udev = dev_get_parent_priv(dev); | |
| 276 | - | |
| 277 | - return legacy_hub_port_reset(udev, port, portstat); | |
| 278 | -} | |
| 279 | -#endif | |
| 280 | - | |
| 281 | 345 | int usb_hub_port_connect_change(struct usb_device *dev, int port) |
| 282 | 346 | { |
| 283 | 347 | ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1); |
| ... | ... | @@ -311,7 +375,7 @@ |
| 311 | 375 | } |
| 312 | 376 | |
| 313 | 377 | /* Reset the port */ |
| 314 | - ret = legacy_hub_port_reset(dev, port, &portstatus); | |
| 378 | + ret = usb_hub_port_reset(dev, port, &portstatus); | |
| 315 | 379 | if (ret < 0) { |
| 316 | 380 | if (ret != -ENXIO) |
| 317 | 381 | printf("cannot reset port %i!?\n", port + 1); |
| ... | ... | @@ -405,8 +469,15 @@ |
| 405 | 469 | portchange = le16_to_cpu(portsts->wPortChange); |
| 406 | 470 | debug("Port %d Status %X Change %X\n", i + 1, portstatus, portchange); |
| 407 | 471 | |
| 408 | - /* No connection change happened, wait a bit more. */ | |
| 409 | - if (!(portchange & USB_PORT_STAT_C_CONNECTION)) { | |
| 472 | + /* | |
| 473 | + * No connection change happened, wait a bit more. | |
| 474 | + * | |
| 475 | + * For some situation, the hub reports no connection change but a | |
| 476 | + * device is connected to the port (eg: CCS bit is set but CSC is not | |
| 477 | + * in the PORTSC register of a root hub), ignore such case. | |
| 478 | + */ | |
| 479 | + if (!(portchange & USB_PORT_STAT_C_CONNECTION) && | |
| 480 | + !(portstatus & USB_PORT_STAT_CONNECTION)) { | |
| 410 | 481 | if (get_timer(0) >= hub->connect_timeout) { |
| 411 | 482 | debug("devnum=%d port=%d: timeout\n", |
| 412 | 483 | dev->devnum, i + 1); |
| ... | ... | @@ -418,10 +489,6 @@ |
| 418 | 489 | return 0; |
| 419 | 490 | } |
| 420 | 491 | |
| 421 | - /* Test if the connection came up, and if not exit */ | |
| 422 | - if (!(portstatus & USB_PORT_STAT_CONNECTION)) | |
| 423 | - return 0; | |
| 424 | - | |
| 425 | 492 | /* A new USB device is ready at this point */ |
| 426 | 493 | debug("devnum=%d port=%d: USB dev found\n", dev->devnum, i + 1); |
| 427 | 494 | |
| ... | ... | @@ -530,6 +597,20 @@ |
| 530 | 597 | return ret; |
| 531 | 598 | } |
| 532 | 599 | |
| 600 | +static struct usb_hub_device *usb_get_hub_device(struct usb_device *dev) | |
| 601 | +{ | |
| 602 | + struct usb_hub_device *hub; | |
| 603 | + | |
| 604 | +#ifndef CONFIG_DM_USB | |
| 605 | + /* "allocate" Hub device */ | |
| 606 | + hub = usb_hub_allocate(); | |
| 607 | +#else | |
| 608 | + hub = dev_get_uclass_priv(dev->dev); | |
| 609 | +#endif | |
| 610 | + | |
| 611 | + return hub; | |
| 612 | +} | |
| 613 | + | |
| 533 | 614 | static int usb_hub_configure(struct usb_device *dev) |
| 534 | 615 | { |
| 535 | 616 | int i, length; |
| 536 | 617 | |
| ... | ... | @@ -541,11 +622,11 @@ |
| 541 | 622 | __maybe_unused struct usb_hub_status *hubsts; |
| 542 | 623 | int ret; |
| 543 | 624 | |
| 544 | - /* "allocate" Hub device */ | |
| 545 | - hub = usb_hub_allocate(); | |
| 625 | + hub = usb_get_hub_device(dev); | |
| 546 | 626 | if (hub == NULL) |
| 547 | 627 | return -ENOMEM; |
| 548 | 628 | hub->pusb_dev = dev; |
| 629 | + | |
| 549 | 630 | /* Get the the hub descriptor */ |
| 550 | 631 | ret = usb_get_hub_descriptor(dev, buffer, 4); |
| 551 | 632 | if (ret < 0) { |
| 552 | 633 | |
| 553 | 634 | |
| 554 | 635 | |
| ... | ... | @@ -570,17 +651,19 @@ |
| 570 | 651 | &descriptor->wHubCharacteristics)), |
| 571 | 652 | &hub->desc.wHubCharacteristics); |
| 572 | 653 | /* set the bitmap */ |
| 573 | - bitmap = (unsigned char *)&hub->desc.DeviceRemovable[0]; | |
| 654 | + bitmap = (unsigned char *)&hub->desc.u.hs.DeviceRemovable[0]; | |
| 574 | 655 | /* devices not removable by default */ |
| 575 | 656 | memset(bitmap, 0xff, (USB_MAXCHILDREN+1+7)/8); |
| 576 | - bitmap = (unsigned char *)&hub->desc.PortPowerCtrlMask[0]; | |
| 657 | + bitmap = (unsigned char *)&hub->desc.u.hs.PortPowerCtrlMask[0]; | |
| 577 | 658 | memset(bitmap, 0xff, (USB_MAXCHILDREN+1+7)/8); /* PowerMask = 1B */ |
| 578 | 659 | |
| 579 | 660 | for (i = 0; i < ((hub->desc.bNbrPorts + 1 + 7)/8); i++) |
| 580 | - hub->desc.DeviceRemovable[i] = descriptor->DeviceRemovable[i]; | |
| 661 | + hub->desc.u.hs.DeviceRemovable[i] = | |
| 662 | + descriptor->u.hs.DeviceRemovable[i]; | |
| 581 | 663 | |
| 582 | 664 | for (i = 0; i < ((hub->desc.bNbrPorts + 1 + 7)/8); i++) |
| 583 | - hub->desc.PortPowerCtrlMask[i] = descriptor->PortPowerCtrlMask[i]; | |
| 665 | + hub->desc.u.hs.PortPowerCtrlMask[i] = | |
| 666 | + descriptor->u.hs.PortPowerCtrlMask[i]; | |
| 584 | 667 | |
| 585 | 668 | dev->maxchild = descriptor->bNbrPorts; |
| 586 | 669 | debug("%d ports detected\n", dev->maxchild); |
| ... | ... | @@ -617,6 +700,56 @@ |
| 617 | 700 | break; |
| 618 | 701 | } |
| 619 | 702 | |
| 703 | + switch (dev->descriptor.bDeviceProtocol) { | |
| 704 | + case USB_HUB_PR_FS: | |
| 705 | + break; | |
| 706 | + case USB_HUB_PR_HS_SINGLE_TT: | |
| 707 | + debug("Single TT\n"); | |
| 708 | + break; | |
| 709 | + case USB_HUB_PR_HS_MULTI_TT: | |
| 710 | + ret = usb_set_interface(dev, 0, 1); | |
| 711 | + if (ret == 0) { | |
| 712 | + debug("TT per port\n"); | |
| 713 | + hub->tt.multi = true; | |
| 714 | + } else { | |
| 715 | + debug("Using single TT (err %d)\n", ret); | |
| 716 | + } | |
| 717 | + break; | |
| 718 | + case USB_HUB_PR_SS: | |
| 719 | + /* USB 3.0 hubs don't have a TT */ | |
| 720 | + break; | |
| 721 | + default: | |
| 722 | + debug("Unrecognized hub protocol %d\n", | |
| 723 | + dev->descriptor.bDeviceProtocol); | |
| 724 | + break; | |
| 725 | + } | |
| 726 | + | |
| 727 | + /* Note 8 FS bit times == (8 bits / 12000000 bps) ~= 666ns */ | |
| 728 | + switch (hubCharacteristics & HUB_CHAR_TTTT) { | |
| 729 | + case HUB_TTTT_8_BITS: | |
| 730 | + if (dev->descriptor.bDeviceProtocol != 0) { | |
| 731 | + hub->tt.think_time = 666; | |
| 732 | + debug("TT requires at most %d FS bit times (%d ns)\n", | |
| 733 | + 8, hub->tt.think_time); | |
| 734 | + } | |
| 735 | + break; | |
| 736 | + case HUB_TTTT_16_BITS: | |
| 737 | + hub->tt.think_time = 666 * 2; | |
| 738 | + debug("TT requires at most %d FS bit times (%d ns)\n", | |
| 739 | + 16, hub->tt.think_time); | |
| 740 | + break; | |
| 741 | + case HUB_TTTT_24_BITS: | |
| 742 | + hub->tt.think_time = 666 * 3; | |
| 743 | + debug("TT requires at most %d FS bit times (%d ns)\n", | |
| 744 | + 24, hub->tt.think_time); | |
| 745 | + break; | |
| 746 | + case HUB_TTTT_32_BITS: | |
| 747 | + hub->tt.think_time = 666 * 4; | |
| 748 | + debug("TT requires at most %d FS bit times (%d ns)\n", | |
| 749 | + 32, hub->tt.think_time); | |
| 750 | + break; | |
| 751 | + } | |
| 752 | + | |
| 620 | 753 | debug("power on to power good time: %dms\n", |
| 621 | 754 | descriptor->bPwrOn2PwrGood * 2); |
| 622 | 755 | debug("hub controller current requirement: %dmA\n", |
| ... | ... | @@ -624,7 +757,7 @@ |
| 624 | 757 | |
| 625 | 758 | for (i = 0; i < dev->maxchild; i++) |
| 626 | 759 | debug("port %d is%s removable\n", i + 1, |
| 627 | - hub->desc.DeviceRemovable[(i + 1) / 8] & \ | |
| 760 | + hub->desc.u.hs.DeviceRemovable[(i + 1) / 8] & \ | |
| 628 | 761 | (1 << ((i + 1) % 8)) ? " not" : ""); |
| 629 | 762 | |
| 630 | 763 | if (sizeof(struct usb_hub_status) > USB_BUFSIZ) { |
| ... | ... | @@ -653,6 +786,59 @@ |
| 653 | 786 | debug("%sover-current condition exists\n", |
| 654 | 787 | (le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_OVERCURRENT) ? \ |
| 655 | 788 | "" : "no "); |
| 789 | + | |
| 790 | +#ifdef CONFIG_DM_USB | |
| 791 | + /* | |
| 792 | + * Update USB host controller's internal representation of this hub | |
| 793 | + * after the hub descriptor is fetched. | |
| 794 | + */ | |
| 795 | + ret = usb_update_hub_device(dev); | |
| 796 | + if (ret < 0 && ret != -ENOSYS) { | |
| 797 | + debug("%s: failed to update hub device for HCD (%x)\n", | |
| 798 | + __func__, ret); | |
| 799 | + return ret; | |
| 800 | + } | |
| 801 | + | |
| 802 | + /* | |
| 803 | + * A maximum of seven tiers are allowed in a USB topology, and the | |
| 804 | + * root hub occupies the first tier. The last tier ends with a normal | |
| 805 | + * USB device. USB 3.0 hubs use a 20-bit field called 'route string' | |
| 806 | + * to route packets to the designated downstream port. The hub uses a | |
| 807 | + * hub depth value multiplied by four as an offset into the 'route | |
| 808 | + * string' to locate the bits it uses to determine the downstream | |
| 809 | + * port number. | |
| 810 | + */ | |
| 811 | + if (usb_hub_is_root_hub(dev->dev)) { | |
| 812 | + hub->hub_depth = -1; | |
| 813 | + } else { | |
| 814 | + struct udevice *hdev; | |
| 815 | + int depth = 0; | |
| 816 | + | |
| 817 | + hdev = dev->dev->parent; | |
| 818 | + while (!usb_hub_is_root_hub(hdev)) { | |
| 819 | + depth++; | |
| 820 | + hdev = hdev->parent; | |
| 821 | + } | |
| 822 | + | |
| 823 | + hub->hub_depth = depth; | |
| 824 | + | |
| 825 | + if (usb_hub_is_superspeed(dev)) { | |
| 826 | + debug("set hub (%p) depth to %d\n", dev, depth); | |
| 827 | + /* | |
| 828 | + * This request sets the value that the hub uses to | |
| 829 | + * determine the index into the 'route string index' | |
| 830 | + * for this hub. | |
| 831 | + */ | |
| 832 | + ret = usb_set_hub_depth(dev, depth); | |
| 833 | + if (ret < 0) { | |
| 834 | + debug("%s: failed to set hub depth (%lX)\n", | |
| 835 | + __func__, dev->status); | |
| 836 | + return ret; | |
| 837 | + } | |
| 838 | + } | |
| 839 | + } | |
| 840 | +#endif | |
| 841 | + | |
| 656 | 842 | usb_hub_power_on(hub); |
| 657 | 843 | |
| 658 | 844 | /* |
| ... | ... | @@ -777,6 +963,7 @@ |
| 777 | 963 | .child_pre_probe = usb_child_pre_probe, |
| 778 | 964 | .per_child_auto_alloc_size = sizeof(struct usb_device), |
| 779 | 965 | .per_child_platdata_auto_alloc_size = sizeof(struct usb_dev_platdata), |
| 966 | + .per_device_auto_alloc_size = sizeof(struct usb_hub_device), | |
| 780 | 967 | }; |
| 781 | 968 | |
| 782 | 969 | static const struct usb_device_id hub_id_table[] = { |
configs/minnowmax_defconfig
drivers/clk/clk-uclass.c
| ... | ... | @@ -65,6 +65,8 @@ |
| 65 | 65 | debug("%s(dev=%p, index=%d, clk=%p)\n", __func__, dev, index, clk); |
| 66 | 66 | |
| 67 | 67 | assert(clk); |
| 68 | + clk->dev = NULL; | |
| 69 | + | |
| 68 | 70 | ret = dev_read_phandle_with_args(dev, "clocks", "#clock-cells", 0, |
| 69 | 71 | index, &args); |
| 70 | 72 | if (ret) { |
| ... | ... | @@ -102,6 +104,7 @@ |
| 102 | 104 | int index; |
| 103 | 105 | |
| 104 | 106 | debug("%s(dev=%p, name=%s, clk=%p)\n", __func__, dev, name, clk); |
| 107 | + clk->dev = NULL; | |
| 105 | 108 | |
| 106 | 109 | index = dev_read_stringlist_search(dev, "clock-names", name); |
| 107 | 110 | if (index < 0) { |
| ... | ... | @@ -111,6 +114,30 @@ |
| 111 | 114 | |
| 112 | 115 | return clk_get_by_index(dev, index, clk); |
| 113 | 116 | } |
| 117 | + | |
| 118 | +int clk_release_all(struct clk *clk, int count) | |
| 119 | +{ | |
| 120 | + int i, ret; | |
| 121 | + | |
| 122 | + for (i = 0; i < count; i++) { | |
| 123 | + debug("%s(clk[%d]=%p)\n", __func__, i, &clk[i]); | |
| 124 | + | |
| 125 | + /* check if clock has been previously requested */ | |
| 126 | + if (!clk[i].dev) | |
| 127 | + continue; | |
| 128 | + | |
| 129 | + ret = clk_disable(&clk[i]); | |
| 130 | + if (ret && ret != -ENOSYS) | |
| 131 | + return ret; | |
| 132 | + | |
| 133 | + ret = clk_free(&clk[i]); | |
| 134 | + if (ret && ret != -ENOSYS) | |
| 135 | + return ret; | |
| 136 | + } | |
| 137 | + | |
| 138 | + return 0; | |
| 139 | +} | |
| 140 | + | |
| 114 | 141 | #endif /* OF_CONTROL */ |
| 115 | 142 | |
| 116 | 143 | int clk_request(struct udevice *dev, struct clk *clk) |
drivers/core/of_access.c
| ... | ... | @@ -665,6 +665,13 @@ |
| 665 | 665 | index, out_args); |
| 666 | 666 | } |
| 667 | 667 | |
| 668 | +int of_count_phandle_with_args(const struct device_node *np, | |
| 669 | + const char *list_name, const char *cells_name) | |
| 670 | +{ | |
| 671 | + return __of_parse_phandle_with_args(np, list_name, cells_name, 0, | |
| 672 | + -1, NULL); | |
| 673 | +} | |
| 674 | + | |
| 668 | 675 | static void of_alias_add(struct alias_prop *ap, struct device_node *np, |
| 669 | 676 | int id, const char *stem, int stem_len) |
| 670 | 677 | { |
drivers/core/ofnode.c
| ... | ... | @@ -315,6 +315,18 @@ |
| 315 | 315 | return 0; |
| 316 | 316 | } |
| 317 | 317 | |
| 318 | +int ofnode_count_phandle_with_args(ofnode node, const char *list_name, | |
| 319 | + const char *cells_name) | |
| 320 | +{ | |
| 321 | + if (ofnode_is_np(node)) | |
| 322 | + return of_count_phandle_with_args(ofnode_to_np(node), | |
| 323 | + list_name, cells_name); | |
| 324 | + else | |
| 325 | + return fdtdec_parse_phandle_with_args(gd->fdt_blob, | |
| 326 | + ofnode_to_offset(node), list_name, cells_name, | |
| 327 | + 0, -1, NULL); | |
| 328 | +} | |
| 329 | + | |
| 318 | 330 | ofnode ofnode_path(const char *path) |
| 319 | 331 | { |
| 320 | 332 | if (of_live_active()) |
drivers/dfu/dfu.c
| ... | ... | @@ -165,18 +165,48 @@ |
| 165 | 165 | return ret; |
| 166 | 166 | } |
| 167 | 167 | |
| 168 | -void dfu_write_transaction_cleanup(struct dfu_entity *dfu) | |
| 168 | +void dfu_transaction_cleanup(struct dfu_entity *dfu) | |
| 169 | 169 | { |
| 170 | 170 | /* clear everything */ |
| 171 | 171 | dfu->crc = 0; |
| 172 | 172 | dfu->offset = 0; |
| 173 | 173 | dfu->i_blk_seq_num = 0; |
| 174 | - dfu->i_buf_start = dfu_buf; | |
| 175 | - dfu->i_buf_end = dfu_buf; | |
| 174 | + dfu->i_buf_start = dfu_get_buf(dfu); | |
| 175 | + dfu->i_buf_end = dfu->i_buf_start; | |
| 176 | 176 | dfu->i_buf = dfu->i_buf_start; |
| 177 | + dfu->r_left = 0; | |
| 178 | + dfu->b_left = 0; | |
| 179 | + dfu->bad_skip = 0; | |
| 180 | + | |
| 177 | 181 | dfu->inited = 0; |
| 178 | 182 | } |
| 179 | 183 | |
| 184 | +int dfu_transaction_initiate(struct dfu_entity *dfu, bool read) | |
| 185 | +{ | |
| 186 | + int ret = 0; | |
| 187 | + | |
| 188 | + if (dfu->inited) | |
| 189 | + return 0; | |
| 190 | + | |
| 191 | + dfu_transaction_cleanup(dfu); | |
| 192 | + | |
| 193 | + if (dfu->i_buf_start == NULL) | |
| 194 | + return -ENOMEM; | |
| 195 | + | |
| 196 | + dfu->i_buf_end = dfu->i_buf_start + dfu_get_buf_size(); | |
| 197 | + | |
| 198 | + if (read) { | |
| 199 | + ret = dfu->get_medium_size(dfu, &dfu->r_left); | |
| 200 | + if (ret < 0) | |
| 201 | + return ret; | |
| 202 | + debug("%s: %s %lld [B]\n", __func__, dfu->name, dfu->r_left); | |
| 203 | + } | |
| 204 | + | |
| 205 | + dfu->inited = 1; | |
| 206 | + | |
| 207 | + return 0; | |
| 208 | +} | |
| 209 | + | |
| 180 | 210 | int dfu_flush(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) |
| 181 | 211 | { |
| 182 | 212 | int ret = 0; |
| ... | ... | @@ -192,7 +222,7 @@ |
| 192 | 222 | printf("\nDFU complete %s: 0x%08x\n", dfu_hash_algo->name, |
| 193 | 223 | dfu->crc); |
| 194 | 224 | |
| 195 | - dfu_write_transaction_cleanup(dfu); | |
| 225 | + dfu_transaction_cleanup(dfu); | |
| 196 | 226 | |
| 197 | 227 | return ret; |
| 198 | 228 | } |
| 199 | 229 | |
| 200 | 230 | |
| ... | ... | @@ -205,25 +235,14 @@ |
| 205 | 235 | __func__, dfu->name, buf, size, blk_seq_num, dfu->offset, |
| 206 | 236 | (unsigned long)(dfu->i_buf - dfu->i_buf_start)); |
| 207 | 237 | |
| 208 | - if (!dfu->inited) { | |
| 209 | - /* initial state */ | |
| 210 | - dfu->crc = 0; | |
| 211 | - dfu->offset = 0; | |
| 212 | - dfu->bad_skip = 0; | |
| 213 | - dfu->i_blk_seq_num = 0; | |
| 214 | - dfu->i_buf_start = dfu_get_buf(dfu); | |
| 215 | - if (dfu->i_buf_start == NULL) | |
| 216 | - return -ENOMEM; | |
| 217 | - dfu->i_buf_end = dfu_get_buf(dfu) + dfu_buf_size; | |
| 218 | - dfu->i_buf = dfu->i_buf_start; | |
| 238 | + ret = dfu_transaction_initiate(dfu, false); | |
| 239 | + if (ret < 0) | |
| 240 | + return ret; | |
| 219 | 241 | |
| 220 | - dfu->inited = 1; | |
| 221 | - } | |
| 222 | - | |
| 223 | 242 | if (dfu->i_blk_seq_num != blk_seq_num) { |
| 224 | 243 | printf("%s: Wrong sequence number! [%d] [%d]\n", |
| 225 | 244 | __func__, dfu->i_blk_seq_num, blk_seq_num); |
| 226 | - dfu_write_transaction_cleanup(dfu); | |
| 245 | + dfu_transaction_cleanup(dfu); | |
| 227 | 246 | return -1; |
| 228 | 247 | } |
| 229 | 248 | |
| ... | ... | @@ -247,7 +266,7 @@ |
| 247 | 266 | if ((dfu->i_buf + size) > dfu->i_buf_end) { |
| 248 | 267 | ret = dfu_write_buffer_drain(dfu); |
| 249 | 268 | if (ret) { |
| 250 | - dfu_write_transaction_cleanup(dfu); | |
| 269 | + dfu_transaction_cleanup(dfu); | |
| 251 | 270 | return ret; |
| 252 | 271 | } |
| 253 | 272 | } |
| ... | ... | @@ -256,7 +275,7 @@ |
| 256 | 275 | if ((dfu->i_buf + size) > dfu->i_buf_end) { |
| 257 | 276 | error("Buffer overflow! (0x%p + 0x%x > 0x%p)\n", dfu->i_buf, |
| 258 | 277 | size, dfu->i_buf_end); |
| 259 | - dfu_write_transaction_cleanup(dfu); | |
| 278 | + dfu_transaction_cleanup(dfu); | |
| 260 | 279 | return -1; |
| 261 | 280 | } |
| 262 | 281 | |
| ... | ... | @@ -267,7 +286,7 @@ |
| 267 | 286 | if (size == 0 || (dfu->i_buf + size) > dfu->i_buf_end) { |
| 268 | 287 | ret = dfu_write_buffer_drain(dfu); |
| 269 | 288 | if (ret) { |
| 270 | - dfu_write_transaction_cleanup(dfu); | |
| 289 | + dfu_transaction_cleanup(dfu); | |
| 271 | 290 | return ret; |
| 272 | 291 | } |
| 273 | 292 | } |
| 274 | 293 | |
| ... | ... | @@ -334,29 +353,10 @@ |
| 334 | 353 | debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x i_buf: 0x%p\n", |
| 335 | 354 | __func__, dfu->name, buf, size, blk_seq_num, dfu->i_buf); |
| 336 | 355 | |
| 337 | - if (!dfu->inited) { | |
| 338 | - dfu->i_buf_start = dfu_get_buf(dfu); | |
| 339 | - if (dfu->i_buf_start == NULL) | |
| 340 | - return -ENOMEM; | |
| 356 | + ret = dfu_transaction_initiate(dfu, true); | |
| 357 | + if (ret < 0) | |
| 358 | + return ret; | |
| 341 | 359 | |
| 342 | - dfu->r_left = dfu->get_medium_size(dfu); | |
| 343 | - if (dfu->r_left < 0) | |
| 344 | - return dfu->r_left; | |
| 345 | - | |
| 346 | - debug("%s: %s %ld [B]\n", __func__, dfu->name, dfu->r_left); | |
| 347 | - | |
| 348 | - dfu->i_blk_seq_num = 0; | |
| 349 | - dfu->crc = 0; | |
| 350 | - dfu->offset = 0; | |
| 351 | - dfu->i_buf_end = dfu_get_buf(dfu) + dfu_buf_size; | |
| 352 | - dfu->i_buf = dfu->i_buf_start; | |
| 353 | - dfu->b_left = 0; | |
| 354 | - | |
| 355 | - dfu->bad_skip = 0; | |
| 356 | - | |
| 357 | - dfu->inited = 1; | |
| 358 | - } | |
| 359 | - | |
| 360 | 360 | if (dfu->i_blk_seq_num != blk_seq_num) { |
| 361 | 361 | printf("%s: Wrong sequence number! [%d] [%d]\n", |
| 362 | 362 | __func__, dfu->i_blk_seq_num, blk_seq_num); |
| ... | ... | @@ -377,17 +377,7 @@ |
| 377 | 377 | dfu_hash_algo->name, dfu->crc); |
| 378 | 378 | puts("\nUPLOAD ... done\nCtrl+C to exit ...\n"); |
| 379 | 379 | |
| 380 | - dfu->i_blk_seq_num = 0; | |
| 381 | - dfu->crc = 0; | |
| 382 | - dfu->offset = 0; | |
| 383 | - dfu->i_buf_start = dfu_buf; | |
| 384 | - dfu->i_buf_end = dfu_buf; | |
| 385 | - dfu->i_buf = dfu->i_buf_start; | |
| 386 | - dfu->b_left = 0; | |
| 387 | - | |
| 388 | - dfu->bad_skip = 0; | |
| 389 | - | |
| 390 | - dfu->inited = 0; | |
| 380 | + dfu_transaction_cleanup(dfu); | |
| 391 | 381 | } |
| 392 | 382 | |
| 393 | 383 | return ret; |
drivers/dfu/dfu_mmc.c
| ... | ... | @@ -17,7 +17,7 @@ |
| 17 | 17 | #include <mmc.h> |
| 18 | 18 | |
| 19 | 19 | static unsigned char *dfu_file_buf; |
| 20 | -static long dfu_file_buf_len; | |
| 20 | +static u64 dfu_file_buf_len; | |
| 21 | 21 | static long dfu_file_buf_filled; |
| 22 | 22 | |
| 23 | 23 | static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu, |
| ... | ... | @@ -107,7 +107,7 @@ |
| 107 | 107 | } |
| 108 | 108 | |
| 109 | 109 | static int mmc_file_op(enum dfu_op op, struct dfu_entity *dfu, |
| 110 | - void *buf, long *len) | |
| 110 | + void *buf, u64 *len) | |
| 111 | 111 | { |
| 112 | 112 | const char *fsname, *opname; |
| 113 | 113 | char cmd_buf[DFU_CMD_BUF_SIZE]; |
| ... | ... | @@ -150,7 +150,7 @@ |
| 150 | 150 | sprintf(cmd_buf + strlen(cmd_buf), " %s", dfu->name); |
| 151 | 151 | |
| 152 | 152 | if (op == DFU_OP_WRITE) |
| 153 | - sprintf(cmd_buf + strlen(cmd_buf), " %lx", *len); | |
| 153 | + sprintf(cmd_buf + strlen(cmd_buf), " %llx", *len); | |
| 154 | 154 | |
| 155 | 155 | debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf); |
| 156 | 156 | |
| 157 | 157 | |
| 158 | 158 | |
| 159 | 159 | |
| 160 | 160 | |
| 161 | 161 | |
| ... | ... | @@ -209,23 +209,23 @@ |
| 209 | 209 | return ret; |
| 210 | 210 | } |
| 211 | 211 | |
| 212 | -long dfu_get_medium_size_mmc(struct dfu_entity *dfu) | |
| 212 | +int dfu_get_medium_size_mmc(struct dfu_entity *dfu, u64 *size) | |
| 213 | 213 | { |
| 214 | 214 | int ret; |
| 215 | - long len; | |
| 216 | 215 | |
| 217 | 216 | switch (dfu->layout) { |
| 218 | 217 | case DFU_RAW_ADDR: |
| 219 | - return dfu->data.mmc.lba_size * dfu->data.mmc.lba_blk_size; | |
| 218 | + *size = dfu->data.mmc.lba_size * dfu->data.mmc.lba_blk_size; | |
| 219 | + return 0; | |
| 220 | 220 | case DFU_FS_FAT: |
| 221 | 221 | case DFU_FS_EXT4: |
| 222 | 222 | dfu_file_buf_filled = -1; |
| 223 | - ret = mmc_file_op(DFU_OP_SIZE, dfu, NULL, &len); | |
| 223 | + ret = mmc_file_op(DFU_OP_SIZE, dfu, NULL, size); | |
| 224 | 224 | if (ret < 0) |
| 225 | 225 | return ret; |
| 226 | - if (len > CONFIG_SYS_DFU_MAX_FILE_SIZE) | |
| 226 | + if (*size > CONFIG_SYS_DFU_MAX_FILE_SIZE) | |
| 227 | 227 | return -1; |
| 228 | - return len; | |
| 228 | + return 0; | |
| 229 | 229 | default: |
| 230 | 230 | printf("%s: Layout (%s) not (yet) supported!\n", __func__, |
| 231 | 231 | dfu_get_layout(dfu->layout)); |
| ... | ... | @@ -237,7 +237,7 @@ |
| 237 | 237 | long *len) |
| 238 | 238 | { |
| 239 | 239 | int ret; |
| 240 | - long file_len; | |
| 240 | + u64 file_len; | |
| 241 | 241 | |
| 242 | 242 | if (dfu_file_buf_filled == -1) { |
| 243 | 243 | ret = mmc_file_op(DFU_OP_READ, dfu, dfu_file_buf, &file_len); |
drivers/dfu/dfu_nand.c
| ... | ... | @@ -114,9 +114,11 @@ |
| 114 | 114 | return ret; |
| 115 | 115 | } |
| 116 | 116 | |
| 117 | -long dfu_get_medium_size_nand(struct dfu_entity *dfu) | |
| 117 | +int dfu_get_medium_size_nand(struct dfu_entity *dfu, u64 *size) | |
| 118 | 118 | { |
| 119 | - return dfu->data.nand.size; | |
| 119 | + *size = dfu->data.nand.size; | |
| 120 | + | |
| 121 | + return 0; | |
| 120 | 122 | } |
| 121 | 123 | |
| 122 | 124 | static int dfu_read_medium_nand(struct dfu_entity *dfu, u64 offset, void *buf, |
drivers/dfu/dfu_ram.c
| ... | ... | @@ -41,9 +41,11 @@ |
| 41 | 41 | return dfu_transfer_medium_ram(DFU_OP_WRITE, dfu, offset, buf, len); |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | -long dfu_get_medium_size_ram(struct dfu_entity *dfu) | |
| 44 | +int dfu_get_medium_size_ram(struct dfu_entity *dfu, u64 *size) | |
| 45 | 45 | { |
| 46 | - return dfu->data.ram.size; | |
| 46 | + *size = dfu->data.ram.size; | |
| 47 | + | |
| 48 | + return 0; | |
| 47 | 49 | } |
| 48 | 50 | |
| 49 | 51 | static int dfu_read_medium_ram(struct dfu_entity *dfu, u64 offset, |
drivers/dfu/dfu_sf.c
| ... | ... | @@ -12,9 +12,11 @@ |
| 12 | 12 | #include <spi.h> |
| 13 | 13 | #include <spi_flash.h> |
| 14 | 14 | |
| 15 | -static long dfu_get_medium_size_sf(struct dfu_entity *dfu) | |
| 15 | +static int dfu_get_medium_size_sf(struct dfu_entity *dfu, u64 *size) | |
| 16 | 16 | { |
| 17 | - return dfu->data.sf.size; | |
| 17 | + *size = dfu->data.sf.size; | |
| 18 | + | |
| 19 | + return 0; | |
| 18 | 20 | } |
| 19 | 21 | |
| 20 | 22 | static int dfu_read_medium_sf(struct dfu_entity *dfu, u64 offset, void *buf, |
drivers/phy/Kconfig
| ... | ... | @@ -41,6 +41,24 @@ |
| 41 | 41 | This select a dummy sandbox PHY driver. It used only to implement |
| 42 | 42 | the unit tests for the phy framework |
| 43 | 43 | |
| 44 | +config NOP_PHY | |
| 45 | + bool "NOP PHY driver" | |
| 46 | + depends on PHY | |
| 47 | + help | |
| 48 | + Support for a no-op PHY driver (stubbed PHY driver). | |
| 49 | + | |
| 50 | + This is useful when a driver uses the PHY framework but no real PHY | |
| 51 | + hardware exists. | |
| 52 | + | |
| 53 | +config SPL_NOP_PHY | |
| 54 | + bool "NOP PHY driver in SPL" | |
| 55 | + depends on SPL_PHY | |
| 56 | + help | |
| 57 | + Support for a no-op PHY driver (stubbed PHY driver) in the SPL. | |
| 58 | + | |
| 59 | + This is useful when a driver uses the PHY framework but no real PHY | |
| 60 | + hardware exists. | |
| 61 | + | |
| 44 | 62 | config PIPE3_PHY |
| 45 | 63 | bool "Support omap's PIPE3 PHY" |
| 46 | 64 | depends on PHY && ARCH_OMAP2PLUS |
drivers/phy/Makefile
drivers/phy/nop-phy.c
| 1 | +/* | |
| 2 | + * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ | |
| 3 | + * Written by Jean-Jacques Hiblot <jjhiblot@ti.com> | |
| 4 | + * | |
| 5 | + * SPDX-License-Identifier: GPL-2.0+ | |
| 6 | + */ | |
| 7 | + | |
| 8 | +#include <common.h> | |
| 9 | +#include <dm.h> | |
| 10 | +#include <dm/device.h> | |
| 11 | +#include <generic-phy.h> | |
| 12 | + | |
| 13 | +static const struct udevice_id nop_phy_ids[] = { | |
| 14 | + { .compatible = "nop-phy" }, | |
| 15 | + { } | |
| 16 | +}; | |
| 17 | + | |
| 18 | +static struct phy_ops nop_phy_ops = { | |
| 19 | +}; | |
| 20 | + | |
| 21 | +U_BOOT_DRIVER(nop_phy) = { | |
| 22 | + .name = "nop_phy", | |
| 23 | + .id = UCLASS_PHY, | |
| 24 | + .of_match = nop_phy_ids, | |
| 25 | + .ops = &nop_phy_ops, | |
| 26 | +}; |
drivers/phy/phy-uclass.c
drivers/reset/reset-uclass.c
| ... | ... | @@ -42,6 +42,7 @@ |
| 42 | 42 | |
| 43 | 43 | debug("%s(dev=%p, index=%d, reset_ctl=%p)\n", __func__, dev, index, |
| 44 | 44 | reset_ctl); |
| 45 | + reset_ctl->dev = NULL; | |
| 45 | 46 | |
| 46 | 47 | ret = dev_read_phandle_with_args(dev, "resets", "#reset-cells", 0, |
| 47 | 48 | index, &args); |
| ... | ... | @@ -87,6 +88,7 @@ |
| 87 | 88 | |
| 88 | 89 | debug("%s(dev=%p, name=%s, reset_ctl=%p)\n", __func__, dev, name, |
| 89 | 90 | reset_ctl); |
| 91 | + reset_ctl->dev = NULL; | |
| 90 | 92 | |
| 91 | 93 | index = dev_read_stringlist_search(dev, "reset-names", name); |
| 92 | 94 | if (index < 0) { |
| ... | ... | @@ -97,6 +99,15 @@ |
| 97 | 99 | return reset_get_by_index(dev, index, reset_ctl); |
| 98 | 100 | } |
| 99 | 101 | |
| 102 | +int reset_request(struct reset_ctl *reset_ctl) | |
| 103 | +{ | |
| 104 | + struct reset_ops *ops = reset_dev_ops(reset_ctl->dev); | |
| 105 | + | |
| 106 | + debug("%s(reset_ctl=%p)\n", __func__, reset_ctl); | |
| 107 | + | |
| 108 | + return ops->request(reset_ctl); | |
| 109 | +} | |
| 110 | + | |
| 100 | 111 | int reset_free(struct reset_ctl *reset_ctl) |
| 101 | 112 | { |
| 102 | 113 | struct reset_ops *ops = reset_dev_ops(reset_ctl->dev); |
| ... | ... | @@ -122,6 +133,29 @@ |
| 122 | 133 | debug("%s(reset_ctl=%p)\n", __func__, reset_ctl); |
| 123 | 134 | |
| 124 | 135 | return ops->rst_deassert(reset_ctl); |
| 136 | +} | |
| 137 | + | |
| 138 | +int reset_release_all(struct reset_ctl *reset_ctl, int count) | |
| 139 | +{ | |
| 140 | + int i, ret; | |
| 141 | + | |
| 142 | + for (i = 0; i < count; i++) { | |
| 143 | + debug("%s(reset_ctl[%d]=%p)\n", __func__, i, &reset_ctl[i]); | |
| 144 | + | |
| 145 | + /* check if reset has been previously requested */ | |
| 146 | + if (!reset_ctl[i].dev) | |
| 147 | + continue; | |
| 148 | + | |
| 149 | + ret = reset_assert(&reset_ctl[i]); | |
| 150 | + if (ret) | |
| 151 | + return ret; | |
| 152 | + | |
| 153 | + ret = reset_free(&reset_ctl[i]); | |
| 154 | + if (ret) | |
| 155 | + return ret; | |
| 156 | + } | |
| 157 | + | |
| 158 | + return 0; | |
| 125 | 159 | } |
| 126 | 160 | |
| 127 | 161 | UCLASS_DRIVER(reset) = { |
drivers/usb/emul/sandbox_hub.c
| ... | ... | @@ -96,7 +96,12 @@ |
| 96 | 96 | 1 << 7), |
| 97 | 97 | .bPwrOn2PwrGood = 2, |
| 98 | 98 | .bHubContrCurrent = 5, |
| 99 | - .DeviceRemovable = {0, 0xff}, /* all ports removeable */ | |
| 99 | + { | |
| 100 | + { | |
| 101 | + /* all ports removeable */ | |
| 102 | + .DeviceRemovable = {0, 0xff} | |
| 103 | + } | |
| 104 | + } | |
| 100 | 105 | #if SANDBOX_NUM_PORTS > 8 |
| 101 | 106 | #error "This code sets up an incorrect mask" |
| 102 | 107 | #endif |
drivers/usb/gadget/f_thor.c
drivers/usb/host/Kconfig
| ... | ... | @@ -31,6 +31,13 @@ |
| 31 | 31 | SoCs, which includes Armada8K, Armada3700 and other Armada |
| 32 | 32 | family SoCs. |
| 33 | 33 | |
| 34 | +config USB_XHCI_PCI | |
| 35 | + bool "Support for PCI-based xHCI USB controller" | |
| 36 | + depends on DM_USB | |
| 37 | + default y if X86 | |
| 38 | + help | |
| 39 | + Enables support for the PCI-based xHCI controller. | |
| 40 | + | |
| 34 | 41 | config USB_XHCI_ROCKCHIP |
| 35 | 42 | bool "Support for Rockchip on-chip xHCI USB controller" |
| 36 | 43 | depends on ARCH_ROCKCHIP |
drivers/usb/host/ehci-generic.c
| ... | ... | @@ -6,6 +6,8 @@ |
| 6 | 6 | |
| 7 | 7 | #include <common.h> |
| 8 | 8 | #include <clk.h> |
| 9 | +#include <dm/ofnode.h> | |
| 10 | +#include <generic-phy.h> | |
| 9 | 11 | #include <reset.h> |
| 10 | 12 | #include <asm/io.h> |
| 11 | 13 | #include <dm.h> |
| 12 | 14 | |
| 13 | 15 | |
| 14 | 16 | |
| 15 | 17 | |
| 16 | 18 | |
| 17 | 19 | |
| 18 | 20 | |
| 19 | 21 | |
| 20 | 22 | |
| ... | ... | @@ -18,45 +20,145 @@ |
| 18 | 20 | */ |
| 19 | 21 | struct generic_ehci { |
| 20 | 22 | struct ehci_ctrl ctrl; |
| 23 | + struct clk *clocks; | |
| 24 | + struct reset_ctl *resets; | |
| 25 | + struct phy phy; | |
| 26 | + int clock_count; | |
| 27 | + int reset_count; | |
| 21 | 28 | }; |
| 22 | 29 | |
| 23 | 30 | static int ehci_usb_probe(struct udevice *dev) |
| 24 | 31 | { |
| 32 | + struct generic_ehci *priv = dev_get_priv(dev); | |
| 25 | 33 | struct ehci_hccr *hccr; |
| 26 | 34 | struct ehci_hcor *hcor; |
| 27 | - int i; | |
| 35 | + int i, err, ret, clock_nb, reset_nb; | |
| 28 | 36 | |
| 29 | - for (i = 0; ; i++) { | |
| 30 | - struct clk clk; | |
| 31 | - int ret; | |
| 37 | + err = 0; | |
| 38 | + priv->clock_count = 0; | |
| 39 | + clock_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "clocks", | |
| 40 | + "#clock-cells"); | |
| 41 | + if (clock_nb > 0) { | |
| 42 | + priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk), | |
| 43 | + GFP_KERNEL); | |
| 44 | + if (!priv->clocks) | |
| 45 | + return -ENOMEM; | |
| 32 | 46 | |
| 33 | - ret = clk_get_by_index(dev, i, &clk); | |
| 34 | - if (ret < 0) | |
| 35 | - break; | |
| 36 | - if (clk_enable(&clk)) | |
| 37 | - printf("failed to enable clock %d\n", i); | |
| 38 | - clk_free(&clk); | |
| 47 | + for (i = 0; i < clock_nb; i++) { | |
| 48 | + err = clk_get_by_index(dev, i, &priv->clocks[i]); | |
| 49 | + | |
| 50 | + if (err < 0) | |
| 51 | + break; | |
| 52 | + err = clk_enable(&priv->clocks[i]); | |
| 53 | + if (err) { | |
| 54 | + error("failed to enable clock %d\n", i); | |
| 55 | + clk_free(&priv->clocks[i]); | |
| 56 | + goto clk_err; | |
| 57 | + } | |
| 58 | + priv->clock_count++; | |
| 59 | + } | |
| 60 | + } else { | |
| 61 | + if (clock_nb != -ENOENT) { | |
| 62 | + error("failed to get clock phandle(%d)\n", clock_nb); | |
| 63 | + return clock_nb; | |
| 64 | + } | |
| 39 | 65 | } |
| 40 | 66 | |
| 41 | - for (i = 0; ; i++) { | |
| 42 | - struct reset_ctl reset; | |
| 43 | - int ret; | |
| 67 | + priv->reset_count = 0; | |
| 68 | + reset_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "resets", | |
| 69 | + "#reset-cells"); | |
| 70 | + if (reset_nb > 0) { | |
| 71 | + priv->resets = devm_kcalloc(dev, reset_nb, | |
| 72 | + sizeof(struct reset_ctl), | |
| 73 | + GFP_KERNEL); | |
| 74 | + if (!priv->resets) | |
| 75 | + return -ENOMEM; | |
| 44 | 76 | |
| 45 | - ret = reset_get_by_index(dev, i, &reset); | |
| 46 | - if (ret < 0) | |
| 47 | - break; | |
| 48 | - if (reset_deassert(&reset)) | |
| 49 | - printf("failed to deassert reset %d\n", i); | |
| 50 | - reset_free(&reset); | |
| 77 | + for (i = 0; i < reset_nb; i++) { | |
| 78 | + err = reset_get_by_index(dev, i, &priv->resets[i]); | |
| 79 | + if (err < 0) | |
| 80 | + break; | |
| 81 | + | |
| 82 | + if (reset_deassert(&priv->resets[i])) { | |
| 83 | + error("failed to deassert reset %d\n", i); | |
| 84 | + reset_free(&priv->resets[i]); | |
| 85 | + goto reset_err; | |
| 86 | + } | |
| 87 | + priv->reset_count++; | |
| 88 | + } | |
| 89 | + } else { | |
| 90 | + if (reset_nb != -ENOENT) { | |
| 91 | + error("failed to get reset phandle(%d)\n", reset_nb); | |
| 92 | + goto clk_err; | |
| 93 | + } | |
| 51 | 94 | } |
| 52 | 95 | |
| 96 | + err = generic_phy_get_by_index(dev, 0, &priv->phy); | |
| 97 | + if (err) { | |
| 98 | + if (err != -ENOENT) { | |
| 99 | + error("failed to get usb phy\n"); | |
| 100 | + goto reset_err; | |
| 101 | + } | |
| 102 | + } else { | |
| 103 | + | |
| 104 | + err = generic_phy_init(&priv->phy); | |
| 105 | + if (err) { | |
| 106 | + error("failed to init usb phy\n"); | |
| 107 | + goto reset_err; | |
| 108 | + } | |
| 109 | + } | |
| 110 | + | |
| 53 | 111 | hccr = map_physmem(devfdt_get_addr(dev), 0x100, MAP_NOCACHE); |
| 54 | 112 | hcor = (struct ehci_hcor *)((uintptr_t)hccr + |
| 55 | 113 | HC_LENGTH(ehci_readl(&hccr->cr_capbase))); |
| 56 | 114 | |
| 57 | - return ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST); | |
| 115 | + err = ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST); | |
| 116 | + if (err) | |
| 117 | + goto phy_err; | |
| 118 | + | |
| 119 | + return 0; | |
| 120 | + | |
| 121 | +phy_err: | |
| 122 | + if (generic_phy_valid(&priv->phy)) { | |
| 123 | + ret = generic_phy_exit(&priv->phy); | |
| 124 | + if (ret) | |
| 125 | + error("failed to release phy\n"); | |
| 126 | + } | |
| 127 | + | |
| 128 | +reset_err: | |
| 129 | + ret = reset_release_all(priv->resets, priv->reset_count); | |
| 130 | + if (ret) | |
| 131 | + error("failed to assert all resets\n"); | |
| 132 | +clk_err: | |
| 133 | + ret = clk_release_all(priv->clocks, priv->clock_count); | |
| 134 | + if (ret) | |
| 135 | + error("failed to disable all clocks\n"); | |
| 136 | + | |
| 137 | + return err; | |
| 58 | 138 | } |
| 59 | 139 | |
| 140 | +static int ehci_usb_remove(struct udevice *dev) | |
| 141 | +{ | |
| 142 | + struct generic_ehci *priv = dev_get_priv(dev); | |
| 143 | + int ret; | |
| 144 | + | |
| 145 | + ret = ehci_deregister(dev); | |
| 146 | + if (ret) | |
| 147 | + return ret; | |
| 148 | + | |
| 149 | + if (generic_phy_valid(&priv->phy)) { | |
| 150 | + ret = generic_phy_exit(&priv->phy); | |
| 151 | + if (ret) | |
| 152 | + return ret; | |
| 153 | + } | |
| 154 | + | |
| 155 | + ret = reset_release_all(priv->resets, priv->reset_count); | |
| 156 | + if (ret) | |
| 157 | + return ret; | |
| 158 | + | |
| 159 | + return clk_release_all(priv->clocks, priv->clock_count); | |
| 160 | +} | |
| 161 | + | |
| 60 | 162 | static const struct udevice_id ehci_usb_ids[] = { |
| 61 | 163 | { .compatible = "generic-ehci" }, |
| 62 | 164 | { } |
| ... | ... | @@ -67,7 +169,7 @@ |
| 67 | 169 | .id = UCLASS_USB, |
| 68 | 170 | .of_match = ehci_usb_ids, |
| 69 | 171 | .probe = ehci_usb_probe, |
| 70 | - .remove = ehci_deregister, | |
| 172 | + .remove = ehci_usb_remove, | |
| 71 | 173 | .ops = &ehci_usb_ops, |
| 72 | 174 | .priv_auto_alloc_size = sizeof(struct generic_ehci), |
| 73 | 175 | .flags = DM_FLAG_ALLOC_PRIV_DMA, |
drivers/usb/host/ehci-hcd.c
| ... | ... | @@ -52,8 +52,8 @@ |
| 52 | 52 | 0, /* wHubCharacteristics */ |
| 53 | 53 | 10, /* bPwrOn2PwrGood */ |
| 54 | 54 | 0, /* bHubCntrCurrent */ |
| 55 | - {}, /* Device removable */ | |
| 56 | - {} /* at most 7 ports! XXX */ | |
| 55 | + { /* Device removable */ | |
| 56 | + } /* at most 7 ports! XXX */ | |
| 57 | 57 | }, |
| 58 | 58 | { |
| 59 | 59 | 0x12, /* bLength */ |
| 60 | 60 | |
| ... | ... | @@ -148,9 +148,12 @@ |
| 148 | 148 | |
| 149 | 149 | static uint32_t *ehci_get_portsc_register(struct ehci_ctrl *ctrl, int port) |
| 150 | 150 | { |
| 151 | - if (port < 0 || port >= CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) { | |
| 151 | + int max_ports = HCS_N_PORTS(ehci_readl(&ctrl->hccr->cr_hcsparams)); | |
| 152 | + | |
| 153 | + if (port < 0 || port >= max_ports) { | |
| 152 | 154 | /* Printing the message would cause a scan failure! */ |
| 153 | - debug("The request port(%u) is not configured\n", port); | |
| 155 | + debug("The request port(%u) exceeds maximum port number\n", | |
| 156 | + port); | |
| 154 | 157 | return NULL; |
| 155 | 158 | } |
| 156 | 159 | |
| ... | ... | @@ -205,6 +208,7 @@ |
| 205 | 208 | { |
| 206 | 209 | int i, ret = 0; |
| 207 | 210 | uint32_t cmd, reg; |
| 211 | + int max_ports = HCS_N_PORTS(ehci_readl(&ctrl->hccr->cr_hcsparams)); | |
| 208 | 212 | |
| 209 | 213 | if (!ctrl || !ctrl->hcor) |
| 210 | 214 | return -EINVAL; |
| ... | ... | @@ -219,7 +223,7 @@ |
| 219 | 223 | 100 * 1000); |
| 220 | 224 | |
| 221 | 225 | if (!ret) { |
| 222 | - for (i = 0; i < CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS; i++) { | |
| 226 | + for (i = 0; i < max_ports; i++) { | |
| 223 | 227 | reg = ehci_readl(&ctrl->hcor->or_portsc[i]); |
| 224 | 228 | reg |= EHCI_PS_SUSP; |
| 225 | 229 | ehci_writel(&ctrl->hcor->or_portsc[i], reg); |
| ... | ... | @@ -937,7 +941,7 @@ |
| 937 | 941 | return -1; |
| 938 | 942 | } |
| 939 | 943 | |
| 940 | -const struct ehci_ops default_ehci_ops = { | |
| 944 | +static const struct ehci_ops default_ehci_ops = { | |
| 941 | 945 | .set_usb_mode = ehci_set_usbmode, |
| 942 | 946 | .get_port_speed = ehci_get_port_speed, |
| 943 | 947 | .powerup_fixup = ehci_powerup_fixup, |
drivers/usb/host/ehci.h
| ... | ... | @@ -11,9 +11,8 @@ |
| 11 | 11 | |
| 12 | 12 | #include <usb.h> |
| 13 | 13 | |
| 14 | -#if !defined(CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) | |
| 15 | -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 2 | |
| 16 | -#endif | |
| 14 | +/* Section 2.2.3 - N_PORTS */ | |
| 15 | +#define MAX_HC_PORTS 15 | |
| 17 | 16 | |
| 18 | 17 | /* |
| 19 | 18 | * Register Space. |
| ... | ... | @@ -62,7 +61,7 @@ |
| 62 | 61 | uint32_t _reserved_1_[6]; |
| 63 | 62 | uint32_t or_configflag; |
| 64 | 63 | #define FLAG_CF (1 << 0) /* true: we'll support "high speed" */ |
| 65 | - uint32_t or_portsc[CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS]; | |
| 64 | + uint32_t or_portsc[MAX_HC_PORTS]; | |
| 66 | 65 | #define PORTSC_PSPD(x) (((x) >> 26) & 0x3) |
| 67 | 66 | #define PORTSC_PSPD_FS 0x0 |
| 68 | 67 | #define PORTSC_PSPD_LS 0x1 |
drivers/usb/host/ohci-generic.c
| ... | ... | @@ -5,7 +5,11 @@ |
| 5 | 5 | */ |
| 6 | 6 | |
| 7 | 7 | #include <common.h> |
| 8 | +#include <clk.h> | |
| 8 | 9 | #include <dm.h> |
| 10 | +#include <dm/ofnode.h> | |
| 11 | +#include <generic-phy.h> | |
| 12 | +#include <reset.h> | |
| 9 | 13 | #include "ohci.h" |
| 10 | 14 | |
| 11 | 15 | #if !defined(CONFIG_USB_OHCI_NEW) |
| 12 | 16 | |
| 13 | 17 | |
| 14 | 18 | |
| ... | ... | @@ -14,18 +18,133 @@ |
| 14 | 18 | |
| 15 | 19 | struct generic_ohci { |
| 16 | 20 | ohci_t ohci; |
| 21 | + struct clk *clocks; /* clock list */ | |
| 22 | + struct reset_ctl *resets; /* reset list */ | |
| 23 | + struct phy phy; | |
| 24 | + int clock_count; /* number of clock in clock list */ | |
| 25 | + int reset_count; /* number of reset in reset list */ | |
| 17 | 26 | }; |
| 18 | 27 | |
| 19 | 28 | static int ohci_usb_probe(struct udevice *dev) |
| 20 | 29 | { |
| 21 | 30 | struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev); |
| 31 | + struct generic_ohci *priv = dev_get_priv(dev); | |
| 32 | + int i, err, ret, clock_nb, reset_nb; | |
| 22 | 33 | |
| 23 | - return ohci_register(dev, regs); | |
| 34 | + err = 0; | |
| 35 | + priv->clock_count = 0; | |
| 36 | + clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells"); | |
| 37 | + if (clock_nb > 0) { | |
| 38 | + priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk), | |
| 39 | + GFP_KERNEL); | |
| 40 | + if (!priv->clocks) | |
| 41 | + return -ENOMEM; | |
| 42 | + | |
| 43 | + for (i = 0; i < clock_nb; i++) { | |
| 44 | + err = clk_get_by_index(dev, i, &priv->clocks[i]); | |
| 45 | + if (err < 0) | |
| 46 | + break; | |
| 47 | + | |
| 48 | + err = clk_enable(&priv->clocks[i]); | |
| 49 | + if (err) { | |
| 50 | + error("failed to enable clock %d\n", i); | |
| 51 | + clk_free(&priv->clocks[i]); | |
| 52 | + goto clk_err; | |
| 53 | + } | |
| 54 | + priv->clock_count++; | |
| 55 | + } | |
| 56 | + } else if (clock_nb != -ENOENT) { | |
| 57 | + error("failed to get clock phandle(%d)\n", clock_nb); | |
| 58 | + return clock_nb; | |
| 59 | + } | |
| 60 | + | |
| 61 | + priv->reset_count = 0; | |
| 62 | + reset_nb = dev_count_phandle_with_args(dev, "resets", "#reset-cells"); | |
| 63 | + if (reset_nb > 0) { | |
| 64 | + priv->resets = devm_kcalloc(dev, reset_nb, | |
| 65 | + sizeof(struct reset_ctl), | |
| 66 | + GFP_KERNEL); | |
| 67 | + if (!priv->resets) | |
| 68 | + return -ENOMEM; | |
| 69 | + | |
| 70 | + for (i = 0; i < reset_nb; i++) { | |
| 71 | + err = reset_get_by_index(dev, i, &priv->resets[i]); | |
| 72 | + if (err < 0) | |
| 73 | + break; | |
| 74 | + | |
| 75 | + err = reset_deassert(&priv->resets[i]); | |
| 76 | + if (err) { | |
| 77 | + error("failed to deassert reset %d\n", i); | |
| 78 | + reset_free(&priv->resets[i]); | |
| 79 | + goto reset_err; | |
| 80 | + } | |
| 81 | + priv->reset_count++; | |
| 82 | + } | |
| 83 | + } else if (reset_nb != -ENOENT) { | |
| 84 | + error("failed to get reset phandle(%d)\n", reset_nb); | |
| 85 | + goto clk_err; | |
| 86 | + } | |
| 87 | + | |
| 88 | + err = generic_phy_get_by_index(dev, 0, &priv->phy); | |
| 89 | + if (err) { | |
| 90 | + if (err != -ENOENT) { | |
| 91 | + error("failed to get usb phy\n"); | |
| 92 | + goto reset_err; | |
| 93 | + } | |
| 94 | + } else { | |
| 95 | + | |
| 96 | + err = generic_phy_init(&priv->phy); | |
| 97 | + if (err) { | |
| 98 | + error("failed to init usb phy\n"); | |
| 99 | + goto reset_err; | |
| 100 | + } | |
| 101 | + } | |
| 102 | + | |
| 103 | + err = ohci_register(dev, regs); | |
| 104 | + if (err) | |
| 105 | + goto phy_err; | |
| 106 | + | |
| 107 | + return 0; | |
| 108 | + | |
| 109 | +phy_err: | |
| 110 | + if (generic_phy_valid(&priv->phy)) { | |
| 111 | + ret = generic_phy_exit(&priv->phy); | |
| 112 | + if (ret) | |
| 113 | + error("failed to release phy\n"); | |
| 114 | + } | |
| 115 | + | |
| 116 | +reset_err: | |
| 117 | + ret = reset_release_all(priv->resets, priv->reset_count); | |
| 118 | + if (ret) | |
| 119 | + error("failed to assert all resets\n"); | |
| 120 | +clk_err: | |
| 121 | + ret = clk_release_all(priv->clocks, priv->clock_count); | |
| 122 | + if (ret) | |
| 123 | + error("failed to disable all clocks\n"); | |
| 124 | + | |
| 125 | + return err; | |
| 24 | 126 | } |
| 25 | 127 | |
| 26 | 128 | static int ohci_usb_remove(struct udevice *dev) |
| 27 | 129 | { |
| 28 | - return ohci_deregister(dev); | |
| 130 | + struct generic_ohci *priv = dev_get_priv(dev); | |
| 131 | + int ret; | |
| 132 | + | |
| 133 | + ret = ohci_deregister(dev); | |
| 134 | + if (ret) | |
| 135 | + return ret; | |
| 136 | + | |
| 137 | + if (generic_phy_valid(&priv->phy)) { | |
| 138 | + ret = generic_phy_exit(&priv->phy); | |
| 139 | + if (ret) | |
| 140 | + return ret; | |
| 141 | + } | |
| 142 | + | |
| 143 | + ret = reset_release_all(priv->resets, priv->reset_count); | |
| 144 | + if (ret) | |
| 145 | + return ret; | |
| 146 | + | |
| 147 | + return clk_release_all(priv->clocks, priv->clock_count); | |
| 29 | 148 | } |
| 30 | 149 | |
| 31 | 150 | static const struct udevice_id ohci_usb_ids[] = { |
drivers/usb/host/usb-uclass.c
| ... | ... | @@ -139,6 +139,17 @@ |
| 139 | 139 | return ops->reset_root_port(bus, udev); |
| 140 | 140 | } |
| 141 | 141 | |
| 142 | +int usb_update_hub_device(struct usb_device *udev) | |
| 143 | +{ | |
| 144 | + struct udevice *bus = udev->controller_dev; | |
| 145 | + struct dm_usb_ops *ops = usb_get_ops(bus); | |
| 146 | + | |
| 147 | + if (!ops->update_hub_device) | |
| 148 | + return -ENOSYS; | |
| 149 | + | |
| 150 | + return ops->update_hub_device(bus, udev); | |
| 151 | +} | |
| 152 | + | |
| 142 | 153 | int usb_stop(void) |
| 143 | 154 | { |
| 144 | 155 | struct udevice *bus; |
| ... | ... | @@ -177,7 +188,6 @@ |
| 177 | 188 | #ifdef CONFIG_USB_STORAGE |
| 178 | 189 | usb_stor_reset(); |
| 179 | 190 | #endif |
| 180 | - usb_hub_reset(); | |
| 181 | 191 | uc_priv->companion_device_count = 0; |
| 182 | 192 | usb_started = 0; |
| 183 | 193 | |
| ... | ... | @@ -230,7 +240,6 @@ |
| 230 | 240 | int ret; |
| 231 | 241 | |
| 232 | 242 | asynch_allowed = 1; |
| 233 | - usb_hub_reset(); | |
| 234 | 243 | |
| 235 | 244 | ret = uclass_get(UCLASS_USB, &uc); |
| 236 | 245 | if (ret) |
| ... | ... | @@ -373,8 +382,8 @@ |
| 373 | 382 | } |
| 374 | 383 | |
| 375 | 384 | /* returns 0 if no match, 1 if match */ |
| 376 | -int usb_match_device(const struct usb_device_descriptor *desc, | |
| 377 | - const struct usb_device_id *id) | |
| 385 | +static int usb_match_device(const struct usb_device_descriptor *desc, | |
| 386 | + const struct usb_device_id *id) | |
| 378 | 387 | { |
| 379 | 388 | if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && |
| 380 | 389 | id->idVendor != le16_to_cpu(desc->idVendor)) |
| ... | ... | @@ -410,9 +419,9 @@ |
| 410 | 419 | } |
| 411 | 420 | |
| 412 | 421 | /* returns 0 if no match, 1 if match */ |
| 413 | -int usb_match_one_id_intf(const struct usb_device_descriptor *desc, | |
| 414 | - const struct usb_interface_descriptor *int_desc, | |
| 415 | - const struct usb_device_id *id) | |
| 422 | +static int usb_match_one_id_intf(const struct usb_device_descriptor *desc, | |
| 423 | + const struct usb_interface_descriptor *int_desc, | |
| 424 | + const struct usb_device_id *id) | |
| 416 | 425 | { |
| 417 | 426 | /* The interface class, subclass, protocol and number should never be |
| 418 | 427 | * checked for a match if the device class is Vendor Specific, |
| ... | ... | @@ -445,9 +454,9 @@ |
| 445 | 454 | } |
| 446 | 455 | |
| 447 | 456 | /* returns 0 if no match, 1 if match */ |
| 448 | -int usb_match_one_id(struct usb_device_descriptor *desc, | |
| 449 | - struct usb_interface_descriptor *int_desc, | |
| 450 | - const struct usb_device_id *id) | |
| 457 | +static int usb_match_one_id(struct usb_device_descriptor *desc, | |
| 458 | + struct usb_interface_descriptor *int_desc, | |
| 459 | + const struct usb_device_id *id) | |
| 451 | 460 | { |
| 452 | 461 | if (!usb_match_device(desc, id)) |
| 453 | 462 | return 0; |
| ... | ... | @@ -680,7 +689,7 @@ |
| 680 | 689 | return change; |
| 681 | 690 | } |
| 682 | 691 | |
| 683 | -int usb_child_post_bind(struct udevice *dev) | |
| 692 | +static int usb_child_post_bind(struct udevice *dev) | |
| 684 | 693 | { |
| 685 | 694 | struct usb_dev_platdata *plat = dev_get_parent_platdata(dev); |
| 686 | 695 | int val; |
drivers/usb/host/xhci-dwc3.c
| ... | ... | @@ -9,9 +9,22 @@ |
| 9 | 9 | */ |
| 10 | 10 | |
| 11 | 11 | #include <common.h> |
| 12 | +#include <dm.h> | |
| 13 | +#include <fdtdec.h> | |
| 14 | +#include <generic-phy.h> | |
| 15 | +#include <usb.h> | |
| 16 | + | |
| 17 | +#include "xhci.h" | |
| 12 | 18 | #include <asm/io.h> |
| 13 | 19 | #include <linux/usb/dwc3.h> |
| 20 | +#include <linux/usb/otg.h> | |
| 14 | 21 | |
| 22 | +DECLARE_GLOBAL_DATA_PTR; | |
| 23 | + | |
| 24 | +struct xhci_dwc3_platdata { | |
| 25 | + struct phy usb_phy; | |
| 26 | +}; | |
| 27 | + | |
| 15 | 28 | void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode) |
| 16 | 29 | { |
| 17 | 30 | clrsetbits_le32(&dwc3_reg->g_ctl, |
| ... | ... | @@ -19,7 +32,7 @@ |
| 19 | 32 | DWC3_GCTL_PRTCAPDIR(mode)); |
| 20 | 33 | } |
| 21 | 34 | |
| 22 | -void dwc3_phy_reset(struct dwc3 *dwc3_reg) | |
| 35 | +static void dwc3_phy_reset(struct dwc3 *dwc3_reg) | |
| 23 | 36 | { |
| 24 | 37 | /* Assert USB3 PHY reset */ |
| 25 | 38 | setbits_le32(&dwc3_reg->g_usb3pipectl[0], DWC3_GUSB3PIPECTL_PHYSOFTRST); |
| ... | ... | @@ -97,4 +110,80 @@ |
| 97 | 110 | setbits_le32(&dwc3_reg->g_fladj, GFLADJ_30MHZ_REG_SEL | |
| 98 | 111 | GFLADJ_30MHZ(val)); |
| 99 | 112 | } |
| 113 | + | |
| 114 | +#ifdef CONFIG_DM_USB | |
| 115 | +static int xhci_dwc3_probe(struct udevice *dev) | |
| 116 | +{ | |
| 117 | + struct xhci_dwc3_platdata *plat = dev_get_platdata(dev); | |
| 118 | + struct xhci_hcor *hcor; | |
| 119 | + struct xhci_hccr *hccr; | |
| 120 | + struct dwc3 *dwc3_reg; | |
| 121 | + enum usb_dr_mode dr_mode; | |
| 122 | + int ret; | |
| 123 | + | |
| 124 | + hccr = (struct xhci_hccr *)((uintptr_t)dev_read_addr(dev)); | |
| 125 | + hcor = (struct xhci_hcor *)((uintptr_t)hccr + | |
| 126 | + HC_LENGTH(xhci_readl(&(hccr)->cr_capbase))); | |
| 127 | + | |
| 128 | + ret = generic_phy_get_by_index(dev, 0, &plat->usb_phy); | |
| 129 | + if (ret) { | |
| 130 | + if (ret != -ENOENT) { | |
| 131 | + error("Failed to get USB PHY for %s\n", dev->name); | |
| 132 | + return ret; | |
| 133 | + } | |
| 134 | + } else { | |
| 135 | + ret = generic_phy_init(&plat->usb_phy); | |
| 136 | + if (ret) { | |
| 137 | + error("Can't init USB PHY for %s\n", dev->name); | |
| 138 | + return ret; | |
| 139 | + } | |
| 140 | + } | |
| 141 | + | |
| 142 | + dwc3_reg = (struct dwc3 *)((char *)(hccr) + DWC3_REG_OFFSET); | |
| 143 | + | |
| 144 | + dwc3_core_init(dwc3_reg); | |
| 145 | + | |
| 146 | + dr_mode = usb_get_dr_mode(dev_of_offset(dev)); | |
| 147 | + if (dr_mode == USB_DR_MODE_UNKNOWN) | |
| 148 | + /* by default set dual role mode to HOST */ | |
| 149 | + dr_mode = USB_DR_MODE_HOST; | |
| 150 | + | |
| 151 | + dwc3_set_mode(dwc3_reg, dr_mode); | |
| 152 | + | |
| 153 | + return xhci_register(dev, hccr, hcor); | |
| 154 | +} | |
| 155 | + | |
| 156 | +static int xhci_dwc3_remove(struct udevice *dev) | |
| 157 | +{ | |
| 158 | + struct xhci_dwc3_platdata *plat = dev_get_platdata(dev); | |
| 159 | + int ret; | |
| 160 | + | |
| 161 | + if (generic_phy_valid(&plat->usb_phy)) { | |
| 162 | + ret = generic_phy_exit(&plat->usb_phy); | |
| 163 | + if (ret) { | |
| 164 | + error("Can't deinit USB PHY for %s\n", dev->name); | |
| 165 | + return ret; | |
| 166 | + } | |
| 167 | + } | |
| 168 | + | |
| 169 | + return xhci_deregister(dev); | |
| 170 | +} | |
| 171 | + | |
| 172 | +static const struct udevice_id xhci_dwc3_ids[] = { | |
| 173 | + { .compatible = "snps,dwc3" }, | |
| 174 | + { } | |
| 175 | +}; | |
| 176 | + | |
| 177 | +U_BOOT_DRIVER(xhci_dwc3) = { | |
| 178 | + .name = "xhci-dwc3", | |
| 179 | + .id = UCLASS_USB, | |
| 180 | + .of_match = xhci_dwc3_ids, | |
| 181 | + .probe = xhci_dwc3_probe, | |
| 182 | + .remove = xhci_dwc3_remove, | |
| 183 | + .ops = &xhci_usb_ops, | |
| 184 | + .priv_auto_alloc_size = sizeof(struct xhci_ctrl), | |
| 185 | + .platdata_auto_alloc_size = sizeof(struct xhci_dwc3_platdata), | |
| 186 | + .flags = DM_FLAG_ALLOC_PRIV_DMA, | |
| 187 | +}; | |
| 188 | +#endif |
drivers/usb/host/xhci-mem.c
| ... | ... | @@ -96,6 +96,25 @@ |
| 96 | 96 | } |
| 97 | 97 | |
| 98 | 98 | /** |
| 99 | + * Free the scratchpad buffer array and scratchpad buffers | |
| 100 | + * | |
| 101 | + * @ctrl host controller data structure | |
| 102 | + * @return none | |
| 103 | + */ | |
| 104 | +static void xhci_scratchpad_free(struct xhci_ctrl *ctrl) | |
| 105 | +{ | |
| 106 | + if (!ctrl->scratchpad) | |
| 107 | + return; | |
| 108 | + | |
| 109 | + ctrl->dcbaa->dev_context_ptrs[0] = 0; | |
| 110 | + | |
| 111 | + free((void *)(uintptr_t)ctrl->scratchpad->sp_array[0]); | |
| 112 | + free(ctrl->scratchpad->sp_array); | |
| 113 | + free(ctrl->scratchpad); | |
| 114 | + ctrl->scratchpad = NULL; | |
| 115 | +} | |
| 116 | + | |
| 117 | +/** | |
| 99 | 118 | * frees the "xhci_container_ctx" pointer passed |
| 100 | 119 | * |
| 101 | 120 | * @param ptr pointer to "xhci_container_ctx" to be freed |
| ... | ... | @@ -155,6 +174,7 @@ |
| 155 | 174 | { |
| 156 | 175 | xhci_ring_free(ctrl->event_ring); |
| 157 | 176 | xhci_ring_free(ctrl->cmd_ring); |
| 177 | + xhci_scratchpad_free(ctrl); | |
| 158 | 178 | xhci_free_virt_devices(ctrl); |
| 159 | 179 | free(ctrl->erst.entries); |
| 160 | 180 | free(ctrl->dcbaa); |
| ... | ... | @@ -320,6 +340,70 @@ |
| 320 | 340 | } |
| 321 | 341 | |
| 322 | 342 | /** |
| 343 | + * Set up the scratchpad buffer array and scratchpad buffers | |
| 344 | + * | |
| 345 | + * @ctrl host controller data structure | |
| 346 | + * @return -ENOMEM if buffer allocation fails, 0 on success | |
| 347 | + */ | |
| 348 | +static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl) | |
| 349 | +{ | |
| 350 | + struct xhci_hccr *hccr = ctrl->hccr; | |
| 351 | + struct xhci_hcor *hcor = ctrl->hcor; | |
| 352 | + struct xhci_scratchpad *scratchpad; | |
| 353 | + int num_sp; | |
| 354 | + uint32_t page_size; | |
| 355 | + void *buf; | |
| 356 | + int i; | |
| 357 | + | |
| 358 | + num_sp = HCS_MAX_SCRATCHPAD(xhci_readl(&hccr->cr_hcsparams2)); | |
| 359 | + if (!num_sp) | |
| 360 | + return 0; | |
| 361 | + | |
| 362 | + scratchpad = malloc(sizeof(*scratchpad)); | |
| 363 | + if (!scratchpad) | |
| 364 | + goto fail_sp; | |
| 365 | + ctrl->scratchpad = scratchpad; | |
| 366 | + | |
| 367 | + scratchpad->sp_array = xhci_malloc(num_sp * sizeof(u64)); | |
| 368 | + if (!scratchpad->sp_array) | |
| 369 | + goto fail_sp2; | |
| 370 | + ctrl->dcbaa->dev_context_ptrs[0] = | |
| 371 | + cpu_to_le64((uintptr_t)scratchpad->sp_array); | |
| 372 | + | |
| 373 | + page_size = xhci_readl(&hcor->or_pagesize) & 0xffff; | |
| 374 | + for (i = 0; i < 16; i++) { | |
| 375 | + if ((0x1 & page_size) != 0) | |
| 376 | + break; | |
| 377 | + page_size = page_size >> 1; | |
| 378 | + } | |
| 379 | + BUG_ON(i == 16); | |
| 380 | + | |
| 381 | + page_size = 1 << (i + 12); | |
| 382 | + buf = memalign(page_size, num_sp * page_size); | |
| 383 | + if (!buf) | |
| 384 | + goto fail_sp3; | |
| 385 | + memset(buf, '\0', num_sp * page_size); | |
| 386 | + xhci_flush_cache((uintptr_t)buf, num_sp * page_size); | |
| 387 | + | |
| 388 | + for (i = 0; i < num_sp; i++) { | |
| 389 | + uintptr_t ptr = (uintptr_t)buf + i * page_size; | |
| 390 | + scratchpad->sp_array[i] = cpu_to_le64(ptr); | |
| 391 | + } | |
| 392 | + | |
| 393 | + return 0; | |
| 394 | + | |
| 395 | +fail_sp3: | |
| 396 | + free(scratchpad->sp_array); | |
| 397 | + | |
| 398 | +fail_sp2: | |
| 399 | + free(scratchpad); | |
| 400 | + ctrl->scratchpad = NULL; | |
| 401 | + | |
| 402 | +fail_sp: | |
| 403 | + return -ENOMEM; | |
| 404 | +} | |
| 405 | + | |
| 406 | +/** | |
| 323 | 407 | * Allocates the Container context |
| 324 | 408 | * |
| 325 | 409 | * @param ctrl Host controller data structure |
| ... | ... | @@ -499,6 +583,9 @@ |
| 499 | 583 | |
| 500 | 584 | xhci_writeq(&ctrl->ir_set->erst_base, val_64); |
| 501 | 585 | |
| 586 | + /* set up the scratchpad buffer array and scratchpad buffers */ | |
| 587 | + xhci_scratchpad_alloc(ctrl); | |
| 588 | + | |
| 502 | 589 | /* initializing the virtual devices to NULL */ |
| 503 | 590 | for (i = 0; i < MAX_HC_SLOTS; ++i) |
| 504 | 591 | ctrl->devs[i] = NULL; |
| 505 | 592 | |
| ... | ... | @@ -626,14 +713,21 @@ |
| 626 | 713 | * @param udev pointer to the Device Data Structure |
| 627 | 714 | * @return returns negative value on failure else 0 on success |
| 628 | 715 | */ |
| 629 | -void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, int slot_id, | |
| 630 | - int speed, int hop_portnr) | |
| 716 | +void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, | |
| 717 | + struct usb_device *udev, int hop_portnr) | |
| 631 | 718 | { |
| 632 | 719 | struct xhci_virt_device *virt_dev; |
| 633 | 720 | struct xhci_ep_ctx *ep0_ctx; |
| 634 | 721 | struct xhci_slot_ctx *slot_ctx; |
| 635 | 722 | u32 port_num = 0; |
| 636 | 723 | u64 trb_64 = 0; |
| 724 | + int slot_id = udev->slot_id; | |
| 725 | + int speed = udev->speed; | |
| 726 | + int route = 0; | |
| 727 | +#ifdef CONFIG_DM_USB | |
| 728 | + struct usb_device *dev = udev; | |
| 729 | + struct usb_hub_device *hub; | |
| 730 | +#endif | |
| 637 | 731 | |
| 638 | 732 | virt_dev = ctrl->devs[slot_id]; |
| 639 | 733 | |
| 640 | 734 | |
| ... | ... | @@ -644,8 +738,33 @@ |
| 644 | 738 | slot_ctx = xhci_get_slot_ctx(ctrl, virt_dev->in_ctx); |
| 645 | 739 | |
| 646 | 740 | /* Only the control endpoint is valid - one endpoint context */ |
| 647 | - slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | 0); | |
| 741 | + slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1)); | |
| 648 | 742 | |
| 743 | +#ifdef CONFIG_DM_USB | |
| 744 | + /* Calculate the route string for this device */ | |
| 745 | + port_num = dev->portnr; | |
| 746 | + while (!usb_hub_is_root_hub(dev->dev)) { | |
| 747 | + hub = dev_get_uclass_priv(dev->dev); | |
| 748 | + /* | |
| 749 | + * Each hub in the topology is expected to have no more than | |
| 750 | + * 15 ports in order for the route string of a device to be | |
| 751 | + * unique. SuperSpeed hubs are restricted to only having 15 | |
| 752 | + * ports, but FS/LS/HS hubs are not. The xHCI specification | |
| 753 | + * says that if the port number the device is greater than 15, | |
| 754 | + * that portion of the route string shall be set to 15. | |
| 755 | + */ | |
| 756 | + if (port_num > 15) | |
| 757 | + port_num = 15; | |
| 758 | + route |= port_num << (hub->hub_depth * 4); | |
| 759 | + dev = dev_get_parent_priv(dev->dev); | |
| 760 | + port_num = dev->portnr; | |
| 761 | + dev = dev_get_parent_priv(dev->dev->parent); | |
| 762 | + } | |
| 763 | + | |
| 764 | + debug("route string %x\n", route); | |
| 765 | +#endif | |
| 766 | + slot_ctx->dev_info |= route; | |
| 767 | + | |
| 649 | 768 | switch (speed) { |
| 650 | 769 | case USB_SPEED_SUPER: |
| 651 | 770 | slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SS); |
| ... | ... | @@ -663,6 +782,20 @@ |
| 663 | 782 | /* Speed was set earlier, this shouldn't happen. */ |
| 664 | 783 | BUG(); |
| 665 | 784 | } |
| 785 | + | |
| 786 | +#ifdef CONFIG_DM_USB | |
| 787 | + /* Set up TT fields to support FS/LS devices */ | |
| 788 | + if (speed == USB_SPEED_LOW || speed == USB_SPEED_FULL) { | |
| 789 | + dev = dev_get_parent_priv(udev->dev); | |
| 790 | + if (dev->speed == USB_SPEED_HIGH) { | |
| 791 | + hub = dev_get_uclass_priv(udev->dev); | |
| 792 | + if (hub->tt.multi) | |
| 793 | + slot_ctx->dev_info |= cpu_to_le32(DEV_MTT); | |
| 794 | + slot_ctx->tt_info |= cpu_to_le32(TT_PORT(udev->portnr)); | |
| 795 | + slot_ctx->tt_info |= cpu_to_le32(TT_SLOT(dev->slot_id)); | |
| 796 | + } | |
| 797 | + } | |
| 798 | +#endif | |
| 666 | 799 | |
| 667 | 800 | port_num = hop_portnr; |
| 668 | 801 | debug("port_num = %d\n", port_num); |
drivers/usb/host/xhci-pci.c
| ... | ... | @@ -8,66 +8,10 @@ |
| 8 | 8 | |
| 9 | 9 | #include <common.h> |
| 10 | 10 | #include <dm.h> |
| 11 | -#include <errno.h> | |
| 12 | 11 | #include <pci.h> |
| 13 | 12 | #include <usb.h> |
| 14 | - | |
| 15 | 13 | #include "xhci.h" |
| 16 | 14 | |
| 17 | -#ifndef CONFIG_DM_USB | |
| 18 | - | |
| 19 | -/* | |
| 20 | - * Create the appropriate control structures to manage a new XHCI host | |
| 21 | - * controller. | |
| 22 | - */ | |
| 23 | -int xhci_hcd_init(int index, struct xhci_hccr **ret_hccr, | |
| 24 | - struct xhci_hcor **ret_hcor) | |
| 25 | -{ | |
| 26 | - struct xhci_hccr *hccr; | |
| 27 | - struct xhci_hcor *hcor; | |
| 28 | - pci_dev_t pdev; | |
| 29 | - uint32_t cmd; | |
| 30 | - int len; | |
| 31 | - | |
| 32 | - pdev = pci_find_class(PCI_CLASS_SERIAL_USB_XHCI, index); | |
| 33 | - if (pdev < 0) { | |
| 34 | - printf("XHCI host controller not found\n"); | |
| 35 | - return -1; | |
| 36 | - } | |
| 37 | - | |
| 38 | - hccr = (struct xhci_hccr *)pci_map_bar(pdev, | |
| 39 | - PCI_BASE_ADDRESS_0, PCI_REGION_MEM); | |
| 40 | - len = HC_LENGTH(xhci_readl(&hccr->cr_capbase)); | |
| 41 | - hcor = (struct xhci_hcor *)((uint32_t)hccr + len); | |
| 42 | - | |
| 43 | - debug("XHCI-PCI init hccr 0x%x and hcor 0x%x hc_length %d\n", | |
| 44 | - (uint32_t)hccr, (uint32_t)hcor, len); | |
| 45 | - | |
| 46 | - *ret_hccr = hccr; | |
| 47 | - *ret_hcor = hcor; | |
| 48 | - | |
| 49 | - /* enable busmaster */ | |
| 50 | - pci_read_config_dword(pdev, PCI_COMMAND, &cmd); | |
| 51 | - cmd |= PCI_COMMAND_MASTER; | |
| 52 | - pci_write_config_dword(pdev, PCI_COMMAND, cmd); | |
| 53 | - | |
| 54 | - return 0; | |
| 55 | -} | |
| 56 | - | |
| 57 | -/* | |
| 58 | - * Destroy the appropriate control structures corresponding * to the XHCI host | |
| 59 | - * controller | |
| 60 | - */ | |
| 61 | -void xhci_hcd_stop(int index) | |
| 62 | -{ | |
| 63 | -} | |
| 64 | - | |
| 65 | -#else | |
| 66 | - | |
| 67 | -struct xhci_pci_priv { | |
| 68 | - struct xhci_ctrl ctrl; /* Needs to come first in this struct! */ | |
| 69 | -}; | |
| 70 | - | |
| 71 | 15 | static void xhci_pci_init(struct udevice *dev, struct xhci_hccr **ret_hccr, |
| 72 | 16 | struct xhci_hcor **ret_hcor) |
| 73 | 17 | { |
| ... | ... | @@ -103,17 +47,6 @@ |
| 103 | 47 | return xhci_register(dev, hccr, hcor); |
| 104 | 48 | } |
| 105 | 49 | |
| 106 | -static int xhci_pci_remove(struct udevice *dev) | |
| 107 | -{ | |
| 108 | - int ret; | |
| 109 | - | |
| 110 | - ret = xhci_deregister(dev); | |
| 111 | - if (ret) | |
| 112 | - return ret; | |
| 113 | - | |
| 114 | - return 0; | |
| 115 | -} | |
| 116 | - | |
| 117 | 50 | static const struct udevice_id xhci_pci_ids[] = { |
| 118 | 51 | { .compatible = "xhci-pci" }, |
| 119 | 52 | { } |
| 120 | 53 | |
| ... | ... | @@ -123,11 +56,11 @@ |
| 123 | 56 | .name = "xhci_pci", |
| 124 | 57 | .id = UCLASS_USB, |
| 125 | 58 | .probe = xhci_pci_probe, |
| 126 | - .remove = xhci_pci_remove, | |
| 59 | + .remove = xhci_deregister, | |
| 127 | 60 | .of_match = xhci_pci_ids, |
| 128 | 61 | .ops = &xhci_usb_ops, |
| 129 | 62 | .platdata_auto_alloc_size = sizeof(struct usb_platdata), |
| 130 | - .priv_auto_alloc_size = sizeof(struct xhci_pci_priv), | |
| 63 | + .priv_auto_alloc_size = sizeof(struct xhci_ctrl), | |
| 131 | 64 | .flags = DM_FLAG_ALLOC_PRIV_DMA, |
| 132 | 65 | }; |
| 133 | 66 | |
| ... | ... | @@ -137,6 +70,4 @@ |
| 137 | 70 | }; |
| 138 | 71 | |
| 139 | 72 | U_BOOT_PCI_DEVICE(xhci_pci, xhci_pci_supported); |
| 140 | - | |
| 141 | -#endif /* CONFIG_DM_USB */ |
drivers/usb/host/xhci-ring.c
| ... | ... | @@ -280,8 +280,15 @@ |
| 280 | 280 | fields[0] = lower_32_bits(val_64); |
| 281 | 281 | fields[1] = upper_32_bits(val_64); |
| 282 | 282 | fields[2] = 0; |
| 283 | - fields[3] = TRB_TYPE(cmd) | EP_ID_FOR_TRB(ep_index) | | |
| 284 | - SLOT_ID_FOR_TRB(slot_id) | ctrl->cmd_ring->cycle_state; | |
| 283 | + fields[3] = TRB_TYPE(cmd) | SLOT_ID_FOR_TRB(slot_id) | | |
| 284 | + ctrl->cmd_ring->cycle_state; | |
| 285 | + | |
| 286 | + /* | |
| 287 | + * Only 'reset endpoint', 'stop endpoint' and 'set TR dequeue pointer' | |
| 288 | + * commands need endpoint id encoded. | |
| 289 | + */ | |
| 290 | + if (cmd >= TRB_RESET_EP && cmd <= TRB_SET_DEQ) | |
| 291 | + fields[3] |= EP_ID_FOR_TRB(ep_index); | |
| 285 | 292 | |
| 286 | 293 | queue_trb(ctrl, ctrl->cmd_ring, false, fields); |
| 287 | 294 |
drivers/usb/host/xhci.c
| ... | ... | @@ -50,8 +50,8 @@ |
| 50 | 50 | cpu_to_le16(0x8), /* wHubCharacteristics */ |
| 51 | 51 | 10, /* bPwrOn2PwrGood */ |
| 52 | 52 | 0, /* bHubCntrCurrent */ |
| 53 | - {}, /* Device removable */ | |
| 54 | - {} /* at most 7 ports! XXX */ | |
| 53 | + { /* Device removable */ | |
| 54 | + } /* at most 7 ports! XXX */ | |
| 55 | 55 | }, |
| 56 | 56 | { |
| 57 | 57 | 0x12, /* bLength */ |
| ... | ... | @@ -192,7 +192,7 @@ |
| 192 | 192 | * @param hcor pointer to host controller operation registers |
| 193 | 193 | * @return -EBUSY if XHCI Controller is not halted else status of handshake |
| 194 | 194 | */ |
| 195 | -int xhci_reset(struct xhci_hcor *hcor) | |
| 195 | +static int xhci_reset(struct xhci_hcor *hcor) | |
| 196 | 196 | { |
| 197 | 197 | u32 cmd; |
| 198 | 198 | u32 state; |
| ... | ... | @@ -332,8 +332,8 @@ |
| 332 | 332 | ifdesc = &udev->config.if_desc[0]; |
| 333 | 333 | |
| 334 | 334 | ctrl_ctx = xhci_get_input_control_ctx(in_ctx); |
| 335 | - /* Zero the input context control */ | |
| 336 | - ctrl_ctx->add_flags = 0; | |
| 335 | + /* Initialize the input context control */ | |
| 336 | + ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG); | |
| 337 | 337 | ctrl_ctx->drop_flags = 0; |
| 338 | 338 | |
| 339 | 339 | /* EP_FLAG gives values 1 & 4 for EP1OUT and EP2IN */ |
| ... | ... | @@ -415,8 +415,7 @@ |
| 415 | 415 | * so setting up the slot context. |
| 416 | 416 | */ |
| 417 | 417 | debug("Setting up addressable devices %p\n", ctrl->dcbaa); |
| 418 | - xhci_setup_addressable_virt_dev(ctrl, udev->slot_id, udev->speed, | |
| 419 | - root_portnr); | |
| 418 | + xhci_setup_addressable_virt_dev(ctrl, udev, root_portnr); | |
| 420 | 419 | |
| 421 | 420 | ctrl_ctx = xhci_get_input_control_ctx(virt_dev->in_ctx); |
| 422 | 421 | ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG); |
| ... | ... | @@ -481,7 +480,7 @@ |
| 481 | 480 | * @param udev pointer to the Device Data Structure |
| 482 | 481 | * @return Returns 0 on succes else return error code on failure |
| 483 | 482 | */ |
| 484 | -int _xhci_alloc_device(struct usb_device *udev) | |
| 483 | +static int _xhci_alloc_device(struct usb_device *udev) | |
| 485 | 484 | { |
| 486 | 485 | struct xhci_ctrl *ctrl = xhci_get_ctrl(udev); |
| 487 | 486 | union xhci_trb *event; |
| 488 | 487 | |
| 489 | 488 | |
| ... | ... | @@ -668,12 +667,14 @@ |
| 668 | 667 | uint32_t reg; |
| 669 | 668 | volatile uint32_t *status_reg; |
| 670 | 669 | struct xhci_ctrl *ctrl = xhci_get_ctrl(udev); |
| 670 | + struct xhci_hccr *hccr = ctrl->hccr; | |
| 671 | 671 | struct xhci_hcor *hcor = ctrl->hcor; |
| 672 | + int max_ports = HCS_MAX_PORTS(xhci_readl(&hccr->cr_hcsparams1)); | |
| 672 | 673 | |
| 673 | 674 | if ((req->requesttype & USB_RT_PORT) && |
| 674 | - le16_to_cpu(req->index) > CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS) { | |
| 675 | - printf("The request port(%d) is not configured\n", | |
| 676 | - le16_to_cpu(req->index) - 1); | |
| 675 | + le16_to_cpu(req->index) > max_ports) { | |
| 676 | + printf("The request port(%d) exceeds maximum port number\n", | |
| 677 | + le16_to_cpu(req->index) - 1); | |
| 677 | 678 | return -EINVAL; |
| 678 | 679 | } |
| 679 | 680 | |
| ... | ... | @@ -727,6 +728,7 @@ |
| 727 | 728 | case USB_REQ_GET_DESCRIPTOR | ((USB_DIR_IN | USB_RT_HUB) << 8): |
| 728 | 729 | switch (le16_to_cpu(req->value) >> 8) { |
| 729 | 730 | case USB_DT_HUB: |
| 731 | + case USB_DT_SS_HUB: | |
| 730 | 732 | debug("USB_DT_HUB config\n"); |
| 731 | 733 | srcptr = &descriptor.hub; |
| 732 | 734 | srclen = 0x8; |
| 733 | 735 | |
| ... | ... | @@ -1113,27 +1115,7 @@ |
| 1113 | 1115 | #endif /* CONFIG_DM_USB */ |
| 1114 | 1116 | |
| 1115 | 1117 | #ifdef CONFIG_DM_USB |
| 1116 | -/* | |
| 1117 | -static struct usb_device *get_usb_device(struct udevice *dev) | |
| 1118 | -{ | |
| 1119 | - struct usb_device *udev; | |
| 1120 | 1118 | |
| 1121 | - if (device_get_uclass_id(dev) == UCLASS_USB) | |
| 1122 | - udev = dev_get_uclass_priv(dev); | |
| 1123 | - else | |
| 1124 | - udev = dev_get_parent_priv(dev); | |
| 1125 | - | |
| 1126 | - return udev; | |
| 1127 | -} | |
| 1128 | -*/ | |
| 1129 | -static bool is_root_hub(struct udevice *dev) | |
| 1130 | -{ | |
| 1131 | - if (device_get_uclass_id(dev->parent) != UCLASS_USB_HUB) | |
| 1132 | - return true; | |
| 1133 | - | |
| 1134 | - return false; | |
| 1135 | -} | |
| 1136 | - | |
| 1137 | 1119 | static int xhci_submit_control_msg(struct udevice *dev, struct usb_device *udev, |
| 1138 | 1120 | unsigned long pipe, void *buffer, int length, |
| 1139 | 1121 | struct devrequest *setup) |
| 1140 | 1122 | |
| ... | ... | @@ -1147,10 +1129,10 @@ |
| 1147 | 1129 | hub = udev->dev; |
| 1148 | 1130 | if (device_get_uclass_id(hub) == UCLASS_USB_HUB) { |
| 1149 | 1131 | /* Figure out our port number on the root hub */ |
| 1150 | - if (is_root_hub(hub)) { | |
| 1132 | + if (usb_hub_is_root_hub(hub)) { | |
| 1151 | 1133 | root_portnr = udev->portnr; |
| 1152 | 1134 | } else { |
| 1153 | - while (!is_root_hub(hub->parent)) | |
| 1135 | + while (!usb_hub_is_root_hub(hub->parent)) | |
| 1154 | 1136 | hub = hub->parent; |
| 1155 | 1137 | uhop = dev_get_parent_priv(hub); |
| 1156 | 1138 | root_portnr = uhop->portnr; |
| ... | ... | @@ -1188,6 +1170,64 @@ |
| 1188 | 1170 | return _xhci_alloc_device(udev); |
| 1189 | 1171 | } |
| 1190 | 1172 | |
| 1173 | +static int xhci_update_hub_device(struct udevice *dev, struct usb_device *udev) | |
| 1174 | +{ | |
| 1175 | + struct xhci_ctrl *ctrl = dev_get_priv(dev); | |
| 1176 | + struct usb_hub_device *hub = dev_get_uclass_priv(udev->dev); | |
| 1177 | + struct xhci_virt_device *virt_dev; | |
| 1178 | + struct xhci_input_control_ctx *ctrl_ctx; | |
| 1179 | + struct xhci_container_ctx *out_ctx; | |
| 1180 | + struct xhci_container_ctx *in_ctx; | |
| 1181 | + struct xhci_slot_ctx *slot_ctx; | |
| 1182 | + int slot_id = udev->slot_id; | |
| 1183 | + unsigned think_time; | |
| 1184 | + | |
| 1185 | + debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev); | |
| 1186 | + | |
| 1187 | + /* Ignore root hubs */ | |
| 1188 | + if (usb_hub_is_root_hub(udev->dev)) | |
| 1189 | + return 0; | |
| 1190 | + | |
| 1191 | + virt_dev = ctrl->devs[slot_id]; | |
| 1192 | + BUG_ON(!virt_dev); | |
| 1193 | + | |
| 1194 | + out_ctx = virt_dev->out_ctx; | |
| 1195 | + in_ctx = virt_dev->in_ctx; | |
| 1196 | + | |
| 1197 | + ctrl_ctx = xhci_get_input_control_ctx(in_ctx); | |
| 1198 | + /* Initialize the input context control */ | |
| 1199 | + ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG); | |
| 1200 | + ctrl_ctx->drop_flags = 0; | |
| 1201 | + | |
| 1202 | + xhci_inval_cache((uintptr_t)out_ctx->bytes, out_ctx->size); | |
| 1203 | + | |
| 1204 | + /* slot context */ | |
| 1205 | + xhci_slot_copy(ctrl, in_ctx, out_ctx); | |
| 1206 | + slot_ctx = xhci_get_slot_ctx(ctrl, in_ctx); | |
| 1207 | + | |
| 1208 | + /* Update hub related fields */ | |
| 1209 | + slot_ctx->dev_info |= cpu_to_le32(DEV_HUB); | |
| 1210 | + if (hub->tt.multi && udev->speed == USB_SPEED_HIGH) | |
| 1211 | + slot_ctx->dev_info |= cpu_to_le32(DEV_MTT); | |
| 1212 | + slot_ctx->dev_info2 |= cpu_to_le32(XHCI_MAX_PORTS(udev->maxchild)); | |
| 1213 | + /* | |
| 1214 | + * Set TT think time - convert from ns to FS bit times. | |
| 1215 | + * Note 8 FS bit times == (8 bits / 12000000 bps) ~= 666ns | |
| 1216 | + * | |
| 1217 | + * 0 = 8 FS bit times, 1 = 16 FS bit times, | |
| 1218 | + * 2 = 24 FS bit times, 3 = 32 FS bit times. | |
| 1219 | + * | |
| 1220 | + * This field shall be 0 if the device is not a high-spped hub. | |
| 1221 | + */ | |
| 1222 | + think_time = hub->tt.think_time; | |
| 1223 | + if (think_time != 0) | |
| 1224 | + think_time = (think_time / 666) - 1; | |
| 1225 | + if (udev->speed == USB_SPEED_HIGH) | |
| 1226 | + slot_ctx->tt_info |= cpu_to_le32(TT_THINK_TIME(think_time)); | |
| 1227 | + | |
| 1228 | + return xhci_configure_endpoints(udev, false); | |
| 1229 | +} | |
| 1230 | + | |
| 1191 | 1231 | int xhci_register(struct udevice *dev, struct xhci_hccr *hccr, |
| 1192 | 1232 | struct xhci_hcor *hcor) |
| 1193 | 1233 | { |
| ... | ... | @@ -1240,6 +1280,7 @@ |
| 1240 | 1280 | .bulk = xhci_submit_bulk_msg, |
| 1241 | 1281 | .interrupt = xhci_submit_int_msg, |
| 1242 | 1282 | .alloc_device = xhci_alloc_device, |
| 1283 | + .update_hub_device = xhci_update_hub_device, | |
| 1243 | 1284 | }; |
| 1244 | 1285 | |
| 1245 | 1286 | #endif |
drivers/usb/host/xhci.h
| ... | ... | @@ -30,7 +30,7 @@ |
| 30 | 30 | /* Max number of USB devices for any host controller - limit in section 6.1 */ |
| 31 | 31 | #define MAX_HC_SLOTS 256 |
| 32 | 32 | /* Section 5.3.3 - MaxPorts */ |
| 33 | -#define MAX_HC_PORTS 127 | |
| 33 | +#define MAX_HC_PORTS 255 | |
| 34 | 34 | |
| 35 | 35 | /* Up to 16 ms to halt an HC */ |
| 36 | 36 | #define XHCI_MAX_HALT_USEC (16*1000) |
| ... | ... | @@ -102,8 +102,8 @@ |
| 102 | 102 | #define HCS_MAX_INTRS(p) (((p) >> 8) & 0x7ff) |
| 103 | 103 | /* bits 24:31, Max Ports - max value is 0x7F = 127 ports */ |
| 104 | 104 | #define HCS_MAX_PORTS_SHIFT 24 |
| 105 | -#define HCS_MAX_PORTS_MASK (0x7f << HCS_MAX_PORTS_SHIFT) | |
| 106 | -#define HCS_MAX_PORTS(p) (((p) >> 24) & 0x7f) | |
| 105 | +#define HCS_MAX_PORTS_MASK (0xff << HCS_MAX_PORTS_SHIFT) | |
| 106 | +#define HCS_MAX_PORTS(p) (((p) >> 24) & 0xff) | |
| 107 | 107 | |
| 108 | 108 | /* HCSPARAMS2 - hcs_params2 - bitmasks */ |
| 109 | 109 | /* bits 0:3, frames or uframes that SW needs to queue transactions |
| 110 | 110 | |
| ... | ... | @@ -111,9 +111,10 @@ |
| 111 | 111 | #define HCS_IST(p) (((p) >> 0) & 0xf) |
| 112 | 112 | /* bits 4:7, max number of Event Ring segments */ |
| 113 | 113 | #define HCS_ERST_MAX(p) (((p) >> 4) & 0xf) |
| 114 | +/* bits 21:25 Hi 5 bits of Scratchpad buffers SW must allocate for the HW */ | |
| 114 | 115 | /* bit 26 Scratchpad restore - for save/restore HW state - not used yet */ |
| 115 | -/* bits 27:31 number of Scratchpad buffers SW must allocate for the HW */ | |
| 116 | -#define HCS_MAX_SCRATCHPAD(p) (((p) >> 27) & 0x1f) | |
| 116 | +/* bits 27:31 Lo 5 bits of Scratchpad buffers SW must allocate for the HW */ | |
| 117 | +#define HCS_MAX_SCRATCHPAD(p) ((((p) >> 16) & 0x3e0) | (((p) >> 27) & 0x1f)) | |
| 117 | 118 | |
| 118 | 119 | /* HCSPARAMS3 - hcs_params3 - bitmasks */ |
| 119 | 120 | /* bits 0:7, Max U1 to U0 latency for the roothub ports */ |
| ... | ... | @@ -171,9 +172,7 @@ |
| 171 | 172 | volatile uint64_t or_dcbaap; |
| 172 | 173 | volatile uint32_t or_config; |
| 173 | 174 | volatile uint32_t reserved_2[241]; |
| 174 | - struct xhci_hcor_port_regs portregs[CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS]; | |
| 175 | - | |
| 176 | - uint32_t reserved_4[CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS * 254]; | |
| 175 | + struct xhci_hcor_port_regs portregs[MAX_HC_PORTS]; | |
| 177 | 176 | }; |
| 178 | 177 | |
| 179 | 178 | /* USBCMD - USB command - command bitmasks */ |
| 180 | 179 | |
| ... | ... | @@ -482,10 +481,9 @@ |
| 482 | 481 | * @type: Type of context. Used to calculated offsets to contained contexts. |
| 483 | 482 | * @size: Size of the context data |
| 484 | 483 | * @bytes: The raw context data given to HW |
| 485 | - * @dma: dma address of the bytes | |
| 486 | 484 | * |
| 487 | 485 | * Represents either a Device or Input context. Holds a pointer to the raw |
| 488 | - * memory used for the context (bytes) and dma address of it (dma). | |
| 486 | + * memory used for the context (bytes). | |
| 489 | 487 | */ |
| 490 | 488 | struct xhci_container_ctx { |
| 491 | 489 | unsigned type; |
| 492 | 490 | |
| ... | ... | @@ -550,12 +548,12 @@ |
| 550 | 548 | * The Slot ID of the hub that isolates the high speed signaling from |
| 551 | 549 | * this low or full-speed device. '0' if attached to root hub port. |
| 552 | 550 | */ |
| 553 | -#define TT_SLOT (0xff) | |
| 551 | +#define TT_SLOT(p) (((p) & 0xff) << 0) | |
| 554 | 552 | /* |
| 555 | 553 | * The number of the downstream facing port of the high-speed hub |
| 556 | 554 | * '0' if the device is not low or full speed. |
| 557 | 555 | */ |
| 558 | -#define TT_PORT (0xff << 8) | |
| 556 | +#define TT_PORT(p) (((p) & 0xff) << 8) | |
| 559 | 557 | #define TT_THINK_TIME(p) (((p) & 0x3) << 16) |
| 560 | 558 | |
| 561 | 559 | /* dev_state bitmasks */ |
| ... | ... | @@ -1038,6 +1036,10 @@ |
| 1038 | 1036 | unsigned int erst_size; |
| 1039 | 1037 | }; |
| 1040 | 1038 | |
| 1039 | +struct xhci_scratchpad { | |
| 1040 | + u64 *sp_array; | |
| 1041 | +}; | |
| 1042 | + | |
| 1041 | 1043 | /* |
| 1042 | 1044 | * Each segment table entry is 4*32bits long. 1K seems like an ok size: |
| 1043 | 1045 | * (1K bytes * 8bytes/bit) / (4*32 bits) = 64 segment entries in the table, |
| ... | ... | @@ -1225,6 +1227,7 @@ |
| 1225 | 1227 | struct xhci_intr_reg *ir_set; |
| 1226 | 1228 | struct xhci_erst erst; |
| 1227 | 1229 | struct xhci_erst_entry entry[ERST_NUM_SEGS]; |
| 1230 | + struct xhci_scratchpad *scratchpad; | |
| 1228 | 1231 | struct xhci_virt_device *devs[MAX_HC_SLOTS]; |
| 1229 | 1232 | int rootdev; |
| 1230 | 1233 | }; |
| ... | ... | @@ -1244,8 +1247,8 @@ |
| 1244 | 1247 | void xhci_slot_copy(struct xhci_ctrl *ctrl, |
| 1245 | 1248 | struct xhci_container_ctx *in_ctx, |
| 1246 | 1249 | struct xhci_container_ctx *out_ctx); |
| 1247 | -void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, int slot_id, | |
| 1248 | - int speed, int hop_portnr); | |
| 1250 | +void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, | |
| 1251 | + struct usb_device *udev, int hop_portnr); | |
| 1249 | 1252 | void xhci_queue_command(struct xhci_ctrl *ctrl, u8 *ptr, |
| 1250 | 1253 | u32 slot_id, u32 ep_index, trb_type cmd); |
| 1251 | 1254 | void xhci_acknowledge_event(struct xhci_ctrl *ctrl); |
include/clk.h
| ... | ... | @@ -98,6 +98,21 @@ |
| 98 | 98 | * @return 0 if OK, or a negative error code. |
| 99 | 99 | */ |
| 100 | 100 | int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk); |
| 101 | + | |
| 102 | +/** | |
| 103 | + * clk_release_all() - Disable (turn off)/Free an array of previously | |
| 104 | + * requested clocks. | |
| 105 | + * | |
| 106 | + * For each clock contained in the clock array, this function will check if | |
| 107 | + * clock has been previously requested and then will disable and free it. | |
| 108 | + * | |
| 109 | + * @clk: A clock struct array that was previously successfully | |
| 110 | + * requested by clk_request/get_by_*(). | |
| 111 | + * @count Number of clock contained in the array | |
| 112 | + * @return zero on success, or -ve error code. | |
| 113 | + */ | |
| 114 | +int clk_release_all(struct clk *clk, int count); | |
| 115 | + | |
| 101 | 116 | #else |
| 102 | 117 | static inline int clk_get_by_index(struct udevice *dev, int index, |
| 103 | 118 | struct clk *clk) |
| ... | ... | @@ -110,6 +125,12 @@ |
| 110 | 125 | { |
| 111 | 126 | return -ENOSYS; |
| 112 | 127 | } |
| 128 | + | |
| 129 | +static inline int clk_release_all(struct clk *clk, int count) | |
| 130 | +{ | |
| 131 | + return -ENOSYS; | |
| 132 | +} | |
| 133 | + | |
| 113 | 134 | #endif |
| 114 | 135 | |
| 115 | 136 | /** |
include/configs/MPC8572DS.h
include/configs/am43xx_evm.h
| ... | ... | @@ -82,7 +82,6 @@ |
| 82 | 82 | #if defined(CONFIG_SPL_USB_HOST_SUPPORT) || !defined(CONFIG_SPL_BUILD) |
| 83 | 83 | #define CONFIG_SYS_USB_FAT_BOOT_PARTITION 1 |
| 84 | 84 | #define CONFIG_USB_XHCI_OMAP |
| 85 | -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 | |
| 86 | 85 | |
| 87 | 86 | #define CONFIG_OMAP_USB_PHY |
| 88 | 87 | #define CONFIG_AM437X_USB2PHY2_HOST |
include/configs/am57xx_evm.h
include/configs/cl-som-am57x.h
include/configs/cm_t43.h
include/configs/cm_t54.h
| ... | ... | @@ -56,7 +56,6 @@ |
| 56 | 56 | #define CONFIG_SYS_SCSI_MAX_DEVICE (CONFIG_SYS_SCSI_MAX_SCSI_ID * \ |
| 57 | 57 | CONFIG_SYS_SCSI_MAX_LUN) |
| 58 | 58 | /* USB UHH support options */ |
| 59 | -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 | |
| 60 | 59 | #define CONFIG_EHCI_HCD_INIT_AFTER_RESET |
| 61 | 60 | |
| 62 | 61 | #define CONFIG_OMAP_EHCI_PHY2_RESET_GPIO 76 /* HSIC2 HUB #RESET */ |
include/configs/corvus.h
include/configs/dra7xx_evm.h
include/configs/ds414.h
include/configs/duovero.h
include/configs/exynos5-common.h
| ... | ... | @@ -134,9 +134,6 @@ |
| 134 | 134 | /* Enable Time Command */ |
| 135 | 135 | |
| 136 | 136 | /* USB */ |
| 137 | -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 | |
| 138 | -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 | |
| 139 | - | |
| 140 | 137 | #define CONFIG_USB_HOST_ETHER |
| 141 | 138 | #define CONFIG_USB_ETHER_ASIX |
| 142 | 139 | #define CONFIG_USB_ETHER_SMSC95XX |
include/configs/ls1012afrdm.h
include/configs/ls1012aqds.h
include/configs/ls1012ardb.h
include/configs/ls1021aiot.h
include/configs/ls1021aqds.h
include/configs/ls1021atwr.h
include/configs/ls1043aqds.h
include/configs/ls1043ardb.h
include/configs/ls1046aqds.h
include/configs/ls1046ardb.h
include/configs/ls2080aqds.h
include/configs/ls2080ardb.h
include/configs/ma5d4evk.h
include/configs/mcx.h
include/configs/minnowmax.h
| ... | ... | @@ -20,7 +20,8 @@ |
| 20 | 20 | |
| 21 | 21 | #define CONFIG_STD_DEVICES_SETTINGS "stdin=usbkbd,serial\0" \ |
| 22 | 22 | "stdout=vidconsole,serial\0" \ |
| 23 | - "stderr=vidconsole,serial\0" | |
| 23 | + "stderr=vidconsole,serial\0" \ | |
| 24 | + "usb_pgood_delay=40\0" | |
| 24 | 25 | |
| 25 | 26 | #define CONFIG_SCSI_DEV_LIST \ |
| 26 | 27 | {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VALLEYVIEW_SATA}, \ |
include/configs/mvebu_armada-37xx.h
| ... | ... | @@ -93,14 +93,7 @@ |
| 93 | 93 | #define CONFIG_NET_RETRY_COUNT 50 |
| 94 | 94 | #define CONFIG_PHY_MARVELL |
| 95 | 95 | |
| 96 | -/* USB 2.0 */ | |
| 97 | -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 | |
| 98 | - | |
| 99 | -/* USB 3.0 */ | |
| 100 | -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 3 | |
| 101 | - | |
| 102 | -#define CONFIG_USB_MAX_CONTROLLER_COUNT (CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS + \ | |
| 103 | - CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS) | |
| 96 | +#define CONFIG_USB_MAX_CONTROLLER_COUNT (3 + 3) | |
| 104 | 97 | |
| 105 | 98 | /* USB ethernet */ |
| 106 | 99 | #define CONFIG_USB_HOST_ETHER |
include/configs/mvebu_armada-8k.h
| ... | ... | @@ -97,14 +97,7 @@ |
| 97 | 97 | #define CONFIG_ARP_TIMEOUT 200 |
| 98 | 98 | #define CONFIG_NET_RETRY_COUNT 50 |
| 99 | 99 | |
| 100 | -/* USB 2.0 */ | |
| 101 | -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 | |
| 102 | - | |
| 103 | -/* USB 3.0 */ | |
| 104 | -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 3 | |
| 105 | - | |
| 106 | -#define CONFIG_USB_MAX_CONTROLLER_COUNT (CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS + \ | |
| 107 | - CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS) | |
| 100 | +#define CONFIG_USB_MAX_CONTROLLER_COUNT (3 + 3) | |
| 108 | 101 | |
| 109 | 102 | /* USB ethernet */ |
| 110 | 103 | #define CONFIG_USB_HOST_ETHER |
include/configs/mx35pdk.h
include/configs/odroid.h
include/configs/omap3_beagle.h
include/configs/omap3_overo.h
include/configs/omap4_panda.h
include/configs/omap5_uevm.h
include/configs/picosam9g45.h
| ... | ... | @@ -97,9 +97,6 @@ |
| 97 | 97 | #define CONFIG_RESET_PHY_R |
| 98 | 98 | #define CONFIG_AT91_WANTS_COMMON_PHY |
| 99 | 99 | |
| 100 | -/* USB */ | |
| 101 | -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 2 | |
| 102 | - | |
| 103 | 100 | #define CONFIG_SYS_LOAD_ADDR 0x22000000 /* load address */ |
| 104 | 101 | |
| 105 | 102 | #define CONFIG_SYS_MEMTEST_START CONFIG_SYS_SDRAM_BASE |
include/configs/poplar.h
include/configs/rk3328_common.h
include/configs/rk3399_common.h
include/configs/sama5d2_ptc.h
include/configs/snapper9g45.h
include/configs/sunxi-common.h
include/configs/tam3517-common.h
include/configs/tao3530.h
include/configs/tegra114-common.h
include/configs/tegra124-common.h
include/configs/tegra20-common.h
include/configs/tegra210-common.h
include/configs/tegra30-common.h
include/configs/ti_armv7_keystone2.h
| ... | ... | @@ -193,7 +193,6 @@ |
| 193 | 193 | |
| 194 | 194 | /* USB Configuration */ |
| 195 | 195 | #define CONFIG_USB_XHCI_KEYSTONE |
| 196 | -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 | |
| 197 | 196 | #define CONFIG_USB_SS_BASE KS2_USB_SS_BASE |
| 198 | 197 | #define CONFIG_USB_HOST_XHCI_BASE KS2_USB_HOST_XHCI_BASE |
| 199 | 198 | #define CONFIG_DEV_USB_PHY_BASE KS2_DEV_USB_PHY_BASE |
include/configs/uniphier.h
include/configs/vinco.h
include/configs/x86-common.h
include/configs/xilinx_zynqmp.h
| ... | ... | @@ -90,8 +90,6 @@ |
| 90 | 90 | #define CONFIG_SYS_LOAD_ADDR 0x8000000 |
| 91 | 91 | |
| 92 | 92 | #if defined(CONFIG_ZYNQMP_USB) |
| 93 | -#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 | |
| 94 | - | |
| 95 | 93 | #define CONFIG_SYS_DFU_DATA_BUF_SIZE 0x1800000 |
| 96 | 94 | #define DFU_DEFAULT_POLL_TIMEOUT 300 |
| 97 | 95 | #define CONFIG_USB_CABLE_CHECK |
include/dfu.h
| ... | ... | @@ -110,7 +110,7 @@ |
| 110 | 110 | struct sf_internal_data sf; |
| 111 | 111 | } data; |
| 112 | 112 | |
| 113 | - long (*get_medium_size)(struct dfu_entity *dfu); | |
| 113 | + int (*get_medium_size)(struct dfu_entity *dfu, u64 *size); | |
| 114 | 114 | |
| 115 | 115 | int (*read_medium)(struct dfu_entity *dfu, |
| 116 | 116 | u64 offset, void *buf, long *len); |
| ... | ... | @@ -132,7 +132,7 @@ |
| 132 | 132 | u8 *i_buf; |
| 133 | 133 | u8 *i_buf_start; |
| 134 | 134 | u8 *i_buf_end; |
| 135 | - long r_left; | |
| 135 | + u64 r_left; | |
| 136 | 136 | long b_left; |
| 137 | 137 | |
| 138 | 138 | u32 bad_skip; /* for nand use */ |
include/dm/of_access.h
| ... | ... | @@ -353,6 +353,24 @@ |
| 353 | 353 | int index, struct of_phandle_args *out_args); |
| 354 | 354 | |
| 355 | 355 | /** |
| 356 | + * of_count_phandle_with_args() - Count the number of phandle in a list | |
| 357 | + * | |
| 358 | + * @np: pointer to a device tree node containing a list | |
| 359 | + * @list_name: property name that contains a list | |
| 360 | + * @cells_name: property name that specifies phandles' arguments count | |
| 361 | + * @return number of phandle found, -ENOENT if | |
| 362 | + * @list_name does not exist, -EINVAL if a phandle was not found, | |
| 363 | + * @cells_name could not be found, the arguments were truncated or there | |
| 364 | + * were too many arguments. | |
| 365 | + * | |
| 366 | + * Returns number of phandle found on success, on error returns appropriate | |
| 367 | + * errno value. | |
| 368 | + * | |
| 369 | + */ | |
| 370 | +int of_count_phandle_with_args(const struct device_node *np, | |
| 371 | + const char *list_name, const char *cells_name); | |
| 372 | + | |
| 373 | +/** | |
| 356 | 374 | * of_alias_scan() - Scan all properties of the 'aliases' node |
| 357 | 375 | * |
| 358 | 376 | * The function scans all the properties of the 'aliases' node and populates |
include/dm/ofnode.h
| ... | ... | @@ -435,6 +435,23 @@ |
| 435 | 435 | struct ofnode_phandle_args *out_args); |
| 436 | 436 | |
| 437 | 437 | /** |
| 438 | + * ofnode_count_phandle_with_args() - Count number of phandle in a list | |
| 439 | + * | |
| 440 | + * This function is useful to count phandles into a list. | |
| 441 | + * Returns number of phandle on success, on error returns appropriate | |
| 442 | + * errno value. | |
| 443 | + * | |
| 444 | + * @node: device tree node containing a list | |
| 445 | + * @list_name: property name that contains a list | |
| 446 | + * @cells_name: property name that specifies phandles' arguments count | |
| 447 | + * @return number of phandle on success, -ENOENT if @list_name does not | |
| 448 | + * exist, -EINVAL if a phandle was not found, @cells_name could not | |
| 449 | + * be found. | |
| 450 | + */ | |
| 451 | +int ofnode_count_phandle_with_args(ofnode node, const char *list_name, | |
| 452 | + const char *cells_name); | |
| 453 | + | |
| 454 | +/** | |
| 438 | 455 | * ofnode_path() - find a node by full path |
| 439 | 456 | * |
| 440 | 457 | * @path: Full path to node, e.g. "/bus/spi@1" |
include/dm/read.h
| ... | ... | @@ -199,6 +199,24 @@ |
| 199 | 199 | struct ofnode_phandle_args *out_args); |
| 200 | 200 | |
| 201 | 201 | /** |
| 202 | + * dev_count_phandle_with_args() - Return phandle number in a list | |
| 203 | + * | |
| 204 | + * This function is usefull to get phandle number contained in a property list. | |
| 205 | + * For example, this allows to allocate the right amount of memory to keep | |
| 206 | + * clock's reference contained into the "clocks" property. | |
| 207 | + * | |
| 208 | + * | |
| 209 | + * @dev: device whose node containing a list | |
| 210 | + * @list_name: property name that contains a list | |
| 211 | + * @cells_name: property name that specifies phandles' arguments count | |
| 212 | + * @Returns number of phandle found on success, on error returns appropriate | |
| 213 | + * errno value. | |
| 214 | + */ | |
| 215 | + | |
| 216 | +int dev_count_phandle_with_args(struct udevice *dev, const char *list_name, | |
| 217 | + const char *cells_name); | |
| 218 | + | |
| 219 | +/** | |
| 202 | 220 | * dev_read_addr_cells() - Get the number of address cells for a device's node |
| 203 | 221 | * |
| 204 | 222 | * This walks back up the tree to find the closest #address-cells property |
| ... | ... | @@ -414,6 +432,13 @@ |
| 414 | 432 | return ofnode_parse_phandle_with_args(dev_ofnode(dev), list_name, |
| 415 | 433 | cells_name, cell_count, index, |
| 416 | 434 | out_args); |
| 435 | +} | |
| 436 | + | |
| 437 | +static inline int dev_count_phandle_with_args(struct udevice *dev, | |
| 438 | + const char *list_name, const char *cells_name) | |
| 439 | +{ | |
| 440 | + return ofnode_count_phandle_with_args(dev_ofnode(dev), list_name, | |
| 441 | + cells_name); | |
| 417 | 442 | } |
| 418 | 443 | |
| 419 | 444 | static inline int dev_read_addr_cells(struct udevice *dev) |
include/generic-phy.h
| ... | ... | @@ -122,6 +122,7 @@ |
| 122 | 122 | int (*power_off)(struct phy *phy); |
| 123 | 123 | }; |
| 124 | 124 | |
| 125 | +#ifdef CONFIG_PHY | |
| 125 | 126 | |
| 126 | 127 | /** |
| 127 | 128 | * generic_phy_init() - initialize the PHY port |
| ... | ... | @@ -219,6 +220,58 @@ |
| 219 | 220 | */ |
| 220 | 221 | int generic_phy_get_by_name(struct udevice *user, const char *phy_name, |
| 221 | 222 | struct phy *phy); |
| 223 | + | |
| 224 | +#else /* CONFIG_PHY */ | |
| 225 | + | |
| 226 | +static inline int generic_phy_init(struct phy *phy) | |
| 227 | +{ | |
| 228 | + return 0; | |
| 229 | +} | |
| 230 | + | |
| 231 | +static inline int generic_phy_exit(struct phy *phy) | |
| 232 | +{ | |
| 233 | + return 0; | |
| 234 | +} | |
| 235 | + | |
| 236 | +static inline int generic_phy_reset(struct phy *phy) | |
| 237 | +{ | |
| 238 | + return 0; | |
| 239 | +} | |
| 240 | + | |
| 241 | +static inline int generic_phy_power_on(struct phy *phy) | |
| 242 | +{ | |
| 243 | + return 0; | |
| 244 | +} | |
| 245 | + | |
| 246 | +static inline int generic_phy_power_off(struct phy *phy) | |
| 247 | +{ | |
| 248 | + return 0; | |
| 249 | +} | |
| 250 | + | |
| 251 | +static inline int generic_phy_get_by_index(struct udevice *user, int index, | |
| 252 | + struct phy *phy) | |
| 253 | +{ | |
| 254 | + return 0; | |
| 255 | +} | |
| 256 | + | |
| 257 | +static inline int generic_phy_get_by_name(struct udevice *user, const char *phy_name, | |
| 258 | + struct phy *phy) | |
| 259 | +{ | |
| 260 | + return 0; | |
| 261 | +} | |
| 262 | + | |
| 263 | +#endif /* CONFIG_PHY */ | |
| 264 | + | |
| 265 | +/** | |
| 266 | + * generic_phy_valid() - check if PHY port is valid | |
| 267 | + * | |
| 268 | + * @phy: the PHY port to check | |
| 269 | + * @return TRUE if valid, or FALSE | |
| 270 | + */ | |
| 271 | +static inline bool generic_phy_valid(struct phy *phy) | |
| 272 | +{ | |
| 273 | + return phy->dev != NULL; | |
| 274 | +} | |
| 222 | 275 | |
| 223 | 276 | #endif /*__GENERIC_PHY_H */ |
include/reset.h
| ... | ... | @@ -100,6 +100,15 @@ |
| 100 | 100 | struct reset_ctl *reset_ctl); |
| 101 | 101 | |
| 102 | 102 | /** |
| 103 | + * reset_request - Request a reset signal. | |
| 104 | + * | |
| 105 | + * @reset_ctl: A reset control struct. | |
| 106 | + * | |
| 107 | + * @return 0 if OK, or a negative error code. | |
| 108 | + */ | |
| 109 | +int reset_request(struct reset_ctl *reset_ctl); | |
| 110 | + | |
| 111 | +/** | |
| 103 | 112 | * reset_free - Free a previously requested reset signal. |
| 104 | 113 | * |
| 105 | 114 | * @reset_ctl: A reset control struct that was previously successfully |
| ... | ... | @@ -135,6 +144,18 @@ |
| 135 | 144 | */ |
| 136 | 145 | int reset_deassert(struct reset_ctl *reset_ctl); |
| 137 | 146 | |
| 147 | +/** | |
| 148 | + * reset_release_all - Assert/Free an array of previously requested resets. | |
| 149 | + * | |
| 150 | + * For each reset contained in the reset array, this function will check if | |
| 151 | + * reset has been previously requested and then will assert and free it. | |
| 152 | + * | |
| 153 | + * @reset_ctl: A reset struct array that was previously successfully | |
| 154 | + * requested by reset_get_by_*(). | |
| 155 | + * @count Number of reset contained in the array | |
| 156 | + * @return 0 if OK, or a negative error code. | |
| 157 | + */ | |
| 158 | +int reset_release_all(struct reset_ctl *reset_ctl, int count); | |
| 138 | 159 | #else |
| 139 | 160 | static inline int reset_get_by_index(struct udevice *dev, int index, |
| 140 | 161 | struct reset_ctl *reset_ctl) |
| ... | ... | @@ -162,6 +183,12 @@ |
| 162 | 183 | { |
| 163 | 184 | return 0; |
| 164 | 185 | } |
| 186 | + | |
| 187 | +static inline int reset_release_all(struct reset_ctl *reset_ctl, int count) | |
| 188 | +{ | |
| 189 | + return 0; | |
| 190 | +} | |
| 191 | + | |
| 165 | 192 | #endif |
| 166 | 193 | |
| 167 | 194 | #endif |
include/usb.h
| ... | ... | @@ -537,7 +537,22 @@ |
| 537 | 537 | unsigned short wHubChange; |
| 538 | 538 | } __attribute__ ((packed)); |
| 539 | 539 | |
| 540 | +/* | |
| 541 | + * Hub Device descriptor | |
| 542 | + * USB Hub class device protocols | |
| 543 | + */ | |
| 544 | +#define USB_HUB_PR_FS 0 /* Full speed hub */ | |
| 545 | +#define USB_HUB_PR_HS_NO_TT 0 /* Hi-speed hub without TT */ | |
| 546 | +#define USB_HUB_PR_HS_SINGLE_TT 1 /* Hi-speed hub with single TT */ | |
| 547 | +#define USB_HUB_PR_HS_MULTI_TT 2 /* Hi-speed hub with multiple TT */ | |
| 548 | +#define USB_HUB_PR_SS 3 /* Super speed hub */ | |
| 540 | 549 | |
| 550 | +/* Transaction Translator Think Times, in bits */ | |
| 551 | +#define HUB_TTTT_8_BITS 0x00 | |
| 552 | +#define HUB_TTTT_16_BITS 0x20 | |
| 553 | +#define HUB_TTTT_24_BITS 0x40 | |
| 554 | +#define HUB_TTTT_32_BITS 0x60 | |
| 555 | + | |
| 541 | 556 | /* Hub descriptor */ |
| 542 | 557 | struct usb_hub_descriptor { |
| 543 | 558 | unsigned char bLength; |
| ... | ... | @@ -546,10 +561,20 @@ |
| 546 | 561 | unsigned short wHubCharacteristics; |
| 547 | 562 | unsigned char bPwrOn2PwrGood; |
| 548 | 563 | unsigned char bHubContrCurrent; |
| 549 | - unsigned char DeviceRemovable[(USB_MAXCHILDREN+1+7)/8]; | |
| 550 | - unsigned char PortPowerCtrlMask[(USB_MAXCHILDREN+1+7)/8]; | |
| 551 | - /* DeviceRemovable and PortPwrCtrlMask want to be variable-length | |
| 552 | - bitmaps that hold max 255 entries. (bit0 is ignored) */ | |
| 564 | + /* 2.0 and 3.0 hubs differ here */ | |
| 565 | + union { | |
| 566 | + struct { | |
| 567 | + /* add 1 bit for hub status change; round to bytes */ | |
| 568 | + __u8 DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8]; | |
| 569 | + __u8 PortPowerCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8]; | |
| 570 | + } __attribute__ ((packed)) hs; | |
| 571 | + | |
| 572 | + struct { | |
| 573 | + __u8 bHubHdrDecLat; | |
| 574 | + __le16 wHubDelay; | |
| 575 | + __le16 DeviceRemovable; | |
| 576 | + } __attribute__ ((packed)) ss; | |
| 577 | + } u; | |
| 553 | 578 | } __attribute__ ((packed)); |
| 554 | 579 | |
| 555 | 580 | |
| ... | ... | @@ -560,6 +585,8 @@ |
| 560 | 585 | ulong connect_timeout; /* Device connection timeout in ms */ |
| 561 | 586 | ulong query_delay; /* Device query delay in ms */ |
| 562 | 587 | int overcurrent_count[USB_MAXCHILDREN]; /* Over-current counter */ |
| 588 | + int hub_depth; /* USB 3.0 hub depth */ | |
| 589 | + struct usb_tt tt; /* Transaction Translator */ | |
| 563 | 590 | }; |
| 564 | 591 | |
| 565 | 592 | #ifdef CONFIG_DM_USB |
| ... | ... | @@ -731,6 +758,14 @@ |
| 731 | 758 | * reset_root_port() - Reset usb root port |
| 732 | 759 | */ |
| 733 | 760 | int (*reset_root_port)(struct udevice *bus, struct usb_device *udev); |
| 761 | + | |
| 762 | + /** | |
| 763 | + * update_hub_device() - Update HCD's internal representation of hub | |
| 764 | + * | |
| 765 | + * After a hub descriptor is fetched, notify HCD so that its internal | |
| 766 | + * representation of this hub can be updated (xHCI) | |
| 767 | + */ | |
| 768 | + int (*update_hub_device)(struct udevice *bus, struct usb_device *udev); | |
| 734 | 769 | }; |
| 735 | 770 | |
| 736 | 771 | #define usb_get_ops(dev) ((struct dm_usb_ops *)(dev)->driver->ops) |
| ... | ... | @@ -766,6 +801,14 @@ |
| 766 | 801 | struct usb_device *parent); |
| 767 | 802 | |
| 768 | 803 | /** |
| 804 | + * usb_hub_is_root_hub() - Test whether a hub device is root hub or not | |
| 805 | + * | |
| 806 | + * @hub: USB hub device to test | |
| 807 | + * @return: true if the hub device is root hub, false otherwise. | |
| 808 | + */ | |
| 809 | +bool usb_hub_is_root_hub(struct udevice *hub); | |
| 810 | + | |
| 811 | +/** | |
| 769 | 812 | * usb_hub_scan() - Scan a hub and find its devices |
| 770 | 813 | * |
| 771 | 814 | * @hub: Hub device to scan |
| ... | ... | @@ -861,24 +904,6 @@ |
| 861 | 904 | int usb_hub_probe(struct usb_device *dev, int ifnum); |
| 862 | 905 | void usb_hub_reset(void); |
| 863 | 906 | |
| 864 | -/** | |
| 865 | - * legacy_hub_port_reset() - reset a port given its usb_device pointer | |
| 866 | - * | |
| 867 | - * Reset a hub port and see if a device is present on that port, providing | |
| 868 | - * sufficient time for it to show itself. The port status is returned. | |
| 869 | - * | |
| 870 | - * With driver model this moves to hub_port_reset() and is passed a struct | |
| 871 | - * udevice. | |
| 872 | - * | |
| 873 | - * @dev: USB device to reset | |
| 874 | - * @port: Port number to reset (note ports are numbered from 0 here) | |
| 875 | - * @portstat: Returns port status | |
| 876 | - */ | |
| 877 | -int legacy_hub_port_reset(struct usb_device *dev, int port, | |
| 878 | - unsigned short *portstat); | |
| 879 | - | |
| 880 | -int hub_port_reset(struct udevice *dev, int port, unsigned short *portstat); | |
| 881 | - | |
| 882 | 907 | /* |
| 883 | 908 | * usb_find_usb2_hub_address_port() - Get hub address and port for TT setting |
| 884 | 909 | * |
| ... | ... | @@ -914,6 +939,17 @@ |
| 914 | 939 | int usb_alloc_device(struct usb_device *dev); |
| 915 | 940 | |
| 916 | 941 | /** |
| 942 | + * update_hub_device() - Update HCD's internal representation of hub | |
| 943 | + * | |
| 944 | + * After a hub descriptor is fetched, notify HCD so that its internal | |
| 945 | + * representation of this hub can be updated. | |
| 946 | + * | |
| 947 | + * @dev: Hub device | |
| 948 | + * @return 0 if OK, -ve on error | |
| 949 | + */ | |
| 950 | +int usb_update_hub_device(struct usb_device *dev); | |
| 951 | + | |
| 952 | +/** | |
| 917 | 953 | * usb_emul_setup_device() - Set up a new USB device emulation |
| 918 | 954 | * |
| 919 | 955 | * This is normally called when a new emulation device is bound. It tells |
| ... | ... | @@ -926,7 +962,7 @@ |
| 926 | 962 | * @desc_list: List of points or USB descriptors, terminated by NULL. |
| 927 | 963 | * The first entry must be struct usb_device_descriptor, |
| 928 | 964 | * and others follow on after that. |
| 929 | - * @return 0 if OK, -ve on error | |
| 965 | + * @return 0 if OK, -ENOSYS if not implemented, other -ve on error | |
| 930 | 966 | */ |
| 931 | 967 | int usb_emul_setup_device(struct udevice *dev, int maxpacketsize, |
| 932 | 968 | struct usb_string *strings, void **desc_list); |
include/usb_defs.h
| ... | ... | @@ -93,6 +93,7 @@ |
| 93 | 93 | #define USB_DT_REPORT (USB_TYPE_CLASS | 0x02) |
| 94 | 94 | #define USB_DT_PHYSICAL (USB_TYPE_CLASS | 0x03) |
| 95 | 95 | #define USB_DT_HUB (USB_TYPE_CLASS | 0x09) |
| 96 | +#define USB_DT_SS_HUB (USB_TYPE_CLASS | 0x0a) | |
| 96 | 97 | |
| 97 | 98 | /* Descriptor sizes per descriptor type */ |
| 98 | 99 | #define USB_DT_DEVICE_SIZE 18 |
| 99 | 100 | |
| ... | ... | @@ -261,12 +262,17 @@ |
| 261 | 262 | |
| 262 | 263 | /* |
| 263 | 264 | * Changes to wPortStatus bit field in USB 3.0 |
| 264 | - * See USB 3.0 spec Table 10-11 | |
| 265 | + * See USB 3.0 spec Table 10-10 | |
| 265 | 266 | */ |
| 266 | 267 | #define USB_SS_PORT_STAT_LINK_STATE 0x01e0 |
| 267 | 268 | #define USB_SS_PORT_STAT_POWER 0x0200 |
| 268 | 269 | #define USB_SS_PORT_STAT_SPEED 0x1c00 |
| 269 | 270 | #define USB_SS_PORT_STAT_SPEED_5GBPS 0x0000 |
| 271 | +/* Bits that are the same from USB 2.0 */ | |
| 272 | +#define USB_SS_PORT_STAT_MASK (USB_PORT_STAT_CONNECTION | \ | |
| 273 | + USB_PORT_STAT_ENABLE | \ | |
| 274 | + USB_PORT_STAT_OVERCURRENT | \ | |
| 275 | + USB_PORT_STAT_RESET) | |
| 270 | 276 | |
| 271 | 277 | /* wPortChange bits */ |
| 272 | 278 | #define USB_PORT_STAT_C_CONNECTION 0x0001 |
| ... | ... | @@ -287,6 +293,7 @@ |
| 287 | 293 | #define HUB_CHAR_LPSM 0x0003 |
| 288 | 294 | #define HUB_CHAR_COMPOUND 0x0004 |
| 289 | 295 | #define HUB_CHAR_OCPM 0x0018 |
| 296 | +#define HUB_CHAR_TTTT 0x0060 /* TT Think Time mask */ | |
| 290 | 297 | |
| 291 | 298 | /* |
| 292 | 299 | * Hub Status & Hub Change bit masks |
| ... | ... | @@ -299,6 +306,20 @@ |
| 299 | 306 | |
| 300 | 307 | /* Mask for wIndex in get/set port feature */ |
| 301 | 308 | #define USB_HUB_PORT_MASK 0xf |
| 309 | + | |
| 310 | +/* Hub class request codes */ | |
| 311 | +#define USB_REQ_SET_HUB_DEPTH 0x0c | |
| 312 | + | |
| 313 | +/* | |
| 314 | + * As of USB 2.0, full/low speed devices are segregated into trees. | |
| 315 | + * One type grows from USB 1.1 host controllers (OHCI, UHCI etc). | |
| 316 | + * The other type grows from high speed hubs when they connect to | |
| 317 | + * full/low speed devices using "Transaction Translators" (TTs). | |
| 318 | + */ | |
| 319 | +struct usb_tt { | |
| 320 | + bool multi; /* true means one TT per port */ | |
| 321 | + unsigned think_time; /* think time in ns */ | |
| 322 | +}; | |
| 302 | 323 | |
| 303 | 324 | /* |
| 304 | 325 | * CBI style |
scripts/config_whitelist.txt
| ... | ... | @@ -4868,7 +4868,6 @@ |
| 4868 | 4868 | CONFIG_SYS_USBCTRL |
| 4869 | 4869 | CONFIG_SYS_USBD_BASE |
| 4870 | 4870 | CONFIG_SYS_USB_EHCI_CPU_INIT |
| 4871 | -CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS | |
| 4872 | 4871 | CONFIG_SYS_USB_EHCI_REGS_BASE |
| 4873 | 4872 | CONFIG_SYS_USB_FAT_BOOT_PARTITION |
| 4874 | 4873 | CONFIG_SYS_USB_HOST |
| ... | ... | @@ -4877,7 +4876,6 @@ |
| 4877 | 4876 | CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS |
| 4878 | 4877 | CONFIG_SYS_USB_OHCI_REGS_BASE |
| 4879 | 4878 | CONFIG_SYS_USB_OHCI_SLOT_NAME |
| 4880 | -CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS | |
| 4881 | 4879 | CONFIG_SYS_USER_SWITCHES_BASE |
| 4882 | 4880 | CONFIG_SYS_USE_BOOT_NORFLASH |
| 4883 | 4881 | CONFIG_SYS_USE_DATAFLASH |
| ... | ... | @@ -5196,7 +5194,6 @@ |
| 5196 | 5194 | CONFIG_USB_XHCI_FSL |
| 5197 | 5195 | CONFIG_USB_XHCI_KEYSTONE |
| 5198 | 5196 | CONFIG_USB_XHCI_OMAP |
| 5199 | -CONFIG_USB_XHCI_PCI | |
| 5200 | 5197 | CONFIG_USER_LOWLEVEL_INIT |
| 5201 | 5198 | CONFIG_USE_FDT |
| 5202 | 5199 | CONFIG_USE_INTERRUPT |