[PATCH 1/1] Implementation for knowing speed_class of inserted SD card from user space

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Dear All,

The below patch allows an application to know the speed_class of the
inserted SD card. Since the MMC cards do not specify speed_class, I'm
making the speed_class to indicate as 0xFF. The coding of the
speed_class is same as present in the SD Simplified specification.

simplified SD spec:
http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf

See page 65 and 66

SPEED_CLASS
This 8-bit field indicates the Speed Class and the value can be
calculated by Pw/2.
SPEED_CLASS Value Definition
00h Class 0
01h Class 2
02h Class 4
03h Class 6
04h – FFh Reserved
Table 4-38: Speed Class Code Field

The changes were tested in our platform, which displayed the proper
speed_class for inserted SD cards (6 of them were tested) and one
MMCMobile card.

The speed_class can be known by looking at sysfs entries at :
/sys/devices/platform/nx_sdiomc.0/mmc_host/mmc0/mmc0:XXXX/speed_class

	This file contains the speed class of the SD/MMC card that is
inserted. Please note that, speed_class is not applicable for MMC
cards. This file contains a hexadecimal number. Interpretation shall
be like as below:
0x00 à Class 0
0x01 à Class 2
0x02 à Class 4
0x03 à Class 6
0x04 to 0xFF à Reserved (currently, for MMC based cards, it is 0xFF)

(where in nx_sdiomc.0 is our platform driver for sdhci)

Let me know if you have any comments/suggestions?

Regards,
Mahadev K Cholachagudda

diff -urNd linux-orig/drivers/mmc/core/mmc.c
linux-current/drivers/mmc/core/mmc.c
--- linux-orig/drivers/mmc/core/mmc.c	2009-09-30 16:52:16.973273403 +0530
+++ linux-current/drivers/mmc/core/mmc.c	2009-09-30 17:06:48.321273501 +0530
@@ -258,6 +258,7 @@
 MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name);
 MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid);
 MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial);
+MMC_DEV_ATTR(speed_class, "0x%02x\n", card->speed_class);

 static struct attribute *mmc_std_attrs[] = {
 	&dev_attr_cid.attr,
@@ -269,6 +270,7 @@
 	&dev_attr_name.attr,
 	&dev_attr_oemid.attr,
 	&dev_attr_serial.attr,
+	&dev_attr_speed_class.attr,
 	NULL,
 };

@@ -454,6 +456,12 @@
 		mmc_set_bus_width(card->host, bus_width);
 	}

+	/*
+	 * to indicate speed_class reserved, as MMC card do not indicate
+	 * any speed_class
+	 * */
+	card->speed_class = 0xFF;
+
 	if (!oldcard)
 		host->card = card;

diff -urNd linux-orig/drivers/mmc/core/sd.c linux-current/drivers/mmc/core/sd.c
--- linux-orig/drivers/mmc/core/sd.c	2009-09-30 16:52:10.588335882 +0530
+++ linux-current/drivers/mmc/core/sd.c	2009-09-30 17:03:59.458273462 +0530
@@ -294,6 +294,7 @@
 MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name);
 MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid);
 MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial);
+MMC_DEV_ATTR(speed_class, "0x%02x\n", card->speed_class);


 static struct attribute *sd_std_attrs[] = {
@@ -307,6 +308,7 @@
 	&dev_attr_name.attr,
 	&dev_attr_oemid.attr,
 	&dev_attr_serial.attr,
+	&dev_attr_speed_class.attr,
 	NULL,
 };

@@ -508,6 +510,20 @@
 		}
 	}

+	if (!oldcard) {
+		/* get the speed class */
+		u8 *sd_status;
+		sd_status = kmalloc(64, GFP_KERNEL);
+		if(!sd_status)
+			goto free_card;
+
+		err = mmc_app_sd_status(card, sd_status);
+		card->speed_class = sd_status[8];
+		kfree(sd_status);
+		if(err)
+			goto free_card;
+	}
+
 	if (!oldcard)
 		host->card = card;

diff -urNd linux-orig/drivers/mmc/core/sd_ops.c
linux-current/drivers/mmc/core/sd_ops.c
--- linux-orig/drivers/mmc/core/sd_ops.c	2009-09-30 16:52:22.195336136 +0530
+++ linux-current/drivers/mmc/core/sd_ops.c	2009-09-30 17:01:11.901274205 +0530
@@ -348,3 +348,50 @@
 	return 0;
 }

+int mmc_app_sd_status(struct mmc_card *card, u8 *sd_status)
+{
+	int err;
+	struct mmc_request mrq;
+	struct mmc_command cmd;
+	struct mmc_data data;
+	struct scatterlist sg;
+
+	BUG_ON(!card);
+	BUG_ON(!card->host);
+	BUG_ON(!sd_status);
+
+	/* NOTE: caller guarantees sd_status is heap-allocated */
+	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 = 13;
+	cmd.arg = 0;
+	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
+
+	data.blksz = 64;
+	data.blocks = 1;
+	data.flags = MMC_DATA_READ;
+	data.sg = &sg;
+	data.sg_len = 1;
+
+	sg_init_one(&sg, sd_status, 64);
+
+	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;
+	return 0;
+}
+
diff -urNd linux-orig/drivers/mmc/core/sd_ops.h
linux-current/drivers/mmc/core/sd_ops.h
--- linux-orig/drivers/mmc/core/sd_ops.h	2009-09-30 16:52:25.708273492 +0530
+++ linux-current/drivers/mmc/core/sd_ops.h	2009-09-30 16:59:04.767273889 +0530
@@ -19,6 +19,7 @@
 int mmc_app_send_scr(struct mmc_card *card, u32 *scr);
 int mmc_sd_switch(struct mmc_card *card, int mode, int group,
 	u8 value, u8 *resp);
+int mmc_app_sd_status(struct mmc_card *card, u8 *sd_status);

 #endif

diff -urNd linux-orig/include/linux/mmc/card.h
linux-current/include/linux/mmc/card.h
--- linux-orig/include/linux/mmc/card.h	2009-09-30 16:51:59.230273430 +0530
+++ linux-current/include/linux/mmc/card.h	2009-09-30 16:53:54.162273013 +0530
@@ -111,6 +111,7 @@
 	unsigned		num_info;	/* number of info strings */
 	const char		**info;		/* info strings */
 	struct sdio_func_tuple	*tuples;	/* unknown common tuples */
+	u32 speed_class; /* speed_class for SD cards, for MMC, it is always
reserved */

 	struct dentry		*debugfs_root;
 };
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux