Statistics
| Branch: | Revision:

root / hw / pxa2xx_dma.c @ 7267c094

History | View | Annotate | Download (16.1 kB)

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