// Copyright 2019 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 "as370-usb-phy.h"

#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <ddk/binding.h>
#include <ddk/debug.h>
#include <ddk/device.h>
#include <ddk/driver.h>
#include <ddk/platform-defs.h>
#include <fbl/algorithm.h>
#include <fbl/alloc_checker.h>
#include <hw/reg.h>
#include <soc/as370/as370-reset.h>
#include <soc/as370/as370-usb.h>
#include <soc/vs680/vs680-reset.h>
#include <soc/vs680/vs680-usb.h>

namespace as370_usb_phy {

void UsbPhy::ResetPhy() {
  auto* mmio = &*reset_mmio_;
  auto reset = as370::GblPerifStickyResetN::Get().ReadFrom(mmio);
  reset.set_usbOtgPhyreset(0).WriteTo(mmio);
  reset.set_usbOtgPrstn(1).WriteTo(mmio);
  usleep(10);
  reset.set_usbOtgHresetn(1).WriteTo(mmio);
  usleep(100);
}

zx_status_t UsbPhy::InitPhy() {
  auto* mmio = &*usbphy_mmio_;

  if (did_ == PDEV_DID_VS680_USB_PHY) {
    auto* resetmmio = &*reset_mmio_;

    vs680::ClockReg700::Get().ReadFrom(resetmmio).set_usb0coreclkEn(1).WriteTo(resetmmio);

    // 1.  Trigger usb0SyncReset (set usb0SyncReset to 1). No read back because no read modify write
    //     that could trigger other agent reset
    vs680::Gbl_perifReset::Get().FromValue(0).set_usb0SyncReset(1).WriteTo(resetmmio);

    // 2.  Assert sticky resets to USBOTG PHY and MAC. (set usb0PhyRstn, usb0CoreRstn
    //     and usb0MahbRstn to 0)
    vs680::Gbl_perifStickyResetN::Get()
      .ReadFrom(resetmmio)
      .set_usb0PhyRstn(0)
      .set_usb0CoreRstn(0)
      .set_usb0MahbRstn(0)
      .WriteTo(resetmmio);

    // 3.1.  Program USB_CTRL0
    vs680::USB_PHY_CTRL0::Get().FromValue(0).set_value(0x533DADF0).WriteTo(mmio);
    // 3.2.  Program USB_CTRL1
    vs680::USB_PHY_CTRL1::Get().FromValue(0).set_value(0x01B10000).WriteTo(mmio);

    // 4.  De-assert sticky resets PHY only. (set usb0PhyRstn to 1)
    vs680::Gbl_perifStickyResetN::Get().ReadFrom(resetmmio).set_usb0PhyRstn(1).WriteTo(resetmmio);

    // 5.  Wait more than 45us
    usleep(45);

    // 6.  De-assert core(set usb0CoreRstn and usb0MahbRstn to 1).
    vs680::Gbl_perifStickyResetN::Get()
      .ReadFrom(resetmmio)
      .set_usb0CoreRstn(1)
      .set_usb0MahbRstn(1)
      .WriteTo(resetmmio);
    usleep(100);

    return ZX_OK;
  } else {
    as370::USB_PHY_CTRL0::Get().FromValue(0).set_value(0x0EB35E84).WriteTo(mmio);
    as370::USB_PHY_CTRL1::Get().FromValue(0).set_value(0x80E9F004).WriteTo(mmio);

    ResetPhy();

    uint32_t count = 10000;
    while (count) {
      if (as370::USB_PHY_RB::Get().ReadFrom(mmio).clk_rdy()) {
        break;
      }
      usleep(1);
      count--;
    }

    return count ? 0 : ZX_ERR_TIMED_OUT;

    return ZX_OK;
  }
}

zx_status_t UsbPhy::Create(void* ctx, zx_device_t* parent) {
  auto dev = std::make_unique<UsbPhy>(parent);
  auto status = dev->Init();
  if (status != ZX_OK) {
    return status;
  }

  // devmgr is now in charge of the device.
  __UNUSED auto* dummy = dev.release();
  return ZX_OK;
}

zx_status_t UsbPhy::AddDwc2Device() {
  if (dwc2_device_) {
    zxlogf(ERROR, "UsbPhy::AddDwc2Device: device already exists!");
    return ZX_ERR_BAD_STATE;
  }

  fbl::AllocChecker ac;
  dwc2_device_ = fbl::make_unique_checked<Dwc2Device>(&ac, zxdev());
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }

  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_DWC2},
  };

  return dwc2_device_->DdkAdd("dwc2", 0, props, countof(props), ZX_PROTOCOL_USB_PHY);
}

zx_status_t UsbPhy::RemoveDwc2Device() {
  if (dwc2_device_ == nullptr) {
    zxlogf(ERROR, "UsbPhy::RemoveDwc2Device: device does not exist!");
    return ZX_ERR_BAD_STATE;
  }

  // devmgr will own the device until it is destroyed.
  __UNUSED auto* dev = dwc2_device_.release();
  dev->DdkRemoveDeprecated();

  return ZX_OK;
}

zx_status_t UsbPhy::Init() {
  if (!pdev_.is_valid()) {
    zxlogf(ERROR, "UsbPhy::Init: could not get platform device protocol");
    return ZX_ERR_NOT_SUPPORTED;
  }

  auto status = pdev_.MapMmio(0, &usbphy_mmio_);
  if (status != ZX_OK) {
    zxlogf(ERROR, "UsbPhy::Init: MapMmio failed for usbphy_mmio_");
    return status;
  }
  status = pdev_.MapMmio(1, &reset_mmio_);
  if (status != ZX_OK) {
    zxlogf(ERROR, "UsbPhy::Init: MapMmio failed for reset_mmio_");
    return status;
  }

  pdev_device_info_t info;
  status = pdev_.GetDeviceInfo(&info);
  if (status != ZX_OK) {
    zxlogf(ERROR, "UsbPhy::Init: GetDeviceInfo failed");
    return status;
  }
  did_ = info.did;

  status = InitPhy();
  if (status != ZX_OK) {
    zxlogf(ERROR, "UsbPhy::Init: InitPhy() failed");
    return status;
  }

  const char* name = "as370-usb-phy";
  if (did_ == PDEV_DID_VS680_USB_PHY) {
    name = "vs680-usb-phy";
  }
  status = DdkAdd(name, DEVICE_ADD_NON_BINDABLE);
  if (status != ZX_OK) {
    zxlogf(ERROR, "UsbPhy::Init: DdkAdd() failed");
    return status;
  }

  AddDwc2Device();

  return ZX_OK;
}

void UsbPhy::DdkUnbindDeprecated() {
  RemoveDwc2Device();
  DdkRemoveDeprecated();
}

void UsbPhy::DdkRelease() { delete this; }

static constexpr zx_driver_ops_t driver_ops = []() {
  zx_driver_ops_t ops = {};
  ops.version = DRIVER_OPS_VERSION;
  ops.bind = UsbPhy::Create;
  return ops;
}();

}  // namespace as370_usb_phy

ZIRCON_DRIVER_BEGIN(as370_usb_phy, as370_usb_phy::driver_ops, "zircon", "0.1", 4)
BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_PDEV),
    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_SYNAPTICS),
    BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_AS370_USB_PHY),
    BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_VS680_USB_PHY),
ZIRCON_DRIVER_END(as370_usb_phy)
