Skip to content

Commit 397d0e6

Browse files
committed
mmc: sd: add quirk for buggy CMD49 handling
Several card OEMs, mainly using Silicon Motion SM270x flash controllers, have a deficient CMD49 handler that throws away length/offset and applies the whole block to the addressed extension register page. Add a quirk to do a read-modify-write cycle for any extension register write. Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
1 parent ec1ef20 commit 397d0e6

2 files changed

Lines changed: 17 additions & 3 deletions

File tree

drivers/mmc/core/sd_ops.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -421,10 +421,23 @@ int mmc_sd_write_ext_reg(struct mmc_card *card, u8 fno, u8 page, u16 offset,
421421
* [17:9] offset address.
422422
* [8:0] length (0 = 1 byte).
423423
*/
424-
cmd.arg = fno << 27 | page << 18 | offset << 9;
424+
if (card->quirks & MMC_QUIRK_NONSTD_SD_CMD49) {
425+
int err;
426+
/*
427+
* Card ignores length/offset and always applies
428+
* all 512B of the write data block. RmW cycle required.
429+
*/
430+
err = mmc_sd_read_ext_reg(card, fno, page, 0, 512, reg_buf);
431+
if (err)
432+
return err;
425433

426-
/* The first byte in the buffer is the data to be written. */
427-
reg_buf[0] = reg_data;
434+
cmd.arg = fno << 27 | page << 18;
435+
reg_buf[offset] = reg_data;
436+
} else {
437+
cmd.arg = fno << 27 | page << 18 | offset << 9;
438+
/* The first byte in the buffer is the data to be written. */
439+
reg_buf[0] = reg_data;
440+
}
428441

429442
data.flags = MMC_DATA_WRITE;
430443
data.blksz = 512;

include/linux/mmc/card.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ struct mmc_card {
296296
#define MMC_QUIRK_BROKEN_CACHE_FLUSH (1<<16) /* Don't flush cache until the write has occurred */
297297
#define MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY (1<<17) /* Disable broken SD poweroff notify support */
298298
#define MMC_QUIRK_NO_UHS_DDR50_TUNING (1<<18) /* Disable DDR50 tuning */
299+
#define MMC_QUIRK_NONSTD_SD_CMD49 (1<<29) /* SD card ignores length/offset argument */
299300
#define MMC_QUIRK_WORKING_SD_CQ (1<<30) /* SD card has known-good CQ implementation */
300301
#define MMC_QUIRK_ERASE_BROKEN (1<<31) /* Skip erase */
301302

0 commit comments

Comments
 (0)