summaryrefslogtreecommitdiff
path: root/drivers/usb/host
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2021-09-27 16:45:36 +0300
committerTom Rini <trini@konsulko.com>2021-09-27 16:45:36 +0300
commite908d20fcbd847e17345591fc171b59d9a156516 (patch)
treedef104237fd9b8888a37a5c3378b4ef7e26b6d43 /drivers/usb/host
parentbb38d77ca779cc8bdad3d4ceb6cecc687f4987c2 (diff)
parent0b9bcf665cd98fe9db0956c894006b250a7d465f (diff)
downloadu-boot-e908d20fcbd847e17345591fc171b59d9a156516.tar.xz
Merge tag 'v2021.10-rc5' into next
Prepare v2021.10-rc5
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/ehci-mx6.c25
-rw-r--r--drivers/usb/host/xhci-dwc3.c59
-rw-r--r--drivers/usb/host/xhci-mem.c2
-rw-r--r--drivers/usb/host/xhci-pci.c52
-rw-r--r--drivers/usb/host/xhci.c35
5 files changed, 129 insertions, 44 deletions
diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c
index c3e4170513..1bd6147c76 100644
--- a/drivers/usb/host/ehci-mx6.c
+++ b/drivers/usb/host/ehci-mx6.c
@@ -23,6 +23,7 @@
#include <asm/mach-types.h>
#include <power/regulator.h>
#include <linux/usb/otg.h>
+#include <linux/usb/phy.h>
#include "ehci.h"
@@ -435,6 +436,7 @@ struct ehci_mx6_priv_data {
struct clk clk;
struct phy phy;
enum usb_init_type init_type;
+ enum usb_phy_interface phy_type;
#if !defined(CONFIG_PHY)
int portnr;
void __iomem *phy_addr;
@@ -443,6 +445,24 @@ struct ehci_mx6_priv_data {
#endif
};
+static u32 mx6_portsc(enum usb_phy_interface phy_type)
+{
+ switch (phy_type) {
+ case USBPHY_INTERFACE_MODE_UTMI:
+ return PORT_PTS_UTMI;
+ case USBPHY_INTERFACE_MODE_UTMIW:
+ return PORT_PTS_UTMI | PORT_PTS_PTW;
+ case USBPHY_INTERFACE_MODE_ULPI:
+ return PORT_PTS_ULPI;
+ case USBPHY_INTERFACE_MODE_SERIAL:
+ return PORT_PTS_SERIAL;
+ case USBPHY_INTERFACE_MODE_HSIC:
+ return PORT_PTS_HSIC;
+ default:
+ return CONFIG_MXC_USB_PORTSC;
+ }
+}
+
static int mx6_init_after_reset(struct ehci_ctrl *dev)
{
struct ehci_mx6_priv_data *priv = dev->priv;
@@ -479,7 +499,7 @@ static int mx6_init_after_reset(struct ehci_ctrl *dev)
return 0;
setbits_le32(&ehci->usbmode, CM_HOST);
- writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc);
+ writel(mx6_portsc(priv->phy_type), &ehci->portsc);
setbits_le32(&ehci->portsc, USB_EN);
mdelay(10);
@@ -641,6 +661,7 @@ static int ehci_usb_probe(struct udevice *dev)
priv->ehci = ehci;
priv->init_type = type;
+ priv->phy_type = usb_get_phy_mode(dev_ofnode(dev));
#if CONFIG_IS_ENABLED(CLK)
ret = clk_get_by_index(dev, 0, &priv->clk);
@@ -690,7 +711,7 @@ static int ehci_usb_probe(struct udevice *dev)
if (priv->init_type == USB_INIT_HOST) {
setbits_le32(&ehci->usbmode, CM_HOST);
- writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc);
+ writel(mx6_portsc(priv->phy_type), &ehci->portsc);
setbits_le32(&ehci->portsc, USB_EN);
}
diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c
index 3e0ae80cec..bec0d98081 100644
--- a/drivers/usb/host/xhci-dwc3.c
+++ b/drivers/usb/host/xhci-dwc3.c
@@ -7,10 +7,12 @@
* Author: Ramneek Mehresh<ramneek.mehresh@freescale.com>
*/
+#include <clk.h>
#include <common.h>
#include <dm.h>
#include <generic-phy.h>
#include <log.h>
+#include <reset.h>
#include <usb.h>
#include <dwc3-uboot.h>
#include <linux/delay.h>
@@ -21,7 +23,9 @@
#include <linux/usb/otg.h>
struct xhci_dwc3_plat {
+ struct clk_bulk clks;
struct phy_bulk phys;
+ struct reset_ctl_bulk resets;
};
void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode)
@@ -70,7 +74,8 @@ int dwc3_core_init(struct dwc3 *dwc3_reg)
revision = readl(&dwc3_reg->g_snpsid);
/* This should read as U3 followed by revision number */
- if ((revision & DWC3_GSNPSID_MASK) != 0x55330000) {
+ if ((revision & DWC3_GSNPSID_MASK) != 0x55330000 &&
+ (revision & DWC3_GSNPSID_MASK) != 0x33310000) {
puts("this is not a DesignWare USB3 DRD Core\n");
return -1;
}
@@ -111,6 +116,46 @@ void dwc3_set_fladj(struct dwc3 *dwc3_reg, u32 val)
}
#if CONFIG_IS_ENABLED(DM_USB)
+static int xhci_dwc3_reset_init(struct udevice *dev,
+ struct xhci_dwc3_plat *plat)
+{
+ int ret;
+
+ ret = reset_get_bulk(dev, &plat->resets);
+ if (ret == -ENOTSUPP || ret == -ENOENT)
+ return 0;
+ else if (ret)
+ return ret;
+
+ ret = reset_deassert_bulk(&plat->resets);
+ if (ret) {
+ reset_release_bulk(&plat->resets);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int xhci_dwc3_clk_init(struct udevice *dev,
+ struct xhci_dwc3_plat *plat)
+{
+ int ret;
+
+ ret = clk_get_bulk(dev, &plat->clks);
+ if (ret == -ENOSYS || ret == -ENOENT)
+ return 0;
+ if (ret)
+ return ret;
+
+ ret = clk_enable_bulk(&plat->clks);
+ if (ret) {
+ clk_release_bulk(&plat->clks);
+ return ret;
+ }
+
+ return 0;
+}
+
static int xhci_dwc3_probe(struct udevice *dev)
{
struct xhci_hcor *hcor;
@@ -122,6 +167,14 @@ static int xhci_dwc3_probe(struct udevice *dev)
u32 reg;
int ret;
+ ret = xhci_dwc3_reset_init(dev, plat);
+ if (ret)
+ return ret;
+
+ ret = xhci_dwc3_clk_init(dev, plat);
+ if (ret)
+ return ret;
+
hccr = (struct xhci_hccr *)((uintptr_t)dev_remap_addr(dev));
hcor = (struct xhci_hcor *)((uintptr_t)hccr +
HC_LENGTH(xhci_readl(&(hccr)->cr_capbase)));
@@ -171,6 +224,10 @@ static int xhci_dwc3_remove(struct udevice *dev)
dwc3_shutdown_phy(dev, &plat->phys);
+ clk_release_bulk(&plat->clks);
+
+ reset_release_bulk(&plat->resets);
+
return xhci_deregister(dev);
}
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 1c11c2e7e0..0d9da62bab 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -180,8 +180,6 @@ void xhci_cleanup(struct xhci_ctrl *ctrl)
xhci_free_virt_devices(ctrl);
free(ctrl->erst.entries);
free(ctrl->dcbaa);
- if (reset_valid(&ctrl->reset))
- reset_free(&ctrl->reset);
memset(ctrl, '\0', sizeof(struct xhci_ctrl));
}
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index aaa243f291..630bc20be1 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -7,12 +7,18 @@
#include <common.h>
#include <dm.h>
+#include <dm/device_compat.h>
#include <init.h>
#include <log.h>
#include <pci.h>
+#include <reset.h>
#include <usb.h>
#include <usb/xhci.h>
+struct xhci_pci_plat {
+ struct reset_ctl reset;
+};
+
static int xhci_pci_init(struct udevice *dev, struct xhci_hccr **ret_hccr,
struct xhci_hcor **ret_hcor)
{
@@ -45,15 +51,53 @@ static int xhci_pci_init(struct udevice *dev, struct xhci_hccr **ret_hccr,
static int xhci_pci_probe(struct udevice *dev)
{
+ struct xhci_pci_plat *plat = dev_get_plat(dev);
struct xhci_hccr *hccr;
struct xhci_hcor *hcor;
int ret;
+ ret = reset_get_by_index(dev, 0, &plat->reset);
+ if (ret && ret != -ENOENT && ret != -ENOTSUPP) {
+ dev_err(dev, "failed to get reset\n");
+ return ret;
+ }
+
+ if (reset_valid(&plat->reset)) {
+ ret = reset_assert(&plat->reset);
+ if (ret)
+ goto err_reset;
+
+ ret = reset_deassert(&plat->reset);
+ if (ret)
+ goto err_reset;
+ }
+
ret = xhci_pci_init(dev, &hccr, &hcor);
if (ret)
- return ret;
+ goto err_reset;
+
+ ret = xhci_register(dev, hccr, hcor);
+ if (ret)
+ goto err_reset;
+
+ return 0;
+
+err_reset:
+ if (reset_valid(&plat->reset))
+ reset_free(&plat->reset);
+
+ return ret;
+}
+
+static int xhci_pci_remove(struct udevice *dev)
+{
+ struct xhci_pci_plat *plat = dev_get_plat(dev);
- return xhci_register(dev, hccr, hcor);
+ xhci_deregister(dev);
+ if (reset_valid(&plat->reset))
+ reset_free(&plat->reset);
+
+ return 0;
}
static const struct udevice_id xhci_pci_ids[] = {
@@ -65,10 +109,10 @@ U_BOOT_DRIVER(xhci_pci) = {
.name = "xhci_pci",
.id = UCLASS_USB,
.probe = xhci_pci_probe,
- .remove = xhci_deregister,
+ .remove = xhci_pci_remove,
.of_match = xhci_pci_ids,
.ops = &xhci_usb_ops,
- .plat_auto = sizeof(struct usb_plat),
+ .plat_auto = sizeof(struct xhci_pci_plat),
.priv_auto = sizeof(struct xhci_ctrl),
.flags = DM_FLAG_OS_PREPARE | DM_FLAG_ALLOC_PRIV_DMA,
};
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index d27ac01c83..452dacc0af 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -188,37 +188,6 @@ static int xhci_start(struct xhci_hcor *hcor)
return ret;
}
-#if CONFIG_IS_ENABLED(DM_USB)
-/**
- * Resets XHCI Hardware
- *
- * @param ctrl pointer to host controller
- * @return 0 if OK, or a negative error code.
- */
-static int xhci_reset_hw(struct xhci_ctrl *ctrl)
-{
- int ret;
-
- ret = reset_get_by_index(ctrl->dev, 0, &ctrl->reset);
- if (ret && ret != -ENOENT && ret != -ENOTSUPP) {
- dev_err(ctrl->dev, "failed to get reset\n");
- return ret;
- }
-
- if (reset_valid(&ctrl->reset)) {
- ret = reset_assert(&ctrl->reset);
- if (ret)
- return ret;
-
- ret = reset_deassert(&ctrl->reset);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-#endif
-
/**
* Resets the XHCI Controller
*
@@ -1534,10 +1503,6 @@ int xhci_register(struct udevice *dev, struct xhci_hccr *hccr,
ctrl->dev = dev;
- ret = xhci_reset_hw(ctrl);
- if (ret)
- goto err;
-
/*
* XHCI needs to issue a Address device command to setup
* proper device context structures, before it can interact