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#include "qemu/log.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#define RWORD(n) (((uint32_t)response[n] << 24) | (response[n + 1] << 16) \
 187                  | (response[n + 2] << 8) | response[n + 3])
 188        if (rlen == 0 || (rlen == 4 && (s->cmd & PL181_CMD_LONGRESP)))
 189            goto error;
 190        if (rlen != 4 && rlen != 16)
 191            goto error;
 192        s->response[0] = RWORD(0);
 193        if (rlen == 4) {
 194            s->response[1] = s->response[2] = s->response[3] = 0;
 195        } else {
 196            s->response[1] = RWORD(4);
 197            s->response[2] = RWORD(8);
 198            s->response[3] = RWORD(12) & ~1;
 199        }
 200        DPRINTF("Response received\n");
 201        s->status |= PL181_STATUS_CMDRESPEND;
 202#undef RWORD
 203    } else {
 204        DPRINTF("Command sent\n");
 205        s->status |= PL181_STATUS_CMDSENT;
 206    }
 207    return;
 208
 209error:
 210    DPRINTF("Timeout\n");
 211    s->status |= PL181_STATUS_CMDTIMEOUT;
 212}
 213
 214/* Transfer data between the card and the FIFO.  This is complicated by
 215   the FIFO holding 32-bit words and the card taking data in single byte
 216   chunks.  FIFO bytes are transferred in little-endian order.  */
 217
 218static void pl181_fifo_run(PL181State *s)
 219{
 220    uint32_t bits;
 221    uint32_t value = 0;
 222    int n;
 223    int is_read;
 224
 225    is_read = (s->datactrl & PL181_DATA_DIRECTION) != 0;
 226    if (s->datacnt != 0 && (!is_read || sd_data_ready(s->card))
 227            && !s->linux_hack) {
 228        if (is_read) {
 229            n = 0;
 230            while (s->datacnt && s->fifo_len < PL181_FIFO_LEN) {
 231                value |= (uint32_t)sd_read_data(s->card) << (n * 8);
 232                s->datacnt--;
 233                n++;
 234                if (n == 4) {
 235                    pl181_fifo_push(s, value);
 236                    n = 0;
 237                    value = 0;
 238                }
 239            }
 240            if (n != 0) {
 241                pl181_fifo_push(s, value);
 242            }
 243        } else { /* write */
 244            n = 0;
 245            while (s->datacnt > 0 && (s->fifo_len > 0 || n > 0)) {
 246                if (n == 0) {
 247                    value = pl181_fifo_pop(s);
 248                    n = 4;
 249                }
 250                n--;
 251                s->datacnt--;
 252                sd_write_data(s->card, value & 0xff);
 253                value >>= 8;
 254            }
 255        }
 256    }
 257    s->status &= ~(PL181_STATUS_RX_FIFO | PL181_STATUS_TX_FIFO);
 258    if (s->datacnt == 0) {
 259        s->status |= PL181_STATUS_DATAEND;
 260        /* HACK: */
 261        s->status |= PL181_STATUS_DATABLOCKEND;
 262        DPRINTF("Transfer Complete\n");
 263    }
 264    if (s->datacnt == 0 && s->fifo_len == 0) {
 265        s->datactrl &= ~PL181_DATA_ENABLE;
 266        DPRINTF("Data engine idle\n");
 267    } else {
 268        /* Update FIFO bits.  */
 269        bits = PL181_STATUS_TXACTIVE | PL181_STATUS_RXACTIVE;
 270        if (s->fifo_len == 0) {
 271            bits |= PL181_STATUS_TXFIFOEMPTY;
 272            bits |= PL181_STATUS_RXFIFOEMPTY;
 273        } else {
 274            bits |= PL181_STATUS_TXDATAAVLBL;
 275            bits |= PL181_STATUS_RXDATAAVLBL;
 276        }
 277        if (s->fifo_len == 16) {
 278            bits |= PL181_STATUS_TXFIFOFULL;
 279            bits |= PL181_STATUS_RXFIFOFULL;
 280        }
 281        if (s->fifo_len <= 8) {
 282            bits |= PL181_STATUS_TXFIFOHALFEMPTY;
 283        }
 284        if (s->fifo_len >= 8) {
 285            bits |= PL181_STATUS_RXFIFOHALFFULL;
 286        }
 287        if (s->datactrl & PL181_DATA_DIRECTION) {
 288            bits &= PL181_STATUS_RX_FIFO;
 289        } else {
 290            bits &= PL181_STATUS_TX_FIFO;
 291        }
 292        s->status |= bits;
 293    }
 294}
 295
 296static uint64_t pl181_read(void *opaque, hwaddr offset,
 297                           unsigned size)
 298{
 299    PL181State *s = (PL181State *)opaque;
 300    uint32_t tmp;
 301
 302    if (offset >= 0xfe0 && offset < 0x1000) {
 303        return pl181_id[(offset - 0xfe0) >> 2];
 304    }
 305    switch (offset) {
 306    case 0x00: /* Power */
 307        return s->power;
 308    case 0x04: /* Clock */
 309        return s->clock;
 310    case 0x08: /* Argument */
 311        return s->cmdarg;
 312    case 0x0c: /* Command */
 313        return s->cmd;
 314    case 0x10: /* RespCmd */
 315        return s->respcmd;
 316    case 0x14: /* Response0 */
 317        return s->response[0];
 318    case 0x18: /* Response1 */
 319        return s->response[1];
 320    case 0x1c: /* Response2 */
 321        return s->response[2];
 322    case 0x20: /* Response3 */
 323        return s->response[3];
 324    case 0x24: /* DataTimer */
 325        return s->datatimer;
 326    case 0x28: /* DataLength */
 327        return s->datalength;
 328    case 0x2c: /* DataCtrl */
 329        return s->datactrl;
 330    case 0x30: /* DataCnt */
 331        return s->datacnt;
 332    case 0x34: /* Status */
 333        tmp = s->status;
 334        if (s->linux_hack) {
 335            s->linux_hack = 0;
 336            pl181_fifo_run(s);
 337            pl181_update(s);
 338        }
 339        return tmp;
 340    case 0x3c: /* Mask0 */
 341        return s->mask[0];
 342    case 0x40: /* Mask1 */
 343        return s->mask[1];
 344    case 0x48: /* FifoCnt */
 345        /* The documentation is somewhat vague about exactly what FifoCnt
 346           does.  On real hardware it appears to be when decrememnted
 347           when a word is transferred between the FIFO and the serial
 348           data engine.  DataCnt is decremented after each byte is
 349           transferred between the serial engine and the card.
 350           We don't emulate this level of detail, so both can be the same.  */
 351        tmp = (s->datacnt + 3) >> 2;
 352        if (s->linux_hack) {
 353            s->linux_hack = 0;
 354            pl181_fifo_run(s);
 355            pl181_update(s);
 356        }
 357        return tmp;
 358    case 0x80: case 0x84: case 0x88: case 0x8c: /* FifoData */
 359    case 0x90: case 0x94: case 0x98: case 0x9c:
 360    case 0xa0: case 0xa4: case 0xa8: case 0xac:
 361    case 0xb0: case 0xb4: case 0xb8: case 0xbc:
 362        if (s->fifo_len == 0) {
 363            qemu_log_mask(LOG_GUEST_ERROR, "pl181: Unexpected FIFO read\n");
 364            return 0;
 365        } else {
 366            uint32_t value;
 367            value = pl181_fifo_pop(s);
 368            s->linux_hack = 1;
 369            pl181_fifo_run(s);
 370            pl181_update(s);
 371            return value;
 372        }
 373    default:
 374        qemu_log_mask(LOG_GUEST_ERROR,
 375                      "pl181_read: Bad offset %x\n", (int)offset);
 376        return 0;
 377    }
 378}
 379
 380static void pl181_write(void *opaque, hwaddr offset,
 381                        uint64_t value, unsigned size)
 382{
 383    PL181State *s = (PL181State *)opaque;
 384
 385    switch (offset) {
 386    case 0x00: /* Power */
 387        s->power = value & 0xff;
 388        break;
 389    case 0x04: /* Clock */
 390        s->clock = value & 0xff;
 391        break;
 392    case 0x08: /* Argument */
 393        s->cmdarg = value;
 394        break;
 395    case 0x0c: /* Command */
 396        s->cmd = value;
 397        if (s->cmd & PL181_CMD_ENABLE) {
 398            if (s->cmd & PL181_CMD_INTERRUPT) {
 399                qemu_log_mask(LOG_UNIMP,
 400                              "pl181: Interrupt mode not implemented\n");
 401            } if (s->cmd & PL181_CMD_PENDING) {
 402                qemu_log_mask(LOG_UNIMP,
 403                              "pl181: Pending commands not implemented\n");
 404            } else {
 405                pl181_send_command(s);
 406                pl181_fifo_run(s);
 407            }
 408            /* The command has completed one way or the other.  */
 409            s->cmd &= ~PL181_CMD_ENABLE;
 410        }
 411        break;
 412    case 0x24: /* DataTimer */
 413        s->datatimer = value;
 414        break;
 415    case 0x28: /* DataLength */
 416        s->datalength = value & 0xffff;
 417        break;
 418    case 0x2c: /* DataCtrl */
 419        s->datactrl = value & 0xff;
 420        if (value & PL181_DATA_ENABLE) {
 421            s->datacnt = s->datalength;
 422            pl181_fifo_run(s);
 423        }
 424        break;
 425    case 0x38: /* Clear */
 426        s->status &= ~(value & 0x7ff);
 427        break;
 428    case 0x3c: /* Mask0 */
 429        s->mask[0] = value;
 430        break;
 431    case 0x40: /* Mask1 */
 432        s->mask[1] = value;
 433        break;
 434    case 0x80: case 0x84: case 0x88: case 0x8c: /* FifoData */
 435    case 0x90: case 0x94: case 0x98: case 0x9c:
 436    case 0xa0: case 0xa4: case 0xa8: case 0xac:
 437    case 0xb0: case 0xb4: case 0xb8: case 0xbc:
 438        if (s->datacnt == 0) {
 439            qemu_log_mask(LOG_GUEST_ERROR, "pl181: Unexpected FIFO write\n");
 440        } else {
 441            pl181_fifo_push(s, value);
 442            pl181_fifo_run(s);
 443        }
 444        break;
 445    default:
 446        qemu_log_mask(LOG_GUEST_ERROR,
 447                      "pl181_write: Bad offset %x\n", (int)offset);
 448    }
 449    pl181_update(s);
 450}
 451
 452static const MemoryRegionOps pl181_ops = {
 453    .read = pl181_read,
 454    .write = pl181_write,
 455    .endianness = DEVICE_NATIVE_ENDIAN,
 456};
 457
 458static void pl181_reset(DeviceState *d)
 459{
 460    PL181State *s = PL181(d);
 461
 462    s->power = 0;
 463    s->cmdarg = 0;
 464    s->cmd = 0;
 465    s->datatimer = 0;
 466    s->datalength = 0;
 467    s->respcmd = 0;
 468    s->response[0] = 0;
 469    s->response[1] = 0;
 470    s->response[2] = 0;
 471    s->response[3] = 0;
 472    s->datatimer = 0;
 473    s->datalength = 0;
 474    s->datactrl = 0;
 475    s->datacnt = 0;
 476    s->status = 0;
 477    s->linux_hack = 0;
 478    s->mask[0] = 0;
 479    s->mask[1] = 0;
 480
 481    /* We can assume our GPIO outputs have been wired up now */
 482    sd_set_cb(s->card, s->cardstatus[0], s->cardstatus[1]);
 483    /* Since we're still using the legacy SD API the card is not plugged
 484     * into any bus, and we must reset it manually.
 485     */
 486    device_reset(DEVICE(s->card));
 487}
 488
 489static void pl181_init(Object *obj)
 490{
 491    DeviceState *dev = DEVICE(obj);
 492    PL181State *s = PL181(obj);
 493    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 494
 495    memory_region_init_io(&s->iomem, obj, &pl181_ops, s, "pl181", 0x1000);
 496    sysbus_init_mmio(sbd, &s->iomem);
 497    sysbus_init_irq(sbd, &s->irq[0]);
 498    sysbus_init_irq(sbd, &s->irq[1]);
 499    qdev_init_gpio_out(dev, s->cardstatus, 2);
 500}
 501
 502static void pl181_realize(DeviceState *dev, Error **errp)
 503{
 504    PL181State *s = PL181(dev);
 505    DriveInfo *dinfo;
 506
 507    /* FIXME use a qdev drive property instead of drive_get_next() */
 508    dinfo = drive_get_next(IF_SD);
 509    s->card = sd_init(dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, false);
 510    if (s->card == NULL) {
 511        error_setg(errp, "sd_init failed");
 512    }
 513}
 514
 515static void pl181_class_init(ObjectClass *klass, void *data)
 516{
 517    DeviceClass *k = DEVICE_CLASS(klass);
 518
 519    k->vmsd = &vmstate_pl181;
 520    k->reset = pl181_reset;
 521    /* Reason: init() method uses drive_get_next() */
 522    k->user_creatable = false;
 523    k->realize = pl181_realize;
 524}
 525
 526static const TypeInfo pl181_info = {
 527    .name          = TYPE_PL181,
 528    .parent        = TYPE_SYS_BUS_DEVICE,
 529    .instance_size = sizeof(PL181State),
 530    .instance_init = pl181_init,
 531    .class_init    = pl181_class_init,
 532};
 533
 534static void pl181_register_types(void)
 535{
 536    type_register_static(&pl181_info);
 537}
 538
 539type_init(pl181_register_types)
 540