qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

mst_fpga.c (6391B)


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