/*
 * Copyright 2023 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

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

#include "hw/ip/spi_host/data/spi_host_regs.h"  // Generated.
#include "sw/device/lib/spi_display/DEV_Config.h"
#include "sw/device/lib/spi_display/LCD_Driver.h"
#include "sw/device/lib/util.h"

dif_result_t spi_display_init(spi_display_t* spi_display,
                              dif_spi_host_t* spi_host,
                              dif_tlul_mailbox_t* mailbox) {
  spi_display->spi_host = spi_host;
  spi_display->mailbox = mailbox;
  spi_display->gpio_write_done = false;
  spi_display->spi_idle_seen = false;

  // Set the SPI_EVENT interrupt, and enable the idle event.
  uint32_t intr_enable =
      mmio_region_read32(spi_host->base_addr, SPI_HOST_INTR_ENABLE_REG_OFFSET);
  intr_enable =
      bitfield_bit32_write(intr_enable, SPI_HOST_INTR_ENABLE_SPI_EVENT_BIT, 1);
  mmio_region_write32(spi_host->base_addr, SPI_HOST_INTR_ENABLE_REG_OFFSET,
                      intr_enable);

  uint32_t event_enable =
      mmio_region_read32(spi_host->base_addr, SPI_HOST_EVENT_ENABLE_REG_OFFSET);
  event_enable =
      bitfield_bit32_write(event_enable, SPI_HOST_EVENT_ENABLE_IDLE_BIT, 1);
  mmio_region_write32(spi_host->base_addr, SPI_HOST_EVENT_ENABLE_REG_OFFSET,
                      event_enable);

  // TODO(atv): Dependency inject our SPI functions?
  LCD_Init(spi_display);

  return kDifOk;
}

dif_result_t spi_display_irq_init(spi_display_t* spi_display,
                                  const dif_rv_plic_t* plic,
                                  dif_rv_plic_irq_id_t irq_id,
                                  dif_rv_plic_target_t target) {
  CHECK_DIF_OK(
      dif_rv_plic_irq_set_enabled(plic, irq_id, target, kDifToggleEnabled));
  CHECK_DIF_OK(
      dif_rv_plic_irq_set_priority(plic, irq_id, kDifRvPlicMaxPriority));
  return kDifOk;
}

dif_result_t spi_display_spi_irq_handler(spi_display_t* spi_display) {
  mmio_region_write32(spi_display->spi_host->base_addr,
                      SPI_HOST_INTR_STATE_REG_OFFSET,
                      mmio_region_read32(spi_display->spi_host->base_addr,
                                         SPI_HOST_INTR_STATE_REG_OFFSET));
  spi_display->spi_idle_seen = true;
  return kDifOk;
}

dif_result_t spi_display_smc_mailbox_irq_handler(spi_display_t* spi_display) {
  uint32_t message;
  CHECK_DIF_OK(dif_tlul_mailbox_irq_acknowledge(spi_display->mailbox,
                                                kDifTlulMailboxIrqRtirq));
  CHECK_DIF_OK(dif_tlul_mailbox_read_message(spi_display->mailbox, &message));
  spi_display->gpio_write_done = true;
  return kDifOk;
}

void spi_display_byte_write(spi_display_t* spi_display, uint8_t value) {
  dif_spi_host_segment_t transaction[] = {
      {
          .type = kDifSpiHostSegmentTypeTx,
          .tx =
              {
                  .width = kDifSpiHostWidthStandard,
                  .buf = &value,
                  .length = sizeof(value),
              },
      },
  };
  CHECK_DIF_OK(dif_spi_host_transaction(spi_display->spi_host, /*csid=*/0,
                                        transaction, ARRAYSIZE(transaction)));
}

void spi_display_block_write(spi_display_t* spi_display, const uint8_t* buffer,
                             size_t bytes) {
  dif_spi_host_segment_t transaction[] = {
      {
          .type = kDifSpiHostSegmentTypeTx,
          .tx =
              {
                  .width = kDifSpiHostWidthStandard,
                  .buf = 0,
                  .length = 0,
              },
      },
  };
  size_t remaining = bytes;
  size_t offset = 0;
  while (remaining) {
    size_t tx_len = MIN(256, remaining);
    transaction[0].tx.length = tx_len;
    transaction[0].tx.buf = buffer + offset;
    spi_display->spi_idle_seen = false;
    CHECK_DIF_OK(dif_spi_host_transaction(spi_display->spi_host, 0, transaction,
                                          ARRAYSIZE(transaction)));
    while (!spi_display->spi_idle_seen) {
      asm volatile("wfi");
    }
    spi_display->spi_idle_seen = false;
    offset += tx_len;
    remaining -= tx_len;
  }
}

void spi_display_gpio_write(spi_display_t* spi_display, UWORD pin,
                            UBYTE value) {
  // Don't worry about it since the hardware controls it.
  if (pin == DEV_CS_PIN) {
    return;
  }

  uint32_t msg = ((pin & 0xFFFF) << 16) | (value & 0xFFFF);
  spi_display->gpio_write_done = false;
  CHECK_DIF_OK(dif_tlul_mailbox_send_message(spi_display->mailbox, &msg));
  while (!spi_display->gpio_write_done) {
    asm volatile("wfi");
  }
  spi_display->gpio_write_done = false;
}

// Implementations needed for LCD_Driver.cpp

void DEV_Delay_ms(void* ctx, UWORD value) {
  spi_display_t* spi_display = (spi_display_t*)ctx;
  busy_spin_micros(value * 1000);
}

void DEV_SPI_BLOCK_WRITE(void* ctx, const uint8_t* buffer, size_t bytes) {
  spi_display_t* spi_display = (spi_display_t*)ctx;
  spi_display_block_write(ctx, buffer, bytes);
}

void DEV_SPI_WRITE(void* ctx, UBYTE value) {
  spi_display_t* spi_display = (spi_display_t*)ctx;
  spi_display_byte_write(ctx, value);
}

void DEV_Digital_Write(void* ctx, UWORD pin, UBYTE value) {
  spi_display_t* spi_display = (spi_display_t*)ctx;
  spi_display_gpio_write(ctx, pin, value);
}
