[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.sept_run = EMC(EMC_SCRATCH0) & EMC_SEPT_RUN;
h_cfg.rcm_patched = true;
h_cfg.sd_timeoff = 0;
}
int create_config_entry()

View file

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

View file

@ -96,7 +96,7 @@ static u32 _parity32_even(u32 *words, u32 count)
lo = ((x & 0xf) ^ (x >> 4)) & 3;
hi = ((x & 0xf) ^ (x >> 4)) >> 2;
x = hi ^ lo;
return (x & 1) ^ (x >> 1);
}

View file

@ -19,6 +19,7 @@
#include "sdmmc.h"
#include "mmc.h"
#include "sd.h"
#include "../config/config.h"
#include "../gfx/gfx.h"
#include "../mem/heap.h"
#include "../utils/util.h"
@ -26,6 +27,8 @@
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DPRINTF(...)
extern hekate_config h_cfg;
static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size)
{
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)
{
case 11:
// Fall through if not supported.
if (buf[13] & SD_MODE_UHS_SDR104)
{
type = 11;
@ -841,7 +845,6 @@ int _sd_storage_enable_highspeed_low_volt(sdmmc_storage_t *storage, u32 type, u8
storage->csd.busspeed = 104;
break;
}
//Fall through.
case 10:
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))
return 0;
//gfx_hexdump(0, (u8 *)buf, 64);
if (!(buf[13] & 2))
if (!(buf[13] & SD_MODE_HIGH_SPEED))
return 1;
if (!_sd_storage_enable_highspeed(storage, 1, buf))
@ -1012,6 +1015,11 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32 bus_width, u32 type)
{
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));
storage->sdmmc = sdmmc;

View file

@ -19,6 +19,7 @@
#include "mmc.h"
#include "sdmmc.h"
#include "../config/config.h"
#include "../gfx/gfx.h"
#include "../power/max7762x.h"
#include "../soc/clock.h"
@ -31,6 +32,8 @@
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DPRINTF(...)
extern hekate_config h_cfg;
/*! SCMMC controller base addresses. */
static const u32 _sdmmc_bases[4] = {
0x700B0000,
@ -1037,6 +1040,7 @@ void sdmmc_end(sdmmc_t *sdmmc)
{
gpio_output_enable(GPIO_PORT_E, GPIO_PIN_4, GPIO_OUTPUT_DISABLE);
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.
}