// Copyright 2020 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 "aml-ram.h"

#include <lib/device-protocol/pdev.h>
#include <lib/zx/clock.h>
#include <zircon/assert.h>

#include <ddk/binding.h>
#include <ddk/debug.h>
#include <ddk/driver.h>
#include <ddk/platform-defs.h>
#include <ddktl/fidl.h>
#include <fbl/alloc_checker.h>
#include <fbl/auto_call.h>
#include <fbl/auto_lock.h>
#include <soc/aml-s905d2/s905d2-hw.h>

namespace amlogic_ram {

constexpr size_t kMaxPendingRequests = 64u;

constexpr uint64_t kPortKeyIrqMsg = 0x0;
constexpr uint64_t kPortKeyCancelMsg = 0x1;
constexpr uint64_t kPortKeyWorkPendingMsg = 0x2;

// TODO(reveman): Understand why this is 16. Configurable and a product
// decision, or simply the way these counters are wired?
constexpr uint64_t kBytesPerCycle = 16ul;

zx_status_t ValidateRequest(const ram_metrics::BandwidthMeasurementConfig& config) {
  // Restrict timer to reasonable values.
  if ((config.cycles_to_measure < kMinimumCycleCount) ||
      (config.cycles_to_measure > kMaximumCycleCount)) {
    return ZX_ERR_INVALID_ARGS;
  }

  int enabled_count = 0;

  for (size_t ix = 0; ix != ram_metrics::MAX_COUNT_CHANNELS; ++ix) {
    auto& channel = config.channels[ix];

    if ((ix >= MEMBW_MAX_CHANNELS) && (channel != 0)) {
      // We only support the first four channels.
      return ZX_ERR_INVALID_ARGS;
    }

    if (channel > 0xffffffff) {
      // We don't support sub-ports (bits above 31) yet.
      return ZX_ERR_NOT_SUPPORTED;
    }

    if (channel != 0) {
      ++enabled_count;
    }
  }

  // At least one channel had at least one port.
  if (enabled_count == 0) {
    return ZX_ERR_INVALID_ARGS;
  }

  return ZX_OK;
}

zx_status_t AmlRam::Create(void* context, zx_device_t* parent) {
  zx_status_t status;
  ddk::PDev pdev(parent);
  std::optional<ddk::MmioBuffer> mmio;
  if ((status = pdev.MapMmio(0, &mmio)) != ZX_OK) {
    zxlogf(ERROR, "aml-ram: Failed to map mmio, st = %d", status);
    return status;
  }

  zx::interrupt irq;
  status = pdev.GetInterrupt(0, &irq);
  if (status != ZX_OK) {
    zxlogf(ERROR, "aml-ram: Failed to map interrupt, st = %d", status);
    return status;
  }

  zx::port port;
  status = zx::port::create(ZX_PORT_BIND_TO_INTERRUPT, &port);
  if (status != ZX_OK) {
    zxlogf(ERROR, "aml-ram: Failed to create port, st = %d", status);
    return status;
  }

  status = irq.bind(port, kPortKeyIrqMsg, 0 /*options*/);
  if (status != ZX_OK) {
    zxlogf(ERROR, "aml-ram: Failed to bind interrupt, st = %d", status);
    return status;
  }

  pdev_device_info_t info;
  status = pdev.GetDeviceInfo(&info);
  if (status != ZX_OK) {
    zxlogf(ERROR, "aml-ram: Failed to get device info, st = %d", status);
    return status;
  }

  fbl::AllocChecker ac;
  auto device = fbl::make_unique_checked<AmlRam>(&ac, parent, *std::move(mmio), std::move(irq),
                                                 std::move(port), info.pid);
  if (!ac.check()) {
    zxlogf(ERROR, "aml-ram: Failed to allocate device memory");
    return ZX_ERR_NO_MEMORY;
  }

  status = device->DdkAdd(ddk::DeviceAddArgs("ram")
                              .set_flags(DEVICE_ADD_NON_BINDABLE)
                              .set_proto_id(ZX_PROTOCOL_AMLOGIC_RAM));
  if (status != ZX_OK) {
    zxlogf(ERROR, "aml-ram: Failed to add ram device, st = %d", status);
    return status;
  }

  // It's now the responsibility of |DdkRelease| to free this object.
  __UNUSED auto* dummy = device.release();
  return ZX_OK;
}

AmlRam::AmlRam(zx_device_t* parent, ddk::MmioBuffer mmio, zx::interrupt irq, zx::port port,
               uint32_t device_pid)
    : DeviceType(parent), mmio_(std::move(mmio)), irq_(std::move(irq)), port_(std::move(port)) {
  // TODO(fxbug.dev/53325): ALL_GRANT counter is broken on S905D2.
  all_grant_broken_ = device_pid == PDEV_PID_AMLOGIC_S905D2;

  // Read windowing data:
  // The S905D2 and the T931 both support the DMC_STICKY_1 register, which is where the
  // DDR Windowing tool writes its results.
  if (device_pid == PDEV_PID_AMLOGIC_S905D2 || device_pid == PDEV_PID_AMLOGIC_T931) {
    windowing_data_supported_ = true;
  } else {
    windowing_data_supported_ = false;
  }
}

AmlRam::~AmlRam() {
  // Verify we drained all requests.
  ZX_ASSERT(requests_.empty());
}

void AmlRam::DdkSuspend(ddk::SuspendTxn txn) {
  // TODO(cpu): First put the device into txn.requested_state().
  if (txn.suspend_reason() & (DEVICE_SUSPEND_REASON_POWEROFF | DEVICE_SUSPEND_REASON_MEXEC |
                              DEVICE_SUSPEND_REASON_REBOOT)) {
    // Do any additional cleanup that is needed while shutting down the driver.
    Shutdown();
  }
  txn.Reply(ZX_OK, txn.requested_state());
}

void AmlRam::DdkRelease() {
  Shutdown();
  delete this;
}

zx_status_t AmlRam::DdkMessage(fidl_incoming_msg_t* msg, fidl_txn_t* txn) {
  DdkTransaction transaction(txn);
  ram_metrics::Device::Dispatch(this, msg, &transaction);
  return transaction.Status();
}

void AmlRam::MeasureBandwidth(ram_metrics::BandwidthMeasurementConfig config,
                              MeasureBandwidthCompleter::Sync& completer) {
  zx_status_t st = ValidateRequest(config);
  if (st != ZX_OK) {
    zxlogf(ERROR, "aml-ram: bad request\n");
    completer.ReplyError(st);
    return;
  }

  if (!thread_.joinable()) {
    thread_ = std::thread([this] { ReadLoop(); });
  }

  {
    fbl::AutoLock lock(&lock_);

    if (requests_.size() > kMaxPendingRequests) {
      // Once the queue is shorter the request would likely succeed.
      completer.ReplyError(ZX_ERR_SHOULD_WAIT);
      return;
    }

    // Enqueue task and signal worker thread as needed.
    requests_.emplace_back(std::move(config), completer.ToAsync());
    if (requests_.size() == 1u) {
      zx_port_packet_t packet = {
          .key = kPortKeyWorkPendingMsg, .type = ZX_PKT_TYPE_USER, .status = ZX_OK};
      ZX_ASSERT(port_.queue(&packet) == ZX_OK);
    }
  }
}

void AmlRam::GetDdrWindowingResults(GetDdrWindowingResultsCompleter::Sync& completer) {
  if (windowing_data_supported_) {
    completer.ReplySuccess(mmio_.Read32(DMC_STICKY_1));
  } else {
    zxlogf(ERROR, "aml-ram: windowing data is not supported\n");
    completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
  }
}

void AmlRam::StartReadBandwithCounters(Job* job) {
  uint32_t channels_enabled = 0u;
  for (size_t ix = 0; ix != MEMBW_MAX_CHANNELS; ++ix) {
    channels_enabled |= (job->config.channels[ix] != 0) ? (1u << ix) : 0;
    mmio_.Write32(static_cast<uint32_t>(job->config.channels[ix]), MEMBW_RP[ix]);
    mmio_.Write32(0xffff, MEMBW_SP[ix]);
  }

  job->start_time = zx_clock_get_monotonic();
  mmio_.Write32(static_cast<uint32_t>(job->config.cycles_to_measure), MEMBW_TIMER);
  mmio_.Write32(channels_enabled | DMC_QOS_ENABLE_CTRL, MEMBW_PORTS_CTRL);
}

void AmlRam::FinishReadBandwithCounters(ram_metrics::BandwidthInfo* bpi, zx_time_t start_time) {
  ZX_ASSERT(irq_.ack() == ZX_OK);

  bpi->timestamp = start_time;
  bpi->frequency = ReadFrequency();
  bpi->bytes_per_cycle = kBytesPerCycle;

  uint32_t value = mmio_.Read32(MEMBW_PORTS_CTRL);
  ZX_ASSERT((value & DMC_QOS_ENABLE_CTRL) == 0);

  bpi->channels[0].readwrite_cycles = mmio_.Read32(MEMBW_C0_GRANT_CNT);
  bpi->channels[1].readwrite_cycles = mmio_.Read32(MEMBW_C1_GRANT_CNT);
  bpi->channels[2].readwrite_cycles = mmio_.Read32(MEMBW_C2_GRANT_CNT);
  bpi->channels[3].readwrite_cycles = mmio_.Read32(MEMBW_C3_GRANT_CNT);

  bpi->total.readwrite_cycles = all_grant_broken_ ? 0 : mmio_.Read32(MEMBW_ALL_GRANT_CNT);

  mmio_.Write32(0x0f | DMC_QOS_CLEAR_CTRL, MEMBW_PORTS_CTRL);
}

void AmlRam::CancelReadBandwithCounters() {
  mmio_.Write32(0x0f | DMC_QOS_CLEAR_CTRL, MEMBW_PORTS_CTRL);
  // Here there might be a pending interrupt packet. The caller
  // is going to exit so it is immaterial if we drain it or
  // not.
}

void AmlRam::ReadLoop() {
  std::deque<Job> jobs;

  for (;;) {
    zx_port_packet_t packet;
    auto status = port_.wait(zx::time::infinite(), &packet);
    if (status != ZX_OK) {
      zxlogf(ERROR, "aml-ram: error in wait, st =%d\n", status);
      return;
    }

    switch (packet.key) {
      case kPortKeyWorkPendingMsg: {
        AcceptJobs(&jobs);
        StartReadBandwithCounters(&jobs.front());
        break;
      }

      case kPortKeyIrqMsg: {
        ZX_ASSERT(!jobs.empty());
        ram_metrics::BandwidthInfo bpi;
        FinishReadBandwithCounters(&bpi, jobs.front().start_time);
        Job job = std::move(jobs.front());
        jobs.pop_front();
        // Start new measurement before we reply the current one.
        if (!jobs.empty()) {
          StartReadBandwithCounters(&jobs.front());
        }
        job.completer.ReplySuccess(bpi);
        break;
      }

      case kPortKeyCancelMsg: {
        if (!jobs.empty()) {
          CancelReadBandwithCounters();
          RevertJobs(&jobs);
        }
        return;
      }

      default: {
        ZX_ASSERT(false);
      }
    }
  }
}

// Merge back the request jobs from the local jobs in |source| preserving
// the order of arrival: the last job in |source| is ahead of the
// first job in |request_|.
void AmlRam::RevertJobs(std::deque<AmlRam::Job>* source) {
  fbl::AutoLock lock(&lock_);
  requests_.insert(requests_.begin(), std::make_move_iterator(source->begin()),
                   std::make_move_iterator(source->end()));
  source->clear();
}

// Merge requests from |request_| into local jobs while preserving order
// of arrival.
void AmlRam::AcceptJobs(std::deque<AmlRam::Job>* dest) {
  fbl::AutoLock lock(&lock_);
  dest->insert(dest->end(), std::make_move_iterator(requests_.begin()),
               std::make_move_iterator(requests_.end()));
  requests_.clear();
}

void AmlRam::Shutdown() {
  if (thread_.joinable()) {
    {
      fbl::AutoLock lock(&lock_);
      shutdown_ = true;
      zx_port_packet_t packet = {
          .key = kPortKeyCancelMsg, .type = ZX_PKT_TYPE_USER, .status = ZX_OK};
      ZX_ASSERT(port_.queue(&packet) == ZX_OK);
    }
    thread_.join();
    // Cancel all pending requests. There are no more threads
    // but we still take the lock to keep lock checker happy.
    {
      fbl::AutoLock lock(&lock_);
      for (auto& request : requests_) {
        request.completer.Close(ZX_ERR_CANCELED);
      }
      requests_.clear();
    }
  }
}

uint64_t AmlRam::ReadFrequency() const {
  uint32_t value = mmio_.Read32(MEMBW_PLL_CNTL);
  uint64_t dpll_int_num = value & 0x1ff;
  uint64_t dpll_ref_div_n = (value >> 10) & 0x1f;
  uint64_t od = (value >> 16) & 0x7;
  uint64_t od1 = (value >> 19) & 0x1;

  ZX_ASSERT(dpll_ref_div_n);
  uint64_t od_div = 1;
  switch (od) {
    case 0:
      od_div = 2;  // 000:/2
      break;
    case 1:
      od_div = 3;  // 001:/3
      break;
    case 2:
      od_div = 4;  // 010:/4
      break;
    case 3:
      od_div = 6;  // 011:/6
      break;
    case 4:
      od_div = 8;  // 100:/8
      break;
  }
  uint64_t od1_shift = od1 == 0 ? 1 : 2;  // 0:/2, 1:/4
  // Frequency is calculated with the following equation:
  //
  // f = fREF * (M + frac) / N
  //
  constexpr uint64_t kFreqRef = 24000000;
  return (((kFreqRef * dpll_int_num) / dpll_ref_div_n) >> od1_shift) / od_div;
}

}  // namespace amlogic_ram

static constexpr zx_driver_ops_t aml_ram_driver_ops = []() {
  zx_driver_ops_t result = {};
  result.version = DRIVER_OPS_VERSION;
  result.bind = amlogic_ram::AmlRam::Create;

  return result;
}();

// clang-format off
ZIRCON_DRIVER_BEGIN(aml_ram, aml_ram_driver_ops, "zircon", "0.1", 5)
    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_PDEV),
    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_AMLOGIC),
    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_DID, PDEV_DID_AMLOGIC_RAM_CTL),
    // This driver can likely support S905D3 in the future.
    BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_PID, PDEV_PID_AMLOGIC_S905D2),
    BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_PID, PDEV_PID_AMLOGIC_T931),
ZIRCON_DRIVER_END(aml_ram)
    // clang-format on
