bdk: sdmmc: better DDR200 detection
Still experimental.
This commit is contained in:
@@ -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.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)
|
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);
|
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 sd_storage_get_ssr_au(sdmmc_storage_t *storage)
|
||||||
{
|
{
|
||||||
u32 au_size = storage->ssr.uhs_au_size;
|
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.hwrev = unstuff_bits(raw_cid, 60, 4);
|
||||||
storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4);
|
storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4);
|
||||||
storage->cid.serial = unstuff_bits(raw_cid, 24, 32);
|
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.year = unstuff_bits(raw_cid, 12, 8) + 2000;
|
||||||
storage->cid.month = unstuff_bits(raw_cid, 8, 4);
|
storage->cid.month = unstuff_bits(raw_cid, 8, 4);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,15 +117,16 @@ typedef struct _mmc_sandisk_report_t
|
|||||||
|
|
||||||
typedef struct _mmc_cid
|
typedef struct _mmc_cid
|
||||||
{
|
{
|
||||||
u32 manfid;
|
u32 manfid; // SDA assigned.
|
||||||
u8 prod_name[8];
|
u8 prod_name[8];
|
||||||
u32 serial;
|
u32 serial;
|
||||||
u16 oemid;
|
u16 oemid; // SDA assigned.
|
||||||
u16 year;
|
u16 year;
|
||||||
u8 prv;
|
u8 prv;
|
||||||
u8 hwrev;
|
u8 hwrev;
|
||||||
u8 fwrev;
|
u8 fwrev;
|
||||||
u8 month;
|
u8 month;
|
||||||
|
u32 rsvd;
|
||||||
} mmc_cid_t;
|
} mmc_cid_t;
|
||||||
|
|
||||||
typedef struct _mmc_csd
|
typedef struct _mmc_csd
|
||||||
@@ -164,6 +165,7 @@ typedef struct _sd_scr
|
|||||||
u8 sda_spec;
|
u8 sda_spec;
|
||||||
u8 bus_widths;
|
u8 bus_widths;
|
||||||
u8 cmds;
|
u8 cmds;
|
||||||
|
u32 vendor;
|
||||||
} sd_scr_t;
|
} sd_scr_t;
|
||||||
|
|
||||||
typedef struct _sd_ssr
|
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);
|
u8 sd_storage_get_scr_sda_ver(sdmmc_storage_t *storage);
|
||||||
int sd_storage_get_ssr(sdmmc_storage_t *storage);
|
int sd_storage_get_ssr(sdmmc_storage_t *storage);
|
||||||
u32 sd_storage_get_ssr_au(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);
|
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);
|
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
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user