/*
 * Arm PrimeCell PL022 Synchronous Serial Port
 *
 * Copyright (c) 2007 CodeSourcery.
 * Written by Paul Brook
 *
 * This code is licenced under the GPL.
 */

#include "sysbus.h"
#include "ssi.h"
#include "primecell.h"

//#define DEBUG_PL022 1

#ifdef DEBUG_PL022
#define DPRINTF(fmt, ...) \
do { printf("pl022: " fmt , ## __VA_ARGS__); } while (0)
#define BADF(fmt, ...) \
do { fprintf(stderr, "pl022: error: " fmt , ## __VA_ARGS__); exit(1);} while (0)
#else
#define DPRINTF(fmt, ...) do {} while(0)
#define BADF(fmt, ...) \
do { fprintf(stderr, "pl022: error: " fmt , ## __VA_ARGS__);} while (0)
#endif

#define PL022_CR1_LBM 0x01
#define PL022_CR1_SSE 0x02
#define PL022_CR1_MS  0x04
#define PL022_CR1_SDO 0x08

#define PL022_SR_TFE  0x01
#define PL022_SR_TNF  0x02
#define PL022_SR_RNE  0x04
#define PL022_SR_RFF  0x08
#define PL022_SR_BSY  0x10

#define PL022_INT_ROR 0x01
#define PL022_INT_RT  0x04
#define PL022_INT_RX  0x04
#define PL022_INT_TX  0x08

typedef struct {
    SysBusDevice busdev;
    uint32_t cr0;
    uint32_t cr1;
    uint32_t bitmask;
    uint32_t sr;
    uint32_t cpsr;
    uint32_t is;
    uint32_t im;
    /* The FIFO head points to the next empty entry.  */
    int tx_fifo_head;
    int rx_fifo_head;
    int tx_fifo_len;
    int rx_fifo_len;
    uint16_t tx_fifo[8];
    uint16_t rx_fifo[8];
    qemu_irq irq;
    SSIBus *ssi;
} pl022_state;

static const unsigned char pl022_id[8] =
  { 0x22, 0x10, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };

static void pl022_update(pl022_state *s)
{
    s->sr = 0;
    if (s->tx_fifo_len == 0)
        s->sr |= PL022_SR_TFE;
    if (s->tx_fifo_len != 8)
        s->sr |= PL022_SR_TNF;
    if (s->rx_fifo_len != 0)
        s->sr |= PL022_SR_RNE;
    if (s->rx_fifo_len == 8)
        s->sr |= PL022_SR_RFF;
    if (s->tx_fifo_len)
        s->sr |= PL022_SR_BSY;
    s->is = 0;
    if (s->rx_fifo_len >= 4)
        s->is |= PL022_INT_RX;
    if (s->tx_fifo_len <= 4)
        s->is |= PL022_INT_TX;

    qemu_set_irq(s->irq, (s->is & s->im) != 0);
}

static void pl022_xfer(pl022_state *s)
{
    int i;
    int o;
    int val;

    if ((s->cr1 & PL022_CR1_SSE) == 0) {
        pl022_update(s);
        DPRINTF("Disabled\n");
        return;
    }

    DPRINTF("Maybe xfer %d/%d\n", s->tx_fifo_len, s->rx_fifo_len);
    i = (s->tx_fifo_head - s->tx_fifo_len) & 7;
    o = s->rx_fifo_head;
    /* ??? We do not emulate the line speed.
       This may break some applications.  The are two problematic cases:
        (a) A driver feeds data into the TX FIFO until it is full,
         and only then drains the RX FIFO.  On real hardware the CPU can
         feed data fast enough that the RX fifo never gets chance to overflow.
        (b) A driver transmits data, deliberately allowing the RX FIFO to
         overflow because it ignores the RX data anyway.

       We choose to support (a) by stalling the transmit engine if it would
       cause the RX FIFO to overflow.  In practice much transmit-only code
       falls into (a) because it flushes the RX FIFO to determine when
       the transfer has completed.  */
    while (s->tx_fifo_len && s->rx_fifo_len < 8) {
        DPRINTF("xfer\n");
        val = s->tx_fifo[i];
        if (s->cr1 & PL022_CR1_LBM) {
            /* Loopback mode.  */
        } else {
            val = ssi_transfer(s->ssi, val);
        }
        s->rx_fifo[o] = val & s->bitmask;
        i = (i + 1) & 7;
        o = (o + 1) & 7;
        s->tx_fifo_len--;
        s->rx_fifo_len++;
    }
    s->rx_fifo_head = o;
    pl022_update(s);
}

static uint32_t pl022_read(void *opaque, target_phys_addr_t offset)
{
    pl022_state *s = (pl022_state *)opaque;
    int val;

    if (offset >= 0xfe0 && offset < 0x1000) {
        return pl022_id[(offset - 0xfe0) >> 2];
    }
    switch (offset) {
    case 0x00: /* CR0 */
      return s->cr0;
    case 0x04: /* CR1 */
      return s->cr1;
    case 0x08: /* DR */
        if (s->rx_fifo_len) {
            val = s->rx_fifo[(s->rx_fifo_head - s->rx_fifo_len) & 7];
            DPRINTF("RX %02x\n", val);
            s->rx_fifo_len--;
            pl022_xfer(s);
        } else {
            val = 0;
        }
        return val;
    case 0x0c: /* SR */
        return s->sr;
    case 0x10: /* CPSR */
        return s->cpsr;
    case 0x14: /* IMSC */
        return s->im;
    case 0x18: /* RIS */
        return s->is;
    case 0x1c: /* MIS */
        return s->im & s->is;
    case 0x20: /* DMACR */
        /* Not implemented.  */
        return 0;
    default:
        hw_error("pl022_read: Bad offset %x\n", (int)offset);
        return 0;
    }
}

static void pl022_write(void *opaque, target_phys_addr_t offset,
                        uint32_t value)
{
    pl022_state *s = (pl022_state *)opaque;

    switch (offset) {
    case 0x00: /* CR0 */
        s->cr0 = value;
        /* Clock rate and format are ignored.  */
        s->bitmask = (1 << ((value & 15) + 1)) - 1;
        break;
    case 0x04: /* CR1 */
        s->cr1 = value;
        if ((s->cr1 & (PL022_CR1_MS | PL022_CR1_SSE))
                   == (PL022_CR1_MS | PL022_CR1_SSE)) {
            BADF("SPI slave mode not implemented\n");
        }
        pl022_xfer(s);
        break;
    case 0x08: /* DR */
        if (s->tx_fifo_len < 8) {
            DPRINTF("TX %02x\n", value);
            s->tx_fifo[s->tx_fifo_head] = value & s->bitmask;
            s->tx_fifo_head = (s->tx_fifo_head + 1) & 7;
            s->tx_fifo_len++;
            pl022_xfer(s);
        }
        break;
    case 0x10: /* CPSR */
        /* Prescaler.  Ignored.  */
        s->cpsr = value & 0xff;
        break;
    case 0x14: /* IMSC */
        s->im = value;
        pl022_update(s);
        break;
    case 0x20: /* DMACR */
        if (value) {
            hw_error("pl022: DMA not implemented\n");
        }
        break;
    default:
        hw_error("pl022_write: Bad offset %x\n", (int)offset);
    }
}

static void pl022_reset(pl022_state *s)
{
    s->rx_fifo_len = 0;
    s->tx_fifo_len = 0;
    s->im = 0;
    s->is = PL022_INT_TX;
    s->sr = PL022_SR_TFE | PL022_SR_TNF;
}

static CPUReadMemoryFunc *pl022_readfn[] = {
   pl022_read,
   pl022_read,
   pl022_read
};

static CPUWriteMemoryFunc *pl022_writefn[] = {
   pl022_write,
   pl022_write,
   pl022_write
};

static void pl022_save(QEMUFile *f, void *opaque)
{
    pl022_state *s = (pl022_state *)opaque;
    int i;

    qemu_put_be32(f, s->cr0);
    qemu_put_be32(f, s->cr1);
    qemu_put_be32(f, s->bitmask);
    qemu_put_be32(f, s->sr);
    qemu_put_be32(f, s->cpsr);
    qemu_put_be32(f, s->is);
    qemu_put_be32(f, s->im);
    qemu_put_be32(f, s->tx_fifo_head);
    qemu_put_be32(f, s->rx_fifo_head);
    qemu_put_be32(f, s->tx_fifo_len);
    qemu_put_be32(f, s->rx_fifo_len);
    for (i = 0; i < 8; i++) {
        qemu_put_be16(f, s->tx_fifo[i]);
        qemu_put_be16(f, s->rx_fifo[i]);
    }
}

static int pl022_load(QEMUFile *f, void *opaque, int version_id)
{
    pl022_state *s = (pl022_state *)opaque;
    int i;

    if (version_id != 1)
        return -EINVAL;

    s->cr0 = qemu_get_be32(f);
    s->cr1 = qemu_get_be32(f);
    s->bitmask = qemu_get_be32(f);
    s->sr = qemu_get_be32(f);
    s->cpsr = qemu_get_be32(f);
    s->is = qemu_get_be32(f);
    s->im = qemu_get_be32(f);
    s->tx_fifo_head = qemu_get_be32(f);
    s->rx_fifo_head = qemu_get_be32(f);
    s->tx_fifo_len = qemu_get_be32(f);
    s->rx_fifo_len = qemu_get_be32(f);
    for (i = 0; i < 8; i++) {
        s->tx_fifo[i] = qemu_get_be16(f);
        s->rx_fifo[i] = qemu_get_be16(f);
    }

    return 0;
}

static void pl022_init(SysBusDevice *dev)
{
    pl022_state *s = FROM_SYSBUS(pl022_state, dev);
    int iomemtype;

    iomemtype = cpu_register_io_memory(pl022_readfn,
                                       pl022_writefn, s);
    sysbus_init_mmio(dev, 0x1000, iomemtype);
    sysbus_init_irq(dev, &s->irq);
    s->ssi = ssi_create_bus(&dev->qdev, "ssi");
    pl022_reset(s);
    register_savevm("pl022_ssp", -1, 1, pl022_save, pl022_load, s);
}

static void pl022_register_devices(void)
{
    sysbus_register_dev("pl022", sizeof(pl022_state), pl022_init);
}

device_init(pl022_register_devices)
