// Copyright 2018 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 <fidl/fuchsia.hardware.platform.bus/cpp/driver/fidl.h>
#include <fidl/fuchsia.hardware.platform.bus/cpp/fidl.h>
#include <fidl/fuchsia.hardware.serial/cpp/wire.h>
#include <lib/ddk/binding.h>
#include <lib/ddk/debug.h>
#include <lib/ddk/metadata.h>
#include <lib/ddk/platform-defs.h>
#include <lib/mmio/mmio.h>
#include <unistd.h>

#include <bind/fuchsia/cpp/bind.h>
#include <bind/fuchsia/gpio/cpp/bind.h>
#include <bind/fuchsia/pwm/cpp/bind.h>
#include <sdk/lib/driver/component/cpp/composite_node_spec.h>
#include <sdk/lib/driver/component/cpp/node_add_args.h>
#include <soc/aml-t931/t931-gpio.h>
#include <soc/aml-t931/t931-hw.h>

#include "sherlock.h"

namespace sherlock {
namespace fpbus = fuchsia_hardware_platform_bus;

static const std::vector<fpbus::Mmio> bt_uart_mmios{
    {{
        .base = T931_UART_A_BASE,
        .length = T931_UART_LENGTH,
    }},
};

static const std::vector<fpbus::Irq> bt_uart_irqs{
    {{
        .irq = T931_UART_A_IRQ,
        .mode = ZX_INTERRUPT_MODE_EDGE_HIGH,
    }},
};

constexpr fuchsia_hardware_serial::wire::SerialPortInfo bt_uart_serial_info = {
    .serial_class = fuchsia_hardware_serial::Class::kBluetoothHci,
    .serial_vid = PDEV_VID_BROADCOM,
    .serial_pid = PDEV_PID_BCM43458,
};

static const std::vector<fpbus::BootMetadata> bt_uart_boot_metadata{
    {{
        .zbi_type = DEVICE_METADATA_MAC_ADDRESS,
        .zbi_extra = MACADDR_BLUETOOTH,
    }},
};

zx_status_t Sherlock::BluetoothInit() {
  // set alternate functions to enable Bluetooth UART
  gpio_init_steps_.push_back({T931_UART_A_TX, GpioSetAltFunction(T931_UART_A_TX_FN)});
  gpio_init_steps_.push_back({T931_UART_A_RX, GpioSetAltFunction(T931_UART_A_RX_FN)});
  gpio_init_steps_.push_back({T931_UART_A_CTS, GpioSetAltFunction(T931_UART_A_CTS_FN)});
  gpio_init_steps_.push_back({T931_UART_A_RTS, GpioSetAltFunction(T931_UART_A_RTS_FN)});

  // Bind UART for Bluetooth HCI
  fdf::Arena arena('BLUE');

  fuchsia_driver_framework::wire::BindRule kPwmBindRules[] = {
      // TODO(https://fxbug.dev/42079489): Replace this with wire type function.
      fidl::ToWire(arena, fdf::MakeAcceptBindRule(bind_fuchsia::INIT_STEP,
                                                  bind_fuchsia_pwm::BIND_INIT_STEP_PWM)),
  };

  fuchsia_driver_framework::wire::NodeProperty kPwmProperties[] = {
      fdf::MakeProperty(arena, bind_fuchsia::INIT_STEP, bind_fuchsia_pwm::BIND_INIT_STEP_PWM),
  };

  fuchsia_driver_framework::wire::BindRule kGpioBindRules[] = {
      fidl::ToWire(arena, fdf::MakeAcceptBindRule(bind_fuchsia::INIT_STEP,
                                                  bind_fuchsia_gpio::BIND_INIT_STEP_GPIO)),
  };

  fuchsia_driver_framework::wire::NodeProperty kGpioProperties[] = {
      fdf::MakeProperty(arena, bind_fuchsia::INIT_STEP, bind_fuchsia_gpio::BIND_INIT_STEP_GPIO),
  };

  auto parents = std::vector{
      fuchsia_driver_framework::wire::ParentSpec{
          .bind_rules = fidl::VectorView<fuchsia_driver_framework::wire::BindRule>::FromExternal(
              kPwmBindRules, 1),
          .properties =
              fidl::VectorView<fuchsia_driver_framework::wire::NodeProperty>::FromExternal(
                  kPwmProperties, 1),
      },
      fuchsia_driver_framework::wire::ParentSpec{
          .bind_rules = fidl::VectorView<fuchsia_driver_framework::wire::BindRule>::FromExternal(
              kGpioBindRules, 1),
          .properties =
              fidl::VectorView<fuchsia_driver_framework::wire::NodeProperty>::FromExternal(
                  kGpioProperties, 1),
      },
  };

  auto builder =
      fuchsia_driver_framework::wire::CompositeNodeSpec::Builder(arena)
          .name("bluetooth-composite-spec")
          .parents(fidl::VectorView<fuchsia_driver_framework::wire::ParentSpec>(arena, parents));

  fit::result encoded = fidl::Persist(bt_uart_serial_info);
  if (encoded.is_error()) {
    zxlogf(ERROR, "Failed to encode serial metadata: %s",
           encoded.error_value().FormatDescription().c_str());
    return encoded.error_value().status();
  }

  const std::vector<fpbus::Metadata> bt_uart_metadata{
      {{
          .type = DEVICE_METADATA_SERIAL_PORT_INFO,
          .data = *std::move(encoded),
      }},
  };

  const fpbus::Node bt_uart_dev = [&]() {
    fpbus::Node dev = {};
    dev.name() = "bt-uart";
    dev.vid() = PDEV_VID_AMLOGIC;
    dev.pid() = PDEV_PID_GENERIC;
    dev.did() = PDEV_DID_AMLOGIC_UART;
    dev.mmio() = bt_uart_mmios;
    dev.irq() = bt_uart_irqs;
    dev.metadata() = bt_uart_metadata;
    dev.boot_metadata() = bt_uart_boot_metadata;
    return dev;
  }();

  // Create composite spec for aml-uart based on UART and PWM nodes. The parent spec of bt_uart_dev
  // will be generated by the handler of AddCompositeNodeSpec.
  auto result =
      pbus_.buffer(arena)->AddCompositeNodeSpec(fidl::ToWire(arena, bt_uart_dev), builder.Build());
  if (!result.ok()) {
    zxlogf(ERROR, "AddCompositeNodeSpec Bluetooth(bt_uart_dev) request failed: %s",
           result.FormatDescription().data());
    return result.status();
  }
  if (result->is_error()) {
    zxlogf(ERROR, "AddCompositeNodeSpec Bluetooth(bt_uart_dev) failed: %s",
           zx_status_get_string(result->error_value()));
    return result->error_value();
  }

  return ZX_OK;
}

}  // namespace sherlock
