aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUri Yanai <uri.yanai@sandisk.com>2016-08-14 04:46:36 -0400
committerUlf Hansson <ulf.hansson@linaro.org>2016-09-26 15:31:09 -0400
commit5275a652d296711aaf7f2f4173c8db153e5777c3 (patch)
tree1a3b3c42261e76dcbafb4ba118e4e94a531c36bc
parentd51c50525f0a4c6b58fdd493a933017c62d98731 (diff)
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: Uri Yanai <uri.yanai@sandisk.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--drivers/mmc/core/sd.c37
-rw-r--r--include/linux/mmc/card.h1
2 files changed, 20 insertions, 18 deletions
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 0123936241b0..73c762a28dfe 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -223,8 +223,7 @@ static int mmc_decode_scr(struct mmc_card *card)
223static int mmc_read_ssr(struct mmc_card *card) 223static int mmc_read_ssr(struct mmc_card *card)
224{ 224{
225 unsigned int au, es, et, eo; 225 unsigned int au, es, et, eo;
226 int err, i; 226 int i;
227 u32 *ssr;
228 227
229 if (!(card->csd.cmdclass & CCC_APP_SPEC)) { 228 if (!(card->csd.cmdclass & CCC_APP_SPEC)) {
230 pr_warn("%s: card lacks mandatory SD Status function\n", 229 pr_warn("%s: card lacks mandatory SD Status function\n",
@@ -232,33 +231,27 @@ static int mmc_read_ssr(struct mmc_card *card)
232 return 0; 231 return 0;
233 } 232 }
234 233
235 ssr = kmalloc(64, GFP_KERNEL); 234 if (mmc_app_sd_status(card, card->raw_ssr)) {
236 if (!ssr)
237 return -ENOMEM;
238
239 err = mmc_app_sd_status(card, ssr);
240 if (err) {
241 pr_warn("%s: problem reading SD Status register\n", 235 pr_warn("%s: problem reading SD Status register\n",
242 mmc_hostname(card->host)); 236 mmc_hostname(card->host));
243 err = 0; 237 return 0;
244 goto out;
245 } 238 }
246 239
247 for (i = 0; i < 16; i++) 240 for (i = 0; i < 16; i++)
248 ssr[i] = be32_to_cpu(ssr[i]); 241 card->raw_ssr[i] = be32_to_cpu(card->raw_ssr[i]);
249 242
250 /* 243 /*
251 * UNSTUFF_BITS only works with four u32s so we have to offset the 244 * UNSTUFF_BITS only works with four u32s so we have to offset the
252 * bitfield positions accordingly. 245 * bitfield positions accordingly.
253 */ 246 */
254 au = UNSTUFF_BITS(ssr, 428 - 384, 4); 247 au = UNSTUFF_BITS(card->raw_ssr, 428 - 384, 4);
255 if (au) { 248 if (au) {
256 if (au <= 9 || card->scr.sda_spec3) { 249 if (au <= 9 || card->scr.sda_spec3) {
257 card->ssr.au = sd_au_size[au]; 250 card->ssr.au = sd_au_size[au];
258 es = UNSTUFF_BITS(ssr, 408 - 384, 16); 251 es = UNSTUFF_BITS(card->raw_ssr, 408 - 384, 16);
259 et = UNSTUFF_BITS(ssr, 402 - 384, 6); 252 et = UNSTUFF_BITS(card->raw_ssr, 402 - 384, 6);
260 if (es && et) { 253 if (es && et) {
261 eo = UNSTUFF_BITS(ssr, 400 - 384, 2); 254 eo = UNSTUFF_BITS(card->raw_ssr, 400 - 384, 2);
262 card->ssr.erase_timeout = (et * 1000) / es; 255 card->ssr.erase_timeout = (et * 1000) / es;
263 card->ssr.erase_offset = eo * 1000; 256 card->ssr.erase_offset = eo * 1000;
264 } 257 }
@@ -267,9 +260,8 @@ static int mmc_read_ssr(struct mmc_card *card)
267 mmc_hostname(card->host)); 260 mmc_hostname(card->host));
268 } 261 }
269 } 262 }
270out: 263
271 kfree(ssr); 264 return 0;
272 return err;
273} 265}
274 266
275/* 267/*
@@ -666,6 +658,14 @@ MMC_DEV_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
666MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], 658MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
667 card->raw_csd[2], card->raw_csd[3]); 659 card->raw_csd[2], card->raw_csd[3]);
668MMC_DEV_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]); 660MMC_DEV_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]);
661MMC_DEV_ATTR(ssr,
662 "%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x\n",
663 card->raw_ssr[0], card->raw_ssr[1], card->raw_ssr[2],
664 card->raw_ssr[3], card->raw_ssr[4], card->raw_ssr[5],
665 card->raw_ssr[6], card->raw_ssr[7], card->raw_ssr[8],
666 card->raw_ssr[9], card->raw_ssr[10], card->raw_ssr[11],
667 card->raw_ssr[12], card->raw_ssr[13], card->raw_ssr[14],
668 card->raw_ssr[15]);
669MMC_DEV_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year); 669MMC_DEV_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);
670MMC_DEV_ATTR(erase_size, "%u\n", card->erase_size << 9); 670MMC_DEV_ATTR(erase_size, "%u\n", card->erase_size << 9);
671MMC_DEV_ATTR(preferred_erase_size, "%u\n", card->pref_erase << 9); 671MMC_DEV_ATTR(preferred_erase_size, "%u\n", card->pref_erase << 9);
@@ -698,6 +698,7 @@ static struct attribute *sd_std_attrs[] = {
698 &dev_attr_cid.attr, 698 &dev_attr_cid.attr,
699 &dev_attr_csd.attr, 699 &dev_attr_csd.attr,
700 &dev_attr_scr.attr, 700 &dev_attr_scr.attr,
701 &dev_attr_ssr.attr,
701 &dev_attr_date.attr, 702 &dev_attr_date.attr,
702 &dev_attr_erase_size.attr, 703 &dev_attr_erase_size.attr,
703 &dev_attr_preferred_erase_size.attr, 704 &dev_attr_preferred_erase_size.attr,
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index d8673ca968ba..73fad83acbcb 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -292,6 +292,7 @@ struct mmc_card {
292 u32 raw_cid[4]; /* raw card CID */ 292 u32 raw_cid[4]; /* raw card CID */
293 u32 raw_csd[4]; /* raw card CSD */ 293 u32 raw_csd[4]; /* raw card CSD */
294 u32 raw_scr[2]; /* raw card SCR */ 294 u32 raw_scr[2]; /* raw card SCR */
295 u32 raw_ssr[16]; /* raw card SSR */
295 struct mmc_cid cid; /* card identification */ 296 struct mmc_cid cid; /* card identification */
296 struct mmc_csd csd; /* card specific */ 297 struct mmc_csd csd; /* card specific */
297 struct mmc_ext_csd ext_csd; /* mmc v4 extended card specific */ 298 struct mmc_ext_csd ext_csd; /* mmc v4 extended card specific */