/* Blackfin Serial Peripheral Interface (SPI) model

   Copyright (C) 2010-2021 Free Software Foundation, Inc.
   Contributed by Analog Devices, Inc.

   This file is part of simulators.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

/* This must come before any other includes.  */
#include "defs.h"

#include "sim-main.h"
#include "devices.h"
#include "dv-bfin_spi.h"

/* XXX: This is merely a stub.  */

struct bfin_spi
{
  /* This top portion matches common dv_bfin struct.  */
  bu32 base;
  struct hw *dma_master;
  bool acked;

  struct hw_event *handler;
  char saved_byte;
  int saved_count;

  /* Order after here is important -- matches hardware MMR layout.  */
  bu16 BFIN_MMR_16(ctl);
  bu16 BFIN_MMR_16(flg);
  bu16 BFIN_MMR_16(stat);
  bu16 BFIN_MMR_16(tdbr);
  bu16 BFIN_MMR_16(rdbr);
  bu16 BFIN_MMR_16(baud);
  bu16 BFIN_MMR_16(shadow);
};
#define mmr_base()      offsetof(struct bfin_spi, ctl)
#define mmr_offset(mmr) (offsetof(struct bfin_spi, mmr) - mmr_base())

static const char * const mmr_names[] =
{
  "SPI_CTL", "SPI_FLG", "SPI_STAT", "SPI_TDBR",
  "SPI_RDBR", "SPI_BAUD", "SPI_SHADOW",
};
#define mmr_name(off) mmr_names[(off) / 4]

static bool
bfin_spi_enabled (struct bfin_spi *spi)
{
  return (spi->ctl & SPE);
}

static bu16
bfin_spi_timod (struct bfin_spi *spi)
{
  return (spi->ctl & TIMOD);
}

static unsigned
bfin_spi_io_write_buffer (struct hw *me, const void *source, int space,
			  address_word addr, unsigned nr_bytes)
{
  struct bfin_spi *spi = hw_data (me);
  bu32 mmr_off;
  bu32 value;
  bu16 *valuep;

  /* Invalid access mode is higher priority than missing register.  */
  if (!dv_bfin_mmr_require_16 (me, addr, nr_bytes, true))
    return 0;

  value = dv_load_2 (source);
  mmr_off = addr - spi->base;
  valuep = (void *)((unsigned long)spi + mmr_base() + mmr_off);

  HW_TRACE_WRITE ();

  switch (mmr_off)
    {
    case mmr_offset(stat):
      dv_w1c_2 (valuep, value, ~(SPIF | TXS | RXS));
      break;
    case mmr_offset(tdbr):
      *valuep = value;
      if (bfin_spi_enabled (spi) && bfin_spi_timod (spi) == TDBR_CORE)
	{
	  spi->stat |= RXS;
	  spi->stat &= ~TXS;
	}
      break;
    case mmr_offset(rdbr):
    case mmr_offset(ctl):
    case mmr_offset(flg):
    case mmr_offset(baud):
    case mmr_offset(shadow):
      *valuep = value;
      break;
    default:
      dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
      return 0;
    }

  return nr_bytes;
}

static unsigned
bfin_spi_io_read_buffer (struct hw *me, void *dest, int space,
			 address_word addr, unsigned nr_bytes)
{
  struct bfin_spi *spi = hw_data (me);
  bu32 mmr_off;
  bu16 *valuep;

  /* Invalid access mode is higher priority than missing register.  */
  if (!dv_bfin_mmr_require_16 (me, addr, nr_bytes, false))
    return 0;

  mmr_off = addr - spi->base;
  valuep = (void *)((unsigned long)spi + mmr_base() + mmr_off);

  HW_TRACE_READ ();

  switch (mmr_off)
    {
    case mmr_offset(rdbr):
      dv_store_2 (dest, *valuep);
      if (bfin_spi_enabled (spi) && bfin_spi_timod (spi) == RDBR_CORE)
	spi->stat &= ~(RXS | TXS);
      break;
    case mmr_offset(ctl):
    case mmr_offset(stat):
    case mmr_offset(flg):
    case mmr_offset(tdbr):
    case mmr_offset(baud):
    case mmr_offset(shadow):
      dv_store_2 (dest, *valuep);
      break;
    default:
      dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
      return 0;
    }

  return nr_bytes;
}

static unsigned
bfin_spi_dma_read_buffer (struct hw *me, void *dest, int space,
			  unsigned_word addr, unsigned nr_bytes)
{
  HW_TRACE_DMA_READ ();
  return 0;
}

static unsigned
bfin_spi_dma_write_buffer (struct hw *me, const void *source,
			   int space, unsigned_word addr,
			   unsigned nr_bytes,
			   int violate_read_only_section)
{
  HW_TRACE_DMA_WRITE ();
  return 0;
}

static const struct hw_port_descriptor bfin_spi_ports[] =
{
  { "stat", 0, 0, output_port, },
  { NULL, 0, 0, 0, },
};

static void
attach_bfin_spi_regs (struct hw *me, struct bfin_spi *spi)
{
  address_word attach_address;
  int attach_space;
  unsigned attach_size;
  reg_property_spec reg;

  if (hw_find_property (me, "reg") == NULL)
    hw_abort (me, "Missing \"reg\" property");

  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
    hw_abort (me, "\"reg\" property must contain three addr/size entries");

  hw_unit_address_to_attach_address (hw_parent (me),
				     &reg.address,
				     &attach_space, &attach_address, me);
  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);

  if (attach_size != BFIN_MMR_SPI_SIZE)
    hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_SPI_SIZE);

  hw_attach_address (hw_parent (me),
		     0, attach_space, attach_address, attach_size, me);

  spi->base = attach_address;
}

static void
bfin_spi_finish (struct hw *me)
{
  struct bfin_spi *spi;

  spi = HW_ZALLOC (me, struct bfin_spi);

  set_hw_data (me, spi);
  set_hw_io_read_buffer (me, bfin_spi_io_read_buffer);
  set_hw_io_write_buffer (me, bfin_spi_io_write_buffer);
  set_hw_dma_read_buffer (me, bfin_spi_dma_read_buffer);
  set_hw_dma_write_buffer (me, bfin_spi_dma_write_buffer);
  set_hw_ports (me, bfin_spi_ports);

  attach_bfin_spi_regs (me, spi);

  /* Initialize the SPI.  */
  spi->ctl  = 0x0400;
  spi->flg  = 0xFF00;
  spi->stat = 0x0001;
}

const struct hw_descriptor dv_bfin_spi_descriptor[] =
{
  {"bfin_spi", bfin_spi_finish,},
  {NULL, NULL},
};
