Statistics
| Branch: | Revision:

root / hw / mst_fpga.c @ 0be71e32

History | View | Annotate | Download (5.1 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 "pxa.h"
12
#include "mainstone.h"
13

    
14
/* Mainstone FPGA for extern irqs */
15
#define FPGA_GPIO_PIN        0
16
#define MST_NUM_IRQS        16
17
#define MST_LEDDAT1                0x10
18
#define MST_LEDDAT2                0x14
19
#define MST_LEDCTRL                0x40
20
#define MST_GPSWR                0x60
21
#define MST_MSCWR1                0x80
22
#define MST_MSCWR2                0x84
23
#define MST_MSCWR3                0x88
24
#define MST_MSCRD                0x90
25
#define MST_INTMSKENA        0xc0
26
#define MST_INTSETCLR        0xd0
27
#define MST_PCMCIA0                0xe0
28
#define MST_PCMCIA1                0xe4
29

    
30
typedef struct mst_irq_state{
31
        qemu_irq *parent;
32
        qemu_irq *pins;
33

    
34
        uint32_t prev_level;
35
        uint32_t leddat1;
36
        uint32_t leddat2;
37
        uint32_t ledctrl;
38
        uint32_t gpswr;
39
        uint32_t mscwr1;
40
        uint32_t mscwr2;
41
        uint32_t mscwr3;
42
        uint32_t mscrd;
43
        uint32_t intmskena;
44
        uint32_t intsetclr;
45
        uint32_t pcmcia0;
46
        uint32_t pcmcia1;
47
}mst_irq_state;
48

    
49
static void
50
mst_fpga_update_gpio(mst_irq_state *s)
51
{
52
        uint32_t level, diff;
53
        int bit;
54
        level = s->prev_level ^ s->intsetclr;
55

    
56
        for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) {
57
                bit = ffs(diff) - 1;
58
                qemu_set_irq(s->pins[bit], (level >> bit) & 1 );
59
        }
60
        s->prev_level = level;
61
}
62

    
63
static void
64
mst_fpga_set_irq(void *opaque, int irq, int level)
65
{
66
        mst_irq_state *s = (mst_irq_state *)opaque;
67

    
68
        if (level)
69
                s->prev_level |= 1u << irq;
70
        else
71
                s->prev_level &= ~(1u << irq);
72

    
73
        if(s->intmskena & (1u << irq)) {
74
                s->intsetclr = 1u << irq;
75
                qemu_set_irq(s->parent[0], level);
76
        }
77
}
78

    
79

    
80
static uint32_t
81
mst_fpga_readb(void *opaque, target_phys_addr_t addr)
82
{
83
        mst_irq_state *s = (mst_irq_state *) opaque;
84

    
85
        switch (addr) {
86
        case MST_LEDDAT1:
87
                return s->leddat1;
88
        case MST_LEDDAT2:
89
                return s->leddat2;
90
        case MST_LEDCTRL:
91
                return s->ledctrl;
92
        case MST_GPSWR:
93
                return s->gpswr;
94
        case MST_MSCWR1:
95
                return s->mscwr1;
96
        case MST_MSCWR2:
97
                return s->mscwr2;
98
        case MST_MSCWR3:
99
                return s->mscwr3;
100
        case MST_MSCRD:
101
                return s->mscrd;
102
        case MST_INTMSKENA:
103
                return s->intmskena;
104
        case MST_INTSETCLR:
105
                return s->intsetclr;
106
        case MST_PCMCIA0:
107
                return s->pcmcia0;
108
        case MST_PCMCIA1:
109
                return s->pcmcia1;
110
        default:
111
                printf("Mainstone - mst_fpga_readb: Bad register offset "
112
                        REG_FMT " \n", addr);
113
        }
114
        return 0;
115
}
116

    
117
static void
118
mst_fpga_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
119
{
120
        mst_irq_state *s = (mst_irq_state *) opaque;
121
        value &= 0xffffffff;
122

    
123
        switch (addr) {
124
        case MST_LEDDAT1:
125
                s->leddat1 = value;
126
                break;
127
        case MST_LEDDAT2:
128
                s->leddat2 = value;
129
                break;
130
        case MST_LEDCTRL:
131
                s->ledctrl = value;
132
                break;
133
        case MST_GPSWR:
134
                s->gpswr = value;
135
                break;
136
        case MST_MSCWR1:
137
                s->mscwr1 = value;
138
                break;
139
        case MST_MSCWR2:
140
                s->mscwr2 = value;
141
                break;
142
        case MST_MSCWR3:
143
                s->mscwr3 = value;
144
                break;
145
        case MST_MSCRD:
146
                s->mscrd =  value;
147
                break;
148
        case MST_INTMSKENA:        /* Mask interupt */
149
                s->intmskena = (value & 0xFEEFF);
150
                mst_fpga_update_gpio(s);
151
                break;
152
        case MST_INTSETCLR:        /* clear or set interrupt */
153
                s->intsetclr = (value & 0xFEEFF);
154
                break;
155
        case MST_PCMCIA0:
156
                s->pcmcia0 = value;
157
                break;
158
        case MST_PCMCIA1:
159
                s->pcmcia1 = value;
160
                break;
161
        default:
162
                printf("Mainstone - mst_fpga_writeb: Bad register offset "
163
                        REG_FMT " \n", addr);
164
        }
165
}
166

    
167
static CPUReadMemoryFunc * const mst_fpga_readfn[] = {
168
        mst_fpga_readb,
169
        mst_fpga_readb,
170
        mst_fpga_readb,
171
};
172
static CPUWriteMemoryFunc * const mst_fpga_writefn[] = {
173
        mst_fpga_writeb,
174
        mst_fpga_writeb,
175
        mst_fpga_writeb,
176
};
177

    
178
static void
179
mst_fpga_save(QEMUFile *f, void *opaque)
180
{
181
        struct mst_irq_state *s = (mst_irq_state *) opaque;
182

    
183
        qemu_put_be32s(f, &s->prev_level);
184
        qemu_put_be32s(f, &s->leddat1);
185
        qemu_put_be32s(f, &s->leddat2);
186
        qemu_put_be32s(f, &s->ledctrl);
187
        qemu_put_be32s(f, &s->gpswr);
188
        qemu_put_be32s(f, &s->mscwr1);
189
        qemu_put_be32s(f, &s->mscwr2);
190
        qemu_put_be32s(f, &s->mscwr3);
191
        qemu_put_be32s(f, &s->mscrd);
192
        qemu_put_be32s(f, &s->intmskena);
193
        qemu_put_be32s(f, &s->intsetclr);
194
        qemu_put_be32s(f, &s->pcmcia0);
195
        qemu_put_be32s(f, &s->pcmcia1);
196
}
197

    
198
static int
199
mst_fpga_load(QEMUFile *f, void *opaque, int version_id)
200
{
201
        mst_irq_state *s = (mst_irq_state *) opaque;
202

    
203
        qemu_get_be32s(f, &s->prev_level);
204
        qemu_get_be32s(f, &s->leddat1);
205
        qemu_get_be32s(f, &s->leddat2);
206
        qemu_get_be32s(f, &s->ledctrl);
207
        qemu_get_be32s(f, &s->gpswr);
208
        qemu_get_be32s(f, &s->mscwr1);
209
        qemu_get_be32s(f, &s->mscwr2);
210
        qemu_get_be32s(f, &s->mscwr3);
211
        qemu_get_be32s(f, &s->mscrd);
212
        qemu_get_be32s(f, &s->intmskena);
213
        qemu_get_be32s(f, &s->intsetclr);
214
        qemu_get_be32s(f, &s->pcmcia0);
215
        qemu_get_be32s(f, &s->pcmcia1);
216
        return 0;
217
}
218

    
219
qemu_irq *mst_irq_init(PXA2xxState *cpu, uint32_t base, int irq)
220
{
221
        mst_irq_state *s;
222
        int iomemtype;
223
        qemu_irq *qi;
224

    
225
        s = (mst_irq_state  *)
226
                qemu_mallocz(sizeof(mst_irq_state));
227

    
228
        s->parent = &cpu->pic[irq];
229

    
230
        /* alloc the external 16 irqs */
231
        qi  = qemu_allocate_irqs(mst_fpga_set_irq, s, MST_NUM_IRQS);
232
        s->pins = qi;
233

    
234
        iomemtype = cpu_register_io_memory(mst_fpga_readfn,
235
                mst_fpga_writefn, s);
236
        cpu_register_physical_memory(base, 0x00100000, iomemtype);
237
        register_savevm(NULL, "mainstone_fpga", 0, 0, mst_fpga_save,
238
                        mst_fpga_load, s);
239
        return qi;
240
}