Commit 201ee40f authored by Russell King's avatar Russell King

[MMC] Add v2.x and v3.x CID parsing.

parent b41465f9
...@@ -300,51 +300,110 @@ static u32 mmc_select_voltage(struct mmc_host *host, u32 ocr) ...@@ -300,51 +300,110 @@ static u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
return ocr; return ocr;
} }
#define UNSTUFF_BITS(resp,start,size) \
({ \
const u32 __mask = (1 << (size)) - 1; \
const int __off = 3 - ((start) / 32); \
const int __shft = (start) & 31; \
u32 __res; \
\
__res = resp[__off] >> __shft; \
if ((size) + __shft >= 32) \
__res |= resp[__off-1] << (32 - __shft); \
__res & __mask; \
})
/*
* Given the decoded CSD structure, decode the raw CID to our CID structure.
*/
static void mmc_decode_cid(struct mmc_card *card) static void mmc_decode_cid(struct mmc_card *card)
{ {
struct mmc_cid *cid = &card->cid;
u32 *resp = card->raw_cid; u32 *resp = card->raw_cid;
memset(cid, 0, sizeof(struct mmc_cid)); memset(&card->cid, 0, sizeof(struct mmc_cid));
cid->manfid = resp[0] >> 8; /*
cid->prod_name[0] = resp[0]; * The selection of the format here is guesswork based upon
cid->prod_name[1] = resp[1] >> 24; * information people have sent to date.
cid->prod_name[2] = resp[1] >> 16; */
cid->prod_name[3] = resp[1] >> 8; switch (card->csd.mmca_vsn) {
cid->prod_name[4] = resp[1]; case 0: /* MMC v1.? */
cid->prod_name[5] = resp[2] >> 24; case 1: /* MMC v1.4 */
cid->prod_name[6] = resp[2] >> 16; card->cid.manfid = UNSTUFF_BITS(resp, 104, 24);
cid->prod_name[7] = '\0'; card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8);
cid->hwrev = (resp[2] >> 12) & 15; card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8);
cid->fwrev = (resp[2] >> 8) & 15; card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8);
cid->serial = (resp[2] & 255) << 16 | (resp[3] >> 16); card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8);
cid->month = (resp[3] >> 12) & 15; card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8);
cid->year = (resp[3] >> 8) & 15; card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8);
card->cid.prod_name[6] = UNSTUFF_BITS(resp, 48, 8);
card->cid.hwrev = UNSTUFF_BITS(resp, 44, 4);
card->cid.fwrev = UNSTUFF_BITS(resp, 40, 4);
card->cid.serial = UNSTUFF_BITS(resp, 16, 24);
card->cid.month = UNSTUFF_BITS(resp, 12, 4);
card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997;
break;
case 2: /* MMC v2.x ? */
case 3: /* MMC v3.x ? */
card->cid.manfid = UNSTUFF_BITS(resp, 120, 8);
card->cid.oemid = UNSTUFF_BITS(resp, 104, 16);
card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8);
card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8);
card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8);
card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8);
card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8);
card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8);
card->cid.serial = UNSTUFF_BITS(resp, 16, 32);
card->cid.month = UNSTUFF_BITS(resp, 12, 4);
card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997;
break;
default:
printk("%s: card has unknown MMCA version %d\n",
card->host->host_name, card->csd.mmca_vsn);
mmc_card_set_bad(card);
break;
}
} }
/*
* Given a 128-bit response, decode to our card CSD structure.
*/
static void mmc_decode_csd(struct mmc_card *card) static void mmc_decode_csd(struct mmc_card *card)
{ {
struct mmc_csd *csd = &card->csd; struct mmc_csd *csd = &card->csd;
unsigned int e, m; unsigned int e, m, csd_struct;
u32 *resp = card->raw_csd; u32 *resp = card->raw_csd;
csd->mmc_prot = (resp[0] >> 26) & 15; /*
m = (resp[0] >> 19) & 15; * We only understand CSD structure v1.1 and v2.
e = (resp[0] >> 16) & 7; * v2 has extra information in bits 15, 11 and 10.
*/
csd_struct = UNSTUFF_BITS(resp, 126, 2);
if (csd_struct != 1 && csd_struct != 2) {
printk("%s: unrecognised CSD structure version %d\n",
card->host->host_name, csd_struct);
mmc_card_set_bad(card);
return;
}
csd->mmca_vsn = UNSTUFF_BITS(resp, 122, 4);
m = UNSTUFF_BITS(resp, 115, 4);
e = UNSTUFF_BITS(resp, 112, 3);
csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10; csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
csd->tacc_clks = ((resp[0] >> 8) & 255) * 100; csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100;
m = (resp[0] >> 3) & 15; m = UNSTUFF_BITS(resp, 99, 4);
e = resp[0] & 7; e = UNSTUFF_BITS(resp, 96, 3);
csd->max_dtr = tran_exp[e] * tran_mant[m]; csd->max_dtr = tran_exp[e] * tran_mant[m];
csd->cmdclass = (resp[1] >> 20) & 0xfff; csd->cmdclass = UNSTUFF_BITS(resp, 84, 12);
e = (resp[2] >> 15) & 7; e = UNSTUFF_BITS(resp, 47, 3);
m = (resp[1] << 2 | resp[2] >> 30) & 0x3fff; m = UNSTUFF_BITS(resp, 62, 12);
csd->capacity = (1 + m) << (e + 2); csd->capacity = (1 + m) << (e + 2);
csd->read_blkbits = (resp[1] >> 16) & 15; csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
} }
/* /*
......
...@@ -67,8 +67,9 @@ mmc_bus_hotplug(struct device *dev, char **envp, int num_envp, char *buf, ...@@ -67,8 +67,9 @@ mmc_bus_hotplug(struct device *dev, char **envp, int num_envp, char *buf,
i = 0; i = 0;
add_env("MMC_CCC=%s", ccc); add_env("MMC_CCC=%s", ccc);
add_env("MMC_MANFID=%03x", card->cid.manfid); add_env("MMC_MANFID=%06x", card->cid.manfid);
add_env("MMC_SLOT_NAME=%s", card->dev.bus_id); add_env("MMC_NAME=%s", mmc_card_name(card));
add_env("MMC_OEMID=%04x", card->cid.oemid);
return 0; return 0;
} }
...@@ -162,12 +163,13 @@ MMC_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1], ...@@ -162,12 +163,13 @@ MMC_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
card->raw_cid[2], card->raw_cid[3]); card->raw_cid[2], card->raw_cid[3]);
MMC_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], MMC_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_ATTR(date, "%02d/%04d\n", card->cid.month, 1997 + card->cid.year); MMC_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);
MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev); MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev);
MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev); MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
MMC_ATTR(manfid, "0x%03x\n", card->cid.manfid); MMC_ATTR(manfid, "0x%06x\n", card->cid.manfid);
MMC_ATTR(name, "%s\n", card->cid.prod_name); MMC_ATTR(name, "%s\n", card->cid.prod_name);
MMC_ATTR(serial, "0x%06x\n", card->cid.serial); MMC_ATTR(oemid, "0x%04x\n", card->cid.oemid);
MMC_ATTR(serial, "0x%08x\n", card->cid.serial);
static struct device_attribute *mmc_dev_attributes[] = { static struct device_attribute *mmc_dev_attributes[] = {
&dev_attr_cid, &dev_attr_cid,
...@@ -177,6 +179,7 @@ static struct device_attribute *mmc_dev_attributes[] = { ...@@ -177,6 +179,7 @@ static struct device_attribute *mmc_dev_attributes[] = {
&dev_attr_hwrev, &dev_attr_hwrev,
&dev_attr_manfid, &dev_attr_manfid,
&dev_attr_name, &dev_attr_name,
&dev_attr_oemid,
&dev_attr_serial, &dev_attr_serial,
}; };
......
...@@ -14,16 +14,17 @@ ...@@ -14,16 +14,17 @@
struct mmc_cid { struct mmc_cid {
unsigned int manfid; unsigned int manfid;
unsigned int serial;
char prod_name[8]; char prod_name[8];
unsigned int serial;
unsigned short oemid;
unsigned short year;
unsigned char hwrev; unsigned char hwrev;
unsigned char fwrev; unsigned char fwrev;
unsigned char month; unsigned char month;
unsigned char year;
}; };
struct mmc_csd { struct mmc_csd {
unsigned char mmc_prot; unsigned char mmca_vsn;
unsigned short cmdclass; unsigned short cmdclass;
unsigned short tacc_clks; unsigned short tacc_clks;
unsigned int tacc_ns; unsigned int tacc_ns;
......
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