X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fusb%2Fhost%2Fusb-uclass.c;h=611ea97a724929903d3ba028b53a42f894c223be;hb=d01806a8fcbdaedcc67cead56ece572021d97ab7;hp=b0e6e71a8fb0f6017d41177d6d5703fe8b3c1e7e;hpb=b2f219b081de964583a5621bc59d43eb75521598;p=oweals%2Fu-boot.git diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c index b0e6e71a8f..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; @@ -139,9 +136,32 @@ int usb_reset_root_port(struct usb_device *udev) 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; @@ -154,27 +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; - ret = device_unbind_children(bus); - 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; @@ -202,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; @@ -213,7 +246,6 @@ int usb_init(void) int ret; asynch_allowed = 1; - usb_hub_reset(); ret = uclass_get(UCLASS_USB, &uc); if (ret) @@ -225,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"); @@ -270,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"); @@ -279,6 +335,14 @@ int usb_init(void) return usb_started ? 0 : -1; } +/* + * 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; @@ -286,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; @@ -303,21 +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; -} + device_find_first_child(bus, &dev); + if (!dev) + 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); + return find_child_devnum(dev, devnum); } +#endif int usb_setup_ehci_gadget(struct ehci_ctrl **ctlrp) { @@ -329,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; @@ -344,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)) @@ -381,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, @@ -416,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; @@ -491,14 +550,15 @@ error: } /** - * usb_find_emul_child() - Find an existing device for emulated devices + * usb_find_child() - Find an existing device which matches our needs + * + * */ -static int usb_find_emul_child(struct udevice *parent, - struct usb_device_descriptor *desc, - struct usb_interface_descriptor *iface, - struct udevice **devp) +static int usb_find_child(struct udevice *parent, + struct usb_device_descriptor *desc, + struct usb_interface_descriptor *iface, + struct udevice **devp) { -#ifdef CONFIG_SANDBOX struct udevice *dev; *devp = NULL; @@ -517,7 +577,7 @@ static int usb_find_emul_child(struct udevice *parent, return 0; } } -#endif + return -ENOENT; } @@ -572,13 +632,13 @@ 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; + 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; - ret = usb_find_emul_child(parent, &udev->descriptor, iface, &dev); - debug("** usb_find_emul_child returns %d\n", ret); + ret = usb_find_child(parent, &udev->descriptor, iface, &dev); + debug("** usb_find_child returns %d\n", ret); if (ret) { if (ret != -ENOENT) return ret; @@ -635,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 */ @@ -650,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; @@ -691,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; @@ -731,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),