Lines Matching +full:ganged +full:- +full:port +full:- +full:switching

1 // SPDX-License-Identifier: GPL-2.0+
6 * (C) Copyright Johannes Erdfelt 1999-2001
15 * Adapted for U-Boot:
51 int port; /* USB port to scan */ member
57 __weak void usb_hub_reset_devices(struct usb_hub_device *hub, int port) in usb_hub_reset_devices() argument
64 return hdev->descriptor.bDeviceProtocol == 3; in usb_hub_is_superspeed()
70 if (device_get_uclass_id(hub->parent) != UCLASS_USB_HUB) in usb_hub_is_root_hub()
79 return -EINVAL; in usb_set_hub_depth()
99 static int usb_clear_port_feature(struct usb_device *dev, int port, int feature) in usb_clear_port_feature() argument
103 port, NULL, 0, USB_CNTL_TIMEOUT); in usb_clear_port_feature()
106 static int usb_set_port_feature(struct usb_device *dev, int port, int feature) in usb_set_port_feature() argument
110 port, NULL, 0, USB_CNTL_TIMEOUT); in usb_set_port_feature()
120 int usb_get_port_status(struct usb_device *dev, int port, void *data) in usb_get_port_status() argument
125 USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port, in usb_get_port_status()
133 * Translate the USB 3.0 hub port status field into the old version in usb_get_port_status()
134 * that U-Boot understands. Do this only when the hub is not root hub. in usb_get_port_status()
135 * For root hub, the port status field has already been translated in usb_get_port_status()
141 if (!usb_hub_is_root_hub(dev->dev) && usb_hub_is_superspeed(dev)) { in usb_get_port_status()
143 u16 tmp = (status->wPortStatus) & USB_SS_PORT_STAT_MASK; in usb_get_port_status()
145 if (status->wPortStatus & USB_SS_PORT_STAT_POWER) in usb_get_port_status()
147 if ((status->wPortStatus & USB_SS_PORT_STAT_SPEED) == in usb_get_port_status()
151 status->wPortStatus = tmp; in usb_get_port_status()
163 unsigned pgood_delay = hub->desc.bPwrOn2PwrGood * 2; in usb_hub_power_on()
166 dev = hub->pusb_dev; in usb_hub_power_on()
169 for (i = 0; i < dev->maxchild; i++) { in usb_hub_power_on()
171 debug("port %d returns %lX\n", i + 1, dev->status); in usb_hub_power_on()
185 * plus spec-defined max time for device to connect in usb_hub_power_on()
187 * devices break the spec and require longer warm-up times in usb_hub_power_on()
199 hub->query_delay = get_timer(0) + max(100, (int)pgood_delay); in usb_hub_power_on()
202 * Record the power-on timeout here. The max. delay (timeout) in usb_hub_power_on()
203 * will be done based on this value in the USB port loop in in usb_hub_power_on()
206 hub->connect_timeout = hub->query_delay + 1000; in usb_hub_power_on()
208 dev->devnum, max(100, (int)pgood_delay), in usb_hub_power_on()
220 /* Zero out global hub_dev in case its re-used again */ in usb_hub_reset()
259 * usb_hub_port_reset() - reset a port given its usb_device pointer
261 * Reset a hub port and see if a device is present on that port, providing
262 * sufficient time for it to show itself. The port status is returned.
265 * @port: Port number to reset (note ports are numbered from 0 here)
266 * @portstat: Returns port status
268 static int usb_hub_port_reset(struct usb_device *dev, int port, in usb_hub_port_reset() argument
277 debug("%s: resetting '%s' port %d...\n", __func__, dev->dev->name, in usb_hub_port_reset()
278 port + 1); in usb_hub_port_reset()
280 debug("%s: resetting port %d...\n", __func__, port + 1); in usb_hub_port_reset()
283 err = usb_set_port_feature(dev, port + 1, USB_PORT_FEAT_RESET); in usb_hub_port_reset()
289 if (usb_get_port_status(dev, port + 1, portsts) < 0) { in usb_hub_port_reset()
291 dev->status); in usb_hub_port_reset()
292 return -1; in usb_hub_port_reset()
294 portstatus = le16_to_cpu(portsts->wPortStatus); in usb_hub_port_reset()
295 portchange = le16_to_cpu(portsts->wPortChange); in usb_hub_port_reset()
308 * - C_CONNECTION hasn't been set. in usb_hub_port_reset()
309 * - CONNECTION is still set. in usb_hub_port_reset()
331 debug("Cannot enable port %i after %i retries, " \ in usb_hub_port_reset()
332 "disabling port.\n", port + 1, MAX_TRIES); in usb_hub_port_reset()
334 return -1; in usb_hub_port_reset()
337 usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_RESET); in usb_hub_port_reset()
342 int usb_hub_port_connect_change(struct usb_device *dev, int port) in usb_hub_port_connect_change() argument
349 ret = usb_get_port_status(dev, port + 1, portsts); in usb_hub_port_connect_change()
355 portstatus = le16_to_cpu(portsts->wPortStatus); in usb_hub_port_connect_change()
358 le16_to_cpu(portsts->wPortChange), in usb_hub_port_connect_change()
362 usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_CONNECTION); in usb_hub_port_connect_change()
364 /* Disconnect any existing devices under this port */ in usb_hub_port_connect_change()
367 usb_device_has_child_on_port(dev, port)) { in usb_hub_port_connect_change()
368 debug("usb_disconnect(&hub->children[port]);\n"); in usb_hub_port_connect_change()
371 return -ENOTCONN; in usb_hub_port_connect_change()
374 /* Reset the port */ in usb_hub_port_connect_change()
375 ret = usb_hub_port_reset(dev, port, &portstatus); in usb_hub_port_connect_change()
377 if (ret != -ENXIO) in usb_hub_port_connect_change()
378 printf("cannot reset port %i!?\n", port + 1); in usb_hub_port_connect_change()
400 ret = usb_scan_device(dev->dev, port + 1, speed, &child); in usb_hub_port_connect_change()
404 ret = usb_alloc_new_device(dev->controller, &usb); in usb_hub_port_connect_change()
410 dev->children[port] = usb; in usb_hub_port_connect_change()
411 usb->speed = speed; in usb_hub_port_connect_change()
412 usb->parent = dev; in usb_hub_port_connect_change()
413 usb->portnr = port + 1; in usb_hub_port_connect_change()
417 /* Woops, disable the port */ in usb_hub_port_connect_change()
418 usb_free_device(dev->controller); in usb_hub_port_connect_change()
419 dev->children[port] = NULL; in usb_hub_port_connect_change()
423 debug("hub: disabling port %d\n", port + 1); in usb_hub_port_connect_change()
424 usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_ENABLE); in usb_hub_port_connect_change()
440 dev = usb_scan->dev; in usb_scan_port()
441 hub = usb_scan->hub; in usb_scan_port()
442 i = usb_scan->port; in usb_scan_port()
448 if (get_timer(0) < hub->query_delay) in usb_scan_port()
454 if (get_timer(0) >= hub->connect_timeout) { in usb_scan_port()
455 debug("devnum=%d port=%d: timeout\n", in usb_scan_port()
456 dev->devnum, i + 1); in usb_scan_port()
458 list_del(&usb_scan->list); in usb_scan_port()
465 portstatus = le16_to_cpu(portsts->wPortStatus); in usb_scan_port()
466 portchange = le16_to_cpu(portsts->wPortChange); in usb_scan_port()
467 debug("Port %d Status %X Change %X\n", i + 1, portstatus, portchange); in usb_scan_port()
473 * device is connected to the port (eg: CCS bit is set but CSC is not in usb_scan_port()
478 if (get_timer(0) >= hub->connect_timeout) { in usb_scan_port()
479 debug("devnum=%d port=%d: timeout\n", in usb_scan_port()
480 dev->devnum, i + 1); in usb_scan_port()
482 list_del(&usb_scan->list); in usb_scan_port()
490 debug("port %d reset change\n", i + 1); in usb_scan_port()
496 debug("port %d BH reset change\n", i + 1); in usb_scan_port()
501 debug("devnum=%d port=%d: USB dev found\n", dev->devnum, i + 1); in usb_scan_port()
506 debug("port %d enable change, status %x\n", i + 1, portstatus); in usb_scan_port()
521 debug("already running port %i disabled by hub (EMI?), re-enabling...\n", in usb_scan_port()
529 debug("port %d suspend change\n", i + 1); in usb_scan_port()
534 debug("port %d over-current change\n", i + 1); in usb_scan_port()
537 /* Only power-on this one port */ in usb_scan_port()
539 hub->overcurrent_count[i]++; in usb_scan_port()
542 * If the max-scan-count is not reached, return without removing in usb_scan_port()
543 * the device from scan-list. This will re-issue a new scan. in usb_scan_port()
545 if (hub->overcurrent_count[i] <= in usb_scan_port()
550 printf("Port %d over-current occurred %d times\n", i + 1, in usb_scan_port()
551 hub->overcurrent_count[i]); in usb_scan_port()
558 list_del(&usb_scan->list); in usb_scan_port()
585 /* Scan this port */ in usb_device_list_scan()
611 hub = dev_get_uclass_priv(dev->dev); in usb_get_hub_device()
630 return -ENOMEM; in usb_hub_configure()
631 hub->pusb_dev = dev; in usb_hub_configure()
637 "descriptor, giving up %lX\n", dev->status); in usb_hub_configure()
642 length = min_t(int, descriptor->bLength, in usb_hub_configure()
648 "descriptor 2nd giving up %lX\n", dev->status); in usb_hub_configure()
651 memcpy((unsigned char *)&hub->desc, buffer, length); in usb_hub_configure()
654 &descriptor->wHubCharacteristics)), in usb_hub_configure()
655 &hub->desc.wHubCharacteristics); in usb_hub_configure()
657 bitmap = (unsigned char *)&hub->desc.u.hs.DeviceRemovable[0]; in usb_hub_configure()
660 bitmap = (unsigned char *)&hub->desc.u.hs.PortPowerCtrlMask[0]; in usb_hub_configure()
663 for (i = 0; i < ((hub->desc.bNbrPorts + 1 + 7)/8); i++) in usb_hub_configure()
664 hub->desc.u.hs.DeviceRemovable[i] = in usb_hub_configure()
665 descriptor->u.hs.DeviceRemovable[i]; in usb_hub_configure()
667 for (i = 0; i < ((hub->desc.bNbrPorts + 1 + 7)/8); i++) in usb_hub_configure()
668 hub->desc.u.hs.PortPowerCtrlMask[i] = in usb_hub_configure()
669 descriptor->u.hs.PortPowerCtrlMask[i]; in usb_hub_configure()
671 dev->maxchild = descriptor->bNbrPorts; in usb_hub_configure()
672 debug("%d ports detected\n", dev->maxchild); in usb_hub_configure()
674 hubCharacteristics = get_unaligned(&hub->desc.wHubCharacteristics); in usb_hub_configure()
677 debug("ganged power switching\n"); in usb_hub_configure()
680 debug("individual port power switching\n"); in usb_hub_configure()
684 debug("unknown reserved power switching mode\n"); in usb_hub_configure()
695 debug("global over-current protection\n"); in usb_hub_configure()
698 debug("individual port over-current protection\n"); in usb_hub_configure()
702 debug("no over-current protection\n"); in usb_hub_configure()
706 switch (dev->descriptor.bDeviceProtocol) { in usb_hub_configure()
715 debug("TT per port\n"); in usb_hub_configure()
716 hub->tt.multi = true; in usb_hub_configure()
726 dev->descriptor.bDeviceProtocol); in usb_hub_configure()
733 if (dev->descriptor.bDeviceProtocol != 0) { in usb_hub_configure()
734 hub->tt.think_time = 666; in usb_hub_configure()
736 8, hub->tt.think_time); in usb_hub_configure()
740 hub->tt.think_time = 666 * 2; in usb_hub_configure()
742 16, hub->tt.think_time); in usb_hub_configure()
745 hub->tt.think_time = 666 * 3; in usb_hub_configure()
747 24, hub->tt.think_time); in usb_hub_configure()
750 hub->tt.think_time = 666 * 4; in usb_hub_configure()
752 32, hub->tt.think_time); in usb_hub_configure()
757 descriptor->bPwrOn2PwrGood * 2); in usb_hub_configure()
759 descriptor->bHubContrCurrent); in usb_hub_configure()
761 for (i = 0; i < dev->maxchild; i++) in usb_hub_configure()
762 debug("port %d is%s removable\n", i + 1, in usb_hub_configure()
763 hub->desc.u.hs.DeviceRemovable[(i + 1) / 8] & \ in usb_hub_configure()
767 debug("usb_hub_configure: failed to get Status - " \ in usb_hub_configure()
768 "too long: %d\n", descriptor->bLength); in usb_hub_configure()
769 return -EFBIG; in usb_hub_configure()
775 dev->status); in usb_hub_configure()
782 le16_to_cpu(hubsts->wHubStatus), in usb_hub_configure()
783 le16_to_cpu(hubsts->wHubChange)); in usb_hub_configure()
785 (le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_LOCAL_POWER) ? \ in usb_hub_configure()
787 debug("%sover-current condition exists\n", in usb_hub_configure()
788 (le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_OVERCURRENT) ? \ in usb_hub_configure()
797 if (ret < 0 && ret != -ENOSYS) { in usb_hub_configure()
806 * USB device. USB 3.0 hubs use a 20-bit field called 'route string' in usb_hub_configure()
807 * to route packets to the designated downstream port. The hub uses a in usb_hub_configure()
810 * port number. in usb_hub_configure()
812 if (usb_hub_is_root_hub(dev->dev)) { in usb_hub_configure()
813 hub->hub_depth = -1; in usb_hub_configure()
818 hdev = dev->dev->parent; in usb_hub_configure()
821 hdev = hdev->parent; in usb_hub_configure()
824 hub->hub_depth = depth; in usb_hub_configure()
836 __func__, dev->status); in usb_hub_configure()
850 for (i = 0; i < dev->maxchild; i++) in usb_hub_configure()
856 * are detected (either via port connected or via port timeout) in usb_hub_configure()
860 for (i = 0; i < dev->maxchild; i++) { in usb_hub_configure()
866 return -ENOMEM; in usb_hub_configure()
868 usb_scan->dev = dev; in usb_hub_configure()
869 usb_scan->hub = hub; in usb_hub_configure()
870 usb_scan->port = i; in usb_hub_configure()
871 list_add_tail(&usb_scan->list, &usb_scan_list); in usb_hub_configure()
887 iface = &dev->config.if_desc[ifnum]; in usb_hub_check()
889 if (iface->desc.bInterfaceClass != USB_CLASS_HUB) in usb_hub_check()
893 if ((iface->desc.bInterfaceSubClass != 0) && in usb_hub_check()
894 (iface->desc.bInterfaceSubClass != 1)) in usb_hub_check()
896 /* Multiple endpoints? What kind of mutant ninja-hub is this? */ in usb_hub_check()
897 if (iface->desc.bNumEndpoints != 1) in usb_hub_check()
899 ep = &iface->ep_desc[0]; in usb_hub_check()
901 if (!(ep->bEndpointAddress & USB_DIR_IN)) in usb_hub_check()
904 if ((ep->bmAttributes & 3) != 3) in usb_hub_check()
912 iface->desc.bInterfaceClass, iface->desc.bInterfaceSubClass, in usb_hub_check()
913 iface->desc.bNumEndpoints); in usb_hub_check()
916 ep->bEndpointAddress, ep->bmAttributes); in usb_hub_check()
919 return -ENOENT; in usb_hub_check()
948 { .compatible = "usb-hub" },