mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-29 04:50:17 +00:00
fusee: Fix SDMMC high speed support and other bugs.
This commit is contained in:
parent
eaa282b915
commit
e58927a8ab
6 changed files with 84 additions and 97 deletions
|
@ -487,12 +487,12 @@ static int sdmmc_sd_send_op_cond(sdmmc_device_t *device, bool is_sd_ver2, bool i
|
|||
return 0;
|
||||
|
||||
/* Delay a bit before asking for the voltage switch. */
|
||||
udelay(1000);
|
||||
mdelay(100);
|
||||
|
||||
/* Tell the driver to switch the voltage. */
|
||||
if (!sdmmc_switch_voltage(device->sdmmc))
|
||||
return 0;
|
||||
|
||||
|
||||
/* We are now running at 1.8V. */
|
||||
device->is_180v = true;
|
||||
}
|
||||
|
@ -693,15 +693,15 @@ static int sdmmc_sd_switch_hs_low(sdmmc_device_t *device, uint8_t *status)
|
|||
/* Adjust the current limit. */
|
||||
if (!sdmmc_sd_set_current_limit(device, status))
|
||||
return 0;
|
||||
|
||||
|
||||
/* Invalid bus width. */
|
||||
if (device->sdmmc->bus_width != SDMMC_BUS_WIDTH_4BIT)
|
||||
return 0;
|
||||
|
||||
|
||||
/* Get the supported high-speed type. */
|
||||
if (!sdmmc_sd_switch(device, 0, 0, 0xF, status))
|
||||
return 0;
|
||||
|
||||
|
||||
/* High-speed SDR104 is supported. */
|
||||
if (status[13] & SD_MODE_UHS_SDR104)
|
||||
{
|
||||
|
@ -748,6 +748,7 @@ static int sdmmc_sd_switch_hs_low(sdmmc_device_t *device, uint8_t *status)
|
|||
else
|
||||
return 0;
|
||||
|
||||
|
||||
/* Peek the SD card's status. */
|
||||
return sdmmc_device_send_status(device);
|
||||
}
|
||||
|
@ -974,22 +975,22 @@ int sdmmc_device_sd_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth b
|
|||
/* Switch to high-speed from low voltage (if possible). */
|
||||
if (!sdmmc_sd_switch_hs_low(device, switch_status))
|
||||
{
|
||||
sdmmc_error(sdmmc, "Failed to switch to high-speed!");
|
||||
sdmmc_error(sdmmc, "Failed to switch to high-speed from low voltage!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
sdmmc_info(sdmmc, "Switched to high-speed!");
|
||||
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)))
|
||||
{
|
||||
/* Switch to high-speed from high voltage (if possible). */
|
||||
if (!sdmmc_sd_switch_hs_high(device, switch_status))
|
||||
{
|
||||
sdmmc_error(sdmmc, "Failed to switch to high-speed!");
|
||||
sdmmc_error(sdmmc, "Failed to switch to high-speed from high voltage!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
sdmmc_info(sdmmc, "Switched to high-speed!");
|
||||
sdmmc_info(sdmmc, "Switched to high-speed from high voltage!");
|
||||
}
|
||||
|
||||
/* Correct any inconsistent states. */
|
||||
|
@ -1373,7 +1374,7 @@ int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth
|
|||
{
|
||||
uint32_t cid[4] = {0};
|
||||
uint32_t csd[4] = {0};
|
||||
uint8_t *ext_csd = (uint8_t *)SDMMC_BOUNCE_BUFFER_ADDRESS; // TODO: Better way to do this.
|
||||
uint8_t ext_csd[512] = {0};
|
||||
|
||||
/* Initialize our device's struct. */
|
||||
memset(device, 0, sizeof(sdmmc_device_t));
|
||||
|
|
|
@ -549,28 +549,26 @@ static int sdmmc_autocal_config(sdmmc_t *sdmmc, SdmmcBusVoltage voltage)
|
|||
case SDMMC_3:
|
||||
switch (voltage) {
|
||||
case SDMMC_VOLTAGE_1V8:
|
||||
sdmmc->regs->auto_cal_config &= ~SDMMC_AUTOCAL_PDPU_CONFIG_MASK;
|
||||
sdmmc->regs->auto_cal_config &= ~(SDMMC_AUTOCAL_PDPU_CONFIG_MASK);
|
||||
sdmmc->regs->auto_cal_config |= SDMMC_AUTOCAL_PDPU_SDMMC1_1V8;
|
||||
break;
|
||||
case SDMMC_VOLTAGE_3V3:
|
||||
sdmmc->regs->auto_cal_config &= ~SDMMC_AUTOCAL_PDPU_CONFIG_MASK;
|
||||
sdmmc->regs->auto_cal_config &= ~(SDMMC_AUTOCAL_PDPU_CONFIG_MASK);
|
||||
sdmmc->regs->auto_cal_config |= SDMMC_AUTOCAL_PDPU_SDMMC1_3V3;
|
||||
break;
|
||||
default:
|
||||
sdmmc_error(sdmmc, "microsd does not support voltage %d", voltage);
|
||||
sdmmc_error(sdmmc, "uSD does not support requested voltage!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SDMMC_2:
|
||||
case SDMMC_4:
|
||||
if (voltage != SDMMC_VOLTAGE_1V8) {
|
||||
sdmmc_error(sdmmc, "eMMC can only run at 1V8, but sdmmc struct claims voltage %d", voltage);
|
||||
sdmmc_error(sdmmc, "eMMC can only run at 1V8!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
sdmmc->regs->auto_cal_config &= ~SDMMC_AUTOCAL_PDPU_CONFIG_MASK;
|
||||
sdmmc->regs->auto_cal_config &= ~(SDMMC_AUTOCAL_PDPU_CONFIG_MASK);
|
||||
sdmmc->regs->auto_cal_config |= SDMMC_AUTOCAL_PDPU_SDMMC4_1V8;
|
||||
break;
|
||||
}
|
||||
|
@ -581,8 +579,8 @@ static int sdmmc_autocal_config(sdmmc_t *sdmmc, SdmmcBusVoltage voltage)
|
|||
/* Run automatic calibration. */
|
||||
static void sdmmc_autocal_run(sdmmc_t *sdmmc, SdmmcBusVoltage voltage)
|
||||
{
|
||||
bool restart_sd_clock = false;
|
||||
volatile tegra_padctl_t *padctl = padctl_get_regs();
|
||||
bool restart_sd_clock = false;
|
||||
|
||||
/* SD clock is enabled. Disable it and restart later. */
|
||||
if (sdmmc->is_sd_clk_enabled)
|
||||
|
@ -619,7 +617,7 @@ static void sdmmc_autocal_run(sdmmc_t *sdmmc, SdmmcBusVoltage voltage)
|
|||
while ((sdmmc->regs->auto_cal_status & SDMMC_AUTOCAL_ACTIVE)) {
|
||||
/* Ensure we haven't timed out. */
|
||||
if (get_time_since(timebase) > SDMMC_AUTOCAL_TIMEOUT) {
|
||||
sdmmc_error(sdmmc, "autocal timed out!");
|
||||
sdmmc_error(sdmmc, "Auto-calibration timed out!");
|
||||
|
||||
/* Force a register read to refresh the clock control value. */
|
||||
sdmmc_get_sd_clock_control(sdmmc);
|
||||
|
@ -642,7 +640,7 @@ static void sdmmc_autocal_run(sdmmc_t *sdmmc, SdmmcBusVoltage voltage)
|
|||
}
|
||||
|
||||
/* Manually clear the autocal enable bit. */
|
||||
sdmmc->regs->auto_cal_config &= ~SDMMC_AUTOCAL_ENABLE;
|
||||
sdmmc->regs->auto_cal_config &= ~(SDMMC_AUTOCAL_ENABLE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -696,16 +694,9 @@ static int sdmmc_int_clk_enable(sdmmc_t *sdmmc)
|
|||
/* Use SDMA by default. */
|
||||
sdmmc->regs->host_control &= ~SDHCI_CTRL_DMA_MASK;
|
||||
|
||||
/* Change to ADMA if requested. */
|
||||
if (sdmmc->use_adma && (sdmmc->regs->capabilities & SDHCI_CAN_DO_ADMA2)) {
|
||||
// TODO: Setting the ADMA flags breaks ADMA...
|
||||
/*
|
||||
if (sdmmc->regs->capabilities & SDHCI_CAN_64BIT)
|
||||
sdmmc->regs->host_control |= SDHCI_CTRL_ADMA64;
|
||||
else
|
||||
sdmmc->regs->host_control |= SDHCI_CTRL_ADMA32;
|
||||
*/
|
||||
}
|
||||
/* Change to ADMA if possible. */
|
||||
if (sdmmc->regs->capabilities & SDHCI_CAN_DO_ADMA2)
|
||||
sdmmc->use_adma = true;
|
||||
|
||||
/* Set the timeout to be the maximum value. */
|
||||
sdmmc->regs->timeout_control &= 0xF0;
|
||||
|
@ -847,9 +838,9 @@ static int sdmmc_dllcal_run(sdmmc_t *sdmmc)
|
|||
is_timeout = (get_time_since(timebase) > 10000);
|
||||
}
|
||||
|
||||
/* Clock failed to stabilize. */
|
||||
/* Calibration failed. */
|
||||
if (is_timeout) {
|
||||
sdmmc_error(sdmmc, "ERROR: DLLCAL failed!");
|
||||
sdmmc_error(sdmmc, "DLLCAL failed!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -898,20 +889,23 @@ int sdmmc_select_speed(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed)
|
|||
case SDMMC_SPEED_DDR50:
|
||||
case SDMMC_SPEED_SDR50:
|
||||
case SDMMC_SPEED_UNK14:
|
||||
sdmmc->regs->host_control2 &= SDHCI_CTRL_UHS_MASK;
|
||||
sdmmc->regs->host_control2 |= (SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180);
|
||||
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK);
|
||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_UHS_SDR104;
|
||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180;
|
||||
break;
|
||||
|
||||
/* 200MHz single-data rate (MMC). */
|
||||
case SDMMC_SPEED_HS400:
|
||||
sdmmc->regs->host_control2 &= SDHCI_CTRL_UHS_MASK;
|
||||
sdmmc->regs->host_control2 |= (SDHCI_CTRL_HS400 | SDHCI_CTRL_VDD_180);
|
||||
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK);
|
||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_HS400;
|
||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180;
|
||||
break;
|
||||
|
||||
/* 25MHz default speed (SD). */
|
||||
case SDMMC_SPEED_SDR12:
|
||||
sdmmc->regs->host_control2 &= SDHCI_CTRL_UHS_MASK;
|
||||
sdmmc->regs->host_control2 |= (SDHCI_CTRL_UHS_SDR12 | SDHCI_CTRL_VDD_180);
|
||||
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK);
|
||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_UHS_SDR12;
|
||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1093,7 +1087,7 @@ static int sdmmc_init_controller(sdmmc_t *sdmmc, SdmmcControllerNum controller)
|
|||
sdmmc->is_clk_running = false;
|
||||
sdmmc->is_sd_clk_enabled = false;
|
||||
sdmmc->is_tuning_tap_val_set = false;
|
||||
sdmmc->use_adma = true;
|
||||
sdmmc->use_adma = false;
|
||||
sdmmc->dma_bounce_buf = (uint8_t*)SDMMC_BOUNCE_BUFFER_ADDRESS;
|
||||
sdmmc->tap_val = 0;
|
||||
sdmmc->internal_divider = 0;
|
||||
|
@ -1206,11 +1200,11 @@ void sdmmc_finish(sdmmc_t *sdmmc)
|
|||
sdmmc_select_voltage(sdmmc, SDMMC_VOLTAGE_NONE);
|
||||
|
||||
/* Disable the SD card power. */
|
||||
if (sdmmc->controller == SDMMC_1)
|
||||
{
|
||||
if (sdmmc->controller == SDMMC_1)
|
||||
{
|
||||
/* Disable GPIO output. */
|
||||
gpio_configure_direction(GPIO_MICROSD_SUPPLY_ENABLE, GPIO_DIRECTION_INPUT);
|
||||
|
||||
|
||||
/* Power cycle for 100ms without power. */
|
||||
mdelay(100);
|
||||
}
|
||||
|
@ -1749,7 +1743,7 @@ int sdmmc_switch_voltage(sdmmc_t *sdmmc)
|
|||
sdmmc_get_sd_clock_control(sdmmc);
|
||||
|
||||
/* Wait a while. */
|
||||
udelay(5000);
|
||||
mdelay(5);
|
||||
|
||||
/* Host control 2 flag should be set by now. */
|
||||
if (sdmmc->regs->host_control2 & SDHCI_CTRL_VDD_180)
|
||||
|
@ -1761,7 +1755,7 @@ int sdmmc_switch_voltage(sdmmc_t *sdmmc)
|
|||
sdmmc_get_sd_clock_control(sdmmc);
|
||||
|
||||
/* Wait a while. */
|
||||
udelay(1000);
|
||||
mdelay(1);
|
||||
|
||||
/* Data level is up. Voltage switching is done.*/
|
||||
if (sdmmc->regs->present_state & SDHCI_DATA_LVL_MASK)
|
||||
|
|
|
@ -106,7 +106,7 @@ typedef struct {
|
|||
uint16_t slot_int_status;
|
||||
uint16_t host_version;
|
||||
|
||||
/* vendor specific registers */
|
||||
/* Vendor specific registers */
|
||||
uint32_t vendor_clock_cntrl;
|
||||
uint32_t vendor_sys_sw_cntrl;
|
||||
uint32_t vendor_err_intr_status;
|
||||
|
@ -121,12 +121,12 @@ typedef struct {
|
|||
uint32_t _0x12c[0x20];
|
||||
uint32_t vendor_io_trim_cntrl;
|
||||
|
||||
/* start of sdmmc2/sdmmc4 only */
|
||||
/* Start of sdmmc2/sdmmc4 only */
|
||||
uint32_t vendor_dllcal_cfg;
|
||||
uint32_t vendor_dll_ctrl0;
|
||||
uint32_t vendor_dll_ctrl1;
|
||||
uint32_t vendor_dllcal_cfg_sta;
|
||||
/* end of sdmmc2/sdmmc4 only */
|
||||
/* End of sdmmc2/sdmmc4 only */
|
||||
|
||||
uint32_t vendor_tuning_cntrl0;
|
||||
uint32_t vendor_tuning_cntrl1;
|
||||
|
|
|
@ -487,12 +487,12 @@ static int sdmmc_sd_send_op_cond(sdmmc_device_t *device, bool is_sd_ver2, bool i
|
|||
return 0;
|
||||
|
||||
/* Delay a bit before asking for the voltage switch. */
|
||||
udelay(1000);
|
||||
mdelay(100);
|
||||
|
||||
/* Tell the driver to switch the voltage. */
|
||||
if (!sdmmc_switch_voltage(device->sdmmc))
|
||||
return 0;
|
||||
|
||||
|
||||
/* We are now running at 1.8V. */
|
||||
device->is_180v = true;
|
||||
}
|
||||
|
@ -693,15 +693,15 @@ static int sdmmc_sd_switch_hs_low(sdmmc_device_t *device, uint8_t *status)
|
|||
/* Adjust the current limit. */
|
||||
if (!sdmmc_sd_set_current_limit(device, status))
|
||||
return 0;
|
||||
|
||||
|
||||
/* Invalid bus width. */
|
||||
if (device->sdmmc->bus_width != SDMMC_BUS_WIDTH_4BIT)
|
||||
return 0;
|
||||
|
||||
|
||||
/* Get the supported high-speed type. */
|
||||
if (!sdmmc_sd_switch(device, 0, 0, 0xF, status))
|
||||
return 0;
|
||||
|
||||
|
||||
/* High-speed SDR104 is supported. */
|
||||
if (status[13] & SD_MODE_UHS_SDR104)
|
||||
{
|
||||
|
@ -748,6 +748,7 @@ static int sdmmc_sd_switch_hs_low(sdmmc_device_t *device, uint8_t *status)
|
|||
else
|
||||
return 0;
|
||||
|
||||
|
||||
/* Peek the SD card's status. */
|
||||
return sdmmc_device_send_status(device);
|
||||
}
|
||||
|
@ -974,22 +975,22 @@ int sdmmc_device_sd_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth b
|
|||
/* Switch to high-speed from low voltage (if possible). */
|
||||
if (!sdmmc_sd_switch_hs_low(device, switch_status))
|
||||
{
|
||||
sdmmc_error(sdmmc, "Failed to switch to high-speed!");
|
||||
sdmmc_error(sdmmc, "Failed to switch to high-speed from low voltage!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
sdmmc_info(sdmmc, "Switched to high-speed!");
|
||||
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)))
|
||||
{
|
||||
/* Switch to high-speed from high voltage (if possible). */
|
||||
if (!sdmmc_sd_switch_hs_high(device, switch_status))
|
||||
{
|
||||
sdmmc_error(sdmmc, "Failed to switch to high-speed!");
|
||||
sdmmc_error(sdmmc, "Failed to switch to high-speed from high voltage!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
sdmmc_info(sdmmc, "Switched to high-speed!");
|
||||
sdmmc_info(sdmmc, "Switched to high-speed from high voltage!");
|
||||
}
|
||||
|
||||
/* Correct any inconsistent states. */
|
||||
|
@ -1322,9 +1323,6 @@ static int sdmmc_mmc_select_hs400(sdmmc_device_t *device)
|
|||
|
||||
static int sdmmc_mmc_select_timing(sdmmc_device_t *device, SdmmcBusSpeed bus_speed)
|
||||
{
|
||||
// FIXME: Tuning is broken. Use HS52 for now.
|
||||
return sdmmc_mmc_select_hs(device, false);
|
||||
|
||||
if ((bus_speed == SDMMC_SPEED_HS400) &&
|
||||
(device->sdmmc->bus_width == SDMMC_BUS_WIDTH_8BIT) &&
|
||||
(device->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_HS400_1_8V))
|
||||
|
@ -1376,7 +1374,7 @@ int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth
|
|||
{
|
||||
uint32_t cid[4] = {0};
|
||||
uint32_t csd[4] = {0};
|
||||
uint8_t *ext_csd = (uint8_t *)SDMMC_BOUNCE_BUFFER_ADDRESS; // TODO: Better way to do this.
|
||||
uint8_t ext_csd[512] = {0};
|
||||
|
||||
/* Initialize our device's struct. */
|
||||
memset(device, 0, sizeof(sdmmc_device_t));
|
||||
|
|
|
@ -549,28 +549,26 @@ static int sdmmc_autocal_config(sdmmc_t *sdmmc, SdmmcBusVoltage voltage)
|
|||
case SDMMC_3:
|
||||
switch (voltage) {
|
||||
case SDMMC_VOLTAGE_1V8:
|
||||
sdmmc->regs->auto_cal_config &= ~SDMMC_AUTOCAL_PDPU_CONFIG_MASK;
|
||||
sdmmc->regs->auto_cal_config &= ~(SDMMC_AUTOCAL_PDPU_CONFIG_MASK);
|
||||
sdmmc->regs->auto_cal_config |= SDMMC_AUTOCAL_PDPU_SDMMC1_1V8;
|
||||
break;
|
||||
case SDMMC_VOLTAGE_3V3:
|
||||
sdmmc->regs->auto_cal_config &= ~SDMMC_AUTOCAL_PDPU_CONFIG_MASK;
|
||||
sdmmc->regs->auto_cal_config &= ~(SDMMC_AUTOCAL_PDPU_CONFIG_MASK);
|
||||
sdmmc->regs->auto_cal_config |= SDMMC_AUTOCAL_PDPU_SDMMC1_3V3;
|
||||
break;
|
||||
default:
|
||||
sdmmc_error(sdmmc, "microsd does not support voltage %d", voltage);
|
||||
sdmmc_error(sdmmc, "uSD does not support requested voltage!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SDMMC_2:
|
||||
case SDMMC_4:
|
||||
if (voltage != SDMMC_VOLTAGE_1V8) {
|
||||
sdmmc_error(sdmmc, "eMMC can only run at 1V8, but sdmmc struct claims voltage %d", voltage);
|
||||
sdmmc_error(sdmmc, "eMMC can only run at 1V8!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
sdmmc->regs->auto_cal_config &= ~SDMMC_AUTOCAL_PDPU_CONFIG_MASK;
|
||||
sdmmc->regs->auto_cal_config &= ~(SDMMC_AUTOCAL_PDPU_CONFIG_MASK);
|
||||
sdmmc->regs->auto_cal_config |= SDMMC_AUTOCAL_PDPU_SDMMC4_1V8;
|
||||
break;
|
||||
}
|
||||
|
@ -581,8 +579,8 @@ static int sdmmc_autocal_config(sdmmc_t *sdmmc, SdmmcBusVoltage voltage)
|
|||
/* Run automatic calibration. */
|
||||
static void sdmmc_autocal_run(sdmmc_t *sdmmc, SdmmcBusVoltage voltage)
|
||||
{
|
||||
bool restart_sd_clock = false;
|
||||
volatile tegra_padctl_t *padctl = padctl_get_regs();
|
||||
bool restart_sd_clock = false;
|
||||
|
||||
/* SD clock is enabled. Disable it and restart later. */
|
||||
if (sdmmc->is_sd_clk_enabled)
|
||||
|
@ -619,7 +617,7 @@ static void sdmmc_autocal_run(sdmmc_t *sdmmc, SdmmcBusVoltage voltage)
|
|||
while ((sdmmc->regs->auto_cal_status & SDMMC_AUTOCAL_ACTIVE)) {
|
||||
/* Ensure we haven't timed out. */
|
||||
if (get_time_since(timebase) > SDMMC_AUTOCAL_TIMEOUT) {
|
||||
sdmmc_error(sdmmc, "autocal timed out!");
|
||||
sdmmc_error(sdmmc, "Auto-calibration timed out!");
|
||||
|
||||
/* Force a register read to refresh the clock control value. */
|
||||
sdmmc_get_sd_clock_control(sdmmc);
|
||||
|
@ -642,7 +640,7 @@ static void sdmmc_autocal_run(sdmmc_t *sdmmc, SdmmcBusVoltage voltage)
|
|||
}
|
||||
|
||||
/* Manually clear the autocal enable bit. */
|
||||
sdmmc->regs->auto_cal_config &= ~SDMMC_AUTOCAL_ENABLE;
|
||||
sdmmc->regs->auto_cal_config &= ~(SDMMC_AUTOCAL_ENABLE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -696,16 +694,9 @@ static int sdmmc_int_clk_enable(sdmmc_t *sdmmc)
|
|||
/* Use SDMA by default. */
|
||||
sdmmc->regs->host_control &= ~SDHCI_CTRL_DMA_MASK;
|
||||
|
||||
/* Change to ADMA if requested. */
|
||||
if (sdmmc->use_adma && (sdmmc->regs->capabilities & SDHCI_CAN_DO_ADMA2)) {
|
||||
// TODO: Setting the ADMA flags breaks ADMA...
|
||||
/*
|
||||
if (sdmmc->regs->capabilities & SDHCI_CAN_64BIT)
|
||||
sdmmc->regs->host_control |= SDHCI_CTRL_ADMA64;
|
||||
else
|
||||
sdmmc->regs->host_control |= SDHCI_CTRL_ADMA32;
|
||||
*/
|
||||
}
|
||||
/* Change to ADMA if possible. */
|
||||
if (sdmmc->regs->capabilities & SDHCI_CAN_DO_ADMA2)
|
||||
sdmmc->use_adma = true;
|
||||
|
||||
/* Set the timeout to be the maximum value. */
|
||||
sdmmc->regs->timeout_control &= 0xF0;
|
||||
|
@ -847,9 +838,9 @@ static int sdmmc_dllcal_run(sdmmc_t *sdmmc)
|
|||
is_timeout = (get_time_since(timebase) > 10000);
|
||||
}
|
||||
|
||||
/* Clock failed to stabilize. */
|
||||
/* Calibration failed. */
|
||||
if (is_timeout) {
|
||||
sdmmc_error(sdmmc, "ERROR: DLLCAL failed!");
|
||||
sdmmc_error(sdmmc, "DLLCAL failed!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -898,20 +889,23 @@ int sdmmc_select_speed(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed)
|
|||
case SDMMC_SPEED_DDR50:
|
||||
case SDMMC_SPEED_SDR50:
|
||||
case SDMMC_SPEED_UNK14:
|
||||
sdmmc->regs->host_control2 &= SDHCI_CTRL_UHS_MASK;
|
||||
sdmmc->regs->host_control2 |= (SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180);
|
||||
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK);
|
||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_UHS_SDR104;
|
||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180;
|
||||
break;
|
||||
|
||||
/* 200MHz single-data rate (MMC). */
|
||||
case SDMMC_SPEED_HS400:
|
||||
sdmmc->regs->host_control2 &= SDHCI_CTRL_UHS_MASK;
|
||||
sdmmc->regs->host_control2 |= (SDHCI_CTRL_HS400 | SDHCI_CTRL_VDD_180);
|
||||
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK);
|
||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_HS400;
|
||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180;
|
||||
break;
|
||||
|
||||
/* 25MHz default speed (SD). */
|
||||
case SDMMC_SPEED_SDR12:
|
||||
sdmmc->regs->host_control2 &= SDHCI_CTRL_UHS_MASK;
|
||||
sdmmc->regs->host_control2 |= (SDHCI_CTRL_UHS_SDR12 | SDHCI_CTRL_VDD_180);
|
||||
sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK);
|
||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_UHS_SDR12;
|
||||
sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1093,7 +1087,7 @@ static int sdmmc_init_controller(sdmmc_t *sdmmc, SdmmcControllerNum controller)
|
|||
sdmmc->is_clk_running = false;
|
||||
sdmmc->is_sd_clk_enabled = false;
|
||||
sdmmc->is_tuning_tap_val_set = false;
|
||||
sdmmc->use_adma = true;
|
||||
sdmmc->use_adma = false;
|
||||
sdmmc->dma_bounce_buf = (uint8_t*)SDMMC_BOUNCE_BUFFER_ADDRESS;
|
||||
sdmmc->tap_val = 0;
|
||||
sdmmc->internal_divider = 0;
|
||||
|
@ -1206,11 +1200,11 @@ void sdmmc_finish(sdmmc_t *sdmmc)
|
|||
sdmmc_select_voltage(sdmmc, SDMMC_VOLTAGE_NONE);
|
||||
|
||||
/* Disable the SD card power. */
|
||||
if (sdmmc->controller == SDMMC_1)
|
||||
{
|
||||
if (sdmmc->controller == SDMMC_1)
|
||||
{
|
||||
/* Disable GPIO output. */
|
||||
gpio_configure_direction(GPIO_MICROSD_SUPPLY_ENABLE, GPIO_DIRECTION_INPUT);
|
||||
|
||||
|
||||
/* Power cycle for 100ms without power. */
|
||||
mdelay(100);
|
||||
}
|
||||
|
@ -1749,7 +1743,7 @@ int sdmmc_switch_voltage(sdmmc_t *sdmmc)
|
|||
sdmmc_get_sd_clock_control(sdmmc);
|
||||
|
||||
/* Wait a while. */
|
||||
udelay(5000);
|
||||
mdelay(5);
|
||||
|
||||
/* Host control 2 flag should be set by now. */
|
||||
if (sdmmc->regs->host_control2 & SDHCI_CTRL_VDD_180)
|
||||
|
@ -1761,7 +1755,7 @@ int sdmmc_switch_voltage(sdmmc_t *sdmmc)
|
|||
sdmmc_get_sd_clock_control(sdmmc);
|
||||
|
||||
/* Wait a while. */
|
||||
udelay(1000);
|
||||
mdelay(1);
|
||||
|
||||
/* Data level is up. Voltage switching is done.*/
|
||||
if (sdmmc->regs->present_state & SDHCI_DATA_LVL_MASK)
|
||||
|
|
|
@ -106,7 +106,7 @@ typedef struct {
|
|||
uint16_t slot_int_status;
|
||||
uint16_t host_version;
|
||||
|
||||
/* vendor specific registers */
|
||||
/* Vendor specific registers */
|
||||
uint32_t vendor_clock_cntrl;
|
||||
uint32_t vendor_sys_sw_cntrl;
|
||||
uint32_t vendor_err_intr_status;
|
||||
|
@ -121,12 +121,12 @@ typedef struct {
|
|||
uint32_t _0x12c[0x20];
|
||||
uint32_t vendor_io_trim_cntrl;
|
||||
|
||||
/* start of sdmmc2/sdmmc4 only */
|
||||
/* Start of sdmmc2/sdmmc4 only */
|
||||
uint32_t vendor_dllcal_cfg;
|
||||
uint32_t vendor_dll_ctrl0;
|
||||
uint32_t vendor_dll_ctrl1;
|
||||
uint32_t vendor_dllcal_cfg_sta;
|
||||
/* end of sdmmc2/sdmmc4 only */
|
||||
/* End of sdmmc2/sdmmc4 only */
|
||||
|
||||
uint32_t vendor_tuning_cntrl0;
|
||||
uint32_t vendor_tuning_cntrl1;
|
||||
|
|
Loading…
Reference in a new issue