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