summaryrefslogtreecommitdiff
path: root/drivers/mmc/core/sd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/core/sd.c')
-rw-r--r--drivers/mmc/core/sd.c44
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;