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

#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
#include "usbdev_regs.h"  // Generated.

#define USBDEV_BASE_ADDR TOP_EARLGREY_USBDEV_BASE_ADDR

#define EXTRACT(n, f) ((n >> USBDEV_##f##_OFFSET) & USBDEV_##f##_MASK)

#define SETBIT(val, bit) (val | 1 << bit)
#define CLRBIT(val, bit) (val & ~(1 << bit))

#define REG32(add) *((volatile uint32_t *)(add))

static bool endpoint_is_in(uint8_t endpoint) { return endpoint & 0x80; }

static uint8_t endpoint_number(uint8_t endpoint) { return endpoint & 0x7F; }

// Free buffer pool is held on a simple stack
// Initalize to all buffer IDs are free
static void buf_init(usbdev_ctx_t *ctx) {
  for (int i = 0; i < NUM_BUFS; i++) {
    ctx->freebuf[i] = i;
  }
  ctx->nfree = NUM_BUFS;
}

// Allocating a buffer just pops next ID from the stack
usbbufid_t usbdev_buf_allocate_byid(usbdev_ctx_t *ctx) {
  if (ctx->nfree <= 0) {
    return -1;
  }
  return ctx->freebuf[--ctx->nfree];
}

// Freeing a buffer just pushes the ID back on the stack
int usbdev_buf_free_byid(usbdev_ctx_t *ctx, usbbufid_t buf) {
  if ((ctx->nfree >= NUM_BUFS) || (buf >= NUM_BUFS)) {
    return -1;
  }
  ctx->freebuf[ctx->nfree++] = buf;
  return 0;
}

uint32_t *usbdev_buf_idtoaddr(usbdev_ctx_t *ctx, usbbufid_t buf) {
  return (uint32_t *)(USBDEV_BASE_ADDR + USBDEV_BUFFER_REG_OFFSET +
                      (buf * BUF_LENGTH));
}

void usbdev_buf_copyto_byid(usbdev_ctx_t *ctx, usbbufid_t buf, const void *from,
                            size_t len_bytes) {
  int32_t *from_word = (int32_t *)from;
  int len_words;
  volatile uint32_t *bp = usbdev_buf_idtoaddr(ctx, buf);

  if (len_bytes > BUF_LENGTH) {
    len_bytes = BUF_LENGTH;
  }
  // This will round up if len_bytes is not on a multiple of int32_t
  // Always ok to fill the extra bytes since the buffers are aligned
  len_words = (len_bytes + sizeof(int32_t) - 1) / sizeof(int32_t);
  for (int i = 0; i < len_words; i++) {
    bp[i] = from_word[i];
  }
}

// Supply as many buffers to the receive available fifo as possible
inline static void fill_av_fifo(usbdev_ctx_t *ctx) {
  while (!(REG32(USBDEV_BASE_ADDR + USBDEV_USBSTAT_REG_OFFSET) &
           (1 << USBDEV_USBSTAT_AV_FULL_BIT))) {
    usbbufid_t buf = usbdev_buf_allocate_byid(ctx);
    if (buf < 0) {
      // no more free buffers, can't fill AV FIFO
      break;
    }
    REG32(USBDEV_BASE_ADDR + USBDEV_AVBUFFER_REG_OFFSET) = buf;
  }
}

void usbdev_sendbuf_byid(usbdev_ctx_t *ctx, usbbufid_t buf, size_t size,
                         int endpoint) {
  uint32_t configin =
      USBDEV_BASE_ADDR + USBDEV_CONFIGIN_0_REG_OFFSET + (4 * endpoint);

  if ((endpoint >= NUM_ENDPOINTS) || (buf >= NUM_BUFS)) {
    return;
  }

  if (size > BUF_LENGTH) {
    size = BUF_LENGTH;
  }

  REG32(configin) = ((buf << USBDEV_CONFIGIN_0_BUFFER_0_OFFSET) |
                     (size << USBDEV_CONFIGIN_0_SIZE_0_OFFSET) |
                     (1 << USBDEV_CONFIGIN_0_RDY_0_BIT));
}

void usbdev_poll(usbdev_ctx_t *ctx) {
  uint32_t istate = REG32(USBDEV_BASE_ADDR + USBDEV_INTR_STATE_REG_OFFSET);

  // Do this first to keep things going
  fill_av_fifo(ctx);

  // Process IN completions first so we get the fact that send completed
  // before processing a response
  if (istate & (1 << USBDEV_INTR_STATE_PKT_SENT_BIT)) {
    uint32_t sentep = REG32(USBDEV_BASE_ADDR + USBDEV_IN_SENT_REG_OFFSET);
    uint32_t configin = USBDEV_BASE_ADDR + USBDEV_CONFIGIN_0_REG_OFFSET;
    TRC_C('a' + sentep);
    for (int ep = 0; ep < NUM_ENDPOINTS; ep++) {
      if (sentep & (1 << ep)) {
        // Free up the buffer and optionally callback
        int32_t cfgin = REG32(configin + (4 * ep));
        usbdev_buf_free_byid(ctx, EXTRACT(cfgin, CONFIGIN_0_BUFFER_0));
        if (ctx->tx_done_callback[ep]) {
          ctx->tx_done_callback[ep](ctx->ep_ctx[ep]);
        }
      }
    }
    // Write one to clear all the ones we handled
    REG32(USBDEV_BASE_ADDR + USBDEV_IN_SENT_REG_OFFSET) = sentep;
    // Clear the interupt
    REG32(USBDEV_BASE_ADDR + USBDEV_INTR_STATE_REG_OFFSET) =
        (1 << USBDEV_INTR_STATE_PKT_SENT_BIT);
  }

  if (istate & (1 << USBDEV_INTR_STATE_PKT_RECEIVED_BIT)) {
    while (!(REG32(USBDEV_BASE_ADDR + USBDEV_USBSTAT_REG_OFFSET) &
             (1 << USBDEV_USBSTAT_RX_EMPTY_BIT))) {
      uint32_t rxinfo = REG32(USBDEV_BASE_ADDR + USBDEV_RXFIFO_REG_OFFSET);
      usbbufid_t buf = EXTRACT(rxinfo, RXFIFO_BUFFER);
      int size = EXTRACT(rxinfo, RXFIFO_SIZE);
      int endpoint = EXTRACT(rxinfo, RXFIFO_EP);
      int setup = (rxinfo >> USBDEV_RXFIFO_SETUP_BIT) & 1;

      if (ctx->rx_callback[endpoint]) {
        ctx->rx_callback[endpoint](ctx->ep_ctx[endpoint], buf, size, setup);
      } else {
        TRC_S("USB: unexpected RX ");
        TRC_I(rxinfo, 24);
      }
      usbdev_buf_free_byid(ctx, buf);
    }
    // Clear the interupt
    REG32(USBDEV_BASE_ADDR + USBDEV_INTR_STATE_REG_OFFSET) =
        (1 << USBDEV_INTR_STATE_PKT_RECEIVED_BIT);
  }
  if (istate & ~((1 << USBDEV_INTR_STATE_PKT_RECEIVED_BIT) |
                 (1 << USBDEV_INTR_STATE_PKT_SENT_BIT))) {
    TRC_C('I');
    TRC_I(istate, 12);
    TRC_C(' ');
    REG32(USBDEV_BASE_ADDR + USBDEV_INTR_STATE_REG_OFFSET) =
        istate & ~((1 << USBDEV_INTR_STATE_PKT_RECEIVED_BIT) |
                   (1 << USBDEV_INTR_STATE_PKT_SENT_BIT));
    if (istate & (1 << USBDEV_INTR_ENABLE_LINK_RESET_BIT)) {
      // Link reset
      for (int ep = 0; ep < NUM_ENDPOINTS; ep++) {
        if (ctx->reset[ep]) {
          ctx->reset[ep](ctx->ep_ctx[ep]);
        }
      }

      // Clear the interupt
      REG32(USBDEV_BASE_ADDR + USBDEV_INTR_STATE_REG_OFFSET) =
          (1 << USBDEV_INTR_ENABLE_LINK_RESET_BIT);
    }
  }
  // TODO - clean this up
  // Frame ticks every 1ms, use to flush data every 16ms
  // (faster in DPI but this seems to work ok)
  // At reset frame count is 0, compare to 1 so no calls before SOF received
  uint32_t usbframe = EXTRACT(
      REG32(USBDEV_BASE_ADDR + USBDEV_USBSTAT_REG_OFFSET), USBSTAT_FRAME);
  if ((usbframe & 0xf) == 1) {
    if (ctx->flushed == 0) {
      for (int i = 0; i < NUM_ENDPOINTS; i++) {
        if (ctx->flush[i]) {
          ctx->flush[i](ctx->ep_ctx[i]);
        }
      }
      ctx->flushed = 1;
    }
  } else {
    ctx->flushed = 0;
  }
  // TODO Errors? What Errors?
}

unsigned int usbdev_get_status(usbdev_ctx_t *ctx) {
  unsigned int status = REG32(USBDEV_BASE_ADDR + USBDEV_USBSTAT_REG_OFFSET);
  return status;
}

unsigned int usbdev_get_link_state(usbdev_ctx_t *ctx) {
  unsigned int link_state = EXTRACT(
      REG32(USBDEV_BASE_ADDR + USBDEV_USBSTAT_REG_OFFSET), USBSTAT_LINK_STATE);
  return link_state;
}

unsigned int usbdev_get_address(usbdev_ctx_t *ctx) {
  unsigned int addr =
      EXTRACT(REG32(USBDEV_BASE_ADDR + USBDEV_USBCTRL_REG_OFFSET),
              USBCTRL_DEVICE_ADDRESS);
  return addr;
}

void usbdev_set_deviceid(usbdev_ctx_t *ctx, int deviceid) {
  REG32(USBDEV_BASE_ADDR + USBDEV_USBCTRL_REG_OFFSET) =
      (1 << USBDEV_USBCTRL_ENABLE_BIT) |
      (deviceid << USBDEV_USBCTRL_DEVICE_ADDRESS_OFFSET);
}

void usbdev_halt(usbdev_ctx_t *ctx, int endpoint, int enable) {
  // FIXME: The two endpoints are supposed to be independent
  uint32_t epbit = 1 << endpoint;
  uint32_t stall = REG32(USBDEV_BASE_ADDR + USBDEV_IN_STALL_REG_OFFSET);
  if (enable) {
    stall |= epbit;
  } else {
    stall &= ~epbit;
  }
  REG32(USBDEV_BASE_ADDR + USBDEV_IN_STALL_REG_OFFSET) = stall;
  REG32(USBDEV_BASE_ADDR + USBDEV_OUT_STALL_REG_OFFSET) = stall;
  ctx->halted = stall;
  // TODO future addition would be to callback the endpoint driver
  // for now it just sees its traffic has stopped
}

void usbdev_set_iso(usbdev_ctx_t *ctx, int endpoint, int enable) {
  if (enable) {
    REG32(USBDEV_BASE_ADDR + USBDEV_ISO_REG_OFFSET) =
        SETBIT(REG32(USBDEV_BASE_ADDR + USBDEV_ISO_REG_OFFSET), endpoint);
  } else {
    REG32(USBDEV_BASE_ADDR + USBDEV_ISO_REG_OFFSET) =
        CLRBIT(REG32(USBDEV_BASE_ADDR + USBDEV_ISO_REG_OFFSET), endpoint);
  }
}

void usbdev_clear_data_toggle(usbdev_ctx_t *ctx, int endpoint) {
  REG32(USBDEV_BASE_ADDR + USBDEV_DATA_TOGGLE_CLEAR_REG_OFFSET) =
      (1 << endpoint);
}

void usbdev_set_ep0_stall(usbdev_ctx_t *ctx, int stall) {
  if (stall) {
    REG32(USBDEV_BASE_ADDR + USBDEV_IN_STALL_REG_OFFSET) =
        REG32(USBDEV_BASE_ADDR + USBDEV_IN_STALL_REG_OFFSET) | 1;
    REG32(USBDEV_BASE_ADDR + USBDEV_OUT_STALL_REG_OFFSET) =
        REG32(USBDEV_BASE_ADDR + USBDEV_OUT_STALL_REG_OFFSET) | 1;
  } else {
    REG32(USBDEV_BASE_ADDR + USBDEV_IN_STALL_REG_OFFSET) =
        REG32(USBDEV_BASE_ADDR + USBDEV_IN_STALL_REG_OFFSET) & ~(1);
    REG32(USBDEV_BASE_ADDR + USBDEV_OUT_STALL_REG_OFFSET) =
        REG32(USBDEV_BASE_ADDR + USBDEV_OUT_STALL_REG_OFFSET) & ~(1);
  }
}

// TODO got hang with this inline
int usbdev_can_rem_wake(usbdev_ctx_t *ctx) { return ctx->can_wake; }

void usbdev_endpoint_setup(usbdev_ctx_t *ctx, int ep, int enableout,
                           void *ep_ctx, void (*tx_done)(void *),
                           void (*rx)(void *, usbbufid_t, int, int),
                           void (*flush)(void *), void (*reset)(void *)) {
  ctx->ep_ctx[ep] = ep_ctx;
  ctx->tx_done_callback[ep] = tx_done;
  ctx->rx_callback[ep] = rx;
  ctx->flush[ep] = flush;
  ctx->reset[ep] = reset;

  uint32_t tx_ep_en = REG32(USBDEV_BASE_ADDR + USBDEV_EP_IN_ENABLE_REG_OFFSET);
  tx_ep_en |= (1 << (ep + USBDEV_EP_IN_ENABLE_ENABLE_0_BIT));
  REG32(USBDEV_BASE_ADDR + USBDEV_EP_IN_ENABLE_REG_OFFSET) = tx_ep_en;

  if (enableout) {
    uint32_t rxen = REG32(USBDEV_BASE_ADDR + USBDEV_RXENABLE_OUT_REG_OFFSET);
    rxen |= (1 << (ep + USBDEV_RXENABLE_OUT_OUT_0_BIT));
    REG32(USBDEV_BASE_ADDR + USBDEV_RXENABLE_OUT_REG_OFFSET) = rxen;
    uint32_t ep_en = REG32(USBDEV_BASE_ADDR + USBDEV_EP_OUT_ENABLE_REG_OFFSET);
    ep_en |= (1 << (ep + USBDEV_EP_OUT_ENABLE_ENABLE_0_BIT));
    REG32(USBDEV_BASE_ADDR + USBDEV_EP_OUT_ENABLE_REG_OFFSET) = ep_en;
  }
}

void usbdev_connect(usbdev_ctx_t *ctx) {
  REG32(USBDEV_BASE_ADDR + USBDEV_USBCTRL_REG_OFFSET) =
      (1 << USBDEV_USBCTRL_ENABLE_BIT);
}

void usbdev_init(usbdev_ctx_t *ctx, bool pinflip, bool diff_rx, bool diff_tx) {
  // setup context
  for (int i = 0; i < NUM_ENDPOINTS; i++) {
    usbdev_endpoint_setup(ctx, i, 0, NULL, NULL, NULL, NULL, NULL);
  }
  ctx->halted = 0;
  ctx->can_wake = 0;
  buf_init(ctx);

  // All about polling...
  REG32(USBDEV_BASE_ADDR + USBDEV_INTR_ENABLE_REG_OFFSET) = 0;

  // Provide buffers for any reception
  fill_av_fifo(ctx);

  REG32(USBDEV_BASE_ADDR + USBDEV_RXENABLE_SETUP_REG_OFFSET) =
      (1 << USBDEV_RXENABLE_SETUP_SETUP_0_BIT);
  REG32(USBDEV_BASE_ADDR + USBDEV_RXENABLE_OUT_REG_OFFSET) =
      (1 << USBDEV_RXENABLE_OUT_OUT_0_BIT);
  REG32(USBDEV_BASE_ADDR + USBDEV_EP_IN_ENABLE_REG_OFFSET) =
      (1 << USBDEV_EP_IN_ENABLE_ENABLE_0_BIT);
  REG32(USBDEV_BASE_ADDR + USBDEV_EP_OUT_ENABLE_REG_OFFSET) =
      (1 << USBDEV_EP_OUT_ENABLE_ENABLE_0_BIT);
  REG32(USBDEV_BASE_ADDR + USBDEV_IN_STALL_REG_OFFSET) = 0;
  REG32(USBDEV_BASE_ADDR + USBDEV_OUT_STALL_REG_OFFSET) = 0;

  uint32_t phy_config =
      (pinflip << USBDEV_PHY_CONFIG_PINFLIP_BIT) |
      (diff_rx << USBDEV_PHY_CONFIG_RX_DIFFERENTIAL_MODE_BIT) |
      (diff_tx << USBDEV_PHY_CONFIG_TX_DIFFERENTIAL_MODE_BIT) |
      (1 << USBDEV_PHY_CONFIG_EOP_SINGLE_BIT_BIT);
  REG32(USBDEV_BASE_ADDR + USBDEV_PHY_CONFIG_REG_OFFSET) = phy_config;
}

void usbdev_force_dx_pullup(line_sel_t line, bool set) {
  // Force usb to pretend it is in suspend
  uint32_t reg_val = REG32(USBDEV_BASE_ADDR + USBDEV_PHY_PINS_DRIVE_REG_OFFSET);
  uint32_t mask;

  mask = line == kDpSel ? USBDEV_PHY_PINS_DRIVE_DP_PULLUP_EN_O_BIT
                        : USBDEV_PHY_PINS_DRIVE_DN_PULLUP_EN_O_BIT;

  if (set) {
    reg_val = SETBIT(reg_val, mask);
  } else {
    reg_val = CLRBIT(reg_val, mask);
  }

  reg_val = SETBIT(reg_val, USBDEV_PHY_PINS_DRIVE_EN_BIT);
  REG32(USBDEV_BASE_ADDR + USBDEV_PHY_PINS_DRIVE_REG_OFFSET) = reg_val;
}

void usbdev_force_suspend() {
  // Force usb to pretend it is in suspend
  REG32(USBDEV_BASE_ADDR + USBDEV_PHY_PINS_DRIVE_REG_OFFSET) |=
      1 << USBDEV_PHY_PINS_DRIVE_SUSPEND_O_BIT |
      1 << USBDEV_PHY_PINS_DRIVE_EN_BIT;
}

void usbdev_wake(bool set) {
  uint32_t reg_val = REG32(USBDEV_BASE_ADDR + USBDEV_WAKE_CONFIG_REG_OFFSET);
  if (set) {
    reg_val = SETBIT(reg_val, USBDEV_WAKE_CONFIG_WAKE_EN_BIT);
  } else {
    reg_val = CLRBIT(reg_val, USBDEV_WAKE_CONFIG_WAKE_EN_BIT);
  }
  REG32(USBDEV_BASE_ADDR + USBDEV_WAKE_CONFIG_REG_OFFSET) = reg_val;
}

// `extern` declarations to give the inline functions in the
// corresponding header a link location.

extern int usbdev_halted(usbdev_ctx_t *ctx, int endpoint);
extern void usbdev_rem_wake_en(usbdev_ctx_t *ctx, int enable);
