📄 sdio.patch
字号:
+ else+ err = MMC_ERR_NO_SDIO;+ + return err;+}++static inline +void sdio_card_unregister (struct mmc_host* host, struct sd_card *card) {+ if (host->sdio_host != NULL)+ host->sdio_host->ops->sdio_card_unregister(card);+}++static inline +int sdio_card_read_cia (struct mmc_host* host, struct sd_card* card) {+ int err = MMC_ERR_NONE;+ + if (host->sdio_host != NULL)+ err = host->sdio_host->ops->sdio_card_read_cia(card);+ else+ err = MMC_ERR_NO_SDIO;+ + return err;+}++static inline +int sdio_card_decode_buffer (struct mmc_host* host,+ struct sd_card* card,+ void* buffer,+ unsigned int sdio_buffer_type) {+#define SDIO_BUFFER_TYPE_R4 4+ int err = MMC_ERR_NONE;+ + if (host->sdio_host != NULL)+ err = host->sdio_host->ops->sdio_card_decode_buffer(card,+ buffer,+ sdio_buffer_type);+ else+ err = MMC_ERR_NO_SDIO;+ + return err;+}+ /** * mmc_request_done - finish processing an MMC command * @host: MMC host which completed command@@ -78,15 +146,31 @@ { struct mmc_command *cmd = mrq->cmd; int err = mrq->cmd->error;- DBG("MMC: req done (%02x): %d: %08x %08x %08x %08x\n", cmd->opcode,- err, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); if (err && cmd->retries) {+ DBG("Retry request\n"); cmd->retries--; cmd->error = 0; host->ops->request(host, mrq);- } else if (mrq->done) {- mrq->done(mrq);+ }+ else {+ if (err)+ DBG("DONE: cmd %d: failed: error = %d\n",+ cmd->opcode, err);+ else+ DBG("DONE: cmd %d: success: resp = %08x %08x %08x %08x\n", + cmd->opcode,+ cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);+ if (mrq->data) {+ if ((mrq->data->flags & MMC_DATA_READ) != 0)+ DBG("Data bytes received: 0x%02x\n",+ mrq->data->bytes_xfered);+ else+ DBG("Data bytes transmitted: 0x%02x\n",+ mrq->data->bytes_xfered);+ }+ if (mrq->done)+ mrq->done(mrq); } } @@ -103,7 +187,7 @@ void mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) {- DBG("MMC: starting cmd %02x arg %08x flags %08x\n",+ DBG("REQU: cmd %d, arg %08x, flags %08x\n", mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags); WARN_ON(host->card_busy == NULL);@@ -393,8 +477,6 @@ if (host->card_selected == card) return MMC_ERR_NONE; - host->card_selected = card;- cmd.opcode = MMC_SELECT_CARD; cmd.arg = card->rca << 16; cmd.flags = MMC_RSP_R1;@@ -403,6 +485,8 @@ if (err != MMC_ERR_NONE) return err; + host->card_selected = card;+ /* * Default bus width is 1 bit. */@@ -494,20 +578,6 @@ return ocr; } -#define UNSTUFF_BITS(resp,start,size) \- ({ \- const int __size = size; \- const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; \- const int __off = 3 - ((start) / 32); \- const int __shft = (start) & 31; \- u32 __res; \- \- __res = resp[__off] >> __shft; \- if (__size + __shft > 32) \- __res |= resp[__off-1] << ((32 - __shft) % 32); \- __res & __mask; \- })- /* * Given the decoded CSD structure, decode the raw CID to our CID structure. */@@ -518,7 +588,7 @@ 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. */@@ -541,46 +611,46 @@ /* * The selection of the format here is based upon published * specs from sandisk and from what people have reported.- */- switch (card->csd.mmca_vsn) {+ */+ 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 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;+ 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; - default:- printk("%s: card has unknown MMCA version %d\n",- card->host->host_name, card->csd.mmca_vsn);- mmc_card_set_bad(card);- break;- }+ default:+ printk("%s: card has unknown MMCA version %d\n",+ card->host->host_name, card->csd.mmca_vsn);+ mmc_card_set_bad(card);+ break;+ } } } @@ -592,7 +662,7 @@ struct mmc_csd *csd = &card->csd; unsigned int e, m, csd_struct; u32 *resp = card->raw_csd;-+ if (mmc_card_sd(card)) { csd_struct = UNSTUFF_BITS(resp, 126, 2); if (csd_struct != 0) {@@ -619,34 +689,34 @@ csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); } 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) {- printk("%s: unrecognised CSD structure version %d\n",- card->host->host_name, csd_struct);- mmc_card_set_bad(card);- return;- }+ */+ csd_struct = UNSTUFF_BITS(resp, 126, 2);+ if (csd_struct != 1 && csd_struct != 2) {+ printk("%s: unrecognised CSD structure version %d\n",+ card->host->host_name, 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->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; - csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);+ 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); } } @@ -678,12 +748,14 @@ /* * Locate a MMC card on this MMC host given a raw CID.+ * + * This applies only to memory cards. */ static struct mmc_card *mmc_find_card(struct mmc_host *host, u32 *raw_cid) { struct mmc_card *card; - list_for_each_entry(card, &host->cards, node) {+ list_for_each_entry(card, &host->mem_cards, mem_node) { if (memcmp(card->raw_cid, raw_cid, sizeof(card->raw_cid)) == 0) return card; }@@ -703,24 +775,42 @@ if (!card) return ERR_PTR(-ENOMEM); - mmc_init_card(card, host);+ memset(card, 0, sizeof(struct mmc_card));+ card->host = host; memcpy(card->raw_cid, raw_cid, sizeof(card->raw_cid)); + /* MMC cards should be initialized with rca != 0 */+ /* SD memory and SDIO cards should be initialized with rca = 0. + This will be changed after sending SEND_RELATIVE_ADDRESS command.+ */+ if (host->mode == MMC_MODE_MMC) { again:- list_for_each_entry(c, &host->cards, node)- if (c->rca == rca) {- rca++;- goto again;- }-- card->rca = rca;-- *frca = rca;-+ list_for_each_entry(c, &host->cards, node)+ if (c->rca == rca) {+ rca++;+ goto again;+ }+ card->rca = rca;+ *frca = rca;+ }+ else {+ card->rca = 0;+ }+ return card; } /*+ * Free an MMC card+ */+static void+mmc_free_card(struct mmc_card * card)+{+ if (card != NULL)+ kfree(card);+}++/* * Tell attached cards to go to IDLE state */ static void mmc_idle_cards(struct mmc_host *host)@@ -806,7 +896,7 @@ cmd.flags = MMC_RSP_R3; for (i = 100; i; i--) {- err = mmc_wait_for_app_cmd(host, 0, &cmd, CMD_RETRIES);+ err = mmc_wait_for_app_cmd(host, 0, &cmd, 0); if (err != MMC_ERR_NONE) break; @@ -824,6 +914,38 @@ return err; } +static int sdio_send_op_cond(struct mmc_host *host, u32 ocr, u32* response)+{+ struct mmc_command cmd;+ int i = 0;+ int err = MMC_ERR_NONE;+ + cmd.opcode = SD_IO_SEND_OP_COND;+ cmd.arg = ocr;+ cmd.flags = SDIO_RSP_R4 | SDIO_DAT_NONE;+ + for (i = 100; i; i--) {+ err = mmc_wait_for_cmd(host, &cmd, 0);+ if (err != MMC_ERR_NONE)+ break;++ if (cmd.resp[0] & SDIO_CARD_BUSY || ocr == 0)+ break;++ err = MMC_ERR_TIMEOUT;++ mmc_delay(10);+ }+ + if (err == MMC_ERR_NONE) {+ if (response != NULL) {+ *response = cmd.resp[0];+ }+ }+ + return err;+}+ /* * Discover cards by requesting their CID. If this command * times out, it is not an error; there are no further cards@@ -863,10 +985,11 @@ break; } list_add(&card->node, &host->cards);+ list_add(&card->mem_node, &host->mem_cards); } card->state &= ~MMC_STATE_DEAD;-+ if (host->mode == MMC_MODE_SD) { mmc_card_set_sd(card); @@ -877,8 +1000,23 @@ err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); if (err != MMC_ERR_NONE) mmc_card_set_dead(card);- else { - card->rca = cmd.resp[0] >> 16;+ else {+ struct mmc_card *c;+ + /* If this is the first SD memory card found, + this will change the RCA of an SDIO card + also. (Since the RCA of that card is also + set to 0.) This is needed for combo cards + that only have one RCA register per SD card.+ + Note:+ We assume the first SD memory card + found to be part of the combo card. */+ list_for_each_entry(c, &host->cards, node)+ if (c->rca == 0) {+ c->rca = cmd.resp[0] >> 16;+ DBG("FOUND: SD memory/combo card: RCA = 0x%04x\n", c->rca);+ } if (!host->ops->get_ro) { printk(KERN_WARNING "%s: host does not "@@ -893,14 +1031,57 @@ } } else {- cmd.opcode = MMC_SET_RELATIVE_ADDR;- cmd.arg = card->rca << 16;- cmd.flags = MMC_RSP_R1;+ cmd.opcode = MMC_SET_RELATIVE_ADDR;+ cmd.arg = card->rca << 16;+ cmd.flags = MMC_RSP_R1;++ err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);+ if (err != MMC_ERR_NONE)+ mmc_card_set_dead(card);+ else+ DBG("FOUND: MMC card: RCA = 0x%04x\n", card->rca);+ }+ }+} +static void sdio_assign_rca(struct mmc_host* host) {+ /* Set SD relative card address */+ unsigned int err = MMC_ERR_NONE;+ struct mmc_command cmd;+ struct mmc_card *c = NULL;+ unsigned int newrca = 0;+ + list_for_each_entry(c, &host->cards, node) {+ if (mmc_card_dead(c))+ continue;+ if (c->rca != 0)+ continue;+ /* Address is not yet assigned */+ /* Get new RCA from card */+ cmd.opcode = SD_SEND_RELATIVE_ADDR;+ cmd.arg = 0;+ cmd.flags = MMC_RSP_R1;+ err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);- if (err != MMC_ERR_NONE)- mmc_card_set_dead(card);+ + if (err == MMC_ERR_NONE) {+ newrca = cmd.resp[0] >> 16;+ }+ break; }+ + list_for_each_entry(c, &host->cards, node) {+ if (mmc_card_dead(c))+ continue;+ if (c->rca != 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -