qemu/hw/sd/ssi-sd.c
<<
>>
Prefs
   1/*
   2 * SSI to SD card adapter.
   3 *
   4 * Copyright (c) 2007-2009 CodeSourcery.
   5 * Written by Paul Brook
   6 *
   7 * This code is licensed under the GNU GPL v2.
   8 *
   9 * Contributions after 2012-01-13 are licensed under the terms of the
  10 * GNU GPL, version 2 or (at your option) any later version.
  11 */
  12
  13#include "qemu/osdep.h"
  14#include "sysemu/blockdev.h"
  15#include "hw/ssi/ssi.h"
  16#include "hw/sd/sd.h"
  17#include "qapi/error.h"
  18
  19//#define DEBUG_SSI_SD 1
  20
  21#ifdef DEBUG_SSI_SD
  22#define DPRINTF(fmt, ...) \
  23do { printf("ssi_sd: " fmt , ## __VA_ARGS__); } while (0)
  24#define BADF(fmt, ...) \
  25do { fprintf(stderr, "ssi_sd: error: " fmt , ## __VA_ARGS__); exit(1);} while (0)
  26#else
  27#define DPRINTF(fmt, ...) do {} while(0)
  28#define BADF(fmt, ...) \
  29do { fprintf(stderr, "ssi_sd: error: " fmt , ## __VA_ARGS__);} while (0)
  30#endif
  31
  32typedef enum {
  33    SSI_SD_CMD = 0,
  34    SSI_SD_CMDARG,
  35    SSI_SD_RESPONSE,
  36    SSI_SD_DATA_START,
  37    SSI_SD_DATA_READ,
  38} ssi_sd_mode;
  39
  40typedef struct {
  41    SSISlave ssidev;
  42    uint32_t mode;
  43    int cmd;
  44    uint8_t cmdarg[4];
  45    uint8_t response[5];
  46    int32_t arglen;
  47    int32_t response_pos;
  48    int32_t stopping;
  49    SDBus sdbus;
  50} ssi_sd_state;
  51
  52#define TYPE_SSI_SD "ssi-sd"
  53#define SSI_SD(obj) OBJECT_CHECK(ssi_sd_state, (obj), TYPE_SSI_SD)
  54
  55/* State word bits.  */
  56#define SSI_SDR_LOCKED          0x0001
  57#define SSI_SDR_WP_ERASE        0x0002
  58#define SSI_SDR_ERROR           0x0004
  59#define SSI_SDR_CC_ERROR        0x0008
  60#define SSI_SDR_ECC_FAILED      0x0010
  61#define SSI_SDR_WP_VIOLATION    0x0020
  62#define SSI_SDR_ERASE_PARAM     0x0040
  63#define SSI_SDR_OUT_OF_RANGE    0x0080
  64#define SSI_SDR_IDLE            0x0100
  65#define SSI_SDR_ERASE_RESET     0x0200
  66#define SSI_SDR_ILLEGAL_COMMAND 0x0400
  67#define SSI_SDR_COM_CRC_ERROR   0x0800
  68#define SSI_SDR_ERASE_SEQ_ERROR 0x1000
  69#define SSI_SDR_ADDRESS_ERROR   0x2000
  70#define SSI_SDR_PARAMETER_ERROR 0x4000
  71
  72static uint32_t ssi_sd_transfer(SSISlave *dev, uint32_t val)
  73{
  74    ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, dev);
  75
  76    /* Special case: allow CMD12 (STOP TRANSMISSION) while reading data.  */
  77    if (s->mode == SSI_SD_DATA_READ && val == 0x4d) {
  78        s->mode = SSI_SD_CMD;
  79        /* There must be at least one byte delay before the card responds.  */
  80        s->stopping = 1;
  81    }
  82
  83    switch (s->mode) {
  84    case SSI_SD_CMD:
  85        if (val == 0xff) {
  86            DPRINTF("NULL command\n");
  87            return 0xff;
  88        }
  89        s->cmd = val & 0x3f;
  90        s->mode = SSI_SD_CMDARG;
  91        s->arglen = 0;
  92        return 0xff;
  93    case SSI_SD_CMDARG:
  94        if (s->arglen == 4) {
  95            SDRequest request;
  96            uint8_t longresp[16];
  97            /* FIXME: Check CRC.  */
  98            request.cmd = s->cmd;
  99            request.arg = ldl_be_p(s->cmdarg);
 100            DPRINTF("CMD%d arg 0x%08x\n", s->cmd, request.arg);
 101            s->arglen = sdbus_do_command(&s->sdbus, &request, longresp);
 102            if (s->arglen <= 0) {
 103                s->arglen = 1;
 104                s->response[0] = 4;
 105                DPRINTF("SD command failed\n");
 106            } else if (s->cmd == 58) {
 107                /* CMD58 returns R3 response (OCR)  */
 108                DPRINTF("Returned OCR\n");
 109                s->arglen = 5;
 110                s->response[0] = 1;
 111                memcpy(&s->response[1], longresp, 4);
 112            } else if (s->arglen != 4) {
 113                BADF("Unexpected response to cmd %d\n", s->cmd);
 114                /* Illegal command is about as near as we can get.  */
 115                s->arglen = 1;
 116                s->response[0] = 4;
 117            } else {
 118                /* All other commands return status.  */
 119                uint32_t cardstatus;
 120                uint16_t status;
 121                /* CMD13 returns a 2-byte statuse work. Other commands
 122                   only return the first byte.  */
 123                s->arglen = (s->cmd == 13) ? 2 : 1;
 124                cardstatus = ldl_be_p(longresp);
 125                status = 0;
 126                if (((cardstatus >> 9) & 0xf) < 4)
 127                    status |= SSI_SDR_IDLE;
 128                if (cardstatus & ERASE_RESET)
 129                    status |= SSI_SDR_ERASE_RESET;
 130                if (cardstatus & ILLEGAL_COMMAND)
 131                    status |= SSI_SDR_ILLEGAL_COMMAND;
 132                if (cardstatus & COM_CRC_ERROR)
 133                    status |= SSI_SDR_COM_CRC_ERROR;
 134                if (cardstatus & ERASE_SEQ_ERROR)
 135                    status |= SSI_SDR_ERASE_SEQ_ERROR;
 136                if (cardstatus & ADDRESS_ERROR)
 137                    status |= SSI_SDR_ADDRESS_ERROR;
 138                if (cardstatus & CARD_IS_LOCKED)
 139                    status |= SSI_SDR_LOCKED;
 140                if (cardstatus & (LOCK_UNLOCK_FAILED | WP_ERASE_SKIP))
 141                    status |= SSI_SDR_WP_ERASE;
 142                if (cardstatus & SD_ERROR)
 143                    status |= SSI_SDR_ERROR;
 144                if (cardstatus & CC_ERROR)
 145                    status |= SSI_SDR_CC_ERROR;
 146                if (cardstatus & CARD_ECC_FAILED)
 147                    status |= SSI_SDR_ECC_FAILED;
 148                if (cardstatus & WP_VIOLATION)
 149                    status |= SSI_SDR_WP_VIOLATION;
 150                if (cardstatus & ERASE_PARAM)
 151                    status |= SSI_SDR_ERASE_PARAM;
 152                if (cardstatus & (OUT_OF_RANGE | CID_CSD_OVERWRITE))
 153                    status |= SSI_SDR_OUT_OF_RANGE;
 154                /* ??? Don't know what Parameter Error really means, so
 155                   assume it's set if the second byte is nonzero.  */
 156                if (status & 0xff)
 157                    status |= SSI_SDR_PARAMETER_ERROR;
 158                s->response[0] = status >> 8;
 159                s->response[1] = status;
 160                DPRINTF("Card status 0x%02x\n", status);
 161            }
 162            s->mode = SSI_SD_RESPONSE;
 163            s->response_pos = 0;
 164        } else {
 165            s->cmdarg[s->arglen++] = val;
 166        }
 167        return 0xff;
 168    case SSI_SD_RESPONSE:
 169        if (s->stopping) {
 170            s->stopping = 0;
 171            return 0xff;
 172        }
 173        if (s->response_pos < s->arglen) {
 174            DPRINTF("Response 0x%02x\n", s->response[s->response_pos]);
 175            return s->response[s->response_pos++];
 176        }
 177        if (sdbus_data_ready(&s->sdbus)) {
 178            DPRINTF("Data read\n");
 179            s->mode = SSI_SD_DATA_START;
 180        } else {
 181            DPRINTF("End of command\n");
 182            s->mode = SSI_SD_CMD;
 183        }
 184        return 0xff;
 185    case SSI_SD_DATA_START:
 186        DPRINTF("Start read block\n");
 187        s->mode = SSI_SD_DATA_READ;
 188        return 0xfe;
 189    case SSI_SD_DATA_READ:
 190        val = sdbus_read_data(&s->sdbus);
 191        if (!sdbus_data_ready(&s->sdbus)) {
 192            DPRINTF("Data read end\n");
 193            s->mode = SSI_SD_CMD;
 194        }
 195        return val;
 196    }
 197    /* Should never happen.  */
 198    return 0xff;
 199}
 200
 201static int ssi_sd_post_load(void *opaque, int version_id)
 202{
 203    ssi_sd_state *s = (ssi_sd_state *)opaque;
 204
 205    if (s->mode > SSI_SD_DATA_READ) {
 206        return -EINVAL;
 207    }
 208    if (s->mode == SSI_SD_CMDARG &&
 209        (s->arglen < 0 || s->arglen >= ARRAY_SIZE(s->cmdarg))) {
 210        return -EINVAL;
 211    }
 212    if (s->mode == SSI_SD_RESPONSE &&
 213        (s->response_pos < 0 || s->response_pos >= ARRAY_SIZE(s->response) ||
 214        (!s->stopping && s->arglen > ARRAY_SIZE(s->response)))) {
 215        return -EINVAL;
 216    }
 217
 218    return 0;
 219}
 220
 221static const VMStateDescription vmstate_ssi_sd = {
 222    .name = "ssi_sd",
 223    .version_id = 2,
 224    .minimum_version_id = 2,
 225    .post_load = ssi_sd_post_load,
 226    .fields = (VMStateField []) {
 227        VMSTATE_UINT32(mode, ssi_sd_state),
 228        VMSTATE_INT32(cmd, ssi_sd_state),
 229        VMSTATE_UINT8_ARRAY(cmdarg, ssi_sd_state, 4),
 230        VMSTATE_UINT8_ARRAY(response, ssi_sd_state, 5),
 231        VMSTATE_INT32(arglen, ssi_sd_state),
 232        VMSTATE_INT32(response_pos, ssi_sd_state),
 233        VMSTATE_INT32(stopping, ssi_sd_state),
 234        VMSTATE_SSI_SLAVE(ssidev, ssi_sd_state),
 235        VMSTATE_END_OF_LIST()
 236    }
 237};
 238
 239static void ssi_sd_realize(SSISlave *d, Error **errp)
 240{
 241    ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, d);
 242    DeviceState *carddev;
 243    DriveInfo *dinfo;
 244    Error *err = NULL;
 245
 246    qbus_create_inplace(&s->sdbus, sizeof(s->sdbus), TYPE_SD_BUS,
 247                        DEVICE(d), "sd-bus");
 248
 249    /* Create and plug in the sd card */
 250    /* FIXME use a qdev drive property instead of drive_get_next() */
 251    dinfo = drive_get_next(IF_SD);
 252    carddev = qdev_create(&s->sdbus.qbus, TYPE_SD_CARD);
 253    if (dinfo) {
 254        qdev_prop_set_drive(carddev, "drive", blk_by_legacy_dinfo(dinfo), &err);
 255    }
 256    object_property_set_bool(OBJECT(carddev), true, "spi", &err);
 257    object_property_set_bool(OBJECT(carddev), true, "realized", &err);
 258    if (err) {
 259        error_setg(errp, "failed to init SD card: %s", error_get_pretty(err));
 260        return;
 261    }
 262}
 263
 264static void ssi_sd_reset(DeviceState *dev)
 265{
 266    ssi_sd_state *s = SSI_SD(dev);
 267
 268    s->mode = SSI_SD_CMD;
 269    s->cmd = 0;
 270    memset(s->cmdarg, 0, sizeof(s->cmdarg));
 271    memset(s->response, 0, sizeof(s->response));
 272    s->arglen = 0;
 273    s->response_pos = 0;
 274    s->stopping = 0;
 275}
 276
 277static void ssi_sd_class_init(ObjectClass *klass, void *data)
 278{
 279    DeviceClass *dc = DEVICE_CLASS(klass);
 280    SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
 281
 282    k->realize = ssi_sd_realize;
 283    k->transfer = ssi_sd_transfer;
 284    k->cs_polarity = SSI_CS_LOW;
 285    dc->vmsd = &vmstate_ssi_sd;
 286    dc->reset = ssi_sd_reset;
 287    /* Reason: init() method uses drive_get_next() */
 288    dc->user_creatable = false;
 289}
 290
 291static const TypeInfo ssi_sd_info = {
 292    .name          = TYPE_SSI_SD,
 293    .parent        = TYPE_SSI_SLAVE,
 294    .instance_size = sizeof(ssi_sd_state),
 295    .class_init    = ssi_sd_class_init,
 296};
 297
 298static void ssi_sd_register_types(void)
 299{
 300    type_register_static(&ssi_sd_info);
 301}
 302
 303type_init(ssi_sd_register_types)
 304