Annotation of sys/dev/sdmmc/sdmmc_mem.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: sdmmc_mem.c,v 1.7 2007/03/18 22:07:16 uwe Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
! 5: *
! 6: * Permission to use, copy, modify, and distribute this software for any
! 7: * purpose with or without fee is hereby granted, provided that the above
! 8: * copyright notice and this permission notice appear in all copies.
! 9: *
! 10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 17: */
! 18:
! 19: /* Routines for SD/MMC memory cards. */
! 20:
! 21: #include <sys/param.h>
! 22: #include <sys/kernel.h>
! 23: #include <sys/malloc.h>
! 24: #include <sys/systm.h>
! 25:
! 26: #include <dev/sdmmc/sdmmcchip.h>
! 27: #include <dev/sdmmc/sdmmcreg.h>
! 28: #include <dev/sdmmc/sdmmcvar.h>
! 29:
! 30: int sdmmc_decode_csd(struct sdmmc_softc *, sdmmc_response,
! 31: struct sdmmc_function *);
! 32: int sdmmc_decode_cid(struct sdmmc_softc *, sdmmc_response,
! 33: struct sdmmc_function *);
! 34: void sdmmc_print_cid(struct sdmmc_cid *);
! 35:
! 36: int sdmmc_mem_send_op_cond(struct sdmmc_softc *, u_int32_t, u_int32_t *);
! 37: int sdmmc_mem_set_blocklen(struct sdmmc_softc *, struct sdmmc_function *);
! 38:
! 39: #ifdef SDMMC_DEBUG
! 40: #define DPRINTF(s) printf s
! 41: #else
! 42: #define DPRINTF(s) /**/
! 43: #endif
! 44:
! 45: /*
! 46: * Initialize SD/MMC memory cards and memory in SDIO "combo" cards.
! 47: */
! 48: int
! 49: sdmmc_mem_enable(struct sdmmc_softc *sc)
! 50: {
! 51: u_int32_t host_ocr;
! 52: u_int32_t card_ocr;
! 53:
! 54: /* Set host mode to SD "combo" card or SD memory-only. */
! 55: SET(sc->sc_flags, SMF_SD_MODE|SMF_MEM_MODE);
! 56:
! 57: /* Reset memory (*must* do that before CMD55 or CMD1). */
! 58: sdmmc_go_idle_state(sc);
! 59:
! 60: /*
! 61: * Read the SD/MMC memory OCR value by issuing CMD55 followed
! 62: * by ACMD41 to read the OCR value from memory-only SD cards.
! 63: * MMC cards will not respond to CMD55 or ACMD41 and this is
! 64: * how we distinguish them from SD cards.
! 65: */
! 66: mmc_mode:
! 67: if (sdmmc_mem_send_op_cond(sc, 0, &card_ocr) != 0) {
! 68: if (ISSET(sc->sc_flags, SMF_SD_MODE) &&
! 69: !ISSET(sc->sc_flags, SMF_IO_MODE)) {
! 70: /* Not a SD card, switch to MMC mode. */
! 71: CLR(sc->sc_flags, SMF_SD_MODE);
! 72: goto mmc_mode;
! 73: }
! 74: if (!ISSET(sc->sc_flags, SMF_SD_MODE)) {
! 75: DPRINTF(("%s: can't read memory OCR\n",
! 76: SDMMCDEVNAME(sc)));
! 77: return 1;
! 78: } else {
! 79: /* Not a "combo" card. */
! 80: CLR(sc->sc_flags, SMF_MEM_MODE);
! 81: return 0;
! 82: }
! 83: }
! 84:
! 85: /* Set the lowest voltage supported by the card and host. */
! 86: host_ocr = sdmmc_chip_host_ocr(sc->sct, sc->sch);
! 87: if (sdmmc_set_bus_power(sc, host_ocr, card_ocr) != 0) {
! 88: DPRINTF(("%s: can't supply voltage requested by card\n",
! 89: SDMMCDEVNAME(sc)));
! 90: return 1;
! 91: }
! 92:
! 93: /* Tell the card(s) to enter the idle state (again). */
! 94: sdmmc_go_idle_state(sc);
! 95:
! 96: /* Send the new OCR value until all cards are ready. */
! 97: if (sdmmc_mem_send_op_cond(sc, host_ocr, NULL) != 0) {
! 98: DPRINTF(("%s: can't send memory OCR\n", SDMMCDEVNAME(sc)));
! 99: return 1;
! 100: }
! 101: return 0;
! 102: }
! 103:
! 104: /*
! 105: * Read the CSD and CID from all cards and assign each card a unique
! 106: * relative card address (RCA). CMD2 is ignored by SDIO-only cards.
! 107: */
! 108: void
! 109: sdmmc_mem_scan(struct sdmmc_softc *sc)
! 110: {
! 111: struct sdmmc_command cmd;
! 112: struct sdmmc_function *sf;
! 113: u_int16_t next_rca;
! 114: int error;
! 115: int i;
! 116:
! 117: /*
! 118: * CMD2 is a broadcast command understood by SD cards and MMC
! 119: * cards. All cards begin to respond to the command, but back
! 120: * off if another card drives the CMD line to a different level.
! 121: * Only one card will get its entire response through. That
! 122: * card remains silent once it has been assigned a RCA.
! 123: */
! 124: for (i = 0; i < 100; i++) {
! 125: bzero(&cmd, sizeof cmd);
! 126: cmd.c_opcode = MMC_ALL_SEND_CID;
! 127: cmd.c_flags = SCF_CMD_BCR | SCF_RSP_R2;
! 128:
! 129: error = sdmmc_mmc_command(sc, &cmd);
! 130: if (error == ETIMEDOUT) {
! 131: /* No more cards there. */
! 132: break;
! 133: } else if (error != 0) {
! 134: DPRINTF(("%s: can't read CID\n", SDMMCDEVNAME(sc)));
! 135: break;
! 136: }
! 137:
! 138: /* In MMC mode, find the next available RCA. */
! 139: next_rca = 1;
! 140: if (!ISSET(sc->sc_flags, SMF_SD_MODE))
! 141: SIMPLEQ_FOREACH(sf, &sc->sf_head, sf_list)
! 142: next_rca++;
! 143:
! 144: /* Allocate a sdmmc_function structure. */
! 145: sf = sdmmc_function_alloc(sc);
! 146: sf->rca = next_rca;
! 147:
! 148: /*
! 149: * Remember the CID returned in the CMD2 response for
! 150: * later decoding.
! 151: */
! 152: bcopy(cmd.c_resp, sf->raw_cid, sizeof sf->raw_cid);
! 153:
! 154: /*
! 155: * Silence the card by assigning it a unique RCA, or
! 156: * querying it for its RCA in the case of SD.
! 157: */
! 158: if (sdmmc_set_relative_addr(sc, sf) != 0) {
! 159: printf("%s: can't set mem RCA\n", SDMMCDEVNAME(sc));
! 160: sdmmc_function_free(sf);
! 161: break;
! 162: }
! 163:
! 164: #if 0
! 165: /* Verify that the RCA has been set by selecting the card. */
! 166: if (sdmmc_select_card(sc, sf) != 0) {
! 167: printf("%s: can't select mem RCA %d\n",
! 168: SDMMCDEVNAME(sc), sf->rca);
! 169: sdmmc_function_free(sf);
! 170: break;
! 171: }
! 172:
! 173: /* Deselect. */
! 174: (void)sdmmc_select_card(sc, NULL);
! 175: #endif
! 176:
! 177: /*
! 178: * If this is a memory-only card, the card responding
! 179: * first becomes an alias for SDIO function 0.
! 180: */
! 181: if (sc->sc_fn0 == NULL)
! 182: sc->sc_fn0 = sf;
! 183:
! 184: SIMPLEQ_INSERT_TAIL(&sc->sf_head, sf, sf_list);
! 185: }
! 186:
! 187: /*
! 188: * All cards are either inactive or awaiting further commands.
! 189: * Read the CSDs and decode the raw CID for each card.
! 190: */
! 191: SIMPLEQ_FOREACH(sf, &sc->sf_head, sf_list) {
! 192: bzero(&cmd, sizeof cmd);
! 193: cmd.c_opcode = MMC_SEND_CSD;
! 194: cmd.c_arg = MMC_ARG_RCA(sf->rca);
! 195: cmd.c_flags = SCF_CMD_AC | SCF_RSP_R2;
! 196:
! 197: if (sdmmc_mmc_command(sc, &cmd) != 0) {
! 198: SET(sf->flags, SFF_ERROR);
! 199: continue;
! 200: }
! 201:
! 202: if (sdmmc_decode_csd(sc, cmd.c_resp, sf) != 0 ||
! 203: sdmmc_decode_cid(sc, sf->raw_cid, sf) != 0) {
! 204: SET(sf->flags, SFF_ERROR);
! 205: continue;
! 206: }
! 207:
! 208: #ifdef SDMMC_DEBUG
! 209: printf("%s: CID: ", SDMMCDEVNAME(sc));
! 210: sdmmc_print_cid(&sf->cid);
! 211: #endif
! 212: }
! 213: }
! 214:
! 215: int
! 216: sdmmc_decode_csd(struct sdmmc_softc *sc, sdmmc_response resp,
! 217: struct sdmmc_function *sf)
! 218: {
! 219: struct sdmmc_csd *csd = &sf->csd;
! 220:
! 221: if (ISSET(sc->sc_flags, SMF_SD_MODE)) {
! 222: /*
! 223: * CSD version 1.0 corresponds to SD system
! 224: * specification version 1.0 - 1.10. (SanDisk, 3.5.3)
! 225: */
! 226: csd->csdver = SD_CSD_CSDVER(resp);
! 227: if (csd->csdver != SD_CSD_CSDVER_1_0) {
! 228: printf("%s: unknown SD CSD structure version 0x%x\n",
! 229: SDMMCDEVNAME(sc), csd->csdver);
! 230: return 1;
! 231: }
! 232:
! 233: csd->capacity = SD_CSD_CAPACITY(resp);
! 234: csd->read_bl_len = SD_CSD_READ_BL_LEN(resp);
! 235: } else {
! 236: csd->csdver = MMC_CSD_CSDVER(resp);
! 237: if (csd->csdver != MMC_CSD_CSDVER_1_0 &&
! 238: csd->csdver != MMC_CSD_CSDVER_2_0) {
! 239: printf("%s: unknown MMC CSD structure version 0x%x\n",
! 240: SDMMCDEVNAME(sc), csd->csdver);
! 241: return 1;
! 242: }
! 243:
! 244: csd->mmcver = MMC_CSD_MMCVER(resp);
! 245: csd->capacity = MMC_CSD_CAPACITY(resp);
! 246: csd->read_bl_len = MMC_CSD_READ_BL_LEN(resp);
! 247: }
! 248: csd->sector_size = MIN(1 << csd->read_bl_len,
! 249: sdmmc_chip_host_maxblklen(sc->sct, sc->sch));
! 250: if (csd->sector_size < (1<<csd->read_bl_len))
! 251: csd->capacity *= (1<<csd->read_bl_len) /
! 252: csd->sector_size;
! 253:
! 254: return 0;
! 255: }
! 256:
! 257: int
! 258: sdmmc_decode_cid(struct sdmmc_softc *sc, sdmmc_response resp,
! 259: struct sdmmc_function *sf)
! 260: {
! 261: struct sdmmc_cid *cid = &sf->cid;
! 262:
! 263: if (ISSET(sc->sc_flags, SMF_SD_MODE)) {
! 264: cid->mid = SD_CID_MID(resp);
! 265: cid->oid = SD_CID_OID(resp);
! 266: SD_CID_PNM_CPY(resp, cid->pnm);
! 267: cid->rev = SD_CID_REV(resp);
! 268: cid->psn = SD_CID_PSN(resp);
! 269: cid->mdt = SD_CID_MDT(resp);
! 270: } else {
! 271: switch(sf->csd.mmcver) {
! 272: case MMC_CSD_MMCVER_1_0:
! 273: case MMC_CSD_MMCVER_1_4:
! 274: cid->mid = MMC_CID_MID_V1(resp);
! 275: MMC_CID_PNM_V1_CPY(resp, cid->pnm);
! 276: cid->rev = MMC_CID_REV_V1(resp);
! 277: cid->psn = MMC_CID_PSN_V1(resp);
! 278: cid->mdt = MMC_CID_MDT_V1(resp);
! 279: break;
! 280: case MMC_CSD_MMCVER_2_0:
! 281: case MMC_CSD_MMCVER_3_1:
! 282: case MMC_CSD_MMCVER_4_0:
! 283: cid->mid = MMC_CID_MID_V2(resp);
! 284: cid->oid = MMC_CID_OID_V2(resp);
! 285: MMC_CID_PNM_V2_CPY(resp, cid->pnm);
! 286: cid->psn = MMC_CID_PSN_V2(resp);
! 287: break;
! 288: default:
! 289: printf("%s: unknown MMC version %d\n",
! 290: SDMMCDEVNAME(sc), sf->csd.mmcver);
! 291: return 1;
! 292: }
! 293: }
! 294: return 0;
! 295: }
! 296:
! 297: #ifdef SDMMC_DEBUG
! 298: void
! 299: sdmmc_print_cid(struct sdmmc_cid *cid)
! 300: {
! 301: printf("mid=0x%02x oid=0x%04x pnm=\"%s\" rev=0x%02x psn=0x%08x"
! 302: " mdt=%03x\n", cid->mid, cid->oid, cid->pnm, cid->rev, cid->psn,
! 303: cid->mdt);
! 304: }
! 305: #endif
! 306:
! 307: /*
! 308: * Initialize a SD/MMC memory card.
! 309: */
! 310: int
! 311: sdmmc_mem_init(struct sdmmc_softc *sc, struct sdmmc_function *sf)
! 312: {
! 313: int error = 0;
! 314:
! 315: SDMMC_LOCK(sc);
! 316: if (sdmmc_select_card(sc, sf) != 0 ||
! 317: sdmmc_mem_set_blocklen(sc, sf) != 0)
! 318: error = 1;
! 319: SDMMC_UNLOCK(sc);
! 320: return error;
! 321: }
! 322:
! 323: /*
! 324: * Get or set the card's memory OCR value (SD or MMC).
! 325: */
! 326: int
! 327: sdmmc_mem_send_op_cond(struct sdmmc_softc *sc, u_int32_t ocr,
! 328: u_int32_t *ocrp)
! 329: {
! 330: struct sdmmc_command cmd;
! 331: int error;
! 332: int i;
! 333:
! 334: SDMMC_LOCK(sc);
! 335:
! 336: /*
! 337: * If we change the OCR value, retry the command until the OCR
! 338: * we receive in response has the "CARD BUSY" bit set, meaning
! 339: * that all cards are ready for identification.
! 340: */
! 341: for (i = 0; i < 100; i++) {
! 342: bzero(&cmd, sizeof cmd);
! 343: cmd.c_arg = ocr;
! 344: cmd.c_flags = SCF_CMD_BCR | SCF_RSP_R3;
! 345:
! 346: if (ISSET(sc->sc_flags, SMF_SD_MODE)) {
! 347: cmd.c_opcode = SD_APP_OP_COND;
! 348: error = sdmmc_app_command(sc, &cmd);
! 349: } else {
! 350: cmd.c_opcode = MMC_SEND_OP_COND;
! 351: error = sdmmc_mmc_command(sc, &cmd);
! 352: }
! 353: if (error != 0)
! 354: break;
! 355: if (ISSET(MMC_R3(cmd.c_resp), MMC_OCR_MEM_READY) ||
! 356: ocr == 0)
! 357: break;
! 358: error = ETIMEDOUT;
! 359: sdmmc_delay(10000);
! 360: }
! 361: if (error == 0 && ocrp != NULL)
! 362: *ocrp = MMC_R3(cmd.c_resp);
! 363:
! 364: SDMMC_UNLOCK(sc);
! 365: return error;
! 366: }
! 367:
! 368: /*
! 369: * Set the read block length appropriately for this card, according to
! 370: * the card CSD register value.
! 371: */
! 372: int
! 373: sdmmc_mem_set_blocklen(struct sdmmc_softc *sc, struct sdmmc_function *sf)
! 374: {
! 375: struct sdmmc_command cmd;
! 376:
! 377: bzero(&cmd, sizeof cmd);
! 378: cmd.c_opcode = MMC_SET_BLOCKLEN;
! 379: cmd.c_arg = sf->csd.sector_size;
! 380: cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1;
! 381: DPRINTF(("%s: read_bl_len=%d sector_size=%d\n", SDMMCDEVNAME(sc),
! 382: 1 << sf->csd.read_bl_len, sf->csd.sector_size));
! 383:
! 384: return sdmmc_mmc_command(sc, &cmd);
! 385: }
! 386:
! 387: int
! 388: sdmmc_mem_read_block(struct sdmmc_function *sf, int blkno, u_char *data,
! 389: size_t datalen)
! 390: {
! 391: struct sdmmc_softc *sc = sf->sc;
! 392: struct sdmmc_command cmd;
! 393: int error;
! 394:
! 395: SDMMC_LOCK(sc);
! 396:
! 397: if ((error = sdmmc_select_card(sc, sf)) != 0)
! 398: goto err;
! 399:
! 400: bzero(&cmd, sizeof cmd);
! 401: cmd.c_data = data;
! 402: cmd.c_datalen = datalen;
! 403: cmd.c_blklen = sf->csd.sector_size;
! 404: cmd.c_opcode = (datalen / cmd.c_blklen) > 1 ?
! 405: MMC_READ_BLOCK_MULTIPLE : MMC_READ_BLOCK_SINGLE;
! 406: cmd.c_arg = blkno << 9;
! 407: cmd.c_flags = SCF_CMD_ADTC | SCF_CMD_READ | SCF_RSP_R1;
! 408:
! 409: error = sdmmc_mmc_command(sc, &cmd);
! 410: if (error != 0)
! 411: goto err;
! 412:
! 413: /* XXX sdhc(4) does not need this */
! 414: #ifdef __zaurus__
! 415: if (cmd.c_opcode == MMC_READ_BLOCK_MULTIPLE) {
! 416: bzero(&cmd, sizeof cmd);
! 417: cmd.c_opcode = MMC_STOP_TRANSMISSION;
! 418: cmd.c_arg = MMC_ARG_RCA(sf->rca);
! 419: cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1B;
! 420: error = sdmmc_mmc_command(sc, &cmd);
! 421: if (error != 0)
! 422: goto err;
! 423: }
! 424: #endif
! 425:
! 426: do {
! 427: bzero(&cmd, sizeof cmd);
! 428: cmd.c_opcode = MMC_SEND_STATUS;
! 429: cmd.c_arg = MMC_ARG_RCA(sf->rca);
! 430: cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1;
! 431: error = sdmmc_mmc_command(sc, &cmd);
! 432: if (error != 0)
! 433: break;
! 434: /* XXX time out */
! 435: } while (!ISSET(MMC_R1(cmd.c_resp), MMC_R1_READY_FOR_DATA));
! 436:
! 437: err:
! 438: SDMMC_UNLOCK(sc);
! 439: return error;
! 440: }
! 441:
! 442: int
! 443: sdmmc_mem_write_block(struct sdmmc_function *sf, int blkno, u_char *data,
! 444: size_t datalen)
! 445: {
! 446: struct sdmmc_softc *sc = sf->sc;
! 447: struct sdmmc_command cmd;
! 448: int error;
! 449:
! 450: SDMMC_LOCK(sc);
! 451:
! 452: if ((error = sdmmc_select_card(sc, sf)) != 0)
! 453: goto err;
! 454:
! 455: bzero(&cmd, sizeof cmd);
! 456: cmd.c_data = data;
! 457: cmd.c_datalen = datalen;
! 458: cmd.c_blklen = sf->csd.sector_size;
! 459: cmd.c_opcode = (datalen / cmd.c_blklen) > 1 ?
! 460: MMC_WRITE_BLOCK_MULTIPLE : MMC_WRITE_BLOCK_SINGLE;
! 461: cmd.c_arg = blkno << 9;
! 462: cmd.c_flags = SCF_CMD_ADTC | SCF_RSP_R1;
! 463:
! 464: error = sdmmc_mmc_command(sc, &cmd);
! 465: if (error != 0)
! 466: goto err;
! 467:
! 468: /* XXX sdhc(4) does not need this */
! 469: #ifdef __zaurus__
! 470: if (cmd.c_opcode == MMC_WRITE_BLOCK_MULTIPLE) {
! 471: bzero(&cmd, sizeof cmd);
! 472: cmd.c_opcode = MMC_STOP_TRANSMISSION;
! 473: cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1B;
! 474: error = sdmmc_mmc_command(sc, &cmd);
! 475: if (error != 0)
! 476: goto err;
! 477: }
! 478: #endif
! 479:
! 480: do {
! 481: bzero(&cmd, sizeof cmd);
! 482: cmd.c_opcode = MMC_SEND_STATUS;
! 483: cmd.c_arg = MMC_ARG_RCA(sf->rca);
! 484: cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1;
! 485: error = sdmmc_mmc_command(sc, &cmd);
! 486: if (error != 0)
! 487: break;
! 488: /* XXX time out */
! 489: } while (!ISSET(MMC_R1(cmd.c_resp), MMC_R1_READY_FOR_DATA));
! 490:
! 491: err:
! 492: SDMMC_UNLOCK(sc);
! 493: return error;
! 494: }
CVSweb