// Copyright 2021 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.

#ifndef LIB_UART_MOTMOT_H_
#define LIB_UART_MOTMOT_H_

#include <lib/zbi-format/driver-config.h>
#include <lib/zbi-format/zbi.h>

#include <array>

#include <hwreg/bitfields.h>

#include "uart.h"

namespace uart::motmot {

// line control register
struct ULCON : public hwreg::RegisterBase<ULCON, uint32_t> {
  // 31:6 Reserved.
  DEF_FIELD(5, 3, parity_mode);
  DEF_BIT(2, num_stop_bits);
  DEF_FIELD(1, 0, word_length);

  static auto Get() { return hwreg::RegisterAddr<ULCON>(0); }
};

// general control register
struct UCON : public hwreg::RegisterBase<UCON, uint32_t> {
  // 31:23 Reserved.
  DEF_FIELD(22, 20, tx_dma_burst_size);
  // 19 Reserved.
  DEF_FIELD(18, 16, rx_dma_burst_size);
  DEF_FIELD(15, 12, rx_timeout_interrupt_interval);
  DEF_BIT(11, rx_timeout_with_empty_rx_fifo);
  DEF_BIT(10, rx_timeout_dma_suspend_enable);
  // 9:8 Reserved.
  DEF_BIT(7, rx_timeout_enable);
  DEF_BIT(6, rx_error_status_interrupt_enable);
  DEF_BIT(5, loop_back_mode);
  DEF_BIT(4, send_break_signal);
  DEF_FIELD(3, 2, transmit_mode);
  DEF_FIELD(1, 0, receive_mode);

  static auto Get() { return hwreg::RegisterAddr<UCON>(0x4); }
};

// fifo control register
struct UFCON : public hwreg::RegisterBase<UFCON, uint32_t> {
  // 31:11 Reserved.
  DEF_FIELD(10, 8, tx_fifo_trigger_level);
  // 7 Reserved.
  DEF_FIELD(6, 4, rx_fifo_trigger_level);
  // 3 Reserved.
  DEF_BIT(2, tx_fifo_reset);
  DEF_BIT(1, rx_fifo_reset);
  DEF_BIT(0, fifo_enable);

  static auto Get() { return hwreg::RegisterAddr<UFCON>(0x8); }
};

// fifo status register
struct UFSTAT : public hwreg::RegisterBase<UFSTAT, uint32_t> {
  // 31:25 Reserved.
  DEF_BIT(24, tx_fifo_full);
  DEF_FIELD(23, 16, tx_fifo_count);
  // 15:10 Reserved.
  DEF_BIT(9, rx_fifo_error);
  DEF_BIT(8, rx_fifo_full);
  DEF_FIELD(7, 0, rx_fifo_count);

  static auto Get() { return hwreg::RegisterAddr<UFSTAT>(0x18); }
};

// transmit register
struct UTXH : public hwreg::RegisterBase<UTXH, uint32_t> {
  // 31:8 Reserved.
  DEF_FIELD(7, 0, data);

  static auto Get() { return hwreg::RegisterAddr<UTXH>(0x20); }
};

// receive register
struct URXH : public hwreg::RegisterBase<URXH, uint32_t> {
  // 31:8 Reserved.
  DEF_FIELD(7, 0, data);

  static auto Get() { return hwreg::RegisterAddr<URXH>(0x24); }
};

// interrupt mask register
struct UINTM : public hwreg::RegisterBase<UINTM, uint32_t> {
  // 31:4 Reserved.
  DEF_BIT(3, mask_cts_irq);
  DEF_BIT(2, mask_transmit_irq);
  DEF_BIT(1, mask_error_irq);
  DEF_BIT(0, mask_receive_irq);

  static auto Get() { return hwreg::RegisterAddr<UINTM>(0x38); }
};

// Universal Serial Config register
struct USI_CONFIG : public hwreg::RegisterBase<USI_CONFIG, uint32_t> {
  // 31:3 Reserved.
  DEF_BIT(2, config_i2c);
  DEF_BIT(1, config_spi);
  DEF_BIT(0, config_uart);

  static auto Get() { return hwreg::RegisterAddr<USI_CONFIG>(0xc0); }
};

// Universal Serial Control register
struct USI_CON : public hwreg::RegisterBase<USI_CON, uint32_t> {
  // 31:1 Reserved.
  DEF_BIT(0, reset);

  static auto Get() { return hwreg::RegisterAddr<USI_CON>(0xc4); }
};

// Universal Serial FIFO Depth register
struct FIFO_DEPTH : public hwreg::RegisterBase<FIFO_DEPTH, uint32_t> {
  // 31:25 Reserved.
  DEF_FIELD(24, 16, tx_fifo_depth);
  // 15:9 Reserved.
  DEF_FIELD(8, 0, rx_fifo_depth);

  static auto Get() { return hwreg::RegisterAddr<FIFO_DEPTH>(0xdc); }
};

// The number of `IoSlots` used by this driver, determined by the last accessed register, see
// `FIFO_DEPTH`. For unscaled MMIO, this corresponds to the size of the MMIO region
// from a provided base address.
static constexpr size_t kIoSlots = 0xdc + sizeof(uint32_t);

struct Driver : public DriverBase<Driver, ZBI_KERNEL_DRIVER_MOTMOT_UART, zbi_dcfg_simple_t,
                                  IoRegisterType::kMmio8, kIoSlots> {
  using Base = DriverBase<Driver, ZBI_KERNEL_DRIVER_MOTMOT_UART, zbi_dcfg_simple_t,
                          IoRegisterType::kMmio8, kIoSlots>;

  static constexpr std::string_view config_name() { return "motmot"; }

  template <typename... Args>
  explicit Driver(Args&&... args) : Base(std::forward<Args>(args)...) {}

  template <class IoProvider>
  void Init(IoProvider& io) {
    // Do a very basic setup to ensure the RX and TX path is enabled and interrupts
    // are masked.

    // Read the fifo depth
    auto fifo_depth = FIFO_DEPTH::Get().ReadFrom(io.io());
    rx_fifo_depth_ = fifo_depth.rx_fifo_depth();
    tx_fifo_depth_ = fifo_depth.tx_fifo_depth();

    // Mask all IRQs
    UINTM::Get()
        .FromValue(0)
        .set_mask_cts_irq(1)
        .set_mask_transmit_irq(1)
        .set_mask_error_irq(1)
        .set_mask_receive_irq(1)
        .WriteTo(io.io());

    // Disable fifo
    UFCON::Get()
        .FromValue(0)
        .set_tx_fifo_trigger_level(0)
        .set_rx_fifo_trigger_level(0)
        .set_fifo_enable(0)
        .WriteTo(io.io());

    // Reset the fifo and wait for it to clear
    UFCON::Get().ReadFrom(io.io()).set_tx_fifo_reset(1).set_rx_fifo_reset(1).WriteTo(io.io());

    // wait for both the tx and rx fifo reset to clear
    auto ufcon_reg = UFCON::Get().FromValue(0);
    do {
      ufcon_reg.ReadFrom(io.io());
    } while (ufcon_reg.tx_fifo_reset() || ufcon_reg.rx_fifo_reset());

    // enable the fifos
    ufcon_reg.ReadFrom(io.io()).set_fifo_enable(1).WriteTo(io.io());

    // enable rx/tx
    UCON::Get()
        .ReadFrom(io.io())
        .set_transmit_mode(1)  // interrupt/polling mode
        .set_receive_mode(1)   // interrupt/polling mode
        .WriteTo(io.io());
  }

  template <class IoProvider>
  bool TxReady(IoProvider& io) {
    return !UFSTAT::Get().ReadFrom(io.io()).tx_fifo_full();
  }

  template <class IoProvider, typename It1, typename It2>
  auto Write(IoProvider& io, bool, It1 it, const It2& end) {
    UTXH::Get().FromValue(0).set_data(*it).WriteTo(io.io());
    return ++it;
  }

  template <class IoProvider>
  std::optional<uint8_t> Read(IoProvider& io) {
    if (UFSTAT::Get().ReadFrom(io.io()).rx_fifo_count() == 0) {
      return {};
    }
    // TODO(https://fxbug.dev/42167593) handle clearing a rx fifo error
    return URXH::Get().ReadFrom(io.io()).data();
  }

  template <class IoProvider>
  void EnableTxInterrupt(IoProvider& io, bool enable = true) {
    // Stubbed out implementation that does nothing.
  }

  template <class IoProvider>
  void EnableRxInterrupt(IoProvider& io, bool enable = true) {
    // Stubbed out implementation that does nothing.
  }

  template <class IoProvider, typename EnableInterruptCallback>
  void InitInterrupt(IoProvider& io, EnableInterruptCallback&& enable_interrupt_callback) {
    // Stubbed out implementation.
    // TODO(https://fxbug.dev/42066912): implement me
    enable_interrupt_callback();
  }

  template <class IoProvider, class Lock, class Waiter, class Tx, class Rx>
  void Interrupt(IoProvider& io, Lock& lock, Waiter& waiter, Tx&& tx, Rx&& rx) {
    // Stubber out implementation.
    // TODO(https://fxbug.dev/42066912): implement me
  }

 private:
  uint32_t rx_fifo_depth_ = 0;
  uint32_t tx_fifo_depth_ = 0;
};

}  // namespace uart::motmot

#endif  // LIB_UART_MOTMOT_H_
