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