usb support for nxp

Change-Id: I6dcde575f96d8e277424f57fac24110580a124e4
diff --git a/system/dev/board/imx8mevk/imx8mevk-usb.c b/system/dev/board/imx8mevk/imx8mevk-usb.c
new file mode 100644
index 0000000..dbde181
--- /dev/null
+++ b/system/dev/board/imx8mevk/imx8mevk-usb.c
@@ -0,0 +1,121 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <ddk/debug.h>
+#include <ddk/device.h>
+#include <ddk/protocol/platform-bus.h>
+#include <ddk/protocol/platform-defs.h>
+
+#include <soc/imx8m/imx8m.h>
+#include <soc/imx8m/imx8m-hw.h>
+#include <soc/imx8m/imx8m-iomux.h>
+#include <soc/imx8m/imx8m-gpio.h>
+#include <limits.h>
+#include <hw/reg.h>
+
+#include "imx8mevk.h"
+
+#define BIT(nr)         (1UL << (nr))
+#define USBMIX_PHY_OFFSET       0xF0040
+
+#define PHY_CTRL0_REF_SSP_EN        BIT(2)
+#define PHY_CTRL1_RESET             BIT(0)
+#define PHY_CTRL1_ATERESET          BIT(3)
+#define PHY_CTRL1_VDATSRCENB0       BIT(19)
+#define PHY_CTRL1_VDATDETENB0       BIT(20)
+#define PHY_CTRL2_TXENABLEN0        BIT(8)
+#define USBMIX_PHY_OFFSET           0xF0040
+#define PHY_CTRL0_REF_SSP_EN        BIT(2)
+#define PHY_CTRL1_RESET             BIT(0)
+#define PHY_CTRL1_ATERESET          BIT(3)
+#define PHY_CTRL1_VDATSRCENB0       BIT(19)
+#define PHY_CTRL1_VDATDETENB0       BIT(20)
+#define PHY_CTRL2_TXENABLEN0        BIT(8)
+
+static const pbus_mmio_t xhci_mmios[] = {
+    {
+        .base = IMX8M_USB2_BASE,
+        .length = IMX8M_USB2_LENGTH,
+    },
+};
+
+static const pbus_irq_t xhci_irqs[] = {
+    {
+        .irq = IMX8M_A53_INTR_USB2,
+        .mode = ZX_INTERRUPT_MODE_EDGE_HIGH,
+    },
+};
+
+static const pbus_bti_t xhci_btis[] = {
+    {
+        .iommu_index = 0,
+        .bti_id = BTI_USB_XHCI,
+    },
+};
+
+static const pbus_dev_t xhci_dev = {
+    .name = "xhci",
+    .vid = PDEV_VID_GENERIC,
+    .pid = PDEV_PID_GENERIC,
+    .did = PDEV_DID_USB_XHCI,
+    .mmios = xhci_mmios,
+    .mmio_count = countof(xhci_mmios),
+    .irqs = xhci_irqs,
+    .irq_count = countof(xhci_irqs),
+    .btis = xhci_btis,
+    .bti_count = countof(xhci_btis),
+};
+
+zx_status_t imx_usb_init(imx8mevk_bus_t* bus) {
+    zx_status_t status;
+
+    uint32_t reg;
+
+    zx_handle_t bti;
+    status = iommu_get_bti(&bus->iommu, 0, BTI_BOARD, &bti);
+    if (status != ZX_OK) {
+        zxlogf(ERROR, "%s: iommu_get_bti failed %d\n", __FUNCTION__, status);
+        return status;
+    }
+
+    io_buffer_t usb_phy;
+    status = io_buffer_init_physical(&usb_phy, bti, IMX8M_USB1_BASE, IMX8M_USB1_LENGTH,
+                                        get_root_resource(), ZX_CACHE_POLICY_UNCACHED_DEVICE);
+    if (status != ZX_OK) {
+        zxlogf(ERROR, "%s io_buffer_init_physical failed %d\n", __FUNCTION__, status);
+        zx_handle_close(bti);
+        return status;
+    }
+
+    volatile void* regs = io_buffer_virt(&usb_phy);
+
+    //TODO: More stuff might be needed if we were to boot from our own bootloader.
+    reg = readl(regs + 0x4);
+    reg &= ~(PHY_CTRL1_VDATSRCENB0 | PHY_CTRL1_VDATDETENB0);
+    reg |= PHY_CTRL1_RESET | PHY_CTRL1_ATERESET;
+    writel(reg, regs + 0x4);
+
+    reg = readl(regs + 0x0);
+    reg |= PHY_CTRL0_REF_SSP_EN;
+    writel(reg, regs + 0x0);
+
+    reg = readl(regs + 0x8);
+    reg |= PHY_CTRL2_TXENABLEN0;
+    writel(reg, regs + 0x8);
+
+    reg = readl(regs + 0x4);
+    reg &= ~(PHY_CTRL1_RESET | PHY_CTRL1_ATERESET);
+    writel(reg, regs + 0x4);
+
+    io_buffer_release(&usb_phy);
+    zx_handle_close(bti);
+
+    if ((status = pbus_device_add(&bus->pbus, &xhci_dev, 0)) != ZX_OK) {
+        zxlogf(ERROR, "%s could not add xhci_dev: %d\n", __FUNCTION__, status);
+        return status;
+    }
+
+    return ZX_OK;
+
+}
\ No newline at end of file
diff --git a/system/dev/board/imx8mevk/imx8mevk.c b/system/dev/board/imx8mevk/imx8mevk.c
index 3405162..8f27df7 100644
--- a/system/dev/board/imx8mevk/imx8mevk.c
+++ b/system/dev/board/imx8mevk/imx8mevk.c
@@ -70,6 +70,11 @@
         goto fail;
     }
 
+    if ((status = imx_usb_init(bus)) != ZX_OK) {
+        zxlogf(ERROR, "%s: failed %d\n", __FUNCTION__, status);
+        goto fail;
+    }
+
     return ZX_OK;
 
 fail:
diff --git a/system/dev/board/imx8mevk/imx8mevk.h b/system/dev/board/imx8mevk/imx8mevk.h
index fc8541a..6e0a4ae 100644
--- a/system/dev/board/imx8mevk/imx8mevk.h
+++ b/system/dev/board/imx8mevk/imx8mevk.h
@@ -16,7 +16,7 @@
 enum
 {
     BTI_BOARD,
-    BTI_IOMUX,
+    BTI_USB_XHCI,
 };
 
 typedef struct {
@@ -31,4 +31,5 @@
 } imx8mevk_bus_t;
 
 
-zx_status_t imx8m_gpio_init(imx8mevk_bus_t* bus);
\ No newline at end of file
+zx_status_t imx8m_gpio_init(imx8mevk_bus_t* bus);
+zx_status_t imx_usb_init(imx8mevk_bus_t* bus);
\ No newline at end of file
diff --git a/system/dev/board/imx8mevk/rules.mk b/system/dev/board/imx8mevk/rules.mk
index ee3bd20..5f052c8 100644
--- a/system/dev/board/imx8mevk/rules.mk
+++ b/system/dev/board/imx8mevk/rules.mk
@@ -11,6 +11,7 @@
 MODULE_SRCS += \
     $(LOCAL_DIR)/imx8mevk.c \
     $(LOCAL_DIR)/imx8mevk-gpio.c \
+    $(LOCAL_DIR)/imx8mevk-usb.c \
 
 MODULE_STATIC_LIBS := \
     system/dev/soc/imx8m \