Ver código fonte

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>
Nicolas Saenz Julienne 3 anos atrás
pai
commit
0b80371b35
3 arquivos alterados com 39 adições e 0 exclusões
  1. 2 0
      drivers/usb/host/xhci-mem.c
  2. 35 0
      drivers/usb/host/xhci.c
  3. 2 0
      include/usb/xhci.h

+ 2 - 0
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));
 }
 

+ 35 - 0
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

+ 2 - 0
include/usb/xhci.h

@@ -16,6 +16,7 @@
 #ifndef HOST_XHCI_H_
 #define HOST_XHCI_H_
 
+#include <reset.h>
 #include <asm/types.h>
 #include <asm/cache.h>
 #include <asm/io.h>
@@ -1209,6 +1210,7 @@ struct xhci_ctrl {
 #if CONFIG_IS_ENABLED(DM_USB)
 	struct udevice *dev;
 #endif
+	struct reset_ctl reset;
 	struct xhci_hccr *hccr;	/* R/O registers, not need for volatile */
 	struct xhci_hcor *hcor;
 	struct xhci_doorbell_array *dba;