// 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 <memory>

#include <ddk/binding.h>
#include <ddk/debug.h>
#include <ddk/driver.h>
#include <ddk/platform-defs.h>
#include <ddktl/fidl.h>
#include <ddktl/protocol/composite.h>
#include <ddktl/protocol/thermal.h>

namespace {
using llcpp::fuchsia::device::MAX_DEVICE_PERFORMANCE_STATES;
using llcpp::fuchsia::hardware::thermal::PowerDomain;

__UNUSED constexpr size_t kFragmentPdev = 0;
constexpr size_t kFragmentThermal = 1;
constexpr size_t kFragmentCount = 2;

uint16_t PstateToOperatingPoint(const uint32_t pstate, const size_t n_operating_points) {
  ZX_ASSERT(pstate < n_operating_points);
  ZX_ASSERT(n_operating_points < MAX_DEVICE_PERFORMANCE_STATES);

  // Operating points are indexed 0 to N-1.
  return static_cast<uint16_t>(n_operating_points - pstate - 1);
}

}  // namespace
namespace amlogic_cpu {

zx_status_t AmlCpu::Create(void* context, zx_device_t* parent) {
  zx_status_t status;

  ddk::CompositeProtocolClient composite(parent);
  if (!composite.is_valid()) {
    zxlogf(ERROR, "%s: failed to get composite protocol", __func__);
    return ZX_ERR_INTERNAL;
  }

  zx_device_t* devices[kFragmentCount];
  size_t actual;
  composite.GetFragments(devices, kFragmentCount, &actual);
  if (actual != kFragmentCount) {
    zxlogf(ERROR, "%s: Expected to get %lu fragments, actually got %lu", __func__,
           kFragmentCount, actual);
    return ZX_ERR_INTERNAL;
  }

  // Initialize an array with the maximum possible number of PStates since we
  // determine the actual number of PStates at runtime by querying the thermal
  // driver.
  device_performance_state_info_t perf_states[MAX_DEVICE_PERFORMANCE_STATES];
  for (size_t i = 0; i < MAX_DEVICE_PERFORMANCE_STATES; i++) {
    perf_states[i].state_id = static_cast<uint8_t>(i);
    perf_states[i].restore_latency = 0;
  }

  // The Thermal Driver is our parent and it exports an interface with one
  // method (Connect) which allows us to connect to its FIDL interface.
  zx_device_t* device = devices[kFragmentThermal];
  ddk::ThermalProtocolClient thermal_client;
  status = ddk::ThermalProtocolClient::CreateFromDevice(device, &thermal_client);
  if (status != ZX_OK) {
    zxlogf(ERROR, "aml-cpu: Failed to get thermal protocol client, st = %d", status);
    return status;
  }

  // This channel pair will be used to talk to the Thermal Device's FIDL
  // interface.
  zx::channel channel_local, channel_remote;
  status = zx::channel::create(0, &channel_local, &channel_remote);
  if (status != ZX_OK) {
    zxlogf(ERROR, "aml-cpu: Failed to create channel pair, st = %d", status);
    return status;
  }

  // Pass one end of the channel to the Thermal driver. The thermal driver will
  // serve its FIDL interface over this channel.
  status = thermal_client.Connect(std::move(channel_remote));
  if (status != ZX_OK) {
    zxlogf(ERROR, "aml-cpu: failed to connect to thermal driver, st = %d", status);
    return status;
  }

  fuchsia_thermal::Device::SyncClient thermal_fidl_client(std::move(channel_local));

  auto device_info = thermal_fidl_client.GetDeviceInfo();
  if (device_info.status() != ZX_OK) {
    zxlogf(ERROR, "aml-cpu: failed to get device info, st = %d", device_info.status());
    return device_info.status();
  }

  const fuchsia_thermal::ThermalDeviceInfo* info = device_info->info.get();

  // Hack: Only support one DVFS domain in this driver. When only one domain is
  // supported, it is published as the "Big" domain, so we check that the Little
  // domain is unpopulated.
  constexpr size_t kLittleDomainIndex = 1u;
  static_assert(static_cast<size_t>(PowerDomain::LITTLE_CLUSTER_POWER_DOMAIN) ==
                kLittleDomainIndex);
  if (info->opps[kLittleDomainIndex].count != 0) {
    zxlogf(ERROR, "aml-cpu: this driver only supports one dvfs domain.");
    return ZX_ERR_INTERNAL;
  }

  // Make sure we don't have more operating points than available performance states.
  const fuchsia_thermal::OperatingPoint& opps = info->opps[0];
  if (opps.count > MAX_DEVICE_PERFORMANCE_STATES) {
    zxlogf(ERROR, "aml-cpu: cpu device has more operating points than we support");
    return ZX_ERR_INTERNAL;
  }

  const uint8_t perf_state_count = static_cast<uint8_t>(opps.count);
  zxlogf(INFO, "aml-cpu: Creating CPU Device with %u operating poitns", opps.count);

  auto cpu_device = std::make_unique<AmlCpu>(device, std::move(thermal_fidl_client));

  status = cpu_device->DdkAdd("cpu",                         // name
                              DEVICE_ADD_NON_BINDABLE,       // flags
                              nullptr, 0,                    // props & propcount
                              ZX_PROTOCOL_CPU_CTRL,          // protocol id
                              nullptr,                       // proxy_args
                              ZX_HANDLE_INVALID,             // client remote
                              nullptr, 0,                    // Power states & count
                              perf_states, perf_state_count  // Perf states & count
  );
  if (status != ZX_OK) {
    zxlogf(ERROR, "aml-cpu: Failed to add cpu device, st = %d", status);
    return status;
  }

  // Intentionally leak this device because it's owned by the driver framework.
  __UNUSED auto unused = cpu_device.release();

  return ZX_OK;
}

zx_status_t AmlCpu::DdkMessage(fidl_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) {
  zx_status_t status;
  fuchsia_thermal::OperatingPoint opps;

  status = GetThermalOperatingPoints(&opps);
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s: Failed to get Thermal operating poitns, st = %d", __func__, status);
    return status;
  }

  if (requested_state >= opps.count) {
    zxlogf(ERROR, "%s: Requested device performance state is out of bounds", __func__);
    return ZX_ERR_OUT_OF_RANGE;
  }

  const uint16_t pstate = PstateToOperatingPoint(requested_state, opps.count);

  const auto result =
      thermal_client_.SetDvfsOperatingPoint(pstate, PowerDomain::BIG_CLUSTER_POWER_DOMAIN);

  if (!result.ok() || result->status != ZX_OK) {
    zxlogf(ERROR, "%s: failed to set dvfs operating point.", __func__);
    return ZX_ERR_INTERNAL;
  }

  *out_state = requested_state;
  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) {
  // Get all performance states.
  zx_status_t status;
  fuchsia_thermal::OperatingPoint opps;

  status = GetThermalOperatingPoints(&opps);
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s: Failed to get Thermal operating poitns, st = %d", __func__, status);
    completer.ReplyError(status);
  }

  // Make sure that the state is in bounds?
  if (state >= opps.count) {
    zxlogf(ERROR, "%s: requested pstate index out of bounds, requested = %u, count = %u",
           __func__, state, opps.count);
    completer.ReplyError(ZX_ERR_OUT_OF_RANGE);
    return;
  }

  const uint16_t pstate = PstateToOperatingPoint(state, opps.count);

  llcpp::fuchsia::hardware::cpu::ctrl::CpuPerformanceStateInfo result;
  result.frequency_hz = opps.opp[pstate].freq_hz;
  result.voltage_uv = opps.opp[pstate].volt_uv;
  completer.ReplySuccess(result);
}

zx_status_t AmlCpu::GetThermalOperatingPoints(fuchsia_thermal::OperatingPoint* out) {
  auto result = thermal_client_.GetDeviceInfo();
  if (!result.ok() || result->status != ZX_OK) {
    zxlogf(ERROR, "%s: Failed to get thermal device info", __func__);
    return ZX_ERR_INTERNAL;
  }

  fuchsia_thermal::ThermalDeviceInfo* info = result->info.get();

  // We only support one DVFS cluster on Astro.
  if (info->opps[1].count != 0) {
    zxlogf(ERROR, "%s: thermal driver reported more than one dvfs domain?", __func__);
    return ZX_ERR_INTERNAL;
  }

  memcpy(out, &info->opps[0], sizeof(*out));
  return ZX_OK;
}

void AmlCpu::GetNumLogicalCores(GetNumLogicalCoresCompleter::Sync completer) {
  unsigned int result = zx_system_get_num_cpus();
  completer.Reply(result);
}

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

}  // 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_BEGIN(aml_cpu, aml_cpu_driver_ops, "zircon", "0.1", 4)
    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_COMPOSITE),
    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_AMLOGIC),
    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_PID, PDEV_PID_AMLOGIC_S905D2),
    BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_AMLOGIC_CPU),
ZIRCON_DRIVER_END(aml_cpu)
