@@ -274,7 +274,7 @@ void *sd_file_read(const char *path, u32 *fsize)
|
||||
return buf;
|
||||
}
|
||||
|
||||
int sd_save_to_file(void *buf, u32 size, const char *filename)
|
||||
int sd_save_to_file(const void *buf, u32 size, const char *filename)
|
||||
{
|
||||
FIL fp;
|
||||
u32 res = 0;
|
||||
|
||||
@@ -61,6 +61,6 @@ void sd_unmount();
|
||||
void sd_end();
|
||||
bool sd_is_gpt();
|
||||
void *sd_file_read(const char *path, u32 *fsize);
|
||||
int sd_save_to_file(void *buf, u32 size, const char *filename);
|
||||
int sd_save_to_file(const void *buf, u32 size, const char *filename);
|
||||
|
||||
#endif
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
/* OCR bit definitions */
|
||||
#define SD_OCR_VDD_18 (1U << 7) /* VDD voltage 1.8 */
|
||||
#define SD_VHD_27_36 (1U << 8) /* VDD voltage 2.7 ~ 3.6 */
|
||||
#define SD_VHS_27_36 (1U << 8) /* VDD voltage 2.7 ~ 3.6 */
|
||||
#define SD_OCR_VDD_32_33 (1U << 20) /* VDD voltage 3.2 ~ 3.3 */
|
||||
#define SD_OCR_S18R (1U << 24) /* 1.8V switching request */
|
||||
#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
u32 sd_power_cycle_time_start;
|
||||
|
||||
static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size)
|
||||
static inline u32 unstuff_bits(const u32 *resp, u32 start, u32 size)
|
||||
{
|
||||
const u32 mask = (size < 32 ? 1 << size : 0) - 1;
|
||||
const u32 off = 3 - ((start) / 32);
|
||||
@@ -234,6 +234,8 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
|
||||
|
||||
int sdmmc_storage_end(sdmmc_storage_t *storage)
|
||||
{
|
||||
DPRINTF("[SDMMC%d] end\n", storage->sdmmc->id);
|
||||
|
||||
if (!_sdmmc_storage_go_idle_state(storage))
|
||||
return 0;
|
||||
|
||||
@@ -276,7 +278,7 @@ reinit_try:
|
||||
// Disk IO failure! Reinit SD/EMMC to a lower speed.
|
||||
if (storage->sdmmc->id == SDMMC_1 || storage->sdmmc->id == SDMMC_4)
|
||||
{
|
||||
int res;
|
||||
int res = 0;
|
||||
|
||||
if (storage->sdmmc->id == SDMMC_1)
|
||||
{
|
||||
@@ -782,7 +784,7 @@ static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp
|
||||
}
|
||||
|
||||
#ifdef SDMMC_DEBUG_PRINT_SD_REGS
|
||||
void _sd_storage_debug_print_cid(u32 *raw_cid)
|
||||
void _sd_storage_debug_print_cid(const u32 *raw_cid)
|
||||
{
|
||||
gfx_printf("Card Identification\n");
|
||||
|
||||
@@ -798,7 +800,7 @@ void _sd_storage_debug_print_cid(u32 *raw_cid)
|
||||
gfx_printf("--RSVD-- %X\n", unstuff_bits(raw_cid, 20, 4));
|
||||
}
|
||||
|
||||
void _sd_storage_debug_print_csd(u32 *raw_csd)
|
||||
void _sd_storage_debug_print_csd(const u32 *raw_csd)
|
||||
{
|
||||
gfx_printf("\n");
|
||||
|
||||
@@ -835,7 +837,7 @@ void _sd_storage_debug_print_csd(u32 *raw_csd)
|
||||
unstuff_bits(raw_csd, 16, 5), unstuff_bits(raw_csd, 8, 2));
|
||||
}
|
||||
|
||||
void _sd_storage_debug_print_scr(u32 *raw_scr)
|
||||
void _sd_storage_debug_print_scr(const u32 *raw_scr)
|
||||
{
|
||||
u32 resp[4];
|
||||
memcpy(&resp[2], raw_scr, 8);
|
||||
@@ -856,7 +858,7 @@ void _sd_storage_debug_print_scr(u32 *raw_scr)
|
||||
gfx_printf("--RSVD-- %X\n", unstuff_bits(resp, 36, 2));
|
||||
}
|
||||
|
||||
void _sd_storage_debug_print_ssr(u8 *raw_ssr)
|
||||
void _sd_storage_debug_print_ssr(const u8 *raw_ssr)
|
||||
{
|
||||
u32 raw_ssr0[4]; // 511:384.
|
||||
u32 raw_ssr1[4]; // 383:256.
|
||||
@@ -911,7 +913,7 @@ void _sd_storage_debug_print_ssr(u8 *raw_ssr)
|
||||
static int _sd_storage_send_if_cond(sdmmc_storage_t *storage, bool *is_sdsc)
|
||||
{
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
u16 vhd_pattern = SD_VHD_27_36 | 0xAA;
|
||||
u16 vhd_pattern = SD_VHS_27_36 | 0xAA;
|
||||
sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, vhd_pattern, SDMMC_RSP_TYPE_5, 0);
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||
{
|
||||
@@ -1133,17 +1135,20 @@ static void _sd_storage_set_power_limit(sdmmc_storage_t *storage, u16 power_limi
|
||||
u32 pwr = SD_SET_POWER_LIMIT_0_72;
|
||||
|
||||
// If UHS-I only, anything above 1.44W defaults to 1.44W.
|
||||
/*
|
||||
if (power_limit & SD_MAX_POWER_2_88)
|
||||
pwr = SD_SET_POWER_LIMIT_2_88;
|
||||
else if (power_limit & SD_MAX_POWER_2_16)
|
||||
pwr = SD_SET_POWER_LIMIT_2_16;
|
||||
else if (power_limit & SD_MAX_POWER_1_44)
|
||||
*/
|
||||
if (power_limit & SD_MAX_POWER_1_44)
|
||||
pwr = SD_SET_POWER_LIMIT_1_44;
|
||||
|
||||
_sd_storage_switch(storage, buf, SD_SWITCH_SET, SD_SWITCH_GRP_PWRLIM, pwr);
|
||||
|
||||
switch ((buf[15] >> 4) & 0x0F)
|
||||
{
|
||||
/*
|
||||
case SD_SET_POWER_LIMIT_2_88:
|
||||
DPRINTF("[SD] power limit raised to 2880 mW\n");
|
||||
break;
|
||||
@@ -1151,7 +1156,7 @@ static void _sd_storage_set_power_limit(sdmmc_storage_t *storage, u16 power_limi
|
||||
case SD_SET_POWER_LIMIT_2_16:
|
||||
DPRINTF("[SD] power limit raised to 2160 mW\n");
|
||||
break;
|
||||
|
||||
*/
|
||||
case SD_SET_POWER_LIMIT_1_44:
|
||||
DPRINTF("[SD] power limit raised to 1440 mW\n");
|
||||
break;
|
||||
@@ -1397,7 +1402,7 @@ static int _sd_storage_enable_uhs_low_volt(sdmmc_storage_t *storage, u32 type, u
|
||||
}
|
||||
|
||||
// Try to raise the power limit to let the card perform better.
|
||||
if (hs_type != UHS_SDR25_BUS_SPEED)
|
||||
if (hs_type != UHS_SDR25_BUS_SPEED) // Not applicable for SDR12/SDR25.
|
||||
_sd_storage_set_power_limit(storage, fmodes.power_limit, buf);
|
||||
|
||||
// Setup and set selected card and bus speed.
|
||||
@@ -1425,9 +1430,6 @@ static int _sd_storage_enable_hs_high_volt(sdmmc_storage_t *storage, u8 *buf)
|
||||
|
||||
DPRINTF("[SD] access: %02X, power: %02X\n", fmodes.access_mode, fmodes.power_limit);
|
||||
|
||||
// Try to raise the power limit to let the card perform better.
|
||||
_sd_storage_set_power_limit(storage, fmodes.power_limit, buf);
|
||||
|
||||
if (!(fmodes.access_mode & SD_MODE_HIGH_SPEED))
|
||||
return 1;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2023 CTCaer
|
||||
* Copyright (c) 2018-2024 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -109,8 +109,8 @@ void sdmmc_save_tap_value(sdmmc_t *sdmmc)
|
||||
|
||||
static int _sdmmc_config_tap_val(sdmmc_t *sdmmc, u32 type)
|
||||
{
|
||||
const u32 dqs_trim_val = 40; // 24 if HS533/HS667.
|
||||
const u8 tap_values_t210[4] = { 4, 0, 3, 0 };
|
||||
static const u32 dqs_trim_val = 40; // 24 if HS533/HS667.
|
||||
static const u8 tap_values_t210[4] = { 4, 0, 3, 0 };
|
||||
|
||||
u32 tap_val = 0;
|
||||
|
||||
@@ -222,6 +222,9 @@ static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power)
|
||||
{
|
||||
sdmmc->regs->autocalcfg &= ~SDHCI_TEGRA_AUTOCAL_ENABLE;
|
||||
_sdmmc_pad_config_fallback(sdmmc, power);
|
||||
#ifdef ERROR_EXTRA_PRINTING
|
||||
EPRINTFARGS("SDMMC%d: Comp Pad cal timeout!", sdmmc->id + 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Disable E_INPUT (SD) or enable E_PWRD (eMMC) to conserve power.
|
||||
@@ -403,7 +406,7 @@ static void _sdmmc_card_clock_enable(sdmmc_t *sdmmc)
|
||||
sdmmc->card_clock_enabled = 1;
|
||||
}
|
||||
|
||||
static void _sdmmc_sd_clock_disable(sdmmc_t *sdmmc)
|
||||
static void _sdmmc_card_clock_disable(sdmmc_t *sdmmc)
|
||||
{
|
||||
sdmmc->card_clock_enabled = 0;
|
||||
sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN;
|
||||
@@ -572,7 +575,7 @@ static int _sdmmc_setup_read_small_block(sdmmc_t *sdmmc)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, bool is_data_present)
|
||||
static int _sdmmc_send_cmd(sdmmc_t *sdmmc, const sdmmc_cmd_t *cmd, bool is_data_present)
|
||||
{
|
||||
u16 cmdflags = 0;
|
||||
|
||||
@@ -934,7 +937,7 @@ static u32 _sdmmc_check_mask_interrupt(sdmmc_t *sdmmc, u16 *pout, u16 mask)
|
||||
if (norintsts & SDHCI_INT_ERROR)
|
||||
{
|
||||
#ifdef ERROR_EXTRA_PRINTING
|
||||
EPRINTFARGS("SDMMC%d: norintsts %08X, errintsts %08X\n", sdmmc->id + 1, norintsts, errintsts);
|
||||
EPRINTFARGS("SDMMC%d: norintsts %08X, errintsts %08X", sdmmc->id + 1, norintsts, errintsts);
|
||||
#endif
|
||||
sdmmc->regs->errintsts = errintsts;
|
||||
return SDMMC_MASKINT_ERROR;
|
||||
@@ -1022,7 +1025,7 @@ int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp)
|
||||
return result;
|
||||
}
|
||||
|
||||
static int _sdmmc_config_sdma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req)
|
||||
static int _sdmmc_config_sdma(sdmmc_t *sdmmc, u32 *blkcnt_out, const sdmmc_req_t *req)
|
||||
{
|
||||
if (!req->blksize || !req->num_sectors)
|
||||
return 0;
|
||||
@@ -1152,7 +1155,7 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
|
||||
int result = _sdmmc_wait_response(sdmmc);
|
||||
#ifdef ERROR_EXTRA_PRINTING
|
||||
if (!result)
|
||||
EPRINTFARGS("SDMMC%d: Transfer timeout!", sdmmc->id + 1);
|
||||
EPRINTFARGS("SDMMC%d: Transfer error!", sdmmc->id + 1);
|
||||
#endif
|
||||
DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
|
||||
sdmmc->regs->rspreg0, sdmmc->regs->rspreg1, sdmmc->regs->rspreg2, sdmmc->regs->rspreg3);
|
||||
@@ -1273,16 +1276,7 @@ static int _sdmmc_config_sdmmc1(bool t210b01)
|
||||
if (!sdmmc_get_sd_inserted())
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Pinmux config:
|
||||
* DRV_TYPE = DRIVE_2X (for 33 Ohm driver)
|
||||
* E_SCHMT = ENABLE (for 1.8V), DISABLE (for 3.3V)
|
||||
* E_INPUT = ENABLE
|
||||
* TRISTATE = PASSTHROUGH
|
||||
* APB_MISC_GP_SDMMCx_CLK_LPBK_CONTROL = SDMMCx_CLK_PAD_E_LPBK for CLK
|
||||
*/
|
||||
|
||||
// Enable deep loopback for SDMMC1 CLK pad.
|
||||
// Enable deep loopback for SDMMC1 CLK pad so reads work.
|
||||
APB_MISC(APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL) = 1;
|
||||
|
||||
// Configure SDMMC1 CLK pinmux, based on state and SoC type.
|
||||
@@ -1302,18 +1296,18 @@ static int _sdmmc_config_sdmmc1(bool t210b01)
|
||||
_sdmmc_config_sdmmc1_schmitt();
|
||||
|
||||
// Make sure the SDMMC1 controller is powered.
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) |= PMC_NO_IOPOWER_SDMMC1_IO_EN;
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) |= PMC_NO_IOPOWER_SDMMC1;
|
||||
usleep(1000);
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) &= ~(PMC_NO_IOPOWER_SDMMC1_IO_EN);
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) &= ~PMC_NO_IOPOWER_SDMMC1;
|
||||
(void)PMC(APBDEV_PMC_NO_IOPOWER); // Commit write.
|
||||
|
||||
// Set enable SD card power.
|
||||
// Enable SD card power. Powers LDO2 also.
|
||||
PINMUX_AUX(PINMUX_AUX_DMIC3_CLK) = PINMUX_PULL_DOWN | 2;
|
||||
gpio_direction_output(GPIO_PORT_E, GPIO_PIN_4, GPIO_HIGH);
|
||||
usleep(10000);
|
||||
|
||||
// Inform IO pads that voltage is gonna be 3.3V.
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_SDMMC1_IO_EN;
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_33V_SDMMC1;
|
||||
(void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write.
|
||||
|
||||
// Enable SD card IO power.
|
||||
@@ -1366,8 +1360,8 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type)
|
||||
u16 divisor;
|
||||
u8 vref_sel = 7;
|
||||
|
||||
const u8 trim_values_t210[4] = { 2, 8, 3, 8 };
|
||||
const u8 trim_values_t210b01[4] = { 14, 13, 15, 13 };
|
||||
static const u8 trim_values_t210[4] = { 2, 8, 3, 8 };
|
||||
static const u8 trim_values_t210b01[4] = { 14, 13, 15, 13 };
|
||||
const u8 *trim_values;
|
||||
|
||||
if (id > SDMMC_4 || id == SDMMC_3)
|
||||
@@ -1403,19 +1397,18 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type)
|
||||
// Disable clock if enabled.
|
||||
if (clock_sdmmc_is_not_reset_and_enabled(id))
|
||||
{
|
||||
_sdmmc_sd_clock_disable(sdmmc);
|
||||
_sdmmc_card_clock_disable(sdmmc);
|
||||
_sdmmc_commit_changes(sdmmc);
|
||||
}
|
||||
|
||||
// Configure and enable selected clock.
|
||||
clock_sdmmc_get_card_clock_div(&clock, &divisor, type);
|
||||
clock_sdmmc_enable(id, clock);
|
||||
sdmmc->clock_stopped = 0;
|
||||
|
||||
// Make sure all sdmmc registers are reset.
|
||||
_sdmmc_reset_all(sdmmc);
|
||||
|
||||
sdmmc->clock_stopped = 0;
|
||||
|
||||
// Set default pad IO trimming configuration.
|
||||
sdmmc->regs->iospare |= BIT(19); // Enable 1 cycle delayed cmd_oen.
|
||||
sdmmc->regs->veniotrimctl &= ~BIT(2); // Set Band Gap VREG to supply DLL.
|
||||
@@ -1456,23 +1449,23 @@ void sdmmc1_disable_power()
|
||||
// T210B01 WAR: Set pads to discharge state.
|
||||
_sdmmc_config_sdmmc1_pads(true);
|
||||
|
||||
// Disable SD card IO power regulator.
|
||||
// Disable SD card IO power.
|
||||
max7762x_regulator_enable(REGULATOR_LDO2, false);
|
||||
usleep(4000);
|
||||
|
||||
// Disable SD card IO power pin.
|
||||
// Disable SD card power.
|
||||
gpio_write(GPIO_PORT_E, GPIO_PIN_4, GPIO_LOW);
|
||||
|
||||
// T210/T210B01 WAR: Set start timer for IO and Controller power discharge.
|
||||
sd_power_cycle_time_start = get_tmr_ms();
|
||||
usleep(1000); // To power cycle, min 1ms without power is needed.
|
||||
usleep(10000); // To power cycle, min 1ms without power is needed.
|
||||
|
||||
// Disable SDMMC1 controller power.
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) |= PMC_NO_IOPOWER_SDMMC1_IO_EN;
|
||||
PMC(APBDEV_PMC_NO_IOPOWER) |= PMC_NO_IOPOWER_SDMMC1;
|
||||
(void)PMC(APBDEV_PMC_NO_IOPOWER); // Commit write.
|
||||
|
||||
// Inform IO pads that next voltage might be 3.3V.
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_SDMMC1_IO_EN;
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_33V_SDMMC1;
|
||||
(void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write.
|
||||
|
||||
// T210B01 WAR: Restore pads to reset state.
|
||||
@@ -1486,7 +1479,7 @@ void sdmmc_end(sdmmc_t *sdmmc)
|
||||
{
|
||||
if (!sdmmc->clock_stopped)
|
||||
{
|
||||
_sdmmc_sd_clock_disable(sdmmc);
|
||||
_sdmmc_card_clock_disable(sdmmc);
|
||||
// Disable SDMMC power.
|
||||
_sdmmc_set_io_power(sdmmc, SDMMC_POWER_OFF);
|
||||
_sdmmc_commit_changes(sdmmc);
|
||||
@@ -1547,7 +1540,7 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc)
|
||||
usleep(150);
|
||||
|
||||
// Inform IO pads that we switched to 1.8V.
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) &= ~(PMC_PWR_DET_SDMMC1_IO_EN);
|
||||
PMC(APBDEV_PMC_PWR_DET_VAL) &= ~PMC_PWR_DET_33V_SDMMC1;
|
||||
(void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write.
|
||||
|
||||
// Enable schmitt trigger for better duty cycle and low jitter clock.
|
||||
|
||||
Reference in New Issue
Block a user