|
|
1.1 root 1: /*
2: * PXA270-based Intel Mainstone platforms.
3: * FPGA driver
4: *
5: * Copyright (c) 2007 by Armin Kuster <[email protected]> or
6: * <[email protected]>
7: *
8: * This code is licensed under the GNU GPL v2.
1.1.1.9 ! root 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.
1.1 root 12: */
13: #include "hw.h"
1.1.1.7 root 14: #include "sysbus.h"
1.1 root 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:
1.1.1.7 root 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:
1.1 root 38: typedef struct mst_irq_state{
1.1.1.7 root 39: SysBusDevice busdev;
1.1.1.9 ! root 40: MemoryRegion iomem;
1.1.1.7 root 41:
42: qemu_irq parent;
1.1 root 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;
1.1.1.7 root 63: uint32_t oldint = s->intsetclr & s->intmskena;
1.1 root 64:
65: if (level)
66: s->prev_level |= 1u << irq;
67: else
68: s->prev_level &= ~(1u << irq);
69:
1.1.1.7 root 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;
1.1 root 83: }
1.1.1.7 root 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);
1.1 root 90: }
91:
92:
1.1.1.9 ! root 93: static uint64_t
! 94: mst_fpga_readb(void *opaque, target_phys_addr_t addr, unsigned size)
1.1 root 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 "
1.1.1.8 root 125: "0x" TARGET_FMT_plx "\n", addr);
1.1 root 126: }
127: return 0;
128: }
129:
130: static void
1.1.1.9 ! root 131: mst_fpga_writeb(void *opaque, target_phys_addr_t addr, uint64_t value,
! 132: unsigned size)
1.1 root 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;
1.1.1.7 root 162: case MST_INTMSKENA: /* Mask interrupt */
1.1 root 163: s->intmskena = (value & 0xFEEFF);
1.1.1.7 root 164: qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
1.1 root 165: break;
166: case MST_INTSETCLR: /* clear or set interrupt */
167: s->intsetclr = (value & 0xFEEFF);
1.1.1.7 root 168: qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
1.1 root 169: break;
1.1.1.7 root 170: /* For PCMCIAx allow the to change only power and reset */
1.1 root 171: case MST_PCMCIA0:
1.1.1.7 root 172: s->pcmcia0 = (value & 0x1f) | (s->pcmcia0 & ~0x1f);
1.1 root 173: break;
174: case MST_PCMCIA1:
1.1.1.7 root 175: s->pcmcia1 = (value & 0x1f) | (s->pcmcia1 & ~0x1f);
1.1 root 176: break;
177: default:
178: printf("Mainstone - mst_fpga_writeb: Bad register offset "
1.1.1.8 root 179: "0x" TARGET_FMT_plx "\n", addr);
1.1 root 180: }
181: }
182:
1.1.1.9 ! root 183: static const MemoryRegionOps mst_fpga_ops = {
! 184: .read = mst_fpga_readb,
! 185: .write = mst_fpga_writeb,
! 186: .endianness = DEVICE_NATIVE_ENDIAN,
1.1 root 187: };
188:
1.1.1.7 root 189: static int mst_fpga_post_load(void *opaque, int version_id)
1.1 root 190: {
191: mst_irq_state *s = (mst_irq_state *) opaque;
192:
1.1.1.7 root 193: qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
1.1 root 194: return 0;
195: }
196:
1.1.1.7 root 197: static int mst_fpga_init(SysBusDevice *dev)
1.1 root 198: {
199: mst_irq_state *s;
200:
1.1.1.7 root 201: s = FROM_SYSBUS(mst_irq_state, dev);
1.1 root 202:
1.1.1.7 root 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);
1.1 root 207:
208: /* alloc the external 16 irqs */
1.1.1.7 root 209: qdev_init_gpio_in(&dev->qdev, mst_fpga_set_irq, MST_NUM_IRQS);
1.1 root 210:
1.1.1.9 ! root 211: memory_region_init_io(&s->iomem, &mst_fpga_ops, s,
! 212: "fpga", 0x00100000);
! 213: sysbus_init_mmio(dev, &s->iomem);
1.1.1.7 root 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:
1.1.1.9 ! root 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 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,
1.1.1.7 root 256: };
257:
1.1.1.9 ! root 258: static void mst_fpga_register_types(void)
1.1.1.7 root 259: {
1.1.1.9 ! root 260: type_register_static(&mst_fpga_info);
1.1 root 261: }
1.1.1.9 ! root 262:
! 263: type_init(mst_fpga_register_types)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.