?? hho-sd.patch
字號:
* published by the Free Software Foundation.@@ -10,6 +12,7 @@ #include <linux/config.h> #include <linux/module.h> #include <linux/init.h>+#include <linux/wait.h> #include <linux/interrupt.h> #include <linux/completion.h> #include <linux/device.h>@@ -17,6 +20,9 @@ #include <linux/pagemap.h> #include <linux/err.h> +#include <asm/scatterlist.h>+#include <linux/scatterlist.h>+ #include <linux/mmc/card.h> #include <linux/mmc/host.h> #include <linux/mmc/protocol.h>@@ -59,7 +65,6 @@ 35, 40, 45, 50, 55, 60, 70, 80, }; - /** * mmc_request_done - finish processing an MMC command * @host: MMC host which completed command@@ -120,6 +125,11 @@ EXPORT_SYMBOL(mmc_start_request); +static void mmc_uninterruptible_wait_done(struct mmc_request *mrq) {+ clear_bit(MMC_CMD_ACTIVE_BIT, &mrq->flags);+ wake_up(&mrq->wait);+}+ static void mmc_wait_done(struct mmc_request *mrq) { complete(mrq->done_data);@@ -141,6 +151,66 @@ EXPORT_SYMBOL(mmc_wait_for_req); +int mmc_uninterruptible_wait_for_req(struct mmc_host *host, struct mmc_request *mrq) {++ DEFINE_WAIT(wait);++ mrq->done_data = NULL;+ mrq->done = mmc_uninterruptible_wait_done;+ mrq->flags = 0;+ init_waitqueue_head(&mrq->wait);++ set_bit(MMC_CMD_ACTIVE_BIT, &mrq->flags);++ mmc_start_request(host, mrq);++ while(test_bit(MMC_CMD_ACTIVE_BIT, &mrq->flags)) {+ prepare_to_wait_exclusive(&mrq->wait, &wait, + TASK_UNINTERRUPTIBLE);+ + if (test_bit(MMC_CMD_ACTIVE_BIT, &mrq->flags)) + io_schedule();+ + finish_wait(&mrq->wait, &wait);+ }++ return 0;+}++EXPORT_SYMBOL(mmc_uninterruptible_wait_for_req);++/** + * mmc_uninterruptible_cmd - Start a command, and IO schedule until completion + * @host: MMC host to start command+ * @cmd: MMC command to start+ * @retries: maximum number of retries+ * + * Start a new MMC comamnd for a host, and wait for the command to complete.+ * The difference here is that we use the IO scheduler instead of waiting for completion+ */++int mmc_uninterruptible_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries)+{+ struct mmc_request mrq;+ DEFINE_WAIT(wait);++ BUG_ON(host->card_busy == NULL);++ memset(&mrq, 0, sizeof(struct mmc_request));++ memset(cmd->resp, 0, sizeof(cmd->resp));+ cmd->retries = retries;++ mrq.cmd = cmd;+ cmd->data = NULL;++ mmc_uninterruptible_wait_for_req(host, &mrq);++ return cmd->error;+}++EXPORT_SYMBOL(mmc_uninterruptible_cmd);+ /** * mmc_wait_for_cmd - start a command and wait for completion * @host: MMC host to start command@@ -172,7 +242,81 @@ EXPORT_SYMBOL(mmc_wait_for_cmd); +/**+ * mmc_wait_for_app_cmd - start an application command and wait for+ completion+ * @host: MMC host to start command+ * @rca: RCA to send MMC_APP_CMD to+ * @cmd: MMC command to start+ * @retries: maximum number of retries+ *+ * Sends a MMC_APP_CMD, checks the card response, sends the command+ * in the parameter and waits for it to complete. Return any error+ * that occurred while the command was executing. Do not attempt to+ * parse the response.+ */+int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca,+ struct mmc_command *cmd, int retries)+{+ struct mmc_request mrq;+ struct mmc_command appcmd;+ + int i, err;++ BUG_ON(host->card_busy == NULL);+ BUG_ON(retries < 0);+ + err = MMC_ERR_INVALID;+ + /*+ * We have to resend MMC_APP_CMD for each attempt so+ * we cannot use the retries field in mmc_command.+ */+ for (i = 0;i <= retries;i++) {+ memset(&mrq, 0, sizeof(struct mmc_request));++ appcmd.opcode = MMC_APP_CMD;+ appcmd.arg = rca << 16;+ appcmd.flags = MMC_RSP_R1;+ appcmd.retries = 0;+ memset(appcmd.resp, 0, sizeof(appcmd.resp));+ appcmd.data = NULL;+ + mrq.cmd = &appcmd;+ appcmd.data = NULL;+ + mmc_wait_for_req(host, &mrq);+ + if (appcmd.error) {+ err = appcmd.error;+ continue;+ }+ + /* Check that card supported application commands */+ if (!(appcmd.resp[0] & R1_APP_CMD))+ return MMC_ERR_FAILED;++ memset(&mrq, 0, sizeof(struct mmc_request));++ memset(cmd->resp, 0, sizeof(cmd->resp));+ cmd->retries = 0;++ mrq.cmd = cmd;+ cmd->data = NULL;++ mmc_wait_for_req(host, &mrq);+ + err = cmd->error;+ if (cmd->error == MMC_ERR_NONE)+ break;+ }++ return err;+} +EXPORT_SYMBOL(mmc_wait_for_app_cmd);++static int mmc_select_card(struct mmc_host *host, struct mmc_card *card); /** * __mmc_claim_host - exclusively claim a host@@ -206,16 +350,10 @@ spin_unlock_irqrestore(&host->lock, flags); remove_wait_queue(&host->wq, &wait); - if (card != (void *)-1 && host->card_selected != card) {- struct mmc_command cmd;-- host->card_selected = card;-- cmd.opcode = MMC_SELECT_CARD;- cmd.arg = card->rca << 16;- cmd.flags = MMC_RSP_R1;-- err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);+ if (card != (void *)-1) {+ err = mmc_select_card(host, card);+ if (err != MMC_ERR_NONE)+ return err; } return err;@@ -245,6 +383,63 @@ EXPORT_SYMBOL(mmc_release_host); +static int mmc_select_card(struct mmc_host *host, struct mmc_card *card)+{+ int err;+ struct mmc_command cmd;++ BUG_ON(host->card_busy == NULL);+ + 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;++ err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);+ if (err != MMC_ERR_NONE)+ return err;++ /*+ * Default bus width is 1 bit.+ */+ host->ios.bus_width = MMC_BUS_WIDTH_1;+ + /*+ * We can only change the bus width of the selected+ * card so therefore we have to put the handling+ * here.+ */+ if (host->caps & MMC_CAP_4_BIT_DATA) {+ /*+ * The card is in 1 bit mode by default so+ * we only need to change if it supports the+ * wider version.+ */+ if (mmc_card_sd(card) &&+ (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {+ struct mmc_command cmd;+ cmd.opcode = SD_APP_SET_BUS_WIDTH;+ cmd.arg = SD_BUS_WIDTH_4;+ cmd.flags = MMC_RSP_R1;+ + err = mmc_wait_for_app_cmd(host, card->rca, &cmd,+ CMD_RETRIES);+ if (err != MMC_ERR_NONE)+ return err;+ + host->ios.bus_width = MMC_BUS_WIDTH_4;+ }+ }++ host->ops->set_ios(host, &host->ios);++ return MMC_ERR_NONE;+}+ /* * Ensure that no card is selected. */@@ -322,12 +517,33 @@ memset(&card->cid, 0, sizeof(struct mmc_cid)); + if (mmc_card_sd(card)) { /*- * The selection of the format here is guesswork based upon- * information people have sent to date.+ * 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.? */+ 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);@@ -344,8 +560,8 @@ card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997; break; - case 2: /* MMC v2.x ? */- case 3: /* MMC v3.x ? */+ 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);@@ -365,6 +581,7 @@ mmc_card_set_bad(card); break; }+ } } /*@@ -376,9 +593,35 @@ 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) {+ printk("%s: unrecognised CSD structure version %d\n",+ card->host->host_name, 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);++ csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);+ }+ else { /*- * We only understand CSD structure v1.1 and v2.- * v2 has extra information in bits 15, 11 and 10.+ * 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) {@@ -404,6 +647,33 @@ 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;+ u32 resp[4];++ BUG_ON(!mmc_card_sd(card));+ + resp[3] = card->raw_scr[1];+ resp[2] = card->raw_scr[0];+ + scr_struct = UNSTUFF_BITS(resp, 60, 4);+ if (scr_struct != 0) {+ printk("%s: unrecognised SCR structure version %d\n",+ card->host->host_name, scr_struct);+ mmc_card_set_bad(card);+ return;+ }+ + scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4);+ scr->bus_widths = UNSTUFF_BITS(resp, 48, 4); } /*@@ -476,6 +746,7 @@ host->ios.vdd = bit; host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; 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);@@ -493,6 +764,7 @@ host->ios.vdd = 0; host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; host->ios.power_mode = MMC_POWER_OFF;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -