mirror of
https://github.com/CTCaer/hekate
synced 2024-12-22 19:31:12 +00:00
sdmmc v2: Add full SD card fallback initialization
hekate main always runs in compatibility mode (SDR82). This ensures speed on boot process. Nyx will first try SDR104. If the sd card is a sandisk U1 and fails, it will try the compatibility mode. After that it fallbacks to lower bus speeds. Both support 1bit mode for broken sd card readers. Having the new error checking in the sdmmc driver, allows for all that to work. It can now fail instead of continuing, like how HOS reacts.
This commit is contained in:
parent
034f680a8e
commit
ce97b97c8d
6 changed files with 230 additions and 21 deletions
|
@ -23,24 +23,96 @@
|
||||||
#include "../mem/heap.h"
|
#include "../mem/heap.h"
|
||||||
|
|
||||||
static bool sd_mounted = false;
|
static bool sd_mounted = false;
|
||||||
|
static u32 sd_mode = SD_UHS_SDR82;
|
||||||
|
|
||||||
|
u32 sd_mode_get()
|
||||||
|
{
|
||||||
|
return sd_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sd_init_retry(bool power_cycle)
|
||||||
|
{
|
||||||
|
u32 bus_width = SDMMC_BUS_WIDTH_4;
|
||||||
|
u32 type = SDHCI_TIMING_UHS_SDR82;
|
||||||
|
|
||||||
|
// Power cycle SD card.
|
||||||
|
if (power_cycle)
|
||||||
|
{
|
||||||
|
sd_mode--;
|
||||||
|
sdmmc_storage_end(&sd_storage);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get init parameters.
|
||||||
|
switch (sd_mode)
|
||||||
|
{
|
||||||
|
case SD_INIT_FAIL: // Reset to max.
|
||||||
|
return 0;
|
||||||
|
case SD_1BIT_HS25:
|
||||||
|
bus_width = SDMMC_BUS_WIDTH_1;
|
||||||
|
type = SDHCI_TIMING_SD_HS25;
|
||||||
|
break;
|
||||||
|
case SD_4BIT_HS25:
|
||||||
|
type = SDHCI_TIMING_SD_HS25;
|
||||||
|
break;
|
||||||
|
case SD_UHS_SDR82:
|
||||||
|
type = SDHCI_TIMING_UHS_SDR82;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sd_mode = SD_UHS_SDR82;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sdmmc_storage_init_sd(&sd_storage, &sd_sdmmc, bus_width, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sd_initialize(bool power_cycle)
|
||||||
|
{
|
||||||
|
if (power_cycle)
|
||||||
|
sdmmc_storage_end(&sd_storage);
|
||||||
|
|
||||||
|
int res = !sd_init_retry(false);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (!res)
|
||||||
|
return true;
|
||||||
|
else if (!sdmmc_get_sd_inserted()) // SD Card is not inserted.
|
||||||
|
{
|
||||||
|
sd_mode = SD_UHS_SDR82;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (sd_mode == SD_INIT_FAIL)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
res = !sd_init_retry(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
sdmmc_storage_end(&sd_storage);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool sd_mount()
|
bool sd_mount()
|
||||||
{
|
{
|
||||||
if (sd_mounted)
|
if (sd_mounted)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!sdmmc_storage_init_sd(&sd_storage, &sd_sdmmc, SDMMC_BUS_WIDTH_4, SDHCI_TIMING_UHS_SDR82))
|
int res = !sd_initialize(false);
|
||||||
|
|
||||||
|
if (res)
|
||||||
{
|
{
|
||||||
gfx_con.mute = false;
|
gfx_con.mute = false;
|
||||||
EPRINTF("Failed to init SD card.\nMake sure that it is inserted.\nOr that SD reader is properly seated!");
|
EPRINTF("Failed to init SD card.");
|
||||||
|
if (!sdmmc_get_sd_inserted())
|
||||||
|
EPRINTF("Make sure that it is inserted.");
|
||||||
|
else
|
||||||
|
EPRINTF("SD Card Reader is not properly seated!");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int res = 0;
|
|
||||||
res = f_mount(&sd_fs, "", 1);
|
res = f_mount(&sd_fs, "", 1);
|
||||||
if (res == FR_OK)
|
if (res == FR_OK)
|
||||||
{
|
{
|
||||||
sd_mounted = 1;
|
sd_mounted = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -55,6 +127,7 @@ bool sd_mount()
|
||||||
|
|
||||||
void sd_unmount()
|
void sd_unmount()
|
||||||
{
|
{
|
||||||
|
sd_mode = SD_UHS_SDR82;
|
||||||
if (sd_mounted)
|
if (sd_mounted)
|
||||||
{
|
{
|
||||||
f_mount(NULL, "", 1);
|
f_mount(NULL, "", 1);
|
||||||
|
|
|
@ -22,10 +22,21 @@
|
||||||
#include "sdmmc_driver.h"
|
#include "sdmmc_driver.h"
|
||||||
#include "../libs/fatfs/ff.h"
|
#include "../libs/fatfs/ff.h"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SD_INIT_FAIL = 0,
|
||||||
|
SD_1BIT_HS25 = 1,
|
||||||
|
SD_4BIT_HS25 = 2,
|
||||||
|
SD_UHS_SDR82 = 3,
|
||||||
|
};
|
||||||
|
|
||||||
sdmmc_t sd_sdmmc;
|
sdmmc_t sd_sdmmc;
|
||||||
sdmmc_storage_t sd_storage;
|
sdmmc_storage_t sd_storage;
|
||||||
FATFS sd_fs;
|
FATFS sd_fs;
|
||||||
|
|
||||||
|
u32 sd_mode_get();
|
||||||
|
int sd_init_retry(bool power_cycle);
|
||||||
|
bool sd_initialize(bool power_cycle);
|
||||||
bool sd_mount();
|
bool sd_mount();
|
||||||
void sd_unmount();
|
void sd_unmount();
|
||||||
void *sd_file_read(const char *path, u32 *fsize);
|
void *sd_file_read(const char *path, u32 *fsize);
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "sdmmc.h"
|
#include "sdmmc.h"
|
||||||
#include "mmc.h"
|
#include "mmc.h"
|
||||||
|
#include "nx_sd.h"
|
||||||
#include "sd.h"
|
#include "sd.h"
|
||||||
#include "../../common/memory_map.h"
|
#include "../../common/memory_map.h"
|
||||||
#include "../gfx/gfx.h"
|
#include "../gfx/gfx.h"
|
||||||
|
@ -172,25 +173,42 @@ int sdmmc_storage_end(sdmmc_storage_t *storage)
|
||||||
static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf, u32 is_write)
|
static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf, u32 is_write)
|
||||||
{
|
{
|
||||||
u8 *bbuf = (u8 *)buf;
|
u8 *bbuf = (u8 *)buf;
|
||||||
|
bool first_reinit = false;
|
||||||
while (num_sectors)
|
while (num_sectors)
|
||||||
{
|
{
|
||||||
u32 blkcnt = 0;
|
u32 blkcnt = 0;
|
||||||
//Retry 9 times on error.
|
// Retry 5 times if failed.
|
||||||
u32 retries = 10;
|
u32 retries = 5;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
reinit_try:
|
||||||
if (_sdmmc_storage_readwrite_ex(storage, &blkcnt, sector, MIN(num_sectors, 0xFFFF), bbuf, is_write))
|
if (_sdmmc_storage_readwrite_ex(storage, &blkcnt, sector, MIN(num_sectors, 0xFFFF), bbuf, is_write))
|
||||||
goto out;
|
goto out;
|
||||||
else
|
else
|
||||||
retries--;
|
retries--;
|
||||||
|
|
||||||
msleep(100);
|
msleep(50);
|
||||||
} while (retries);
|
} while (retries);
|
||||||
|
|
||||||
|
// Disk IO failure! Reinit SD Card to a lower speed.
|
||||||
|
if (storage->sdmmc->id == SDMMC_1)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
if (!first_reinit)
|
||||||
|
res = sd_initialize(true);
|
||||||
|
else
|
||||||
|
res = sd_init_retry(true);
|
||||||
|
|
||||||
|
retries = 3;
|
||||||
|
first_reinit = true;
|
||||||
|
|
||||||
|
if (res)
|
||||||
|
goto reinit_try;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out:;
|
out:
|
||||||
DPRINTF("readwrite: %08X\n", blkcnt);
|
DPRINTF("readwrite: %08X\n", blkcnt);
|
||||||
sector += blkcnt;
|
sector += blkcnt;
|
||||||
num_sectors -= blkcnt;
|
num_sectors -= blkcnt;
|
||||||
|
|
|
@ -33,6 +33,78 @@ bool sd_get_card_removed()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 sd_mode_get()
|
||||||
|
{
|
||||||
|
return sd_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sd_init_retry(bool power_cycle)
|
||||||
|
{
|
||||||
|
u32 bus_width = SDMMC_BUS_WIDTH_4;
|
||||||
|
u32 type = SDHCI_TIMING_UHS_SDR104;
|
||||||
|
|
||||||
|
// Power cycle SD card.
|
||||||
|
if (power_cycle)
|
||||||
|
{
|
||||||
|
sd_mode--;
|
||||||
|
sdmmc_storage_end(&sd_storage);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get init parameters.
|
||||||
|
switch (sd_mode)
|
||||||
|
{
|
||||||
|
case SD_INIT_FAIL: // Reset to max.
|
||||||
|
return 0;
|
||||||
|
case SD_1BIT_HS25:
|
||||||
|
bus_width = SDMMC_BUS_WIDTH_1;
|
||||||
|
type = SDHCI_TIMING_SD_HS25;
|
||||||
|
break;
|
||||||
|
case SD_4BIT_HS25:
|
||||||
|
type = SDHCI_TIMING_SD_HS25;
|
||||||
|
break;
|
||||||
|
case SD_UHS_SDR82:
|
||||||
|
type = SDHCI_TIMING_UHS_SDR82;
|
||||||
|
break;
|
||||||
|
case SD_UHS_SDR104:
|
||||||
|
type = SDHCI_TIMING_UHS_SDR104;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sd_mode = SD_UHS_SDR104;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sdmmc_storage_init_sd(&sd_storage, &sd_sdmmc, bus_width, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sd_initialize(bool power_cycle)
|
||||||
|
{
|
||||||
|
if (power_cycle)
|
||||||
|
sdmmc_storage_end(&sd_storage);
|
||||||
|
|
||||||
|
int res = !sd_init_retry(false);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (!res)
|
||||||
|
return true;
|
||||||
|
else if (!sdmmc_get_sd_inserted()) // SD Card is not inserted.
|
||||||
|
{
|
||||||
|
sd_mode = SD_UHS_SDR104;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (sd_mode == SD_INIT_FAIL)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
res = !sd_init_retry(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sdmmc_storage_end(&sd_storage);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool sd_mount()
|
bool sd_mount()
|
||||||
{
|
{
|
||||||
if (sd_mounted)
|
if (sd_mounted)
|
||||||
|
@ -41,19 +113,20 @@ bool sd_mount()
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
if (!sd_init_done)
|
if (!sd_init_done)
|
||||||
{
|
res = !sd_initialize(false);
|
||||||
res = !sdmmc_storage_init_sd(&sd_storage, &sd_sdmmc, SDMMC_BUS_WIDTH_4, SDHCI_TIMING_UHS_SDR82);
|
|
||||||
if (!res)
|
|
||||||
sd_init_done = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
EPRINTF("Failed to init SD card.\nMake sure that it is inserted.\nOr that SD reader is properly seated!");
|
EPRINTF("Failed to init SD card.");
|
||||||
|
if (!sdmmc_get_sd_inserted())
|
||||||
|
EPRINTF("Make sure that it is inserted.");
|
||||||
|
else
|
||||||
|
EPRINTF("SD Card Reader is not properly seated!");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int res = f_mount(&sd_fs, "", 1);
|
sd_init_done = true;
|
||||||
|
res = f_mount(&sd_fs, "", 1);
|
||||||
if (res == FR_OK)
|
if (res == FR_OK)
|
||||||
{
|
{
|
||||||
sd_mounted = true;
|
sd_mounted = true;
|
||||||
|
@ -70,6 +143,9 @@ bool sd_mount()
|
||||||
|
|
||||||
void sd_unmount(bool deinit)
|
void sd_unmount(bool deinit)
|
||||||
{
|
{
|
||||||
|
if (sd_mode == SD_INIT_FAIL)
|
||||||
|
sd_mode = SD_UHS_SDR104;
|
||||||
|
|
||||||
if (sd_init_done && sd_mounted)
|
if (sd_init_done && sd_mounted)
|
||||||
{
|
{
|
||||||
f_mount(NULL, "", 1);
|
f_mount(NULL, "", 1);
|
||||||
|
|
|
@ -22,11 +22,23 @@
|
||||||
#include "sdmmc_driver.h"
|
#include "sdmmc_driver.h"
|
||||||
#include "../libs/fatfs/ff.h"
|
#include "../libs/fatfs/ff.h"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SD_INIT_FAIL = 0,
|
||||||
|
SD_1BIT_HS25 = 1,
|
||||||
|
SD_4BIT_HS25 = 2,
|
||||||
|
SD_UHS_SDR82 = 3,
|
||||||
|
SD_UHS_SDR104 = 4
|
||||||
|
};
|
||||||
|
|
||||||
sdmmc_t sd_sdmmc;
|
sdmmc_t sd_sdmmc;
|
||||||
sdmmc_storage_t sd_storage;
|
sdmmc_storage_t sd_storage;
|
||||||
FATFS sd_fs;
|
FATFS sd_fs;
|
||||||
|
|
||||||
bool sd_get_card_removed();
|
bool sd_get_card_removed();
|
||||||
|
u32 sd_get_mode();
|
||||||
|
int sd_init_retry(bool power_cycle);
|
||||||
|
bool sd_initialize(bool power_cycle);
|
||||||
bool sd_mount();
|
bool sd_mount();
|
||||||
void sd_unmount(bool deinit);
|
void sd_unmount(bool deinit);
|
||||||
void *sd_file_read(const char *path, u32 *fsize);
|
void *sd_file_read(const char *path, u32 *fsize);
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "sdmmc.h"
|
#include "sdmmc.h"
|
||||||
#include "mmc.h"
|
#include "mmc.h"
|
||||||
|
#include "nx_sd.h"
|
||||||
#include "sd.h"
|
#include "sd.h"
|
||||||
#include "../../../common/memory_map.h"
|
#include "../../../common/memory_map.h"
|
||||||
#include "../gfx/gfx.h"
|
#include "../gfx/gfx.h"
|
||||||
|
@ -172,25 +173,43 @@ int sdmmc_storage_end(sdmmc_storage_t *storage)
|
||||||
static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf, u32 is_write)
|
static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf, u32 is_write)
|
||||||
{
|
{
|
||||||
u8 *bbuf = (u8 *)buf;
|
u8 *bbuf = (u8 *)buf;
|
||||||
|
bool first_reinit = false;
|
||||||
while (num_sectors)
|
while (num_sectors)
|
||||||
{
|
{
|
||||||
u32 blkcnt = 0;
|
u32 blkcnt = 0;
|
||||||
//Retry 9 times on error.
|
// Retry 5 times if failed.
|
||||||
u32 retries = 10;
|
u32 retries = 5;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
reinit_try:
|
||||||
if (_sdmmc_storage_readwrite_ex(storage, &blkcnt, sector, MIN(num_sectors, 0xFFFF), bbuf, is_write))
|
if (_sdmmc_storage_readwrite_ex(storage, &blkcnt, sector, MIN(num_sectors, 0xFFFF), bbuf, is_write))
|
||||||
goto out;
|
goto out;
|
||||||
else
|
else
|
||||||
retries--;
|
retries--;
|
||||||
|
|
||||||
msleep(100);
|
msleep(50);
|
||||||
} while (retries);
|
} while (retries);
|
||||||
|
|
||||||
|
// Disk IO failure! Reinit SD Card to a lower speed.
|
||||||
|
if (storage->sdmmc->id == SDMMC_1)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (!first_reinit)
|
||||||
|
res = sd_initialize(true);
|
||||||
|
else
|
||||||
|
res = sd_init_retry(true);
|
||||||
|
|
||||||
|
retries = 3;
|
||||||
|
first_reinit = true;
|
||||||
|
|
||||||
|
if (res)
|
||||||
|
goto reinit_try;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out:;
|
out:
|
||||||
DPRINTF("readwrite: %08X\n", blkcnt);
|
DPRINTF("readwrite: %08X\n", blkcnt);
|
||||||
sector += blkcnt;
|
sector += blkcnt;
|
||||||
num_sectors -= blkcnt;
|
num_sectors -= blkcnt;
|
||||||
|
|
Loading…
Reference in a new issue