// 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", __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", __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", __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", __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", __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", __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", __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", __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", __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)
