Statistics
| Branch: | Revision:

root / hw / mst_fpga.c @ ff2712ba

History | View | Annotate | Download (5.7 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
#include "hw.h"
11
#include "sysbus.h"
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

    
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

    
35
typedef struct mst_irq_state{
36
        SysBusDevice busdev;
37

    
38
        qemu_irq parent;
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;
59
        uint32_t oldint = s->intsetclr & s->intmskena;
60

    
61
        if (level)
62
                s->prev_level |= 1u << irq;
63
        else
64
                s->prev_level &= ~(1u << irq);
65

    
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;
79
        }
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);
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 "
121
                        "0x" TARGET_FMT_plx " \n", addr);
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;
157
        case MST_INTMSKENA:        /* Mask interrupt */
158
                s->intmskena = (value & 0xFEEFF);
159
                qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
160
                break;
161
        case MST_INTSETCLR:        /* clear or set interrupt */
162
                s->intsetclr = (value & 0xFEEFF);
163
                qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
164
                break;
165
                /* For PCMCIAx allow the to change only power and reset */
166
        case MST_PCMCIA0:
167
                s->pcmcia0 = (value & 0x1f) | (s->pcmcia0 & ~0x1f);
168
                break;
169
        case MST_PCMCIA1:
170
                s->pcmcia1 = (value & 0x1f) | (s->pcmcia1 & ~0x1f);
171
                break;
172
        default:
173
                printf("Mainstone - mst_fpga_writeb: Bad register offset "
174
                        "0x" TARGET_FMT_plx " \n", addr);
175
        }
176
}
177

    
178
static CPUReadMemoryFunc * const mst_fpga_readfn[] = {
179
        mst_fpga_readb,
180
        mst_fpga_readb,
181
        mst_fpga_readb,
182
};
183
static CPUWriteMemoryFunc * const mst_fpga_writefn[] = {
184
        mst_fpga_writeb,
185
        mst_fpga_writeb,
186
        mst_fpga_writeb,
187
};
188

    
189

    
190
static int mst_fpga_post_load(void *opaque, int version_id)
191
{
192
        mst_irq_state *s = (mst_irq_state *) opaque;
193

    
194
        qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
195
        return 0;
196
}
197

    
198
static int mst_fpga_init(SysBusDevice *dev)
199
{
200
        mst_irq_state *s;
201
        int iomemtype;
202

    
203
        s = FROM_SYSBUS(mst_irq_state, dev);
204

    
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);
209

    
210
        /* alloc the external 16 irqs */
211
        qdev_init_gpio_in(&dev->qdev, mst_fpga_set_irq, MST_NUM_IRQS);
212

    
213
        iomemtype = cpu_register_io_memory(mst_fpga_readfn,
214
                mst_fpga_writefn, s, DEVICE_NATIVE_ENDIAN);
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);
254
}
255
device_init(mst_fpga_register);