// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#include "sw/device/lib/dif/dif_uart.h"

#include <stddef.h>

#include "sw/device/lib/base/bitfield.h"
#include "sw/device/lib/base/mmio.h"

#include "uart_regs.h"  // Generated.

#define UART_INTR_STATE_MASK 0xffffffffu

const uint32_t kDifUartFifoSizeBytes = 32u;

static bool uart_tx_full(const dif_uart_t *uart) {
  return mmio_region_get_bit32(uart->params.base_addr, UART_STATUS_REG_OFFSET,
                               UART_STATUS_TXFULL_BIT);
}

static bool uart_tx_idle(const dif_uart_t *uart) {
  return mmio_region_get_bit32(uart->params.base_addr, UART_STATUS_REG_OFFSET,
                               UART_STATUS_TXIDLE_BIT);
}

static bool uart_rx_empty(const dif_uart_t *uart) {
  return mmio_region_get_bit32(uart->params.base_addr, UART_STATUS_REG_OFFSET,
                               UART_STATUS_RXEMPTY_BIT);
}

static uint8_t uart_rx_fifo_read(const dif_uart_t *uart) {
  uint32_t reg =
      mmio_region_read32(uart->params.base_addr, UART_RDATA_REG_OFFSET);

  return reg & UART_RDATA_RDATA_MASK;
}

static void uart_tx_fifo_write(const dif_uart_t *uart, uint8_t byte) {
  uint32_t reg = (byte & UART_WDATA_WDATA_MASK) << UART_WDATA_WDATA_OFFSET;
  mmio_region_write32(uart->params.base_addr, UART_WDATA_REG_OFFSET, reg);
}

/**
 * Get the corresponding interrupt register bit offset. INTR_STATE, INTR_ENABLE
 * and INTR_TEST registers have the same bit offsets, so this routine can be
 * reused.
 */
static bool uart_irq_offset_get(dif_uart_irq_t irq_type,
                                ptrdiff_t *offset_out) {
  ptrdiff_t offset;
  switch (irq_type) {
    case kDifUartIrqTxWatermark:
      offset = UART_INTR_STATE_TX_WATERMARK_BIT;
      break;
    case kDifUartIrqRxWatermark:
      offset = UART_INTR_STATE_RX_WATERMARK_BIT;
      break;
    case kDifUartIrqTxEmpty:
      offset = UART_INTR_STATE_TX_EMPTY_BIT;
      break;
    case kDifUartIrqRxOverflow:
      offset = UART_INTR_STATE_RX_OVERFLOW_BIT;
      break;
    case kDifUartIrqRxFrameErr:
      offset = UART_INTR_STATE_RX_FRAME_ERR_BIT;
      break;
    case kDifUartIrqRxBreakErr:
      offset = UART_INTR_STATE_RX_BREAK_ERR_BIT;
      break;
    case kDifUartIrqRxTimeout:
      offset = UART_INTR_STATE_RX_TIMEOUT_BIT;
      break;
    case kDifUartIrqRxParityErr:
      offset = UART_INTR_STATE_RX_PARITY_ERR_BIT;
      break;
    default:
      return false;
  }

  *offset_out = offset;

  return true;
}

static void uart_reset(const dif_uart_t *uart) {
  mmio_region_write32(uart->params.base_addr, UART_CTRL_REG_OFFSET, 0u);
  // Write to the relevant bits clears the FIFOs.
  mmio_region_write32(
      uart->params.base_addr, UART_FIFO_CTRL_REG_OFFSET,
      (1u << UART_FIFO_CTRL_RXRST_BIT) | (1u << UART_FIFO_CTRL_TXRST_BIT));
  mmio_region_write32(uart->params.base_addr, UART_OVRD_REG_OFFSET, 0u);
  mmio_region_write32(uart->params.base_addr, UART_TIMEOUT_CTRL_REG_OFFSET, 0u);
  mmio_region_write32(uart->params.base_addr, UART_INTR_ENABLE_REG_OFFSET, 0u);
  mmio_region_write32(uart->params.base_addr, UART_INTR_STATE_REG_OFFSET,
                      UART_INTR_STATE_MASK);
}

/**
 * Write up to `bytes_requested` number of bytes to the TX FIFO.
 */
static size_t uart_bytes_send(const dif_uart_t *uart, const uint8_t *data,
                              size_t bytes_requested) {
  size_t bytes_written = 0;
  while ((bytes_written < bytes_requested) && !uart_tx_full(uart)) {
    uart_tx_fifo_write(uart, data[bytes_written]);
    ++bytes_written;
  }

  return bytes_written;
}

/**
 * Read up to `bytes_requested` number of bytes from the RX FIFO.
 */
static size_t uart_bytes_receive(const dif_uart_t *uart, size_t bytes_requested,
                                 uint8_t *data) {
  size_t bytes_read = 0;
  while ((bytes_read < bytes_requested) && !uart_rx_empty(uart)) {
    data[bytes_read] = uart_rx_fifo_read(uart);
    ++bytes_read;
  }

  return bytes_read;
}

dif_uart_result_t dif_uart_init(dif_uart_params_t params, dif_uart_t *uart) {
  if (uart == NULL) {
    return kDifUartBadArg;
  }

  uart->params = params;
  return kDifUartOk;
}

dif_uart_config_result_t dif_uart_configure(const dif_uart_t *uart,
                                            dif_uart_config_t config) {
  if (uart == NULL) {
    return kDifUartConfigBadArg;
  }

  if (config.baudrate == 0 || config.clk_freq_hz == 0) {
    return kDifUartConfigBadConfig;
  }

  // Calculation formula: NCO = 16 * 2^nco_width * baud / fclk.

  // Compute NCO register bit width
  uint32_t nco_width = 0;

  for (int i = 0; i < 32; i++) {
    nco_width += (UART_CTRL_NCO_MASK >> i) & 1;
  }

  _Static_assert((UART_CTRL_NCO_MASK >> 28) == 0,
                 "NCO bit width exceeds 28 bits.");

  // NCO creates 16x of baudrate. So, in addition to the nco_width,
  // 2^4 should be multiplied.
  uint64_t nco =
      ((uint64_t)config.baudrate << (nco_width + 4)) / config.clk_freq_hz;
  uint32_t nco_masked = nco & UART_CTRL_NCO_MASK;

  // Requested baudrate is too high for the given clock frequency.
  if (nco != nco_masked) {
    return kDifUartConfigBadNco;
  }

  // Must be called before the first write to any of the UART registers.
  uart_reset(uart);

  // Set baudrate, enable RX and TX, configure parity.
  uint32_t reg = (nco_masked << UART_CTRL_NCO_OFFSET);
  reg |= (1u << UART_CTRL_TX_BIT);
  reg |= (1u << UART_CTRL_RX_BIT);
  if (config.parity_enable == kDifUartToggleEnabled) {
    reg |= (1u << UART_CTRL_PARITY_EN_BIT);
  }
  if (config.parity == kDifUartParityOdd) {
    reg |= (1u << UART_CTRL_PARITY_ODD_BIT);
  }
  mmio_region_write32(uart->params.base_addr, UART_CTRL_REG_OFFSET, reg);

  // Reset RX/TX FIFOs.
  reg = (1u << UART_FIFO_CTRL_RXRST_BIT);
  reg |= (1u << UART_FIFO_CTRL_TXRST_BIT);
  mmio_region_write32(uart->params.base_addr, UART_FIFO_CTRL_REG_OFFSET, reg);

  // Disable interrupts.
  mmio_region_write32(uart->params.base_addr, UART_INTR_ENABLE_REG_OFFSET, 0u);

  return kDifUartConfigOk;
}

dif_uart_result_t dif_uart_irq_is_pending(const dif_uart_t *uart,
                                          dif_uart_irq_t irq,
                                          bool *is_pending) {
  if (uart == NULL || is_pending == NULL) {
    return kDifUartBadArg;
  }

  ptrdiff_t offset;
  if (!uart_irq_offset_get(irq, &offset)) {
    return kDifUartError;
  }

  *is_pending = mmio_region_get_bit32(uart->params.base_addr,
                                      UART_INTR_STATE_REG_OFFSET, offset);
  return kDifUartOk;
}

dif_uart_result_t dif_uart_irq_acknowledge(const dif_uart_t *uart,
                                           dif_uart_irq_t irq) {
  if (uart == NULL) {
    return kDifUartBadArg;
  }

  ptrdiff_t offset;
  if (!uart_irq_offset_get(irq, &offset)) {
    return kDifUartError;
  }

  // Writing to the register clears the corresponding bits.
  mmio_region_write_only_set_bit32(uart->params.base_addr,
                                   UART_INTR_STATE_REG_OFFSET, offset);

  return kDifUartOk;
}

dif_uart_result_t dif_uart_irq_disable_all(const dif_uart_t *uart,
                                           dif_uart_irq_snapshot_t *snapshot) {
  if (uart == NULL) {
    return kDifUartBadArg;
  }

  // Pass the current interrupt state to the caller.
  if (snapshot != NULL) {
    *snapshot =
        mmio_region_read32(uart->params.base_addr, UART_INTR_ENABLE_REG_OFFSET);
  }

  // Disable all UART interrupts.
  mmio_region_write32(uart->params.base_addr, UART_INTR_ENABLE_REG_OFFSET, 0u);

  return kDifUartOk;
}

dif_uart_result_t dif_uart_irq_restore_all(
    const dif_uart_t *uart, const dif_uart_irq_snapshot_t *snapshot) {
  if (uart == NULL || snapshot == NULL) {
    return kDifUartBadArg;
  }

  mmio_region_write32(uart->params.base_addr, UART_INTR_ENABLE_REG_OFFSET,
                      *snapshot);

  return kDifUartOk;
}

dif_uart_result_t dif_uart_irq_get_enabled(const dif_uart_t *uart,
                                           dif_uart_irq_t irq,
                                           dif_uart_toggle_t *state) {
  if (uart == NULL || state == NULL) {
    return kDifUartBadArg;
  }

  ptrdiff_t offset;
  if (!uart_irq_offset_get(irq, &offset)) {
    return kDifUartError;
  }

  bool is_enabled = mmio_region_get_bit32(uart->params.base_addr,
                                          UART_INTR_ENABLE_REG_OFFSET, offset);
  *state = is_enabled ? kDifUartToggleEnabled : kDifUartToggleDisabled;

  return kDifUartOk;
}

dif_uart_result_t dif_uart_irq_set_enabled(const dif_uart_t *uart,
                                           dif_uart_irq_t irq,
                                           dif_uart_toggle_t state) {
  if (uart == NULL) {
    return kDifUartBadArg;
  }

  ptrdiff_t offset;
  if (!uart_irq_offset_get(irq, &offset)) {
    return kDifUartError;
  }

  if (state == kDifUartToggleEnabled) {
    mmio_region_nonatomic_set_bit32(uart->params.base_addr,
                                    UART_INTR_ENABLE_REG_OFFSET, offset);
  } else {
    mmio_region_nonatomic_clear_bit32(uart->params.base_addr,
                                      UART_INTR_ENABLE_REG_OFFSET, offset);
  }

  return kDifUartOk;
}

dif_uart_result_t dif_uart_irq_force(const dif_uart_t *uart,
                                     dif_uart_irq_t irq) {
  if (uart == NULL) {
    return kDifUartBadArg;
  }

  ptrdiff_t offset;
  if (!uart_irq_offset_get(irq, &offset)) {
    return kDifUartError;
  }

  // Force the requested interrupt.
  mmio_region_nonatomic_set_bit32(uart->params.base_addr,
                                  UART_INTR_TEST_REG_OFFSET, offset);

  return kDifUartOk;
}

dif_uart_result_t dif_uart_watermark_rx_set(const dif_uart_t *uart,
                                            dif_uart_watermark_t watermark) {
  if (uart == NULL) {
    return kDifUartBadArg;
  }

  // Check if the requested watermark is valid, and get a corresponding
  // register definition to be written.
  uint32_t value;
  switch (watermark) {
    case kDifUartWatermarkByte1:
      value = UART_FIFO_CTRL_RXILVL_VALUE_RXLVL1;
      break;
    case kDifUartWatermarkByte4:
      value = UART_FIFO_CTRL_RXILVL_VALUE_RXLVL4;
      break;
    case kDifUartWatermarkByte8:
      value = UART_FIFO_CTRL_RXILVL_VALUE_RXLVL8;
      break;
    case kDifUartWatermarkByte16:
      value = UART_FIFO_CTRL_RXILVL_VALUE_RXLVL16;
      break;
    case kDifUartWatermarkByte30:
      value = UART_FIFO_CTRL_RXILVL_VALUE_RXLVL30;
      break;
    default:
      return kDifUartError;
  }

  // Set watermark level.
  mmio_region_nonatomic_set_field32(uart->params.base_addr,
                                    UART_FIFO_CTRL_REG_OFFSET,
                                    UART_FIFO_CTRL_RXILVL_FIELD, value);

  return kDifUartOk;
}

dif_uart_result_t dif_uart_watermark_tx_set(const dif_uart_t *uart,
                                            dif_uart_watermark_t watermark) {
  if (uart == NULL) {
    return kDifUartBadArg;
  }

  // Check if the requested watermark is valid, and get a corresponding
  // register definition to be written.
  uint32_t value;
  switch (watermark) {
    case kDifUartWatermarkByte1:
      value = UART_FIFO_CTRL_TXILVL_VALUE_TXLVL1;
      break;
    case kDifUartWatermarkByte4:
      value = UART_FIFO_CTRL_TXILVL_VALUE_TXLVL4;
      break;
    case kDifUartWatermarkByte8:
      value = UART_FIFO_CTRL_TXILVL_VALUE_TXLVL8;
      break;
    case kDifUartWatermarkByte16:
      value = UART_FIFO_CTRL_TXILVL_VALUE_TXLVL16;
      break;
    default:
      // The minimal TX watermark is 1 byte, maximal 16 bytes.
      return kDifUartError;
  }

  // Set watermark level.
  mmio_region_nonatomic_set_field32(uart->params.base_addr,
                                    UART_FIFO_CTRL_REG_OFFSET,
                                    UART_FIFO_CTRL_TXILVL_FIELD, value);

  return kDifUartOk;
}

dif_uart_result_t dif_uart_bytes_send(const dif_uart_t *uart,
                                      const uint8_t *data,
                                      size_t bytes_requested,
                                      size_t *bytes_written) {
  if (uart == NULL || data == NULL) {
    return kDifUartBadArg;
  }

  // `bytes_written` is an optional parameter.
  size_t res = uart_bytes_send(uart, data, bytes_requested);
  if (bytes_written != NULL) {
    *bytes_written = res;
  }

  return kDifUartOk;
}

dif_uart_result_t dif_uart_bytes_receive(const dif_uart_t *uart,
                                         size_t bytes_requested, uint8_t *data,
                                         size_t *bytes_read) {
  if (uart == NULL || data == NULL) {
    return kDifUartBadArg;
  }

  // `bytes_read` is an optional parameter.
  size_t res = uart_bytes_receive(uart, bytes_requested, data);
  if (bytes_read != NULL) {
    *bytes_read = res;
  }

  return kDifUartOk;
}

dif_uart_result_t dif_uart_byte_send_polled(const dif_uart_t *uart,
                                            uint8_t byte) {
  if (uart == NULL) {
    return kDifUartBadArg;
  }

  // Busy wait for the TX FIFO to free up.
  while (uart_tx_full(uart)) {
  }

  (void)uart_bytes_send(uart, &byte, 1);

  // Busy wait for the TX FIFO to be drained and for HW to finish processing
  // the last byte.
  while (!uart_tx_idle(uart)) {
  }

  return kDifUartOk;
}

dif_uart_result_t dif_uart_byte_receive_polled(const dif_uart_t *uart,
                                               uint8_t *byte) {
  if (uart == NULL || byte == NULL) {
    return kDifUartBadArg;
  }

  // Busy wait for the RX message in the FIFO.
  while (uart_rx_empty(uart)) {
  }

  (void)uart_bytes_receive(uart, 1, byte);

  return kDifUartOk;
}

dif_uart_result_t dif_uart_rx_bytes_available(const dif_uart_t *uart,
                                              size_t *num_bytes) {
  if (uart == NULL || num_bytes == NULL) {
    return kDifUartBadArg;
  }

  // RX FIFO fill level (in bytes).
  *num_bytes = (size_t)mmio_region_read_mask32(
      uart->params.base_addr, UART_FIFO_STATUS_REG_OFFSET,
      UART_FIFO_STATUS_RXLVL_MASK, UART_FIFO_STATUS_RXLVL_OFFSET);

  return kDifUartOk;
}

dif_uart_result_t dif_uart_tx_bytes_available(const dif_uart_t *uart,
                                              size_t *num_bytes) {
  if (uart == NULL || num_bytes == NULL) {
    return kDifUartBadArg;
  }

  // TX FIFO fill level (in bytes).
  uint32_t fill_bytes = mmio_region_read_mask32(
      uart->params.base_addr, UART_FIFO_STATUS_REG_OFFSET,
      UART_FIFO_STATUS_TXLVL_MASK, UART_FIFO_STATUS_TXLVL_OFFSET);

  *num_bytes = kDifUartFifoSizeBytes - fill_bytes;

  return kDifUartOk;
}

dif_uart_result_t dif_uart_fifo_reset(const dif_uart_t *uart,
                                      dif_uart_fifo_reset_t reset) {
  if (uart == NULL) {
    return kDifUartBadArg;
  }

  uint32_t reg =
      mmio_region_read32(uart->params.base_addr, UART_FIFO_CTRL_REG_OFFSET);

  if (reset == kDifUartFifoResetRx || reset == kDifUartFifoResetAll) {
    reg = bitfield_field32_write(reg,
                                 (bitfield_field32_t){
                                     .mask = 0x1,
                                     .index = UART_FIFO_CTRL_RXRST_BIT,
                                 },
                                 1);
  }

  if (reset == kDifUartFifoResetTx || reset == kDifUartFifoResetAll) {
    reg = bitfield_field32_write(reg,
                                 (bitfield_field32_t){
                                     .mask = 0x1,
                                     .index = UART_FIFO_CTRL_TXRST_BIT,
                                 },
                                 1);
  }

  mmio_region_write32(uart->params.base_addr, UART_FIFO_CTRL_REG_OFFSET, reg);

  return kDifUartOk;
}

dif_uart_result_t dif_uart_loopback_set(const dif_uart_t *uart,
                                        dif_uart_loopback_t loopback,
                                        dif_uart_toggle_t enable) {
  if (uart == NULL) {
    return kDifUartBadArg;
  }

  bitfield_field32_t field = {
      .mask = 0x1,
      .index = loopback ? UART_CTRL_LLPBK_BIT : UART_CTRL_SLPBK_BIT,
  };

  uint32_t reg =
      mmio_region_read32(uart->params.base_addr, UART_CTRL_REG_OFFSET);
  reg = bitfield_field32_write(reg, field, enable == kDifUartToggleEnabled);
  mmio_region_write32(uart->params.base_addr, UART_CTRL_REG_OFFSET, reg);

  return kDifUartOk;
}
