summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2014-02-03 09:55:52 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2014-02-03 09:55:52 +0100
commitd3c96d65222b3ae99f03affda5ecd05fdb9873a4 (patch)
tree1087466b3a6fd116c3ae775758f5510ace6bfed1
parent4a53361beb278b110d1b73ca71398ecb7de54fed (diff)
parent6b5f0d4c9a1789f517e12e3958ba20899db9a1f4 (diff)
downloadbarebox-d3c96d65222b3ae99f03affda5ecd05fdb9873a4.tar.gz
barebox-d3c96d65222b3ae99f03affda5ecd05fdb9873a4.tar.xz
Merge branch 'for-next/mci'
Conflicts: arch/arm/boards/tqma53/board.c
-rw-r--r--arch/arm/mach-imx/include/mach/esdhc.h2
-rw-r--r--drivers/mci/imx-esdhc.c4
-rw-r--r--drivers/mci/mci-core.c86
-rw-r--r--include/mci.h24
4 files changed, 97 insertions, 19 deletions
diff --git a/arch/arm/mach-imx/include/mach/esdhc.h b/arch/arm/mach-imx/include/mach/esdhc.h
index add1691c4b..fb7380a182 100644
--- a/arch/arm/mach-imx/include/mach/esdhc.h
+++ b/arch/arm/mach-imx/include/mach/esdhc.h
@@ -42,5 +42,7 @@ struct esdhc_platform_data {
enum cd_types cd_type;
unsigned caps;
char *devname;
+ unsigned dsr_val;
+ int use_dsr;
};
#endif /* __ASM_ARCH_IMX_ESDHC_H */
diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c
index c5cf0ae52e..f5e78e0d79 100644
--- a/drivers/mci/imx-esdhc.c
+++ b/drivers/mci/imx-esdhc.c
@@ -582,6 +582,10 @@ static int fsl_esdhc_probe(struct device_d *dev)
if (host->mci.f_min < 200000)
host->mci.f_min = 200000;
host->mci.f_max = rate;
+ if (pdata) {
+ host->mci.use_dsr = pdata->use_dsr;
+ host->mci.dsr_val = pdata->dsr_val;
+ }
mci_of_parse(&host->mci);
diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
index a232679571..cf38a88a9b 100644
--- a/drivers/mci/mci-core.c
+++ b/drivers/mci/mci-core.c
@@ -102,6 +102,20 @@ static void mci_setup_cmd(struct mci_cmd *p, unsigned cmd, unsigned arg, unsigne
}
/**
+ * configure optional DSR value
+ * @param mci_dev MCI instance
+ * @return Transaction status (0 on success)
+ */
+static int mci_set_dsr(struct mci *mci)
+{
+ struct mci_cmd cmd;
+
+ mci_setup_cmd(&cmd, MMC_CMD_SET_DSR,
+ (mci->host->dsr_val >> 16) | 0xffff, MMC_RSP_NONE);
+ return mci_send_cmd(mci, &cmd, NULL);
+}
+
+/**
* Setup SD/MMC card's blocklength to be used for future transmitts
* @param mci_dev MCI instance
* @param len Blocklength in bytes
@@ -695,7 +709,6 @@ static void mci_set_bus_width(struct mci *mci, unsigned width)
static void mci_detect_version_from_csd(struct mci *mci)
{
int version;
- char *vstr;
if (mci->version == MMC_VERSION_UNKNOWN) {
/* the version is coded in the bits 127:126 (left aligned) */
@@ -703,32 +716,52 @@ static void mci_detect_version_from_csd(struct mci *mci)
switch (version) {
case 0:
- vstr = "1.2";
mci->version = MMC_VERSION_1_2;
break;
case 1:
- vstr = "1.4";
mci->version = MMC_VERSION_1_4;
break;
case 2:
- vstr = "2.2";
mci->version = MMC_VERSION_2_2;
break;
case 3:
- vstr = "3.0";
mci->version = MMC_VERSION_3;
break;
case 4:
- vstr = "4.0";
mci->version = MMC_VERSION_4;
break;
default:
- vstr = "unknown, fallback to 1.2";
+ printf("unknown card version, fallback to 1.02\n");
mci->version = MMC_VERSION_1_2;
break;
}
+ }
+}
- dev_info(&mci->dev, "detected card version %s\n", vstr);
+/**
+ * correct the version from ext_csd data if it's not an SD-card, detected
+ * version is at least 4 and we have ext_csd data
+ */
+static void mci_correct_version_from_ext_csd(struct mci *mci)
+{
+ if (!IS_SD(mci) && (mci->version >= MMC_VERSION_4) && mci->ext_csd) {
+ switch (mci->ext_csd[EXT_CSD_REV]) {
+ case 1:
+ mci->version = MMC_VERSION_4_1;
+ break;
+ case 2:
+ mci->version = MMC_VERSION_4_2;
+ break;
+ case 3:
+ mci->version = MMC_VERSION_4_3;
+ break;
+ case 5:
+ mci->version = MMC_VERSION_4_41;
+ break;
+ case 6:
+ mci->version = MMC_VERSION_4_5;
+ break;
+ }
}
}
@@ -836,6 +869,15 @@ static void mci_extract_card_capacity_from_csd(struct mci *mci)
dev_dbg(&mci->dev, "Capacity: %u MiB\n", (unsigned)(mci->capacity >> 20));
}
+/**
+ * Extract card's DSR implementation state from CSD
+ * @param mci MCI instance
+ */
+static void mci_extract_card_dsr_imp_from_csd(struct mci *mci)
+{
+ mci->dsr_imp = UNSTUFF_BITS(mci->csd, 76, 1);
+}
+
static int mmc_compare_ext_csds(struct mci *mci, unsigned bus_width)
{
u8 *bw_ext_csd;
@@ -1058,6 +1100,7 @@ static int mci_startup(struct mci *mci)
mci_detect_version_from_csd(mci);
mci_extract_max_tran_speed_from_csd(mci);
mci_extract_block_lengths_from_csd(mci);
+ mci_extract_card_dsr_imp_from_csd(mci);
/* sanitiy? */
if (mci->read_bl_len > SECTOR_SIZE) {
@@ -1074,6 +1117,9 @@ static int mci_startup(struct mci *mci)
dev_dbg(&mci->dev, "Read block length: %u, Write block length: %u\n",
mci->read_bl_len, mci->write_bl_len);
+ if (mci->dsr_imp && mci->host->use_dsr)
+ mci_set_dsr(mci);
+
if (!mmc_host_is_spi(host)) { /* cmd not supported in spi */
dev_dbg(&mci->dev, "Select the card, and put it into Transfer Mode\n");
/* Select the card, and put it into Transfer Mode */
@@ -1093,6 +1139,9 @@ static int mci_startup(struct mci *mci)
if (err)
return err;
+ mci_correct_version_from_ext_csd(mci);
+ printf("detected %s card version %d.%d\n", IS_SD(mci) ? "SD" : "MMC",
+ (mci->version >> 8) & 0xf, mci->version & 0xff);
mci_extract_card_capacity_from_csd(mci);
if (IS_SD(mci))
@@ -1376,10 +1425,17 @@ static unsigned extract_mtd_month(struct mci *mci)
*/
static unsigned extract_mtd_year(struct mci *mci)
{
+ unsigned year;
if (IS_SD(mci))
- return UNSTUFF_BITS(mci->cid, 12, 8) + 2000;
- else
+ year = UNSTUFF_BITS(mci->cid, 12, 8) + 2000;
+ else if (mci->version < MMC_VERSION_4_41)
return UNSTUFF_BITS(mci->cid, 8, 4) + 1997;
+ else {
+ year = UNSTUFF_BITS(mci->cid, 8, 4) + 1997;
+ if (year < 2010)
+ year += 16;
+ }
+ return year;
}
static void mci_print_caps(unsigned caps)
@@ -1426,7 +1482,7 @@ static void mci_info(struct device_d *dev)
(mci->version >> 4) & 0xf, mci->version & 0xf);
} else {
printf(" Attached is an SD Card (Version: %u.%u)\n",
- (mci->version >> 4) & 0xf, mci->version & 0xf);
+ (mci->version >> 8) & 0xf, mci->version & 0xff);
}
printf(" Capacity: %u MiB\n", (unsigned)(mci->capacity >> 20));
@@ -1719,6 +1775,7 @@ void mci_of_parse(struct mci_host *host)
{
struct device_node *np;
u32 bus_width;
+ u32 dsr_val;
if (!IS_ENABLED(CONFIG_OFDEVICE))
return;
@@ -1751,4 +1808,11 @@ void mci_of_parse(struct mci_host *host)
/* f_max is obtained from the optional "max-frequency" property */
of_property_read_u32(np, "max-frequency", &host->f_max);
+
+ if (!of_property_read_u32(np, "dsr", &dsr_val)) {
+ if (dsr_val < 0x10000) {
+ host->use_dsr = 1;
+ host->dsr_val = dsr_val;
+ }
+ }
}
diff --git a/include/mci.h b/include/mci.h
index 0f10e8aea9..40a712b4dc 100644
--- a/include/mci.h
+++ b/include/mci.h
@@ -31,18 +31,23 @@
/* Firmware revisions for SD cards */
#define SD_VERSION_SD 0x20000
-#define SD_VERSION_2 (SD_VERSION_SD | 0x20)
-#define SD_VERSION_1_0 (SD_VERSION_SD | 0x10)
-#define SD_VERSION_1_10 (SD_VERSION_SD | 0x1a)
+#define SD_VERSION_2 (SD_VERSION_SD | 0x200)
+#define SD_VERSION_1_0 (SD_VERSION_SD | 0x100)
+#define SD_VERSION_1_10 (SD_VERSION_SD | 0x10a)
/* Firmware revisions for MMC cards */
#define MMC_VERSION_MMC 0x10000
#define MMC_VERSION_UNKNOWN (MMC_VERSION_MMC)
-#define MMC_VERSION_1_2 (MMC_VERSION_MMC | 0x12)
-#define MMC_VERSION_1_4 (MMC_VERSION_MMC | 0x14)
-#define MMC_VERSION_2_2 (MMC_VERSION_MMC | 0x22)
-#define MMC_VERSION_3 (MMC_VERSION_MMC | 0x30)
-#define MMC_VERSION_4 (MMC_VERSION_MMC | 0x40)
+#define MMC_VERSION_1_2 (MMC_VERSION_MMC | 0x102)
+#define MMC_VERSION_1_4 (MMC_VERSION_MMC | 0x104)
+#define MMC_VERSION_2_2 (MMC_VERSION_MMC | 0x202)
+#define MMC_VERSION_3 (MMC_VERSION_MMC | 0x300)
+#define MMC_VERSION_4 (MMC_VERSION_MMC | 0x400)
+#define MMC_VERSION_4_1 (MMC_VERSION_MMC | 0x401)
+#define MMC_VERSION_4_2 (MMC_VERSION_MMC | 0x402)
+#define MMC_VERSION_4_3 (MMC_VERSION_MMC | 0x403)
+#define MMC_VERSION_4_41 (MMC_VERSION_MMC | 0x429)
+#define MMC_VERSION_4_5 (MMC_VERSION_MMC | 0x405)
#define MMC_CAP_SPI (1 << 0)
#define MMC_CAP_4_BIT_DATA (1 << 1)
@@ -294,6 +299,8 @@ struct mci_host {
unsigned clock; /**< Current clock used to talk to the card */
unsigned bus_width; /**< used data bus width to the card */
unsigned max_req_size;
+ unsigned dsr_val; /**< optional dsr value */
+ int use_dsr; /**< optional dsr usage flag */
/** init the host interface */
int (*init)(struct mci_host*, struct device_d*);
@@ -344,6 +351,7 @@ struct mci {
unsigned write_bl_len;
uint64_t capacity; /**< Card's data capacity in bytes */
int ready_for_use; /** true if already probed */
+ int dsr_imp; /**< DSR implementation state from CSD */
char *ext_csd;
int probe;
struct param_d *param_probe;