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