diff options
author | Nicolas Saenz Julienne <nsaenzjulienne@suse.de> | 2020-06-29 18:37:25 +0200 |
---|---|---|
committer | Matthias Brugger <mbrugger@suse.com> | 2020-07-10 11:49:28 +0200 |
commit | 0b80371b350e6732a02d5e39bf900413ae1271ba (patch) | |
tree | c6b01968e0d4c12b8614590cd3616cf97e29af93 /drivers/usb | |
parent | 6836d59094727423086dbc27fd7732f514495af4 (diff) | |
download | u-boot-0b80371b350e6732a02d5e39bf900413ae1271ba.tar.gz |
usb: xhci: Add reset controller support
Some atypical users of xhci might need to manually reset their xHCI
controller before starting the HCD setup. Check if a reset controller
device is available to the PCI bus and trigger a reset.
Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
[mb: squash fix to only build xhci_reset_hw() if CONFIG_DM_BUS]
Signed-off-by: Matthias Brugger <mbrugger@suse.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/host/xhci-mem.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/xhci.c | 35 |
2 files changed, 37 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index f446520528..108f4bd8cf 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -180,6 +180,8 @@ 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.c b/drivers/usb/host/xhci.c index ebd2954571..f635bb39f6 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -190,6 +190,37 @@ 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 * @@ -1508,6 +1539,10 @@ 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 |