qemu/hw/sd/pl181.c
<<
>>
Prefs
   1/*
   2 * Arm PrimeCell PL181 MultiMedia Card Interface
   3 *
   4 * Copyright (c) 2007 CodeSourcery.
   5 * Written by Paul Brook
   6 *
   7 * This code is licensed under the GPL.
   8 */
   9
  10#include "qemu/osdep.h"
  11#include "sysemu/block-backend.h"
  12#include "sysemu/blockdev.h"
  13#include "hw/sysbus.h"
  14#include "hw/sd/sd.h"
  15
  16//#define DEBUG_PL181 1
  17
  18#ifdef DEBUG_PL181
  19#define DPRINTF(fmt, ...) \
  20do { printf("pl181: " fmt , ## __VA_ARGS__); } while (0)
  21#else
  22#define DPRINTF(fmt, ...) do {} while(0)
  23#endif
  24
  25#define PL181_FIFO_LEN 16
  26
  27#define TYPE_PL181 "pl181"
  28#define PL181(obj) OBJECT_CHECK(PL181State, (obj), TYPE_PL181)
  29
  30typedef struct PL181State {
  31    SysBusDevice parent_obj;
  32
  33    MemoryRegion iomem;
  34    SDState *card;
  35    uint32_t clock;
  36    uint32_t power;
  37    uint32_t cmdarg;
  38    uint32_t cmd;
  39    uint32_t datatimer;
  40    uint32_t datalength;
  41    uint32_t respcmd;
  42    uint32_t response[4];
  43    uint32_t datactrl;
  44    uint32_t datacnt;
  45    uint32_t status;
  46    uint32_t mask[2];
  47    int32_t fifo_pos;
  48    int32_t fifo_len;
  49    /* The linux 2.6.21 driver is buggy, and misbehaves if new data arrives
  50       while it is reading the FIFO.  We hack around this by deferring
  51       subsequent transfers until after the driver polls the status word.
  52       http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=4446/1
  53     */
  54    int32_t linux_hack;
  55    uint32_t fifo[PL181_FIFO_LEN];
  56    qemu_irq irq[2];
  57    /* GPIO outputs for 'card is readonly' and 'card inserted' */
  58    qemu_irq cardstatus[2];
  59} PL181State;
  60
  61static const VMStateDescription vmstate_pl181 = {
  62    .name = "pl181",
  63    .version_id = 1,
  64    .minimum_version_id = 1,
  65    .fields = (VMStateField[]) {
  66        VMSTATE_UINT32(clock, PL181State),
  67        VMSTATE_UINT32(power, PL181State),
  68        VMSTATE_UINT32(cmdarg, PL181State),
  69        VMSTATE_UINT32(cmd, PL181State),
  70        VMSTATE_UINT32(datatimer, PL181State),
  71        VMSTATE_UINT32(datalength, PL181State),
  72        VMSTATE_UINT32(respcmd, PL181State),
  73        VMSTATE_UINT32_ARRAY(response, PL181State, 4),
  74        VMSTATE_UINT32(datactrl, PL181State),
  75        VMSTATE_UINT32(datacnt, PL181State),
  76        VMSTATE_UINT32(status, PL181State),
  77        VMSTATE_UINT32_ARRAY(mask, PL181State, 2),
  78        VMSTATE_INT32(fifo_pos, PL181State),
  79        VMSTATE_INT32(fifo_len, PL181State),
  80        VMSTATE_INT32(linux_hack, PL181State),
  81        VMSTATE_UINT32_ARRAY(fifo, PL181State, PL181_FIFO_LEN),
  82        VMSTATE_END_OF_LIST()
  83    }
  84};
  85
  86#define PL181_CMD_INDEX     0x3f
  87#define PL181_CMD_RESPONSE  (1 << 6)
  88#define PL181_CMD_LONGRESP  (1 << 7)
  89#define PL181_CMD_INTERRUPT (1 << 8)
  90#define PL181_CMD_PENDING   (1 << 9)
  91#define PL181_CMD_ENABLE    (1 << 10)
  92
  93#define PL181_DATA_ENABLE             (1 << 0)
  94#define PL181_DATA_DIRECTION          (1 << 1)
  95#define PL181_DATA_MODE               (1 << 2)
  96#define PL181_DATA_DMAENABLE          (1 << 3)
  97
  98#define PL181_STATUS_CMDCRCFAIL       (1 << 0)
  99#define PL181_STATUS_DATACRCFAIL      (1 << 1)
 100#define PL181_STATUS_CMDTIMEOUT       (1 << 2)
 101#define PL181_STATUS_DATATIMEOUT      (1 << 3)
 102#define PL181_STATUS_TXUNDERRUN       (1 << 4)
 103#define PL181_STATUS_RXOVERRUN        (1 << 5)
 104#define PL181_STATUS_CMDRESPEND       (1 << 6)
 105#define PL181_STATUS_CMDSENT          (1 << 7)
 106#define PL181_STATUS_DATAEND          (1 << 8)
 107#define PL181_STATUS_DATABLOCKEND     (1 << 10)
 108#define PL181_STATUS_CMDACTIVE        (1 << 11)
 109#define PL181_STATUS_TXACTIVE         (1 << 12)
 110#define PL181_STATUS_RXACTIVE         (1 << 13)
 111#define PL181_STATUS_TXFIFOHALFEMPTY  (1 << 14)
 112#define PL181_STATUS_RXFIFOHALFFULL   (1 << 15)
 113#define PL181_STATUS_TXFIFOFULL       (1 << 16)
 114#define PL181_STATUS_RXFIFOFULL       (1 << 17)
 115#define PL181_STATUS_TXFIFOEMPTY      (1 << 18)
 116#define PL181_STATUS_RXFIFOEMPTY      (1 << 19)
 117#define PL181_STATUS_TXDATAAVLBL      (1 << 20)
 118#define PL181_STATUS_RXDATAAVLBL      (1 << 21)
 119
 120#define PL181_STATUS_TX_FIFO (PL181_STATUS_TXACTIVE \
 121                             |PL181_STATUS_TXFIFOHALFEMPTY \
 122                             |PL181_STATUS_TXFIFOFULL \
 123                             |PL181_STATUS_TXFIFOEMPTY \
 124                             |PL181_STATUS_TXDATAAVLBL)
 125#define PL181_STATUS_RX_FIFO (PL181_STATUS_RXACTIVE \
 126                             |PL181_STATUS_RXFIFOHALFFULL \
 127                             |PL181_STATUS_RXFIFOFULL \
 128                             |PL181_STATUS_RXFIFOEMPTY \
 129                             |PL181_STATUS_RXDATAAVLBL)
 130
 131static const unsigned char pl181_id[] =
 132{ 0x81, 0x11, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
 133
 134static void pl181_update(PL181State *s)
 135{
 136    int i;
 137    for (i = 0; i < 2; i++) {
 138        qemu_set_irq(s->irq[i], (s->status & s->mask[i]) != 0);
 139    }
 140}
 141
 142static void pl181_fifo_push(PL181State *s, uint32_t value)
 143{
 144    int n;
 145
 146    if (s->fifo_len == PL181_FIFO_LEN) {
 147        fprintf(stderr, "pl181: FIFO overflow\n");
 148        return;
 149    }
 150    n = (s->fifo_pos + s->fifo_len) & (PL181_FIFO_LEN - 1);
 151    s->fifo_len++;
 152    s->fifo[n] = value;
 153    DPRINTF("FIFO push %08x\n", (int)value);
 154}
 155
 156static uint32_t pl181_fifo_pop(PL181State *s)
 157{
 158    uint32_t value;
 159
 160    if (s->fifo_len == 0) {
 161        fprintf(stderr, "pl181: FIFO underflow\n");
 162        return 0;
 163    }
 164    value = s->fifo[s->fifo_pos];
 165    s->fifo_len--;
 166    s->fifo_pos = (s->fifo_pos + 1) & (PL181_FIFO_LEN - 1);
 167    DPRINTF("FIFO pop %08x\n", (int)value);
 168    return value;
 169}
 170
 171static void pl181_send_command(PL181State *s)
 172{
 173    SDRequest request;
 174    uint8_t response[16];
 175    int rlen;
 176
 177    request.cmd = s->cmd & PL181_CMD_INDEX;
 178    request.arg = s->cmdarg;
 179    DPRINTF("Command %d %08x\n", request.cmd, request.arg);
 180    rlen = sd_do_command(s->card, &request, response);
 181    if (rlen < 0)
 182        goto error;
 183    if (s->cmd & PL181_CMD_RESPONSE) {
 184#define RWORD(n) (((uint32_t)response[n] << 24) | (response[n + 1] << 16) \
 185                  | (response[n + 2] << 8) | response[n + 3])
 186        if (rlen == 0 || (rlen == 4 && (s->cmd & PL181_CMD_LONGRESP)))
 187            goto error;
 188        if (rlen != 4 && rlen != 16)
 189            goto error;
 190        s->response[0] = RWORD(0);
 191        if (rlen == 4) {
 192            s->response[1] = s->response[2] = s->response[3] = 0;
 193        } else {
 194            s->response[1] = RWORD(4);
 195            s->response[2] = RWORD(8);
 196            s->response[3] = RWORD(12) & ~1;
 197        }
 198        DPRINTF("Response received\n");
 199        s->status |= PL181_STATUS_CMDRESPEND;
 200#undef RWORD
 201    } else {
 202        DPRINTF("Command sent\n");
 203        s->status |= PL181_STATUS_CMDSENT;
 204    }
 205    return;
 206
 207error:
 208    DPRINTF("Timeout\n");
 209    s->status |= PL181_STATUS_CMDTIMEOUT;
 210}
 211
 212/* Transfer data between the card and the FIFO.  This is complicated by
 213   the FIFO holding 32-bit words and the card taking data in single byte
 214   chunks.  FIFO bytes are transferred in little-endian order.  */
 215
 216static void pl181_fifo_run(PL181State *s)
 217{
 218    uint32_t bits;
 219    uint32_t value = 0;
 220    int n;
 221    int is_read;
 222
 223    is_read = (s->datactrl & PL181_DATA_DIRECTION) != 0;
 224    if (s->datacnt != 0 && (!is_read || sd_data_ready(s->card))
 225            && !s->linux_hack) {
 226        if (is_read) {
 227            n = 0;
 228            while (s->datacnt && s->fifo_len < PL181_FIFO_LEN) {
 229                value |= (uint32_t)sd_read_data(s->card) << (n * 8);
 230                s->datacnt--;
 231                n++;
 232                if (n == 4) {
 233                    pl181_fifo_push(s, value);
 234                    n = 0;
 235                    value = 0;
 236                }
 237            }
 238            if (n != 0) {
 239                pl181_fifo_push(s, value);
 240            }
 241        } else { /* write */
 242            n = 0;
 243            while (s->datacnt > 0 && (s->fifo_len > 0 || n > 0)) {
 244                if (n == 0) {
 245                    value = pl181_fifo_pop(s);
 246                    n = 4;
 247                }
 248                n--;
 249                s->datacnt--;
 250                sd_write_data(s->card, value & 0xff);
 251                value >>= 8;
 252            }
 253        }
 254    }
 255    s->status &= ~(PL181_STATUS_RX_FIFO | PL181_STATUS_TX_FIFO);
 256    if (s->datacnt == 0) {
 257        s->status |= PL181_STATUS_DATAEND;
 258        /* HACK: */
 259        s->status |= PL181_STATUS_DATABLOCKEND;
 260        DPRINTF("Transfer Complete\n");
 261    }
 262    if (s->datacnt == 0 && s->fifo_len == 0) {
 263        s->datactrl &= ~PL181_DATA_ENABLE;
 264        DPRINTF("Data engine idle\n");
 265    } else {
 266        /* Update FIFO bits.  */
 267        bits = PL181_STATUS_TXACTIVE | PL181_STATUS_RXACTIVE;
 268        if (s->fifo_len == 0) {
 269            bits |= PL181_STATUS_TXFIFOEMPTY;
 270            bits |= PL181_STATUS_RXFIFOEMPTY;
 271        } else {
 272            bits |= PL181_STATUS_TXDATAAVLBL;
 273            bits |= PL181_STATUS_RXDATAAVLBL;
 274        }
 275        if (s->fifo_len == 16) {
 276            bits |= PL181_STATUS_TXFIFOFULL;
 277            bits |= PL181_STATUS_RXFIFOFULL;
 278        }
 279        if (s->fifo_len <= 8) {
 280            bits |= PL181_STATUS_TXFIFOHALFEMPTY;
 281        }
 282        if (s->fifo_len >= 8) {
 283            bits |= PL181_STATUS_RXFIFOHALFFULL;
 284        }
 285        if (s->datactrl & PL181_DATA_DIRECTION) {
 286            bits &= PL181_STATUS_RX_FIFO;
 287        } else {
 288            bits &= PL181_STATUS_TX_FIFO;
 289        }
 290        s->status |= bits;
 291    }
 292}
 293
 294static uint64_t pl181_read(void *opaque, hwaddr offset,
 295                           unsigned size)
 296{
 297    PL181State *s = (PL181State *)opaque;
 298    uint32_t tmp;
 299
 300    if (offset >= 0xfe0 && offset < 0x1000) {
 301        return pl181_id[(offset - 0xfe0) >> 2];
 302    }
 303    switch (offset) {
 304    case 0x00: /* Power */
 305        return s->power;
 306    case 0x04: /* Clock */
 307        return s->clock;
 308    case 0x08: /* Argument */
 309        return s->cmdarg;
 310    case 0x0c: /* Command */
 311        return s->cmd;
 312    case 0x10: /* RespCmd */
 313        return s->respcmd;
 314    case 0x14: /* Response0 */
 315        return s->response[0];
 316    case 0x18: /* Response1 */
 317        return s->response[1];
 318    case 0x1c: /* Response2 */
 319        return s->response[2];
 320    case 0x20: /* Response3 */
 321        return s->response[3];
 322    case 0x24: /* DataTimer */
 323        return s->datatimer;
 324    case 0x28: /* DataLength */
 325        return s->datalength;
 326    case 0x2c: /* DataCtrl */
 327        return s->datactrl;
 328    case 0x30: /* DataCnt */
 329        return s->datacnt;
 330    case 0x34: /* Status */
 331        tmp = s->status;
 332        if (s->linux_hack) {
 333            s->linux_hack = 0;
 334            pl181_fifo_run(s);
 335            pl181_update(s);
 336        }
 337        return tmp;
 338    case 0x3c: /* Mask0 */
 339        return s->mask[0];
 340    case 0x40: /* Mask1 */
 341        return s->mask[1];
 342    case 0x48: /* FifoCnt */
 343        /* The documentation is somewhat vague about exactly what FifoCnt
 344           does.  On real hardware it appears to be when decrememnted
 345           when a word is transferred between the FIFO and the serial
 346           data engine.  DataCnt is decremented after each byte is
 347           transferred between the serial engine and the card.
 348           We don't emulate this level of detail, so both can be the same.  */
 349        tmp = (s->datacnt + 3) >> 2;
 350        if (s->linux_hack) {
 351            s->linux_hack = 0;
 352            pl181_fifo_run(s);
 353            pl181_update(s);
 354        }
 355        return tmp;
 356    case 0x80: case 0x84: case 0x88: case 0x8c: /* FifoData */
 357    case 0x90: case 0x94: case 0x98: case 0x9c:
 358    case 0xa0: case 0xa4: case 0xa8: case 0xac:
 359    case 0xb0: case 0xb4: case 0xb8: case 0xbc:
 360        if (s->fifo_len == 0) {
 361            qemu_log_mask(LOG_GUEST_ERROR, "pl181: Unexpected FIFO read\n");
 362            return 0;
 363        } else {
 364            uint32_t value;
 365            value = pl181_fifo_pop(s);
 366            s->linux_hack = 1;
 367            pl181_fifo_run(s);
 368            pl181_update(s);
 369            return value;
 370        }
 371    default:
 372        qemu_log_mask(LOG_GUEST_ERROR,
 373                      "pl181_read: Bad offset %x\n", (int)offset);
 374        return 0;
 375    }
 376}
 377
 378static void pl181_write(void *opaque, hwaddr offset,
 379                        uint64_t value, unsigned size)
 380{
 381    PL181State *s = (PL181State *)opaque;
 382
 383    switch (offset) {
 384    case 0x00: /* Power */
 385        s->power = value & 0xff;
 386        break;
 387    case 0x04: /* Clock */
 388        s->clock = value & 0xff;
 389        break;
 390    case 0x08: /* Argument */
 391        s->cmdarg = value;
 392        break;
 393    case 0x0c: /* Command */
 394        s->cmd = value;
 395        if (s->cmd & PL181_CMD_ENABLE) {
 396            if (s->cmd & PL181_CMD_INTERRUPT) {
 397                qemu_log_mask(LOG_UNIMP,
 398                              "pl181: Interrupt mode not implemented\n");
 399            } if (s->cmd & PL181_CMD_PENDING) {
 400                qemu_log_mask(LOG_UNIMP,
 401                              "pl181: Pending commands not implemented\n");
 402            } else {
 403                pl181_send_command(s);
 404                pl181_fifo_run(s);
 405            }
 406            /* The command has completed one way or the other.  */
 407            s->cmd &= ~PL181_CMD_ENABLE;
 408        }
 409        break;
 410    case 0x24: /* DataTimer */
 411        s->datatimer = value;
 412        break;
 413    case 0x28: /* DataLength */
 414        s->datalength = value & 0xffff;
 415        break;
 416    case 0x2c: /* DataCtrl */
 417        s->datactrl = value & 0xff;
 418        if (value & PL181_DATA_ENABLE) {
 419            s->datacnt = s->datalength;
 420            pl181_fifo_run(s);
 421        }
 422        break;
 423    case 0x38: /* Clear */
 424        s->status &= ~(value & 0x7ff);
 425        break;
 426    case 0x3c: /* Mask0 */
 427        s->mask[0] = value;
 428        break;
 429    case 0x40: /* Mask1 */
 430        s->mask[1] = value;
 431        break;
 432    case 0x80: case 0x84: case 0x88: case 0x8c: /* FifoData */
 433    case 0x90: case 0x94: case 0x98: case 0x9c:
 434    case 0xa0: case 0xa4: case 0xa8: case 0xac:
 435    case 0xb0: case 0xb4: case 0xb8: case 0xbc:
 436        if (s->datacnt == 0) {
 437            qemu_log_mask(LOG_GUEST_ERROR, "pl181: Unexpected FIFO write\n");
 438        } else {
 439            pl181_fifo_push(s, value);
 440            pl181_fifo_run(s);
 441        }
 442        break;
 443    default:
 444        qemu_log_mask(LOG_GUEST_ERROR,
 445                      "pl181_write: Bad offset %x\n", (int)offset);
 446    }
 447    pl181_update(s);
 448}
 449
 450static const MemoryRegionOps pl181_ops = {
 451    .read = pl181_read,
 452    .write = pl181_write,
 453    .endianness = DEVICE_NATIVE_ENDIAN,
 454};
 455
 456static void pl181_reset(DeviceState *d)
 457{
 458    PL181State *s = PL181(d);
 459
 460    s->power = 0;
 461    s->cmdarg = 0;
 462    s->cmd = 0;
 463    s->datatimer = 0;
 464    s->datalength = 0;
 465    s->respcmd = 0;
 466    s->response[0] = 0;
 467    s->response[1] = 0;
 468    s->response[2] = 0;
 469    s->response[3] = 0;
 470    s->datatimer = 0;
 471    s->datalength = 0;
 472    s->datactrl = 0;
 473    s->datacnt = 0;
 474    s->status = 0;
 475    s->linux_hack = 0;
 476    s->mask[0] = 0;
 477    s->mask[1] = 0;
 478
 479    /* We can assume our GPIO outputs have been wired up now */
 480    sd_set_cb(s->card, s->cardstatus[0], s->cardstatus[1]);
 481}
 482
 483static int pl181_init(SysBusDevice *sbd)
 484{
 485    DeviceState *dev = DEVICE(sbd);
 486    PL181State *s = PL181(dev);
 487    DriveInfo *dinfo;
 488
 489    memory_region_init_io(&s->iomem, OBJECT(s), &pl181_ops, s, "pl181", 0x1000);
 490    sysbus_init_mmio(sbd, &s->iomem);
 491    sysbus_init_irq(sbd, &s->irq[0]);
 492    sysbus_init_irq(sbd, &s->irq[1]);
 493    qdev_init_gpio_out(dev, s->cardstatus, 2);
 494    /* FIXME use a qdev drive property instead of drive_get_next() */
 495    dinfo = drive_get_next(IF_SD);
 496    s->card = sd_init(dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, false);
 497    if (s->card == NULL) {
 498        return -1;
 499    }
 500
 501    return 0;
 502}
 503
 504static void pl181_class_init(ObjectClass *klass, void *data)
 505{
 506    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
 507    DeviceClass *k = DEVICE_CLASS(klass);
 508
 509    sdc->init = pl181_init;
 510    k->vmsd = &vmstate_pl181;
 511    k->reset = pl181_reset;
 512    /* Reason: init() method uses drive_get_next() */
 513    k->cannot_instantiate_with_device_add_yet = true;
 514}
 515
 516static const TypeInfo pl181_info = {
 517    .name          = TYPE_PL181,
 518    .parent        = TYPE_SYS_BUS_DEVICE,
 519    .instance_size = sizeof(PL181State),
 520    .class_init    = pl181_class_init,
 521};
 522
 523static void pl181_register_types(void)
 524{
 525    type_register_static(&pl181_info);
 526}
 527
 528type_init(pl181_register_types)
 529