ssi-sd.c (14242B)
1/* 2 * SSI to SD card adapter. 3 * 4 * Copyright (c) 2007-2009 CodeSourcery. 5 * Written by Paul Brook 6 * 7 * Copyright (c) 2021 Wind River Systems, Inc. 8 * Improved by Bin Meng <bin.meng@windriver.com> 9 * 10 * Validated with U-Boot v2021.01 and Linux v5.10 mmc_spi driver 11 * 12 * This code is licensed under the GNU GPL v2. 13 * 14 * Contributions after 2012-01-13 are licensed under the terms of the 15 * GNU GPL, version 2 or (at your option) any later version. 16 */ 17 18#include "qemu/osdep.h" 19#include "sysemu/blockdev.h" 20#include "hw/ssi/ssi.h" 21#include "migration/vmstate.h" 22#include "hw/qdev-properties.h" 23#include "hw/sd/sd.h" 24#include "qapi/error.h" 25#include "qemu/crc-ccitt.h" 26#include "qemu/module.h" 27#include "qom/object.h" 28 29//#define DEBUG_SSI_SD 1 30 31#ifdef DEBUG_SSI_SD 32#define DPRINTF(fmt, ...) \ 33do { printf("ssi_sd: " fmt , ## __VA_ARGS__); } while (0) 34#define BADF(fmt, ...) \ 35do { fprintf(stderr, "ssi_sd: error: " fmt , ## __VA_ARGS__); exit(1);} while (0) 36#else 37#define DPRINTF(fmt, ...) do {} while(0) 38#define BADF(fmt, ...) \ 39do { fprintf(stderr, "ssi_sd: error: " fmt , ## __VA_ARGS__);} while (0) 40#endif 41 42typedef enum { 43 SSI_SD_CMD = 0, 44 SSI_SD_CMDARG, 45 SSI_SD_PREP_RESP, 46 SSI_SD_RESPONSE, 47 SSI_SD_PREP_DATA, 48 SSI_SD_DATA_START, 49 SSI_SD_DATA_READ, 50 SSI_SD_DATA_CRC16, 51 SSI_SD_DATA_WRITE, 52 SSI_SD_SKIP_CRC16, 53} ssi_sd_mode; 54 55struct ssi_sd_state { 56 SSIPeripheral ssidev; 57 uint32_t mode; 58 int cmd; 59 uint8_t cmdarg[4]; 60 uint8_t response[5]; 61 uint16_t crc16; 62 int32_t read_bytes; 63 int32_t write_bytes; 64 int32_t arglen; 65 int32_t response_pos; 66 int32_t stopping; 67 SDBus sdbus; 68}; 69 70#define TYPE_SSI_SD "ssi-sd" 71OBJECT_DECLARE_SIMPLE_TYPE(ssi_sd_state, SSI_SD) 72 73/* State word bits. */ 74#define SSI_SDR_LOCKED 0x0001 75#define SSI_SDR_WP_ERASE 0x0002 76#define SSI_SDR_ERROR 0x0004 77#define SSI_SDR_CC_ERROR 0x0008 78#define SSI_SDR_ECC_FAILED 0x0010 79#define SSI_SDR_WP_VIOLATION 0x0020 80#define SSI_SDR_ERASE_PARAM 0x0040 81#define SSI_SDR_OUT_OF_RANGE 0x0080 82#define SSI_SDR_IDLE 0x0100 83#define SSI_SDR_ERASE_RESET 0x0200 84#define SSI_SDR_ILLEGAL_COMMAND 0x0400 85#define SSI_SDR_COM_CRC_ERROR 0x0800 86#define SSI_SDR_ERASE_SEQ_ERROR 0x1000 87#define SSI_SDR_ADDRESS_ERROR 0x2000 88#define SSI_SDR_PARAMETER_ERROR 0x4000 89 90/* multiple block write */ 91#define SSI_TOKEN_MULTI_WRITE 0xfc 92/* terminate multiple block write */ 93#define SSI_TOKEN_STOP_TRAN 0xfd 94/* single block read/write, multiple block read */ 95#define SSI_TOKEN_SINGLE 0xfe 96 97/* dummy value - don't care */ 98#define SSI_DUMMY 0xff 99 100/* data accepted */ 101#define DATA_RESPONSE_ACCEPTED 0x05 102 103static uint32_t ssi_sd_transfer(SSIPeripheral *dev, uint32_t val) 104{ 105 ssi_sd_state *s = SSI_SD(dev); 106 SDRequest request; 107 uint8_t longresp[16]; 108 109 /* 110 * Special case: allow CMD12 (STOP TRANSMISSION) while reading data. 111 * 112 * See "Physical Layer Specification Version 8.00" chapter 7.5.2.2, 113 * to avoid conflict between CMD12 response and next data block, 114 * timing of CMD12 should be controlled as follows: 115 * 116 * - CMD12 issued at the timing that end bit of CMD12 and end bit of 117 * data block is overlapped 118 * - CMD12 issued after one clock cycle after host receives a token 119 * (either Start Block token or Data Error token) 120 * 121 * We need to catch CMD12 in all of the data read states. 122 */ 123 if (s->mode >= SSI_SD_PREP_DATA && s->mode <= SSI_SD_DATA_CRC16) { 124 if (val == 0x4c) { 125 s->mode = SSI_SD_CMD; 126 /* There must be at least one byte delay before the card responds */ 127 s->stopping = 1; 128 } 129 } 130 131 switch (s->mode) { 132 case SSI_SD_CMD: 133 switch (val) { 134 case SSI_DUMMY: 135 DPRINTF("NULL command\n"); 136 return SSI_DUMMY; 137 break; 138 case SSI_TOKEN_SINGLE: 139 case SSI_TOKEN_MULTI_WRITE: 140 DPRINTF("Start write block\n"); 141 s->mode = SSI_SD_DATA_WRITE; 142 return SSI_DUMMY; 143 case SSI_TOKEN_STOP_TRAN: 144 DPRINTF("Stop multiple write\n"); 145 146 /* manually issue cmd12 to stop the transfer */ 147 request.cmd = 12; 148 request.arg = 0; 149 s->arglen = sdbus_do_command(&s->sdbus, &request, longresp); 150 if (s->arglen <= 0) { 151 s->arglen = 1; 152 /* a zero value indicates the card is busy */ 153 s->response[0] = 0; 154 DPRINTF("SD card busy\n"); 155 } else { 156 s->arglen = 1; 157 /* a non-zero value indicates the card is ready */ 158 s->response[0] = SSI_DUMMY; 159 } 160 161 return SSI_DUMMY; 162 } 163 164 s->cmd = val & 0x3f; 165 s->mode = SSI_SD_CMDARG; 166 s->arglen = 0; 167 return SSI_DUMMY; 168 case SSI_SD_CMDARG: 169 if (s->arglen == 4) { 170 /* FIXME: Check CRC. */ 171 request.cmd = s->cmd; 172 request.arg = ldl_be_p(s->cmdarg); 173 DPRINTF("CMD%d arg 0x%08x\n", s->cmd, request.arg); 174 s->arglen = sdbus_do_command(&s->sdbus, &request, longresp); 175 if (s->arglen <= 0) { 176 s->arglen = 1; 177 s->response[0] = 4; 178 DPRINTF("SD command failed\n"); 179 } else if (s->cmd == 8 || s->cmd == 58) { 180 /* CMD8/CMD58 returns R3/R7 response */ 181 DPRINTF("Returned R3/R7\n"); 182 s->arglen = 5; 183 s->response[0] = 1; 184 memcpy(&s->response[1], longresp, 4); 185 } else if (s->arglen != 4) { 186 BADF("Unexpected response to cmd %d\n", s->cmd); 187 /* Illegal command is about as near as we can get. */ 188 s->arglen = 1; 189 s->response[0] = 4; 190 } else { 191 /* All other commands return status. */ 192 uint32_t cardstatus; 193 uint16_t status; 194 /* CMD13 returns a 2-byte statuse work. Other commands 195 only return the first byte. */ 196 s->arglen = (s->cmd == 13) ? 2 : 1; 197 198 /* handle R1b */ 199 if (s->cmd == 28 || s->cmd == 29 || s->cmd == 38) { 200 s->stopping = 1; 201 } 202 203 cardstatus = ldl_be_p(longresp); 204 status = 0; 205 if (((cardstatus >> 9) & 0xf) < 4) 206 status |= SSI_SDR_IDLE; 207 if (cardstatus & ERASE_RESET) 208 status |= SSI_SDR_ERASE_RESET; 209 if (cardstatus & ILLEGAL_COMMAND) 210 status |= SSI_SDR_ILLEGAL_COMMAND; 211 if (cardstatus & COM_CRC_ERROR) 212 status |= SSI_SDR_COM_CRC_ERROR; 213 if (cardstatus & ERASE_SEQ_ERROR) 214 status |= SSI_SDR_ERASE_SEQ_ERROR; 215 if (cardstatus & ADDRESS_ERROR) 216 status |= SSI_SDR_ADDRESS_ERROR; 217 if (cardstatus & CARD_IS_LOCKED) 218 status |= SSI_SDR_LOCKED; 219 if (cardstatus & (LOCK_UNLOCK_FAILED | WP_ERASE_SKIP)) 220 status |= SSI_SDR_WP_ERASE; 221 if (cardstatus & SD_ERROR) 222 status |= SSI_SDR_ERROR; 223 if (cardstatus & CC_ERROR) 224 status |= SSI_SDR_CC_ERROR; 225 if (cardstatus & CARD_ECC_FAILED) 226 status |= SSI_SDR_ECC_FAILED; 227 if (cardstatus & WP_VIOLATION) 228 status |= SSI_SDR_WP_VIOLATION; 229 if (cardstatus & ERASE_PARAM) 230 status |= SSI_SDR_ERASE_PARAM; 231 if (cardstatus & (OUT_OF_RANGE | CID_CSD_OVERWRITE)) 232 status |= SSI_SDR_OUT_OF_RANGE; 233 /* ??? Don't know what Parameter Error really means, so 234 assume it's set if the second byte is nonzero. */ 235 if (status & 0xff) 236 status |= SSI_SDR_PARAMETER_ERROR; 237 s->response[0] = status >> 8; 238 s->response[1] = status; 239 DPRINTF("Card status 0x%02x\n", status); 240 } 241 s->mode = SSI_SD_PREP_RESP; 242 s->response_pos = 0; 243 } else { 244 s->cmdarg[s->arglen++] = val; 245 } 246 return SSI_DUMMY; 247 case SSI_SD_PREP_RESP: 248 DPRINTF("Prepare card response (Ncr)\n"); 249 s->mode = SSI_SD_RESPONSE; 250 return SSI_DUMMY; 251 case SSI_SD_RESPONSE: 252 if (s->response_pos < s->arglen) { 253 DPRINTF("Response 0x%02x\n", s->response[s->response_pos]); 254 return s->response[s->response_pos++]; 255 } 256 if (s->stopping) { 257 s->stopping = 0; 258 s->mode = SSI_SD_CMD; 259 return SSI_DUMMY; 260 } 261 if (sdbus_data_ready(&s->sdbus)) { 262 DPRINTF("Data read\n"); 263 s->mode = SSI_SD_DATA_START; 264 } else { 265 DPRINTF("End of command\n"); 266 s->mode = SSI_SD_CMD; 267 } 268 return SSI_DUMMY; 269 case SSI_SD_PREP_DATA: 270 DPRINTF("Prepare data block (Nac)\n"); 271 s->mode = SSI_SD_DATA_START; 272 return SSI_DUMMY; 273 case SSI_SD_DATA_START: 274 DPRINTF("Start read block\n"); 275 s->mode = SSI_SD_DATA_READ; 276 s->response_pos = 0; 277 return SSI_TOKEN_SINGLE; 278 case SSI_SD_DATA_READ: 279 val = sdbus_read_byte(&s->sdbus); 280 s->read_bytes++; 281 s->crc16 = crc_ccitt_false(s->crc16, (uint8_t *)&val, 1); 282 if (!sdbus_data_ready(&s->sdbus) || s->read_bytes == 512) { 283 DPRINTF("Data read end\n"); 284 s->mode = SSI_SD_DATA_CRC16; 285 } 286 return val; 287 case SSI_SD_DATA_CRC16: 288 val = (s->crc16 & 0xff00) >> 8; 289 s->crc16 <<= 8; 290 s->response_pos++; 291 if (s->response_pos == 2) { 292 DPRINTF("CRC16 read end\n"); 293 if (s->read_bytes == 512 && s->cmd != 17) { 294 s->mode = SSI_SD_PREP_DATA; 295 } else { 296 s->mode = SSI_SD_CMD; 297 } 298 s->read_bytes = 0; 299 s->response_pos = 0; 300 } 301 return val; 302 case SSI_SD_DATA_WRITE: 303 sdbus_write_byte(&s->sdbus, val); 304 s->write_bytes++; 305 if (!sdbus_receive_ready(&s->sdbus) || s->write_bytes == 512) { 306 DPRINTF("Data write end\n"); 307 s->mode = SSI_SD_SKIP_CRC16; 308 s->response_pos = 0; 309 } 310 return val; 311 case SSI_SD_SKIP_CRC16: 312 /* we don't verify the crc16 */ 313 s->response_pos++; 314 if (s->response_pos == 2) { 315 DPRINTF("CRC16 receive end\n"); 316 s->mode = SSI_SD_RESPONSE; 317 s->write_bytes = 0; 318 s->arglen = 1; 319 s->response[0] = DATA_RESPONSE_ACCEPTED; 320 s->response_pos = 0; 321 } 322 return SSI_DUMMY; 323 } 324 /* Should never happen. */ 325 return SSI_DUMMY; 326} 327 328static int ssi_sd_post_load(void *opaque, int version_id) 329{ 330 ssi_sd_state *s = (ssi_sd_state *)opaque; 331 332 if (s->mode > SSI_SD_SKIP_CRC16) { 333 return -EINVAL; 334 } 335 if (s->mode == SSI_SD_CMDARG && 336 (s->arglen < 0 || s->arglen >= ARRAY_SIZE(s->cmdarg))) { 337 return -EINVAL; 338 } 339 if (s->mode == SSI_SD_RESPONSE && 340 (s->response_pos < 0 || s->response_pos >= ARRAY_SIZE(s->response) || 341 (!s->stopping && s->arglen > ARRAY_SIZE(s->response)))) { 342 return -EINVAL; 343 } 344 345 return 0; 346} 347 348static const VMStateDescription vmstate_ssi_sd = { 349 .name = "ssi_sd", 350 .version_id = 7, 351 .minimum_version_id = 7, 352 .post_load = ssi_sd_post_load, 353 .fields = (VMStateField []) { 354 VMSTATE_UINT32(mode, ssi_sd_state), 355 VMSTATE_INT32(cmd, ssi_sd_state), 356 VMSTATE_UINT8_ARRAY(cmdarg, ssi_sd_state, 4), 357 VMSTATE_UINT8_ARRAY(response, ssi_sd_state, 5), 358 VMSTATE_UINT16(crc16, ssi_sd_state), 359 VMSTATE_INT32(read_bytes, ssi_sd_state), 360 VMSTATE_INT32(write_bytes, ssi_sd_state), 361 VMSTATE_INT32(arglen, ssi_sd_state), 362 VMSTATE_INT32(response_pos, ssi_sd_state), 363 VMSTATE_INT32(stopping, ssi_sd_state), 364 VMSTATE_SSI_PERIPHERAL(ssidev, ssi_sd_state), 365 VMSTATE_END_OF_LIST() 366 } 367}; 368 369static void ssi_sd_realize(SSIPeripheral *d, Error **errp) 370{ 371 ERRP_GUARD(); 372 ssi_sd_state *s = SSI_SD(d); 373 DeviceState *carddev; 374 DriveInfo *dinfo; 375 376 qbus_init(&s->sdbus, sizeof(s->sdbus), TYPE_SD_BUS, DEVICE(d), "sd-bus"); 377 378 /* Create and plug in the sd card */ 379 /* FIXME use a qdev drive property instead of drive_get_next() */ 380 dinfo = drive_get_next(IF_SD); 381 carddev = qdev_new(TYPE_SD_CARD); 382 if (dinfo) { 383 if (!qdev_prop_set_drive_err(carddev, "drive", 384 blk_by_legacy_dinfo(dinfo), errp)) { 385 goto fail; 386 } 387 } 388 389 if (!object_property_set_bool(OBJECT(carddev), "spi", true, errp)) { 390 goto fail; 391 } 392 393 if (!qdev_realize_and_unref(carddev, BUS(&s->sdbus), errp)) { 394 goto fail; 395 } 396 397 return; 398 399fail: 400 error_prepend(errp, "failed to init SD card: "); 401} 402 403static void ssi_sd_reset(DeviceState *dev) 404{ 405 ssi_sd_state *s = SSI_SD(dev); 406 407 s->mode = SSI_SD_CMD; 408 s->cmd = 0; 409 memset(s->cmdarg, 0, sizeof(s->cmdarg)); 410 memset(s->response, 0, sizeof(s->response)); 411 s->crc16 = 0; 412 s->read_bytes = 0; 413 s->write_bytes = 0; 414 s->arglen = 0; 415 s->response_pos = 0; 416 s->stopping = 0; 417} 418 419static void ssi_sd_class_init(ObjectClass *klass, void *data) 420{ 421 DeviceClass *dc = DEVICE_CLASS(klass); 422 SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass); 423 424 k->realize = ssi_sd_realize; 425 k->transfer = ssi_sd_transfer; 426 k->cs_polarity = SSI_CS_LOW; 427 dc->vmsd = &vmstate_ssi_sd; 428 dc->reset = ssi_sd_reset; 429 /* Reason: init() method uses drive_get_next() */ 430 dc->user_creatable = false; 431} 432 433static const TypeInfo ssi_sd_info = { 434 .name = TYPE_SSI_SD, 435 .parent = TYPE_SSI_PERIPHERAL, 436 .instance_size = sizeof(ssi_sd_state), 437 .class_init = ssi_sd_class_init, 438}; 439 440static void ssi_sd_register_types(void) 441{ 442 type_register_static(&ssi_sd_info); 443} 444 445type_init(ssi_sd_register_types)