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