Commit 5275a652 authored by Uri Yanai's avatar Uri Yanai Committed by Ulf Hansson

mmc: sd: Export SD Status via “ssr” device attribute

The SD Status register contains several important fields related to the
SD Card proprietary features.
Those fields may be used by user space applications for vendor specific
usage.
None of those fields are exported today by the driver to user space.
In this patch, we are reading the SD Status register and exporting
(using MMC_DEV_ATTR) the SD Status register to the user space.
Signed-off-by: default avatarUri Yanai <uri.yanai@sandisk.com>
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent d51c5052
...@@ -223,8 +223,7 @@ static int mmc_decode_scr(struct mmc_card *card) ...@@ -223,8 +223,7 @@ static int mmc_decode_scr(struct mmc_card *card)
static int mmc_read_ssr(struct mmc_card *card) static int mmc_read_ssr(struct mmc_card *card)
{ {
unsigned int au, es, et, eo; unsigned int au, es, et, eo;
int err, i; int i;
u32 *ssr;
if (!(card->csd.cmdclass & CCC_APP_SPEC)) { if (!(card->csd.cmdclass & CCC_APP_SPEC)) {
pr_warn("%s: card lacks mandatory SD Status function\n", pr_warn("%s: card lacks mandatory SD Status function\n",
...@@ -232,33 +231,27 @@ static int mmc_read_ssr(struct mmc_card *card) ...@@ -232,33 +231,27 @@ static int mmc_read_ssr(struct mmc_card *card)
return 0; return 0;
} }
ssr = kmalloc(64, GFP_KERNEL); if (mmc_app_sd_status(card, card->raw_ssr)) {
if (!ssr)
return -ENOMEM;
err = mmc_app_sd_status(card, ssr);
if (err) {
pr_warn("%s: problem reading SD Status register\n", pr_warn("%s: problem reading SD Status register\n",
mmc_hostname(card->host)); mmc_hostname(card->host));
err = 0; return 0;
goto out;
} }
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
ssr[i] = be32_to_cpu(ssr[i]); card->raw_ssr[i] = be32_to_cpu(card->raw_ssr[i]);
/* /*
* UNSTUFF_BITS only works with four u32s so we have to offset the * UNSTUFF_BITS only works with four u32s so we have to offset the
* bitfield positions accordingly. * bitfield positions accordingly.
*/ */
au = UNSTUFF_BITS(ssr, 428 - 384, 4); au = UNSTUFF_BITS(card->raw_ssr, 428 - 384, 4);
if (au) { if (au) {
if (au <= 9 || card->scr.sda_spec3) { if (au <= 9 || card->scr.sda_spec3) {
card->ssr.au = sd_au_size[au]; card->ssr.au = sd_au_size[au];
es = UNSTUFF_BITS(ssr, 408 - 384, 16); es = UNSTUFF_BITS(card->raw_ssr, 408 - 384, 16);
et = UNSTUFF_BITS(ssr, 402 - 384, 6); et = UNSTUFF_BITS(card->raw_ssr, 402 - 384, 6);
if (es && et) { if (es && et) {
eo = UNSTUFF_BITS(ssr, 400 - 384, 2); eo = UNSTUFF_BITS(card->raw_ssr, 400 - 384, 2);
card->ssr.erase_timeout = (et * 1000) / es; card->ssr.erase_timeout = (et * 1000) / es;
card->ssr.erase_offset = eo * 1000; card->ssr.erase_offset = eo * 1000;
} }
...@@ -267,9 +260,8 @@ static int mmc_read_ssr(struct mmc_card *card) ...@@ -267,9 +260,8 @@ static int mmc_read_ssr(struct mmc_card *card)
mmc_hostname(card->host)); mmc_hostname(card->host));
} }
} }
out:
kfree(ssr); return 0;
return err;
} }
/* /*
...@@ -666,6 +658,14 @@ MMC_DEV_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1], ...@@ -666,6 +658,14 @@ MMC_DEV_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
card->raw_csd[2], card->raw_csd[3]); card->raw_csd[2], card->raw_csd[3]);
MMC_DEV_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]); MMC_DEV_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]);
MMC_DEV_ATTR(ssr,
"%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x\n",
card->raw_ssr[0], card->raw_ssr[1], card->raw_ssr[2],
card->raw_ssr[3], card->raw_ssr[4], card->raw_ssr[5],
card->raw_ssr[6], card->raw_ssr[7], card->raw_ssr[8],
card->raw_ssr[9], card->raw_ssr[10], card->raw_ssr[11],
card->raw_ssr[12], card->raw_ssr[13], card->raw_ssr[14],
card->raw_ssr[15]);
MMC_DEV_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year); MMC_DEV_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);
MMC_DEV_ATTR(erase_size, "%u\n", card->erase_size << 9); MMC_DEV_ATTR(erase_size, "%u\n", card->erase_size << 9);
MMC_DEV_ATTR(preferred_erase_size, "%u\n", card->pref_erase << 9); MMC_DEV_ATTR(preferred_erase_size, "%u\n", card->pref_erase << 9);
...@@ -698,6 +698,7 @@ static struct attribute *sd_std_attrs[] = { ...@@ -698,6 +698,7 @@ static struct attribute *sd_std_attrs[] = {
&dev_attr_cid.attr, &dev_attr_cid.attr,
&dev_attr_csd.attr, &dev_attr_csd.attr,
&dev_attr_scr.attr, &dev_attr_scr.attr,
&dev_attr_ssr.attr,
&dev_attr_date.attr, &dev_attr_date.attr,
&dev_attr_erase_size.attr, &dev_attr_erase_size.attr,
&dev_attr_preferred_erase_size.attr, &dev_attr_preferred_erase_size.attr,
......
...@@ -292,6 +292,7 @@ struct mmc_card { ...@@ -292,6 +292,7 @@ struct mmc_card {
u32 raw_cid[4]; /* raw card CID */ u32 raw_cid[4]; /* raw card CID */
u32 raw_csd[4]; /* raw card CSD */ u32 raw_csd[4]; /* raw card CSD */
u32 raw_scr[2]; /* raw card SCR */ u32 raw_scr[2]; /* raw card SCR */
u32 raw_ssr[16]; /* raw card SSR */
struct mmc_cid cid; /* card identification */ struct mmc_cid cid; /* card identification */
struct mmc_csd csd; /* card specific */ struct mmc_csd csd; /* card specific */
struct mmc_ext_csd ext_csd; /* mmc v4 extended card specific */ struct mmc_ext_csd ext_csd; /* mmc v4 extended card specific */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment