// Copyright 2022 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 "vim3-usb-phy.h"

#include <assert.h>
#include <lib/ddk/debug.h>
#include <lib/ddk/device.h>
#include <lib/ddk/driver.h>
#include <lib/ddk/hw/reg.h>
#include <lib/ddk/metadata.h>
#include <lib/ddk/platform-defs.h>
#include <lib/fit/defer.h>
#include <lib/zx/time.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zircon/errors.h>

#include <cstdio>
#include <sstream>
#include <string>

#include <ddktl/fidl.h>
#include <fbl/algorithm.h>
#include <fbl/auto_lock.h>

#include "src/devices/usb/drivers/vim3-usb-phy/vim3_usb_phy_bind.h"
#include "usb-phy-regs.h"

namespace vim3_usb_phy {

// Based on set_usb_pll() in phy-aml-new-usb2-v2.c
void Vim3UsbPhy::InitPll(fdf::MmioBuffer* mmio) {
  PLL_REGISTER_40::Get()
      .FromValue(0)
      .set_value(pll_settings_[0])
      .set_enable(1)
      .set_reset(1)
      .WriteTo(mmio);

  PLL_REGISTER::Get(0x44).FromValue(pll_settings_[1]).WriteTo(mmio);

  PLL_REGISTER::Get(0x48).FromValue(pll_settings_[2]).WriteTo(mmio);

  zx::nanosleep(zx::deadline_after(zx::usec(100)));

  PLL_REGISTER_40::Get()
      .FromValue(0)
      .set_value(pll_settings_[0])
      .set_enable(1)
      .set_reset(0)
      .WriteTo(mmio);

  // PLL

  zx::nanosleep(zx::deadline_after(zx::usec(100)));

  PLL_REGISTER::Get(0x50).FromValue(pll_settings_[3]).WriteTo(mmio);

  PLL_REGISTER::Get(0x10).FromValue(pll_settings_[4]).WriteTo(mmio);

  // Recovery state
  PLL_REGISTER::Get(0x38).FromValue(0).WriteTo(mmio);

  PLL_REGISTER::Get(0x34).FromValue(pll_settings_[5]).WriteTo(mmio);

  // Disconnect threshold
  PLL_REGISTER::Get(0xc).FromValue(0x3c).WriteTo(mmio);

  // Tuning

  zx::nanosleep(zx::deadline_after(zx::usec(100)));

  PLL_REGISTER::Get(0x38).FromValue(pll_settings_[6]).WriteTo(mmio);

  PLL_REGISTER::Get(0x34).FromValue(pll_settings_[5]).WriteTo(mmio);

  zx::nanosleep(zx::deadline_after(zx::usec(100)));
}

zx_status_t Vim3UsbPhy::InitPhy() {
  auto* usbctrl_mmio = &*usbctrl_mmio_;

  // first reset USB
  // The bits being manipulated here are not documented.
  auto level_result =
      reset_register_->WriteRegister32(RESET1_LEVEL_OFFSET, aml_registers::USB_RESET1_LEVEL_MASK,
                                       aml_registers::USB_RESET1_LEVEL_MASK);
  if ((level_result.status() != ZX_OK) || level_result->is_error()) {
    zxlogf(ERROR, "%s: Reset Level Write failed\n", __func__);
    return ZX_ERR_INTERNAL;
  }

  // amlogic_new_usbphy_reset_v2()
  auto register_result1 = reset_register_->WriteRegister32(
      RESET1_REGISTER_OFFSET, aml_registers::USB_RESET1_REGISTER_UNKNOWN_1_MASK,
      aml_registers::USB_RESET1_REGISTER_UNKNOWN_1_MASK);
  if ((register_result1.status() != ZX_OK) || register_result1->is_error()) {
    zxlogf(ERROR, "%s: Reset Register Write on 1 << 2 failed\n", __func__);
    return ZX_ERR_INTERNAL;
  }
  // FIXME(voydanoff) this delay is very long, but it is what the Amlogic Linux kernel is doing.
  zx::nanosleep(zx::deadline_after(zx::usec(500)));

  // amlogic_new_usb2_init()
  for (int i = 0; i < 2; i++) {
    U2P_R0_V2::Get(i).ReadFrom(usbctrl_mmio).set_por(1).WriteTo(usbctrl_mmio);
    if (i == 1) {
      U2P_R0_V2::Get(i)
          .ReadFrom(usbctrl_mmio)
          .set_idpullup0(1)
          .set_drvvbus0(1)
          .set_host_device((dr_mode_ == USB_MODE_PERIPHERAL) ? 0 : 1)
          .WriteTo(usbctrl_mmio);
    } else {
      U2P_R0_V2::Get(i).ReadFrom(usbctrl_mmio).set_host_device(1).WriteTo(usbctrl_mmio);
    }
    U2P_R0_V2::Get(i).ReadFrom(usbctrl_mmio).set_por(0).WriteTo(usbctrl_mmio);

    zx::nanosleep(zx::deadline_after(zx::usec(10)));

    // amlogic_new_usbphy_reset_phycfg_v2()
    // The bit being manipulated here is not documented.
    auto register_result2 = reset_register_->WriteRegister32(
        RESET1_REGISTER_OFFSET, aml_registers::USB_RESET1_REGISTER_UNKNOWN_2_MASK,
        aml_registers::USB_RESET1_REGISTER_UNKNOWN_2_MASK);
    if ((register_result2.status() != ZX_OK) || register_result2->is_error()) {
      zxlogf(ERROR, "%s: Reset Register Write on 1 << 16 failed\n", __func__);
      return ZX_ERR_INTERNAL;
    }

    zx::nanosleep(zx::deadline_after(zx::usec(50)));

    auto u2p_r1 = U2P_R1_V2::Get(i);

    int count = 0;
    while (!u2p_r1.ReadFrom(usbctrl_mmio).phy_rdy()) {
      // wait phy ready max 5ms, common is 100us
      if (count > 1000) {
        zxlogf(WARNING, "Vim3UsbPhy::InitPhy U2P_R1_PHY_RDY wait failed");
        break;
      }

      count++;
      zx::nanosleep(zx::deadline_after(zx::usec(5)));
    }
  }

  return ZX_OK;
}

zx_status_t Vim3UsbPhy::InitOtg() {
  auto* mmio = &*usbctrl_mmio_;

  USB_R1_V2::Get().ReadFrom(mmio).set_u3h_fladj_30mhz_reg(0x20).WriteTo(mmio);

  USB_R5_V2::Get().ReadFrom(mmio).set_iddig_en0(1).set_iddig_en1(1).set_iddig_th(255).WriteTo(mmio);

  return ZX_OK;
}

void Vim3UsbPhy::SetMode(UsbMode mode, SetModeCompletion completion) {
  ZX_DEBUG_ASSERT(mode == UsbMode::HOST || mode == UsbMode::PERIPHERAL);
  // Only the irq thread calls |SetMode|, and it should have waited for the
  // previous call to |SetMode| to complete.
  ZX_DEBUG_ASSERT(!set_mode_completion_);
  auto cleanup = fit::defer([&]() {
    if (completion)
      completion();
  });

  if (mode == phy_mode_)
    return;

  auto* usbctrl_mmio = &*usbctrl_mmio_;

  auto r0 = USB_R0_V2::Get().ReadFrom(usbctrl_mmio);
  if (mode == UsbMode::HOST) {
    r0.set_u2d_act(0);
  } else {
    r0.set_u2d_act(1);
    r0.set_u2d_ss_scaledown_mode(0);
  }
  r0.WriteTo(usbctrl_mmio);

  USB_R4_V2::Get()
      .ReadFrom(usbctrl_mmio)
      .set_p21_sleepm0(mode == UsbMode::PERIPHERAL)
      .WriteTo(usbctrl_mmio);

  U2P_R0_V2::Get(0)
      .ReadFrom(usbctrl_mmio)
      .set_host_device(mode == UsbMode::HOST)
      .set_por(0)
      .WriteTo(usbctrl_mmio);

  zx::nanosleep(zx::deadline_after(zx::usec(500)));

  auto old_mode = phy_mode_;
  phy_mode_ = mode;

  if (old_mode == UsbMode::UNKNOWN) {
    // One time PLL initialization
    InitPll(&*usbphy20_mmio_);
    InitPll(&*usbphy21_mmio_);
  } else {
    auto* phy_mmio = &*usbphy21_mmio_;

    PLL_REGISTER::Get(0x38)
        .FromValue(mode == UsbMode::HOST ? pll_settings_[6] : 0)
        .WriteTo(phy_mmio);
    PLL_REGISTER::Get(0x34).FromValue(pll_settings_[5]).WriteTo(phy_mmio);
  }

  AddXhciDevice();
  AddDwc2Device();
}

int Vim3UsbPhy::IrqThread() {
  auto* mmio = &*usbctrl_mmio_;

  // Wait for PHY to stabilize before reading initial mode.
  zx::nanosleep(zx::deadline_after(zx::sec(1)));

  lock_.Acquire();

  while (true) {
    auto r5 = USB_R5_V2::Get().ReadFrom(mmio);

    // Since |SetMode| is asynchronous, we need to block until it completes.
    sync_completion_t set_mode_sync;
    auto completion = [&](void) { sync_completion_signal(&set_mode_sync); };
    // Read current host/device role.
    if (r5.iddig_curr() == 0) {
      zxlogf(INFO, "Entering USB Host Mode");
      SetMode(UsbMode::HOST, std::move(completion));
    } else {
      zxlogf(INFO, "Entering USB Peripheral Mode");
      SetMode(UsbMode::PERIPHERAL, std::move(completion));
    }

    lock_.Release();
    sync_completion_wait(&set_mode_sync, ZX_TIME_INFINITE);
    auto status = irq_.wait(nullptr);
    if (status == ZX_ERR_CANCELED) {
      return 0;
    } else if (status != ZX_OK) {
      zxlogf(ERROR, "%s: irq_.wait failed: %d", __func__, status);
      return -1;
    }
    lock_.Acquire();

    // Acknowledge interrupt
    r5.ReadFrom(mmio).set_usb_iddig_irq(0).WriteTo(mmio);
  }

  lock_.Release();

  return 0;
}

zx_status_t Vim3UsbPhy::Create(void* ctx, zx_device_t* parent) {
  auto dev = std::make_unique<Vim3UsbPhy>(parent);

  auto status = dev->Init();
  if (status != ZX_OK) {
    return status;
  }

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

zx_status_t Vim3UsbPhy::AddXhciDevice() {
  if (xhci_device_) {
    return ZX_ERR_BAD_STATE;
  }

  xhci_device_ = std::make_unique<XhciDevice>(zxdev());

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

  return xhci_device_->DdkAdd(
      ddk::DeviceAddArgs("xhci").set_props(props).set_proto_id(ZX_PROTOCOL_USB_PHY));
}

void Vim3UsbPhy::RemoveXhciDevice(SetModeCompletion completion) {
  auto cleanup = fit::defer([&]() {
    if (completion)
      completion();
  });
  if (xhci_device_) {
    // The callback will be run by the ChildPreRelease hook once the xhci device has been removed.
    set_mode_completion_ = std::move(completion);
    xhci_device_->DdkAsyncRemove();
  }
}

zx_status_t Vim3UsbPhy::AddDwc2Device() {
  if (dwc2_device_) {
    return ZX_ERR_BAD_STATE;
  }

  dwc2_device_ = std::make_unique<Dwc2Device>(zxdev());

  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(
      ddk::DeviceAddArgs("dwc2").set_props(props).set_proto_id(ZX_PROTOCOL_USB_PHY));
}

void Vim3UsbPhy::RemoveDwc2Device(SetModeCompletion completion) {
  auto cleanup = fit::defer([&]() {
    if (completion)
      completion();
  });
  if (dwc2_device_) {
    // The callback will be run by the ChildPreRelease hook once the dwc2 device has been removed.
    set_mode_completion_ = std::move(completion);
    dwc2_device_->DdkAsyncRemove();
  }
}

zx_status_t Vim3UsbPhy::Init() {
  zx_status_t status = ZX_OK;
  pdev_ = ddk::PDev::FromFragment(parent());
  if (!pdev_.is_valid()) {
    zxlogf(ERROR, "Vim3UsbPhy::Init: could not get platform device protocol");
    return ZX_ERR_NOT_SUPPORTED;
  }

  ddk::RegistersProtocolClient reset_register(parent(), "register-reset");
  if (!reset_register.is_valid()) {
    zxlogf(ERROR, "%s: could not get reset_register fragment", __func__);
    return ZX_ERR_NO_RESOURCES;
  }
  zx::channel register_client_end, register_server_end;
  if ((status = zx::channel::create(0, &register_client_end, &register_server_end)) != ZX_OK) {
    zxlogf(ERROR, "%s: could not create channel %d\n", __func__, status);
    return status;
  }
  reset_register.Connect(std::move(register_server_end));
  reset_register_ =
      fidl::WireSyncClient<fuchsia_hardware_registers::Device>(std::move(register_client_end));

  size_t actual;
  status = DdkGetMetadata(DEVICE_METADATA_PRIVATE, pll_settings_, sizeof(pll_settings_), &actual);
  if (status != ZX_OK || actual != sizeof(pll_settings_)) {
    zxlogf(ERROR, "Vim3UsbPhy::Init could not get metadata for PLL settings");
    return ZX_ERR_INTERNAL;
  }
  status = DdkGetMetadata(DEVICE_METADATA_USB_MODE, &dr_mode_, sizeof(dr_mode_), &actual);
  if (status == ZX_OK && actual != sizeof(dr_mode_)) {
    zxlogf(ERROR, "Vim3UsbPhy::Init could not get metadata for USB Mode");
    return ZX_ERR_INTERNAL;
  } else if (status != ZX_OK) {
    dr_mode_ = USB_MODE_OTG;
  }

  status = pdev_.MapMmio(0, &usbctrl_mmio_);
  if (status != ZX_OK) {
    return status;
  }
  status = pdev_.MapMmio(1, &usbphy20_mmio_);
  if (status != ZX_OK) {
    return status;
  }
  status = pdev_.MapMmio(2, &usbphy21_mmio_);
  if (status != ZX_OK) {
    return status;
  }

  status = pdev_.GetInterrupt(0, &irq_);
  if (status != ZX_OK) {
    return status;
  }

  status = InitPhy();
  if (status != ZX_OK) {
    return status;
  }
  status = InitOtg();
  if (status != ZX_OK) {
    return status;
  }

  return DdkAdd("vim3-usb-phy", DEVICE_ADD_NON_BINDABLE);
}

void Vim3UsbPhy::DdkInit(ddk::InitTxn txn) {
  if (dr_mode_ != USB_MODE_OTG) {
    sync_completion_t set_mode_sync;
    auto completion = [&](void) { sync_completion_signal(&set_mode_sync); };
    fbl::AutoLock lock(&lock_);
    if (dr_mode_ == USB_MODE_PERIPHERAL) {
      zxlogf(INFO, "Entering USB Peripheral Mode");
      SetMode(UsbMode::PERIPHERAL, std::move(completion));
    } else {
      zxlogf(INFO, "Entering USB Host Mode");
      SetMode(UsbMode::HOST, std::move(completion));
    }
    sync_completion_wait(&set_mode_sync, ZX_TIME_INFINITE);

    return txn.Reply(ZX_OK);
  }

  irq_thread_started_ = true;
  int rc = thrd_create_with_name(
      &irq_thread_,
      [](void* arg) -> int { return reinterpret_cast<Vim3UsbPhy*>(arg)->IrqThread(); },
      reinterpret_cast<void*>(this), "amlogic-usb-thread");
  if (rc != thrd_success) {
    irq_thread_started_ = false;
    return txn.Reply(ZX_ERR_INTERNAL);  // This will schedule the device to be unbound.
  }
  return txn.Reply(ZX_OK);
}

// PHY tuning based on connection state
void Vim3UsbPhy::UsbPhyConnectStatusChanged(bool connected) {
  fbl::AutoLock lock(&lock_);

  if (dwc2_connected_ == connected)
    return;

  auto* mmio = &*usbphy21_mmio_;

  if (connected) {
    PLL_REGISTER::Get(0x38).FromValue(pll_settings_[7]).WriteTo(mmio);
    PLL_REGISTER::Get(0x34).FromValue(pll_settings_[5]).WriteTo(mmio);
  } else {
    InitPll(mmio);
  }

  dwc2_connected_ = connected;
}

void Vim3UsbPhy::DdkUnbind(ddk::UnbindTxn txn) {
  irq_.destroy();
  if (irq_thread_started_) {
    thrd_join(irq_thread_, nullptr);
  }
  txn.Reply();
}

void Vim3UsbPhy::DdkChildPreRelease(void* child_ctx) {
  fbl::AutoLock lock(&lock_);
  // devmgr will own the device until it is destroyed.
  if (xhci_device_ && (child_ctx == xhci_device_.get())) {
    __UNUSED auto* dev = xhci_device_.release();
  } else if (dwc2_device_ && (child_ctx == dwc2_device_.get())) {
    __UNUSED auto* dev = dwc2_device_.release();
  } else {
    zxlogf(ERROR, "Vim3UsbPhy::DdkChildPreRelease unexpected child ctx %p", child_ctx);
  }
  if (set_mode_completion_) {
    // If the mode is currently being set, the irq thread will be blocked
    // until we call this completion.
    set_mode_completion_();
  }
}

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

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

}  // namespace vim3_usb_phy

ZIRCON_DRIVER(vim3_usb_phy, vim3_usb_phy::driver_ops, "zircon", "0.1");
