Revision e69954b9 hw/pl080.c

b/hw/pl080.c
1 1
/* 
2
 * Arm PrimeCell PL080 DMA controller
2
 * Arm PrimeCell PL080/PL081 DMA controller
3 3
 *
4 4
 * Copyright (c) 2006 CodeSourcery.
5 5
 * Written by Paul Brook
......
9 9

  
10 10
#include "vl.h"
11 11

  
12
#define PL080_NUM_CHANNELS 8
12
#define PL080_MAX_CHANNELS 8
13 13
#define PL080_CONF_E    0x1
14 14
#define PL080_CONF_M1   0x2
15 15
#define PL080_CONF_M2   0x4
......
45 45
    uint32_t sync;
46 46
    uint32_t req_single;
47 47
    uint32_t req_burst;
48
    pl080_channel chan[PL080_NUM_CHANNELS];
48
    pl080_channel chan[PL080_MAX_CHANNELS];
49
    int nchannels;
49 50
    /* Flag to avoid recursive DMA invocations.  */
50 51
    int running;
51 52
    void *pic;
......
55 56
static const unsigned char pl080_id[] =
56 57
{ 0x80, 0x10, 0x04, 0x0a, 0x0d, 0xf0, 0x05, 0xb1 };
57 58

  
59
static const unsigned char pl081_id[] =
60
{ 0x81, 0x10, 0x04, 0x0a, 0x0d, 0xf0, 0x05, 0xb1 };
61

  
58 62
static void pl080_update(pl080_state *s)
59 63
{
60 64
    if ((s->tc_int & s->tc_mask)
......
80 84
    uint32_t req;
81 85

  
82 86
    s->tc_mask = 0;
83
    for (c = 0; c < PL080_NUM_CHANNELS; c++) {
87
    for (c = 0; c < s->nchannels; c++) {
84 88
        if (s->chan[c].conf & PL080_CCONF_ITC)
85 89
            s->tc_mask |= 1 << c;
86 90
        if (s->chan[c].conf & PL080_CCONF_IE)
......
99 103
    }
100 104
    s->running = 1;
101 105
    while (s->running) {
102
        for (c = 0; c < PL080_NUM_CHANNELS; c++) {
106
        for (c = 0; c < s->nchannels; c++) {
103 107
            ch = &s->chan[c];
104 108
again:
105 109
            /* Test if thiws channel has any pending DMA requests.  */
......
185 189

  
186 190
    offset -= s->base;
187 191
    if (offset >= 0xfe0 && offset < 0x1000) {
188
        return pl080_id[(offset - 0xfe0) >> 2];
192
        if (s->nchannels == 8) {
193
            return pl080_id[(offset - 0xfe0) >> 2];
194
        } else {
195
            return pl081_id[(offset - 0xfe0) >> 2];
196
        }
189 197
    }
190 198
    if (offset >= 0x100 && offset < 0x200) {
191 199
        i = (offset & 0xe0) >> 5;
200
        if (i >= s->nchannels)
201
            goto bad_offset;
192 202
        switch (offset >> 2) {
193 203
        case 0: /* SrcAddr */
194 204
            return s->chan[i].src;
......
217 227
        return s->err_int;
218 228
    case 7: /* EnbldChns */
219 229
        mask = 0;
220
        for (i = 0; i < PL080_NUM_CHANNELS; i++) {
230
        for (i = 0; i < s->nchannels; i++) {
221 231
            if (s->chan[i].conf & PL080_CCONF_E)
222 232
                mask |= 1 << i;
223 233
        }
......
248 258
    offset -= s->base;
249 259
    if (offset >= 0x100 && offset < 0x200) {
250 260
        i = (offset & 0xe0) >> 5;
261
        if (i >= s->nchannels)
262
            goto bad_offset;
251 263
        switch (offset >> 2) {
252 264
        case 0: /* SrcAddr */
253 265
            s->chan[i].src = value;
......
293 305
        s->sync = value;
294 306
        break;
295 307
    default:
308
    bad_offset:
296 309
        cpu_abort(cpu_single_env, "pl080_write: Bad offset %x\n", offset);
297 310
    }
298 311
    pl080_update(s);
......
310 323
   pl080_write
311 324
};
312 325

  
313
void *pl080_init(uint32_t base, void *pic, int irq)
326
/* The PL080 and PL081 are the same except for the number of channels
327
   they implement (8 and 2 respectively).  */
328
void *pl080_init(uint32_t base, void *pic, int irq, int nchannels)
314 329
{
315 330
    int iomemtype;
316 331
    pl080_state *s;
......
322 337
    s->base = base;
323 338
    s->pic = pic;
324 339
    s->irq = irq;
340
    s->nchannels = nchannels;
325 341
    /* ??? Save/restore.  */
326 342
    return s;
327 343
}

Also available in: Unified diff