// 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 "mtk-spi.h"

#include <lib/device-protocol/pdev.h>
#include <unistd.h>

#include <ddk/binding.h>
#include <ddk/debug.h>
#include <ddk/metadata.h>
#include <ddk/metadata/spi.h>
#include <ddk/platform-defs.h>
#include <fbl/alloc_checker.h>
#include <fbl/auto_call.h>

#include "registers.h"

namespace spi {

namespace {

constexpr size_t kFifoAccessSize = 4;
constexpr size_t kMaxFifoSize = 32;  // Depth of FIFO is 32 bytes.
constexpr uint32_t kDummy = 0xFFFFFFFF;

}  // namespace

void MtkSpi::FifoTransferPacket(const uint8_t** tx, uint8_t** rx, size_t packet_size) {
  // Transfer
  {  // Fill FIFO
    for (size_t bytes_left = packet_size; bytes_left > 0;) {
      const size_t transfer_size = std::min(kFifoAccessSize, bytes_left);

      if (*tx) {
        uint32_t i32 = 0;
        memcpy(&i32, *tx, transfer_size);
        mmio_.Write32(i32, MTK_SPI_TX_DATA);
        *tx += transfer_size;
      } else {
        mmio_.Write32(kDummy, MTK_SPI_TX_DATA);
      }

      bytes_left -= transfer_size;
    }

    // Enable transfer
    CmdReg::Get().ReadFrom(&mmio_).set_activate(1).WriteTo(&mmio_);
  }

  // Wait for completion
  auto busy = Status1Reg::Get().ReadFrom(&mmio_);
  while (!busy.busy()) {
    busy.ReadFrom(&mmio_);
  };

  // Receive
  {
    for (size_t bytes_left = packet_size; bytes_left > 0;) {
      const size_t transfer_size = std::min(kFifoAccessSize, bytes_left);

      auto data = mmio_.Read32(MTK_SPI_RX_DATA);
      if (*rx) {
        memcpy(*rx, &data, transfer_size);
        *rx += transfer_size;
      }

      bytes_left -= transfer_size;
    }
  }
}

zx_status_t MtkSpi::FifoExchange(const uint8_t* txdata, uint8_t* out_rxdata, size_t data_size) {
  CmdReg::Get().ReadFrom(&mmio_).set_tx_dma_en(0).set_rx_dma_en(0).WriteTo(&mmio_);  // Disable DMA

  // Setup packet
  auto packet_size = std::min(kMaxFifoSize, data_size);
  auto packet_loop = static_cast<uint32_t>(data_size / packet_size);
  Cfg1Reg::Get()
      .ReadFrom(&mmio_)
      .set_packet_length(static_cast<uint32_t>(packet_size - 1))
      .set_packet_loop_count(packet_loop - 1)
      .WriteTo(&mmio_);

  const uint8_t* tx = txdata;
  uint8_t* rx = out_rxdata;
  for (uint32_t loop = 0; loop < packet_loop; loop++) {
    FifoTransferPacket(&tx, &rx, packet_size);
  }

  return (data_size % packet_size) ? FifoExchange(tx, rx, data_size % packet_size) : ZX_OK;
}

zx_status_t MtkSpi::SpiImplExchange(uint32_t cs, const uint8_t* txdata, size_t txdata_size,
                                    uint8_t* out_rxdata, size_t rxdata_size,
                                    size_t* out_rxdata_actual) {
  if (cs >= SpiImplGetChipSelectCount()) {
    return ZX_ERR_INVALID_ARGS;
  }

  if ((txdata_size && rxdata_size && (txdata_size != rxdata_size)) || (!txdata && !out_rxdata) ||
      (static_cast<bool>(txdata) ^ static_cast<bool>(txdata_size)) ||
      (static_cast<bool>(out_rxdata) ^ static_cast<bool>(rxdata_size))) {
    return ZX_ERR_INVALID_ARGS;
  }
  size_t data_size = txdata_size ? txdata_size : rxdata_size;

  memset(out_rxdata, 0, rxdata_size);

  zx_status_t status = ZX_OK;
  // Using FIFO for now, could also support DMA
  if ((status = FifoExchange(txdata, out_rxdata, data_size)) != ZX_OK) {
    zxlogf(ERROR, "%s: FifoExchange failed with %d\n", __func__, status);
    return status;
  }

  *out_rxdata_actual = rxdata_size;

  return ZX_OK;
}

zx_status_t MtkSpi::Init() {
  // Reset
  CmdReg::Get().ReadFrom(&mmio_).set_reset(1).WriteTo(&mmio_);
  CmdReg::Get().ReadFrom(&mmio_).set_reset(0).WriteTo(&mmio_);

  CmdReg::Get().ReadFrom(&mmio_).set_rx_msb_first(1).set_tx_msb_first(1).WriteTo(&mmio_);

  // Prepare transfer
  uint32_t div =
      (speed_hz_ < spi_clk_hz_ / 2) ? static_cast<uint32_t>((spi_clk_hz_ + 0.5) / speed_hz_) : 1;
  uint32_t sck_time = (div + 1) / 2;
  uint32_t cs_time = sck_time * 2;
  Cfg0Reg::Get()
      .ReadFrom(&mmio_)
      .set_cs_setup_count((cs_time - 1) & 0xFF)
      .set_cs_hold_count((cs_time - 1) & 0xFF)
      .WriteTo(&mmio_);
  Cfg2Reg::Get()
      .ReadFrom(&mmio_)
      .set_sck_low_count((sck_time - 1) & 0xFF)
      .set_sck_high_count((sck_time - 1) & 0xFF)
      .WriteTo(&mmio_);
  Cfg1Reg::Get().ReadFrom(&mmio_).set_cs_idle_count((cs_time - 1) & 0xFF).WriteTo(&mmio_);

  return ZX_OK;
}

zx_status_t MtkSpi::Create(void* ctx, zx_device_t* device) {
  ddk::PDev pdev(device);
  if (!pdev.is_valid()) {
    zxlogf(ERROR, "%s: Could not get pdev protocol\n", __func__);
    return ZX_ERR_NOT_SUPPORTED;
  }

  zx_status_t status = ZX_OK;
  size_t metadata_size, actual;
  if ((status = device_get_metadata_size(device, DEVICE_METADATA_SPI_CHANNELS, &metadata_size)) !=
      ZX_OK) {
    zxlogf(ERROR, "%s: device_get_metadata_size failed %d\n", __func__, status);
    return ZX_ERR_INTERNAL;
  }
  auto channel_count = metadata_size / sizeof(spi_channel_t);
  fbl::AllocChecker ac;
  std::unique_ptr<spi_channel_t[]> channels(new (&ac) spi_channel_t[channel_count]);
  if (!ac.check()) {
    zxlogf(ERROR, "%s: out of memory\n", __func__);
    return ZX_ERR_NO_MEMORY;
  }
  status = device_get_metadata(device, DEVICE_METADATA_SPI_CHANNELS, channels.get(), metadata_size,
                               &actual);
  if (status != ZX_OK || actual != metadata_size) {
    zxlogf(ERROR, "%s: device_get_metadata failed %d\n", __func__, status);
    return ZX_ERR_INTERNAL;
  }

  for (uint32_t i = 0; i < channel_count; i++) {
    std::optional<ddk::MmioBuffer> mmio;
    if ((status = pdev.MapMmio(i, &mmio)) != ZX_OK) {
      zxlogf(ERROR, "%s: could not map mmio %d\n", __func__, status);
      return status;
    }

    fbl::AllocChecker ac;
    auto spi = fbl::make_unique_checked<MtkSpi>(&ac, device, std::move(mmio.value()));
    if (!ac.check()) {
      return ZX_ERR_NO_MEMORY;
    }

    if ((status = spi->Init()) != ZX_OK) {
      zxlogf(ERROR, "%s could not init %d\n", __func__, status);
      return status;
    }

    char devname[32];
    sprintf(devname, "mtk-spi-%d", channels[i].bus_id);
    status = spi->DdkAdd(devname);
    if (status != ZX_OK) {
      zxlogf(ERROR, "%s: DdkDeviceAdd failed for %s\n", __func__, devname);
      return status;
    }
    auto* ptr = spi.release();

    auto cleanup = fbl::MakeAutoCall([&ptr]() { ptr->DdkAsyncRemove(); });

    status = ptr->DdkAddMetadata(DEVICE_METADATA_PRIVATE, &channels[i].bus_id,
                                 sizeof channels[i].bus_id);
    if (status != ZX_OK) {
      zxlogf(ERROR, "%s: DdkAddMetadata failed for %s\n", __func__, devname);
      return status;
    }

    cleanup.cancel();
  }

  return ZX_OK;
}

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

}  // namespace spi

// clang-format off
ZIRCON_DRIVER_BEGIN(mtk_spi, spi::driver_ops, "zircon", "0.1", 3)
    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_PDEV),
    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_MEDIATEK),
    BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_MEDIATEK_SPI),
ZIRCON_DRIVER_END(mtk_spi)
