Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions drivers/mmc/core/card.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,10 @@ struct mmc_fixup {
#define CID_MANFID_SAMSUNG 0x15
#define CID_MANFID_SAMSUNG_SD 0x1b
#define CID_MANFID_APACER 0x27
#define CID_MANFID_BIWIN_SD 0x4E
#define CID_MANFID_SWISSBIT 0x5D
#define CID_MANFID_KINGSTON 0x70
#define CID_MANFID_TRANSCEND_SD 0x74
#define CID_MANFID_HYNIX 0x90
#define CID_MANFID_KINGSTON_SD 0x9F
#define CID_MANFID_LONGSYS_SD 0xAD
Expand Down
10 changes: 10 additions & 0 deletions drivers/mmc/core/quirks.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ static const struct mmc_fixup __maybe_unused mmc_sd_fixups[] = {
0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd,
MMC_QUIRK_BROKEN_SD_CACHE, EXT_CSD_REV_ANY),

/* Transcend cards need a CMD49 workaround */
_FIXUP_EXT("USDU1", CID_MANFID_TRANSCEND_SD, 0x4a60, CID_YEAR_ANY, CID_MONTH_ANY,
cid_rev(2, 0, 0, 0), -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd,
MMC_QUIRK_NONSTD_SD_CMD49, EXT_CSD_REV_ANY),

/* Certain Biwin cards need a CMD49 workaround */
_FIXUP_EXT("SMI ", CID_MANFID_BIWIN_SD, 0x4257, CID_YEAR_ANY, CID_MONTH_ANY,
cid_rev(1, 0, 2025, 0), -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd,
MMC_QUIRK_NONSTD_SD_CMD49, EXT_CSD_REV_ANY),

/* SD A2 allow-list - only trust CQ on these cards */
/* Raspberry Pi A2 cards */
_FIXUP_EXT(CID_NAME_ANY, CID_MANFID_LONGSYS_SD, 0x4c53, CID_YEAR_ANY, CID_MONTH_ANY,
Expand Down
20 changes: 20 additions & 0 deletions drivers/mmc/core/sd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1218,6 +1218,26 @@ static int mmc_sd_read_ext_regs(struct mmc_card *card)
goto out;
}

/* Some cards have zeroes in GEN_INFO but correctly implement EXT_PERF and EXT_PWR */
if (!memcmp(card->ext_reg_buf, gen_info_buf, 512)) {
pr_info("%s: using fall-back extension register parsing\n",
mmc_hostname(card->host));
/* PWR typically hard-coded at FNO=1 */
err = sd_parse_ext_reg_power(card, 1, 0, 0);
if (err) {
pr_err("%s: error %d parsing SD Power extension\n",
mmc_hostname(card->host), err);
goto out;
}
/* PERF typically hard-coded at FNO=2 */
err = sd_parse_ext_reg_perf(card, 2, 0, 0);
if (err) {
pr_err("%s: error %d parsing SD Performance extension\n",
mmc_hostname(card->host), err);
}
goto out;
}

/* General info structure revision. */
memcpy(&rev, &gen_info_buf[0], 2);

Expand Down
19 changes: 16 additions & 3 deletions drivers/mmc/core/sd_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -421,10 +421,23 @@ int mmc_sd_write_ext_reg(struct mmc_card *card, u8 fno, u8 page, u16 offset,
* [17:9] offset address.
* [8:0] length (0 = 1 byte).
*/
cmd.arg = fno << 27 | page << 18 | offset << 9;
if (card->quirks & MMC_QUIRK_NONSTD_SD_CMD49) {
int err;
/*
* Card ignores length/offset and always applies
* all 512B of the write data block. RmW cycle required.
*/
err = mmc_sd_read_ext_reg(card, fno, page, 0, 512, reg_buf);
if (err)
return err;

/* The first byte in the buffer is the data to be written. */
reg_buf[0] = reg_data;
cmd.arg = fno << 27 | page << 18;
reg_buf[offset] = reg_data;
} else {
cmd.arg = fno << 27 | page << 18 | offset << 9;
/* The first byte in the buffer is the data to be written. */
reg_buf[0] = reg_data;
}

data.flags = MMC_DATA_WRITE;
data.blksz = 512;
Expand Down
1 change: 1 addition & 0 deletions include/linux/mmc/card.h
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ struct mmc_card {
#define MMC_QUIRK_BROKEN_CACHE_FLUSH (1<<16) /* Don't flush cache until the write has occurred */
#define MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY (1<<17) /* Disable broken SD poweroff notify support */
#define MMC_QUIRK_NO_UHS_DDR50_TUNING (1<<18) /* Disable DDR50 tuning */
#define MMC_QUIRK_NONSTD_SD_CMD49 (1<<29) /* SD card ignores length/offset argument */
#define MMC_QUIRK_WORKING_SD_CQ (1<<30) /* SD card has known-good CQ implementation */
#define MMC_QUIRK_ERASE_BROKEN (1<<31) /* Skip erase */

Expand Down