/* Blackfin Enhanced Parallel Port Interface (EPPI) model
   For "new style" PPIs on BF54x/etc... parts.

   Copyright (C) 2010-2013 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/>.  */

#include "config.h"

#include "sim-main.h"
#include "devices.h"
#include "dv-bfin_eppi.h"
#include "gui.h"

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

struct bfin_eppi
{
  /* 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;

  /* GUI state.  */
  void *gui_state;
  int color;

  /* Order after here is important -- matches hardware MMR layout.  */
  bu16 BFIN_MMR_16(status);
  bu16 BFIN_MMR_16(hcount);
  bu16 BFIN_MMR_16(hdelay);
  bu16 BFIN_MMR_16(vcount);
  bu16 BFIN_MMR_16(vdelay);
  bu16 BFIN_MMR_16(frame);
  bu16 BFIN_MMR_16(line);
  bu16 BFIN_MMR_16(clkdiv);
  bu32 control, fs1w_hbl, fs1p_avpl, fsw2_lvb, fs2p_lavf, clip, err;
};
#define mmr_base()      offsetof(struct bfin_eppi, status)
#define mmr_offset(mmr) (offsetof(struct bfin_eppi, mmr) - mmr_base())

static const char * const mmr_names[] =
{
  "EPPI_STATUS", "EPPI_HCOUNT", "EPPI_HDELAY", "EPPI_VCOUNT", "EPPI_VDELAY",
  "EPPI_FRAME", "EPPI_LINE", "EPPI_CLKDIV", "EPPI_CONTROL", "EPPI_FS1W_HBL",
  "EPPI_FS1P_AVPL", "EPPI_FS2W_LVB", "EPPI_FS2P_LAVF", "EPPI_CLIP", "EPPI_ERR",
};
#define mmr_name(off) (mmr_names[(off) / 4] ? : "<INV>")

static void
bfin_eppi_gui_setup (struct bfin_eppi *eppi)
{
  /* If we are in RX mode, nothing to do.  */
  if (!(eppi->control & PORT_DIR))
    return;

  eppi->gui_state = bfin_gui_setup (eppi->gui_state,
				    eppi->control & PORT_EN,
				    eppi->hcount,
				    eppi->vcount,
				    eppi->color);
}

static unsigned
bfin_eppi_io_write_buffer (struct hw *me, const void *source,
			   int space, address_word addr, unsigned nr_bytes)
{
  struct bfin_eppi *eppi = hw_data (me);
  bu32 mmr_off;
  bu32 value;
  bu16 *value16p;
  bu32 *value32p;
  void *valuep;

  if (nr_bytes == 4)
    value = dv_load_4 (source);
  else
    value = dv_load_2 (source);

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

  HW_TRACE_WRITE ();

  switch (mmr_off)
    {
    case mmr_offset(status):
      dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
      dv_w1c_2 (value16p, value, 0x1ff);
      break;
    case mmr_offset(hcount):
    case mmr_offset(hdelay):
    case mmr_offset(vcount):
    case mmr_offset(vdelay):
    case mmr_offset(frame):
    case mmr_offset(line):
    case mmr_offset(clkdiv):
      dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
      *value16p = value;
      break;
    case mmr_offset(control):
      *value32p = value;
      bfin_eppi_gui_setup (eppi);
      break;
    case mmr_offset(fs1w_hbl):
    case mmr_offset(fs1p_avpl):
    case mmr_offset(fsw2_lvb):
    case mmr_offset(fs2p_lavf):
    case mmr_offset(clip):
    case mmr_offset(err):
      dv_bfin_mmr_require_32 (me, addr, nr_bytes, true);
      *value32p = value;
      break;
    default:
      dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
      break;
    }

  return nr_bytes;
}

static unsigned
bfin_eppi_io_read_buffer (struct hw *me, void *dest,
			  int space, address_word addr, unsigned nr_bytes)
{
  struct bfin_eppi *eppi = hw_data (me);
  bu32 mmr_off;
  bu16 *value16p;
  bu32 *value32p;
  void *valuep;

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

  HW_TRACE_READ ();

  switch (mmr_off)
    {
    case mmr_offset(status):
    case mmr_offset(hcount):
    case mmr_offset(hdelay):
    case mmr_offset(vcount):
    case mmr_offset(vdelay):
    case mmr_offset(frame):
    case mmr_offset(line):
    case mmr_offset(clkdiv):
      dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
      dv_store_2 (dest, *value16p);
      break;
    case mmr_offset(control):
    case mmr_offset(fs1w_hbl):
    case mmr_offset(fs1p_avpl):
    case mmr_offset(fsw2_lvb):
    case mmr_offset(fs2p_lavf):
    case mmr_offset(clip):
    case mmr_offset(err):
      dv_bfin_mmr_require_32 (me, addr, nr_bytes, false);
      dv_store_4 (dest, *value32p);
      break;
    default:
      dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
      break;
    }

  return nr_bytes;
}

static unsigned
bfin_eppi_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_eppi_dma_write_buffer (struct hw *me, const void *source,
			    int space, unsigned_word addr,
			    unsigned nr_bytes,
			    int violate_read_only_section)
{
  struct bfin_eppi *eppi = hw_data (me);

  HW_TRACE_DMA_WRITE ();

  return bfin_gui_update (eppi->gui_state, source, nr_bytes);
}

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

static void
attach_bfin_eppi_regs (struct hw *me, struct bfin_eppi *eppi)
{
  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_EPPI_SIZE)
    hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_EPPI_SIZE);

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

  eppi->base = attach_address;
}

static void
bfin_eppi_finish (struct hw *me)
{
  struct bfin_eppi *eppi;
  const char *color;

  eppi = HW_ZALLOC (me, struct bfin_eppi);

  set_hw_data (me, eppi);
  set_hw_io_read_buffer (me, bfin_eppi_io_read_buffer);
  set_hw_io_write_buffer (me, bfin_eppi_io_write_buffer);
  set_hw_dma_read_buffer (me, bfin_eppi_dma_read_buffer);
  set_hw_dma_write_buffer (me, bfin_eppi_dma_write_buffer);
  set_hw_ports (me, bfin_eppi_ports);

  attach_bfin_eppi_regs (me, eppi);

  /* Initialize the EPPI.  */
  if (hw_find_property (me, "color"))
    color = hw_find_string_property (me, "color");
  else
    color = NULL;
  eppi->color = bfin_gui_color (color);
}

const struct hw_descriptor dv_bfin_eppi_descriptor[] =
{
  {"bfin_eppi", bfin_eppi_finish,},
  {NULL, NULL},
};
