mst_fpga.c 5.7 KB
Newer Older
T
ths 已提交
1 2 3 4 5 6 7 8
/*
 * 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.
9 10 11
 *
 * Contributions after 2012-01-13 are licensed under the terms of the
 * GNU GPL, version 2 or (at your option) any later version.
T
ths 已提交
12 13
 */
#include "hw.h"
14
#include "sysbus.h"
T
ths 已提交
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

/* 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

32 33 34 35 36 37
#define MST_PCMCIAx_READY	(1 << 10)
#define MST_PCMCIAx_nCD		(1 << 5)

#define MST_PCMCIA_CD0_IRQ	9
#define MST_PCMCIA_CD1_IRQ	13

T
ths 已提交
38
typedef struct mst_irq_state{
39
	SysBusDevice busdev;
40
	MemoryRegion iomem;
41

42
	qemu_irq parent;
T
ths 已提交
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62

	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_set_irq(void *opaque, int irq, int level)
{
	mst_irq_state *s = (mst_irq_state *)opaque;
63
	uint32_t oldint = s->intsetclr & s->intmskena;
T
ths 已提交
64 65 66 67 68 69

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

70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
	switch(irq) {
	case MST_PCMCIA_CD0_IRQ:
		if (level)
			s->pcmcia0 &= ~MST_PCMCIAx_nCD;
		else
			s->pcmcia0 |=  MST_PCMCIAx_nCD;
		break;
	case MST_PCMCIA_CD1_IRQ:
		if (level)
			s->pcmcia1 &= ~MST_PCMCIAx_nCD;
		else
			s->pcmcia1 |=  MST_PCMCIAx_nCD;
		break;
	}

85 86 87 88 89
	if ((s->intmskena & (1u << irq)) && level)
		s->intsetclr |= 1u << irq;

	if (oldint != (s->intsetclr & s->intmskena))
		qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
T
ths 已提交
90 91 92
}


93 94
static uint64_t
mst_fpga_readb(void *opaque, target_phys_addr_t addr, unsigned size)
T
ths 已提交
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
{
	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 "
125
			"0x" TARGET_FMT_plx "\n", addr);
T
ths 已提交
126 127 128 129 130
	}
	return 0;
}

static void
131 132
mst_fpga_writeb(void *opaque, target_phys_addr_t addr, uint64_t value,
		unsigned size)
T
ths 已提交
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
{
	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;
162
	case MST_INTMSKENA:	/* Mask interrupt */
T
ths 已提交
163
		s->intmskena = (value & 0xFEEFF);
164
		qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
T
ths 已提交
165 166 167
		break;
	case MST_INTSETCLR:	/* clear or set interrupt */
		s->intsetclr = (value & 0xFEEFF);
168
		qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
T
ths 已提交
169
		break;
170
		/* For PCMCIAx allow the to change only power and reset */
T
ths 已提交
171
	case MST_PCMCIA0:
172
		s->pcmcia0 = (value & 0x1f) | (s->pcmcia0 & ~0x1f);
T
ths 已提交
173 174
		break;
	case MST_PCMCIA1:
175
		s->pcmcia1 = (value & 0x1f) | (s->pcmcia1 & ~0x1f);
T
ths 已提交
176 177 178
		break;
	default:
		printf("Mainstone - mst_fpga_writeb: Bad register offset "
179
			"0x" TARGET_FMT_plx "\n", addr);
T
ths 已提交
180 181 182
	}
}

183 184 185 186
static const MemoryRegionOps mst_fpga_ops = {
	.read = mst_fpga_readb,
	.write = mst_fpga_writeb,
	.endianness = DEVICE_NATIVE_ENDIAN,
T
ths 已提交
187 188
};

189
static int mst_fpga_post_load(void *opaque, int version_id)
T
ths 已提交
190 191 192
{
	mst_irq_state *s = (mst_irq_state *) opaque;

193
	qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
T
ths 已提交
194 195 196
	return 0;
}

197
static int mst_fpga_init(SysBusDevice *dev)
T
ths 已提交
198 199 200
{
	mst_irq_state *s;

201
	s = FROM_SYSBUS(mst_irq_state, dev);
T
ths 已提交
202

203 204 205
	s->pcmcia0 = MST_PCMCIAx_READY | MST_PCMCIAx_nCD;
	s->pcmcia1 = MST_PCMCIAx_READY | MST_PCMCIAx_nCD;

206
	sysbus_init_irq(dev, &s->parent);
T
ths 已提交
207 208

	/* alloc the external 16 irqs */
209
	qdev_init_gpio_in(&dev->qdev, mst_fpga_set_irq, MST_NUM_IRQS);
T
ths 已提交
210

211 212
	memory_region_init_io(&s->iomem, &mst_fpga_ops, s,
			    "fpga", 0x00100000);
213
	sysbus_init_mmio(dev, &s->iomem);
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
	return 0;
}

static VMStateDescription vmstate_mst_fpga_regs = {
	.name = "mainstone_fpga",
	.version_id = 0,
	.minimum_version_id = 0,
	.minimum_version_id_old = 0,
	.post_load = mst_fpga_post_load,
	.fields = (VMStateField []) {
		VMSTATE_UINT32(prev_level, mst_irq_state),
		VMSTATE_UINT32(leddat1, mst_irq_state),
		VMSTATE_UINT32(leddat2, mst_irq_state),
		VMSTATE_UINT32(ledctrl, mst_irq_state),
		VMSTATE_UINT32(gpswr, mst_irq_state),
		VMSTATE_UINT32(mscwr1, mst_irq_state),
		VMSTATE_UINT32(mscwr2, mst_irq_state),
		VMSTATE_UINT32(mscwr3, mst_irq_state),
		VMSTATE_UINT32(mscrd, mst_irq_state),
		VMSTATE_UINT32(intmskena, mst_irq_state),
		VMSTATE_UINT32(intsetclr, mst_irq_state),
		VMSTATE_UINT32(pcmcia0, mst_irq_state),
		VMSTATE_UINT32(pcmcia1, mst_irq_state),
		VMSTATE_END_OF_LIST(),
	},
};

static SysBusDeviceInfo mst_fpga_info = {
	.init = mst_fpga_init,
	.qdev.name = "mainstone-fpga",
	.qdev.desc = "Mainstone II FPGA",
	.qdev.size = sizeof(mst_irq_state),
	.qdev.vmsd = &vmstate_mst_fpga_regs,
};

static void mst_fpga_register(void)
{
	sysbus_register_withprop(&mst_fpga_info);
T
ths 已提交
252
}
253
device_init(mst_fpga_register);
新手
引导
客服 返回
顶部