diff --git a/arch/arm/mach-imx/include/mach/esdhc.h b/arch/arm/mach-imx/include/mach/esdhc.h index add1691c4..fb7380a18 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 c5cf0ae52..f5e78e0d7 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 a23267957..cf38a88a9 100644 --- a/drivers/mci/mci-core.c +++ b/drivers/mci/mci-core.c @@ -101,6 +101,20 @@ static void mci_setup_cmd(struct mci_cmd *p, unsigned cmd, unsigned arg, unsigne p->resp_type = response; } +/** + * 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 @@ -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 0f10e8aea..40a712b4d 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;