checkpoint madrone-usb
Change-Id: I41ba7e1f5bb0362152ddd294ce4cd27f1887f84e
diff --git a/system/dev/board/imx8mevk/imx8mevk-usb.c b/system/dev/board/imx8mevk/imx8mevk-usb.c
index 8febdcc..7276061 100644
--- a/system/dev/board/imx8mevk/imx8mevk-usb.c
+++ b/system/dev/board/imx8mevk/imx8mevk-usb.c
@@ -93,7 +93,7 @@
}
};
-// USB1 is USB-A port, host only
+// USB2 is USB-A port, host only
static const pbus_dev_t usb2_dev = {
.name = "dwc3-2",
.vid = PDEV_VID_GENERIC,
@@ -110,9 +110,31 @@
};
zx_status_t imx_usb_phy_init(zx_paddr_t usb_base, size_t usb_length, zx_handle_t bti) {
+ // turn on usb via smc calls
+ zx_smc_parameters_t otg1_en_params = {.func_id = IMX8M_SIP_GPC,
+ .arg1 = IMX8M_SIP_CONFIG_GPC_PM_DOMAIN,
+ .arg2 = IMX8M_PD_USB_OTG1,
+ .arg3 = 1};
+ zx_smc_result_t smc_result;
+ zx_status_t status = zx_smc_call(get_root_resource(), &otg1_en_params, &smc_result);
+ if (status != ZX_OK) {
+ zxlogf(ERROR, "%s: SMC call to turn USB on failed %d\n", __FUNCTION__, status);
+ return status;
+ }
+
+ zx_smc_parameters_t otg2_en_params = {.func_id = IMX8M_SIP_GPC,
+ .arg1 = IMX8M_SIP_CONFIG_GPC_PM_DOMAIN,
+ .arg2 = IMX8M_PD_USB_OTG2,
+ .arg3 = 1};
+ status = zx_smc_call(get_root_resource(), &otg2_en_params, &smc_result);
+ if (status != ZX_OK) {
+ zxlogf(ERROR, "%s: SMC call to turn USB on failed %d\n", __FUNCTION__, status);
+ return status;
+ }
+
uint32_t reg;
io_buffer_t usb_buf;
- zx_status_t status = io_buffer_init_physical(&usb_buf, bti, usb_base, usb_length,
+ status = io_buffer_init_physical(&usb_buf, bti, usb_base, usb_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);
@@ -146,28 +168,6 @@
zx_status_t status;
zx_handle_t bti;
- // turn on usb via smc calls
- zx_smc_parameters_t otg1_en_params = {.func_id = IMX8M_SIP_GPC,
- .arg1 = IMX8M_SIP_CONFIG_GPC_PM_DOMAIN,
- .arg2 = IMX8M_PD_USB_OTG1,
- .arg3 = 1};
- zx_smc_result_t smc_result;
- status = zx_smc_call(get_root_resource(), &otg1_en_params, &smc_result);
- if (status != ZX_OK) {
- zxlogf(ERROR, "%s: SMC call to turn USB on failed %d\n", __FUNCTION__, status);
- return status;
- }
-
- zx_smc_parameters_t otg2_en_params = {.func_id = IMX8M_SIP_GPC,
- .arg1 = IMX8M_SIP_CONFIG_GPC_PM_DOMAIN,
- .arg2 = IMX8M_PD_USB_OTG2,
- .arg3 = 1};
- status = zx_smc_call(get_root_resource(), &otg2_en_params, &smc_result);
- if (status != ZX_OK) {
- zxlogf(ERROR, "%s: SMC call to turn USB on failed %d\n", __FUNCTION__, status);
- return status;
- }
-
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);
diff --git a/system/dev/board/imx8mevk/imx8mevk.c b/system/dev/board/imx8mevk/imx8mevk.c
index 261709c..9bad241 100644
--- a/system/dev/board/imx8mevk/imx8mevk.c
+++ b/system/dev/board/imx8mevk/imx8mevk.c
@@ -121,8 +121,13 @@
gpio_set_alt_function(&bus->gpio, 0, imx8mevk_pinmux[i]);
}
- if ((status = imx_usb_init(bus)) != ZX_OK) {
- zxlogf(ERROR, "%s: failed %d\n", __FUNCTION__, status);
+ if (bus->board == BOARD_MADRONE) {
+ status = madrone_usb_init(bus);
+ } else {
+ status = imx_usb_init(bus);
+ }
+ if (status != ZX_OK) {
+ zxlogf(ERROR, "%s: USB init failed %d\n", __FUNCTION__, status);
goto fail;
}
@@ -160,6 +165,13 @@
goto fail;
}
+ const char* board_name = pbus_get_board_name(&bus->pbus);
+ if (!strcmp(board_name, "madrone")) {
+ bus->board = BOARD_MADRONE;
+ } else {
+ bus->board = BOARD_IMX8M_EVK;
+ }
+
// get default BTI from the dummy IOMMU implementation in the platform bus
status = device_get_protocol(parent, ZX_PROTOCOL_IOMMU, &bus->iommu);
if (status != ZX_OK) {
diff --git a/system/dev/board/imx8mevk/imx8mevk.h b/system/dev/board/imx8mevk/imx8mevk.h
index 03a2399..d9e60f0 100644
--- a/system/dev/board/imx8mevk/imx8mevk.h
+++ b/system/dev/board/imx8mevk/imx8mevk.h
@@ -18,20 +18,25 @@
BTI_DISPLAY,
BTI_GPU,
BTI_SDHCI,
-
};
+typedef enum {
+ BOARD_IMX8M_EVK,
+ BOARD_MADRONE,
+} imx8_board_t;
+
typedef struct {
platform_bus_protocol_t pbus;
zx_device_t* parent;
iommu_protocol_t iommu;
gpio_protocol_t gpio;
zx_handle_t bti_handle;
- uint32_t soc_pid;
+ imx8_board_t board;
} imx8mevk_bus_t;
-
zx_status_t imx8m_gpio_init(imx8mevk_bus_t* bus);
+zx_status_t imx_usb_phy_init(zx_paddr_t usb_base, size_t usb_length, zx_handle_t bti);
zx_status_t imx_usb_init(imx8mevk_bus_t* bus);
+zx_status_t madrone_usb_init(imx8mevk_bus_t* bus);
zx_status_t imx_gpu_init(imx8mevk_bus_t* bus);
zx_status_t imx8m_sdhci_init(imx8mevk_bus_t* bus);
\ No newline at end of file
diff --git a/system/dev/board/imx8mevk/madrone-usb.c b/system/dev/board/imx8mevk/madrone-usb.c
new file mode 100644
index 0000000..79252c6
--- /dev/null
+++ b/system/dev/board/imx8mevk/madrone-usb.c
@@ -0,0 +1,163 @@
+// 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 <stdio.h>
+
+#include <ddk/debug.h>
+#include <ddk/metadata.h>
+#include <ddk/protocol/platform-defs.h>
+#include <ddk/protocol/usb-mode-switch.h>
+#include <soc/imx8m/imx8m-gpio.h>
+#include <soc/imx8m/imx8m-hw.h>
+#include <soc/imx8m/imx8m-sip.h>
+#include <zircon/syscalls/smc.h>
+
+#include "imx8mevk.h"
+
+static const pbus_mmio_t dwc3_mmios[] = {
+ {
+ .base = IMX8M_USB1_BASE,
+ .length = IMX8M_USB1_LENGTH,
+ },
+};
+
+static const pbus_irq_t dwc3_irqs[] = {
+ {
+ .irq = IMX8M_A53_INTR_USB1,
+ .mode = ZX_INTERRUPT_MODE_EDGE_HIGH,
+ },
+};
+
+static const pbus_bti_t dwc3_btis[] = {
+ {
+ .iommu_index = 0,
+ .bti_id = BTI_USB1,
+ },
+};
+
+static usb_mode_t dwc3_mode = USB_MODE_HOST;
+
+static const pbus_metadata_t dwc3_metadata[] = {
+ {
+ .type = DEVICE_METADATA_USB_MODE,
+ .data = &dwc3_mode,
+ .len = sizeof(dwc3_mode),
+ }
+};
+
+static const pbus_dev_t madrone_usb_children[] = {
+ {
+ .name = "dwc3",
+ .vid = PDEV_VID_GENERIC,
+ .pid = PDEV_PID_GENERIC,
+ .did = PDEV_DID_USB_DWC3,
+ .mmios = dwc3_mmios,
+ .mmio_count = countof(dwc3_mmios),
+ .irqs = dwc3_irqs,
+ .irq_count = countof(dwc3_irqs),
+ .btis = dwc3_btis,
+ .bti_count = countof(dwc3_btis),
+ .metadata = dwc3_metadata,
+ .metadata_count = countof(dwc3_metadata),
+ },
+};
+
+static const pbus_gpio_t madrone_usb_gpios[] = {
+ {
+ .gpio = IMX_GPIO_PIN(5, 4), // first argument is 1-based
+ },
+};
+
+const pbus_dev_t madrone_usb_dev = {
+ .name = "madrone-usb",
+ .vid = PDEV_VID_GOOGLE,
+ .pid = PDEV_PID_MADRONE,
+ .did = PDEV_DID_MADRONE_USB,
+ .gpios = madrone_usb_gpios,
+ .gpio_count = countof(madrone_usb_gpios),
+ .children = madrone_usb_children,
+ .child_count = countof(madrone_usb_children),
+};
+
+static const pbus_mmio_t usb2_mmios[] = {
+ {
+ .base = IMX8M_USB2_BASE,
+ .length = IMX8M_USB2_LENGTH,
+ },
+};
+static const pbus_irq_t usb2_irqs[] = {
+ {
+ .irq = IMX8M_A53_INTR_USB2,
+ .mode = ZX_INTERRUPT_MODE_EDGE_HIGH,
+ },
+};
+
+static const pbus_bti_t usb2_btis[] = {
+ {
+ .iommu_index = 0,
+ .bti_id = BTI_USB2,
+ },
+};
+
+static usb_mode_t usb2_mode = USB_MODE_HOST;
+
+static const pbus_metadata_t usb2_metadata[] = {
+ {
+ .type = DEVICE_METADATA_USB_MODE,
+ .data = &usb2_mode,
+ .len = sizeof(usb2_mode),
+ }
+};
+
+// USB2 is USB-A port, host only
+static const pbus_dev_t usb2_dev = {
+ .name = "dwc3-2",
+ .vid = PDEV_VID_GENERIC,
+ .pid = PDEV_PID_GENERIC,
+ .did = PDEV_DID_USB_XHCI,
+ .mmios = usb2_mmios,
+ .mmio_count = countof(usb2_mmios),
+ .irqs = usb2_irqs,
+ .irq_count = countof(usb2_irqs),
+ .btis = usb2_btis,
+ .bti_count = countof(usb2_btis),
+ .metadata = usb2_metadata,
+ .metadata_count = countof(usb2_metadata),
+};
+
+
+zx_status_t madrone_usb_init(imx8mevk_bus_t* bus) {
+ zx_status_t status;
+ 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;
+ }
+
+ status = imx_usb_phy_init(IMX8M_USB1_BASE, IMX8M_USB1_LENGTH, bti);
+ if (status != ZX_OK) {
+ zxlogf(ERROR, "%s: imx_usb_phy_init failed %d\n", __FUNCTION__, status);
+ zx_handle_close(bti);
+ return status;
+ }
+ status = imx_usb_phy_init(IMX8M_USB2_BASE, IMX8M_USB2_LENGTH, bti);
+ if (status != ZX_OK) {
+ zxlogf(ERROR, "%s: imx_usb_phy_init failed %d\n", __FUNCTION__, status);
+ zx_handle_close(bti);
+ return status;
+ }
+ zx_handle_close(bti);
+
+ if ((status = pbus_device_add(&bus->pbus, &madrone_usb_dev)) != ZX_OK) {
+ zxlogf(ERROR, "imx_usb_init could not add madrone_usb_dev: %d\n", status);
+ return status;
+ }
+ if ((status = pbus_device_add(&bus->pbus, &usb2_dev)) != ZX_OK) {
+ zxlogf(ERROR, "imx_usb_init could not add usb2_dev: %d\n", status);
+ return status;
+ }
+ return ZX_OK;
+}
diff --git a/system/dev/board/imx8mevk/rules.mk b/system/dev/board/imx8mevk/rules.mk
index b435bfe..e914224 100644
--- a/system/dev/board/imx8mevk/rules.mk
+++ b/system/dev/board/imx8mevk/rules.mk
@@ -14,7 +14,7 @@
$(LOCAL_DIR)/imx8mevk-gpu.c \
$(LOCAL_DIR)/imx8mevk-usb.c \
$(LOCAL_DIR)/imx8mevk-sdhci.c \
-
+ $(LOCAL_DIR)/madrone-usb.c \
MODULE_STATIC_LIBS := \
system/dev/lib/imx8m \
diff --git a/system/dev/usb/madrone-usb/bind.c b/system/dev/usb/madrone-usb/bind.c
new file mode 100644
index 0000000..53eec9b
--- /dev/null
+++ b/system/dev/usb/madrone-usb/bind.c
@@ -0,0 +1,21 @@
+// 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/binding.h>
+#include <ddk/driver.h>
+#include <ddk/protocol/platform-defs.h>
+
+extern zx_status_t madrone_usb_bind(void* ctx, zx_device_t* parent);
+
+static zx_driver_ops_t madrone_usb_driver_ops = {
+ .version = DRIVER_OPS_VERSION,
+ .bind = madrone_usb_bind,
+};
+
+ZIRCON_DRIVER_BEGIN(madrone_usb, madrone_usb_driver_ops, "zircon", "0.1", 4)
+ BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_PLATFORM_DEV),
+ BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_GOOGLE),
+ BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_PID, PDEV_PID_MADRONE),
+ BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_MADRONE_USB),
+ZIRCON_DRIVER_END(hikey_usb)
diff --git a/system/dev/usb/madrone-usb/madrone-usb.cpp b/system/dev/usb/madrone-usb/madrone-usb.cpp
new file mode 100644
index 0000000..798c06a
--- /dev/null
+++ b/system/dev/usb/madrone-usb/madrone-usb.cpp
@@ -0,0 +1,127 @@
+// 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 "madrone-usb.h"
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <ddk/binding.h>
+#include <ddk/debug.h>
+#include <ddk/device.h>
+#include <ddk/driver.h>
+#include <ddk/protocol/platform-defs.h>
+#include <ddk/protocol/platform-device.h>
+#include <ddktl/protocol/gpio.h>
+#include <fbl/unique_ptr.h>
+
+namespace madrone_usb {
+
+zx_status_t MadroneUsb::Create(zx_device_t* parent) {
+ fbl::AllocChecker ac;
+ auto bus = fbl::make_unique_checked<MadroneUsb>(&ac, parent);
+ if (!ac.check()) {
+ return ZX_ERR_NO_MEMORY;
+ }
+
+ auto status = bus->Init();
+ if (status != ZX_OK) {
+ return status;
+ }
+
+ // devmgr is now in charge of the device.
+ __UNUSED auto* dummy = bus.release();
+ return ZX_OK;
+}
+
+zx_status_t MadroneUsb::Init() {
+ platform_device_protocol_t pdev;
+
+ auto status = device_get_protocol(parent(), ZX_PROTOCOL_PLATFORM_DEV, &pdev);
+ if (status != ZX_OK) {
+ return status;
+ }
+
+ status = device_get_protocol(parent(), ZX_PROTOCOL_GPIO, &gpio_);
+ if (status != ZX_OK) {
+ return status;
+ }
+
+ ddk::GpioProtocolProxy gpio(&gpio_);
+ if (status != ZX_OK) {
+ return status;
+ }
+ status = gpio.Config(0, GPIO_DIR_IN | GPIO_TRIGGER_RISING | GPIO_TRIGGER_FALLING);
+
+ status = gpio.GetInterrupt(0, ZX_INTERRUPT_MODE_EDGE_BOTH, interrupt_.reset_and_get_address());
+ if (status != ZX_OK) {
+ return status;
+ }
+
+ zx_device_prop_t props[] = {
+ {BIND_PLATFORM_DEV_VID, 0, PDEV_VID_GENERIC},
+ {BIND_PLATFORM_DEV_PID, 0, PDEV_PID_GENERIC},
+ {BIND_PLATFORM_DEV_DID, 0, PDEV_DID_USB_DWC3},
+ };
+
+ device_add_args_t args = {};
+ args.version = DEVICE_ADD_ARGS_VERSION;
+ args.name = "dwc3";
+ args.ctx = this;
+ args.ops = &ddk_device_proto_;
+ args.props = props;
+ args.prop_count = countof(props);
+ args.proto_id = ddk_proto_id_;
+ args.proto_ops = ddk_proto_ops_;
+
+ status = pdev_device_add(&pdev, 0, &args, &zxdev_);
+ if (status != ZX_OK) {
+ return status;
+ }
+
+ auto thunk = [](void* arg) { return static_cast<MadroneUsb*>(arg)->InterruptThread(); };
+ thrd_create_with_name(&interrupt_thread_, thunk, this, "MadroneUsb::InterruptThread");
+ return ZX_OK;
+}
+
+int MadroneUsb::InterruptThread() {
+ while (true) {
+ zx::time timestamp;
+ auto status = interrupt_.wait(×tamp);
+ printf("MadroneUsb::InterruptThread got %d\n", status);
+ }
+ return 0;
+}
+
+zx_status_t MadroneUsb::UmsSetMode(usb_mode_t mode) {
+/*
+ if (mode == usb_mode_) {
+ return ZX_OK;
+ }
+ if (mode == USB_MODE_OTG) {
+ return ZX_ERR_NOT_SUPPORTED;
+ }
+
+ ddk::GpioProtocolProxy gpio(&gpio_);
+ gpio.Write(HUB_VDD33_EN, mode == USB_MODE_HOST);
+ gpio.Write(VBUS_TYPEC, mode == USB_MODE_HOST);
+ gpio.Write(USBSW_SW_SEL, mode == USB_MODE_HOST);
+
+ usb_mode_ = mode;
+*/
+ return ZX_OK;
+}
+
+void MadroneUsb::DdkRelease() {
+ delete this;
+}
+
+} // namespace madrone_usb
+
+zx_status_t madrone_usb_bind(void* ctx, zx_device_t* parent) {
+ return madrone_usb::MadroneUsb::Create(parent);
+}
diff --git a/system/dev/usb/madrone-usb/madrone-usb.h b/system/dev/usb/madrone-usb/madrone-usb.h
new file mode 100644
index 0000000..2bc7c28
--- /dev/null
+++ b/system/dev/usb/madrone-usb/madrone-usb.h
@@ -0,0 +1,53 @@
+// 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.
+
+#pragma once
+
+#include <threads.h>
+
+#include <ddk/device.h>
+#include <ddktl/device.h>
+#include <ddktl/protocol/gpio.h>
+#include <ddktl/protocol/usb-mode-switch.h>
+#include <fbl/macros.h>
+#include <lib/zx/interrupt.h>
+
+namespace madrone_usb {
+
+class MadroneUsb;
+using MadroneUsbType = ddk::Device<MadroneUsb>;
+
+// This is the main class for the platform bus driver.
+class MadroneUsb : public MadroneUsbType, public ddk::UmsProtocol<MadroneUsb> {
+public:
+ explicit MadroneUsb(zx_device_t* parent)
+ : MadroneUsbType(parent), usb_mode_(USB_MODE_NONE) {}
+
+ static zx_status_t Create(zx_device_t* parent);
+
+ // Device protocol implementation.
+ void DdkRelease();
+
+ // USB mode switch protocol implementation.
+ zx_status_t UmsSetMode(usb_mode_t mode);
+
+private:
+ DISALLOW_COPY_ASSIGN_AND_MOVE(MadroneUsb);
+
+ zx_status_t Init();
+
+ int InterruptThread();
+
+ gpio_protocol_t gpio_;
+ usb_mode_t usb_mode_;
+
+ thrd_t interrupt_thread_;
+ zx::interrupt interrupt_;
+};
+
+} // namespace madrone_usb
+
+__BEGIN_CDECLS
+zx_status_t madrone_usb_bind(void* ctx, zx_device_t* parent);
+__END_CDECLS
diff --git a/system/dev/usb/madrone-usb/rules.mk b/system/dev/usb/madrone-usb/rules.mk
new file mode 100644
index 0000000..3a773d8
--- /dev/null
+++ b/system/dev/usb/madrone-usb/rules.mk
@@ -0,0 +1,27 @@
+# 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.
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+MODULE := $(LOCAL_DIR)
+
+MODULE_TYPE := driver
+
+MODULE_SRCS := \
+ $(LOCAL_DIR)/bind.c \
+ $(LOCAL_DIR)/madrone-usb.cpp \
+
+MODULE_STATIC_LIBS := \
+ system/ulib/ddk \
+ system/ulib/ddktl \
+ system/ulib/fbl \
+ system/ulib/zx \
+ system/ulib/zxcpp \
+
+MODULE_LIBS := \
+ system/ulib/driver \
+ system/ulib/zircon \
+ system/ulib/c \
+
+include make/module.mk
diff --git a/system/ulib/ddk/include/ddk/protocol/platform-defs.h b/system/ulib/ddk/include/ddk/protocol/platform-defs.h
index 764b255..b61b8d5 100644
--- a/system/ulib/ddk/include/ddk/protocol/platform-defs.h
+++ b/system/ulib/ddk/include/ddk/protocol/platform-defs.h
@@ -57,6 +57,7 @@
#define PDEV_DID_GAUSS_LED 4
#define PDEV_DID_ASTRO_FOCALTOUCH 5
#define PDEV_DID_ASTRO_GOODIXTOUCH 6
+#define PDEV_DID_MADRONE_USB 7
// Khadas