Add a file to debugfs to read back the SD_STATUS register from an SD
card.  SD_STATUS contains performance-related information.

Signed-off-by: don.mul...@gmail.com
---
 drivers/mmc/core/debugfs.c |   56 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/mmc/core/sd_ops.c  |   51 ++++++++++++++++++++++++++++++++++++++++
 drivers/mmc/core/sd_ops.h  |    1 
 include/linux/mmc/sd.h     |    1 
 4 files changed, 109 insertions(+)

Index: linux-2.6/drivers/mmc/core/sd_ops.c
===================================================================
--- linux-2.6.orig/drivers/mmc/core/sd_ops.c    2009-11-02 15:10:28.000000000 
-0800
+++ linux-2.6/drivers/mmc/core/sd_ops.c 2009-11-02 15:19:01.000000000 -0800
@@ -299,6 +299,57 @@ int mmc_app_send_scr(struct mmc_card *ca
        return 0;
 }
 
+int mmc_send_sd_status(struct mmc_card *card, u32 *sd_status)
+{
+       int err;
+       struct mmc_request mrq;
+       struct mmc_command cmd;
+       struct mmc_data data;
+       struct scatterlist sg;
+       int i;
+
+       BUG_ON(!card);
+       BUG_ON(!card->host);
+       BUG_ON(!sd_status);
+
+       err = mmc_app_cmd(card->host, card);
+       if (err)
+               return err;
+
+       memset(&mrq, 0, sizeof(struct mmc_request));
+       memset(&cmd, 0, sizeof(struct mmc_command));
+       memset(&data, 0, sizeof(struct mmc_data));
+
+       mrq.cmd = &cmd;
+       mrq.data = &data;
+
+       cmd.opcode = SD_APP_SEND_SD_STATUS;
+       cmd.arg = 0;  /* not used */
+       cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
+
+       data.blksz = 16*sizeof(u32);
+       data.blocks = 1;
+       data.flags = MMC_DATA_READ;
+       data.sg = &sg;
+       data.sg_len = 1;
+
+       sg_init_one(&sg, sd_status, 16*sizeof(u32));
+
+       mmc_set_data_timeout(&data, card);
+
+       mmc_wait_for_req(card->host, &mrq);
+
+       if (cmd.error)
+               return cmd.error;
+       if (data.error)
+               return data.error;
+
+       for (i = 0; i < 16; i++)
+               sd_status[i] = be32_to_cpu(sd_status[i]);
+
+       return 0;
+}
+
 int mmc_sd_switch(struct mmc_card *card, int mode, int group,
        u8 value, u8 *resp)
 {
Index: linux-2.6/drivers/mmc/core/sd_ops.h
===================================================================
--- linux-2.6.orig/drivers/mmc/core/sd_ops.h    2009-11-02 15:10:28.000000000 
-0800
+++ linux-2.6/drivers/mmc/core/sd_ops.h 2009-11-02 15:19:01.000000000 -0800
@@ -13,6 +13,7 @@
 #define _MMC_SD_OPS_H
 
 int mmc_app_set_bus_width(struct mmc_card *card, int width);
+int mmc_send_sd_status(struct mmc_card *card, u32 *sd_status);
 int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
 int mmc_send_if_cond(struct mmc_host *host, u32 ocr);
 int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca);
Index: linux-2.6/include/linux/mmc/sd.h
===================================================================
--- linux-2.6.orig/include/linux/mmc/sd.h       2009-11-02 15:10:28.000000000 
-0800
+++ linux-2.6/include/linux/mmc/sd.h    2009-11-02 15:19:01.000000000 -0800
@@ -26,6 +26,7 @@
 #define SD_APP_SEND_NUM_WR_BLKS  22   /* adtc                    R1  */
 #define SD_APP_OP_COND           41   /* bcr  [31:0] OCR         R3  */
 #define SD_APP_SEND_SCR          51   /* adtc                    R1  */
+#define SD_APP_SEND_SD_STATUS    13   /* adtc                    R1  */
 
 /*
  * SD_SWITCH argument format:
Index: linux-2.6/drivers/mmc/core/debugfs.c
===================================================================
--- linux-2.6.orig/drivers/mmc/core/debugfs.c   2009-11-02 15:10:28.000000000 
-0800
+++ linux-2.6/drivers/mmc/core/debugfs.c        2009-11-03 12:29:23.000000000 
-0800
@@ -17,6 +17,7 @@
 
 #include "core.h"
 #include "mmc_ops.h"
+#include "sd_ops.h"
 
 /* The debugfs functions are optimized away when CONFIG_DEBUG_FS isn't set. */
 static int mmc_ios_show(struct seq_file *s, void *data)
@@ -246,6 +247,56 @@ static struct file_operations mmc_dbg_ex
        .release        = mmc_ext_csd_release,
 };
 
+static int mmc_card_sd_status_show(struct seq_file *s, void *data)
+{
+       struct mmc_card *card = s->private;
+       u32             sd_status[16];
+       int             ret;
+
+       mmc_claim_host(card->host);
+
+       /*
+        * Fields as defined in the Simplified SD Spec, available from
+        * http://www.sdcard.org/developers/tech/sdcard/pls/
+        */
+       ret = mmc_send_sd_status(card, sd_status);
+       if (!ret) {
+               int i;
+               const int WIDTH = 24;
+
+               for (i = 0; i < 16; i++)
+                       seq_printf(s, "%3d: %8x\n", 511-i*32, sd_status[i]);
+               seq_printf(s, "\n");
+
+               seq_printf(s, "%-*s %d\n", WIDTH, "SPEED_CLASS:",
+                       UNSTUFF_BITS_ARRAY(sd_status, 440, 8)*2);
+               seq_printf(s, "%-*s %01x\n", WIDTH, "PERFORMANCE_MOVE (MB/s):",
+                       UNSTUFF_BITS_ARRAY(sd_status, 432, 8));
+               seq_printf(s, "%-*s %01x\n", WIDTH, "AU_SIZE (kB):",
+                       (1<<(UNSTUFF_BITS_ARRAY(sd_status, 428, 4)-1))*16);
+               seq_printf(s, "%-*s %d\n", WIDTH, "ERASE_SIZE (AU):",
+                       UNSTUFF_BITS_ARRAY(sd_status, 408, 16));
+               seq_printf(s, "%-*s %d\n", WIDTH, "ERASE_TIMEOUT (sec):",
+                       UNSTUFF_BITS_ARRAY(sd_status, 402, 6));
+       }
+
+       mmc_release_host(card->host);
+
+       return ret;
+}
+
+static int mmc_card_sd_status_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, mmc_card_sd_status_show, inode->i_private);
+}
+
+static const struct file_operations mmc_dbg_card_sd_status_fops = {
+       .open           = mmc_card_sd_status_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
 void mmc_add_card_debugfs(struct mmc_card *card)
 {
        struct mmc_host *host = card->host;
@@ -278,6 +329,11 @@ void mmc_add_card_debugfs(struct mmc_car
                                        &mmc_dbg_ext_csd_fops))
                        goto err;
 
+       if (mmc_card_sd(card))
+               if (!debugfs_create_file("sd_status", S_IRUSR, root, card,
+                                       &mmc_dbg_card_sd_status_fops))
+                       goto err;
+
        return;
 
 err:
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to