// 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 "aml-cpu.h"

#include <lib/ddk/debug.h>
#include <lib/ddk/driver.h>
#include <lib/ddk/platform-defs.h>
#include <lib/device-protocol/pdev.h>
#include <lib/inspect/cpp/inspector.h>
#include <lib/mmio/mmio.h>

#include <memory>
#include <vector>

#include <ddktl/fidl.h>
#include <fbl/string_buffer.h>

#include "src/devices/cpu/drivers/aml-cpu/aml-cpu-bind.h"

namespace amlogic_cpu {

namespace {
// Fragments are provided to this driver in groups of 4. Fragments are provided as follows:
// [4 fragments for cluster 0]
// [4 fragments for cluster 1]
// [...]
// [4 fragments for cluster n]
// Each fragment is a combination of the fixed string + id.
constexpr size_t kFragmentsPerPfDomain = 4;

constexpr zx_off_t kCpuVersionOffset = 0x220;

}  // namespace

zx_status_t AmlCpu::Create(void* context, zx_device_t* parent) {
  zx_status_t st;
  size_t actual;

  // Get the metadata for the performance domains.
  size_t perf_domain_size = 0;
  st = device_get_metadata_size(parent, DEVICE_METADATA_AML_PERF_DOMAINS, &perf_domain_size);
  zxlogf(DEBUG, "%s: Got AML_PERF_DOMAINS metadata size, st = %d, size = %lu", __func__, st,
         perf_domain_size);

  if (st != ZX_OK) {
    zxlogf(ERROR, "%s: Failed to get performance domain count from board driver, st = %d", __func__,
           st);
    return st;
  }

  // Make sure that the board driver gave us an exact integer number of performance domains.
  if (perf_domain_size % sizeof(perf_domain_t) != 0) {
    zxlogf(ERROR,
           "%s: Performance domain metadata from board driver is malformed. perf_domain_size = "
           "%lu, sizeof(perf_domain_t) = %lu",
           __func__, perf_domain_size, sizeof(perf_domain_t));
    return ZX_ERR_INTERNAL;
  }

  const size_t num_perf_domains = perf_domain_size / sizeof(perf_domain_t);
  std::unique_ptr<perf_domain_t[]> perf_domains =
      std::make_unique<perf_domain_t[]>(num_perf_domains);
  st = device_get_metadata(parent, DEVICE_METADATA_AML_PERF_DOMAINS, perf_domains.get(),
                           perf_domain_size, &actual);
  zxlogf(DEBUG, "%s: Got AML_PERF_DOMAINS metadata, st = %d, actual = %lu", __func__, st, actual);

  if (st != ZX_OK) {
    zxlogf(ERROR, "%s: Failed to get performance domain metadata from board driver, st = %d",
           __func__, st);
    return st;
  }
  if (actual != perf_domain_size) {
    zxlogf(ERROR, "%s: Expected %lu bytes in perf domain metadata, got %lu", __func__,
           perf_domain_size, actual);
    return ZX_ERR_INTERNAL;
  }

  size_t op_point_size;
  st = device_get_metadata_size(parent, DEVICE_METADATA_AML_OP_POINTS, &op_point_size);
  zxlogf(DEBUG, "%s: Got AML_OP_POINTS metadata size, st = %d, size = %lu", __func__, st,
         op_point_size);
  if (st != ZX_OK) {
    zxlogf(ERROR, "%s: Failed to get opp count metadata size from board driver, st = %d", __func__,
           st);
    return st;
  }

  if (op_point_size % sizeof(operating_point_t) != 0) {
    zxlogf(ERROR, "%s: Operating point metadata from board driver is malformed", __func__);
    return ZX_ERR_INTERNAL;
  }

  const size_t num_op_points = op_point_size / sizeof(operating_point_t);
  std::unique_ptr<operating_point_t[]> operating_points =
      std::make_unique<operating_point_t[]>(num_op_points);
  st = device_get_metadata(parent, DEVICE_METADATA_AML_OP_POINTS, operating_points.get(),
                           op_point_size, &actual);
  zxlogf(DEBUG, "%s: Got AML_OP_POINTS metadata, st = %d, actual = %lu", __func__, st, actual);
  if (st != ZX_OK) {
    zxlogf(ERROR, "%s: Failed to get operating points from board driver, st = %d", __func__, st);
    return st;
  }
  if (actual != op_point_size) {
    zxlogf(ERROR, "%s: Expected %lu bytes in operating point metadata, got %lu", __func__,
           op_point_size, actual);
    return ZX_ERR_INTERNAL;
  }
  // Make sure we have the right number of fragments.
  const uint32_t fragment_count = device_get_fragment_count(parent);
  zxlogf(DEBUG, "%s: GetFragmentCount = %u", __func__, fragment_count);
  if ((num_perf_domains * kFragmentsPerPfDomain) + 1 != fragment_count) {
    zxlogf(ERROR,
           "%s: Expected %lu fragments for each %lu performance domains for a total of %lu "
           "fragments but got %u instead",
           __func__, kFragmentsPerPfDomain, perf_domain_size,
           perf_domain_size * kFragmentsPerPfDomain, fragment_count);
    return ZX_ERR_INTERNAL;
  }

  // Map AOBUS registers
  auto pdev = ddk::PDev::FromFragment(parent);
  if (!pdev.is_valid()) {
    zxlogf(ERROR, "Failed to get platform device fragment");
    return ZX_ERR_NO_RESOURCES;
  }
  std::optional<ddk::MmioBuffer> mmio_buffer;
  if ((st = pdev.MapMmio(0, &mmio_buffer)) != ZX_OK) {
    zxlogf(ERROR, "aml-cpu: Failed to map mmio, st = %d", st);
    return st;
  }
  const uint32_t cpu_version_packed = mmio_buffer->Read32(kCpuVersionOffset);

  // Build and publish each performance domain.
  for (size_t i = 0; i < num_perf_domains; i++) {
    const perf_domain_t& perf_domain = perf_domains[i];

    fbl::StringBuffer<32> fragment_name;
    fragment_name.AppendPrintf("clock-pll-div16-%02d", perf_domain.id);
    ddk::ClockProtocolClient pll_div16_client;
    if ((st = ddk::ClockProtocolClient::CreateFromDevice(parent, fragment_name.c_str(),
                                                         &pll_div16_client)) != ZX_OK) {
      zxlogf(ERROR, "%s: Failed to create pll_div_16 clock client, st = %d", __func__, st);
      return st;
    }

    fragment_name.Resize(0);
    fragment_name.AppendPrintf("clock-cpu-div16-%02d", perf_domain.id);
    ddk::ClockProtocolClient cpu_div16_client;
    if ((st = ddk::ClockProtocolClient::CreateFromDevice(parent, fragment_name.c_str(),
                                                         &cpu_div16_client)) != ZX_OK) {
      zxlogf(ERROR, "%s: Failed to create cpu_div_16 clock client, st = %d", __func__, st);
      return st;
    }

    fragment_name.Resize(0);
    fragment_name.AppendPrintf("clock-cpu-scaler-%02d", perf_domain.id);
    ddk::ClockProtocolClient cpu_scaler_client;
    if ((st = ddk::ClockProtocolClient::CreateFromDevice(parent, fragment_name.c_str(),
                                                         &cpu_scaler_client)) != ZX_OK) {
      zxlogf(ERROR, "%s: Failed to create cpu_scaler clock client, st = %d", __func__, st);
      return st;
    }

    fragment_name.Resize(0);
    fragment_name.AppendPrintf("power-%02d", perf_domain.id);
    ddk::PowerProtocolClient power_client;
    if ((st = ddk::PowerProtocolClient::CreateFromDevice(parent, fragment_name.c_str(),
                                                         &power_client)) != ZX_OK) {
      zxlogf(ERROR, "%s: Failed to create power client, st = %d", __func__, st);
      return st;
    }

    // Vector of operating points that belong to this power domain.
    std::vector<operating_point_t> pd_op_points;
    std::copy_if(operating_points.get(), operating_points.get() + num_op_points,
                 std::back_inserter(pd_op_points), [&perf_domain](const operating_point_t& op) {
                   return op.pd_id == perf_domain.id;
                 });

    // Order operating points from highest frequency to lowest because Operating Point 0 is the
    // fastest.
    std::sort(pd_op_points.begin(), pd_op_points.end(),
              [](const operating_point_t& a, const operating_point_t& b) {
                return a.freq_hz > b.freq_hz;
              });

    const size_t perf_state_count = pd_op_points.size();
    auto perf_states = std::make_unique<device_performance_state_info_t[]>(perf_state_count);
    for (size_t j = 0; j < perf_state_count; j++) {
      perf_states[j].state_id = static_cast<uint8_t>(j);
      perf_states[j].restore_latency = 0;
    }

    auto device = std::make_unique<AmlCpu>(
        parent, std::move(pll_div16_client), std::move(cpu_div16_client),
        std::move(cpu_scaler_client), std::move(power_client), std::move(pd_op_points),
        perf_domain.core_count);

    st = device->Init();
    if (st != ZX_OK) {
      zxlogf(ERROR, "%s: Failed to initialize device, st = %d", __func__, st);
      return st;
    }

    device->SetCpuInfo(cpu_version_packed);

    st = device->DdkAdd(ddk::DeviceAddArgs("cpu")
                            .set_flags(DEVICE_ADD_NON_BINDABLE)
                            .set_proto_id(ZX_PROTOCOL_CPU_CTRL)
                            .set_performance_states({perf_states.get(), perf_state_count})
                            .set_inspect_vmo(device->inspector_.DuplicateVmo()));

    if (st != ZX_OK) {
      zxlogf(ERROR, "%s: DdkAdd failed, st = %d", __func__, st);
      return st;
    }

    __UNUSED auto ptr = device.release();
  }

  return ZX_OK;
}

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

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

zx_status_t AmlCpu::DdkSetPerformanceState(uint32_t requested_state, uint32_t* out_state) {
  if (requested_state >= operating_points_.size()) {
    zxlogf(ERROR, "%s: Requested performance state is out of bounds, state = %u\n", __func__,
           requested_state);
    return ZX_ERR_OUT_OF_RANGE;
  }

  if (!out_state) {
    zxlogf(ERROR, "%s: out_state may not be null", __func__);
    return ZX_ERR_INVALID_ARGS;
  }

  // There is no condition under which this function will return ZX_OK but out_state will not
  // be requested_state so we're going to go ahead and set that up front.
  *out_state = requested_state;

  const operating_point_t& target_state = operating_points_[requested_state];
  const operating_point_t& initial_state = operating_points_[current_pstate_];

  zxlogf(INFO, "%s: Scaling from %u MHz %u mV to %u MHz %u mV", __func__,
         initial_state.freq_hz / 1000000, initial_state.volt_uv / 1000,
         target_state.freq_hz / 1000000, target_state.volt_uv / 1000);

  if (initial_state.freq_hz == target_state.freq_hz &&
      initial_state.volt_uv == target_state.volt_uv) {
    // Nothing to be done.
    return ZX_OK;
  }

  zx_status_t st;
  if (target_state.freq_hz > initial_state.freq_hz) {
    // If we're increasing the frequency, we need to increase the voltage first.
    uint32_t actual_voltage;
    st = pwr_.RequestVoltage(target_state.volt_uv, &actual_voltage);
    if (st != ZX_OK || actual_voltage != target_state.volt_uv) {
      zxlogf(ERROR, "%s: Failed to set cpu voltage, requested = %u, got = %u, st = %d", __func__,
             target_state.volt_uv, actual_voltage, st);
      return st;
    }
  }

  // Set the frequency next.
  st = cpuscaler_.SetRate(target_state.freq_hz);
  if (st != ZX_OK) {
    zxlogf(ERROR, "%s: Could not set CPU frequency, st = %d\n", __func__, st);

    // Put the voltage back if frequency scaling fails.
    uint32_t actual_voltage;
    zx_status_t vt_st = pwr_.RequestVoltage(initial_state.volt_uv, &actual_voltage);
    if (vt_st != ZX_OK) {
      zxlogf(ERROR, "%s: Failed to reset CPU voltage, st = %d, Voltage and frequency mismatch!",
             __func__, vt_st);
      return vt_st;
    }
    return st;
  }

  // If we're decreasing the frequency, then we set the voltage after the frequency has
  // been reduced.
  if (target_state.freq_hz < initial_state.freq_hz) {
    // If we're increasing the frequency, we need to increase the voltage first.
    uint32_t actual_voltage;
    st = pwr_.RequestVoltage(target_state.volt_uv, &actual_voltage);
    if (st != ZX_OK || actual_voltage != target_state.volt_uv) {
      zxlogf(ERROR,
             "%s: Failed to set cpu voltage, requested = %u, got = %u, st = %d. "
             "Voltage and frequency mismatch!",
             __func__, target_state.volt_uv, actual_voltage, st);
      return st;
    }
  }

  zxlogf(INFO, "%s: Success\n", __func__);

  current_pstate_ = requested_state;

  return ZX_OK;
}

zx_status_t AmlCpu::Init() {
  zx_status_t result;
  constexpr uint32_t kInitialPstate = 0;

  result = plldiv16_.Enable();
  if (result != ZX_OK) {
    zxlogf(ERROR, "%s: Failed to enable plldiv16, st = %d", __func__, result);
    return result;
  }

  result = cpudiv16_.Enable();
  if (result != ZX_OK) {
    zxlogf(ERROR, "%s: Failed to enable cpudiv16_, st = %d", __func__, result);
    return result;
  }

  uint32_t min_voltage, max_voltage;
  pwr_.GetSupportedVoltageRange(&min_voltage, &max_voltage);
  pwr_.RegisterPowerDomain(min_voltage, max_voltage);

  uint32_t actual;
  result = DdkSetPerformanceState(kInitialPstate, &actual);

  if (result != ZX_OK) {
    zxlogf(ERROR, "%s: Failed to set initial performance state, st = %d", __func__, result);
    return result;
  }

  if (actual != kInitialPstate) {
    zxlogf(ERROR, "%s: Failed to set initial performance state, requested = %u, actual = %u",
           __func__, kInitialPstate, actual);
    return ZX_ERR_INTERNAL;
  }

  return ZX_OK;
}

zx_status_t AmlCpu::DdkConfigureAutoSuspend(bool enable, uint8_t requested_sleep_state) {
  return ZX_ERR_NOT_SUPPORTED;
}

void AmlCpu::GetPerformanceStateInfo(uint32_t state,
                                     GetPerformanceStateInfoCompleter::Sync& completer) {
  if (state >= operating_points_.size()) {
    zxlogf(INFO, "%s: Requested an operating point that's out of bounds, %u\n", __func__, state);
    completer.ReplyError(ZX_ERR_OUT_OF_RANGE);
    return;
  }

  fuchsia_hardware_cpu_ctrl::wire::CpuPerformanceStateInfo result;
  result.frequency_hz = operating_points_[state].freq_hz;
  result.voltage_uv = operating_points_[state].volt_uv;

  completer.ReplySuccess(result);
}

void AmlCpu::GetNumLogicalCores(GetNumLogicalCoresCompleter::Sync& completer) {
  completer.Reply(core_count_);
}

void AmlCpu::GetLogicalCoreId(uint64_t index, GetLogicalCoreIdCompleter::Sync& completer) {
  // Placeholder.
  completer.Reply(0);
}

void AmlCpu::SetCpuInfo(uint32_t cpu_version_packed) {
  const uint8_t major_revision = (cpu_version_packed >> 24) & 0xff;
  const uint8_t minor_revision = (cpu_version_packed >> 8) & 0xff;
  const uint8_t cpu_package_id = (cpu_version_packed >> 20) & 0x0f;
  zxlogf(INFO, "major revision number: 0x%x", major_revision);
  zxlogf(INFO, "minor revision number: 0x%x", minor_revision);
  zxlogf(INFO, "cpu package id number: 0x%x", cpu_package_id);

  cpu_info_.CreateUint("cpu_major_revision", major_revision, &inspector_);
  cpu_info_.CreateUint("cpu_minor_revision", minor_revision, &inspector_);
  cpu_info_.CreateUint("cpu_package_id", cpu_package_id, &inspector_);
}

}  // namespace amlogic_cpu

static constexpr zx_driver_ops_t aml_cpu_driver_ops = []() {
  zx_driver_ops_t result = {};
  result.version = DRIVER_OPS_VERSION;
  result.bind = amlogic_cpu::AmlCpu::Create;
  return result;
}();

// clang-format off
ZIRCON_DRIVER(aml_cpu, aml_cpu_driver_ops, "zircon", "0.1");

