Statistics
| Branch: | Revision:

root / hw / mst_fpga.c @ a8170e5e

History | View | Annotate | Download (6 kB)

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.h"
14
#include "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 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)