X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fusb%2Fhost%2Fusb-uclass.c;h=611ea97a724929903d3ba028b53a42f894c223be;hb=d01806a8fcbdaedcc67cead56ece572021d97ab7;hp=6e86f4a24a48ff26e19013ed7746d60212a66705;hpb=0d3f732fd2ba679b4498541f075d1b1bdbea3935;p=oweals%2Fu-boot.git diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c index 6e86f4a24a..611ea97a72 100644 --- a/drivers/usb/host/usb-uclass.c +++ b/drivers/usb/host/usb-uclass.c @@ -1,23 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * (C) Copyright 2015 Google, Inc * Written by Simon Glass * * usb_match_device() modified from Linux kernel v4.0. - * - * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include +#include #include #include #include -#include #include -DECLARE_GLOBAL_DATA_PTR; - extern bool usb_started; /* flag for the started/stopped USB status */ static bool asynch_allowed; @@ -128,9 +125,43 @@ int usb_alloc_device(struct usb_device *udev) return ops->alloc_device(bus, udev); } +int usb_reset_root_port(struct usb_device *udev) +{ + struct udevice *bus = udev->controller_dev; + struct dm_usb_ops *ops = usb_get_ops(bus); + + if (!ops->reset_root_port) + return -ENOSYS; + + return ops->reset_root_port(bus, udev); +} + +int usb_update_hub_device(struct usb_device *udev) +{ + struct udevice *bus = udev->controller_dev; + struct dm_usb_ops *ops = usb_get_ops(bus); + + if (!ops->update_hub_device) + return -ENOSYS; + + return ops->update_hub_device(bus, udev); +} + +int usb_get_max_xfer_size(struct usb_device *udev, size_t *size) +{ + struct udevice *bus = udev->controller_dev; + struct dm_usb_ops *ops = usb_get_ops(bus); + + if (!ops->get_max_xfer_size) + return -ENOSYS; + + return ops->get_max_xfer_size(bus, size); +} + int usb_stop(void) { struct udevice *bus; + struct udevice *rh; struct uclass *uc; struct usb_uclass_priv *uc_priv; int err = 0, ret; @@ -143,24 +174,26 @@ int usb_stop(void) uc_priv = uc->priv; uclass_foreach_dev(bus, uc) { - ret = device_remove(bus); + ret = device_remove(bus, DM_REMOVE_NORMAL); if (ret && !err) err = ret; - } - -#ifdef CONFIG_SANDBOX - struct udevice *dev; - /* Reset all enulation devices */ - ret = uclass_get(UCLASS_USB_EMUL, &uc); - if (ret) - return ret; + /* Locate root hub device */ + device_find_first_child(bus, &rh); + if (rh) { + /* + * All USB devices are children of root hub. + * Unbinding root hub will unbind all of its children. + */ + ret = device_unbind(rh); + if (ret && !err) + err = ret; + } + } - uclass_foreach_dev(dev, uc) - usb_emul_reset(dev); -#endif +#ifdef CONFIG_USB_STORAGE usb_stor_reset(); - usb_hub_reset(); +#endif uc_priv->companion_device_count = 0; usb_started = 0; @@ -188,6 +221,20 @@ static void usb_scan_bus(struct udevice *bus, bool recurse) printf("%d USB Device(s) found\n", priv->next_addr); } +static void remove_inactive_children(struct uclass *uc, struct udevice *bus) +{ + uclass_foreach_dev(bus, uc) { + struct udevice *dev, *next; + + if (!device_active(bus)) + continue; + device_foreach_child_safe(dev, next, bus) { + if (!device_active(dev)) + device_unbind(dev); + } + } +} + int usb_init(void) { int controllers_initialized = 0; @@ -199,7 +246,6 @@ int usb_init(void) int ret; asynch_allowed = 1; - usb_hub_reset(); ret = uclass_get(UCLASS_USB, &uc); if (ret) @@ -211,6 +257,21 @@ int usb_init(void) /* init low_level USB */ printf("USB%d: ", count); count++; + +#ifdef CONFIG_SANDBOX + /* + * For Sandbox, we need scan the device tree each time when we + * start the USB stack, in order to re-create the emulated USB + * devices and bind drivers for them before we actually do the + * driver probe. + */ + ret = dm_scan_fdt_dev(bus); + if (ret) { + printf("Sandbox USB device scan failed (%d)\n", ret); + continue; + } +#endif + ret = device_probe(bus); if (ret == -ENODEV) { /* No such device. */ puts("Port not available.\n"); @@ -256,6 +317,15 @@ int usb_init(void) } debug("scan end\n"); + + /* Remove any devices that were not found on this scan */ + remove_inactive_children(uc, bus); + + ret = uclass_get(UCLASS_USB_HUB, &uc); + if (ret) + return ret; + remove_inactive_children(uc, bus); + /* if we were not able to find at least one working bus, bail out */ if (!count) printf("No controllers found\n"); @@ -265,11 +335,14 @@ int usb_init(void) return usb_started ? 0 : -1; } -int usb_reset_root_port(void) -{ - return -ENOSYS; -} - +/* + * TODO(sjg@chromium.org): Remove this legacy function. At present it is needed + * to support boards which use driver model for USB but not Ethernet, and want + * to use USB Ethernet. + * + * The #if clause is here to ensure that remains the only case. + */ +#if !defined(CONFIG_DM_ETH) && defined(CONFIG_USB_HOST_ETHER) static struct usb_device *find_child_devnum(struct udevice *parent, int devnum) { struct usb_device *udev; @@ -277,7 +350,7 @@ static struct usb_device *find_child_devnum(struct udevice *parent, int devnum) if (!device_active(parent)) return NULL; - udev = dev_get_parentdata(parent); + udev = dev_get_parent_priv(parent); if (udev->devnum == devnum) return udev; @@ -294,50 +367,16 @@ static struct usb_device *find_child_devnum(struct udevice *parent, int devnum) struct usb_device *usb_get_dev_index(struct udevice *bus, int index) { - struct udevice *hub; + struct udevice *dev; int devnum = index + 1; /* Addresses are allocated from 1 on USB */ - device_find_first_child(bus, &hub); - if (device_get_uclass_id(hub) == UCLASS_USB_HUB) - return find_child_devnum(hub, devnum); - - return NULL; -} - -int usb_post_bind(struct udevice *dev) -{ - /* Scan the bus for devices */ - return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); -} - -int usb_port_reset(struct usb_device *parent, int portnr) -{ - unsigned short portstatus; - int ret; - - debug("%s: start\n", __func__); - - if (parent) { - /* reset the port for the second time */ - assert(portnr > 0); - debug("%s: reset %d\n", __func__, portnr - 1); - ret = legacy_hub_port_reset(parent, portnr - 1, &portstatus); - if (ret < 0) { - printf("\n Couldn't reset port %i\n", portnr); - return ret; - } - } else { - debug("%s: reset root\n", __func__); - usb_reset_root_port(); - } - - return 0; -} + device_find_first_child(bus, &dev); + if (!dev) + return NULL; -int usb_legacy_port_reset(struct usb_device *parent, int portnr) -{ - return usb_port_reset(parent, portnr); + return find_child_devnum(dev, devnum); } +#endif int usb_setup_ehci_gadget(struct ehci_ctrl **ctlrp) { @@ -349,7 +388,7 @@ int usb_setup_ehci_gadget(struct ehci_ctrl **ctlrp) ret = uclass_find_device_by_seq(UCLASS_USB, 0, true, &dev); if (ret) return ret; - ret = device_remove(dev); + ret = device_remove(dev, DM_REMOVE_NORMAL); if (ret) return ret; @@ -364,8 +403,8 @@ int usb_setup_ehci_gadget(struct ehci_ctrl **ctlrp) } /* returns 0 if no match, 1 if match */ -int usb_match_device(const struct usb_device_descriptor *desc, - const struct usb_device_id *id) +static int usb_match_device(const struct usb_device_descriptor *desc, + const struct usb_device_id *id) { if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && id->idVendor != le16_to_cpu(desc->idVendor)) @@ -401,9 +440,9 @@ int usb_match_device(const struct usb_device_descriptor *desc, } /* returns 0 if no match, 1 if match */ -int usb_match_one_id_intf(const struct usb_device_descriptor *desc, - const struct usb_interface_descriptor *int_desc, - const struct usb_device_id *id) +static int usb_match_one_id_intf(const struct usb_device_descriptor *desc, + const struct usb_interface_descriptor *int_desc, + const struct usb_device_id *id) { /* The interface class, subclass, protocol and number should never be * checked for a match if the device class is Vendor Specific, @@ -436,9 +475,9 @@ int usb_match_one_id_intf(const struct usb_device_descriptor *desc, } /* returns 0 if no match, 1 if match */ -int usb_match_one_id(struct usb_device_descriptor *desc, - struct usb_interface_descriptor *int_desc, - const struct usb_device_id *id) +static int usb_match_one_id(struct usb_device_descriptor *desc, + struct usb_interface_descriptor *int_desc, + const struct usb_device_id *id) { if (!usb_match_device(desc, id)) return 0; @@ -593,8 +632,8 @@ int usb_scan_device(struct udevice *parent, int port, udev->portnr = port; debug("Calling usb_setup_device(), portnr=%d\n", udev->portnr); parent_udev = device_get_uclass_id(parent) == UCLASS_USB_HUB ? - dev_get_parentdata(parent) : NULL; - ret = usb_setup_device(udev, priv->desc_before_addr, parent_udev, port); + dev_get_parent_priv(parent) : NULL; + ret = usb_setup_device(udev, priv->desc_before_addr, parent_udev); debug("read_descriptor for '%s': ret=%d\n", parent->name, ret); if (ret) return ret; @@ -656,7 +695,7 @@ int usb_detect_change(void) if (!device_active(dev)) continue; - udev = dev_get_parentdata(dev); + udev = dev_get_parent_priv(dev); if (usb_get_port_status(udev, udev->portnr, &status) < 0) /* USB request failed */ @@ -671,22 +710,21 @@ int usb_detect_change(void) return change; } -int usb_child_post_bind(struct udevice *dev) +static int usb_child_post_bind(struct udevice *dev) { struct usb_dev_platdata *plat = dev_get_parent_platdata(dev); - const void *blob = gd->fdt_blob; int val; - if (dev->of_offset == -1) + if (!dev_of_valid(dev)) return 0; /* We only support matching a few things */ - val = fdtdec_get_int(blob, dev->of_offset, "usb,device-class", -1); + val = dev_read_u32_default(dev, "usb,device-class", -1); if (val != -1) { plat->id.match_flags |= USB_DEVICE_ID_MATCH_DEV_CLASS; plat->id.bDeviceClass = val; } - val = fdtdec_get_int(blob, dev->of_offset, "usb,interface-class", -1); + val = dev_read_u32_default(dev, "usb,interface-class", -1); if (val != -1) { plat->id.match_flags |= USB_DEVICE_ID_MATCH_INT_CLASS; plat->id.bInterfaceClass = val; @@ -712,7 +750,7 @@ struct udevice *usb_get_bus(struct udevice *dev) int usb_child_pre_probe(struct udevice *dev) { - struct usb_device *udev = dev_get_parentdata(dev); + struct usb_device *udev = dev_get_parent_priv(dev); struct usb_dev_platdata *plat = dev_get_parent_platdata(dev); int ret; @@ -752,7 +790,7 @@ UCLASS_DRIVER(usb) = { .id = UCLASS_USB, .name = "usb", .flags = DM_UC_FLAG_SEQ_ALIAS, - .post_bind = usb_post_bind, + .post_bind = dm_scan_fdt_dev, .priv_auto_alloc_size = sizeof(struct usb_uclass_priv), .per_child_auto_alloc_size = sizeof(struct usb_device), .per_device_auto_alloc_size = sizeof(struct usb_bus_priv),