[sdmmc] Fix Sandisk U1 fast power cycle

Some Sandisk U1 sd cards do not behave nicely if they power cycle too fast. A min 100ms wait, is enough to mitigate that.

Fortunately, because of how the code paths are structured, this was never hit.
This commit is contained in:
ctcaer@gmail.com 2019-04-23 03:31:16 +03:00
parent 36d2da5d79
commit 25f6e91677
5 changed files with 17 additions and 3 deletions

View file

@ -45,6 +45,7 @@ void set_default_configuration()
h_cfg.autonogc = 1; h_cfg.autonogc = 1;
h_cfg.sept_run = EMC(EMC_SCRATCH0) & EMC_SEPT_RUN; h_cfg.sept_run = EMC(EMC_SCRATCH0) & EMC_SEPT_RUN;
h_cfg.rcm_patched = true; h_cfg.rcm_patched = true;
h_cfg.sd_timeoff = 0;
} }
int create_config_entry() int create_config_entry()

View file

@ -35,6 +35,7 @@ typedef struct _hekate_config
u32 errors; u32 errors;
int sept_run; int sept_run;
bool rcm_patched; bool rcm_patched;
u32 sd_timeoff;
} hekate_config; } hekate_config;
typedef enum typedef enum

View file

@ -19,6 +19,7 @@
#include "sdmmc.h" #include "sdmmc.h"
#include "mmc.h" #include "mmc.h"
#include "sd.h" #include "sd.h"
#include "../config/config.h"
#include "../gfx/gfx.h" #include "../gfx/gfx.h"
#include "../mem/heap.h" #include "../mem/heap.h"
#include "../utils/util.h" #include "../utils/util.h"
@ -26,6 +27,8 @@
//#define DPRINTF(...) gfx_printf(__VA_ARGS__) //#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DPRINTF(...) #define DPRINTF(...)
extern hekate_config h_cfg;
static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size) static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size)
{ {
const u32 mask = (size < 32 ? 1 << size : 0) - 1; const u32 mask = (size < 32 ? 1 << size : 0) - 1;
@ -833,6 +836,7 @@ int _sd_storage_enable_highspeed_low_volt(sdmmc_storage_t *storage, u32 type, u8
switch (type) switch (type)
{ {
case 11: case 11:
// Fall through if not supported.
if (buf[13] & SD_MODE_UHS_SDR104) if (buf[13] & SD_MODE_UHS_SDR104)
{ {
type = 11; type = 11;
@ -841,7 +845,6 @@ int _sd_storage_enable_highspeed_low_volt(sdmmc_storage_t *storage, u32 type, u8
storage->csd.busspeed = 104; storage->csd.busspeed = 104;
break; break;
} }
//Fall through.
case 10: case 10:
if (buf[13] & SD_MODE_UHS_SDR50) if (buf[13] & SD_MODE_UHS_SDR50)
{ {
@ -878,7 +881,7 @@ int _sd_storage_enable_highspeed_high_volt(sdmmc_storage_t *storage, u8 *buf)
if (!_sd_storage_switch_get(storage, buf)) if (!_sd_storage_switch_get(storage, buf))
return 0; return 0;
//gfx_hexdump(0, (u8 *)buf, 64); //gfx_hexdump(0, (u8 *)buf, 64);
if (!(buf[13] & 2)) if (!(buf[13] & SD_MODE_HIGH_SPEED))
return 1; return 1;
if (!_sd_storage_enable_highspeed(storage, 1, buf)) if (!_sd_storage_enable_highspeed(storage, 1, buf))
@ -1013,6 +1016,11 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
{ {
int is_version_1 = 0; int is_version_1 = 0;
// Some cards (Sandisk U1), do not like a fast power cycle. Wait min 100ms.
u32 sd_poweroff_time = (u32)get_tmr_ms() - h_cfg.sd_timeoff;
if (id == SDMMC_1 && (sd_poweroff_time < 100))
msleep(100 - sd_poweroff_time);
memset(storage, 0, sizeof(sdmmc_storage_t)); memset(storage, 0, sizeof(sdmmc_storage_t));
storage->sdmmc = sdmmc; storage->sdmmc = sdmmc;

View file

@ -19,6 +19,7 @@
#include "mmc.h" #include "mmc.h"
#include "sdmmc.h" #include "sdmmc.h"
#include "../config/config.h"
#include "../gfx/gfx.h" #include "../gfx/gfx.h"
#include "../power/max7762x.h" #include "../power/max7762x.h"
#include "../soc/clock.h" #include "../soc/clock.h"
@ -31,6 +32,8 @@
//#define DPRINTF(...) gfx_printf(__VA_ARGS__) //#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DPRINTF(...) #define DPRINTF(...)
extern hekate_config h_cfg;
/*! SCMMC controller base addresses. */ /*! SCMMC controller base addresses. */
static const u32 _sdmmc_bases[4] = { static const u32 _sdmmc_bases[4] = {
0x700B0000, 0x700B0000,
@ -1037,6 +1040,7 @@ void sdmmc_end(sdmmc_t *sdmmc)
{ {
gpio_output_enable(GPIO_PORT_E, GPIO_PIN_4, GPIO_OUTPUT_DISABLE); gpio_output_enable(GPIO_PORT_E, GPIO_PIN_4, GPIO_OUTPUT_DISABLE);
max77620_regulator_enable(REGULATOR_LDO2, 0); max77620_regulator_enable(REGULATOR_LDO2, 0);
h_cfg.sd_timeoff = get_tmr_ms(); // Some sandisc U1 cards need 100ms for a power cycle.
msleep(1); // To power cycle min 1ms without power is needed. msleep(1); // To power cycle min 1ms without power is needed.
} }