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