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