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

#include "spi_device.h"

#include "common.h"
#include "spi_device_regs.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);
}
