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

#include <lib/device-protocol/pdev.h>
#include <lib/zx/vmo.h>
#include <stdint.h>
#include <string.h>
#include <zircon/threads.h>
#include <zircon/types.h>

#include <bits/limits.h>
#include <ddk/binding.h>
#include <ddk/debug.h>
#include <ddk/device.h>
#include <ddk/metadata.h>
#include <ddk/platform-defs.h>
#include <ddk/protocol/platform/bus.h>
#include <ddktl/device.h>
#include <ddktl/protocol/composite.h>
#include <fbl/alloc_checker.h>
#include <fbl/auto_call.h>
#include <fbl/auto_lock.h>
#include <hw/reg.h>
#include <hwreg/mmio.h>

#include "registers.h"

namespace serial {

constexpr auto kMinBaudRate = 2;

zx_status_t AmlUart::Create(void* ctx, zx_device_t* parent) {
  zx_status_t status;

  ddk::CompositeProtocolClient composite(parent);
  if (!composite.is_valid()) {
    zxlogf(ERROR, "AmlUart::Could not get composite protocol\n");
    return ZX_ERR_NOT_SUPPORTED;
  }

  zx_device_t* components[COMPONENT_COUNT];
  size_t component_count;
  composite.GetComponents(components, fbl::count_of(components), &component_count);
  // Only pdev component is required.
  if (component_count < 1) {
    zxlogf(ERROR, "AmlUart: Could not get components\n");
    return ZX_ERR_NOT_SUPPORTED;
  }

  ddk::PwmProtocolClient pwm;
  if (component_count > COMPONENT_PWM_E) {
    pwm = components[COMPONENT_PWM_E];
  }

  ddk::PDev pdev(components[COMPONENT_PDEV]);
  if (!pdev.is_valid()) {
    zxlogf(ERROR, "AmlUart::Create: Could not get pdev\n");
    return ZX_ERR_NO_RESOURCES;
  }
  pdev_protocol_t proto;
  pdev.GetProto(&proto);

  serial_port_info_t info;
  size_t actual;
  status =
      device_get_metadata(parent, DEVICE_METADATA_SERIAL_PORT_INFO, &info, sizeof(info), &actual);
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s: device_get_metadata failed %d\n", __func__, status);
    return status;
  }
  if (actual < sizeof(info)) {
    zxlogf(ERROR, "%s: serial_port_info_t metadata too small\n", __func__);
    return ZX_ERR_INTERNAL;
  }

  mmio_buffer_t mmio;
  status = pdev_map_mmio_buffer(&proto, 0, ZX_CACHE_POLICY_UNCACHED_DEVICE, &mmio);
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s: pdev_map_&mmio__buffer failed %d\n", __func__, status);
    return status;
  }

  fbl::AllocChecker ac;
  auto* uart = new (&ac) AmlUart(parent, proto, info, ddk::MmioBuffer(mmio));
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }
  return uart->Init(pwm);
}

zx_status_t AmlUart::Init(ddk::PwmProtocolClient pwm) {
  zx_status_t status = ZX_OK;
  if (pwm.is_valid()) {
    if ((status = pwm.Enable()) != ZX_OK) {
      zxlogf(ERROR, "%s: Could not enable PWM\n", __func__);
      return status;
    }
    aml_pwm::mode_config two_timer = {.mode = aml_pwm::TWO_TIMER,
                                      .two_timer = {30052, 50.0, 0x0a, 0x0a}};
    pwm_config_t init_cfg = {false, 30053, static_cast<float>(49.931787176), &two_timer,
                             sizeof(two_timer)};
    if ((status = pwm.SetConfig(&init_cfg)) != ZX_OK) {
      zxlogf(ERROR, "%s: Could not initialize PWM\n", __func__);
      return status;
    }
  }

  auto cleanup = fbl::MakeAutoCall([this]() { DdkRelease(); });

  // Default configuration for the case that serial_impl_config is not called.
  constexpr uint32_t kDefaultBaudRate = 115200;
  constexpr uint32_t kDefaultConfig = SERIAL_DATA_BITS_8 | SERIAL_STOP_BITS_1 | SERIAL_PARITY_NONE;
  SerialImplAsyncConfig(kDefaultBaudRate, kDefaultConfig);
  zx_device_prop_t props[] = {
      {BIND_PROTOCOL, 0, ZX_PROTOCOL_SERIAL_IMPL_ASYNC},
      {BIND_SERIAL_CLASS, 0, serial_port_info_.serial_class},
  };
  status = DdkAdd("aml-uart", 0, props, fbl::count_of(props));
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s: DdkDeviceAdd failed\n", __func__);
    return status;
  }

  cleanup.cancel();
  return status;
}

uint32_t AmlUart::ReadState() {
  auto status = Status::Get().ReadFrom(&mmio_);
  uint32_t state = 0;
  if (!status.rx_empty()) {
    state |= SERIAL_STATE_READABLE;
  }

  if (!status.tx_full()) {
    state |= SERIAL_STATE_WRITABLE;
  }
  return state;
}

uint32_t AmlUart::ReadStateAndNotify() {
  auto status = Status::Get().ReadFrom(&mmio_);

  uint32_t state = 0;
  if (!status.rx_empty()) {
    state |= SERIAL_STATE_READABLE;
    HandleRX();
  }
  if (!status.tx_full()) {
    state |= SERIAL_STATE_WRITABLE;
    HandleTX();
  }

  return state;
}

int AmlUart::IrqThread() {
  zxlogf(INFO, "%s start\n", __func__);

  while (1) {
    zx_status_t status;
    status = irq_.wait(nullptr);
    if (status != ZX_OK) {
      zxlogf(ERROR, "%s: irq.wait() got %d\n", __func__, status);
      break;
    }
    // This will call the notify_cb if the serial state has changed.
    ReadStateAndNotify();
  }

  return 0;
}

zx_status_t AmlUart::SerialImplAsyncGetInfo(serial_port_info_t* info) {
  memcpy(info, &serial_port_info_, sizeof(*info));
  return ZX_OK;
}

zx_status_t AmlUart::SerialImplAsyncConfig(uint32_t baud_rate, uint32_t flags) {
  // Control register is determined completely by this logic, so start with a clean slate.
  if (baud_rate < kMinBaudRate) {
    return ZX_ERR_INVALID_ARGS;
  }
  auto ctrl = Control::Get().FromValue(0);

  if ((flags & SERIAL_SET_BAUD_RATE_ONLY) == 0) {
    switch (flags & SERIAL_DATA_BITS_MASK) {
      case SERIAL_DATA_BITS_5:
        ctrl.set_xmit_len(Control::kXmitLength5);
        break;
      case SERIAL_DATA_BITS_6:
        ctrl.set_xmit_len(Control::kXmitLength6);
        break;
      case SERIAL_DATA_BITS_7:
        ctrl.set_xmit_len(Control::kXmitLength7);
        break;
      case SERIAL_DATA_BITS_8:
        ctrl.set_xmit_len(Control::kXmitLength8);
        break;
      default:
        return ZX_ERR_INVALID_ARGS;
    }

    switch (flags & SERIAL_STOP_BITS_MASK) {
      case SERIAL_STOP_BITS_1:
        ctrl.set_stop_len(Control::kStopLen1);
        break;
      case SERIAL_STOP_BITS_2:
        ctrl.set_stop_len(Control::kStopLen2);
        break;
      default:
        return ZX_ERR_INVALID_ARGS;
    }

    switch (flags & SERIAL_PARITY_MASK) {
      case SERIAL_PARITY_NONE:
        ctrl.set_parity(Control::kParityNone);
        break;
      case SERIAL_PARITY_EVEN:
        ctrl.set_parity(Control::kParityEven);
        break;
      case SERIAL_PARITY_ODD:
        ctrl.set_parity(Control::kParityOdd);
        break;
      default:
        return ZX_ERR_INVALID_ARGS;
    }

    switch (flags & SERIAL_FLOW_CTRL_MASK) {
      case SERIAL_FLOW_CTRL_NONE:
        ctrl.set_two_wire(1);
        break;
      case SERIAL_FLOW_CTRL_CTS_RTS:
        // CTS/RTS is on by default
        break;
      default:
        return ZX_ERR_INVALID_ARGS;
    }
  }

  // Configure baud rate based on crystal clock speed.
  // See meson_uart_change_speed() in drivers/amlogic/uart/uart/meson_uart.c.
  constexpr uint32_t kCrystalClockSpeed = 24000000;
  uint32_t baud_bits = (kCrystalClockSpeed / 3) / baud_rate - 1;
  if (baud_bits & (~AML_UART_REG5_NEW_BAUD_RATE_MASK)) {
    zxlogf(ERROR, "%s: baud rate %u too large\n", __func__, baud_rate);
    return ZX_ERR_OUT_OF_RANGE;
  }
  auto baud = Reg5::Get()
                  .FromValue(0)
                  .set_new_baud_rate(baud_bits)
                  .set_use_xtal_clk(1)
                  .set_use_new_baud_rate(1);

  fbl::AutoLock al(&enable_lock_);

  if ((flags & SERIAL_SET_BAUD_RATE_ONLY) == 0) {
    // Invert our RTS if we are we are not enabled and configured for flow control.
    if (!enabled_ && (ctrl.two_wire() == 0)) {
      ctrl.set_inv_rts(1);
    }
    ctrl.WriteTo(&mmio_);
  }

  baud.WriteTo(&mmio_);

  return ZX_OK;
}

void AmlUart::EnableLocked(bool enable) {
  auto ctrl = Control::Get().ReadFrom(&mmio_);

  if (enable) {
    // Reset the port.
    ctrl.set_rst_rx(1).set_rst_tx(1).set_clear_error(1).WriteTo(&mmio_);

    ctrl.set_rst_rx(0).set_rst_tx(0).set_clear_error(0).WriteTo(&mmio_);

    // Enable rx and tx.
    ctrl.set_tx_enable(1)
        .set_rx_enable(1)
        .set_tx_interrupt_enable(1)
        .set_rx_interrupt_enable(1)
        // Clear our RTS.
        .set_inv_rts(0)
        .WriteTo(&mmio_);

    // Set interrupt thresholds.
    // Generate interrupt if TX buffer drops below half full.
    constexpr uint32_t kTransmitIrqCount = 32;
    // Generate interrupt as soon as we receive any data.
    constexpr uint32_t kRecieveIrqCount = 1;
    Misc::Get()
        .FromValue(0)
        .set_xmit_irq_count(kTransmitIrqCount)
        .set_recv_irq_count(kRecieveIrqCount)
        .WriteTo(&mmio_);
  } else {
    ctrl.set_tx_enable(0)
        .set_rx_enable(0)
        // Invert our RTS if we are configured for flow control.
        .set_inv_rts(!ctrl.two_wire())
        .WriteTo(&mmio_);
  }
}

void AmlUart::HandleTXRaceForTest() {
  {
    fbl::AutoLock al(&enable_lock_);
    EnableLocked(true);
  }
  ReadState();
  HandleTX();
  HandleTX();
}

void AmlUart::HandleRXRaceForTest() {
  {
    fbl::AutoLock al(&enable_lock_);
    EnableLocked(true);
  }
  ReadState();
  HandleRX();
  HandleRX();
}

zx_status_t AmlUart::SerialImplAsyncEnable(bool enable) {
  fbl::AutoLock al(&enable_lock_);

  if (enable && !enabled_) {
    zx_status_t status = pdev_get_interrupt(&pdev_, 0, 0, irq_.reset_and_get_address());
    if (status != ZX_OK) {
      zxlogf(ERROR, "%s: pdev_get_interrupt failed %d\n", __func__, status);
      return status;
    }

    EnableLocked(true);

    auto start_thread = [](void* arg) { return static_cast<AmlUart*>(arg)->IrqThread(); };
    int rc = thrd_create_with_name(&irq_thread_, start_thread, this, "aml_uart_irq_thread");
    if (rc != thrd_success) {
      EnableLocked(false);
      return thrd_status_to_zx_status(rc);
    }
  } else if (!enable && enabled_) {
    irq_.destroy();
    thrd_join(irq_thread_, nullptr);
    EnableLocked(false);
  }

  enabled_ = enable;
  return ZX_OK;
}

void AmlUart::SerialImplAsyncReadAsync(serial_impl_async_read_async_callback callback,
                                       void* cookie) {
  fbl::AutoLock lock(&read_lock_);
  if (read_pending_) {
    lock.release();
    callback(cookie, ZX_ERR_NOT_SUPPORTED, nullptr, 0);
    return;
  }
  read_callback_ = callback;
  read_cookie_ = cookie;
  read_pending_ = true;
  lock.release();
  HandleRX();
}

void AmlUart::SerialImplAsyncCancelAll() {
  {
    fbl::AutoLock read_lock(&read_lock_);
    if (read_pending_) {
      read_pending_ = false;
      auto cb = MakeReadCallbackLocked(ZX_ERR_CANCELED, nullptr, 0);
      read_lock.release();
      cb();
    }
  }
  fbl::AutoLock write_lock(&write_lock_);
  if (write_pending_) {
    write_pending_ = false;
    auto cb = MakeWriteCallbackLocked(ZX_ERR_CANCELED);
    write_lock.release();
    cb();
  }
}

// Handles receiviung data into the buffer and calling the read callback when complete.
// Does nothing if read_pending_ is false.
void AmlUart::HandleRX() {
  fbl::AutoLock lock(&read_lock_);
  if (!read_pending_) {
    return;
  }
  unsigned char buf[128];
  size_t length = 128;
  auto* bufptr = static_cast<uint8_t*>(buf);
  const uint8_t* const end = bufptr + length;
  while (bufptr < end && (ReadState() & SERIAL_STATE_READABLE)) {
    uint32_t val = mmio_.Read32(AML_UART_RFIFO);
    *bufptr++ = static_cast<uint8_t>(val);
  }

  const size_t read = reinterpret_cast<uintptr_t>(bufptr) - reinterpret_cast<uintptr_t>(buf);
  if (read == 0) {
    return;
  }
  // Some bytes were read.  The client must queue another read to get any data.
  read_pending_ = false;
  auto cb = MakeReadCallbackLocked(ZX_OK, buf, read);
  lock.release();
  cb();
}

// Handles transmitting the data in write_buffer_ until it is completely written.
// Does nothing if write_pending_ is not true.
void AmlUart::HandleTX() {
  fbl::AutoLock lock(&write_lock_);
  if (!write_pending_) {
    return;
  }
  const auto* bufptr = static_cast<const uint8_t*>(write_buffer_);
  const uint8_t* const end = bufptr + write_size_;
  while (bufptr < end && (ReadState() & SERIAL_STATE_WRITABLE)) {
    mmio_.Write32(*bufptr++, AML_UART_WFIFO);
  }

  const size_t written =
      reinterpret_cast<uintptr_t>(bufptr) - reinterpret_cast<uintptr_t>(write_buffer_);
  write_size_ -= written;
  write_buffer_ += written;
  if (!write_size_) {
    // The write has completed, notify the client.
    write_pending_ = false;
    auto cb = MakeWriteCallbackLocked(ZX_OK);
    lock.release();
    cb();
  }
}

fit::closure AmlUart::MakeReadCallbackLocked(zx_status_t status, void* buf, size_t len) {
  if (read_callback_ == nullptr) {
    return []() {};
  }
  auto callback = [cb = read_callback_, cookie = read_cookie_, status, buf, len]() {
    cb(cookie, status, buf, len);
  };
  read_callback_ = nullptr;
  read_cookie_ = nullptr;
  return callback;
}

fit::closure AmlUart::MakeWriteCallbackLocked(zx_status_t status) {
  if (write_callback_ == nullptr) {
    return []() {};
  }
  auto callback = [cb = write_callback_, cookie = write_cookie_, status]() { cb(cookie, status); };
  write_callback_ = nullptr;
  write_cookie_ = nullptr;
  return callback;
}

void AmlUart::SerialImplAsyncWriteAsync(const void* buf, size_t length,
                                        serial_impl_async_write_async_callback callback,
                                        void* cookie) {
  fbl::AutoLock lock(&write_lock_);
  if (write_pending_) {
    lock.release();
    callback(cookie, ZX_ERR_NOT_SUPPORTED);
    return;
  }
  write_buffer_ = static_cast<const uint8_t*>(buf);
  write_size_ = length;
  write_callback_ = callback;
  write_cookie_ = cookie;
  write_pending_ = true;
  lock.release();
  HandleTX();
}

static constexpr zx_driver_ops_t driver_ops = []() {
  zx_driver_ops_t ops = {};
  ops.version = DRIVER_OPS_VERSION;
  ops.bind = AmlUart::Create;
  return ops;
}();

}  // namespace serial

// clang-format off
ZIRCON_DRIVER_BEGIN(aml_uart, serial::driver_ops, "zircon", "0.1", 3)
    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_COMPOSITE),
    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_AMLOGIC),
    BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_AMLOGIC_UART),
ZIRCON_DRIVER_END(aml_uart)
    // clang-format on
