diff options
Diffstat (limited to 'drivers/mmc/core/sd.c')
-rw-r--r-- | drivers/mmc/core/sd.c | 44 |
1 files changed, 28 insertions, 16 deletions
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 12fe282bea77..cc757b850e79 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -100,7 +100,7 @@ void mmc_decode_cid(struct mmc_card *card) /* * Given a 128-bit response, decode to our card CSD structure. */ -static int mmc_decode_csd(struct mmc_card *card) +static int mmc_decode_csd(struct mmc_card *card, bool is_sduc) { struct mmc_csd *csd = &card->csd; unsigned int e, m, csd_struct; @@ -144,9 +144,10 @@ static int mmc_decode_csd(struct mmc_card *card) mmc_card_set_readonly(card); break; case 1: + case 2: /* - * This is a block-addressed SDHC or SDXC card. Most - * interesting fields are unused and have fixed + * This is a block-addressed SDHC, SDXC or SDUC card. + * Most interesting fields are unused and have fixed * values. To avoid getting tripped by buggy cards, * we assume those fixed values ourselves. */ @@ -159,14 +160,19 @@ static int mmc_decode_csd(struct mmc_card *card) e = unstuff_bits(resp, 96, 3); csd->max_dtr = tran_exp[e] * tran_mant[m]; csd->cmdclass = unstuff_bits(resp, 84, 12); - csd->c_size = unstuff_bits(resp, 48, 22); - /* SDXC cards have a minimum C_SIZE of 0x00FFFF */ - if (csd->c_size >= 0xFFFF) + if (csd_struct == 1) + m = unstuff_bits(resp, 48, 22); + else + m = unstuff_bits(resp, 48, 28); + csd->c_size = m; + + if (csd->c_size >= 0x400000 && is_sduc) + mmc_card_set_ult_capacity(card); + else if (csd->c_size >= 0xFFFF) mmc_card_set_ext_capacity(card); - m = unstuff_bits(resp, 48, 22); - csd->capacity = (1 + m) << 10; + csd->capacity = (1 + (typeof(sector_t))m) << 10; csd->read_blkbits = 9; csd->read_partial = 0; @@ -194,7 +200,7 @@ static int mmc_decode_csd(struct mmc_card *card) /* * Given a 64-bit response, decode to our card SCR structure. */ -static int mmc_decode_scr(struct mmc_card *card) +int mmc_decode_scr(struct mmc_card *card) { struct sd_scr *scr = &card->scr; unsigned int scr_struct; @@ -830,8 +836,11 @@ try_again: * block-addressed SDHC cards. */ err = mmc_send_if_cond(host, ocr); - if (!err) + if (!err) { ocr |= SD_OCR_CCS; + /* Set HO2T as well - SDUC card won't respond otherwise */ + ocr |= SD_OCR_2T; + } /* * If the host supports one of UHS-I modes, request the card @@ -876,7 +885,7 @@ try_again: return err; } -int mmc_sd_get_csd(struct mmc_card *card) +int mmc_sd_get_csd(struct mmc_card *card, bool is_sduc) { int err; @@ -887,14 +896,14 @@ int mmc_sd_get_csd(struct mmc_card *card) if (err) return err; - err = mmc_decode_csd(card); + err = mmc_decode_csd(card, is_sduc); if (err) return err; return 0; } -static int mmc_sd_get_ro(struct mmc_host *host) +int mmc_sd_get_ro(struct mmc_host *host) { int ro; @@ -1107,7 +1116,7 @@ static int sd_parse_ext_reg_power(struct mmc_card *card, u8 fno, u8 page, card->ext_power.rev = reg_buf[0] & 0xf; /* Power Off Notification support at bit 4. */ - if (reg_buf[1] & BIT(4)) + if ((reg_buf[1] & BIT(4)) && !mmc_card_broken_sd_poweroff_notify(card)) card->ext_power.feature_support |= SD_EXT_POWER_OFF_NOTIFY; /* Power Sustenance support at bit 5. */ @@ -1442,7 +1451,10 @@ retry: } if (!oldcard) { - err = mmc_sd_get_csd(card); + u32 sduc_arg = SD_OCR_CCS | SD_OCR_2T; + bool is_sduc = (rocr & sduc_arg) == sduc_arg; + + err = mmc_sd_get_csd(card, is_sduc); if (err) goto free_card; @@ -1552,7 +1564,7 @@ cont: goto free_card; } - if (host->cqe_ops && !host->cqe_enabled) { + if (!mmc_card_ult_capacity(card) && host->cqe_ops && !host->cqe_enabled) { err = host->cqe_ops->cqe_enable(host, card); if (!err) { host->cqe_enabled = true; |