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

#include "spi_device_regs.h"  // Generated.

#include "sw/device/lib/common.h"

#define SPI_DEVICE0_BASE_ADDR 0x40020000
#define SPID_SRAM_ADDR SPI_DEVICE_BUFFER(0)
#define SPID_RXF_BASE 0x000
#define SPID_RXF_SIZE 0x400
#define SPID_TXF_BASE 0x600
#define SPID_TXF_SIZE 0x200

#define SPID_SRAM_SIZE (0x800)

/* Note: these will correctly remove the phase bit */
#define READ32_RXFPTR(P) \
  REG32(SPID_SRAM_ADDR + SPID_RXF_BASE + ((P) & (SPID_RXF_SIZE - 1)))

#define ACCESS32_TXFPTR(P) \
  REG32(SPID_SRAM_ADDR + SPID_TXF_BASE + ((P) & ((SPID_TXF_SIZE - 1) & ~0x3)))

uint32_t calc_depth(uint32_t wptr, uint32_t rptr, uint32_t size);

void spid_init(void) {
  /* Abort 0 */
  REG32(SPI_DEVICE_CONTROL(0)) =
      REG32(SPI_DEVICE_CONTROL(0)) & ~(1 << SPI_DEVICE_CONTROL_ABORT);

  /* CPOL(0), CPHA(0), ORDERs(00), TIMER(63) */
  REG32(SPI_DEVICE_CFG(0)) =
      ((0 << SPI_DEVICE_CFG_CPOL) | (0 << SPI_DEVICE_CFG_CPHA) |
       (0 << SPI_DEVICE_CFG_RX_ORDER) | (0 << SPI_DEVICE_CFG_TX_ORDER) |
       ((63 & SPI_DEVICE_CFG_TIMER_V_MASK) << SPI_DEVICE_CFG_TIMER_V_OFFSET));

  /* SRAM RXF/TXF ADDR. */
  REG32(SPI_DEVICE_RXF_ADDR(0)) =
      ((SPID_RXF_BASE & SPI_DEVICE_RXF_ADDR_BASE_MASK)
       << SPI_DEVICE_RXF_ADDR_BASE_OFFSET) |
      (((SPID_RXF_SIZE - 1) & SPI_DEVICE_RXF_ADDR_LIMIT_MASK)
       << SPI_DEVICE_RXF_ADDR_LIMIT_OFFSET);

  REG32(SPI_DEVICE_TXF_ADDR(0)) =
      ((SPID_TXF_BASE & SPI_DEVICE_TXF_ADDR_BASE_MASK)
       << SPI_DEVICE_TXF_ADDR_BASE_OFFSET) |
      (((SPID_TXF_SIZE - 1) & SPI_DEVICE_TXF_ADDR_LIMIT_MASK)
       << SPI_DEVICE_TXF_ADDR_LIMIT_OFFSET);
}

/**
 * Calculation FIFO depth in bytes
 *
 *  Assume SRAM size is fixed (constant) given by SPI_DEVICE_BUFFER_SIZE
 *
 * Fifo pointers are in bytes
 */
inline uint32_t calc_depth(uint32_t wptr, uint32_t rptr, uint32_t size) {
  const uint32_t sram_szw = BITLENGTH(SPI_DEVICE_BUFFER_SIZE_BYTES - 1);
  uint32_t depth;
  uint32_t wptr_phase, rptr_phase, wptr_v, rptr_v;
  wptr_phase = wptr >> sram_szw;
  rptr_phase = rptr >> sram_szw;
  wptr_v = wptr & (SPI_DEVICE_BUFFER_SIZE_BYTES - 1);
  rptr_v = rptr & (SPI_DEVICE_BUFFER_SIZE_BYTES - 1);

  if (wptr_phase == rptr_phase) {
    depth = (wptr_v - rptr_v);
  } else {
    depth = size - rptr_v + wptr_v;
  }

  return depth;
}

/*
 * Increment pointer, zero and flip phase if it gets to size
 */
uint32_t ptr_inc(uint32_t ptr, uint32_t inc, uint32_t size) {
  uint32_t phase = ptr & SPI_DEVICE_BUFFER_SIZE_BYTES;
  ptr = (ptr & (SPI_DEVICE_BUFFER_SIZE_BYTES - 1)) + inc;
  if (ptr >= size) {
    ptr -= size;
    phase ^= SPI_DEVICE_BUFFER_SIZE_BYTES;
  }
  return ptr | phase;
}

static int word_aligned(void *p) { return (((int)p & 0x3) == 0); }

uint32_t spid_send(void *data, uint32_t len_bytes) {
  uint32_t txf_ptr, txf_wptr, txf_rptr;
  uint32_t fifo_inuse_bytes;
  uint32_t msg_length_bytes;

  /* Check if TXF has enough space */
  txf_ptr = REG32(SPI_DEVICE_TXF_PTR(0));
  txf_wptr = (txf_ptr >> SPI_DEVICE_TXF_PTR_WPTR_OFFSET) &
             SPI_DEVICE_TXF_PTR_WPTR_MASK;
  txf_rptr = (txf_ptr >> SPI_DEVICE_TXF_PTR_RPTR_OFFSET) &
             SPI_DEVICE_TXF_PTR_RPTR_MASK;

  fifo_inuse_bytes = calc_depth(txf_wptr, txf_rptr, SPID_TXF_SIZE);

  // Reserve the last 4 bytes in the fifo so it is always safe
  // to write 32-bit words
  if (len_bytes < SPID_TXF_SIZE - fifo_inuse_bytes - 4) {
    // Safe to send all data
    msg_length_bytes = len_bytes;
  } else {
    msg_length_bytes = SPID_TXF_SIZE - fifo_inuse_bytes - 4;
  }
  int tocopy = msg_length_bytes;

  // Aligned case can just copy words
  if (word_aligned(data) && word_aligned((void *)txf_wptr)) {
    uint32_t *data_w = (uint32_t *)data;
    while (tocopy > 0) {
      ACCESS32_TXFPTR(txf_wptr) = *data_w++;
      if (tocopy >= 4) {
        txf_wptr = ptr_inc(txf_wptr, 4, SPID_TXF_SIZE);
        tocopy -= 4;
      } else {
        txf_wptr = ptr_inc(txf_wptr, tocopy, SPID_TXF_SIZE);
        tocopy = 0;  // tocopy -= tocopy always gives zero
      }
    }
  } else {
    // preserve data if unaligned start
    uint8_t *data_b = (uint8_t *)data;
    uint32_t d = ACCESS32_TXFPTR(txf_wptr);
    while (tocopy > 0) {
      int shift = (txf_wptr & 0x3) * 8;
      uint32_t mask = 0xff << shift;
      d = (d & ~mask) | (*data_b++ << shift);
      if ((txf_wptr & 0x3) == 0x3) {
        ACCESS32_TXFPTR(txf_wptr) = d;
      }
      txf_wptr = ptr_inc(txf_wptr, 1, SPID_TXF_SIZE);
      tocopy--;
    }
  }

  // Write pointer, requires read pointer to be RO
  REG32(SPI_DEVICE_TXF_PTR(0)) = txf_wptr << SPI_DEVICE_TXF_PTR_WPTR_OFFSET;

  return msg_length_bytes;
}

uint32_t spid_read_nb(void *data, uint32_t len_bytes) {
  uint32_t rxf_ptr, rxf_wptr, rxf_rptr;
  uint32_t msg_len_bytes;

  rxf_ptr = REG32(SPI_DEVICE_RXF_PTR(0));
  rxf_wptr = (rxf_ptr >> SPI_DEVICE_RXF_PTR_WPTR_OFFSET) &
             SPI_DEVICE_RXF_PTR_WPTR_MASK;
  rxf_rptr = (rxf_ptr >> SPI_DEVICE_RXF_PTR_RPTR_OFFSET) &
             SPI_DEVICE_RXF_PTR_RPTR_MASK;

  msg_len_bytes = calc_depth(rxf_wptr, rxf_rptr, SPID_RXF_SIZE);
  if (msg_len_bytes == 0) {
    return 0;
  }
  /* Check there is room for the whole buffer */
  if (msg_len_bytes > len_bytes) {
    msg_len_bytes = len_bytes;
  }

  int tocopy = msg_len_bytes;
  // Aligned case  -- which for now it always will be
  // if tocopy is not multiple of 4 then will read / write extra bytes
  // so check buffer length
  if (word_aligned(data) && ((len_bytes & 0x3) == 0) &&
      word_aligned((void *)rxf_ptr)) {
    uint32_t *data_w = (uint32_t *)data;
    while (tocopy > 0) {
      *data_w++ = READ32_RXFPTR(rxf_rptr);
      if (tocopy >= 4) {
        rxf_rptr = ptr_inc(rxf_rptr, 4, SPID_RXF_SIZE);
        tocopy -= 4;
      } else {
        rxf_rptr = ptr_inc(rxf_rptr, tocopy, SPID_RXF_SIZE);
        tocopy = 0;  // tocopy -= tocopy always gives zero
      }
    }
  } else {
    uint8_t *data_b = (uint8_t *)data;
    // Have to deal with only being able to do 32-bit accesses
    int dst = 0;
    uint32_t d = READ32_RXFPTR(rxf_rptr & ~0x3);
    while (tocopy--) {
      int boff = rxf_rptr & 0x3;
      data_b[dst++] = (d >> (boff * 8)) & 0xff;
      rxf_rptr = ptr_inc(rxf_rptr, 1, SPID_RXF_SIZE);
      if (((rxf_rptr & 0x3) == 0) && tocopy) {
        d = READ32_RXFPTR(rxf_rptr);
      }
    }
  }
  /* Update read pointer -- NB relies on write pointer being RO */
  REG32(SPI_DEVICE_RXF_PTR(0)) = rxf_rptr << SPI_DEVICE_RXF_PTR_RPTR_OFFSET;

  return msg_len_bytes;
}

uint32_t spid_bytes_available(void) {
  uint32_t rxf_ptr = REG32(SPI_DEVICE_RXF_PTR(0));
  uint32_t rxf_wptr = (rxf_ptr >> SPI_DEVICE_RXF_PTR_WPTR_OFFSET) &
                      SPI_DEVICE_RXF_PTR_WPTR_MASK;
  uint32_t rxf_rptr = (rxf_ptr >> SPI_DEVICE_RXF_PTR_RPTR_OFFSET) &
                      SPI_DEVICE_RXF_PTR_RPTR_MASK;

  return calc_depth(rxf_wptr, rxf_rptr, SPID_RXF_SIZE);
}
