📄 mmc.c
字号:
#endif/* * Given the decoded CSD structure, decode the raw CID to our CID structure. */static void mmc_decode_cid(struct mmc_card *card){ u16 *resp =(unsigned short *) card->raw_cid; memset(&card->cid, 0, sizeof(struct mmc_cid)); if (mmc_card_sd(card)) { /* * SD doesn't currently have a version field so we will * have to assume we can parse this. */ card->cid.manfid = UNSTUFF_BITS(resp, 120, 8); card->cid.oemid = UNSTUFF_BITS(resp, 104, 16); card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8); card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8); card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8); card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8); card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8); card->cid.hwrev = UNSTUFF_BITS(resp, 60, 4); card->cid.fwrev = UNSTUFF_BITS(resp, 56, 4); card->cid.serial = UNSTUFF_BITS(resp, 24, 32); card->cid.year = UNSTUFF_BITS(resp, 12, 8); card->cid.month = UNSTUFF_BITS(resp, 8, 4); card->cid.year += 2000; /* SD cards year offset */ } else { /* * The selection of the format here is based upon published * specs from sandisk and from what people have reported. */ switch (card->csd.mmca_vsn) { case 0: /* MMC v1.0 - v1.2 */ case 1: /* MMC v1.4 */ card->cid.manfid = UNSTUFF_BITS(resp, 104, 24); card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8); card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8); card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8); card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8); card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8); card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8); card->cid.prod_name[6] = UNSTUFF_BITS(resp, 48, 8); card->cid.hwrev = UNSTUFF_BITS(resp, 44, 4); card->cid.fwrev = UNSTUFF_BITS(resp, 40, 4); card->cid.serial = UNSTUFF_BITS(resp, 16, 24); card->cid.month = UNSTUFF_BITS(resp, 12, 4); card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997; break; case 2: /* MMC v2.0 - v2.2 */ case 3: /* MMC v3.1 - v3.3 */ card->cid.manfid = UNSTUFF_BITS(resp, 120, 8); card->cid.oemid = UNSTUFF_BITS(resp, 104, 16); card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8); card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8); card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8); card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8); card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8); card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8); card->cid.serial = UNSTUFF_BITS(resp, 16, 32); card->cid.month = UNSTUFF_BITS(resp, 12, 4); card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997; break; case 4: break; default: mmc_debug_msg("%s: card has unknown MMCA version %d\n", mmc_hostname(card->host), card->csd.mmca_vsn); mmc_card_set_bad(card); break; } }}static void mmc_decode_csd(struct mmc_card *card){ struct mmc_csd *csd = &card->csd; unsigned int e, m, csd_struct; u16 *resp =(unsigned short *) card->raw_csd; if (mmc_card_sd(card)) { csd_struct = UNSTUFF_BITS(resp, 126, 2); if (csd_struct != 0) { mmc_debug_msg("%s: unrecognised CSD structure version %d\n", mmc_hostname(card->host), csd_struct); mmc_card_set_bad(card); return; } m = UNSTUFF_BITS(resp, 115, 4); e = UNSTUFF_BITS(resp, 112, 3); csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10; csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100; m = UNSTUFF_BITS(resp, 99, 4); e = UNSTUFF_BITS(resp, 96, 3); csd->max_dtr = tran_exp[e] * tran_mant[m]; csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); e = UNSTUFF_BITS(resp, 47, 3); m = UNSTUFF_BITS(resp, 62, 12); csd->capacity = (1 + m) << (e + 2); mmc_debug_msg ("device_size : %d\n",m); mmc_debug_msg ("device_size multiplier: %d\n",e); //printk("\nCapacity : %d MB\n",(csd->capacity)/(2048)); csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); mmc_debug_msg ("blocklen : %d\n",(1 <<csd->read_blkbits)); } else { /* * We only understand CSD structure v1.1 and v1.2. * v1.2 has extra information in bits 15, 11 and 10. */ csd_struct = UNSTUFF_BITS(resp, 126, 2); if (csd_struct != 1 && csd_struct != 2) { mmc_debug_msg("%s: unrecognised CSD structure version %d\n", mmc_hostname(card->host), csd_struct); mmc_card_set_bad(card); return; } csd->mmca_vsn = UNSTUFF_BITS(resp, 122, 4); m = UNSTUFF_BITS(resp, 115, 4); e = UNSTUFF_BITS(resp, 112, 3); csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10; csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100; m = UNSTUFF_BITS(resp, 99, 4); e = UNSTUFF_BITS(resp, 96, 3); csd->max_dtr = tran_exp[e] * tran_mant[m]; csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); e = UNSTUFF_BITS(resp, 47, 3); m = UNSTUFF_BITS(resp, 62, 12); csd->capacity = (1 + m) << (e + 2); csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); }}/* * Given a 64-bit response, decode to our card SCR structure. */static void mmc_decode_scr(struct mmc_card *card){ struct sd_scr *scr = &card->scr; unsigned int scr_struct; u16 resp[4];#if 1 BUG_ON(!mmc_card_sd(card)); resp[0] = card->raw_scr[0]; resp[1] = card->raw_scr[1]; resp[2] = card->raw_scr[2]; resp[3] = card->raw_scr[3]; scr_struct = (resp[0] >> 12) & 0x000F; if (scr_struct != 0) { printk("%s: unrecognised SCR structure version %d\n", mmc_hostname(card->host), scr_struct); mmc_card_set_bad(card); return; } scr->sda_vsn = (resp[0] >> 9) & 0x000F ; scr->bus_widths = resp[0] & 0x000F;#else scr->bus_widths = SD_SCR_BUS_WIDTH_4;#endif}/* * Locate a MMC card on this MMC host given a raw CID. *///static struct mmc_card *mmc_find_card(struct mmc_host *host, u32 *raw_cid)static struct mmc_card *mmc_find_card(struct mmc_host *host, u16 *raw_cid){ struct mmc_card *card; list_for_each_entry(card, &host->cards, node) { if (memcmp(card->raw_cid, raw_cid, sizeof(card->raw_cid)) == 0) return card; } return NULL;}/* * Allocate a new MMC card, and assign a unique RCA. */static struct mmc_card *mmc_alloc_card(struct mmc_host *host, u16 *raw_cid, unsigned int *frca){ struct mmc_card *card, *c; unsigned int rca = *frca; card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL); if (!card) return ERR_PTR(-ENOMEM); mmc_init_card(card, host); memcpy(card->raw_cid, raw_cid, sizeof(card->raw_cid)); again: list_for_each_entry(c, &host->cards, node) if (c->rca == rca) { rca++; goto again; } card->rca = rca; *frca = rca; return card;}/* * Tell attached cards to go to IDLE state */static void mmc_idle_cards(struct mmc_host *host){ struct mmc_command cmd; host->ios.chip_select = MMC_CS_HIGH; host->ops->set_ios(host, &host->ios); //mmc_delay(1); cmd.opcode = MMC_GO_IDLE_STATE | 0x0000; cmd.arg = 0; cmd.flags = MMCSD_RSPNONE; mmc_wait_for_cmd(host, &cmd, 0); //mmc_delay(1); host->ios.chip_select = MMC_CS_DONTCARE; host->ops->set_ios(host, &host->ios); //mmc_delay(1);}/* * Apply power to the MMC stack. */static void mmc_power_up(struct mmc_host *host){ int bit = fls(host->ocr_avail) - 1; host->ios.vdd = bit; host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; host->ios.chip_select = MMC_CS_DONTCARE; host->ios.power_mode = MMC_POWER_UP; host->ios.bus_width = MMC_BUS_WIDTH_1; host->ops->set_ios(host, &host->ios); mmc_delay(1); host->ios.clock = host->f_min; host->ios.power_mode = MMC_POWER_ON; host->ops->set_ios(host, &host->ios); mmc_delay(2);}static void mmc_power_off(struct mmc_host *host){ host->ios.clock = 0; host->ios.vdd = 0; host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; host->ios.chip_select = MMC_CS_DONTCARE; host->ios.power_mode = MMC_POWER_OFF; host->ios.bus_width = MMC_BUS_WIDTH_1; host->ops->set_ios(host, &host->ios);}static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr){ struct mmc_command cmd; int err = 0; cmd.opcode = MMC_SEND_OP_COND; cmd.arg = ocr; cmd.flags = MMCSD_RSP3; err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); while (!((cmd.resp[6]|(cmd.resp[7] << 16)) & MMC_CARD_BUSY || ocr == 0)){ if (err != MMC_ERR_NONE) break; err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); mdelay(2); } if (rocr) *rocr = cmd.resp[6]|(cmd.resp[7] << 16); return err;}static int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr){ struct mmc_command cmd; int err = 0; cmd.opcode = SD_APP_OP_COND; cmd.arg = ocr; cmd.flags = MMCSD_RSP3;#if 0 for (i = 200; i; i--) { err = mmc_wait_for_app_cmd(host, 0, &cmd, CMD_RETRIES); if (err != MMC_ERR_NONE) break; if ((cmd.resp[6]|(cmd.resp[7] << 16)) & MMC_CARD_BUSY || ocr == 0){ break; } err = MMC_ERR_TIMEOUT; mdelay(2); }#endif#if 1 err = mmc_wait_for_app_cmd(host, 0, &cmd, CMD_RETRIES); while (!((cmd.resp[6]|(cmd.resp[7] << 16)) & MMC_CARD_BUSY || ocr == 0)){ if (err != MMC_ERR_NONE) break; err = mmc_wait_for_app_cmd(host, 0, &cmd, CMD_RETRIES); mdelay(2); }#endif if (rocr) *rocr = cmd.resp[6]|(cmd.resp[7] << 16); return err;}/* * Discover cards by requesting their CID. If this command * times out, it is not an error; there are no further cards * to be discovered. Add new cards to the list. * * Create a mmc_card entry for each discovered card, assigning * it an RCA, and save the raw CID for decoding later. */static void mmc_discover_cards(struct mmc_host *host){ struct mmc_card *card; unsigned int first_rca = 1, err; while (1) { struct mmc_command cmd; cmd.opcode = MMC_ALL_SEND_CID; cmd.arg = 0; cmd.flags = MMCSD_RSP2; err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); if (err == MMC_ERR_TIMEOUT) { err = MMC_ERR_NONE; break; } if (err != MMC_ERR_NONE) { printk(KERN_ERR "%s: error requesting CID: %d\n", mmc_hostname(host), err); break; } mmc_debug_msg ("%s in %d\n",__FUNCTION__,__LINE__); card = (struct mmc_card *)mmc_find_card(host, cmd.resp); if (!card) { mmc_debug_msg ("%s in %d\n",__FUNCTION__,__LINE__); card = mmc_alloc_card(host, cmd.resp, &first_rca); if (IS_ERR(card)) { err = PTR_ERR(card); break; } list_add(&card->node, &host->cards); } card->state &= ~MMC_STATE_DEAD; if (host->mode == MMC_MODE_SD) { mmc_card_set_sd(card); cmd.opcode = SD_SEND_RELATIVE_ADDR; cmd.arg = 0; cmd.flags = MMCSD_RSP1; err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); if (err != MMC_ERR_NONE) mmc_card_set_dead(card); else { card->rca = cmd.resp[7]; if (!host->ops->get_ro) { printk(KERN_WARNING "%s: host does not " "support reading read-only " "switch. assuming write-enable.\n", mmc_hostname(host)); } else { if (host->ops->get_ro(host)){ mmc_card_set_readonly(card); } } } } else { cmd.opcode = MMC_SET_RELATIVE_ADDR; cmd.arg = card->rca << 16; cmd.flags = MMCSD_RSP6; err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); if (err != MMC_ERR_NONE) mmc_card_set_dead(card); } }}static void mmc_read_csds(struct mmc_host *host){ struct mmc_card *card; mmc_debug_msg ("%s %d card->state : %d\n",__FUNCTION__,__LINE__,card->state); list_for_each_entry(card, &host->cards, node) { struct mmc_command cmd; int err; if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT)) continue; cmd.opcode = MMC_SEND_CSD; cmd.arg = card->rca << 16; cmd.flags = MMCSD_RSP2; err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); if (err != MMC_ERR_NONE) { mmc_card_set_dead(card); continue; } memcpy(card->raw_csd, cmd.resp, sizeof(card->raw_csd)); mmc_decode_csd(card); mmc_decode_cid(card); }}static void mmc_disable_pull_up(struct mmc_host *host){ int err; struct mmc_card *card; struct mmc_command cmd; list_for_each_entry(card, &host->cards, node) { if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT)) continue; if (!mmc_card_sd(card)) continue; err = mmc_select_card(host, card); if (err != MMC_ERR_NONE) { mmc_card_set_dead(card); continue; } memset(&cmd, 0, sizeof(struct mmc_command)); cmd.opcode = MMC_APP_CMD; cmd.arg = card->rca << 16; cmd.flags = MMCSD_RSP1; err = mmc_wait_for_cmd(host, &cmd, 0); if ((err != MMC_ERR_NONE) || !(cmd.resp[6] & R1_APP_CMD)) { mmc_card_set_dead(card); continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -