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