/*
 * Arm PrimeCell PL061 General Purpose IO with additional
 * Luminary Micro Stellaris bits.
 *
 * Copyright (c) 2007 CodeSourcery.
 * Written by Paul Brook
 *
 * This code is licenced under the GPL.
 */

#include "hw.h"
#include "primecell.h"

//#define DEBUG_PL061 1

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

static const uint8_t pl061_id[12] =
  { 0x00, 0x00, 0x00, 0x00, 0x61, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 };

typedef struct {
    int locked;
    uint8_t data;
    uint8_t old_data;
    uint8_t dir;
    uint8_t isense;
    uint8_t ibe;
    uint8_t iev;
    uint8_t im;
    uint8_t istate;
    uint8_t afsel;
    uint8_t dr2r;
    uint8_t dr4r;
    uint8_t dr8r;
    uint8_t odr;
    uint8_t pur;
    uint8_t pdr;
    uint8_t slr;
    uint8_t den;
    uint8_t cr;
    uint8_t float_high;
    qemu_irq irq;
    qemu_irq out[8];
} pl061_state;

static void pl061_update(pl061_state *s)
{
    uint8_t changed;
    uint8_t mask;
    uint8_t out;
    int i;

    /* Outputs float high.  */
    /* FIXME: This is board dependent.  */
    out = (s->data & s->dir) | ~s->dir;
    changed = s->old_data ^ out;
    if (!changed)
        return;

    s->old_data = out;
    for (i = 0; i < 8; i++) {
        mask = 1 << i;
        if ((changed & mask) && s->out) {
            DPRINTF("Set output %d = %d\n", i, (out & mask) != 0);
            qemu_set_irq(s->out[i], (out & mask) != 0);
        }
    }

    /* FIXME: Implement input interrupts.  */
}

static uint32_t pl061_read(void *opaque, target_phys_addr_t offset)
{
    pl061_state *s = (pl061_state *)opaque;

    if (offset >= 0xfd0 && offset < 0x1000) {
        return pl061_id[(offset - 0xfd0) >> 2];
    }
    if (offset < 0x400) {
        return s->data & (offset >> 2);
    }
    switch (offset) {
    case 0x400: /* Direction */
        return s->dir;
    case 0x404: /* Interrupt sense */
        return s->isense;
    case 0x408: /* Interrupt both edges */
        return s->ibe;
    case 0x40c: /* Interupt event */
        return s->iev;
    case 0x410: /* Interrupt mask */
        return s->im;
    case 0x414: /* Raw interrupt status */
        return s->istate;
    case 0x418: /* Masked interrupt status */
        return s->istate | s->im;
    case 0x420: /* Alternate function select */
        return s->afsel;
    case 0x500: /* 2mA drive */
        return s->dr2r;
    case 0x504: /* 4mA drive */
        return s->dr4r;
    case 0x508: /* 8mA drive */
        return s->dr8r;
    case 0x50c: /* Open drain */
        return s->odr;
    case 0x510: /* Pull-up */
        return s->pur;
    case 0x514: /* Pull-down */
        return s->pdr;
    case 0x518: /* Slew rate control */
        return s->slr;
    case 0x51c: /* Digital enable */
        return s->den;
    case 0x520: /* Lock */
        return s->locked;
    case 0x524: /* Commit */
        return s->cr;
    default:
        hw_error("pl061_read: Bad offset %x\n", (int)offset);
        return 0;
    }
}

static void pl061_write(void *opaque, target_phys_addr_t offset,
                        uint32_t value)
{
    pl061_state *s = (pl061_state *)opaque;
    uint8_t mask;

    if (offset < 0x400) {
        mask = (offset >> 2) & s->dir;
        s->data = (s->data & ~mask) | (value & mask);
        pl061_update(s);
        return;
    }
    switch (offset) {
    case 0x400: /* Direction */
        s->dir = value;
        break;
    case 0x404: /* Interrupt sense */
        s->isense = value;
        break;
    case 0x408: /* Interrupt both edges */
        s->ibe = value;
        break;
    case 0x40c: /* Interupt event */
        s->iev = value;
        break;
    case 0x410: /* Interrupt mask */
        s->im = value;
        break;
    case 0x41c: /* Interrupt clear */
        s->istate &= ~value;
        break;
    case 0x420: /* Alternate function select */
        mask = s->cr;
        s->afsel = (s->afsel & ~mask) | (value & mask);
        break;
    case 0x500: /* 2mA drive */
        s->dr2r = value;
        break;
    case 0x504: /* 4mA drive */
        s->dr4r = value;
        break;
    case 0x508: /* 8mA drive */
        s->dr8r = value;
        break;
    case 0x50c: /* Open drain */
        s->odr = value;
        break;
    case 0x510: /* Pull-up */
        s->pur = value;
        break;
    case 0x514: /* Pull-down */
        s->pdr = value;
        break;
    case 0x518: /* Slew rate control */
        s->slr = value;
        break;
    case 0x51c: /* Digital enable */
        s->den = value;
        break;
    case 0x520: /* Lock */
        s->locked = (value != 0xacce551);
        break;
    case 0x524: /* Commit */
        if (!s->locked)
            s->cr = value;
        break;
    default:
        hw_error("pl061_write: Bad offset %x\n", (int)offset);
    }
    pl061_update(s);
}

static void pl061_reset(pl061_state *s)
{
  s->locked = 1;
  s->cr = 0xff;
}

static void pl061_set_irq(void * opaque, int irq, int level)
{
    pl061_state *s = (pl061_state *)opaque;
    uint8_t mask;

    mask = 1 << irq;
    if ((s->dir & mask) == 0) {
        s->data &= ~mask;
        if (level)
            s->data |= mask;
        pl061_update(s);
    }
}

static CPUReadMemoryFunc *pl061_readfn[] = {
   pl061_read,
   pl061_read,
   pl061_read
};

static CPUWriteMemoryFunc *pl061_writefn[] = {
   pl061_write,
   pl061_write,
   pl061_write
};

static void pl061_save(QEMUFile *f, void *opaque)
{
    pl061_state *s = (pl061_state *)opaque;

    qemu_put_be32(f, s->locked);
    qemu_put_be32(f, s->data);
    qemu_put_be32(f, s->old_data);
    qemu_put_be32(f, s->dir);
    qemu_put_be32(f, s->isense);
    qemu_put_be32(f, s->ibe);
    qemu_put_be32(f, s->iev);
    qemu_put_be32(f, s->im);
    qemu_put_be32(f, s->istate);
    qemu_put_be32(f, s->afsel);
    qemu_put_be32(f, s->dr2r);
    qemu_put_be32(f, s->dr4r);
    qemu_put_be32(f, s->dr8r);
    qemu_put_be32(f, s->odr);
    qemu_put_be32(f, s->pur);
    qemu_put_be32(f, s->pdr);
    qemu_put_be32(f, s->slr);
    qemu_put_be32(f, s->den);
    qemu_put_be32(f, s->cr);
    qemu_put_be32(f, s->float_high);
}

static int pl061_load(QEMUFile *f, void *opaque, int version_id)
{
    pl061_state *s = (pl061_state *)opaque;
    if (version_id != 1)
        return -EINVAL;

    s->locked = qemu_get_be32(f);
    s->data = qemu_get_be32(f);
    s->old_data = qemu_get_be32(f);
    s->dir = qemu_get_be32(f);
    s->isense = qemu_get_be32(f);
    s->ibe = qemu_get_be32(f);
    s->iev = qemu_get_be32(f);
    s->im = qemu_get_be32(f);
    s->istate = qemu_get_be32(f);
    s->afsel = qemu_get_be32(f);
    s->dr2r = qemu_get_be32(f);
    s->dr4r = qemu_get_be32(f);
    s->dr8r = qemu_get_be32(f);
    s->odr = qemu_get_be32(f);
    s->pur = qemu_get_be32(f);
    s->pdr = qemu_get_be32(f);
    s->slr = qemu_get_be32(f);
    s->den = qemu_get_be32(f);
    s->cr = qemu_get_be32(f);
    s->float_high = qemu_get_be32(f);

    return 0;
}

/* Returns an array of inputs.  */
qemu_irq *pl061_init(uint32_t base, qemu_irq irq, qemu_irq **out)
{
    int iomemtype;
    pl061_state *s;

    s = (pl061_state *)qemu_mallocz(sizeof(pl061_state));
    iomemtype = cpu_register_io_memory(0, pl061_readfn,
                                       pl061_writefn, s);
    cpu_register_physical_memory(base, 0x00001000, iomemtype);
    s->irq = irq;
    pl061_reset(s);
    if (out)
        *out = s->out;

    register_savevm("pl061_gpio", -1, 1, pl061_save, pl061_load, s);
    return qemu_allocate_irqs(pl061_set_irq, s, 8);
}
