static void * mmc_cim_get_status( struct mmc_dev *dev, int first ) { struct mmc_slot *slot = dev->slot + dev->io_request->id; struct mmc_response_r1 r1; int retval = MMC_NO_ERROR; DEBUG(2," first=%d\n",first); if ( first ) { mmc_simple_cmd(dev, MMC_SEND_STATUS, slot->rca, RESPONSE_R1 ); return NULL; } switch (dev->request.cmd) { case MMC_SEND_STATUS: retval = mmc_unpack_r1(&dev->request,&r1,slot->state); if ( !retval || retval == MMC_ERROR_STATE_MISMATCH ) { slot->state = R1_CURRENT_STATE(r1.status); return mmc_cim_read_write_block; } break; default: break; } DEBUG(0, ": failure during cmd %d, error=%d (%s)\n", dev->request.cmd, retval, mmc_result_to_string(retval)); mmc_finish_io_request(dev,0); return mmc_cim_default_state; }
static void * mmc_cim_single_card_acq( struct mmc_dev *dev, int first ) { struct mmc_response_r3 r3; struct mmc_response_r1 r1; struct mmc_slot *slot = dev->slot; /* Must be slot 0 */ int retval; DEBUG(2,"\n"); if ( first ) { mmc_simple_cmd(dev, MMC_GO_IDLE_STATE, 0, RESPONSE_NONE); slot->sd = 0; return NULL; } switch (dev->request.cmd) { case MMC_GO_IDLE_STATE: /* No response to parse */ if ( (dev->sdrive->flags & MMC_SDFLAG_VOLTAGE )) DEBUG(0,": error - current driver doesn't do OCR\n"); mmc_simple_cmd(dev, MMC_APP_CMD, 0, RESPONSE_R1); break; case MMC_APP_CMD: retval = mmc_unpack_r1(&dev->request,&r1,slot->state); if ( retval ) { DEBUG(0, ": unable to MMC_APP_CMD error=%d (%s)\n", retval, mmc_result_to_string(retval)); mmc_simple_cmd(dev, MMC_SEND_OP_COND, dev->sdrive->ocr, RESPONSE_R3); } else { mmc_simple_cmd(dev, SD_SEND_OP_COND, 0x00ff8000, RESPONSE_R3); } break; case SD_SEND_OP_COND: retval = mmc_unpack_r3(&dev->request, &r3); if ( retval ) { /* Try MMC card */ mmc_simple_cmd(dev, MMC_SEND_OP_COND, dev->sdrive->ocr, RESPONSE_R3); break; } DEBUG(2,": read ocr value = 0x%08x\n", r3.ocr); if (!(r3.ocr & MMC_CARD_BUSY)) { mmc_simple_cmd(dev, MMC_APP_CMD, 0, RESPONSE_R1); } else { /* Set the data bus width to 4 bits */ slot->sd = 1; /* SD Card ready */ slot->state = CARD_STATE_READY; mmc_simple_cmd(dev, MMC_ALL_SEND_CID, 0, RESPONSE_R2_CID); } break; case MMC_SEND_OP_COND: retval = mmc_unpack_r3(&dev->request, &r3); if ( retval ) { DEBUG(0,": failed SEND_OP_COND error=%d (%s)\n", retval, mmc_result_to_string(retval)); return mmc_cim_default_state; } DEBUG(2,": read ocr value = 0x%08x\n", r3.ocr); if (!(r3.ocr & MMC_CARD_BUSY)) { mmc_simple_cmd(dev, MMC_SEND_OP_COND, dev->sdrive->ocr, RESPONSE_R3); } else { slot->sd = 0; /* MMC Card ready */ slot->state = CARD_STATE_READY; mmc_simple_cmd(dev, MMC_ALL_SEND_CID, 0, RESPONSE_R2_CID); } break; case MMC_ALL_SEND_CID: retval = mmc_unpack_cid( &dev->request, &slot->cid ); if ( retval ) { DEBUG(0,": unable to ALL_SEND_CID error=%d (%s)\n", retval, mmc_result_to_string(retval)); return mmc_cim_default_state; } slot->state = CARD_STATE_IDENT; if(slot->sd) { mmc_simple_cmd(dev, MMC_SET_RELATIVE_ADDR, 0, RESPONSE_R6); } else { mmc_simple_cmd(dev, MMC_SET_RELATIVE_ADDR, ID_TO_RCA(slot->id) << 16, RESPONSE_R1); } break; case MMC_SET_RELATIVE_ADDR: if (slot->sd) { retval = mmc_unpack_r6(&dev->request, &r1, slot->state, &slot->rca); slot->rca = slot->rca << 16; DEBUG(2, ": Get RCA from SD: 0x%04x Status: %x\n", slot->rca, r1.status); } else { retval = mmc_unpack_r1(&dev->request,&r1,slot->state); slot->rca = ID_TO_RCA(slot->id) << 16; } if ( retval ) { DEBUG(0, ": unable to SET_RELATIVE_ADDR error=%d (%s)\n", retval, mmc_result_to_string(retval)); return mmc_cim_default_state; } slot->state = CARD_STATE_STBY; mmc_simple_cmd(dev, MMC_SEND_CSD, slot->rca, RESPONSE_R2_CSD); break; case MMC_SEND_CSD: retval = mmc_unpack_csd(&dev->request, &slot->csd); if ( retval ) { DEBUG(0, ": unable to SEND_CSD error=%d (%s)\n", retval, mmc_result_to_string(retval)); return mmc_cim_default_state; } if ( slot->csd.dsr_imp ) { DEBUG(0, ": driver doesn't support setting DSR\n"); // mmc_simple_cmd(dev, MMC_SET_DSR, 0, RESPONSE_NONE); } mmc_configure_card( dev, 0 ); return mmc_cim_default_state; default: DEBUG(0, ": error! Illegal last cmd %d\n", dev->request.cmd); return mmc_cim_default_state; } return NULL; }
static void * mmc_cim_read_write_block( struct mmc_dev *dev, int first ) { struct mmc_io_request *t = dev->io_request; struct mmc_response_r1 r1; struct mmc_slot *slot = dev->slot + t->id; int retval = 0; int i; DEBUG(2," first=%d\n",first); if ( first ) { mmc_fix_request_block_size( dev ); switch ( slot->state ) { case CARD_STATE_STBY: mmc_simple_cmd(dev, MMC_SELECT_CARD, slot->rca, RESPONSE_R1B ); break; case CARD_STATE_TRAN: mmc_simple_cmd(dev, MMC_SET_BLOCKLEN, t->block_len, RESPONSE_R1 ); break; default: DEBUG(0,": invalid card state %d\n", slot->state); goto read_block_error; break; } return NULL; } switch (dev->request.cmd) { case MMC_SELECT_CARD: if ( (retval = mmc_unpack_r1( &dev->request, &r1, slot->state )) ) goto read_block_error; for ( i = 0 ; i < dev->num_slots ; i++ ) dev->slot[i].state = ( i == t->id ? CARD_STATE_TRAN : CARD_STATE_STBY ); if(slot->sd) { slot->scr = 0; mmc_simple_cmd(dev, MMC_APP_CMD, slot->rca, RESPONSE_R1); } else { mmc_simple_cmd(dev, MMC_SET_BLOCKLEN, t->block_len, RESPONSE_R1 ); } break; case MMC_APP_CMD: retval = mmc_unpack_r1(&dev->request,&r1,slot->state); if ( retval ) { DEBUG(0, ": unable to MMC_APP_CMD error=%d (%s)\n", retval, mmc_result_to_string(retval)); goto read_block_error; } if (slot->scr & (1 << 18)) { mmc_simple_cmd(dev, SET_BUS_WIDTH, 2, RESPONSE_R1); } else if (slot->scr) { mmc_simple_cmd(dev, SET_BUS_WIDTH, 0, RESPONSE_R1); } else { /* Get SCR */ mmc_simple_cmd(dev, SEND_SCR, 0, RESPONSE_R1); } break; case SEND_SCR: retval = mmc_unpack_scr(&dev->request, &r1, slot->state, &slot->scr); if ( retval ) { DEBUG(0, ": unable to SEND_SCR error=%d (%s)\n", retval, mmc_result_to_string(retval)); goto read_block_error; } DEBUG(2, ": Get SCR from SD: 0x%x Satus: %x\n", slot->scr, r1.status); mmc_simple_cmd(dev, MMC_APP_CMD, slot->rca, RESPONSE_R1); break; case SET_BUS_WIDTH: retval = mmc_unpack_r1(&dev->request,&r1,slot->state); if ( retval ) { DEBUG(0, ": unable to SET_BUS_WIDTH error=%d (%s)\n", retval, mmc_result_to_string(retval)); goto read_block_error; } else { mmc_simple_cmd(dev, MMC_SET_BLOCKLEN, t->block_len, RESPONSE_R1 ); } break; case MMC_SET_BLOCKLEN: if ( (retval = mmc_unpack_r1( &dev->request, &r1, slot->state )) ) goto read_block_error; mmc_send_cmd(dev, (t->cmd == READ ? MMC_READ_SINGLE_BLOCK : MMC_WRITE_BLOCK), t->sector * t->block_len, 1, t->block_len, RESPONSE_R1 ); break; case MMC_READ_SINGLE_BLOCK: case MMC_WRITE_BLOCK: if ( (retval = mmc_unpack_r1( &dev->request, &r1, slot->state )) ) goto read_block_error; t->nr_sectors--; t->sector++; t->buffer += t->block_len; if ( t->nr_sectors ) { mmc_send_cmd(dev, (t->cmd == READ ? MMC_READ_SINGLE_BLOCK : MMC_WRITE_BLOCK), t->sector * t->block_len, 1, t->block_len, RESPONSE_R1 ); } else { mmc_finish_io_request( dev, 1 ); if ( mmc_has_valid_request(dev) ) return mmc_cim_read_write_block; return mmc_cim_default_state; } break; default: goto read_block_error; break; } return NULL; read_block_error: DEBUG(0,": failure during cmd %d, error %d (%s)\n", dev->request.cmd, retval, mmc_result_to_string(retval)); mmc_finish_io_request( dev, 0 ); // Failure return mmc_cim_default_state; }
static int mmc_init_card_state(struct mmc_request *request) { struct mmc_response_r1 r1; struct mmc_response_r3 r3; int retval; int ocr = 0x40300000; DEBUG(2, "mmc_init_card_state\n"); switch (request->cmd) { case MMC_GO_IDLE_STATE: /* No response to parse */ if (mmcinfo.sd) mmc_simple_cmd(request, 8, 0x1aa, RESPONSE_R1); else mmc_simple_cmd(request, MMC_SEND_OP_COND, MMC_OCR_ARG, RESPONSE_R3); break; case 8: retval = mmc_unpack_r1(request, &r1, mmcinfo.state); mmc_simple_cmd(request, MMC_APP_CMD, 0, RESPONSE_R1); break; case MMC_APP_CMD: retval = mmc_unpack_r1(request, &r1, mmcinfo.state); if (retval & (limit_41 < 100)) { DEBUG(0, "mmc_init_card_state: unable to MMC_APP_CMD error=%d (%s)\n", retval, mmc_result_to_string(retval)); limit_41++; mmc_simple_cmd(request, SD_SEND_OP_COND, ocr, RESPONSE_R3); } else if (limit_41 < 100) { limit_41++; mmc_simple_cmd(request, SD_SEND_OP_COND, ocr, RESPONSE_R3); } else { /* reset the card to idle */ mmc_simple_cmd(request, MMC_GO_IDLE_STATE, 0, RESPONSE_NONE); mmcinfo.sd = 0; } break; case SD_SEND_OP_COND: retval = mmc_unpack_r3(request, &r3); if (retval) { /* Try MMC card */ mmc_simple_cmd(request, MMC_SEND_OP_COND, MMC_OCR_ARG, RESPONSE_R3); break; } DEBUG(2, "mmc_init_card_state: read ocr value = 0x%08x\n", r3.ocr); if (!(r3.ocr & MMC_CARD_BUSY || ocr == 0)) { mdelay(10); mmc_simple_cmd(request, MMC_APP_CMD, 0, RESPONSE_R1); } else { /* Set the data bus width to 4 bits */ mmcinfo.sd = 1; /* SD Card ready */ mmcinfo.state = CARD_STATE_READY; mmc_simple_cmd(request, MMC_ALL_SEND_CID, 0, RESPONSE_R2_CID); } break; case MMC_SEND_OP_COND: retval = mmc_unpack_r3(request, &r3); if (retval) { DEBUG(0, "mmc_init_card_state: failed SEND_OP_COND error=%d (%s)\n", retval, mmc_result_to_string(retval)); return MMC_INIT_FAILED; } DEBUG(2, "mmc_init_card_state: read ocr value = 0x%08x\n", r3.ocr); if (!(r3.ocr & MMC_CARD_BUSY)) { mmc_simple_cmd(request, MMC_SEND_OP_COND, MMC_OCR_ARG, RESPONSE_R3); } else { mmcinfo.sd = 0; /* MMC Card ready */ mmcinfo.state = CARD_STATE_READY; mmc_simple_cmd(request, MMC_ALL_SEND_CID, 0, RESPONSE_R2_CID); } break; case MMC_ALL_SEND_CID: retval = mmc_unpack_cid(request, &mmcinfo.cid); /*FIXME:ignore CRC error for CMD2/CMD9/CMD10 */ if (retval && (retval != MMC_ERROR_CRC)) { DEBUG(0, "mmc_init_card_state: unable to ALL_SEND_CID error=%d (%s)\n", retval, mmc_result_to_string(retval)); return MMC_INIT_FAILED; } mmcinfo.state = CARD_STATE_IDENT; if (mmcinfo.sd) mmc_simple_cmd(request, MMC_SET_RELATIVE_ADDR, 0, RESPONSE_R6); else mmc_simple_cmd(request, MMC_SET_RELATIVE_ADDR, ID_TO_RCA(mmcinfo.id) << 16, RESPONSE_R1); break; case MMC_SET_RELATIVE_ADDR: if (mmcinfo.sd) { retval = mmc_unpack_r6(request, &r1, mmcinfo.state, &mmcinfo.rca); mmcinfo.rca = mmcinfo.rca << 16; DEBUG(2, "mmc_init_card_state: Get RCA from SD: 0x%04x Status: %x\n", mmcinfo.rca, r1.status); } else { retval = mmc_unpack_r1(request, &r1, mmcinfo.state); mmcinfo.rca = ID_TO_RCA(mmcinfo.id) << 16; } if (retval) { DEBUG(0, "mmc_init_card_state: unable to SET_RELATIVE_ADDR error=%d (%s)\n", retval, mmc_result_to_string(retval)); return MMC_INIT_FAILED; } mmcinfo.state = CARD_STATE_STBY; mmc_simple_cmd(request, MMC_SEND_CSD, mmcinfo.rca, RESPONSE_R2_CSD); break; case MMC_SEND_CSD: retval = mmc_unpack_csd(request, &mmcinfo.csd); /*FIXME:ignore CRC error for CMD2/CMD9/CMD10 */ if (retval && (retval != MMC_ERROR_CRC)) { DEBUG(0, "mmc_init_card_state: unable to SEND_CSD error=%d (%s)\n", retval, mmc_result_to_string(retval)); return MMC_INIT_FAILED; } if (mmcinfo.csd.dsr_imp) { DEBUG(0, "mmc_init_card_state: driver doesn't support setting DSR\n"); } mmc_configure_card(); return MMC_INIT_PASSED; break; default: DEBUG(0, "mmc_init_card_state: error! Illegal last cmd %d\n", request->cmd); return MMC_INIT_FAILED; } return MMC_INIT_DOING; }