/*
 * PXA270-based Intel Mainstone platforms.
 * FPGA driver
 *
 * Copyright (c) 2007 by Armin Kuster <akuster@kama-aina.net> or
 *                                    <akuster@mvista.com>
 *
 * This code is licensed under the GNU GPL v2.
 */
#include "hw.h"
#include "pxa.h"
#include "mainstone.h"

/* Mainstone FPGA for extern irqs */
#define FPGA_GPIO_PIN	0
#define MST_NUM_IRQS	16
#define MST_LEDDAT1		0x10
#define MST_LEDDAT2		0x14
#define MST_LEDCTRL		0x40
#define MST_GPSWR		0x60
#define MST_MSCWR1		0x80
#define MST_MSCWR2		0x84
#define MST_MSCWR3		0x88
#define MST_MSCRD		0x90
#define MST_INTMSKENA	0xc0
#define MST_INTSETCLR	0xd0
#define MST_PCMCIA0		0xe0
#define MST_PCMCIA1		0xe4

typedef struct mst_irq_state{
	qemu_irq *parent;
	qemu_irq *pins;

	uint32_t prev_level;
	uint32_t leddat1;
	uint32_t leddat2;
	uint32_t ledctrl;
	uint32_t gpswr;
	uint32_t mscwr1;
	uint32_t mscwr2;
	uint32_t mscwr3;
	uint32_t mscrd;
	uint32_t intmskena;
	uint32_t intsetclr;
	uint32_t pcmcia0;
	uint32_t pcmcia1;
}mst_irq_state;

static void
mst_fpga_update_gpio(mst_irq_state *s)
{
	uint32_t level, diff;
	int bit;
	level = s->prev_level ^ s->intsetclr;

	for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) {
		bit = ffs(diff) - 1;
		qemu_set_irq(s->pins[bit], (level >> bit) & 1 );
	}
	s->prev_level = level;
}

static void
mst_fpga_set_irq(void *opaque, int irq, int level)
{
	mst_irq_state *s = (mst_irq_state *)opaque;

	if (level)
		s->prev_level |= 1u << irq;
	else
		s->prev_level &= ~(1u << irq);

	if(s->intmskena & (1u << irq)) {
		s->intsetclr = 1u << irq;
		qemu_set_irq(s->parent[0], level);
	}
}


static uint32_t
mst_fpga_readb(void *opaque, target_phys_addr_t addr)
{
	mst_irq_state *s = (mst_irq_state *) opaque;

	switch (addr) {
	case MST_LEDDAT1:
		return s->leddat1;
	case MST_LEDDAT2:
		return s->leddat2;
	case MST_LEDCTRL:
		return s->ledctrl;
	case MST_GPSWR:
		return s->gpswr;
	case MST_MSCWR1:
		return s->mscwr1;
	case MST_MSCWR2:
		return s->mscwr2;
	case MST_MSCWR3:
		return s->mscwr3;
	case MST_MSCRD:
		return s->mscrd;
	case MST_INTMSKENA:
		return s->intmskena;
	case MST_INTSETCLR:
		return s->intsetclr;
	case MST_PCMCIA0:
		return s->pcmcia0;
	case MST_PCMCIA1:
		return s->pcmcia1;
	default:
		printf("Mainstone - mst_fpga_readb: Bad register offset "
			REG_FMT " \n", addr);
	}
	return 0;
}

static void
mst_fpga_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
{
	mst_irq_state *s = (mst_irq_state *) opaque;
	value &= 0xffffffff;

	switch (addr) {
	case MST_LEDDAT1:
		s->leddat1 = value;
		break;
	case MST_LEDDAT2:
		s->leddat2 = value;
		break;
	case MST_LEDCTRL:
		s->ledctrl = value;
		break;
	case MST_GPSWR:
		s->gpswr = value;
		break;
	case MST_MSCWR1:
		s->mscwr1 = value;
		break;
	case MST_MSCWR2:
		s->mscwr2 = value;
		break;
	case MST_MSCWR3:
		s->mscwr3 = value;
		break;
	case MST_MSCRD:
		s->mscrd =  value;
		break;
	case MST_INTMSKENA:	/* Mask interupt */
		s->intmskena = (value & 0xFEEFF);
		mst_fpga_update_gpio(s);
		break;
	case MST_INTSETCLR:	/* clear or set interrupt */
		s->intsetclr = (value & 0xFEEFF);
		break;
	case MST_PCMCIA0:
		s->pcmcia0 = value;
		break;
	case MST_PCMCIA1:
		s->pcmcia1 = value;
		break;
	default:
		printf("Mainstone - mst_fpga_writeb: Bad register offset "
			REG_FMT " \n", addr);
	}
}

static CPUReadMemoryFunc *mst_fpga_readfn[] = {
	mst_fpga_readb,
	mst_fpga_readb,
	mst_fpga_readb,
};
static CPUWriteMemoryFunc *mst_fpga_writefn[] = {
	mst_fpga_writeb,
	mst_fpga_writeb,
	mst_fpga_writeb,
};

static void
mst_fpga_save(QEMUFile *f, void *opaque)
{
	struct mst_irq_state *s = (mst_irq_state *) opaque;

	qemu_put_be32s(f, &s->prev_level);
	qemu_put_be32s(f, &s->leddat1);
	qemu_put_be32s(f, &s->leddat2);
	qemu_put_be32s(f, &s->ledctrl);
	qemu_put_be32s(f, &s->gpswr);
	qemu_put_be32s(f, &s->mscwr1);
	qemu_put_be32s(f, &s->mscwr2);
	qemu_put_be32s(f, &s->mscwr3);
	qemu_put_be32s(f, &s->mscrd);
	qemu_put_be32s(f, &s->intmskena);
	qemu_put_be32s(f, &s->intsetclr);
	qemu_put_be32s(f, &s->pcmcia0);
	qemu_put_be32s(f, &s->pcmcia1);
}

static int
mst_fpga_load(QEMUFile *f, void *opaque, int version_id)
{
	mst_irq_state *s = (mst_irq_state *) opaque;

	qemu_get_be32s(f, &s->prev_level);
	qemu_get_be32s(f, &s->leddat1);
	qemu_get_be32s(f, &s->leddat2);
	qemu_get_be32s(f, &s->ledctrl);
	qemu_get_be32s(f, &s->gpswr);
	qemu_get_be32s(f, &s->mscwr1);
	qemu_get_be32s(f, &s->mscwr2);
	qemu_get_be32s(f, &s->mscwr3);
	qemu_get_be32s(f, &s->mscrd);
	qemu_get_be32s(f, &s->intmskena);
	qemu_get_be32s(f, &s->intsetclr);
	qemu_get_be32s(f, &s->pcmcia0);
	qemu_get_be32s(f, &s->pcmcia1);
	return 0;
}

qemu_irq *mst_irq_init(struct pxa2xx_state_s *cpu, uint32_t base, int irq)
{
	mst_irq_state *s;
	int iomemtype;
	qemu_irq *qi;

	s = (mst_irq_state  *)
		qemu_mallocz(sizeof(mst_irq_state));

	s->parent = &cpu->pic[irq];

	/* alloc the external 16 irqs */
	qi  = qemu_allocate_irqs(mst_fpga_set_irq, s, MST_NUM_IRQS);
	s->pins = qi;

	iomemtype = cpu_register_io_memory(0, mst_fpga_readfn,
		mst_fpga_writefn, s);
	cpu_register_physical_memory(base, 0x00100000, iomemtype);
	register_savevm("mainstone_fpga", 0, 0, mst_fpga_save, mst_fpga_load, s);
	return qi;
}
