bdk: sdmmc: better DDR200 detection

Still experimental.
This commit is contained in:
CTCaer
2026-06-16 15:01:19 +03:00
parent 52ba13da50
commit d01a7285df
2 changed files with 66 additions and 3 deletions

View File

@@ -1179,6 +1179,8 @@ static void _sd_storage_parse_scr(sdmmc_storage_t *storage)
}
storage->scr.sda_spec = sda_spec3 | (sda_spec4 << 1) | (sda_specx << 4);
storage->scr.vendor = unstuff_bits(scr, 0, 32);
}
int sd_storage_get_scr(sdmmc_storage_t *storage)
@@ -1580,6 +1582,64 @@ static int _sd_storage_set_hs25_bus_speed(sdmmc_storage_t *storage)
return sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_HS25);
}
bool sd_storage_get_ddr200_support(sdmmc_storage_t *storage)
{
// DDR200 CID reserved/SCR vendor (hex):
// Samsung 0x1B: A 00000000
// Longsys 0xAD: A 00000000
// Kowin 0x22: 7 33333039 33333039 SMART?
// Phison 0x27: 0 01196432 Byte2: DDR2XX (25 == DDR225)?
// Taishin 0x9F: 0 01006432
// Non-DDR200:
// Phison 0x27: 0 01000000
// Taishin 0x9F: 0 01000000
// Taishin 0x9F: 7 33333039 Supported but slow nand?
sd_func_modes_t fmodes = { 0 };
if (sd_storage_get_fmodes(storage, storage->raw_ext_csd, &fmodes))
return false;
// Introduced first in 2018 via Sandisk Quickflow.
if (storage->cid.year < 2018)
return false;
// No DDR200 if no SDR104.
if (!(fmodes.access_mode & SD_MODE_UHS_SDR104))
return false;
// Can't enter DDR200 mode without Vendor Command System mode.
if (!(fmodes.cmd_system & SD_CMD_SYSTEM_VND))
return false;
// Assume no support if 4.10 and lower. (Should be < 6?)
if (sd_storage_get_scr_sda_ver(storage) < 5)
return false;
// Sandisk.
if (storage->cid.manfid == 0x03)
{
// 0x80: DDR200, 0x85: DDR225, 0x86: DDR250? 0x87:DDR275?
if (storage->cid.prv >= 0x80)
return true;
else
return false;
}
// CID Reserved bits.
if (storage->cid.rsvd == 0xA || // Samsung / Longsys.
storage->cid.rsvd == 0x7) // Taishin A / Kowin.
return true;
// SCR Vendor bits.
u32 scr_vnd = storage->scr.vendor & 0xFFFF;
if (scr_vnd == 0x6432) // Phison / Taishin B. "d2".
return true;
return false;
}
u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage)
{
u32 au_size = storage->ssr.uhs_au_size;
@@ -1798,6 +1858,7 @@ static void _sd_storage_parse_cid(sdmmc_storage_t *storage)
storage->cid.hwrev = unstuff_bits(raw_cid, 60, 4);
storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4);
storage->cid.serial = unstuff_bits(raw_cid, 24, 32);
storage->cid.rsvd = unstuff_bits(raw_cid, 20, 4);
storage->cid.year = unstuff_bits(raw_cid, 12, 8) + 2000;
storage->cid.month = unstuff_bits(raw_cid, 8, 4);
}

View File

@@ -117,15 +117,16 @@ typedef struct _mmc_sandisk_report_t
typedef struct _mmc_cid
{
u32 manfid;
u32 manfid; // SDA assigned.
u8 prod_name[8];
u32 serial;
u16 oemid;
u16 oemid; // SDA assigned.
u16 year;
u8 prv;
u8 hwrev;
u8 fwrev;
u8 month;
u32 rsvd;
} mmc_cid_t;
typedef struct _mmc_csd
@@ -164,6 +165,7 @@ typedef struct _sd_scr
u8 sda_spec;
u8 bus_widths;
u8 cmds;
u32 vendor;
} sd_scr_t;
typedef struct _sd_ssr
@@ -242,8 +244,8 @@ int sd_storage_get_scr(sdmmc_storage_t *storage);
u8 sd_storage_get_scr_sda_ver(sdmmc_storage_t *storage);
int sd_storage_get_ssr(sdmmc_storage_t *storage);
u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage);
void sd_storage_get_ext_regs(sdmmc_storage_t *storage, u8 *buf);
int sd_storage_parse_perf_enhance(sdmmc_storage_t *storage, u8 fno, u8 page, u16 offset, u8 *buf);
bool sd_storage_get_ddr200_support(sdmmc_storage_t *storage);
#endif