mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2025-09-19 21:01:51 +02:00
When bringing in the series 'arm: dts: am62-beagleplay: Fix Beagleplay Ethernet"' I failed to notice that b4 noticed it was based on next and so took that as the base commit and merged that part of next to master. This reverts commit c8ffd1356d42223cbb8c86280a083cc3c93e6426, reversing changes made to 2ee6f3a5f7550de3599faef9704e166e5dcace35. Reported-by: Jonas Karlman <jonas@kwiboo.se> Signed-off-by: Tom Rini <trini@konsulko.com>
173 lines
3.6 KiB
C
173 lines
3.6 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Copyright (C) 2015 Alexey Brodkin <abrodkin@synopsys.com>
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <clk.h>
|
|
#include <log.h>
|
|
#include <dm/device_compat.h>
|
|
#include <dm/devres.h>
|
|
#include <dm/ofnode.h>
|
|
#include <generic-phy.h>
|
|
#include <reset.h>
|
|
#include <asm/io.h>
|
|
#include <dm.h>
|
|
#include "ehci.h"
|
|
#include <power/regulator.h>
|
|
|
|
/*
|
|
* Even though here we don't explicitly use "struct ehci_ctrl"
|
|
* ehci_register() expects it to be the first thing that resides in
|
|
* device's private data.
|
|
*/
|
|
struct generic_ehci {
|
|
struct ehci_ctrl ctrl;
|
|
struct clk_bulk clocks;
|
|
struct reset_ctl_bulk resets;
|
|
struct phy phy;
|
|
struct udevice *vbus_supply;
|
|
};
|
|
|
|
static int ehci_enable_vbus_supply(struct udevice *dev)
|
|
{
|
|
struct generic_ehci *priv = dev_get_priv(dev);
|
|
int ret;
|
|
|
|
ret = device_get_supply_regulator(dev, "vbus-supply",
|
|
&priv->vbus_supply);
|
|
if (ret && ret != -ENOENT)
|
|
return ret;
|
|
|
|
ret = regulator_set_enable_if_allowed(priv->vbus_supply, true);
|
|
if (ret && ret != -ENOSYS) {
|
|
dev_err(dev, "Error enabling VBUS supply (ret=%d)\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int ehci_disable_vbus_supply(struct generic_ehci *priv)
|
|
{
|
|
int ret;
|
|
|
|
ret = regulator_set_enable_if_allowed(priv->vbus_supply, false);
|
|
if (ret && ret != -ENOSYS)
|
|
return ret;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int ehci_usb_probe(struct udevice *dev)
|
|
{
|
|
struct generic_ehci *priv = dev_get_priv(dev);
|
|
struct ehci_hccr *hccr;
|
|
struct ehci_hcor *hcor;
|
|
int err, ret;
|
|
|
|
err = 0;
|
|
ret = clk_get_bulk(dev, &priv->clocks);
|
|
if (ret && ret != -ENOENT) {
|
|
dev_err(dev, "Failed to get clocks (ret=%d)\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
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 get deassert resets (err=%d)\n", err);
|
|
goto reset_err;
|
|
}
|
|
|
|
err = ehci_enable_vbus_supply(dev);
|
|
if (err)
|
|
goto reset_err;
|
|
|
|
err = generic_setup_phy(dev, &priv->phy, 0);
|
|
if (err)
|
|
goto regulator_err;
|
|
|
|
hccr = map_physmem(dev_read_addr(dev), 0x100, MAP_NOCACHE);
|
|
hcor = (struct ehci_hcor *)((uintptr_t)hccr +
|
|
HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
|
|
|
|
err = ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
|
|
if (err)
|
|
goto phy_err;
|
|
|
|
return 0;
|
|
|
|
phy_err:
|
|
ret = generic_shutdown_phy(&priv->phy);
|
|
if (ret)
|
|
dev_err(dev, "failed to shutdown usb phy (ret=%d)\n", ret);
|
|
|
|
regulator_err:
|
|
ret = ehci_disable_vbus_supply(priv);
|
|
if (ret)
|
|
dev_err(dev, "failed to disable VBUS supply (ret=%d)\n", ret);
|
|
|
|
reset_err:
|
|
ret = reset_release_bulk(&priv->resets);
|
|
if (ret)
|
|
dev_err(dev, "failed to release resets (ret=%d)\n", ret);
|
|
clk_err:
|
|
ret = clk_release_bulk(&priv->clocks);
|
|
if (ret)
|
|
dev_err(dev, "failed to release clocks (ret=%d)\n", ret);
|
|
|
|
return err;
|
|
}
|
|
|
|
static int ehci_usb_remove(struct udevice *dev)
|
|
{
|
|
struct generic_ehci *priv = dev_get_priv(dev);
|
|
int ret;
|
|
|
|
ret = ehci_deregister(dev);
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = generic_shutdown_phy(&priv->phy);
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = ehci_disable_vbus_supply(priv);
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = reset_release_bulk(&priv->resets);
|
|
if (ret)
|
|
return ret;
|
|
|
|
return clk_release_bulk(&priv->clocks);
|
|
}
|
|
|
|
static const struct udevice_id ehci_usb_ids[] = {
|
|
{ .compatible = "generic-ehci" },
|
|
{ }
|
|
};
|
|
|
|
U_BOOT_DRIVER(ehci_generic) = {
|
|
.name = "ehci_generic",
|
|
.id = UCLASS_USB,
|
|
.of_match = ehci_usb_ids,
|
|
.probe = ehci_usb_probe,
|
|
.remove = ehci_usb_remove,
|
|
.ops = &ehci_usb_ops,
|
|
.priv_auto = sizeof(struct generic_ehci),
|
|
.flags = DM_FLAG_ALLOC_PRIV_DMA,
|
|
};
|