~ahs3/+junk/cq-qemu

« back to all changes in this revision

Viewing changes to hw/pxa2xx_dma.c

  • Committer: Al Stone
  • Date: 2012-02-09 01:17:20 UTC
  • Revision ID: albert.stone@canonical.com-20120209011720-tztl7ik3qayz80p4
first commit to bzr for qemu

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Intel XScale PXA255/270 DMA controller.
 
3
 *
 
4
 * Copyright (c) 2006 Openedhand Ltd.
 
5
 * Copyright (c) 2006 Thorsten Zitterell
 
6
 * Written by Andrzej Zaborowski <balrog@zabor.org>
 
7
 *
 
8
 * This code is licensed under the GPL.
 
9
 */
 
10
 
 
11
#include "hw.h"
 
12
#include "pxa.h"
 
13
#include "sysbus.h"
 
14
 
 
15
#define PXA255_DMA_NUM_CHANNELS 16
 
16
#define PXA27X_DMA_NUM_CHANNELS 32
 
17
 
 
18
#define PXA2XX_DMA_NUM_REQUESTS 75
 
19
 
 
20
typedef struct {
 
21
    target_phys_addr_t descr;
 
22
    target_phys_addr_t src;
 
23
    target_phys_addr_t dest;
 
24
    uint32_t cmd;
 
25
    uint32_t state;
 
26
    int request;
 
27
} PXA2xxDMAChannel;
 
28
 
 
29
typedef struct PXA2xxDMAState {
 
30
    SysBusDevice busdev;
 
31
    qemu_irq irq;
 
32
 
 
33
    uint32_t stopintr;
 
34
    uint32_t eorintr;
 
35
    uint32_t rasintr;
 
36
    uint32_t startintr;
 
37
    uint32_t endintr;
 
38
 
 
39
    uint32_t align;
 
40
    uint32_t pio;
 
41
 
 
42
    int channels;
 
43
    PXA2xxDMAChannel *chan;
 
44
 
 
45
    uint8_t req[PXA2XX_DMA_NUM_REQUESTS];
 
46
 
 
47
    /* Flag to avoid recursive DMA invocations.  */
 
48
    int running;
 
49
} PXA2xxDMAState;
 
50
 
 
51
#define DCSR0   0x0000  /* DMA Control / Status register for Channel 0 */
 
52
#define DCSR31  0x007c  /* DMA Control / Status register for Channel 31 */
 
53
#define DALGN   0x00a0  /* DMA Alignment register */
 
54
#define DPCSR   0x00a4  /* DMA Programmed I/O Control Status register */
 
55
#define DRQSR0  0x00e0  /* DMA DREQ<0> Status register */
 
56
#define DRQSR1  0x00e4  /* DMA DREQ<1> Status register */
 
57
#define DRQSR2  0x00e8  /* DMA DREQ<2> Status register */
 
58
#define DINT    0x00f0  /* DMA Interrupt register */
 
59
#define DRCMR0  0x0100  /* Request to Channel Map register 0 */
 
60
#define DRCMR63 0x01fc  /* Request to Channel Map register 63 */
 
61
#define D_CH0   0x0200  /* Channel 0 Descriptor start */
 
62
#define DRCMR64 0x1100  /* Request to Channel Map register 64 */
 
63
#define DRCMR74 0x1128  /* Request to Channel Map register 74 */
 
64
 
 
65
/* Per-channel register */
 
66
#define DDADR   0x00
 
67
#define DSADR   0x01
 
68
#define DTADR   0x02
 
69
#define DCMD    0x03
 
70
 
 
71
/* Bit-field masks */
 
72
#define DRCMR_CHLNUM            0x1f
 
73
#define DRCMR_MAPVLD            (1 << 7)
 
74
#define DDADR_STOP              (1 << 0)
 
75
#define DDADR_BREN              (1 << 1)
 
76
#define DCMD_LEN                0x1fff
 
77
#define DCMD_WIDTH(x)           (1 << ((((x) >> 14) & 3) - 1))
 
78
#define DCMD_SIZE(x)            (4 << (((x) >> 16) & 3))
 
79
#define DCMD_FLYBYT             (1 << 19)
 
80
#define DCMD_FLYBYS             (1 << 20)
 
81
#define DCMD_ENDIRQEN           (1 << 21)
 
82
#define DCMD_STARTIRQEN         (1 << 22)
 
83
#define DCMD_CMPEN              (1 << 25)
 
84
#define DCMD_FLOWTRG            (1 << 28)
 
85
#define DCMD_FLOWSRC            (1 << 29)
 
86
#define DCMD_INCTRGADDR         (1 << 30)
 
87
#define DCMD_INCSRCADDR         (1 << 31)
 
88
#define DCSR_BUSERRINTR         (1 << 0)
 
89
#define DCSR_STARTINTR          (1 << 1)
 
90
#define DCSR_ENDINTR            (1 << 2)
 
91
#define DCSR_STOPINTR           (1 << 3)
 
92
#define DCSR_RASINTR            (1 << 4)
 
93
#define DCSR_REQPEND            (1 << 8)
 
94
#define DCSR_EORINT             (1 << 9)
 
95
#define DCSR_CMPST              (1 << 10)
 
96
#define DCSR_MASKRUN            (1 << 22)
 
97
#define DCSR_RASIRQEN           (1 << 23)
 
98
#define DCSR_CLRCMPST           (1 << 24)
 
99
#define DCSR_SETCMPST           (1 << 25)
 
100
#define DCSR_EORSTOPEN          (1 << 26)
 
101
#define DCSR_EORJMPEN           (1 << 27)
 
102
#define DCSR_EORIRQEN           (1 << 28)
 
103
#define DCSR_STOPIRQEN          (1 << 29)
 
104
#define DCSR_NODESCFETCH        (1 << 30)
 
105
#define DCSR_RUN                (1 << 31)
 
106
 
 
107
static inline void pxa2xx_dma_update(PXA2xxDMAState *s, int ch)
 
108
{
 
109
    if (ch >= 0) {
 
110
        if ((s->chan[ch].state & DCSR_STOPIRQEN) &&
 
111
                (s->chan[ch].state & DCSR_STOPINTR))
 
112
            s->stopintr |= 1 << ch;
 
113
        else
 
114
            s->stopintr &= ~(1 << ch);
 
115
 
 
116
        if ((s->chan[ch].state & DCSR_EORIRQEN) &&
 
117
                (s->chan[ch].state & DCSR_EORINT))
 
118
            s->eorintr |= 1 << ch;
 
119
        else
 
120
            s->eorintr &= ~(1 << ch);
 
121
 
 
122
        if ((s->chan[ch].state & DCSR_RASIRQEN) &&
 
123
                (s->chan[ch].state & DCSR_RASINTR))
 
124
            s->rasintr |= 1 << ch;
 
125
        else
 
126
            s->rasintr &= ~(1 << ch);
 
127
 
 
128
        if (s->chan[ch].state & DCSR_STARTINTR)
 
129
            s->startintr |= 1 << ch;
 
130
        else
 
131
            s->startintr &= ~(1 << ch);
 
132
 
 
133
        if (s->chan[ch].state & DCSR_ENDINTR)
 
134
            s->endintr |= 1 << ch;
 
135
        else
 
136
            s->endintr &= ~(1 << ch);
 
137
    }
 
138
 
 
139
    if (s->stopintr | s->eorintr | s->rasintr | s->startintr | s->endintr)
 
140
        qemu_irq_raise(s->irq);
 
141
    else
 
142
        qemu_irq_lower(s->irq);
 
143
}
 
144
 
 
145
static inline void pxa2xx_dma_descriptor_fetch(
 
146
                PXA2xxDMAState *s, int ch)
 
147
{
 
148
    uint32_t desc[4];
 
149
    target_phys_addr_t daddr = s->chan[ch].descr & ~0xf;
 
150
    if ((s->chan[ch].descr & DDADR_BREN) && (s->chan[ch].state & DCSR_CMPST))
 
151
        daddr += 32;
 
152
 
 
153
    cpu_physical_memory_read(daddr, (uint8_t *) desc, 16);
 
154
    s->chan[ch].descr = desc[DDADR];
 
155
    s->chan[ch].src = desc[DSADR];
 
156
    s->chan[ch].dest = desc[DTADR];
 
157
    s->chan[ch].cmd = desc[DCMD];
 
158
 
 
159
    if (s->chan[ch].cmd & DCMD_FLOWSRC)
 
160
        s->chan[ch].src &= ~3;
 
161
    if (s->chan[ch].cmd & DCMD_FLOWTRG)
 
162
        s->chan[ch].dest &= ~3;
 
163
 
 
164
    if (s->chan[ch].cmd & (DCMD_CMPEN | DCMD_FLYBYS | DCMD_FLYBYT))
 
165
        printf("%s: unsupported mode in channel %i\n", __FUNCTION__, ch);
 
166
 
 
167
    if (s->chan[ch].cmd & DCMD_STARTIRQEN)
 
168
        s->chan[ch].state |= DCSR_STARTINTR;
 
169
}
 
170
 
 
171
static void pxa2xx_dma_run(PXA2xxDMAState *s)
 
172
{
 
173
    int c, srcinc, destinc;
 
174
    uint32_t n, size;
 
175
    uint32_t width;
 
176
    uint32_t length;
 
177
    uint8_t buffer[32];
 
178
    PXA2xxDMAChannel *ch;
 
179
 
 
180
    if (s->running ++)
 
181
        return;
 
182
 
 
183
    while (s->running) {
 
184
        s->running = 1;
 
185
        for (c = 0; c < s->channels; c ++) {
 
186
            ch = &s->chan[c];
 
187
 
 
188
            while ((ch->state & DCSR_RUN) && !(ch->state & DCSR_STOPINTR)) {
 
189
                /* Test for pending requests */
 
190
                if ((ch->cmd & (DCMD_FLOWSRC | DCMD_FLOWTRG)) && !ch->request)
 
191
                    break;
 
192
 
 
193
                length = ch->cmd & DCMD_LEN;
 
194
                size = DCMD_SIZE(ch->cmd);
 
195
                width = DCMD_WIDTH(ch->cmd);
 
196
 
 
197
                srcinc = (ch->cmd & DCMD_INCSRCADDR) ? width : 0;
 
198
                destinc = (ch->cmd & DCMD_INCTRGADDR) ? width : 0;
 
199
 
 
200
                while (length) {
 
201
                    size = MIN(length, size);
 
202
 
 
203
                    for (n = 0; n < size; n += width) {
 
204
                        cpu_physical_memory_read(ch->src, buffer + n, width);
 
205
                        ch->src += srcinc;
 
206
                    }
 
207
 
 
208
                    for (n = 0; n < size; n += width) {
 
209
                        cpu_physical_memory_write(ch->dest, buffer + n, width);
 
210
                        ch->dest += destinc;
 
211
                    }
 
212
 
 
213
                    length -= size;
 
214
 
 
215
                    if ((ch->cmd & (DCMD_FLOWSRC | DCMD_FLOWTRG)) &&
 
216
                            !ch->request) {
 
217
                        ch->state |= DCSR_EORINT;
 
218
                        if (ch->state & DCSR_EORSTOPEN)
 
219
                            ch->state |= DCSR_STOPINTR;
 
220
                        if ((ch->state & DCSR_EORJMPEN) &&
 
221
                                        !(ch->state & DCSR_NODESCFETCH))
 
222
                            pxa2xx_dma_descriptor_fetch(s, c);
 
223
                        break;
 
224
                    }
 
225
                }
 
226
 
 
227
                ch->cmd = (ch->cmd & ~DCMD_LEN) | length;
 
228
 
 
229
                /* Is the transfer complete now? */
 
230
                if (!length) {
 
231
                    if (ch->cmd & DCMD_ENDIRQEN)
 
232
                        ch->state |= DCSR_ENDINTR;
 
233
 
 
234
                    if ((ch->state & DCSR_NODESCFETCH) ||
 
235
                                (ch->descr & DDADR_STOP) ||
 
236
                                (ch->state & DCSR_EORSTOPEN)) {
 
237
                        ch->state |= DCSR_STOPINTR;
 
238
                        ch->state &= ~DCSR_RUN;
 
239
 
 
240
                        break;
 
241
                    }
 
242
 
 
243
                    ch->state |= DCSR_STOPINTR;
 
244
                    break;
 
245
                }
 
246
            }
 
247
        }
 
248
 
 
249
        s->running --;
 
250
    }
 
251
}
 
252
 
 
253
static uint32_t pxa2xx_dma_read(void *opaque, target_phys_addr_t offset)
 
254
{
 
255
    PXA2xxDMAState *s = (PXA2xxDMAState *) opaque;
 
256
    unsigned int channel;
 
257
 
 
258
    switch (offset) {
 
259
    case DRCMR64 ... DRCMR74:
 
260
        offset -= DRCMR64 - DRCMR0 - (64 << 2);
 
261
        /* Fall through */
 
262
    case DRCMR0 ... DRCMR63:
 
263
        channel = (offset - DRCMR0) >> 2;
 
264
        return s->req[channel];
 
265
 
 
266
    case DRQSR0:
 
267
    case DRQSR1:
 
268
    case DRQSR2:
 
269
        return 0;
 
270
 
 
271
    case DCSR0 ... DCSR31:
 
272
        channel = offset >> 2;
 
273
        if (s->chan[channel].request)
 
274
            return s->chan[channel].state | DCSR_REQPEND;
 
275
        return s->chan[channel].state;
 
276
 
 
277
    case DINT:
 
278
        return s->stopintr | s->eorintr | s->rasintr |
 
279
                s->startintr | s->endintr;
 
280
 
 
281
    case DALGN:
 
282
        return s->align;
 
283
 
 
284
    case DPCSR:
 
285
        return s->pio;
 
286
    }
 
287
 
 
288
    if (offset >= D_CH0 && offset < D_CH0 + (s->channels << 4)) {
 
289
        channel = (offset - D_CH0) >> 4;
 
290
        switch ((offset & 0x0f) >> 2) {
 
291
        case DDADR:
 
292
            return s->chan[channel].descr;
 
293
        case DSADR:
 
294
            return s->chan[channel].src;
 
295
        case DTADR:
 
296
            return s->chan[channel].dest;
 
297
        case DCMD:
 
298
            return s->chan[channel].cmd;
 
299
        }
 
300
    }
 
301
 
 
302
    hw_error("%s: Bad offset 0x" TARGET_FMT_plx "\n", __FUNCTION__, offset);
 
303
    return 7;
 
304
}
 
305
 
 
306
static void pxa2xx_dma_write(void *opaque,
 
307
                 target_phys_addr_t offset, uint32_t value)
 
308
{
 
309
    PXA2xxDMAState *s = (PXA2xxDMAState *) opaque;
 
310
    unsigned int channel;
 
311
 
 
312
    switch (offset) {
 
313
    case DRCMR64 ... DRCMR74:
 
314
        offset -= DRCMR64 - DRCMR0 - (64 << 2);
 
315
        /* Fall through */
 
316
    case DRCMR0 ... DRCMR63:
 
317
        channel = (offset - DRCMR0) >> 2;
 
318
 
 
319
        if (value & DRCMR_MAPVLD)
 
320
            if ((value & DRCMR_CHLNUM) > s->channels)
 
321
                hw_error("%s: Bad DMA channel %i\n",
 
322
                         __FUNCTION__, value & DRCMR_CHLNUM);
 
323
 
 
324
        s->req[channel] = value;
 
325
        break;
 
326
 
 
327
    case DRQSR0:
 
328
    case DRQSR1:
 
329
    case DRQSR2:
 
330
        /* Nothing to do */
 
331
        break;
 
332
 
 
333
    case DCSR0 ... DCSR31:
 
334
        channel = offset >> 2;
 
335
        s->chan[channel].state &= 0x0000071f & ~(value &
 
336
                        (DCSR_EORINT | DCSR_ENDINTR |
 
337
                         DCSR_STARTINTR | DCSR_BUSERRINTR));
 
338
        s->chan[channel].state |= value & 0xfc800000;
 
339
 
 
340
        if (s->chan[channel].state & DCSR_STOPIRQEN)
 
341
            s->chan[channel].state &= ~DCSR_STOPINTR;
 
342
 
 
343
        if (value & DCSR_NODESCFETCH) {
 
344
            /* No-descriptor-fetch mode */
 
345
            if (value & DCSR_RUN) {
 
346
                s->chan[channel].state &= ~DCSR_STOPINTR;
 
347
                pxa2xx_dma_run(s);
 
348
            }
 
349
        } else {
 
350
            /* Descriptor-fetch mode */
 
351
            if (value & DCSR_RUN) {
 
352
                s->chan[channel].state &= ~DCSR_STOPINTR;
 
353
                pxa2xx_dma_descriptor_fetch(s, channel);
 
354
                pxa2xx_dma_run(s);
 
355
            }
 
356
        }
 
357
 
 
358
        /* Shouldn't matter as our DMA is synchronous.  */
 
359
        if (!(value & (DCSR_RUN | DCSR_MASKRUN)))
 
360
            s->chan[channel].state |= DCSR_STOPINTR;
 
361
 
 
362
        if (value & DCSR_CLRCMPST)
 
363
            s->chan[channel].state &= ~DCSR_CMPST;
 
364
        if (value & DCSR_SETCMPST)
 
365
            s->chan[channel].state |= DCSR_CMPST;
 
366
 
 
367
        pxa2xx_dma_update(s, channel);
 
368
        break;
 
369
 
 
370
    case DALGN:
 
371
        s->align = value;
 
372
        break;
 
373
 
 
374
    case DPCSR:
 
375
        s->pio = value & 0x80000001;
 
376
        break;
 
377
 
 
378
    default:
 
379
        if (offset >= D_CH0 && offset < D_CH0 + (s->channels << 4)) {
 
380
            channel = (offset - D_CH0) >> 4;
 
381
            switch ((offset & 0x0f) >> 2) {
 
382
            case DDADR:
 
383
                s->chan[channel].descr = value;
 
384
                break;
 
385
            case DSADR:
 
386
                s->chan[channel].src = value;
 
387
                break;
 
388
            case DTADR:
 
389
                s->chan[channel].dest = value;
 
390
                break;
 
391
            case DCMD:
 
392
                s->chan[channel].cmd = value;
 
393
                break;
 
394
            default:
 
395
                goto fail;
 
396
            }
 
397
 
 
398
            break;
 
399
        }
 
400
    fail:
 
401
        hw_error("%s: Bad offset " TARGET_FMT_plx "\n", __FUNCTION__, offset);
 
402
    }
 
403
}
 
404
 
 
405
static uint32_t pxa2xx_dma_readbad(void *opaque, target_phys_addr_t offset)
 
406
{
 
407
    hw_error("%s: Bad access width\n", __FUNCTION__);
 
408
    return 5;
 
409
}
 
410
 
 
411
static void pxa2xx_dma_writebad(void *opaque,
 
412
                 target_phys_addr_t offset, uint32_t value)
 
413
{
 
414
    hw_error("%s: Bad access width\n", __FUNCTION__);
 
415
}
 
416
 
 
417
static CPUReadMemoryFunc * const pxa2xx_dma_readfn[] = {
 
418
    pxa2xx_dma_readbad,
 
419
    pxa2xx_dma_readbad,
 
420
    pxa2xx_dma_read
 
421
};
 
422
 
 
423
static CPUWriteMemoryFunc * const pxa2xx_dma_writefn[] = {
 
424
    pxa2xx_dma_writebad,
 
425
    pxa2xx_dma_writebad,
 
426
    pxa2xx_dma_write
 
427
};
 
428
 
 
429
static void pxa2xx_dma_request(void *opaque, int req_num, int on)
 
430
{
 
431
    PXA2xxDMAState *s = opaque;
 
432
    int ch;
 
433
    if (req_num < 0 || req_num >= PXA2XX_DMA_NUM_REQUESTS)
 
434
        hw_error("%s: Bad DMA request %i\n", __FUNCTION__, req_num);
 
435
 
 
436
    if (!(s->req[req_num] & DRCMR_MAPVLD))
 
437
        return;
 
438
    ch = s->req[req_num] & DRCMR_CHLNUM;
 
439
 
 
440
    if (!s->chan[ch].request && on)
 
441
        s->chan[ch].state |= DCSR_RASINTR;
 
442
    else
 
443
        s->chan[ch].state &= ~DCSR_RASINTR;
 
444
    if (s->chan[ch].request && !on)
 
445
        s->chan[ch].state |= DCSR_EORINT;
 
446
 
 
447
    s->chan[ch].request = on;
 
448
    if (on) {
 
449
        pxa2xx_dma_run(s);
 
450
        pxa2xx_dma_update(s, ch);
 
451
    }
 
452
}
 
453
 
 
454
static int pxa2xx_dma_init(SysBusDevice *dev)
 
455
{
 
456
    int i, iomemtype;
 
457
    PXA2xxDMAState *s;
 
458
    s = FROM_SYSBUS(PXA2xxDMAState, dev);
 
459
 
 
460
    if (s->channels <= 0) {
 
461
        return -1;
 
462
    }
 
463
 
 
464
    s->chan = g_malloc0(sizeof(PXA2xxDMAChannel) * s->channels);
 
465
 
 
466
    memset(s->chan, 0, sizeof(PXA2xxDMAChannel) * s->channels);
 
467
    for (i = 0; i < s->channels; i ++)
 
468
        s->chan[i].state = DCSR_STOPINTR;
 
469
 
 
470
    memset(s->req, 0, sizeof(uint8_t) * PXA2XX_DMA_NUM_REQUESTS);
 
471
 
 
472
    qdev_init_gpio_in(&dev->qdev, pxa2xx_dma_request, PXA2XX_DMA_NUM_REQUESTS);
 
473
 
 
474
    iomemtype = cpu_register_io_memory(pxa2xx_dma_readfn,
 
475
                    pxa2xx_dma_writefn, s, DEVICE_NATIVE_ENDIAN);
 
476
    sysbus_init_mmio(dev, 0x00010000, iomemtype);
 
477
    sysbus_init_irq(dev, &s->irq);
 
478
 
 
479
    return 0;
 
480
}
 
481
 
 
482
DeviceState *pxa27x_dma_init(target_phys_addr_t base, qemu_irq irq)
 
483
{
 
484
    DeviceState *dev;
 
485
 
 
486
    dev = qdev_create(NULL, "pxa2xx-dma");
 
487
    qdev_prop_set_int32(dev, "channels", PXA27X_DMA_NUM_CHANNELS);
 
488
    qdev_init_nofail(dev);
 
489
 
 
490
    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
 
491
    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
 
492
 
 
493
    return dev;
 
494
}
 
495
 
 
496
DeviceState *pxa255_dma_init(target_phys_addr_t base, qemu_irq irq)
 
497
{
 
498
    DeviceState *dev;
 
499
 
 
500
    dev = qdev_create(NULL, "pxa2xx-dma");
 
501
    qdev_prop_set_int32(dev, "channels", PXA27X_DMA_NUM_CHANNELS);
 
502
    qdev_init_nofail(dev);
 
503
 
 
504
    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
 
505
    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
 
506
 
 
507
    return dev;
 
508
}
 
509
 
 
510
static bool is_version_0(void *opaque, int version_id)
 
511
{
 
512
    return version_id == 0;
 
513
}
 
514
 
 
515
static VMStateDescription vmstate_pxa2xx_dma_chan = {
 
516
    .name = "pxa2xx_dma_chan",
 
517
    .version_id = 1,
 
518
    .minimum_version_id = 1,
 
519
    .minimum_version_id_old = 1,
 
520
    .fields = (VMStateField[]) {
 
521
        VMSTATE_UINTTL(descr, PXA2xxDMAChannel),
 
522
        VMSTATE_UINTTL(src, PXA2xxDMAChannel),
 
523
        VMSTATE_UINTTL(dest, PXA2xxDMAChannel),
 
524
        VMSTATE_UINT32(cmd, PXA2xxDMAChannel),
 
525
        VMSTATE_UINT32(state, PXA2xxDMAChannel),
 
526
        VMSTATE_INT32(request, PXA2xxDMAChannel),
 
527
        VMSTATE_END_OF_LIST(),
 
528
    },
 
529
};
 
530
 
 
531
static VMStateDescription vmstate_pxa2xx_dma = {
 
532
    .name = "pxa2xx_dma",
 
533
    .version_id = 1,
 
534
    .minimum_version_id = 0,
 
535
    .minimum_version_id_old = 0,
 
536
    .fields = (VMStateField[]) {
 
537
        VMSTATE_UNUSED_TEST(is_version_0, 4),
 
538
        VMSTATE_UINT32(stopintr, PXA2xxDMAState),
 
539
        VMSTATE_UINT32(eorintr, PXA2xxDMAState),
 
540
        VMSTATE_UINT32(rasintr, PXA2xxDMAState),
 
541
        VMSTATE_UINT32(startintr, PXA2xxDMAState),
 
542
        VMSTATE_UINT32(endintr, PXA2xxDMAState),
 
543
        VMSTATE_UINT32(align, PXA2xxDMAState),
 
544
        VMSTATE_UINT32(pio, PXA2xxDMAState),
 
545
        VMSTATE_BUFFER(req, PXA2xxDMAState),
 
546
        VMSTATE_STRUCT_VARRAY_POINTER_INT32(chan, PXA2xxDMAState, channels,
 
547
                vmstate_pxa2xx_dma_chan, PXA2xxDMAChannel),
 
548
        VMSTATE_END_OF_LIST(),
 
549
    },
 
550
};
 
551
 
 
552
static SysBusDeviceInfo pxa2xx_dma_info = {
 
553
    .init       = pxa2xx_dma_init,
 
554
    .qdev.name  = "pxa2xx-dma",
 
555
    .qdev.desc  = "PXA2xx DMA controller",
 
556
    .qdev.size  = sizeof(PXA2xxDMAState),
 
557
    .qdev.vmsd  = &vmstate_pxa2xx_dma,
 
558
    .qdev.props = (Property[]) {
 
559
        DEFINE_PROP_INT32("channels", PXA2xxDMAState, channels, -1),
 
560
        DEFINE_PROP_END_OF_LIST(),
 
561
    },
 
562
};
 
563
 
 
564
static void pxa2xx_dma_register(void)
 
565
{
 
566
    sysbus_register_withprop(&pxa2xx_dma_info);
 
567
}
 
568
device_init(pxa2xx_dma_register);