tree 39592e326f498231b39e95c299ad6fcd559341ef
parent a00fc09029f02ca833cf90e5d5625f08c4ac4f51
author Pierre Ossman <[EMAIL PROTECTED]> Wed, 07 Sep 2005 05:18:53 -0700
committer Linus Torvalds <[EMAIL PROTECTED]> Thu, 08 Sep 2005 06:57:50 -0700

[PATCH] sd: SCR register

Read the SD specific SCR register from the card.

Signed-off-by: Pierre Ossman <[EMAIL PROTECTED]>
Cc: Russell King <[EMAIL PROTECTED]>
Cc: David Brownell <[EMAIL PROTECTED]>
Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>

 drivers/mmc/mmc.c        |  143 +++++++++++++++++++++++++++++++++++++++++++----
 include/linux/mmc/card.h |    9 ++
 2 files changed, 142 insertions(+), 10 deletions(-)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -16,6 +16,8 @@
 #include <linux/delay.h>
 #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>
@@ -246,6 +248,8 @@ int mmc_wait_for_app_cmd(struct mmc_host
 
 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
  *     @host: mmc host to claim
@@ -278,16 +282,10 @@ int __mmc_claim_host(struct mmc_host *ho
        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;
@@ -317,6 +315,29 @@ void mmc_release_host(struct mmc_host *h
 
 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;
+
+       return MMC_ERR_NONE;
+}
+
 /*
  * Ensure that no card is selected.
  */
@@ -526,6 +547,32 @@ static void mmc_decode_csd(struct mmc_ca
 }
 
 /*
+ * 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",
+                       mmc_hostname(card->host), scr_struct);
+               mmc_card_set_bad(card);
+               return;
+       }
+
+       scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4);
+       scr->bus_widths = UNSTUFF_BITS(resp, 48, 4);
+}
+
+/*
  * 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)
@@ -789,6 +836,79 @@ static void mmc_read_csds(struct mmc_hos
        }
 }
 
+static void mmc_read_scrs(struct mmc_host *host)
+{
+       int err;
+       struct mmc_card *card;
+
+       struct mmc_request mrq;
+       struct mmc_command cmd;
+       struct mmc_data data;
+
+       struct scatterlist sg;
+
+       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 = MMC_RSP_R1;
+
+               err = mmc_wait_for_cmd(host, &cmd, 0);
+               if ((err != MMC_ERR_NONE) || !(cmd.resp[0] & R1_APP_CMD)) {
+                       mmc_card_set_dead(card);
+                       continue;
+               }
+
+               memset(&cmd, 0, sizeof(struct mmc_command));
+
+               cmd.opcode = SD_APP_SEND_SCR;
+               cmd.arg = 0;
+               cmd.flags = MMC_RSP_R1;
+
+               memset(&data, 0, sizeof(struct mmc_data));
+
+               data.timeout_ns = card->csd.tacc_ns * 10;
+               data.timeout_clks = card->csd.tacc_clks * 10;
+               data.blksz_bits = 3;
+               data.blocks = 1;
+               data.flags = MMC_DATA_READ;
+               data.sg = &sg;
+               data.sg_len = 1;
+
+               memset(&mrq, 0, sizeof(struct mmc_request));
+
+               mrq.cmd = &cmd;
+               mrq.data = &data;
+
+               sg_init_one(&sg, (u8*)card->raw_scr, 8);
+
+               err = mmc_wait_for_req(host, &mrq);
+               if (err != MMC_ERR_NONE) {
+                       mmc_card_set_dead(card);
+                       continue;
+               }
+
+               card->raw_scr[0] = ntohl(card->raw_scr[0]);
+               card->raw_scr[1] = ntohl(card->raw_scr[1]);
+
+               mmc_decode_scr(card);
+       }
+
+       mmc_deselect_cards(host);
+}
+
 static unsigned int mmc_calculate_clock(struct mmc_host *host)
 {
        struct mmc_card *card;
@@ -912,6 +1032,9 @@ static void mmc_setup(struct mmc_host *h
        host->ops->set_ios(host, &host->ios);
 
        mmc_read_csds(host);
+
+       if (host->mode == MMC_MODE_SD)
+               mmc_read_scrs(host);
 }
 
 
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -33,6 +33,13 @@ struct mmc_csd {
        unsigned int            capacity;
 };
 
+struct sd_scr {
+       unsigned char           sda_vsn;
+       unsigned char           bus_widths;
+#define SD_SCR_BUS_WIDTH_1     (1<<0)
+#define SD_SCR_BUS_WIDTH_4     (1<<2)
+};
+
 struct mmc_host;
 
 /*
@@ -51,8 +58,10 @@ struct mmc_card {
 #define MMC_STATE_READONLY     (1<<4)          /* card is read-only */
        u32                     raw_cid[4];     /* raw card CID */
        u32                     raw_csd[4];     /* raw card CSD */
+       u32                     raw_scr[2];     /* raw card SCR */
        struct mmc_cid          cid;            /* card identification */
        struct mmc_csd          csd;            /* card specific */
+       struct sd_scr           scr;            /* extra SD information */
 };
 
 #define mmc_card_present(c)    ((c)->state & MMC_STATE_PRESENT)
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to