summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/host/xhci-fsl.c83
1 files changed, 82 insertions, 1 deletions
diff --git a/drivers/usb/host/xhci-fsl.c b/drivers/usb/host/xhci-fsl.c
index c12a189485..bdcd4f1c99 100644
--- a/drivers/usb/host/xhci-fsl.c
+++ b/drivers/usb/host/xhci-fsl.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 Freescale Semiconductor, Inc.
+ * Copyright 2015,2016 Freescale Semiconductor, Inc.
*
* FSL USB HOST xHCI Controller
*
@@ -17,12 +17,21 @@
#include "xhci.h"
#include <fsl_errata.h>
#include <fsl_usb.h>
+#include <dm.h>
/* Declare global data pointer */
DECLARE_GLOBAL_DATA_PTR;
+#ifndef CONFIG_DM_USB
static struct fsl_xhci fsl_xhci;
unsigned long ctr_addr[] = FSL_USB_XHCI_ADDR;
+#else
+struct xhci_fsl_priv {
+ struct xhci_ctrl xhci;
+ fdt_addr_t hcd_base;
+ struct fsl_xhci ctx;
+};
+#endif
__weak int __board_usb_init(int index, enum usb_init_type init)
{
@@ -77,6 +86,77 @@ static int fsl_xhci_core_exit(struct fsl_xhci *fsl_xhci)
return 0;
}
+#ifdef CONFIG_DM_USB
+static int xhci_fsl_probe(struct udevice *dev)
+{
+ struct xhci_fsl_priv *priv = dev_get_priv(dev);
+ struct xhci_hccr *hccr;
+ struct xhci_hcor *hcor;
+
+ int ret = 0;
+
+ /*
+ * Get the base address for XHCI controller from the device node
+ */
+ priv->hcd_base = dev_get_addr(dev);
+ if (priv->hcd_base == FDT_ADDR_T_NONE) {
+ debug("Can't get the XHCI register base address\n");
+ return -ENXIO;
+ }
+ priv->ctx.hcd = (struct xhci_hccr *)priv->hcd_base;
+ priv->ctx.dwc3_reg = (struct dwc3 *)((char *)(priv->hcd_base) +
+ DWC3_REG_OFFSET);
+
+ fsl_apply_xhci_errata();
+
+ ret = fsl_xhci_core_init(&priv->ctx);
+ if (ret < 0) {
+ puts("Failed to initialize xhci\n");
+ return ret;
+ }
+
+ hccr = (struct xhci_hccr *)(priv->ctx.hcd);
+ hcor = (struct xhci_hcor *)((uintptr_t) hccr
+ + HC_LENGTH(xhci_readl(&hccr->cr_capbase)));
+
+ debug("xhci-fsl: init hccr %lx and hcor %lx hc_length %lx\n",
+ (uintptr_t)hccr, (uintptr_t)hcor,
+ (uintptr_t)HC_LENGTH(xhci_readl(&hccr->cr_capbase)));
+
+ return xhci_register(dev, hccr, hcor);
+}
+
+static int xhci_fsl_remove(struct udevice *dev)
+{
+ struct xhci_fsl_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ fsl_xhci_core_exit(&priv->ctx);
+
+ ret = xhci_deregister(dev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static const struct udevice_id xhci_usb_ids[] = {
+ { .compatible = "fsl,layerscape-dwc3", },
+ { }
+};
+
+U_BOOT_DRIVER(xhci_fsl) = {
+ .name = "xhci_fsl",
+ .id = UCLASS_USB,
+ .of_match = xhci_usb_ids,
+ .probe = xhci_fsl_probe,
+ .remove = xhci_fsl_remove,
+ .ops = &xhci_usb_ops,
+ .platdata_auto_alloc_size = sizeof(struct usb_platdata),
+ .priv_auto_alloc_size = sizeof(struct xhci_fsl_priv),
+ .flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
+#else
int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor)
{
struct fsl_xhci *ctx = &fsl_xhci;
@@ -116,3 +196,4 @@ void xhci_hcd_stop(int index)
fsl_xhci_core_exit(ctx);
}
+#endif