mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
fusee: cleanup sdmmc related code
This commit is contained in:
parent
8bd79e8299
commit
a4daa0761a
15 changed files with 330 additions and 314 deletions
|
@ -38,7 +38,7 @@ bool mount_sd(void)
|
||||||
|
|
||||||
if (!g_sd_initialized) {
|
if (!g_sd_initialized) {
|
||||||
/* Initialize SD. */
|
/* Initialize SD. */
|
||||||
if (sdmmc_device_sd_init(&g_sd_device, &g_sd_sdmmc, SDMMC_BUS_WIDTH_4BIT, SDMMC_SPEED_SDR104))
|
if (sdmmc_device_sd_init(&g_sd_device, &g_sd_sdmmc, SDMMC_BUS_WIDTH_4BIT, SDMMC_SPEED_UHS_SDR104))
|
||||||
{
|
{
|
||||||
g_sd_initialized = true;
|
g_sd_initialized = true;
|
||||||
|
|
||||||
|
|
|
@ -727,11 +727,11 @@ static int sdmmc_sd_switch_hs_low(sdmmc_device_t *device, uint8_t *status)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_SDR104))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_UHS_SDR104))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Run tuning. */
|
/* Run tuning. */
|
||||||
if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_SDR104, MMC_SEND_TUNING_BLOCK))
|
if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_UHS_SDR104, MMC_SEND_TUNING_BLOCK))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (status[13] & SD_MODE_UHS_SDR50) /* High-speed SDR50 is supported. */
|
else if (status[13] & SD_MODE_UHS_SDR50) /* High-speed SDR50 is supported. */
|
||||||
|
@ -741,11 +741,11 @@ static int sdmmc_sd_switch_hs_low(sdmmc_device_t *device, uint8_t *status)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_SDR50))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_UHS_SDR50))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Run tuning. */
|
/* Run tuning. */
|
||||||
if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_SDR50, MMC_SEND_TUNING_BLOCK))
|
if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_UHS_SDR50, MMC_SEND_TUNING_BLOCK))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (status[13] & SD_MODE_UHS_SDR12) /* High-speed SDR12 is supported. */
|
else if (status[13] & SD_MODE_UHS_SDR12) /* High-speed SDR12 is supported. */
|
||||||
|
@ -755,11 +755,11 @@ static int sdmmc_sd_switch_hs_low(sdmmc_device_t *device, uint8_t *status)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_SDR12))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_UHS_SDR12))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Run tuning. */
|
/* Run tuning. */
|
||||||
if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_SDR12, MMC_SEND_TUNING_BLOCK))
|
if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_UHS_SDR12, MMC_SEND_TUNING_BLOCK))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -784,7 +784,7 @@ static int sdmmc_sd_switch_hs_high(sdmmc_device_t *device, uint8_t *status)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_SDR25))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_UHS_SDR25))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Peek the SD card's status. */
|
/* Peek the SD card's status. */
|
||||||
|
@ -841,7 +841,7 @@ int sdmmc_device_sd_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth b
|
||||||
memset(device, 0, sizeof(sdmmc_device_t));
|
memset(device, 0, sizeof(sdmmc_device_t));
|
||||||
|
|
||||||
/* Try to initialize the driver. */
|
/* Try to initialize the driver. */
|
||||||
if (!sdmmc_init(sdmmc, SDMMC_1, SDMMC_VOLTAGE_3V3, SDMMC_BUS_WIDTH_1BIT, SDMMC_SPEED_INIT_SDR))
|
if (!sdmmc_init(sdmmc, SDMMC_1, SDMMC_VOLTAGE_3V3, SDMMC_BUS_WIDTH_1BIT, SDMMC_SPEED_SD_INIT))
|
||||||
{
|
{
|
||||||
sdmmc_error(sdmmc, "Failed to initialize the SDMMC driver!");
|
sdmmc_error(sdmmc, "Failed to initialize the SDMMC driver!");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -874,7 +874,7 @@ int sdmmc_device_sd_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth b
|
||||||
sdmmc_info(sdmmc, "Sent if cond to SD card!");
|
sdmmc_info(sdmmc, "Sent if cond to SD card!");
|
||||||
|
|
||||||
/* Get the SD card's operating conditions. */
|
/* Get the SD card's operating conditions. */
|
||||||
if (!sdmmc_sd_send_op_cond(device, is_sd_ver2, (bus_width == SDMMC_BUS_WIDTH_4BIT) && (bus_speed == SDMMC_SPEED_SDR104)))
|
if (!sdmmc_sd_send_op_cond(device, is_sd_ver2, (bus_width == SDMMC_BUS_WIDTH_4BIT) && (bus_speed == SDMMC_SPEED_UHS_SDR104)))
|
||||||
{
|
{
|
||||||
sdmmc_error(sdmmc, "Failed to send op cond!");
|
sdmmc_error(sdmmc, "Failed to send op cond!");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -920,7 +920,7 @@ int sdmmc_device_sd_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth b
|
||||||
if (!device->is_180v)
|
if (!device->is_180v)
|
||||||
{
|
{
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_UNK6))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_SD_LEGACY))
|
||||||
{
|
{
|
||||||
sdmmc_error(sdmmc, "Failed to apply the correct bus speed!");
|
sdmmc_error(sdmmc, "Failed to apply the correct bus speed!");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -998,7 +998,7 @@ int sdmmc_device_sd_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth b
|
||||||
|
|
||||||
sdmmc_info(sdmmc, "Switched to high-speed from low voltage!");
|
sdmmc_info(sdmmc, "Switched to high-speed from low voltage!");
|
||||||
}
|
}
|
||||||
else if ((device->scr.sda_vsn & (SD_SCR_SPEC_VER_1 | SD_SCR_SPEC_VER_2)) && ((bus_speed != SDMMC_SPEED_UNK6)))
|
else if ((device->scr.sda_vsn & (SD_SCR_SPEC_VER_1 | SD_SCR_SPEC_VER_2)) && ((bus_speed != SDMMC_SPEED_SD_LEGACY)))
|
||||||
{
|
{
|
||||||
/* Switch to high-speed from high voltage (if possible). */
|
/* Switch to high-speed from high voltage (if possible). */
|
||||||
if (!sdmmc_sd_switch_hs_high(device, switch_status))
|
if (!sdmmc_sd_switch_hs_high(device, switch_status))
|
||||||
|
@ -1273,7 +1273,7 @@ static int sdmmc_mmc_select_hs(sdmmc_device_t *device, bool ignore_status)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_HS52))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_MMC_HS))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Check the status if necessary. */
|
/* Check the status if necessary. */
|
||||||
|
@ -1292,11 +1292,11 @@ static int sdmmc_mmc_select_hs200(sdmmc_device_t *device)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_HS200))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_MMC_HS200))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Execute tuning procedure. */
|
/* Execute tuning procedure. */
|
||||||
if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_HS200, MMC_SEND_TUNING_BLOCK_HS200))
|
if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_MMC_HS200, MMC_SEND_TUNING_BLOCK_HS200))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Peek the current status. */
|
/* Peek the current status. */
|
||||||
|
@ -1331,7 +1331,7 @@ static int sdmmc_mmc_select_hs400(sdmmc_device_t *device)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_HS400))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_MMC_HS400))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Peek the current status. */
|
/* Peek the current status. */
|
||||||
|
@ -1340,14 +1340,14 @@ static int sdmmc_mmc_select_hs400(sdmmc_device_t *device)
|
||||||
|
|
||||||
static int sdmmc_mmc_select_timing(sdmmc_device_t *device, SdmmcBusSpeed bus_speed)
|
static int sdmmc_mmc_select_timing(sdmmc_device_t *device, SdmmcBusSpeed bus_speed)
|
||||||
{
|
{
|
||||||
if ((bus_speed == SDMMC_SPEED_HS400) &&
|
if ((bus_speed == SDMMC_SPEED_MMC_HS400) &&
|
||||||
(device->sdmmc->bus_width == SDMMC_BUS_WIDTH_8BIT) &&
|
(device->sdmmc->bus_width == SDMMC_BUS_WIDTH_8BIT) &&
|
||||||
(device->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_HS400_1_8V))
|
(device->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_HS400_1_8V))
|
||||||
{
|
{
|
||||||
/* Switch to HS400. */
|
/* Switch to HS400. */
|
||||||
return sdmmc_mmc_select_hs400(device);
|
return sdmmc_mmc_select_hs400(device);
|
||||||
}
|
}
|
||||||
else if (((bus_speed == SDMMC_SPEED_HS400) || (bus_speed == SDMMC_SPEED_HS200)) &&
|
else if (((bus_speed == SDMMC_SPEED_MMC_HS400) || (bus_speed == SDMMC_SPEED_MMC_HS200)) &&
|
||||||
((device->sdmmc->bus_width == SDMMC_BUS_WIDTH_8BIT) || (device->sdmmc->bus_width == SDMMC_BUS_WIDTH_4BIT)) &&
|
((device->sdmmc->bus_width == SDMMC_BUS_WIDTH_8BIT) || (device->sdmmc->bus_width == SDMMC_BUS_WIDTH_4BIT)) &&
|
||||||
(device->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_HS200_1_8V))
|
(device->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_HS200_1_8V))
|
||||||
{
|
{
|
||||||
|
@ -1397,7 +1397,7 @@ int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth
|
||||||
memset(device, 0, sizeof(sdmmc_device_t));
|
memset(device, 0, sizeof(sdmmc_device_t));
|
||||||
|
|
||||||
/* Try to initialize the driver. */
|
/* Try to initialize the driver. */
|
||||||
if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_VOLTAGE_1V8, SDMMC_BUS_WIDTH_1BIT, SDMMC_SPEED_INIT_HS))
|
if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_VOLTAGE_1V8, SDMMC_BUS_WIDTH_1BIT, SDMMC_SPEED_MMC_INIT))
|
||||||
{
|
{
|
||||||
sdmmc_error(sdmmc, "Failed to initialize the SDMMC driver!");
|
sdmmc_error(sdmmc, "Failed to initialize the SDMMC driver!");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1464,7 +1464,7 @@ int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth
|
||||||
sdmmc_warn(sdmmc, "Got unknown CSD structure (0x%08x)!", device->csd.structure);
|
sdmmc_warn(sdmmc, "Got unknown CSD structure (0x%08x)!", device->csd.structure);
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_HS26))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_MMC_LEGACY))
|
||||||
{
|
{
|
||||||
sdmmc_error(sdmmc, "Failed to apply the correct bus speed!");
|
sdmmc_error(sdmmc, "Failed to apply the correct bus speed!");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -289,26 +289,28 @@ static int sdmmc_get_sdclk_freq(SdmmcBusSpeed bus_speed)
|
||||||
{
|
{
|
||||||
switch (bus_speed)
|
switch (bus_speed)
|
||||||
{
|
{
|
||||||
case SDMMC_SPEED_INIT_HS:
|
case SDMMC_SPEED_MMC_INIT:
|
||||||
case SDMMC_SPEED_HS26:
|
case SDMMC_SPEED_MMC_LEGACY:
|
||||||
return 26000;
|
return 26000;
|
||||||
case SDMMC_SPEED_HS52:
|
case SDMMC_SPEED_MMC_HS:
|
||||||
return 52000;
|
return 52000;
|
||||||
case SDMMC_SPEED_HS200:
|
case SDMMC_SPEED_MMC_HS200:
|
||||||
case SDMMC_SPEED_HS400:
|
case SDMMC_SPEED_MMC_HS400:
|
||||||
case SDMMC_SPEED_SDR104:
|
case SDMMC_SPEED_UHS_SDR104:
|
||||||
|
case SDMMC_SPEED_EMU_SDR104:
|
||||||
return 200000;
|
return 200000;
|
||||||
case SDMMC_SPEED_INIT_SDR:
|
case SDMMC_SPEED_SD_INIT:
|
||||||
case SDMMC_SPEED_UNK6:
|
case SDMMC_SPEED_SD_LEGACY:
|
||||||
case SDMMC_SPEED_SDR12:
|
case SDMMC_SPEED_UHS_SDR12:
|
||||||
return 25000;
|
return 25000;
|
||||||
case SDMMC_SPEED_SDR25:
|
case SDMMC_SPEED_SD_HS:
|
||||||
|
case SDMMC_SPEED_UHS_SDR25:
|
||||||
return 50000;
|
return 50000;
|
||||||
case SDMMC_SPEED_SDR50:
|
case SDMMC_SPEED_UHS_SDR50:
|
||||||
return 100000;
|
return 100000;
|
||||||
case SDMMC_SPEED_DDR50:
|
case SDMMC_SPEED_UHS_DDR50:
|
||||||
return 40800;
|
return 40800;
|
||||||
case SDMMC_SPEED_UNK14:
|
case SDMMC_SPEED_MMC_DDR52:
|
||||||
return 200000;
|
return 200000;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -320,22 +322,23 @@ static int sdmmc_get_sdclk_div(SdmmcBusSpeed bus_speed)
|
||||||
{
|
{
|
||||||
switch (bus_speed)
|
switch (bus_speed)
|
||||||
{
|
{
|
||||||
case SDMMC_SPEED_INIT_HS:
|
case SDMMC_SPEED_MMC_INIT:
|
||||||
return 66;
|
return 66;
|
||||||
case SDMMC_SPEED_INIT_SDR:
|
case SDMMC_SPEED_SD_INIT:
|
||||||
// TODO: TRM says return 64?
|
case SDMMC_SPEED_MMC_LEGACY:
|
||||||
case SDMMC_SPEED_HS26:
|
case SDMMC_SPEED_MMC_HS:
|
||||||
case SDMMC_SPEED_HS52:
|
case SDMMC_SPEED_MMC_HS200:
|
||||||
case SDMMC_SPEED_HS200:
|
case SDMMC_SPEED_MMC_HS400:
|
||||||
case SDMMC_SPEED_HS400:
|
case SDMMC_SPEED_SD_LEGACY:
|
||||||
case SDMMC_SPEED_UNK6:
|
case SDMMC_SPEED_SD_HS:
|
||||||
case SDMMC_SPEED_SDR25:
|
case SDMMC_SPEED_UHS_SDR12:
|
||||||
case SDMMC_SPEED_SDR12:
|
case SDMMC_SPEED_UHS_SDR25:
|
||||||
case SDMMC_SPEED_SDR50:
|
case SDMMC_SPEED_UHS_SDR50:
|
||||||
case SDMMC_SPEED_SDR104:
|
case SDMMC_SPEED_UHS_SDR104:
|
||||||
case SDMMC_SPEED_DDR50:
|
case SDMMC_SPEED_UHS_DDR50:
|
||||||
|
case SDMMC_SPEED_EMU_SDR104:
|
||||||
return 1;
|
return 1;
|
||||||
case SDMMC_SPEED_UNK14:
|
case SDMMC_SPEED_MMC_DDR52:
|
||||||
return 2;
|
return 2;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -354,35 +357,35 @@ static int sdmmc_clk_set_source(SdmmcControllerNum controller, uint32_t clk_freq
|
||||||
{
|
{
|
||||||
case 25000:
|
case 25000:
|
||||||
out_freq = 24728;
|
out_freq = 24728;
|
||||||
car_div = SDMMC_CAR_DIVIDER_SDR12;
|
car_div = SDMMC_CAR_DIVIDER_UHS_SDR12;
|
||||||
break;
|
break;
|
||||||
case 26000:
|
case 26000:
|
||||||
out_freq = 25500;
|
out_freq = 25500;
|
||||||
car_div = SDMMC_CAR_DIVIDER_HS26;
|
car_div = SDMMC_CAR_DIVIDER_MMC_LEGACY;
|
||||||
break;
|
break;
|
||||||
case 40800:
|
case 40800:
|
||||||
out_freq = 40800;
|
out_freq = 40800;
|
||||||
car_div = SDMMC_CAR_DIVIDER_DDR50;
|
car_div = SDMMC_CAR_DIVIDER_UHS_DDR50;
|
||||||
break;
|
break;
|
||||||
case 50000:
|
case 50000:
|
||||||
out_freq = 48000;
|
out_freq = 48000;
|
||||||
car_div = SDMMC_CAR_DIVIDER_SDR25;
|
car_div = SDMMC_CAR_DIVIDER_UHS_SDR25;
|
||||||
break;
|
break;
|
||||||
case 52000:
|
case 52000:
|
||||||
out_freq = 51000;
|
out_freq = 51000;
|
||||||
car_div = SDMMC_CAR_DIVIDER_HS52;
|
car_div = SDMMC_CAR_DIVIDER_MMC_HS;
|
||||||
break;
|
break;
|
||||||
case 100000:
|
case 100000:
|
||||||
out_freq = 90667;
|
out_freq = 90667;
|
||||||
car_div = SDMMC_CAR_DIVIDER_SDR50;
|
car_div = SDMMC_CAR_DIVIDER_UHS_SDR50;
|
||||||
break;
|
break;
|
||||||
case 200000:
|
case 200000:
|
||||||
out_freq = 163200;
|
out_freq = 163200;
|
||||||
car_div = SDMMC_CAR_DIVIDER_HS200;
|
car_div = SDMMC_CAR_DIVIDER_MMC_HS200;
|
||||||
break;
|
break;
|
||||||
case 208000:
|
case 208000:
|
||||||
out_freq = 204000;
|
out_freq = 204000;
|
||||||
car_div = SDMMC_CAR_DIVIDER_SDR104;
|
car_div = SDMMC_CAR_DIVIDER_UHS_SDR104;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -747,7 +750,7 @@ void sdmmc_select_voltage(sdmmc_t *sdmmc, SdmmcBusVoltage voltage)
|
||||||
|
|
||||||
static void sdmmc_tap_config(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed)
|
static void sdmmc_tap_config(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed)
|
||||||
{
|
{
|
||||||
if (bus_speed == SDMMC_SPEED_HS400)
|
if (bus_speed == SDMMC_SPEED_MMC_HS400)
|
||||||
{
|
{
|
||||||
/* Clear and set DQS_TRIM_VAL (used in HS400) */
|
/* Clear and set DQS_TRIM_VAL (used in HS400) */
|
||||||
sdmmc->regs->vendor_cap_overrides &= ~(0x3F00);
|
sdmmc->regs->vendor_cap_overrides &= ~(0x3F00);
|
||||||
|
@ -757,7 +760,7 @@ static void sdmmc_tap_config(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed)
|
||||||
/* Clear TAP_VAL_UPDATED_BY_HW */
|
/* Clear TAP_VAL_UPDATED_BY_HW */
|
||||||
sdmmc->regs->vendor_tuning_cntrl0 &= ~(0x20000);
|
sdmmc->regs->vendor_tuning_cntrl0 &= ~(0x20000);
|
||||||
|
|
||||||
if (bus_speed == SDMMC_SPEED_HS400)
|
if (bus_speed == SDMMC_SPEED_MMC_HS400)
|
||||||
{
|
{
|
||||||
/* We must have obtained the tap value from the tuning procedure here. */
|
/* We must have obtained the tap value from the tuning procedure here. */
|
||||||
if (sdmmc->is_tuning_tap_val_set)
|
if (sdmmc->is_tuning_tap_val_set)
|
||||||
|
@ -863,41 +866,43 @@ int sdmmc_select_speed(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed)
|
||||||
/* Set the appropriate host speed. */
|
/* Set the appropriate host speed. */
|
||||||
switch (bus_speed) {
|
switch (bus_speed) {
|
||||||
/* 400kHz initialization mode and a few others. */
|
/* 400kHz initialization mode and a few others. */
|
||||||
case SDMMC_SPEED_INIT_HS:
|
case SDMMC_SPEED_MMC_INIT:
|
||||||
case SDMMC_SPEED_HS26:
|
case SDMMC_SPEED_MMC_LEGACY:
|
||||||
case SDMMC_SPEED_INIT_SDR:
|
case SDMMC_SPEED_SD_INIT:
|
||||||
case SDMMC_SPEED_UNK6:
|
case SDMMC_SPEED_SD_LEGACY:
|
||||||
sdmmc->regs->host_control &= ~(SDHCI_CTRL_HISPD);
|
sdmmc->regs->host_control &= ~(SDHCI_CTRL_HISPD);
|
||||||
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_VDD_180);
|
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_VDD_180);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* 50MHz high speed (SD) and 52MHz high speed (MMC). */
|
/* 50MHz high speed (SD) and 52MHz high speed (MMC). */
|
||||||
case SDMMC_SPEED_SDR25:
|
case SDMMC_SPEED_SD_HS:
|
||||||
case SDMMC_SPEED_HS52:
|
case SDMMC_SPEED_MMC_HS:
|
||||||
|
case SDMMC_SPEED_UHS_SDR25:
|
||||||
sdmmc->regs->host_control |= SDHCI_CTRL_HISPD;
|
sdmmc->regs->host_control |= SDHCI_CTRL_HISPD;
|
||||||
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_VDD_180);
|
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_VDD_180);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* 200MHz UHS-I (SD) and other modes due to errata. */
|
/* 200MHz UHS-I (SD) and other modes due to errata. */
|
||||||
case SDMMC_SPEED_HS200:
|
case SDMMC_SPEED_MMC_HS200:
|
||||||
case SDMMC_SPEED_SDR104:
|
case SDMMC_SPEED_UHS_SDR104:
|
||||||
case SDMMC_SPEED_DDR50:
|
case SDMMC_SPEED_UHS_DDR50:
|
||||||
case SDMMC_SPEED_SDR50:
|
case SDMMC_SPEED_UHS_SDR50:
|
||||||
case SDMMC_SPEED_UNK14:
|
case SDMMC_SPEED_MMC_DDR52:
|
||||||
|
case SDMMC_SPEED_EMU_SDR104:
|
||||||
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK);
|
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK);
|
||||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_UHS_SDR104;
|
sdmmc->regs->host_control2 |= SDHCI_CTRL_UHS_SDR104;
|
||||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180;
|
sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* 200MHz single-data rate (MMC). */
|
/* 200MHz single-data rate (MMC). */
|
||||||
case SDMMC_SPEED_HS400:
|
case SDMMC_SPEED_MMC_HS400:
|
||||||
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK);
|
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK);
|
||||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_HS400;
|
sdmmc->regs->host_control2 |= SDHCI_CTRL_HS400;
|
||||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180;
|
sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* 25MHz default speed (SD). */
|
/* 25MHz default speed (SD). */
|
||||||
case SDMMC_SPEED_SDR12:
|
case SDMMC_SPEED_UHS_SDR12:
|
||||||
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK);
|
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK);
|
||||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_UHS_SDR12;
|
sdmmc->regs->host_control2 |= SDHCI_CTRL_UHS_SDR12;
|
||||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180;
|
sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180;
|
||||||
|
@ -936,7 +941,7 @@ int sdmmc_select_speed(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed)
|
||||||
sdmmc_enable_sd_clock(sdmmc);
|
sdmmc_enable_sd_clock(sdmmc);
|
||||||
|
|
||||||
/* Run DLLCAL for HS400 only */
|
/* Run DLLCAL for HS400 only */
|
||||||
if (bus_speed == SDMMC_SPEED_HS400)
|
if (bus_speed == SDMMC_SPEED_MMC_HS400)
|
||||||
return sdmmc_dllcal_run(sdmmc);
|
return sdmmc_dllcal_run(sdmmc);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1720,7 +1725,7 @@ int sdmmc_switch_voltage(sdmmc_t *sdmmc)
|
||||||
sdmmc_disable_sd_clock(sdmmc);
|
sdmmc_disable_sd_clock(sdmmc);
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(sdmmc, SDMMC_SPEED_SDR12))
|
if (!sdmmc_select_speed(sdmmc, SDMMC_SPEED_UHS_SDR12))
|
||||||
{
|
{
|
||||||
sdmmc_error(sdmmc, "Failed to apply the correct bus speed for low voltage support!");
|
sdmmc_error(sdmmc, "Failed to apply the correct bus speed for low voltage support!");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1883,15 +1888,16 @@ int sdmmc_execute_tuning(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed, uint32_t opcod
|
||||||
|
|
||||||
switch (bus_speed)
|
switch (bus_speed)
|
||||||
{
|
{
|
||||||
case SDMMC_SPEED_HS200:
|
case SDMMC_SPEED_MMC_HS200:
|
||||||
case SDMMC_SPEED_HS400:
|
case SDMMC_SPEED_MMC_HS400:
|
||||||
case SDMMC_SPEED_SDR104:
|
case SDMMC_SPEED_UHS_SDR104:
|
||||||
|
case SDMMC_SPEED_EMU_SDR104:
|
||||||
max_tuning_loop = 0x80;
|
max_tuning_loop = 0x80;
|
||||||
tuning_cntrl_flag = 0x4000;
|
tuning_cntrl_flag = 0x4000;
|
||||||
break;
|
break;
|
||||||
case SDMMC_SPEED_SDR50:
|
case SDMMC_SPEED_UHS_SDR50:
|
||||||
case SDMMC_SPEED_DDR50:
|
case SDMMC_SPEED_UHS_DDR50:
|
||||||
case SDMMC_SPEED_UNK14:
|
case SDMMC_SPEED_MMC_DDR52:
|
||||||
max_tuning_loop = 0x100;
|
max_tuning_loop = 0x100;
|
||||||
tuning_cntrl_flag = 0x8000;
|
tuning_cntrl_flag = 0x8000;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -210,33 +210,33 @@ typedef enum {
|
||||||
} SdmmcBusWidth;
|
} SdmmcBusWidth;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SDMMC_SPEED_INIT_HS = 0,
|
SDMMC_SPEED_MMC_INIT = 0,
|
||||||
SDMMC_SPEED_HS26 = 1,
|
SDMMC_SPEED_MMC_LEGACY = 1,
|
||||||
SDMMC_SPEED_HS52 = 2,
|
SDMMC_SPEED_MMC_HS = 2,
|
||||||
SDMMC_SPEED_HS200 = 3,
|
SDMMC_SPEED_MMC_HS200 = 3,
|
||||||
SDMMC_SPEED_HS400 = 4,
|
SDMMC_SPEED_MMC_HS400 = 4,
|
||||||
SDMMC_SPEED_INIT_SDR = 5,
|
SDMMC_SPEED_SD_INIT = 5,
|
||||||
SDMMC_SPEED_UNK6 = 6,
|
SDMMC_SPEED_SD_LEGACY = 6,
|
||||||
SDMMC_SPEED_SDR25 = 7,
|
SDMMC_SPEED_SD_HS = 7,
|
||||||
SDMMC_SPEED_SDR12 = 8,
|
SDMMC_SPEED_UHS_SDR12 = 8,
|
||||||
SDMMC_SPEED_UNK9 = 9,
|
SDMMC_SPEED_UHS_SDR25 = 9,
|
||||||
SDMMC_SPEED_SDR50 = 10,
|
SDMMC_SPEED_UHS_SDR50 = 10,
|
||||||
SDMMC_SPEED_SDR104 = 11,
|
SDMMC_SPEED_UHS_SDR104 = 11,
|
||||||
SDMMC_SPEED_UNK12 = 12,
|
SDMMC_SPEED_UHS_RESERVED = 12,
|
||||||
SDMMC_SPEED_DDR50 = 13,
|
SDMMC_SPEED_UHS_DDR50 = 13,
|
||||||
SDMMC_SPEED_UNK14 = 14,
|
SDMMC_SPEED_MMC_DDR52 = 14,
|
||||||
|
SDMMC_SPEED_EMU_SDR104 = 255, /* Custom speed mode. Prevents low voltage switch in MMC emulation. */
|
||||||
} SdmmcBusSpeed;
|
} SdmmcBusSpeed;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SDMMC_CAR_DIVIDER_SDR12 = 31, // (16.5 * 2) - 2
|
SDMMC_CAR_DIVIDER_UHS_SDR12 = 31, /* (16.5 * 2) - 2 */
|
||||||
SDMMC_CAR_DIVIDER_SDR25 = 15, // (8.5 * 2) - 2
|
SDMMC_CAR_DIVIDER_UHS_SDR25 = 15, /* (8.5 * 2) - 2 */
|
||||||
SDMMC_CAR_DIVIDER_SDR50 = 7, // (4.5 * 2) - 2
|
SDMMC_CAR_DIVIDER_UHS_SDR50 = 7, /* (4.5 * 2) - 2 */
|
||||||
SDMMC_CAR_DIVIDER_SDR104 = 2, // (2 * 2) - 2
|
SDMMC_CAR_DIVIDER_UHS_SDR104 = 2, /* (2 * 2) - 2 */
|
||||||
SDMMC_CAR_DIVIDER_DDR50 = 18, // (5 * 2 * 2) - 2
|
SDMMC_CAR_DIVIDER_UHS_DDR50 = 18, /* (5 * 2 * 2) - 2 */
|
||||||
SDMMC_CAR_DIVIDER_HS26 = 30, // (16 * 2) - 2
|
SDMMC_CAR_DIVIDER_MMC_LEGACY = 30, /* (16 * 2) - 2 */
|
||||||
SDMMC_CAR_DIVIDER_HS52 = 14, // (8 * 2) - 2
|
SDMMC_CAR_DIVIDER_MMC_HS = 14, /* (8 * 2) - 2 */
|
||||||
SDMMC_CAR_DIVIDER_HS200 = 3, // (2.5 * 2) - 2 (for PLLP_OUT0)
|
SDMMC_CAR_DIVIDER_MMC_HS200 = 3, /* (2.5 * 2) - 2 (for PLLP_OUT0, same as HS400) */
|
||||||
SDMMC_CAR_DIVIDER_HS400 = 3, // (2.5 * 2) - 2 (for PLLP_OUT0)
|
|
||||||
} SdmmcCarDivider;
|
} SdmmcCarDivider;
|
||||||
|
|
||||||
/* Structure for describing a SDMMC device. */
|
/* Structure for describing a SDMMC device. */
|
||||||
|
@ -272,7 +272,7 @@ typedef struct {
|
||||||
uint32_t opcode;
|
uint32_t opcode;
|
||||||
uint32_t arg;
|
uint32_t arg;
|
||||||
uint32_t resp[4];
|
uint32_t resp[4];
|
||||||
uint32_t flags; /* expected response type */
|
uint32_t flags; /* Expected response type. */
|
||||||
} sdmmc_command_t;
|
} sdmmc_command_t;
|
||||||
|
|
||||||
/* Structure for describing a SDMMC request. */
|
/* Structure for describing a SDMMC request. */
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#define FUSEE_FS_UTILS_H
|
#define FUSEE_FS_UTILS_H
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "sdmmc/sdmmc.h"
|
|
||||||
|
|
||||||
size_t get_file_size(const char *filename);
|
size_t get_file_size(const char *filename);
|
||||||
size_t read_from_file(void *dst, size_t dst_size, const char *filename);
|
size_t read_from_file(void *dst, size_t dst_size, const char *filename);
|
||||||
|
|
|
@ -82,7 +82,7 @@ static int mmc_partition_initialize(device_partition_t *devpart) {
|
||||||
/* Initialize hardware. */
|
/* Initialize hardware. */
|
||||||
if (mmcpart->device == &g_sd_device) {
|
if (mmcpart->device == &g_sd_device) {
|
||||||
if (!g_sd_device_initialized) {
|
if (!g_sd_device_initialized) {
|
||||||
int rc = sdmmc_device_sd_init(mmcpart->device, &g_sd_sdmmc, SDMMC_BUS_WIDTH_4BIT, SDMMC_SPEED_SDR104) ? 0 : EIO;
|
int rc = sdmmc_device_sd_init(mmcpart->device, &g_sd_sdmmc, SDMMC_BUS_WIDTH_4BIT, SDMMC_SPEED_EMU_SDR104) ? 0 : EIO;
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
g_sd_device_initialized = true;
|
g_sd_device_initialized = true;
|
||||||
|
@ -91,7 +91,7 @@ static int mmc_partition_initialize(device_partition_t *devpart) {
|
||||||
return 0;
|
return 0;
|
||||||
} else if (mmcpart->device == &g_emmc_device) {
|
} else if (mmcpart->device == &g_emmc_device) {
|
||||||
if (!g_emmc_device_initialized) {
|
if (!g_emmc_device_initialized) {
|
||||||
int rc = sdmmc_device_mmc_init(mmcpart->device, &g_emmc_sdmmc, SDMMC_BUS_WIDTH_8BIT, SDMMC_SPEED_HS400) ? 0 : EIO;
|
int rc = sdmmc_device_mmc_init(mmcpart->device, &g_emmc_sdmmc, SDMMC_BUS_WIDTH_8BIT, SDMMC_SPEED_MMC_HS400) ? 0 : EIO;
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
g_emmc_device_initialized = true;
|
g_emmc_device_initialized = true;
|
||||||
|
|
|
@ -494,7 +494,7 @@ static int sdmmc_sd_send_op_cond(sdmmc_device_t *device, bool is_sd_ver2, bool i
|
||||||
device->is_block_sdhc = true;
|
device->is_block_sdhc = true;
|
||||||
|
|
||||||
/* We asked for low voltage support and the card accepted. */
|
/* We asked for low voltage support and the card accepted. */
|
||||||
if (false && is_uhs_en && (resp & SD_ROCR_S18A))
|
if (is_uhs_en && (resp & SD_ROCR_S18A))
|
||||||
{
|
{
|
||||||
/* Voltage switching is only valid for SDMMC1. */
|
/* Voltage switching is only valid for SDMMC1. */
|
||||||
if (device->sdmmc->controller == SDMMC_1)
|
if (device->sdmmc->controller == SDMMC_1)
|
||||||
|
@ -727,11 +727,11 @@ static int sdmmc_sd_switch_hs_low(sdmmc_device_t *device, uint8_t *status)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_SDR104))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_UHS_SDR104))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Run tuning. */
|
/* Run tuning. */
|
||||||
if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_SDR104, MMC_SEND_TUNING_BLOCK))
|
if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_UHS_SDR104, MMC_SEND_TUNING_BLOCK))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (status[13] & SD_MODE_UHS_SDR50) /* High-speed SDR50 is supported. */
|
else if (status[13] & SD_MODE_UHS_SDR50) /* High-speed SDR50 is supported. */
|
||||||
|
@ -741,11 +741,11 @@ static int sdmmc_sd_switch_hs_low(sdmmc_device_t *device, uint8_t *status)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_SDR50))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_UHS_SDR50))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Run tuning. */
|
/* Run tuning. */
|
||||||
if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_SDR50, MMC_SEND_TUNING_BLOCK))
|
if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_UHS_SDR50, MMC_SEND_TUNING_BLOCK))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (status[13] & SD_MODE_UHS_SDR12) /* High-speed SDR12 is supported. */
|
else if (status[13] & SD_MODE_UHS_SDR12) /* High-speed SDR12 is supported. */
|
||||||
|
@ -755,11 +755,11 @@ static int sdmmc_sd_switch_hs_low(sdmmc_device_t *device, uint8_t *status)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_SDR12))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_UHS_SDR12))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Run tuning. */
|
/* Run tuning. */
|
||||||
if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_SDR12, MMC_SEND_TUNING_BLOCK))
|
if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_UHS_SDR12, MMC_SEND_TUNING_BLOCK))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -784,7 +784,7 @@ static int sdmmc_sd_switch_hs_high(sdmmc_device_t *device, uint8_t *status)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_SDR25))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_UHS_SDR25))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Peek the SD card's status. */
|
/* Peek the SD card's status. */
|
||||||
|
@ -841,7 +841,7 @@ int sdmmc_device_sd_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth b
|
||||||
memset(device, 0, sizeof(sdmmc_device_t));
|
memset(device, 0, sizeof(sdmmc_device_t));
|
||||||
|
|
||||||
/* Try to initialize the driver. */
|
/* Try to initialize the driver. */
|
||||||
if (!sdmmc_init(sdmmc, SDMMC_1, SDMMC_VOLTAGE_3V3, SDMMC_BUS_WIDTH_1BIT, SDMMC_SPEED_INIT_SDR))
|
if (!sdmmc_init(sdmmc, SDMMC_1, SDMMC_VOLTAGE_3V3, SDMMC_BUS_WIDTH_1BIT, SDMMC_SPEED_SD_INIT))
|
||||||
{
|
{
|
||||||
sdmmc_error(sdmmc, "Failed to initialize the SDMMC driver!");
|
sdmmc_error(sdmmc, "Failed to initialize the SDMMC driver!");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -874,7 +874,7 @@ int sdmmc_device_sd_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth b
|
||||||
sdmmc_info(sdmmc, "Sent if cond to SD card!");
|
sdmmc_info(sdmmc, "Sent if cond to SD card!");
|
||||||
|
|
||||||
/* Get the SD card's operating conditions. */
|
/* Get the SD card's operating conditions. */
|
||||||
if (!sdmmc_sd_send_op_cond(device, is_sd_ver2, (bus_width == SDMMC_BUS_WIDTH_4BIT) && (bus_speed == SDMMC_SPEED_SDR104)))
|
if (!sdmmc_sd_send_op_cond(device, is_sd_ver2, (bus_width == SDMMC_BUS_WIDTH_4BIT) && (bus_speed == SDMMC_SPEED_UHS_SDR104)))
|
||||||
{
|
{
|
||||||
sdmmc_error(sdmmc, "Failed to send op cond!");
|
sdmmc_error(sdmmc, "Failed to send op cond!");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -920,7 +920,7 @@ int sdmmc_device_sd_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth b
|
||||||
if (!device->is_180v)
|
if (!device->is_180v)
|
||||||
{
|
{
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_UNK6))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_SD_LEGACY))
|
||||||
{
|
{
|
||||||
sdmmc_error(sdmmc, "Failed to apply the correct bus speed!");
|
sdmmc_error(sdmmc, "Failed to apply the correct bus speed!");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -998,7 +998,7 @@ int sdmmc_device_sd_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth b
|
||||||
|
|
||||||
sdmmc_info(sdmmc, "Switched to high-speed from low voltage!");
|
sdmmc_info(sdmmc, "Switched to high-speed from low voltage!");
|
||||||
}
|
}
|
||||||
else if ((device->scr.sda_vsn & (SD_SCR_SPEC_VER_1 | SD_SCR_SPEC_VER_2)) && ((bus_speed != SDMMC_SPEED_UNK6)))
|
else if ((device->scr.sda_vsn & (SD_SCR_SPEC_VER_1 | SD_SCR_SPEC_VER_2)) && ((bus_speed != SDMMC_SPEED_SD_LEGACY)))
|
||||||
{
|
{
|
||||||
/* Switch to high-speed from high voltage (if possible). */
|
/* Switch to high-speed from high voltage (if possible). */
|
||||||
if (!sdmmc_sd_switch_hs_high(device, switch_status))
|
if (!sdmmc_sd_switch_hs_high(device, switch_status))
|
||||||
|
@ -1273,7 +1273,7 @@ static int sdmmc_mmc_select_hs(sdmmc_device_t *device, bool ignore_status)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_HS52))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_MMC_HS))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Check the status if necessary. */
|
/* Check the status if necessary. */
|
||||||
|
@ -1292,11 +1292,11 @@ static int sdmmc_mmc_select_hs200(sdmmc_device_t *device)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_HS200))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_MMC_HS200))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Execute tuning procedure. */
|
/* Execute tuning procedure. */
|
||||||
if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_HS200, MMC_SEND_TUNING_BLOCK_HS200))
|
if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_MMC_HS200, MMC_SEND_TUNING_BLOCK_HS200))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Peek the current status. */
|
/* Peek the current status. */
|
||||||
|
@ -1331,7 +1331,7 @@ static int sdmmc_mmc_select_hs400(sdmmc_device_t *device)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_HS400))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_MMC_HS400))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Peek the current status. */
|
/* Peek the current status. */
|
||||||
|
@ -1340,14 +1340,14 @@ static int sdmmc_mmc_select_hs400(sdmmc_device_t *device)
|
||||||
|
|
||||||
static int sdmmc_mmc_select_timing(sdmmc_device_t *device, SdmmcBusSpeed bus_speed)
|
static int sdmmc_mmc_select_timing(sdmmc_device_t *device, SdmmcBusSpeed bus_speed)
|
||||||
{
|
{
|
||||||
if ((bus_speed == SDMMC_SPEED_HS400) &&
|
if ((bus_speed == SDMMC_SPEED_MMC_HS400) &&
|
||||||
(device->sdmmc->bus_width == SDMMC_BUS_WIDTH_8BIT) &&
|
(device->sdmmc->bus_width == SDMMC_BUS_WIDTH_8BIT) &&
|
||||||
(device->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_HS400_1_8V))
|
(device->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_HS400_1_8V))
|
||||||
{
|
{
|
||||||
/* Switch to HS400. */
|
/* Switch to HS400. */
|
||||||
return sdmmc_mmc_select_hs400(device);
|
return sdmmc_mmc_select_hs400(device);
|
||||||
}
|
}
|
||||||
else if (((bus_speed == SDMMC_SPEED_HS400) || (bus_speed == SDMMC_SPEED_HS200)) &&
|
else if (((bus_speed == SDMMC_SPEED_MMC_HS400) || (bus_speed == SDMMC_SPEED_MMC_HS200)) &&
|
||||||
((device->sdmmc->bus_width == SDMMC_BUS_WIDTH_8BIT) || (device->sdmmc->bus_width == SDMMC_BUS_WIDTH_4BIT)) &&
|
((device->sdmmc->bus_width == SDMMC_BUS_WIDTH_8BIT) || (device->sdmmc->bus_width == SDMMC_BUS_WIDTH_4BIT)) &&
|
||||||
(device->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_HS200_1_8V))
|
(device->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_HS200_1_8V))
|
||||||
{
|
{
|
||||||
|
@ -1397,7 +1397,7 @@ int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth
|
||||||
memset(device, 0, sizeof(sdmmc_device_t));
|
memset(device, 0, sizeof(sdmmc_device_t));
|
||||||
|
|
||||||
/* Try to initialize the driver. */
|
/* Try to initialize the driver. */
|
||||||
if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_VOLTAGE_1V8, SDMMC_BUS_WIDTH_1BIT, SDMMC_SPEED_INIT_HS))
|
if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_VOLTAGE_1V8, SDMMC_BUS_WIDTH_1BIT, SDMMC_SPEED_MMC_INIT))
|
||||||
{
|
{
|
||||||
sdmmc_error(sdmmc, "Failed to initialize the SDMMC driver!");
|
sdmmc_error(sdmmc, "Failed to initialize the SDMMC driver!");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1464,7 +1464,7 @@ int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth
|
||||||
sdmmc_warn(sdmmc, "Got unknown CSD structure (0x%08x)!", device->csd.structure);
|
sdmmc_warn(sdmmc, "Got unknown CSD structure (0x%08x)!", device->csd.structure);
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_HS26))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_MMC_LEGACY))
|
||||||
{
|
{
|
||||||
sdmmc_error(sdmmc, "Failed to apply the correct bus speed!");
|
sdmmc_error(sdmmc, "Failed to apply the correct bus speed!");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -289,26 +289,28 @@ static int sdmmc_get_sdclk_freq(SdmmcBusSpeed bus_speed)
|
||||||
{
|
{
|
||||||
switch (bus_speed)
|
switch (bus_speed)
|
||||||
{
|
{
|
||||||
case SDMMC_SPEED_INIT_HS:
|
case SDMMC_SPEED_MMC_INIT:
|
||||||
case SDMMC_SPEED_HS26:
|
case SDMMC_SPEED_MMC_LEGACY:
|
||||||
return 26000;
|
return 26000;
|
||||||
case SDMMC_SPEED_HS52:
|
case SDMMC_SPEED_MMC_HS:
|
||||||
return 52000;
|
return 52000;
|
||||||
case SDMMC_SPEED_HS200:
|
case SDMMC_SPEED_MMC_HS200:
|
||||||
case SDMMC_SPEED_HS400:
|
case SDMMC_SPEED_MMC_HS400:
|
||||||
case SDMMC_SPEED_SDR104:
|
case SDMMC_SPEED_UHS_SDR104:
|
||||||
|
case SDMMC_SPEED_EMU_SDR104:
|
||||||
return 200000;
|
return 200000;
|
||||||
case SDMMC_SPEED_INIT_SDR:
|
case SDMMC_SPEED_SD_INIT:
|
||||||
case SDMMC_SPEED_UNK6:
|
case SDMMC_SPEED_SD_LEGACY:
|
||||||
case SDMMC_SPEED_SDR12:
|
case SDMMC_SPEED_UHS_SDR12:
|
||||||
return 25000;
|
return 25000;
|
||||||
case SDMMC_SPEED_SDR25:
|
case SDMMC_SPEED_SD_HS:
|
||||||
|
case SDMMC_SPEED_UHS_SDR25:
|
||||||
return 50000;
|
return 50000;
|
||||||
case SDMMC_SPEED_SDR50:
|
case SDMMC_SPEED_UHS_SDR50:
|
||||||
return 100000;
|
return 100000;
|
||||||
case SDMMC_SPEED_DDR50:
|
case SDMMC_SPEED_UHS_DDR50:
|
||||||
return 40800;
|
return 40800;
|
||||||
case SDMMC_SPEED_UNK14:
|
case SDMMC_SPEED_MMC_DDR52:
|
||||||
return 200000;
|
return 200000;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -320,22 +322,23 @@ static int sdmmc_get_sdclk_div(SdmmcBusSpeed bus_speed)
|
||||||
{
|
{
|
||||||
switch (bus_speed)
|
switch (bus_speed)
|
||||||
{
|
{
|
||||||
case SDMMC_SPEED_INIT_HS:
|
case SDMMC_SPEED_MMC_INIT:
|
||||||
return 66;
|
return 66;
|
||||||
case SDMMC_SPEED_INIT_SDR:
|
case SDMMC_SPEED_SD_INIT:
|
||||||
// TODO: TRM says return 64?
|
case SDMMC_SPEED_MMC_LEGACY:
|
||||||
case SDMMC_SPEED_HS26:
|
case SDMMC_SPEED_MMC_HS:
|
||||||
case SDMMC_SPEED_HS52:
|
case SDMMC_SPEED_MMC_HS200:
|
||||||
case SDMMC_SPEED_HS200:
|
case SDMMC_SPEED_MMC_HS400:
|
||||||
case SDMMC_SPEED_HS400:
|
case SDMMC_SPEED_SD_LEGACY:
|
||||||
case SDMMC_SPEED_UNK6:
|
case SDMMC_SPEED_SD_HS:
|
||||||
case SDMMC_SPEED_SDR25:
|
case SDMMC_SPEED_UHS_SDR12:
|
||||||
case SDMMC_SPEED_SDR12:
|
case SDMMC_SPEED_UHS_SDR25:
|
||||||
case SDMMC_SPEED_SDR50:
|
case SDMMC_SPEED_UHS_SDR50:
|
||||||
case SDMMC_SPEED_SDR104:
|
case SDMMC_SPEED_UHS_SDR104:
|
||||||
case SDMMC_SPEED_DDR50:
|
case SDMMC_SPEED_UHS_DDR50:
|
||||||
|
case SDMMC_SPEED_EMU_SDR104:
|
||||||
return 1;
|
return 1;
|
||||||
case SDMMC_SPEED_UNK14:
|
case SDMMC_SPEED_MMC_DDR52:
|
||||||
return 2;
|
return 2;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -354,35 +357,35 @@ static int sdmmc_clk_set_source(SdmmcControllerNum controller, uint32_t clk_freq
|
||||||
{
|
{
|
||||||
case 25000:
|
case 25000:
|
||||||
out_freq = 24728;
|
out_freq = 24728;
|
||||||
car_div = SDMMC_CAR_DIVIDER_SDR12;
|
car_div = SDMMC_CAR_DIVIDER_UHS_SDR12;
|
||||||
break;
|
break;
|
||||||
case 26000:
|
case 26000:
|
||||||
out_freq = 25500;
|
out_freq = 25500;
|
||||||
car_div = SDMMC_CAR_DIVIDER_HS26;
|
car_div = SDMMC_CAR_DIVIDER_MMC_LEGACY;
|
||||||
break;
|
break;
|
||||||
case 40800:
|
case 40800:
|
||||||
out_freq = 40800;
|
out_freq = 40800;
|
||||||
car_div = SDMMC_CAR_DIVIDER_DDR50;
|
car_div = SDMMC_CAR_DIVIDER_UHS_DDR50;
|
||||||
break;
|
break;
|
||||||
case 50000:
|
case 50000:
|
||||||
out_freq = 48000;
|
out_freq = 48000;
|
||||||
car_div = SDMMC_CAR_DIVIDER_SDR25;
|
car_div = SDMMC_CAR_DIVIDER_UHS_SDR25;
|
||||||
break;
|
break;
|
||||||
case 52000:
|
case 52000:
|
||||||
out_freq = 51000;
|
out_freq = 51000;
|
||||||
car_div = SDMMC_CAR_DIVIDER_HS52;
|
car_div = SDMMC_CAR_DIVIDER_MMC_HS;
|
||||||
break;
|
break;
|
||||||
case 100000:
|
case 100000:
|
||||||
out_freq = 90667;
|
out_freq = 90667;
|
||||||
car_div = SDMMC_CAR_DIVIDER_SDR50;
|
car_div = SDMMC_CAR_DIVIDER_UHS_SDR50;
|
||||||
break;
|
break;
|
||||||
case 200000:
|
case 200000:
|
||||||
out_freq = 163200;
|
out_freq = 163200;
|
||||||
car_div = SDMMC_CAR_DIVIDER_HS200;
|
car_div = SDMMC_CAR_DIVIDER_MMC_HS200;
|
||||||
break;
|
break;
|
||||||
case 208000:
|
case 208000:
|
||||||
out_freq = 204000;
|
out_freq = 204000;
|
||||||
car_div = SDMMC_CAR_DIVIDER_SDR104;
|
car_div = SDMMC_CAR_DIVIDER_UHS_SDR104;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -747,7 +750,7 @@ void sdmmc_select_voltage(sdmmc_t *sdmmc, SdmmcBusVoltage voltage)
|
||||||
|
|
||||||
static void sdmmc_tap_config(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed)
|
static void sdmmc_tap_config(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed)
|
||||||
{
|
{
|
||||||
if (bus_speed == SDMMC_SPEED_HS400)
|
if (bus_speed == SDMMC_SPEED_MMC_HS400)
|
||||||
{
|
{
|
||||||
/* Clear and set DQS_TRIM_VAL (used in HS400) */
|
/* Clear and set DQS_TRIM_VAL (used in HS400) */
|
||||||
sdmmc->regs->vendor_cap_overrides &= ~(0x3F00);
|
sdmmc->regs->vendor_cap_overrides &= ~(0x3F00);
|
||||||
|
@ -757,7 +760,7 @@ static void sdmmc_tap_config(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed)
|
||||||
/* Clear TAP_VAL_UPDATED_BY_HW */
|
/* Clear TAP_VAL_UPDATED_BY_HW */
|
||||||
sdmmc->regs->vendor_tuning_cntrl0 &= ~(0x20000);
|
sdmmc->regs->vendor_tuning_cntrl0 &= ~(0x20000);
|
||||||
|
|
||||||
if (bus_speed == SDMMC_SPEED_HS400)
|
if (bus_speed == SDMMC_SPEED_MMC_HS400)
|
||||||
{
|
{
|
||||||
/* We must have obtained the tap value from the tuning procedure here. */
|
/* We must have obtained the tap value from the tuning procedure here. */
|
||||||
if (sdmmc->is_tuning_tap_val_set)
|
if (sdmmc->is_tuning_tap_val_set)
|
||||||
|
@ -863,41 +866,43 @@ int sdmmc_select_speed(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed)
|
||||||
/* Set the appropriate host speed. */
|
/* Set the appropriate host speed. */
|
||||||
switch (bus_speed) {
|
switch (bus_speed) {
|
||||||
/* 400kHz initialization mode and a few others. */
|
/* 400kHz initialization mode and a few others. */
|
||||||
case SDMMC_SPEED_INIT_HS:
|
case SDMMC_SPEED_MMC_INIT:
|
||||||
case SDMMC_SPEED_HS26:
|
case SDMMC_SPEED_MMC_LEGACY:
|
||||||
case SDMMC_SPEED_INIT_SDR:
|
case SDMMC_SPEED_SD_INIT:
|
||||||
case SDMMC_SPEED_UNK6:
|
case SDMMC_SPEED_SD_LEGACY:
|
||||||
sdmmc->regs->host_control &= ~(SDHCI_CTRL_HISPD);
|
sdmmc->regs->host_control &= ~(SDHCI_CTRL_HISPD);
|
||||||
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_VDD_180);
|
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_VDD_180);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* 50MHz high speed (SD) and 52MHz high speed (MMC). */
|
/* 50MHz high speed (SD) and 52MHz high speed (MMC). */
|
||||||
case SDMMC_SPEED_SDR25:
|
case SDMMC_SPEED_SD_HS:
|
||||||
case SDMMC_SPEED_HS52:
|
case SDMMC_SPEED_MMC_HS:
|
||||||
|
case SDMMC_SPEED_UHS_SDR25:
|
||||||
sdmmc->regs->host_control |= SDHCI_CTRL_HISPD;
|
sdmmc->regs->host_control |= SDHCI_CTRL_HISPD;
|
||||||
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_VDD_180);
|
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_VDD_180);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* 200MHz UHS-I (SD) and other modes due to errata. */
|
/* 200MHz UHS-I (SD) and other modes due to errata. */
|
||||||
case SDMMC_SPEED_HS200:
|
case SDMMC_SPEED_MMC_HS200:
|
||||||
case SDMMC_SPEED_SDR104:
|
case SDMMC_SPEED_UHS_SDR104:
|
||||||
case SDMMC_SPEED_DDR50:
|
case SDMMC_SPEED_UHS_DDR50:
|
||||||
case SDMMC_SPEED_SDR50:
|
case SDMMC_SPEED_UHS_SDR50:
|
||||||
case SDMMC_SPEED_UNK14:
|
case SDMMC_SPEED_MMC_DDR52:
|
||||||
|
case SDMMC_SPEED_EMU_SDR104:
|
||||||
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK);
|
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK);
|
||||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_UHS_SDR104;
|
sdmmc->regs->host_control2 |= SDHCI_CTRL_UHS_SDR104;
|
||||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180;
|
sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* 200MHz single-data rate (MMC). */
|
/* 200MHz single-data rate (MMC). */
|
||||||
case SDMMC_SPEED_HS400:
|
case SDMMC_SPEED_MMC_HS400:
|
||||||
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK);
|
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK);
|
||||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_HS400;
|
sdmmc->regs->host_control2 |= SDHCI_CTRL_HS400;
|
||||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180;
|
sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* 25MHz default speed (SD). */
|
/* 25MHz default speed (SD). */
|
||||||
case SDMMC_SPEED_SDR12:
|
case SDMMC_SPEED_UHS_SDR12:
|
||||||
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK);
|
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK);
|
||||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_UHS_SDR12;
|
sdmmc->regs->host_control2 |= SDHCI_CTRL_UHS_SDR12;
|
||||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180;
|
sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180;
|
||||||
|
@ -936,7 +941,7 @@ int sdmmc_select_speed(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed)
|
||||||
sdmmc_enable_sd_clock(sdmmc);
|
sdmmc_enable_sd_clock(sdmmc);
|
||||||
|
|
||||||
/* Run DLLCAL for HS400 only */
|
/* Run DLLCAL for HS400 only */
|
||||||
if (bus_speed == SDMMC_SPEED_HS400)
|
if (bus_speed == SDMMC_SPEED_MMC_HS400)
|
||||||
return sdmmc_dllcal_run(sdmmc);
|
return sdmmc_dllcal_run(sdmmc);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1720,7 +1725,7 @@ int sdmmc_switch_voltage(sdmmc_t *sdmmc)
|
||||||
sdmmc_disable_sd_clock(sdmmc);
|
sdmmc_disable_sd_clock(sdmmc);
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(sdmmc, SDMMC_SPEED_SDR12))
|
if (!sdmmc_select_speed(sdmmc, SDMMC_SPEED_UHS_SDR12))
|
||||||
{
|
{
|
||||||
sdmmc_error(sdmmc, "Failed to apply the correct bus speed for low voltage support!");
|
sdmmc_error(sdmmc, "Failed to apply the correct bus speed for low voltage support!");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1883,15 +1888,16 @@ int sdmmc_execute_tuning(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed, uint32_t opcod
|
||||||
|
|
||||||
switch (bus_speed)
|
switch (bus_speed)
|
||||||
{
|
{
|
||||||
case SDMMC_SPEED_HS200:
|
case SDMMC_SPEED_MMC_HS200:
|
||||||
case SDMMC_SPEED_HS400:
|
case SDMMC_SPEED_MMC_HS400:
|
||||||
case SDMMC_SPEED_SDR104:
|
case SDMMC_SPEED_UHS_SDR104:
|
||||||
|
case SDMMC_SPEED_EMU_SDR104:
|
||||||
max_tuning_loop = 0x80;
|
max_tuning_loop = 0x80;
|
||||||
tuning_cntrl_flag = 0x4000;
|
tuning_cntrl_flag = 0x4000;
|
||||||
break;
|
break;
|
||||||
case SDMMC_SPEED_SDR50:
|
case SDMMC_SPEED_UHS_SDR50:
|
||||||
case SDMMC_SPEED_DDR50:
|
case SDMMC_SPEED_UHS_DDR50:
|
||||||
case SDMMC_SPEED_UNK14:
|
case SDMMC_SPEED_MMC_DDR52:
|
||||||
max_tuning_loop = 0x100;
|
max_tuning_loop = 0x100;
|
||||||
tuning_cntrl_flag = 0x8000;
|
tuning_cntrl_flag = 0x8000;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -210,33 +210,33 @@ typedef enum {
|
||||||
} SdmmcBusWidth;
|
} SdmmcBusWidth;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SDMMC_SPEED_INIT_HS = 0,
|
SDMMC_SPEED_MMC_INIT = 0,
|
||||||
SDMMC_SPEED_HS26 = 1,
|
SDMMC_SPEED_MMC_LEGACY = 1,
|
||||||
SDMMC_SPEED_HS52 = 2,
|
SDMMC_SPEED_MMC_HS = 2,
|
||||||
SDMMC_SPEED_HS200 = 3,
|
SDMMC_SPEED_MMC_HS200 = 3,
|
||||||
SDMMC_SPEED_HS400 = 4,
|
SDMMC_SPEED_MMC_HS400 = 4,
|
||||||
SDMMC_SPEED_INIT_SDR = 5,
|
SDMMC_SPEED_SD_INIT = 5,
|
||||||
SDMMC_SPEED_UNK6 = 6,
|
SDMMC_SPEED_SD_LEGACY = 6,
|
||||||
SDMMC_SPEED_SDR25 = 7,
|
SDMMC_SPEED_SD_HS = 7,
|
||||||
SDMMC_SPEED_SDR12 = 8,
|
SDMMC_SPEED_UHS_SDR12 = 8,
|
||||||
SDMMC_SPEED_UNK9 = 9,
|
SDMMC_SPEED_UHS_SDR25 = 9,
|
||||||
SDMMC_SPEED_SDR50 = 10,
|
SDMMC_SPEED_UHS_SDR50 = 10,
|
||||||
SDMMC_SPEED_SDR104 = 11,
|
SDMMC_SPEED_UHS_SDR104 = 11,
|
||||||
SDMMC_SPEED_UNK12 = 12,
|
SDMMC_SPEED_UHS_RESERVED = 12,
|
||||||
SDMMC_SPEED_DDR50 = 13,
|
SDMMC_SPEED_UHS_DDR50 = 13,
|
||||||
SDMMC_SPEED_UNK14 = 14,
|
SDMMC_SPEED_MMC_DDR52 = 14,
|
||||||
|
SDMMC_SPEED_EMU_SDR104 = 255, /* Custom speed mode. Prevents low voltage switch in MMC emulation. */
|
||||||
} SdmmcBusSpeed;
|
} SdmmcBusSpeed;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SDMMC_CAR_DIVIDER_SDR12 = 31, // (16.5 * 2) - 2
|
SDMMC_CAR_DIVIDER_UHS_SDR12 = 31, /* (16.5 * 2) - 2 */
|
||||||
SDMMC_CAR_DIVIDER_SDR25 = 15, // (8.5 * 2) - 2
|
SDMMC_CAR_DIVIDER_UHS_SDR25 = 15, /* (8.5 * 2) - 2 */
|
||||||
SDMMC_CAR_DIVIDER_SDR50 = 7, // (4.5 * 2) - 2
|
SDMMC_CAR_DIVIDER_UHS_SDR50 = 7, /* (4.5 * 2) - 2 */
|
||||||
SDMMC_CAR_DIVIDER_SDR104 = 2, // (2 * 2) - 2
|
SDMMC_CAR_DIVIDER_UHS_SDR104 = 2, /* (2 * 2) - 2 */
|
||||||
SDMMC_CAR_DIVIDER_DDR50 = 18, // (5 * 2 * 2) - 2
|
SDMMC_CAR_DIVIDER_UHS_DDR50 = 18, /* (5 * 2 * 2) - 2 */
|
||||||
SDMMC_CAR_DIVIDER_HS26 = 30, // (16 * 2) - 2
|
SDMMC_CAR_DIVIDER_MMC_LEGACY = 30, /* (16 * 2) - 2 */
|
||||||
SDMMC_CAR_DIVIDER_HS52 = 14, // (8 * 2) - 2
|
SDMMC_CAR_DIVIDER_MMC_HS = 14, /* (8 * 2) - 2 */
|
||||||
SDMMC_CAR_DIVIDER_HS200 = 3, // (2.5 * 2) - 2 (for PLLP_OUT0)
|
SDMMC_CAR_DIVIDER_MMC_HS200 = 3, /* (2.5 * 2) - 2 (for PLLP_OUT0, same as HS400) */
|
||||||
SDMMC_CAR_DIVIDER_HS400 = 3, // (2.5 * 2) - 2 (for PLLP_OUT0)
|
|
||||||
} SdmmcCarDivider;
|
} SdmmcCarDivider;
|
||||||
|
|
||||||
/* Structure for describing a SDMMC device. */
|
/* Structure for describing a SDMMC device. */
|
||||||
|
@ -272,7 +272,7 @@ typedef struct {
|
||||||
uint32_t opcode;
|
uint32_t opcode;
|
||||||
uint32_t arg;
|
uint32_t arg;
|
||||||
uint32_t resp[4];
|
uint32_t resp[4];
|
||||||
uint32_t flags; /* expected response type */
|
uint32_t flags; /* Expected response type. */
|
||||||
} sdmmc_command_t;
|
} sdmmc_command_t;
|
||||||
|
|
||||||
/* Structure for describing a SDMMC request. */
|
/* Structure for describing a SDMMC request. */
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#define FUSEE_STAGE2_H
|
#define FUSEE_STAGE2_H
|
||||||
|
|
||||||
#include "lib/log.h"
|
#include "lib/log.h"
|
||||||
#include "sdmmc/sdmmc.h"
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
/* TODO: Is there a more concise way to do this? */
|
/* TODO: Is there a more concise way to do this? */
|
||||||
|
|
|
@ -210,7 +210,7 @@ static kip1_header_t *inject_emummc_kip(kip1_header_t *fs_kip, kip1_header_t *em
|
||||||
/* Add extra cap for 1.0.0 */
|
/* Add extra cap for 1.0.0 */
|
||||||
if (stratosphere_get_fs_version() == FS_VER_1_0_0) {
|
if (stratosphere_get_fs_version() == FS_VER_1_0_0) {
|
||||||
for (size_t i = 0; i < 0x20; i++) {
|
for (size_t i = 0; i < 0x20; i++) {
|
||||||
if (injected_kip->capabilities[i] = 0xFFFFFFFF) {
|
if (injected_kip->capabilities[i] == 0xFFFFFFFF) {
|
||||||
/* Map PMC registers in. */
|
/* Map PMC registers in. */
|
||||||
injected_kip->capabilities[i] = 0x07000E7F;
|
injected_kip->capabilities[i] = 0x07000E7F;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -38,7 +38,7 @@ bool mount_sd(void)
|
||||||
|
|
||||||
if (!g_sd_initialized) {
|
if (!g_sd_initialized) {
|
||||||
/* Initialize SD. */
|
/* Initialize SD. */
|
||||||
if (sdmmc_device_sd_init(&g_sd_device, &g_sd_sdmmc, SDMMC_BUS_WIDTH_4BIT, SDMMC_SPEED_SDR104))
|
if (sdmmc_device_sd_init(&g_sd_device, &g_sd_sdmmc, SDMMC_BUS_WIDTH_4BIT, SDMMC_SPEED_UHS_SDR104))
|
||||||
{
|
{
|
||||||
g_sd_initialized = true;
|
g_sd_initialized = true;
|
||||||
|
|
||||||
|
|
|
@ -727,11 +727,11 @@ static int sdmmc_sd_switch_hs_low(sdmmc_device_t *device, uint8_t *status)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_SDR104))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_UHS_SDR104))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Run tuning. */
|
/* Run tuning. */
|
||||||
if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_SDR104, MMC_SEND_TUNING_BLOCK))
|
if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_UHS_SDR104, MMC_SEND_TUNING_BLOCK))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (status[13] & SD_MODE_UHS_SDR50) /* High-speed SDR50 is supported. */
|
else if (status[13] & SD_MODE_UHS_SDR50) /* High-speed SDR50 is supported. */
|
||||||
|
@ -741,11 +741,11 @@ static int sdmmc_sd_switch_hs_low(sdmmc_device_t *device, uint8_t *status)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_SDR50))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_UHS_SDR50))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Run tuning. */
|
/* Run tuning. */
|
||||||
if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_SDR50, MMC_SEND_TUNING_BLOCK))
|
if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_UHS_SDR50, MMC_SEND_TUNING_BLOCK))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (status[13] & SD_MODE_UHS_SDR12) /* High-speed SDR12 is supported. */
|
else if (status[13] & SD_MODE_UHS_SDR12) /* High-speed SDR12 is supported. */
|
||||||
|
@ -755,11 +755,11 @@ static int sdmmc_sd_switch_hs_low(sdmmc_device_t *device, uint8_t *status)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_SDR12))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_UHS_SDR12))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Run tuning. */
|
/* Run tuning. */
|
||||||
if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_SDR12, MMC_SEND_TUNING_BLOCK))
|
if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_UHS_SDR12, MMC_SEND_TUNING_BLOCK))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -784,7 +784,7 @@ static int sdmmc_sd_switch_hs_high(sdmmc_device_t *device, uint8_t *status)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_SDR25))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_UHS_SDR25))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Peek the SD card's status. */
|
/* Peek the SD card's status. */
|
||||||
|
@ -841,7 +841,7 @@ int sdmmc_device_sd_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth b
|
||||||
memset(device, 0, sizeof(sdmmc_device_t));
|
memset(device, 0, sizeof(sdmmc_device_t));
|
||||||
|
|
||||||
/* Try to initialize the driver. */
|
/* Try to initialize the driver. */
|
||||||
if (!sdmmc_init(sdmmc, SDMMC_1, SDMMC_VOLTAGE_3V3, SDMMC_BUS_WIDTH_1BIT, SDMMC_SPEED_INIT_SDR))
|
if (!sdmmc_init(sdmmc, SDMMC_1, SDMMC_VOLTAGE_3V3, SDMMC_BUS_WIDTH_1BIT, SDMMC_SPEED_SD_INIT))
|
||||||
{
|
{
|
||||||
sdmmc_error(sdmmc, "Failed to initialize the SDMMC driver!");
|
sdmmc_error(sdmmc, "Failed to initialize the SDMMC driver!");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -874,7 +874,7 @@ int sdmmc_device_sd_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth b
|
||||||
sdmmc_info(sdmmc, "Sent if cond to SD card!");
|
sdmmc_info(sdmmc, "Sent if cond to SD card!");
|
||||||
|
|
||||||
/* Get the SD card's operating conditions. */
|
/* Get the SD card's operating conditions. */
|
||||||
if (!sdmmc_sd_send_op_cond(device, is_sd_ver2, (bus_width == SDMMC_BUS_WIDTH_4BIT) && (bus_speed == SDMMC_SPEED_SDR104)))
|
if (!sdmmc_sd_send_op_cond(device, is_sd_ver2, (bus_width == SDMMC_BUS_WIDTH_4BIT) && (bus_speed == SDMMC_SPEED_UHS_SDR104)))
|
||||||
{
|
{
|
||||||
sdmmc_error(sdmmc, "Failed to send op cond!");
|
sdmmc_error(sdmmc, "Failed to send op cond!");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -920,7 +920,7 @@ int sdmmc_device_sd_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth b
|
||||||
if (!device->is_180v)
|
if (!device->is_180v)
|
||||||
{
|
{
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_UNK6))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_SD_LEGACY))
|
||||||
{
|
{
|
||||||
sdmmc_error(sdmmc, "Failed to apply the correct bus speed!");
|
sdmmc_error(sdmmc, "Failed to apply the correct bus speed!");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -998,7 +998,7 @@ int sdmmc_device_sd_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth b
|
||||||
|
|
||||||
sdmmc_info(sdmmc, "Switched to high-speed from low voltage!");
|
sdmmc_info(sdmmc, "Switched to high-speed from low voltage!");
|
||||||
}
|
}
|
||||||
else if ((device->scr.sda_vsn & (SD_SCR_SPEC_VER_1 | SD_SCR_SPEC_VER_2)) && ((bus_speed != SDMMC_SPEED_UNK6)))
|
else if ((device->scr.sda_vsn & (SD_SCR_SPEC_VER_1 | SD_SCR_SPEC_VER_2)) && ((bus_speed != SDMMC_SPEED_SD_LEGACY)))
|
||||||
{
|
{
|
||||||
/* Switch to high-speed from high voltage (if possible). */
|
/* Switch to high-speed from high voltage (if possible). */
|
||||||
if (!sdmmc_sd_switch_hs_high(device, switch_status))
|
if (!sdmmc_sd_switch_hs_high(device, switch_status))
|
||||||
|
@ -1273,7 +1273,7 @@ static int sdmmc_mmc_select_hs(sdmmc_device_t *device, bool ignore_status)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_HS52))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_MMC_HS))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Check the status if necessary. */
|
/* Check the status if necessary. */
|
||||||
|
@ -1292,11 +1292,11 @@ static int sdmmc_mmc_select_hs200(sdmmc_device_t *device)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_HS200))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_MMC_HS200))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Execute tuning procedure. */
|
/* Execute tuning procedure. */
|
||||||
if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_HS200, MMC_SEND_TUNING_BLOCK_HS200))
|
if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_MMC_HS200, MMC_SEND_TUNING_BLOCK_HS200))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Peek the current status. */
|
/* Peek the current status. */
|
||||||
|
@ -1331,7 +1331,7 @@ static int sdmmc_mmc_select_hs400(sdmmc_device_t *device)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_HS400))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_MMC_HS400))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Peek the current status. */
|
/* Peek the current status. */
|
||||||
|
@ -1340,14 +1340,14 @@ static int sdmmc_mmc_select_hs400(sdmmc_device_t *device)
|
||||||
|
|
||||||
static int sdmmc_mmc_select_timing(sdmmc_device_t *device, SdmmcBusSpeed bus_speed)
|
static int sdmmc_mmc_select_timing(sdmmc_device_t *device, SdmmcBusSpeed bus_speed)
|
||||||
{
|
{
|
||||||
if ((bus_speed == SDMMC_SPEED_HS400) &&
|
if ((bus_speed == SDMMC_SPEED_MMC_HS400) &&
|
||||||
(device->sdmmc->bus_width == SDMMC_BUS_WIDTH_8BIT) &&
|
(device->sdmmc->bus_width == SDMMC_BUS_WIDTH_8BIT) &&
|
||||||
(device->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_HS400_1_8V))
|
(device->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_HS400_1_8V))
|
||||||
{
|
{
|
||||||
/* Switch to HS400. */
|
/* Switch to HS400. */
|
||||||
return sdmmc_mmc_select_hs400(device);
|
return sdmmc_mmc_select_hs400(device);
|
||||||
}
|
}
|
||||||
else if (((bus_speed == SDMMC_SPEED_HS400) || (bus_speed == SDMMC_SPEED_HS200)) &&
|
else if (((bus_speed == SDMMC_SPEED_MMC_HS400) || (bus_speed == SDMMC_SPEED_MMC_HS200)) &&
|
||||||
((device->sdmmc->bus_width == SDMMC_BUS_WIDTH_8BIT) || (device->sdmmc->bus_width == SDMMC_BUS_WIDTH_4BIT)) &&
|
((device->sdmmc->bus_width == SDMMC_BUS_WIDTH_8BIT) || (device->sdmmc->bus_width == SDMMC_BUS_WIDTH_4BIT)) &&
|
||||||
(device->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_HS200_1_8V))
|
(device->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_HS200_1_8V))
|
||||||
{
|
{
|
||||||
|
@ -1397,7 +1397,7 @@ int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth
|
||||||
memset(device, 0, sizeof(sdmmc_device_t));
|
memset(device, 0, sizeof(sdmmc_device_t));
|
||||||
|
|
||||||
/* Try to initialize the driver. */
|
/* Try to initialize the driver. */
|
||||||
if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_VOLTAGE_1V8, SDMMC_BUS_WIDTH_1BIT, SDMMC_SPEED_INIT_HS))
|
if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_VOLTAGE_1V8, SDMMC_BUS_WIDTH_1BIT, SDMMC_SPEED_MMC_INIT))
|
||||||
{
|
{
|
||||||
sdmmc_error(sdmmc, "Failed to initialize the SDMMC driver!");
|
sdmmc_error(sdmmc, "Failed to initialize the SDMMC driver!");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1464,7 +1464,7 @@ int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth
|
||||||
sdmmc_warn(sdmmc, "Got unknown CSD structure (0x%08x)!", device->csd.structure);
|
sdmmc_warn(sdmmc, "Got unknown CSD structure (0x%08x)!", device->csd.structure);
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_HS26))
|
if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_MMC_LEGACY))
|
||||||
{
|
{
|
||||||
sdmmc_error(sdmmc, "Failed to apply the correct bus speed!");
|
sdmmc_error(sdmmc, "Failed to apply the correct bus speed!");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -289,26 +289,28 @@ static int sdmmc_get_sdclk_freq(SdmmcBusSpeed bus_speed)
|
||||||
{
|
{
|
||||||
switch (bus_speed)
|
switch (bus_speed)
|
||||||
{
|
{
|
||||||
case SDMMC_SPEED_INIT_HS:
|
case SDMMC_SPEED_MMC_INIT:
|
||||||
case SDMMC_SPEED_HS26:
|
case SDMMC_SPEED_MMC_LEGACY:
|
||||||
return 26000;
|
return 26000;
|
||||||
case SDMMC_SPEED_HS52:
|
case SDMMC_SPEED_MMC_HS:
|
||||||
return 52000;
|
return 52000;
|
||||||
case SDMMC_SPEED_HS200:
|
case SDMMC_SPEED_MMC_HS200:
|
||||||
case SDMMC_SPEED_HS400:
|
case SDMMC_SPEED_MMC_HS400:
|
||||||
case SDMMC_SPEED_SDR104:
|
case SDMMC_SPEED_UHS_SDR104:
|
||||||
|
case SDMMC_SPEED_EMU_SDR104:
|
||||||
return 200000;
|
return 200000;
|
||||||
case SDMMC_SPEED_INIT_SDR:
|
case SDMMC_SPEED_SD_INIT:
|
||||||
case SDMMC_SPEED_UNK6:
|
case SDMMC_SPEED_SD_LEGACY:
|
||||||
case SDMMC_SPEED_SDR12:
|
case SDMMC_SPEED_UHS_SDR12:
|
||||||
return 25000;
|
return 25000;
|
||||||
case SDMMC_SPEED_SDR25:
|
case SDMMC_SPEED_SD_HS:
|
||||||
|
case SDMMC_SPEED_UHS_SDR25:
|
||||||
return 50000;
|
return 50000;
|
||||||
case SDMMC_SPEED_SDR50:
|
case SDMMC_SPEED_UHS_SDR50:
|
||||||
return 100000;
|
return 100000;
|
||||||
case SDMMC_SPEED_DDR50:
|
case SDMMC_SPEED_UHS_DDR50:
|
||||||
return 40800;
|
return 40800;
|
||||||
case SDMMC_SPEED_UNK14:
|
case SDMMC_SPEED_MMC_DDR52:
|
||||||
return 200000;
|
return 200000;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -320,22 +322,23 @@ static int sdmmc_get_sdclk_div(SdmmcBusSpeed bus_speed)
|
||||||
{
|
{
|
||||||
switch (bus_speed)
|
switch (bus_speed)
|
||||||
{
|
{
|
||||||
case SDMMC_SPEED_INIT_HS:
|
case SDMMC_SPEED_MMC_INIT:
|
||||||
return 66;
|
return 66;
|
||||||
case SDMMC_SPEED_INIT_SDR:
|
case SDMMC_SPEED_SD_INIT:
|
||||||
// TODO: TRM says return 64?
|
case SDMMC_SPEED_MMC_LEGACY:
|
||||||
case SDMMC_SPEED_HS26:
|
case SDMMC_SPEED_MMC_HS:
|
||||||
case SDMMC_SPEED_HS52:
|
case SDMMC_SPEED_MMC_HS200:
|
||||||
case SDMMC_SPEED_HS200:
|
case SDMMC_SPEED_MMC_HS400:
|
||||||
case SDMMC_SPEED_HS400:
|
case SDMMC_SPEED_SD_LEGACY:
|
||||||
case SDMMC_SPEED_UNK6:
|
case SDMMC_SPEED_SD_HS:
|
||||||
case SDMMC_SPEED_SDR25:
|
case SDMMC_SPEED_UHS_SDR12:
|
||||||
case SDMMC_SPEED_SDR12:
|
case SDMMC_SPEED_UHS_SDR25:
|
||||||
case SDMMC_SPEED_SDR50:
|
case SDMMC_SPEED_UHS_SDR50:
|
||||||
case SDMMC_SPEED_SDR104:
|
case SDMMC_SPEED_UHS_SDR104:
|
||||||
case SDMMC_SPEED_DDR50:
|
case SDMMC_SPEED_UHS_DDR50:
|
||||||
|
case SDMMC_SPEED_EMU_SDR104:
|
||||||
return 1;
|
return 1;
|
||||||
case SDMMC_SPEED_UNK14:
|
case SDMMC_SPEED_MMC_DDR52:
|
||||||
return 2;
|
return 2;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -354,35 +357,35 @@ static int sdmmc_clk_set_source(SdmmcControllerNum controller, uint32_t clk_freq
|
||||||
{
|
{
|
||||||
case 25000:
|
case 25000:
|
||||||
out_freq = 24728;
|
out_freq = 24728;
|
||||||
car_div = SDMMC_CAR_DIVIDER_SDR12;
|
car_div = SDMMC_CAR_DIVIDER_UHS_SDR12;
|
||||||
break;
|
break;
|
||||||
case 26000:
|
case 26000:
|
||||||
out_freq = 25500;
|
out_freq = 25500;
|
||||||
car_div = SDMMC_CAR_DIVIDER_HS26;
|
car_div = SDMMC_CAR_DIVIDER_MMC_LEGACY;
|
||||||
break;
|
break;
|
||||||
case 40800:
|
case 40800:
|
||||||
out_freq = 40800;
|
out_freq = 40800;
|
||||||
car_div = SDMMC_CAR_DIVIDER_DDR50;
|
car_div = SDMMC_CAR_DIVIDER_UHS_DDR50;
|
||||||
break;
|
break;
|
||||||
case 50000:
|
case 50000:
|
||||||
out_freq = 48000;
|
out_freq = 48000;
|
||||||
car_div = SDMMC_CAR_DIVIDER_SDR25;
|
car_div = SDMMC_CAR_DIVIDER_UHS_SDR25;
|
||||||
break;
|
break;
|
||||||
case 52000:
|
case 52000:
|
||||||
out_freq = 51000;
|
out_freq = 51000;
|
||||||
car_div = SDMMC_CAR_DIVIDER_HS52;
|
car_div = SDMMC_CAR_DIVIDER_MMC_HS;
|
||||||
break;
|
break;
|
||||||
case 100000:
|
case 100000:
|
||||||
out_freq = 90667;
|
out_freq = 90667;
|
||||||
car_div = SDMMC_CAR_DIVIDER_SDR50;
|
car_div = SDMMC_CAR_DIVIDER_UHS_SDR50;
|
||||||
break;
|
break;
|
||||||
case 200000:
|
case 200000:
|
||||||
out_freq = 163200;
|
out_freq = 163200;
|
||||||
car_div = SDMMC_CAR_DIVIDER_HS200;
|
car_div = SDMMC_CAR_DIVIDER_MMC_HS200;
|
||||||
break;
|
break;
|
||||||
case 208000:
|
case 208000:
|
||||||
out_freq = 204000;
|
out_freq = 204000;
|
||||||
car_div = SDMMC_CAR_DIVIDER_SDR104;
|
car_div = SDMMC_CAR_DIVIDER_UHS_SDR104;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -747,7 +750,7 @@ void sdmmc_select_voltage(sdmmc_t *sdmmc, SdmmcBusVoltage voltage)
|
||||||
|
|
||||||
static void sdmmc_tap_config(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed)
|
static void sdmmc_tap_config(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed)
|
||||||
{
|
{
|
||||||
if (bus_speed == SDMMC_SPEED_HS400)
|
if (bus_speed == SDMMC_SPEED_MMC_HS400)
|
||||||
{
|
{
|
||||||
/* Clear and set DQS_TRIM_VAL (used in HS400) */
|
/* Clear and set DQS_TRIM_VAL (used in HS400) */
|
||||||
sdmmc->regs->vendor_cap_overrides &= ~(0x3F00);
|
sdmmc->regs->vendor_cap_overrides &= ~(0x3F00);
|
||||||
|
@ -757,7 +760,7 @@ static void sdmmc_tap_config(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed)
|
||||||
/* Clear TAP_VAL_UPDATED_BY_HW */
|
/* Clear TAP_VAL_UPDATED_BY_HW */
|
||||||
sdmmc->regs->vendor_tuning_cntrl0 &= ~(0x20000);
|
sdmmc->regs->vendor_tuning_cntrl0 &= ~(0x20000);
|
||||||
|
|
||||||
if (bus_speed == SDMMC_SPEED_HS400)
|
if (bus_speed == SDMMC_SPEED_MMC_HS400)
|
||||||
{
|
{
|
||||||
/* We must have obtained the tap value from the tuning procedure here. */
|
/* We must have obtained the tap value from the tuning procedure here. */
|
||||||
if (sdmmc->is_tuning_tap_val_set)
|
if (sdmmc->is_tuning_tap_val_set)
|
||||||
|
@ -863,41 +866,43 @@ int sdmmc_select_speed(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed)
|
||||||
/* Set the appropriate host speed. */
|
/* Set the appropriate host speed. */
|
||||||
switch (bus_speed) {
|
switch (bus_speed) {
|
||||||
/* 400kHz initialization mode and a few others. */
|
/* 400kHz initialization mode and a few others. */
|
||||||
case SDMMC_SPEED_INIT_HS:
|
case SDMMC_SPEED_MMC_INIT:
|
||||||
case SDMMC_SPEED_HS26:
|
case SDMMC_SPEED_MMC_LEGACY:
|
||||||
case SDMMC_SPEED_INIT_SDR:
|
case SDMMC_SPEED_SD_INIT:
|
||||||
case SDMMC_SPEED_UNK6:
|
case SDMMC_SPEED_SD_LEGACY:
|
||||||
sdmmc->regs->host_control &= ~(SDHCI_CTRL_HISPD);
|
sdmmc->regs->host_control &= ~(SDHCI_CTRL_HISPD);
|
||||||
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_VDD_180);
|
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_VDD_180);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* 50MHz high speed (SD) and 52MHz high speed (MMC). */
|
/* 50MHz high speed (SD) and 52MHz high speed (MMC). */
|
||||||
case SDMMC_SPEED_SDR25:
|
case SDMMC_SPEED_SD_HS:
|
||||||
case SDMMC_SPEED_HS52:
|
case SDMMC_SPEED_MMC_HS:
|
||||||
|
case SDMMC_SPEED_UHS_SDR25:
|
||||||
sdmmc->regs->host_control |= SDHCI_CTRL_HISPD;
|
sdmmc->regs->host_control |= SDHCI_CTRL_HISPD;
|
||||||
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_VDD_180);
|
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_VDD_180);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* 200MHz UHS-I (SD) and other modes due to errata. */
|
/* 200MHz UHS-I (SD) and other modes due to errata. */
|
||||||
case SDMMC_SPEED_HS200:
|
case SDMMC_SPEED_MMC_HS200:
|
||||||
case SDMMC_SPEED_SDR104:
|
case SDMMC_SPEED_UHS_SDR104:
|
||||||
case SDMMC_SPEED_DDR50:
|
case SDMMC_SPEED_UHS_DDR50:
|
||||||
case SDMMC_SPEED_SDR50:
|
case SDMMC_SPEED_UHS_SDR50:
|
||||||
case SDMMC_SPEED_UNK14:
|
case SDMMC_SPEED_MMC_DDR52:
|
||||||
|
case SDMMC_SPEED_EMU_SDR104:
|
||||||
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK);
|
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK);
|
||||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_UHS_SDR104;
|
sdmmc->regs->host_control2 |= SDHCI_CTRL_UHS_SDR104;
|
||||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180;
|
sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* 200MHz single-data rate (MMC). */
|
/* 200MHz single-data rate (MMC). */
|
||||||
case SDMMC_SPEED_HS400:
|
case SDMMC_SPEED_MMC_HS400:
|
||||||
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK);
|
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK);
|
||||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_HS400;
|
sdmmc->regs->host_control2 |= SDHCI_CTRL_HS400;
|
||||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180;
|
sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* 25MHz default speed (SD). */
|
/* 25MHz default speed (SD). */
|
||||||
case SDMMC_SPEED_SDR12:
|
case SDMMC_SPEED_UHS_SDR12:
|
||||||
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK);
|
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK);
|
||||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_UHS_SDR12;
|
sdmmc->regs->host_control2 |= SDHCI_CTRL_UHS_SDR12;
|
||||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180;
|
sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180;
|
||||||
|
@ -936,7 +941,7 @@ int sdmmc_select_speed(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed)
|
||||||
sdmmc_enable_sd_clock(sdmmc);
|
sdmmc_enable_sd_clock(sdmmc);
|
||||||
|
|
||||||
/* Run DLLCAL for HS400 only */
|
/* Run DLLCAL for HS400 only */
|
||||||
if (bus_speed == SDMMC_SPEED_HS400)
|
if (bus_speed == SDMMC_SPEED_MMC_HS400)
|
||||||
return sdmmc_dllcal_run(sdmmc);
|
return sdmmc_dllcal_run(sdmmc);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1720,7 +1725,7 @@ int sdmmc_switch_voltage(sdmmc_t *sdmmc)
|
||||||
sdmmc_disable_sd_clock(sdmmc);
|
sdmmc_disable_sd_clock(sdmmc);
|
||||||
|
|
||||||
/* Reconfigure the internal clock. */
|
/* Reconfigure the internal clock. */
|
||||||
if (!sdmmc_select_speed(sdmmc, SDMMC_SPEED_SDR12))
|
if (!sdmmc_select_speed(sdmmc, SDMMC_SPEED_UHS_SDR12))
|
||||||
{
|
{
|
||||||
sdmmc_error(sdmmc, "Failed to apply the correct bus speed for low voltage support!");
|
sdmmc_error(sdmmc, "Failed to apply the correct bus speed for low voltage support!");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1883,15 +1888,16 @@ int sdmmc_execute_tuning(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed, uint32_t opcod
|
||||||
|
|
||||||
switch (bus_speed)
|
switch (bus_speed)
|
||||||
{
|
{
|
||||||
case SDMMC_SPEED_HS200:
|
case SDMMC_SPEED_MMC_HS200:
|
||||||
case SDMMC_SPEED_HS400:
|
case SDMMC_SPEED_MMC_HS400:
|
||||||
case SDMMC_SPEED_SDR104:
|
case SDMMC_SPEED_UHS_SDR104:
|
||||||
|
case SDMMC_SPEED_EMU_SDR104:
|
||||||
max_tuning_loop = 0x80;
|
max_tuning_loop = 0x80;
|
||||||
tuning_cntrl_flag = 0x4000;
|
tuning_cntrl_flag = 0x4000;
|
||||||
break;
|
break;
|
||||||
case SDMMC_SPEED_SDR50:
|
case SDMMC_SPEED_UHS_SDR50:
|
||||||
case SDMMC_SPEED_DDR50:
|
case SDMMC_SPEED_UHS_DDR50:
|
||||||
case SDMMC_SPEED_UNK14:
|
case SDMMC_SPEED_MMC_DDR52:
|
||||||
max_tuning_loop = 0x100;
|
max_tuning_loop = 0x100;
|
||||||
tuning_cntrl_flag = 0x8000;
|
tuning_cntrl_flag = 0x8000;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -210,33 +210,33 @@ typedef enum {
|
||||||
} SdmmcBusWidth;
|
} SdmmcBusWidth;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SDMMC_SPEED_INIT_HS = 0,
|
SDMMC_SPEED_MMC_INIT = 0,
|
||||||
SDMMC_SPEED_HS26 = 1,
|
SDMMC_SPEED_MMC_LEGACY = 1,
|
||||||
SDMMC_SPEED_HS52 = 2,
|
SDMMC_SPEED_MMC_HS = 2,
|
||||||
SDMMC_SPEED_HS200 = 3,
|
SDMMC_SPEED_MMC_HS200 = 3,
|
||||||
SDMMC_SPEED_HS400 = 4,
|
SDMMC_SPEED_MMC_HS400 = 4,
|
||||||
SDMMC_SPEED_INIT_SDR = 5,
|
SDMMC_SPEED_SD_INIT = 5,
|
||||||
SDMMC_SPEED_UNK6 = 6,
|
SDMMC_SPEED_SD_LEGACY = 6,
|
||||||
SDMMC_SPEED_SDR25 = 7,
|
SDMMC_SPEED_SD_HS = 7,
|
||||||
SDMMC_SPEED_SDR12 = 8,
|
SDMMC_SPEED_UHS_SDR12 = 8,
|
||||||
SDMMC_SPEED_UNK9 = 9,
|
SDMMC_SPEED_UHS_SDR25 = 9,
|
||||||
SDMMC_SPEED_SDR50 = 10,
|
SDMMC_SPEED_UHS_SDR50 = 10,
|
||||||
SDMMC_SPEED_SDR104 = 11,
|
SDMMC_SPEED_UHS_SDR104 = 11,
|
||||||
SDMMC_SPEED_UNK12 = 12,
|
SDMMC_SPEED_UHS_RESERVED = 12,
|
||||||
SDMMC_SPEED_DDR50 = 13,
|
SDMMC_SPEED_UHS_DDR50 = 13,
|
||||||
SDMMC_SPEED_UNK14 = 14,
|
SDMMC_SPEED_MMC_DDR52 = 14,
|
||||||
|
SDMMC_SPEED_EMU_SDR104 = 255, /* Custom speed mode. Prevents low voltage switch in MMC emulation. */
|
||||||
} SdmmcBusSpeed;
|
} SdmmcBusSpeed;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SDMMC_CAR_DIVIDER_SDR12 = 31, // (16.5 * 2) - 2
|
SDMMC_CAR_DIVIDER_UHS_SDR12 = 31, /* (16.5 * 2) - 2 */
|
||||||
SDMMC_CAR_DIVIDER_SDR25 = 15, // (8.5 * 2) - 2
|
SDMMC_CAR_DIVIDER_UHS_SDR25 = 15, /* (8.5 * 2) - 2 */
|
||||||
SDMMC_CAR_DIVIDER_SDR50 = 7, // (4.5 * 2) - 2
|
SDMMC_CAR_DIVIDER_UHS_SDR50 = 7, /* (4.5 * 2) - 2 */
|
||||||
SDMMC_CAR_DIVIDER_SDR104 = 2, // (2 * 2) - 2
|
SDMMC_CAR_DIVIDER_UHS_SDR104 = 2, /* (2 * 2) - 2 */
|
||||||
SDMMC_CAR_DIVIDER_DDR50 = 18, // (5 * 2 * 2) - 2
|
SDMMC_CAR_DIVIDER_UHS_DDR50 = 18, /* (5 * 2 * 2) - 2 */
|
||||||
SDMMC_CAR_DIVIDER_HS26 = 30, // (16 * 2) - 2
|
SDMMC_CAR_DIVIDER_MMC_LEGACY = 30, /* (16 * 2) - 2 */
|
||||||
SDMMC_CAR_DIVIDER_HS52 = 14, // (8 * 2) - 2
|
SDMMC_CAR_DIVIDER_MMC_HS = 14, /* (8 * 2) - 2 */
|
||||||
SDMMC_CAR_DIVIDER_HS200 = 3, // (2.5 * 2) - 2 (for PLLP_OUT0)
|
SDMMC_CAR_DIVIDER_MMC_HS200 = 3, /* (2.5 * 2) - 2 (for PLLP_OUT0, same as HS400) */
|
||||||
SDMMC_CAR_DIVIDER_HS400 = 3, // (2.5 * 2) - 2 (for PLLP_OUT0)
|
|
||||||
} SdmmcCarDivider;
|
} SdmmcCarDivider;
|
||||||
|
|
||||||
/* Structure for describing a SDMMC device. */
|
/* Structure for describing a SDMMC device. */
|
||||||
|
@ -272,7 +272,7 @@ typedef struct {
|
||||||
uint32_t opcode;
|
uint32_t opcode;
|
||||||
uint32_t arg;
|
uint32_t arg;
|
||||||
uint32_t resp[4];
|
uint32_t resp[4];
|
||||||
uint32_t flags; /* expected response type */
|
uint32_t flags; /* Expected response type. */
|
||||||
} sdmmc_command_t;
|
} sdmmc_command_t;
|
||||||
|
|
||||||
/* Structure for describing a SDMMC request. */
|
/* Structure for describing a SDMMC request. */
|
||||||
|
|
Loading…
Reference in a new issue