mirror of
https://github.com/CTCaer/hekate
synced 2024-12-22 19:31:12 +00:00
sdmmc: add support for sandisk emmc device report
This commit is contained in:
parent
e94bd23d6f
commit
dcdf687a07
3 changed files with 190 additions and 51 deletions
|
@ -2,6 +2,7 @@
|
||||||
* Header for MultiMediaCard (MMC)
|
* Header for MultiMediaCard (MMC)
|
||||||
*
|
*
|
||||||
* Copyright 2002 Hewlett-Packard Company
|
* Copyright 2002 Hewlett-Packard Company
|
||||||
|
* Copyright 2018-2021 CTCaer
|
||||||
*
|
*
|
||||||
* Use consistent with the GNU GPL is permitted,
|
* Use consistent with the GNU GPL is permitted,
|
||||||
* provided that this copyright notice is
|
* provided that this copyright notice is
|
||||||
|
@ -21,8 +22,8 @@
|
||||||
* 15 May 2002
|
* 15 May 2002
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LINUX_MMC_MMC_H
|
#ifndef MMC_H
|
||||||
#define LINUX_MMC_MMC_H
|
#define MMC_H
|
||||||
|
|
||||||
/* Standard MMC commands (4.1) type argument response */
|
/* Standard MMC commands (4.1) type argument response */
|
||||||
/* class 1 */
|
/* class 1 */
|
||||||
|
@ -108,18 +109,18 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
MMC status in R1, for native mode (SPI bits are different)
|
* MMC status in R1, for native mode (SPI bits are different)
|
||||||
Type
|
* Type
|
||||||
e : error bit
|
* e : error bit
|
||||||
s : status bit
|
* s : status bit
|
||||||
r : detected and set for the actual command response
|
* r : detected and set for the actual command response
|
||||||
x : detected and set during command execution. the host must poll
|
* x : detected and set during command execution. the host must poll
|
||||||
the card by sending status command in order to read these bits.
|
* the card by sending status command in order to read these bits.
|
||||||
Clear condition
|
* Clear condition
|
||||||
a : according to the card state
|
* a : according to the card state
|
||||||
b : always related to the previous command. Reception of
|
* b : always related to the previous command. Reception of a valid
|
||||||
a valid command will clear it (with a delay of one command)
|
* command will clear it (with a delay of one command)
|
||||||
c : clear by read
|
* c : clear by read
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define R1_OUT_OF_RANGE (1 << 31) /* er, c */
|
#define R1_OUT_OF_RANGE (1 << 31) /* er, c */
|
||||||
|
@ -151,6 +152,7 @@ c : clear by read
|
||||||
#define R1_AKE_SEQ_ERROR (1 << 3)
|
#define R1_AKE_SEQ_ERROR (1 << 3)
|
||||||
|
|
||||||
/* R1_CURRENT_STATE 12:9 */
|
/* R1_CURRENT_STATE 12:9 */
|
||||||
|
#define R1_STATE(x) ((x) << 9)
|
||||||
#define R1_STATE_IDLE 0
|
#define R1_STATE_IDLE 0
|
||||||
#define R1_STATE_READY 1
|
#define R1_STATE_READY 1
|
||||||
#define R1_STATE_IDENT 2
|
#define R1_STATE_IDENT 2
|
||||||
|
@ -441,4 +443,9 @@ c : clear by read
|
||||||
#define MMC_SECURE_ARGS 0x80000000
|
#define MMC_SECURE_ARGS 0x80000000
|
||||||
#define MMC_TRIM_ARGS 0x00008001
|
#define MMC_TRIM_ARGS 0x00008001
|
||||||
|
|
||||||
#endif /* LINUX_MMC_MMC_H */
|
/*
|
||||||
|
* Vendor definitions and structs
|
||||||
|
*/
|
||||||
|
#define MMC_SANDISK_HEALTH_REPORT 0x96C9D71C
|
||||||
|
|
||||||
|
#endif /* MMC_H */
|
||||||
|
|
|
@ -139,6 +139,60 @@ static int _sdmmc_storage_check_status(sdmmc_storage_t *storage)
|
||||||
return _sdmmc_storage_get_status(storage, &tmp, 0);
|
return _sdmmc_storage_get_status(storage, &tmp, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sdmmc_storage_execute_vendor_cmd(sdmmc_storage_t *storage, u32 arg)
|
||||||
|
{
|
||||||
|
sdmmc_cmd_t cmdbuf;
|
||||||
|
sdmmc_init_cmd(&cmdbuf, MMC_VENDOR_62_CMD, arg, SDMMC_RSP_TYPE_1, 1);
|
||||||
|
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
u32 resp;
|
||||||
|
sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_1);
|
||||||
|
|
||||||
|
resp = -1;
|
||||||
|
u32 timeout = get_tmr_ms() + 1500;
|
||||||
|
while (resp != (R1_READY_FOR_DATA | R1_STATE(R1_STATE_TRAN)))
|
||||||
|
{
|
||||||
|
_sdmmc_storage_get_status(storage, &resp, 0);
|
||||||
|
|
||||||
|
if (get_tmr_ms() > timeout)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _sdmmc_storage_check_card_status(resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sdmmc_storage_vendor_sandisk_report(sdmmc_storage_t *storage, void *buf)
|
||||||
|
{
|
||||||
|
// Request health report.
|
||||||
|
if (!sdmmc_storage_execute_vendor_cmd(storage, MMC_SANDISK_HEALTH_REPORT))
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
u32 tmp = 0;
|
||||||
|
sdmmc_cmd_t cmdbuf;
|
||||||
|
sdmmc_req_t reqbuf;
|
||||||
|
|
||||||
|
sdmmc_init_cmd(&cmdbuf, MMC_VENDOR_63_CMD, 0, SDMMC_RSP_TYPE_1, 0); // similar to CMD17 with arg 0x0.
|
||||||
|
|
||||||
|
reqbuf.buf = buf;
|
||||||
|
reqbuf.num_sectors = 1;
|
||||||
|
reqbuf.blksize = 512;
|
||||||
|
reqbuf.is_write = 0;
|
||||||
|
reqbuf.is_multi_block = 0;
|
||||||
|
reqbuf.is_auto_stop_trn = 0;
|
||||||
|
|
||||||
|
u32 blkcnt_out;
|
||||||
|
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, &blkcnt_out))
|
||||||
|
{
|
||||||
|
sdmmc_stop_transmission(storage->sdmmc, &tmp);
|
||||||
|
_sdmmc_storage_get_status(storage, &tmp, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out, u32 sector, u32 num_sectors, void *buf, u32 is_write)
|
static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out, u32 sector, u32 num_sectors, void *buf, u32 is_write)
|
||||||
{
|
{
|
||||||
u32 tmp = 0;
|
u32 tmp = 0;
|
||||||
|
@ -1360,8 +1414,6 @@ DPRINTF("[SD] SD does not support wide bus width\n");
|
||||||
if (!_sd_storage_enable_uhs_low_volt(storage, type, buf))
|
if (!_sd_storage_enable_uhs_low_volt(storage, type, buf))
|
||||||
return 0;
|
return 0;
|
||||||
DPRINTF("[SD] enabled UHS\n");
|
DPRINTF("[SD] enabled UHS\n");
|
||||||
|
|
||||||
sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE);
|
|
||||||
}
|
}
|
||||||
else if (type != SDHCI_TIMING_SD_DS12 && storage->scr.sda_vsn) // Not default speed and not SD Version 1.0.
|
else if (type != SDHCI_TIMING_SD_DS12 && storage->scr.sda_vsn) // Not default speed and not SD Version 1.0.
|
||||||
{
|
{
|
||||||
|
@ -1387,6 +1439,8 @@ DPRINTF("[SD] enabled HS\n");
|
||||||
DPRINTF("[SD] got sd status\n");
|
DPRINTF("[SD] got sd status\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE);
|
||||||
|
|
||||||
storage->initialized = 1;
|
storage->initialized = 1;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -34,6 +34,81 @@ typedef enum _sdmmc_type
|
||||||
EMMC_RPMB = 3
|
EMMC_RPMB = 3
|
||||||
} sdmmc_type;
|
} sdmmc_type;
|
||||||
|
|
||||||
|
typedef struct _mmc_sandisk_advanced_report_t
|
||||||
|
{
|
||||||
|
u32 power_inits;
|
||||||
|
|
||||||
|
u32 max_erase_cycles_sys;
|
||||||
|
u32 max_erase_cycles_slc;
|
||||||
|
u32 max_erase_cycles_mlc;
|
||||||
|
|
||||||
|
u32 min_erase_cycles_sys;
|
||||||
|
u32 min_erase_cycles_slc;
|
||||||
|
u32 min_erase_cycles_mlc;
|
||||||
|
|
||||||
|
u32 max_erase_cycles_euda;
|
||||||
|
u32 min_erase_cycles_euda;
|
||||||
|
u32 avg_erase_cycles_euda;
|
||||||
|
u32 read_reclaim_cnt_euda;
|
||||||
|
u32 bad_blocks_euda;
|
||||||
|
|
||||||
|
u32 pre_eol_euda;
|
||||||
|
u32 pre_eol_sys;
|
||||||
|
u32 pre_eol_mlc;
|
||||||
|
|
||||||
|
u32 uncorrectable_ecc;
|
||||||
|
|
||||||
|
u32 temperature_now;
|
||||||
|
u32 temperature_min;
|
||||||
|
u32 temperature_max;
|
||||||
|
|
||||||
|
u32 health_pct_euda;
|
||||||
|
u32 health_pct_sys;
|
||||||
|
u32 health_pct_mlc;
|
||||||
|
|
||||||
|
u32 unk0;
|
||||||
|
u32 unk1;
|
||||||
|
u32 unk2;
|
||||||
|
|
||||||
|
u32 reserved[78];
|
||||||
|
} mmc_sandisk_advanced_report_t;
|
||||||
|
|
||||||
|
typedef struct _mmc_sandisk_report_t
|
||||||
|
{
|
||||||
|
u32 avg_erase_cycles_sys;
|
||||||
|
u32 avg_erase_cycles_slc;
|
||||||
|
u32 avg_erase_cycles_mlc;
|
||||||
|
|
||||||
|
u32 read_reclaim_cnt_sys;
|
||||||
|
u32 read_reclaim_cnt_slc;
|
||||||
|
u32 read_reclaim_cnt_mlc;
|
||||||
|
|
||||||
|
u32 bad_blocks_factory;
|
||||||
|
u32 bad_blocks_sys;
|
||||||
|
u32 bad_blocks_slc;
|
||||||
|
u32 bad_blocks_mlc;
|
||||||
|
|
||||||
|
u32 fw_updates_cnt;
|
||||||
|
|
||||||
|
u8 fw_update_date[12];
|
||||||
|
u8 fw_update_time[8];
|
||||||
|
|
||||||
|
u32 total_writes_100mb;
|
||||||
|
u32 vdrops;
|
||||||
|
u32 vdroops;
|
||||||
|
|
||||||
|
u32 vdrops_failed_data_rec;
|
||||||
|
u32 vdrops_data_rec_ops;
|
||||||
|
|
||||||
|
u32 total_writes_slc_100mb;
|
||||||
|
u32 total_writes_mlc_100mb;
|
||||||
|
|
||||||
|
u32 mlc_bigfile_mode_limit_exceeded;
|
||||||
|
u32 avg_erase_cycles_hybrid;
|
||||||
|
|
||||||
|
mmc_sandisk_advanced_report_t advanced;
|
||||||
|
} mmc_sandisk_report_t;
|
||||||
|
|
||||||
typedef struct _mmc_cid
|
typedef struct _mmc_cid
|
||||||
{
|
{
|
||||||
u32 manfid;
|
u32 manfid;
|
||||||
|
@ -131,6 +206,9 @@ void sdmmc_storage_init_wait_sd();
|
||||||
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type);
|
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type);
|
||||||
int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc);
|
int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc);
|
||||||
|
|
||||||
|
int sdmmc_storage_execute_vendor_cmd(sdmmc_storage_t *storage, u32 arg);
|
||||||
|
int sdmmc_storage_vendor_sandisk_report(sdmmc_storage_t *storage, void *buf);
|
||||||
|
|
||||||
int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf);
|
int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf);
|
||||||
u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage);
|
u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue