mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-04 05:50:17 +00:00 
			
		
		
		
	Merge branch 'next' of https://source.denx.de/u-boot/custodians/u-boot-usb into next
This commit is contained in:
		
						commit
						31d9d64444
					
				@ -16,75 +16,41 @@
 | 
			
		||||
 | 
			
		||||
struct generic_ohci {
 | 
			
		||||
	ohci_t ohci;
 | 
			
		||||
	struct clk *clocks;	/* clock list */
 | 
			
		||||
	struct reset_ctl *resets; /* reset list */
 | 
			
		||||
	struct clk_bulk clocks;	/* clock list */
 | 
			
		||||
	struct reset_ctl_bulk resets; /* reset list */
 | 
			
		||||
	struct phy phy;
 | 
			
		||||
	int clock_count;	/* number of clock in clock list */
 | 
			
		||||
	int reset_count;	/* number of reset in reset list */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int ohci_usb_probe(struct udevice *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct ohci_regs *regs = dev_read_addr_ptr(dev);
 | 
			
		||||
	struct generic_ohci *priv = dev_get_priv(dev);
 | 
			
		||||
	int i, err, ret, clock_nb, reset_nb;
 | 
			
		||||
	int err, ret;
 | 
			
		||||
 | 
			
		||||
	err = 0;
 | 
			
		||||
	priv->clock_count = 0;
 | 
			
		||||
	clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells",
 | 
			
		||||
					       0);
 | 
			
		||||
	if (clock_nb > 0) {
 | 
			
		||||
		priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk),
 | 
			
		||||
					    GFP_KERNEL);
 | 
			
		||||
		if (!priv->clocks)
 | 
			
		||||
			return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
		for (i = 0; i < clock_nb; i++) {
 | 
			
		||||
			err = clk_get_by_index(dev, i, &priv->clocks[i]);
 | 
			
		||||
			if (err < 0)
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			err = clk_enable(&priv->clocks[i]);
 | 
			
		||||
			if (err && err != -ENOSYS) {
 | 
			
		||||
				dev_err(dev, "failed to enable clock %d\n", i);
 | 
			
		||||
				clk_free(&priv->clocks[i]);
 | 
			
		||||
				goto clk_err;
 | 
			
		||||
			}
 | 
			
		||||
			priv->clock_count++;
 | 
			
		||||
		}
 | 
			
		||||
	} else if (clock_nb != -ENOENT) {
 | 
			
		||||
		dev_err(dev, "failed to get clock phandle(%d)\n", clock_nb);
 | 
			
		||||
		return clock_nb;
 | 
			
		||||
	ret = clk_get_bulk(dev, &priv->clocks);
 | 
			
		||||
	if (ret && ret != -ENOENT) {
 | 
			
		||||
		dev_err(dev, "Failed to get clocks (ret=%d)\n", ret);
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	priv->reset_count = 0;
 | 
			
		||||
	reset_nb = dev_count_phandle_with_args(dev, "resets", "#reset-cells",
 | 
			
		||||
					       0);
 | 
			
		||||
	if (reset_nb > 0) {
 | 
			
		||||
		priv->resets = devm_kcalloc(dev, reset_nb,
 | 
			
		||||
					    sizeof(struct reset_ctl),
 | 
			
		||||
					    GFP_KERNEL);
 | 
			
		||||
		if (!priv->resets)
 | 
			
		||||
			return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
		for (i = 0; i < reset_nb; i++) {
 | 
			
		||||
			err = reset_get_by_index(dev, i, &priv->resets[i]);
 | 
			
		||||
			if (err < 0)
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			err = reset_deassert(&priv->resets[i]);
 | 
			
		||||
			if (err) {
 | 
			
		||||
				dev_err(dev, "failed to deassert reset %d\n", i);
 | 
			
		||||
				reset_free(&priv->resets[i]);
 | 
			
		||||
				goto reset_err;
 | 
			
		||||
			}
 | 
			
		||||
			priv->reset_count++;
 | 
			
		||||
		}
 | 
			
		||||
	} else if (reset_nb != -ENOENT) {
 | 
			
		||||
		dev_err(dev, "failed to get reset phandle(%d)\n", reset_nb);
 | 
			
		||||
	err = clk_enable_bulk(&priv->clocks);
 | 
			
		||||
	if (err) {
 | 
			
		||||
		dev_err(dev, "Failed to enable clocks (err=%d)\n", err);
 | 
			
		||||
		goto clk_err;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = reset_get_bulk(dev, &priv->resets);
 | 
			
		||||
	if (err && err != -ENOENT) {
 | 
			
		||||
		dev_err(dev, "failed to get resets (err=%d)\n", err);
 | 
			
		||||
		goto clk_err;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = reset_deassert_bulk(&priv->resets);
 | 
			
		||||
	if (err) {
 | 
			
		||||
		dev_err(dev, "failed to deassert resets (err=%d)\n", err);
 | 
			
		||||
		goto reset_err;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = generic_setup_phy(dev, &priv->phy, 0);
 | 
			
		||||
	if (err)
 | 
			
		||||
		goto reset_err;
 | 
			
		||||
@ -101,13 +67,13 @@ phy_err:
 | 
			
		||||
		dev_err(dev, "failed to shutdown usb phy\n");
 | 
			
		||||
 | 
			
		||||
reset_err:
 | 
			
		||||
	ret = reset_release_all(priv->resets, priv->reset_count);
 | 
			
		||||
	ret = reset_release_bulk(&priv->resets);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		dev_err(dev, "failed to assert all resets\n");
 | 
			
		||||
		dev_err(dev, "failed to release resets (ret=%d)\n", ret);
 | 
			
		||||
clk_err:
 | 
			
		||||
	ret = clk_release_all(priv->clocks, priv->clock_count);
 | 
			
		||||
	ret = clk_release_bulk(&priv->clocks);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		dev_err(dev, "failed to disable all clocks\n");
 | 
			
		||||
		dev_err(dev, "failed to release clocks (ret=%d)\n", ret);
 | 
			
		||||
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
@ -125,11 +91,11 @@ static int ohci_usb_remove(struct udevice *dev)
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	ret = reset_release_all(priv->resets, priv->reset_count);
 | 
			
		||||
	ret = reset_release_bulk(&priv->resets);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	return clk_release_all(priv->clocks, priv->clock_count);
 | 
			
		||||
	return clk_release_bulk(&priv->clocks);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct udevice_id ohci_usb_ids[] = {
 | 
			
		||||
 | 
			
		||||
@ -249,6 +249,37 @@ static void remove_inactive_children(struct uclass *uc, struct udevice *bus)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int usb_probe_companion(struct udevice *bus)
 | 
			
		||||
{
 | 
			
		||||
	struct udevice *companion_dev;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Enforce optional companion controller is marked as such in order to
 | 
			
		||||
	 * 1st scan the primary controller, before the companion controller
 | 
			
		||||
	 * (ownership is given to companion when low or full speed devices
 | 
			
		||||
	 * have been detected).
 | 
			
		||||
	 */
 | 
			
		||||
	ret = uclass_get_device_by_phandle(UCLASS_USB, bus, "companion", &companion_dev);
 | 
			
		||||
	if (!ret) {
 | 
			
		||||
		struct usb_bus_priv *companion_bus_priv;
 | 
			
		||||
 | 
			
		||||
		debug("%s is the companion of %s\n", companion_dev->name, bus->name);
 | 
			
		||||
		companion_bus_priv = dev_get_uclass_priv(companion_dev);
 | 
			
		||||
		companion_bus_priv->companion = true;
 | 
			
		||||
	} else if (ret && ret != -ENOENT && ret != -ENODEV) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * Treat everything else than no companion or disabled
 | 
			
		||||
		 * companion as an error. (It may not be enabled on boards
 | 
			
		||||
		 * that have a High-Speed HUB to handle FS and LS traffic).
 | 
			
		||||
		 */
 | 
			
		||||
		printf("Failed to get companion (ret=%d)\n", ret);
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int usb_init(void)
 | 
			
		||||
{
 | 
			
		||||
	int controllers_initialized = 0;
 | 
			
		||||
@ -299,6 +330,11 @@ int usb_init(void)
 | 
			
		||||
			printf("probe failed, error %d\n", ret);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ret = usb_probe_companion(bus);
 | 
			
		||||
		if (ret)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		controllers_initialized++;
 | 
			
		||||
		usb_started = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user