xref: /qemu/hw/misc/mst_fpga.c (revision e4ea952f)
1e28bee8eSPaolo Bonzini /*
2e28bee8eSPaolo Bonzini  * PXA270-based Intel Mainstone platforms.
3e28bee8eSPaolo Bonzini  * FPGA driver
4e28bee8eSPaolo Bonzini  *
5e28bee8eSPaolo Bonzini  * Copyright (c) 2007 by Armin Kuster <akuster@kama-aina.net> or
6e28bee8eSPaolo Bonzini  *                                    <akuster@mvista.com>
7e28bee8eSPaolo Bonzini  *
8e28bee8eSPaolo Bonzini  * This code is licensed under the GNU GPL v2.
9e28bee8eSPaolo Bonzini  *
10e28bee8eSPaolo Bonzini  * Contributions after 2012-01-13 are licensed under the terms of the
11e28bee8eSPaolo Bonzini  * GNU GPL, version 2 or (at your option) any later version.
12e28bee8eSPaolo Bonzini  */
130b8fa32fSMarkus Armbruster 
140d1c9782SPeter Maydell #include "qemu/osdep.h"
1564552b6bSMarkus Armbruster #include "hw/irq.h"
16e28bee8eSPaolo Bonzini #include "hw/sysbus.h"
17d6454270SMarkus Armbruster #include "migration/vmstate.h"
180b8fa32fSMarkus Armbruster #include "qemu/module.h"
19db1015e9SEduardo Habkost #include "qom/object.h"
20e28bee8eSPaolo Bonzini 
21e28bee8eSPaolo Bonzini /* Mainstone FPGA for extern irqs */
22e28bee8eSPaolo Bonzini #define FPGA_GPIO_PIN	0
23e28bee8eSPaolo Bonzini #define MST_NUM_IRQS	16
24e28bee8eSPaolo Bonzini #define MST_LEDDAT1		0x10
25e28bee8eSPaolo Bonzini #define MST_LEDDAT2		0x14
26e28bee8eSPaolo Bonzini #define MST_LEDCTRL		0x40
27e28bee8eSPaolo Bonzini #define MST_GPSWR		0x60
28e28bee8eSPaolo Bonzini #define MST_MSCWR1		0x80
29e28bee8eSPaolo Bonzini #define MST_MSCWR2		0x84
30e28bee8eSPaolo Bonzini #define MST_MSCWR3		0x88
31e28bee8eSPaolo Bonzini #define MST_MSCRD		0x90
32e28bee8eSPaolo Bonzini #define MST_INTMSKENA	0xc0
33e28bee8eSPaolo Bonzini #define MST_INTSETCLR	0xd0
34e28bee8eSPaolo Bonzini #define MST_PCMCIA0		0xe0
35e28bee8eSPaolo Bonzini #define MST_PCMCIA1		0xe4
36e28bee8eSPaolo Bonzini 
37e28bee8eSPaolo Bonzini #define MST_PCMCIAx_READY	(1 << 10)
38e28bee8eSPaolo Bonzini #define MST_PCMCIAx_nCD		(1 << 5)
39e28bee8eSPaolo Bonzini 
40e28bee8eSPaolo Bonzini #define MST_PCMCIA_CD0_IRQ	9
41e28bee8eSPaolo Bonzini #define MST_PCMCIA_CD1_IRQ	13
42e28bee8eSPaolo Bonzini 
435c0e12f5SAndreas Färber #define TYPE_MAINSTONE_FPGA "mainstone-fpga"
448063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(mst_irq_state, MAINSTONE_FPGA)
455c0e12f5SAndreas Färber 
46db1015e9SEduardo Habkost struct mst_irq_state {
475c0e12f5SAndreas Färber     SysBusDevice parent_obj;
485c0e12f5SAndreas Färber 
49e28bee8eSPaolo Bonzini     MemoryRegion iomem;
50e28bee8eSPaolo Bonzini 
51e28bee8eSPaolo Bonzini     qemu_irq parent;
52e28bee8eSPaolo Bonzini 
53e28bee8eSPaolo Bonzini     uint32_t prev_level;
54e28bee8eSPaolo Bonzini     uint32_t leddat1;
55e28bee8eSPaolo Bonzini     uint32_t leddat2;
56e28bee8eSPaolo Bonzini     uint32_t ledctrl;
57e28bee8eSPaolo Bonzini     uint32_t gpswr;
58e28bee8eSPaolo Bonzini     uint32_t mscwr1;
59e28bee8eSPaolo Bonzini     uint32_t mscwr2;
60e28bee8eSPaolo Bonzini     uint32_t mscwr3;
61e28bee8eSPaolo Bonzini     uint32_t mscrd;
62e28bee8eSPaolo Bonzini     uint32_t intmskena;
63e28bee8eSPaolo Bonzini     uint32_t intsetclr;
64e28bee8eSPaolo Bonzini     uint32_t pcmcia0;
65e28bee8eSPaolo Bonzini     uint32_t pcmcia1;
66db1015e9SEduardo Habkost };
67e28bee8eSPaolo Bonzini 
68e28bee8eSPaolo Bonzini static void
mst_fpga_set_irq(void * opaque,int irq,int level)69e28bee8eSPaolo Bonzini mst_fpga_set_irq(void *opaque, int irq, int level)
70e28bee8eSPaolo Bonzini {
71e28bee8eSPaolo Bonzini 	mst_irq_state *s = (mst_irq_state *)opaque;
72e28bee8eSPaolo Bonzini 	uint32_t oldint = s->intsetclr & s->intmskena;
73e28bee8eSPaolo Bonzini 
74e28bee8eSPaolo Bonzini 	if (level)
75e28bee8eSPaolo Bonzini 		s->prev_level |= 1u << irq;
76e28bee8eSPaolo Bonzini 	else
77e28bee8eSPaolo Bonzini 		s->prev_level &= ~(1u << irq);
78e28bee8eSPaolo Bonzini 
79e28bee8eSPaolo Bonzini 	switch(irq) {
80e28bee8eSPaolo Bonzini 	case MST_PCMCIA_CD0_IRQ:
81e28bee8eSPaolo Bonzini 		if (level)
82e28bee8eSPaolo Bonzini 			s->pcmcia0 &= ~MST_PCMCIAx_nCD;
83e28bee8eSPaolo Bonzini 		else
84e28bee8eSPaolo Bonzini 			s->pcmcia0 |=  MST_PCMCIAx_nCD;
85e28bee8eSPaolo Bonzini 		break;
86e28bee8eSPaolo Bonzini 	case MST_PCMCIA_CD1_IRQ:
87e28bee8eSPaolo Bonzini 		if (level)
88e28bee8eSPaolo Bonzini 			s->pcmcia1 &= ~MST_PCMCIAx_nCD;
89e28bee8eSPaolo Bonzini 		else
90e28bee8eSPaolo Bonzini 			s->pcmcia1 |=  MST_PCMCIAx_nCD;
91e28bee8eSPaolo Bonzini 		break;
92e28bee8eSPaolo Bonzini 	}
93e28bee8eSPaolo Bonzini 
94e28bee8eSPaolo Bonzini 	if ((s->intmskena & (1u << irq)) && level)
95e28bee8eSPaolo Bonzini 		s->intsetclr |= 1u << irq;
96e28bee8eSPaolo Bonzini 
97e28bee8eSPaolo Bonzini 	if (oldint != (s->intsetclr & s->intmskena))
98e28bee8eSPaolo Bonzini 		qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
99e28bee8eSPaolo Bonzini }
100e28bee8eSPaolo Bonzini 
101e28bee8eSPaolo Bonzini 
102e28bee8eSPaolo Bonzini static uint64_t
mst_fpga_readb(void * opaque,hwaddr addr,unsigned size)103e28bee8eSPaolo Bonzini mst_fpga_readb(void *opaque, hwaddr addr, unsigned size)
104e28bee8eSPaolo Bonzini {
105e28bee8eSPaolo Bonzini 	mst_irq_state *s = (mst_irq_state *) opaque;
106e28bee8eSPaolo Bonzini 
107e28bee8eSPaolo Bonzini 	switch (addr) {
108e28bee8eSPaolo Bonzini 	case MST_LEDDAT1:
109e28bee8eSPaolo Bonzini 		return s->leddat1;
110e28bee8eSPaolo Bonzini 	case MST_LEDDAT2:
111e28bee8eSPaolo Bonzini 		return s->leddat2;
112e28bee8eSPaolo Bonzini 	case MST_LEDCTRL:
113e28bee8eSPaolo Bonzini 		return s->ledctrl;
114e28bee8eSPaolo Bonzini 	case MST_GPSWR:
115e28bee8eSPaolo Bonzini 		return s->gpswr;
116e28bee8eSPaolo Bonzini 	case MST_MSCWR1:
117e28bee8eSPaolo Bonzini 		return s->mscwr1;
118e28bee8eSPaolo Bonzini 	case MST_MSCWR2:
119e28bee8eSPaolo Bonzini 		return s->mscwr2;
120e28bee8eSPaolo Bonzini 	case MST_MSCWR3:
121e28bee8eSPaolo Bonzini 		return s->mscwr3;
122e28bee8eSPaolo Bonzini 	case MST_MSCRD:
123e28bee8eSPaolo Bonzini 		return s->mscrd;
124e28bee8eSPaolo Bonzini 	case MST_INTMSKENA:
125e28bee8eSPaolo Bonzini 		return s->intmskena;
126e28bee8eSPaolo Bonzini 	case MST_INTSETCLR:
127e28bee8eSPaolo Bonzini 		return s->intsetclr;
128e28bee8eSPaolo Bonzini 	case MST_PCMCIA0:
129e28bee8eSPaolo Bonzini 		return s->pcmcia0;
130e28bee8eSPaolo Bonzini 	case MST_PCMCIA1:
131e28bee8eSPaolo Bonzini 		return s->pcmcia1;
132e28bee8eSPaolo Bonzini 	default:
133e28bee8eSPaolo Bonzini 		printf("Mainstone - mst_fpga_readb: Bad register offset "
134883f2c59SPhilippe Mathieu-Daudé 			"0x" HWADDR_FMT_plx "\n", addr);
135e28bee8eSPaolo Bonzini 	}
136e28bee8eSPaolo Bonzini 	return 0;
137e28bee8eSPaolo Bonzini }
138e28bee8eSPaolo Bonzini 
139e28bee8eSPaolo Bonzini static void
mst_fpga_writeb(void * opaque,hwaddr addr,uint64_t value,unsigned size)140e28bee8eSPaolo Bonzini mst_fpga_writeb(void *opaque, hwaddr addr, uint64_t value,
141e28bee8eSPaolo Bonzini 		unsigned size)
142e28bee8eSPaolo Bonzini {
143e28bee8eSPaolo Bonzini 	mst_irq_state *s = (mst_irq_state *) opaque;
144e28bee8eSPaolo Bonzini 	value &= 0xffffffff;
145e28bee8eSPaolo Bonzini 
146e28bee8eSPaolo Bonzini 	switch (addr) {
147e28bee8eSPaolo Bonzini 	case MST_LEDDAT1:
148e28bee8eSPaolo Bonzini 		s->leddat1 = value;
149e28bee8eSPaolo Bonzini 		break;
150e28bee8eSPaolo Bonzini 	case MST_LEDDAT2:
151e28bee8eSPaolo Bonzini 		s->leddat2 = value;
152e28bee8eSPaolo Bonzini 		break;
153e28bee8eSPaolo Bonzini 	case MST_LEDCTRL:
154e28bee8eSPaolo Bonzini 		s->ledctrl = value;
155e28bee8eSPaolo Bonzini 		break;
156e28bee8eSPaolo Bonzini 	case MST_GPSWR:
157e28bee8eSPaolo Bonzini 		s->gpswr = value;
158e28bee8eSPaolo Bonzini 		break;
159e28bee8eSPaolo Bonzini 	case MST_MSCWR1:
160e28bee8eSPaolo Bonzini 		s->mscwr1 = value;
161e28bee8eSPaolo Bonzini 		break;
162e28bee8eSPaolo Bonzini 	case MST_MSCWR2:
163e28bee8eSPaolo Bonzini 		s->mscwr2 = value;
164e28bee8eSPaolo Bonzini 		break;
165e28bee8eSPaolo Bonzini 	case MST_MSCWR3:
166e28bee8eSPaolo Bonzini 		s->mscwr3 = value;
167e28bee8eSPaolo Bonzini 		break;
168e28bee8eSPaolo Bonzini 	case MST_MSCRD:
169e28bee8eSPaolo Bonzini 		s->mscrd =  value;
170e28bee8eSPaolo Bonzini 		break;
171e28bee8eSPaolo Bonzini 	case MST_INTMSKENA:	/* Mask interrupt */
172e28bee8eSPaolo Bonzini 		s->intmskena = (value & 0xFEEFF);
173e28bee8eSPaolo Bonzini 		qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
174e28bee8eSPaolo Bonzini 		break;
175e28bee8eSPaolo Bonzini 	case MST_INTSETCLR:	/* clear or set interrupt */
176e28bee8eSPaolo Bonzini 		s->intsetclr = (value & 0xFEEFF);
177e28bee8eSPaolo Bonzini 		qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
178e28bee8eSPaolo Bonzini 		break;
179e28bee8eSPaolo Bonzini 		/* For PCMCIAx allow the to change only power and reset */
180e28bee8eSPaolo Bonzini 	case MST_PCMCIA0:
181e28bee8eSPaolo Bonzini 		s->pcmcia0 = (value & 0x1f) | (s->pcmcia0 & ~0x1f);
182e28bee8eSPaolo Bonzini 		break;
183e28bee8eSPaolo Bonzini 	case MST_PCMCIA1:
184e28bee8eSPaolo Bonzini 		s->pcmcia1 = (value & 0x1f) | (s->pcmcia1 & ~0x1f);
185e28bee8eSPaolo Bonzini 		break;
186e28bee8eSPaolo Bonzini 	default:
187e28bee8eSPaolo Bonzini 		printf("Mainstone - mst_fpga_writeb: Bad register offset "
188883f2c59SPhilippe Mathieu-Daudé 			"0x" HWADDR_FMT_plx "\n", addr);
189e28bee8eSPaolo Bonzini 	}
190e28bee8eSPaolo Bonzini }
191e28bee8eSPaolo Bonzini 
192e28bee8eSPaolo Bonzini static const MemoryRegionOps mst_fpga_ops = {
193e28bee8eSPaolo Bonzini 	.read = mst_fpga_readb,
194e28bee8eSPaolo Bonzini 	.write = mst_fpga_writeb,
195e28bee8eSPaolo Bonzini 	.endianness = DEVICE_NATIVE_ENDIAN,
196e28bee8eSPaolo Bonzini };
197e28bee8eSPaolo Bonzini 
mst_fpga_post_load(void * opaque,int version_id)198e28bee8eSPaolo Bonzini static int mst_fpga_post_load(void *opaque, int version_id)
199e28bee8eSPaolo Bonzini {
200e28bee8eSPaolo Bonzini 	mst_irq_state *s = (mst_irq_state *) opaque;
201e28bee8eSPaolo Bonzini 
202e28bee8eSPaolo Bonzini 	qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
203e28bee8eSPaolo Bonzini 	return 0;
204e28bee8eSPaolo Bonzini }
205e28bee8eSPaolo Bonzini 
mst_fpga_init(Object * obj)206e2d4f17eSxiaoqiang zhao static void mst_fpga_init(Object *obj)
207e28bee8eSPaolo Bonzini {
208e2d4f17eSxiaoqiang zhao     DeviceState *dev = DEVICE(obj);
209e2d4f17eSxiaoqiang zhao     mst_irq_state *s = MAINSTONE_FPGA(obj);
210e2d4f17eSxiaoqiang zhao     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
211e28bee8eSPaolo Bonzini 
212e28bee8eSPaolo Bonzini     s->pcmcia0 = MST_PCMCIAx_READY | MST_PCMCIAx_nCD;
213e28bee8eSPaolo Bonzini     s->pcmcia1 = MST_PCMCIAx_READY | MST_PCMCIAx_nCD;
214e28bee8eSPaolo Bonzini 
2155c0e12f5SAndreas Färber     sysbus_init_irq(sbd, &s->parent);
216e28bee8eSPaolo Bonzini 
217e28bee8eSPaolo Bonzini     /* alloc the external 16 irqs */
2185c0e12f5SAndreas Färber     qdev_init_gpio_in(dev, mst_fpga_set_irq, MST_NUM_IRQS);
219e28bee8eSPaolo Bonzini 
220e2d4f17eSxiaoqiang zhao     memory_region_init_io(&s->iomem, obj, &mst_fpga_ops, s,
221e28bee8eSPaolo Bonzini                           "fpga", 0x00100000);
2225c0e12f5SAndreas Färber     sysbus_init_mmio(sbd, &s->iomem);
223e28bee8eSPaolo Bonzini }
224e28bee8eSPaolo Bonzini 
225cfa52e09SPhilippe Mathieu-Daudé static const VMStateDescription vmstate_mst_fpga_regs = {
226e28bee8eSPaolo Bonzini     .name = "mainstone_fpga",
227e28bee8eSPaolo Bonzini     .version_id = 0,
228e28bee8eSPaolo Bonzini     .minimum_version_id = 0,
229e28bee8eSPaolo Bonzini     .post_load = mst_fpga_post_load,
230*e4ea952fSRichard Henderson     .fields = (const VMStateField[]) {
231e28bee8eSPaolo Bonzini 		VMSTATE_UINT32(prev_level, mst_irq_state),
232e28bee8eSPaolo Bonzini 		VMSTATE_UINT32(leddat1, mst_irq_state),
233e28bee8eSPaolo Bonzini 		VMSTATE_UINT32(leddat2, mst_irq_state),
234e28bee8eSPaolo Bonzini 		VMSTATE_UINT32(ledctrl, mst_irq_state),
235e28bee8eSPaolo Bonzini 		VMSTATE_UINT32(gpswr, mst_irq_state),
236e28bee8eSPaolo Bonzini 		VMSTATE_UINT32(mscwr1, mst_irq_state),
237e28bee8eSPaolo Bonzini 		VMSTATE_UINT32(mscwr2, mst_irq_state),
238e28bee8eSPaolo Bonzini 		VMSTATE_UINT32(mscwr3, mst_irq_state),
239e28bee8eSPaolo Bonzini 		VMSTATE_UINT32(mscrd, mst_irq_state),
240e28bee8eSPaolo Bonzini 		VMSTATE_UINT32(intmskena, mst_irq_state),
241e28bee8eSPaolo Bonzini 		VMSTATE_UINT32(intsetclr, mst_irq_state),
242e28bee8eSPaolo Bonzini 		VMSTATE_UINT32(pcmcia0, mst_irq_state),
243e28bee8eSPaolo Bonzini 		VMSTATE_UINT32(pcmcia1, mst_irq_state),
244e28bee8eSPaolo Bonzini 		VMSTATE_END_OF_LIST(),
245e28bee8eSPaolo Bonzini 	},
246e28bee8eSPaolo Bonzini };
247e28bee8eSPaolo Bonzini 
mst_fpga_class_init(ObjectClass * klass,void * data)248e28bee8eSPaolo Bonzini static void mst_fpga_class_init(ObjectClass *klass, void *data)
249e28bee8eSPaolo Bonzini {
250e28bee8eSPaolo Bonzini     DeviceClass *dc = DEVICE_CLASS(klass);
251e28bee8eSPaolo Bonzini 
252e28bee8eSPaolo Bonzini     dc->desc = "Mainstone II FPGA";
253e28bee8eSPaolo Bonzini     dc->vmsd = &vmstate_mst_fpga_regs;
254e28bee8eSPaolo Bonzini }
255e28bee8eSPaolo Bonzini 
256e28bee8eSPaolo Bonzini static const TypeInfo mst_fpga_info = {
2575c0e12f5SAndreas Färber     .name          = TYPE_MAINSTONE_FPGA,
258e28bee8eSPaolo Bonzini     .parent        = TYPE_SYS_BUS_DEVICE,
259e28bee8eSPaolo Bonzini     .instance_size = sizeof(mst_irq_state),
260e2d4f17eSxiaoqiang zhao     .instance_init = mst_fpga_init,
261e28bee8eSPaolo Bonzini     .class_init    = mst_fpga_class_init,
262e28bee8eSPaolo Bonzini };
263e28bee8eSPaolo Bonzini 
mst_fpga_register_types(void)264e28bee8eSPaolo Bonzini static void mst_fpga_register_types(void)
265e28bee8eSPaolo Bonzini {
266e28bee8eSPaolo Bonzini     type_register_static(&mst_fpga_info);
267e28bee8eSPaolo Bonzini }
268e28bee8eSPaolo Bonzini 
269e28bee8eSPaolo Bonzini type_init(mst_fpga_register_types)
270