📄 sd_protocol.c
字号:
scr->data_stat_after_erase, scr->sd_security, scr->sd_bus_width); return 0;} static int sd_get_status(struct mss_card *card, int *status){ struct sd_response_r1 r1; struct sd_card *sd_card = card->prot_card; struct mss_host *host = card->slot->host; int clock, ret, retries = 4; clock = sd_tran_speed(sd_card->csd.tran_speed); mss_set_clock(card->slot->host, clock); while (retries--) { ret = mss_send_simple_ll_req(host, &sd_card->llreq, &sd_card->cmd, SD_SEND_STATUS, sd_card->rca << 16, MSS_RESPONSE_R1, 0); if (ret && !retries) return ret; else if (!ret) { ret = sd_unpack_r1(&sd_card->cmd, &r1, sd_card); if (ret) { if (sd_card->errno == SD_ERROR_STATE_MISMATCH) { sd_card->state = R1_CURRENT_STATE(r1.status); sd_card->errno = SD_ERROR_NONE; } else return ret; } else break; } clock = host->ios.clock; clock = clock >> 1; if (clock < SD_CARD_CLOCK_SLOW || retries == 1) clock = SD_CARD_CLOCK_SLOW; mss_set_clock(host, clock); } *status = r1.status; return MSS_ERROR_NONE; }/** * The blocks requested by the kernel may or may not match what we can do. * Unfortunately, filesystems play fast and loose with block sizes, so we're * stuck with this. */static void sd_fix_request_block_len(struct mss_card *card, int action, struct mss_rw_arg *arg){ u16 block_len = 0; struct sd_card *sd_card = card->prot_card; struct mss_host *host = card->slot->host; switch(action) { case MSS_DATA_READ: block_len = 1 << sd_card->csd.read_bl_len; break; case MSS_DATA_WRITE: block_len = 1 << sd_card->csd.write_bl_len; break; default: return; } if (host->high_capacity && (sd_card->ocr & SD_OCR_CCS)) block_len = 512; if (block_len < arg->block_len) { int scale = arg->block_len / block_len; arg->block_len = block_len; arg->block *= scale; arg->nob *= scale; }}static int sd_send_cmd6(struct mss_card *card, struct sw_func_status *status, int mode, u32 funcs){ struct sd_response_r1 r1; struct sd_card *sd_card = card->prot_card; struct mss_ll_request *llreq = &sd_card->llreq; struct mss_cmd *cmd = &sd_card->cmd; struct mss_data *data = &sd_card->data; struct mss_host *host= card->slot->host; struct scatterlist sg; char *g_buffer = sd_card->buf; int ret; /* Set the argumens for CMD6. */ /* [31]: Mode * [30:24]: reserved (all 0s) * [23:20]: group 6 * [19:16]: group 5 * [15:12]: group 4 * [11:8]: group 3 * [7:4]: group 2 * [3:0]: group 1 */ sg.page = virt_to_page(g_buffer); sg.offset = offset_in_page(g_buffer); sg.length = 8; memset(llreq, 0x0, sizeof(struct mss_ll_request)); memset(cmd, 0x0, sizeof(struct mss_cmd)); memset(data, 0x0, sizeof(struct mss_data)); MSS_INIT_CMD(cmd, SD_SW_FUNC, (funcs | ((mode & 0x1) << 31)), 0, MSS_RESPONSE_R1); MSS_INIT_DATA(data, 1, 32, MSS_DATA_READ, 1, &sg, 0); llreq->cmd = cmd; llreq->data = data; ret = mss_send_ll_req(host, llreq); if (ret) return ret; ret = sd_unpack_r1(cmd, &r1, sd_card); if (ret) return ret; sd_unpack_swfuncstatus(g_buffer, status); return 0;}/***************************************************************************** * * protocol entry functions * ****************************************************************************/static int sd_recognize_card(struct mss_card *card){ struct sd_response_r1 r1; struct sd_response_r3 r3; struct sd_response_r7 r7; int ret; struct sd_card *sd_card = (struct sd_card *)card->prot_card; struct mss_ios ios; struct mss_host *host = card->slot->host; struct mss_ll_request *llreq = &sd_card->llreq; struct mss_cmd *cmd = &sd_card->cmd; card->state = CARD_STATE_IDLE; card->bus_width = MSS_BUSWIDTH_1BIT; memcpy(&ios, &host->ios, sizeof(struct mss_ios)); ios.bus_mode = MSS_BUSMODE_OPENDRAIN; ios.clock = host->f_min; ios.bus_width = MSS_BUSWIDTH_1BIT; host->ops->set_ios(host, &ios); card->card_type = MSS_UNKNOWN_CARD; ret = mss_send_simple_ll_req(host, llreq, cmd, SD_GO_IDLE_STATE, 0, MSS_RESPONSE_NONE, MSS_CMD_INIT); if (ret) return ret; if (host->sd_spec == MSS_SD_SPEC_20) { if (!(host->vdd & MSS_VDD_27_36)) return MSS_ERROR_NO_PROTOCOL; ret = mss_send_simple_ll_req(host, llreq, cmd, SD_SEND_IF_COND, 0x1AA, MSS_RESPONSE_R7, 0); if (ret == MSS_ERROR_TIMEOUT) { sd_card->ver = MSS_SD_SPEC_11; goto next; } else if (ret) return ret; ret = sd_unpack_r7(cmd, &r7, 0x1AA, sd_card); if (!ret) { sd_card->ver = MSS_SD_SPEC_20; goto next; } else return ret; } next: ret = mss_send_simple_ll_req(host, llreq, cmd, SD_APP_CMD, 0, MSS_RESPONSE_R1, 0); if (ret) return ret; ret = sd_unpack_r1(cmd, &r1, sd_card); if (ret && !(sd_card->errno == SD_ERROR_ILLEGAL_COMMAND && sd_card->ver == MSS_SD_SPEC_11)) return ret; ret = mss_send_simple_ll_req(host, llreq, cmd, SD_SD_SEND_OP_COND, 0, MSS_RESPONSE_R3, 0); if (ret) return ret; ret = sd_unpack_r3(cmd, &r3, sd_card); if (ret) return ret; if (r3.ocr & host->vdd) { card->card_type = MSS_SD_CARD; } else card->card_type = MSS_UNCOMPATIBLE_CARD; return MSS_ERROR_NONE;}/** * sd_card_init * @dev: mss_card_device * * return value: 0: success, -1: failed */static int sd_card_init(struct mss_card *card){ struct sd_response_r1 r1; struct sd_response_r3 r3; struct sd_response_r6 r6; struct sd_response_r7 r7; struct sd_cid cid; int ret; struct sd_card * sd_card= (struct sd_card *)card->prot_card; struct mss_ios ios; struct mss_host *host = card->slot->host; struct mss_ll_request *llreq = &sd_card->llreq; struct mss_cmd *cmd = &sd_card->cmd; int hcs = 0; sd_card->state = CARD_STATE_IDLE; card->bus_width = MSS_BUSWIDTH_1BIT; sd_card->rca = 0; memcpy(&ios, &host->ios, sizeof(struct mss_ios)); ios.bus_mode = MSS_BUSMODE_OPENDRAIN; ios.bus_width = MSS_BUSWIDTH_1BIT; ios.clock = host->f_min; host->ops->set_ios(host, &ios); ret = mss_send_simple_ll_req(host, llreq, cmd, SD_GO_IDLE_STATE, 0, MSS_RESPONSE_NONE, MSS_CMD_INIT); if (ret) return ret; /* * We have to send cmd 8 to 2.0 card. It will tell the card that the * host support 2.0 spec. */ if (sd_card->ver == MSS_SD_SPEC_20 && host->sd_spec == MSS_SD_SPEC_20) { ret = mss_send_simple_ll_req(host, llreq, cmd, SD_SEND_IF_COND, 0x1AA, MSS_RESPONSE_R7, 0); if (ret) return ret; ret = sd_unpack_r7(cmd, &r7, 0x1AA, sd_card); if (ret) return ret; if (host->high_capacity) hcs = 1; } ret = mss_send_simple_ll_req(host, llreq, cmd, SD_APP_CMD, 0, MSS_RESPONSE_R1, 0); if (ret) return ret; ret = sd_unpack_r1(cmd, &r1, sd_card); if (ret) return ret; ret = mss_send_simple_ll_req(host, llreq, cmd, SD_SD_SEND_OP_COND, hcs << 30 | host->vdd, MSS_RESPONSE_R3, 0); if (ret) return ret; ret = sd_unpack_r3(cmd, &r3, sd_card); if (ret) return ret; while (!(r3.ocr & SD_OCR_CARD_BUSY)) { mdelay(20); ret = mss_send_simple_ll_req(host, llreq, cmd, SD_APP_CMD, 0, MSS_RESPONSE_R1, 0); if (ret) return ret; ret = sd_unpack_r1(cmd, &r1, sd_card); if (ret) return ret; ret = mss_send_simple_ll_req(host, llreq, cmd, SD_SD_SEND_OP_COND, hcs << 30 | host->vdd, MSS_RESPONSE_R3, 0); if (ret) return ret; ret = sd_unpack_r3(cmd, &r3, sd_card); if (ret) return ret; } memcpy(&sd_card->ocr, &r3.ocr, sizeof(r3.ocr)); sd_card->state = CARD_STATE_READY; ret = mss_send_simple_ll_req(host, llreq, cmd, SD_ALL_SEND_CID, 0, MSS_RESPONSE_R2_CID, 0); if (ret) return ret; memset(&cid, 0x0, sizeof(struct sd_cid)); ret = sd_unpack_cid(cmd, &cid, sd_card); if (ret) return ret; if (sd_card->cid.mid != 0) { if (sd_card->cid.mid != cid.mid || sd_card->cid.oid != cid.oid || sd_card->cid.prv != cid.prv || sd_card->cid.psn != cid.psn || sd_card->cid.mdt != cid.mdt || memcmp(sd_card->cid.pnm, cid.pnm, 6)) return MSS_ERROR_MISMATCH_CARD; if (memcmp(&cid, &sd_card->cid, sizeof(struct sd_cid))) return MSS_ERROR_MISMATCH_CARD; } else memcpy(&sd_card->cid, &cid, sizeof(struct sd_cid)); sd_card->state = CARD_STATE_IDENT; ret = mss_send_simple_ll_req(host, llreq, cmd, SD_SEND_RELATIVE_ADDR, 0, MSS_RESPONSE_R6, 0); if (ret) return ret; ret = sd_unpack_r6(cmd, &r6, sd_card); if (ret) return ret; sd_card->state = CARD_STATE_STBY; sd_card->rca = r6.rca; ret = mss_send_simple_ll_req(host, llreq, cmd, SD_SEND_CSD, sd_card->rca << 16, MSS_RESPONSE_R2_CSD, 0); if (ret) return ret; ret = sd_unpack_csd(cmd, &sd_card->csd, sd_card); if (ret) return ret; if (host->ops->is_slot_wp && host->ops->is_slot_wp(card->slot)) card->state |= MSS_CARD_WP; return MSS_ERROR_NONE;}static int sd_read_write_entry(struct mss_card *card, int action, struct mss_rw_arg *arg, struct mss_rw_result *result){ struct sd_response_r1 r1; struct mss_host *host = card->slot->host; struct mss_ios ios; int ret, retries = 4; struct sd_card *sd_card = (struct sd_card *)card->prot_card; struct mss_ll_request *llreq = &sd_card->llreq; struct mss_cmd *cmd = &sd_card->cmd; struct mss_data *data = &sd_card->data; struct scatterlist sg; char *g_buffer = sd_card->buf; int status; u32 clock; u32 cmdarg, blklen, opcode, flags; dbg("block:%d, nob:%d, blok_len:%d", arg->block, arg->nob, arg->block_len); ret = sd_get_status(card, &status); if (ret) return ret; if (status & R1_CARD_IS_LOCKED) return MSS_ERROR_LOCKED; if (action == MSS_WRITE_MEM && host->ops->is_slot_wp && host->ops->is_slot_wp(card->slot)) return MSS_ERROR_WP; if (sd_card->state == CARD_STATE_STBY) { ret = mss_send_simple_ll_req(host, llreq, cmd, SD_SELECT_CARD, sd_card->rca << 16, MSS_RESPONSE_R1B, 0); if (ret) return ret; ret = sd_unpack_r1(cmd, &r1, sd_card); if (ret) return ret; } sd_card->state = CARD_STATE_TRAN; sd_fix_request_block_len(card, action, arg); if (!sd_card->scr.init) { ret = mss_send_simple_ll_req(host, llreq, cmd, SD_APP_CMD, sd_card->rca << 16, MSS_RESPONSE_R1, 0); if (ret) return ret; sg.page = virt_to_page(g_buffer); sg.offset = offset_in_page(g_buffer); sg.length = 8; memset(llreq, 0x0, sizeof(struct mss_ll_request)); memset(cmd, 0x0, sizeof(struct mss_cmd)); memset(data, 0x0, sizeof(struct mss_data)); MSS_INIT_CMD(cmd, SD_SEND_SCR, 0, 0, MSS_RESPONSE_R1); MSS_INIT_DATA(data, 1, 8, MSS_DATA_READ, 1, &sg, 0); llreq->cmd = cmd; llreq->data = data; ret = mss_send_ll_req(host, llreq); if (ret) return ret; ret = sd_unpack_scr(g_buffer, &sd_card->scr); if (ret) return ret; } if (sd_card->scr.sd_bus_width == SCR_BUSWIDTH_1BIT) { mss_set_buswidth(host, MSS_BUSWIDTH_1BIT); card->bus_width = MSS_BUSWIDTH_1BIT; } else { if (card->bus_width == MSS_BUSWIDTH_1BIT && host->bus_width == MSS_BUSWIDTH_4BIT) { mss_set_buswidth(host, MSS_BUSWIDTH_4BIT); card->bus_width = MSS_BUSWIDTH_4BIT; ret = mss_send_simple_ll_req(host, llreq, cmd, SD_APP_CMD, sd_card->rca << 16, MSS_RESPONSE_R1, 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -