// 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 <fuchsia/hardware/usb/peripheral/c/fidl.h>
#include <stdio.h>
#include <string.h>
#include <zircon/device/usb-peripheral.h>
#include <zircon/hw/usb.h>
#include <zircon/hw/usb/cdc.h>

#include <ddk/binding.h>
#include <ddk/debug.h>
#include <ddk/metadata.h>
#include <ddk/platform-defs.h>
#include <ddk/protocol/usb/modeswitch.h>
#include <ddk/usb-peripheral-config.h>
#include <hw/reg.h>
#include <soc/hi3660/hi3660-hw.h>
#include <soc/hi3660/hi3660-regs.h>

#include "hikey960-hw.h"
#include "hikey960.h"

static const char* kManufacturer = "Zircon";
static const char* kProduct = "CDC-Ethernet";
static const char* kSerial = "0123456789ABCDEF";

typedef fuchsia_hardware_usb_peripheral_FunctionDescriptor FunctionDescriptor;

zx_status_t hikey960_usb_phy_init(hikey960_t* hikey) {
  volatile void* usb3otg_bc = hikey->usb3otg_bc.vaddr;
  volatile void* peri_crg = hikey->peri_crg.vaddr;
  volatile void* pctrl = hikey->pctrl.vaddr;
  uint32_t temp;

  writel(PERI_CRG_ISODIS_REFCLK_ISO_EN, peri_crg + PERI_CRG_ISODIS);
  writel(PCTRL_CTRL3_USB_TCXO_EN | (PCTRL_CTRL3_USB_TCXO_EN << PCTRL_CTRL3_MSK_START),
         pctrl + PCTRL_CTRL3);

  temp = readl(pctrl + PCTRL_CTRL24);
  temp &= ~PCTRL_CTRL24_SC_CLK_USB3PHY_3MUX1_SEL;
  writel(temp, pctrl + PCTRL_CTRL24);

  writel(PERI_CRG_GT_CLK_USB3OTG_REF | PERI_CRG_GT_ACLK_USB3OTG, peri_crg + PERI_CRG_CLK_EN4);
  writel(PERI_CRG_IP_RST_USB3OTG_MUX | PERI_CRG_IP_RST_USB3OTG_AHBIF | PERI_CRG_IP_RST_USB3OTG_32K,
         peri_crg + PERI_CRG_RSTDIS4);

  writel(PERI_CRG_IP_RST_USB3OTGPHY_POR | PERI_CRG_IP_RST_USB3OTG, peri_crg + PERI_CRG_RSTEN4);

  // enable PHY REF CLK
  temp = readl(usb3otg_bc + USB3OTG_CTRL0);
  temp |= USB3OTG_CTRL0_ABB_GT_EN;
  writel(temp, usb3otg_bc + USB3OTG_CTRL0);

  temp = readl(usb3otg_bc + USB3OTG_CTRL7);
  temp |= USB3OTG_CTRL7_REF_SSP_EN;
  writel(temp, usb3otg_bc + USB3OTG_CTRL7);

  // exit from IDDQ mode
  temp = readl(usb3otg_bc + USB3OTG_CTRL2);
  temp &= ~(USB3OTG_CTRL2_POWERDOWN_HSP | USB3OTG_CTRL2_POWERDOWN_SSP);
  writel(temp, usb3otg_bc + USB3OTG_CTRL2);
  zx_nanosleep(zx_deadline_after(ZX_USEC(100)));

  writel(PERI_CRG_IP_RST_USB3OTGPHY_POR, peri_crg + PERI_CRG_RSTDIS4);
  writel(PERI_CRG_IP_RST_USB3OTG, peri_crg + PERI_CRG_RSTDIS4);
  zx_nanosleep(zx_deadline_after(ZX_MSEC(20)));

  temp = readl(usb3otg_bc + USB3OTG_CTRL3);
  temp |= (USB3OTG_CTRL3_VBUSVLDEXT | USB3OTG_CTRL3_VBUSVLDEXTSEL);
  writel(temp, usb3otg_bc + USB3OTG_CTRL3);
  zx_nanosleep(zx_deadline_after(ZX_USEC(100)));

  return ZX_OK;
}

static const pbus_mmio_t dwc3_mmios[] = {
    {
        .base = MMIO_USB3OTG_BASE,
        .length = MMIO_USB3OTG_LENGTH,
    },
};

static const pbus_irq_t dwc3_irqs[] = {
    {
        .irq = IRQ_USB3,
        .mode = ZX_INTERRUPT_MODE_EDGE_HIGH,
    },
};

static const pbus_bti_t dwc3_btis[] = {
    {
        .iommu_index = 0,
        .bti_id = BTI_USB_DWC3,
    },
};

static pbus_metadata_t dwc3_metadata[] = {
    {
        .type = DEVICE_METADATA_USB_CONFIG,
        // data_buffer and data_size filled in below
    },
};

static const pbus_dev_t dwc3_dev = {
    .name = "dwc3",
    .vid = PDEV_VID_GENERIC,
    .pid = PDEV_PID_GENERIC,
    .did = PDEV_DID_USB_DWC3,
    .mmio_list = dwc3_mmios,
    .mmio_count = countof(dwc3_mmios),
    .irq_list = dwc3_irqs,
    .irq_count = countof(dwc3_irqs),
    .bti_list = dwc3_btis,
    .bti_count = countof(dwc3_btis),
    .metadata_list = dwc3_metadata,
    .metadata_count = countof(dwc3_metadata),
};

static usb_mode_t hikey_usb_mode = USB_MODE_HOST;

static pbus_metadata_t hikey_usb_metadata[] = {
    {
        .type = DEVICE_METADATA_USB_MODE,
        .data_buffer = &hikey_usb_mode,
        .data_size = sizeof(hikey_usb_mode),
    },
};

const pbus_dev_t hikey_usb_dev = {
    .name = "hikey-usb",
    .vid = PDEV_VID_96BOARDS,
    .pid = PDEV_PID_HIKEY960,
    .did = PDEV_DID_HIKEY960_USB,
    .metadata_list = hikey_usb_metadata,
    .metadata_count = countof(hikey_usb_metadata),
};

// Composite binding rules for the USB drivers.
static const zx_bind_inst_t root_match[] = {
    BI_MATCH(),
};

static const zx_bind_inst_t gpio1_match[] = {
    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_GPIO),
    BI_MATCH_IF(EQ, BIND_GPIO_PIN, GPIO_HUB_VDD33_EN),
};
static const device_fragment_part_t gpio1_fragment[] = {
    {countof(root_match), root_match},
    {countof(gpio1_match), gpio1_match},
};
static const zx_bind_inst_t gpio2_match[] = {
    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_GPIO),
    BI_MATCH_IF(EQ, BIND_GPIO_PIN, GPIO_VBUS_TYPEC),
};
static const device_fragment_part_t gpio2_fragment[] = {
    {countof(root_match), root_match},
    {countof(gpio2_match), gpio2_match},
};
static const zx_bind_inst_t gpio3_match[] = {
    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_GPIO),
    BI_MATCH_IF(EQ, BIND_GPIO_PIN, GPIO_USBSW_SW_SEL),
};
static const device_fragment_part_t gpio3_fragment[] = {
    {countof(root_match), root_match},
    {countof(gpio3_match), gpio3_match},
};
static const device_fragment_t hikey_usb_fragments[] = {
    {countof(gpio1_fragment), gpio1_fragment},
    {countof(gpio2_fragment), gpio2_fragment},
    {countof(gpio3_fragment), gpio3_fragment},
};

static const zx_bind_inst_t ums_match[] = {
    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_USB_MODE_SWITCH),
    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_GENERIC),
    BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_PID, PDEV_PID_GENERIC),
    BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_USB_DWC3),
};
static const device_fragment_part_t ums_fragment[] = {
    {countof(root_match), root_match},
    {countof(ums_match), ums_match},
};
static const device_fragment_t dwc3_fragments[] = {
    {countof(ums_fragment), ums_fragment},
};

zx_status_t hikey960_usb_init(hikey960_t* hikey) {
  zx_status_t status = hikey960_usb_phy_init(hikey);
  if (status != ZX_OK) {
    return status;
  }

  status = pbus_composite_device_add(&hikey->pbus, &hikey_usb_dev, hikey_usb_fragments,
                                     countof(hikey_usb_fragments), UINT32_MAX);
  if (status != ZX_OK) {
    zxlogf(ERROR, "hikey960_add_devices could not add hikey_usb_dev: %d", status);
    return status;
  }

  // construct USB config metadata
  uint8_t buffer[sizeof(struct UsbConfig) + sizeof(FunctionDescriptor)];
  struct UsbConfig* config = (struct UsbConfig*)buffer;
  config->vid = GOOGLE_USB_VID;
  config->pid = GOOGLE_USB_CDC_PID;
  strcpy(config->manufacturer, kManufacturer);
  strcpy(config->serial, kSerial);
  strcpy(config->product, kProduct);
  config->functions[0].interface_class = USB_CLASS_COMM;
  config->functions[0].interface_protocol = 0;
  config->functions[0].interface_subclass = USB_CDC_SUBCLASS_ETHERNET;
  dwc3_metadata[0].data_size = sizeof(struct UsbConfig) + sizeof(FunctionDescriptor);
  dwc3_metadata[0].data_buffer = config;

  status = pbus_composite_device_add(&hikey->pbus, &dwc3_dev, dwc3_fragments,
                                     countof(dwc3_fragments), 1);
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s: pbus_composite_device_add failed: %d", __FUNCTION__, status);
    return status;
  }

  return ZX_OK;
}
