bdk: sdmmc: small refactor

This commit is contained in:
CTCaer
2025-01-24 15:30:10 +02:00
parent 5ce22a67dc
commit e030a4ad6d
5 changed files with 78 additions and 100 deletions

View File

@@ -55,7 +55,7 @@ static inline u32 unstuff_bits(const u32 *resp, u32 start, u32 size)
static int _sdmmc_storage_check_card_status(u32 res) static int _sdmmc_storage_check_card_status(u32 res)
{ {
//Error mask: //Error mask:
//TODO: R1_SWITCH_ERROR can be skipped for certain card types. //!WARN: R1_SWITCH_ERROR is reserved on SD. The card isn't supposed to use it.
if (res & if (res &
(R1_OUT_OF_RANGE | R1_ADDRESS_ERROR | R1_BLOCK_LEN_ERROR | (R1_OUT_OF_RANGE | R1_ADDRESS_ERROR | R1_BLOCK_LEN_ERROR |
R1_ERASE_SEQ_ERROR | R1_ERASE_PARAM | R1_WP_VIOLATION | R1_ERASE_SEQ_ERROR | R1_ERASE_PARAM | R1_WP_VIOLATION |
@@ -76,7 +76,7 @@ static int _sdmmc_storage_execute_cmd_type1_ex(sdmmc_storage_t *storage, u32 *re
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0; return 0;
sdmmc_get_rsp(storage->sdmmc, resp, 4, SDMMC_RSP_TYPE_1); sdmmc_get_cached_rsp(storage->sdmmc, resp, SDMMC_RSP_TYPE_1);
if (mask) if (mask)
*resp &= ~mask; *resp &= ~mask;
@@ -108,7 +108,7 @@ static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage)
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0; return 0;
sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_cid, 16, SDMMC_RSP_TYPE_2); sdmmc_get_cached_rsp(storage->sdmmc, (u32 *)storage->raw_cid, SDMMC_RSP_TYPE_2);
return 1; return 1;
} }
@@ -125,7 +125,7 @@ static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage)
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0; return 0;
sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_csd, 16, SDMMC_RSP_TYPE_2); sdmmc_get_cached_rsp(storage->sdmmc, (u32 *)storage->raw_csd, SDMMC_RSP_TYPE_2);
return 1; return 1;
} }
@@ -154,7 +154,7 @@ int sdmmc_storage_execute_vendor_cmd(sdmmc_storage_t *storage, u32 arg)
return 0; return 0;
u32 resp; u32 resp;
sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_1); sdmmc_get_cached_rsp(storage->sdmmc, &resp, SDMMC_RSP_TYPE_1);
resp = -1; resp = -1;
u32 timeout = get_tmr_ms() + 1500; u32 timeout = get_tmr_ms() + 1500;
@@ -405,7 +405,7 @@ static int _mmc_storage_get_op_cond_inner(sdmmc_storage_t *storage, u32 *pout, u
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0; return 0;
return sdmmc_get_rsp(storage->sdmmc, pout, 4, SDMMC_RSP_TYPE_3); return sdmmc_get_cached_rsp(storage->sdmmc, pout, SDMMC_RSP_TYPE_3);
} }
static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power) static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power)
@@ -543,7 +543,7 @@ int mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
return 0; return 0;
u32 tmp = 0; u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
_mmc_storage_parse_ext_csd(storage, buf); _mmc_storage_parse_ext_csd(storage, buf);
return _sdmmc_storage_check_card_status(tmp); return _sdmmc_storage_check_card_status(tmp);
@@ -934,7 +934,7 @@ static int _sd_storage_send_if_cond(sdmmc_storage_t *storage, bool *is_sdsc)
// For Card version >= 2.0, parse results. // For Card version >= 2.0, parse results.
u32 resp = 0; u32 resp = 0;
sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5); sdmmc_get_cached_rsp(storage->sdmmc, &resp, SDMMC_RSP_TYPE_5);
// Check if VHD was accepted and pattern was properly returned. // Check if VHD was accepted and pattern was properly returned.
if ((resp & 0xFFF) == vhd_pattern) if ((resp & 0xFFF) == vhd_pattern)
@@ -960,7 +960,7 @@ static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, boo
if (!_sd_storage_execute_app_cmd(storage, R1_SKIP_STATE_CHECK, is_sdsc ? R1_ILLEGAL_COMMAND : 0, &cmdbuf, NULL, NULL)) if (!_sd_storage_execute_app_cmd(storage, R1_SKIP_STATE_CHECK, is_sdsc ? R1_ILLEGAL_COMMAND : 0, &cmdbuf, NULL, NULL))
return 0; return 0;
return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3); return sdmmc_get_cached_rsp(storage->sdmmc, cond, SDMMC_RSP_TYPE_3);
} }
static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, bool is_sdsc, int bus_uhs_support) static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, bool is_sdsc, int bus_uhs_support)
@@ -983,7 +983,7 @@ static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, bool is_sdsc, int b
storage->has_sector_access = 1; storage->has_sector_access = 1;
// Check if card supports 1.8V signaling. // Check if card supports 1.8V signaling.
if (cond & SD_ROCR_S18A && bus_uhs_support) if (cond & SD_ROCR_S18A && bus_uhs_support && !storage->is_low_voltage)
{ {
// Switch to 1.8V signaling. // Switch to 1.8V signaling.
if (_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY)) if (_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
@@ -1027,7 +1027,7 @@ static int _sd_storage_get_rca(sdmmc_storage_t *storage)
break; break;
u32 resp = 0; u32 resp = 0;
if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_4)) if (!sdmmc_get_cached_rsp(storage->sdmmc, &resp, SDMMC_RSP_TYPE_4))
break; break;
if (resp >> 16) if (resp >> 16)
@@ -1058,7 +1058,7 @@ static void _sd_storage_parse_scr(sdmmc_storage_t *storage)
storage->scr.sda_vsn = unstuff_bits(resp, 56, 4); storage->scr.sda_vsn = unstuff_bits(resp, 56, 4);
storage->scr.bus_widths = unstuff_bits(resp, 48, 4); storage->scr.bus_widths = unstuff_bits(resp, 48, 4);
/* If v2.0 is supported, check if Physical Layer Spec v3.0 is supported */ // If v2.0 is supported, check if Physical Layer Spec v3.0 is supported.
if (storage->scr.sda_vsn == SCR_SPEC_VER_2) if (storage->scr.sda_vsn == SCR_SPEC_VER_2)
storage->scr.sda_spec3 = unstuff_bits(resp, 47, 1); storage->scr.sda_spec3 = unstuff_bits(resp, 47, 1);
if (storage->scr.sda_spec3) if (storage->scr.sda_spec3)
@@ -1082,9 +1082,9 @@ int sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf)
return 0; return 0;
u32 tmp = 0; u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
//Prepare buffer for unstuff_bits //Prepare buffer for unstuff_bits
for (int i = 0; i < 8; i+=4) for (u32 i = 0; i < 8; i+=4)
{ {
storage->raw_scr[i + 3] = buf[i]; storage->raw_scr[i + 3] = buf[i];
storage->raw_scr[i + 2] = buf[i + 1]; storage->raw_scr[i + 2] = buf[i + 1];
@@ -1113,7 +1113,7 @@ static int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf)
return 0; return 0;
u32 tmp = 0; u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
return _sdmmc_storage_check_card_status(tmp); return _sdmmc_storage_check_card_status(tmp);
} }
@@ -1137,7 +1137,7 @@ static int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int
return 0; return 0;
u32 tmp = 0; u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
return _sdmmc_storage_check_card_status(tmp); return _sdmmc_storage_check_card_status(tmp);
} }
@@ -1253,7 +1253,7 @@ static int _sd_storage_enable_DDR200(sdmmc_storage_t *storage, u8 *buf)
u16 total_pwr_consumption = ((u16)buf[0] << 8) | buf[1]; u16 total_pwr_consumption = ((u16)buf[0] << 8) | buf[1];
DPRINTF("[SD] max power: %d mW\n", total_pwr_consumption * 3600 / 1000); DPRINTF("[SD] max power: %d mW\n", total_pwr_consumption * 3600 / 1000);
storage->card_power_limit = total_pwr_consumption; storage->max_power = total_pwr_consumption;
if (total_pwr_consumption <= 800) if (total_pwr_consumption <= 800)
{ {
@@ -1292,7 +1292,7 @@ static int _sd_storage_set_card_bus_speed(sdmmc_storage_t *storage, u32 hs_type,
u16 total_pwr_consumption = ((u16)buf[0] << 8) | buf[1]; u16 total_pwr_consumption = ((u16)buf[0] << 8) | buf[1];
DPRINTF("[SD] max power: %d mW\n", total_pwr_consumption * 3600 / 1000); DPRINTF("[SD] max power: %d mW\n", total_pwr_consumption * 3600 / 1000);
storage->card_power_limit = total_pwr_consumption; storage->max_power = total_pwr_consumption;
if (total_pwr_consumption <= 800) if (total_pwr_consumption <= 800)
{ {
@@ -1556,10 +1556,10 @@ int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
return 0; return 0;
u32 tmp = 0; u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
// Convert buffer to LE. // Convert buffer to LE.
for (int i = 0; i < SDMMC_CMD_BLOCKSIZE; i += 4) for (u32 i = 0; i < SDMMC_CMD_BLOCKSIZE; i += 4)
{ {
storage->raw_ssr[i + 3] = buf[i]; storage->raw_ssr[i + 3] = buf[i];
storage->raw_ssr[i + 2] = buf[i + 1]; storage->raw_ssr[i + 2] = buf[i + 1];
@@ -1656,7 +1656,7 @@ void sdmmc_storage_init_wait_sd()
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type) int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
{ {
u32 tmp = 0; u32 tmp = 0;
int is_sdsc = 0; bool is_sdsc = 0;
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER; u8 *buf = (u8 *)SDMMC_UPPER_BUFFER;
bool bus_uhs_support = _sdmmc_storage_get_bus_uhs_support(bus_width, type); bool bus_uhs_support = _sdmmc_storage_get_bus_uhs_support(bus_width, type);
@@ -1801,7 +1801,7 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
return 0; return 0;
} }
if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_1)) if (!sdmmc_get_cached_rsp(storage->sdmmc, &resp, SDMMC_RSP_TYPE_1))
return 0; return 0;
if (!_sdmmc_storage_check_card_status(resp)) if (!_sdmmc_storage_check_card_status(resp))
return 0; return 0;

View File

@@ -181,13 +181,13 @@ typedef struct _sd_ssr
typedef struct _sdmmc_storage_t typedef struct _sdmmc_storage_t
{ {
sdmmc_t *sdmmc; sdmmc_t *sdmmc;
u32 rca;
int has_sector_access;
u32 sec_cnt;
int is_low_voltage;
u32 partition;
int initialized; int initialized;
u32 card_power_limit; int is_low_voltage;
int has_sector_access;
u32 rca;
u32 sec_cnt;
u32 partition;
u32 max_power;
u8 raw_cid[0x10]; u8 raw_cid[0x10];
u8 raw_csd[0x10]; u8 raw_csd[0x10];
u8 raw_scr[8]; u8 raw_scr[8];

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2024 CTCaer * Copyright (c) 2018-2025 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -212,7 +212,7 @@ static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power)
// Use 0x1F mask for all. // Use 0x1F mask for all.
u8 autocal_pu_status = sdmmc->regs->autocalsts & 0x1F; u8 autocal_pu_status = sdmmc->regs->autocalsts & 0x1F;
if (!autocal_pu_status) if (!autocal_pu_status)
EPRINTFARGS("SDMMC%d: Comp Pad open!", sdmmc->id + 1); EPRINTFARGS("SDMMC%d: Comp Pad open!", sdmmc->id + 1); // Or resistance is extreme.
else if (autocal_pu_status == 0x1F) else if (autocal_pu_status == 0x1F)
EPRINTFARGS("SDMMC%d: Comp Pad short to gnd!", sdmmc->id + 1); EPRINTFARGS("SDMMC%d: Comp Pad short to gnd!", sdmmc->id + 1);
#endif #endif
@@ -394,8 +394,8 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
static void _sdmmc_card_clock_enable(sdmmc_t *sdmmc) static void _sdmmc_card_clock_enable(sdmmc_t *sdmmc)
{ {
// Recalibrate conditionally. // Recalibrate periodically if needed.
if (sdmmc->manual_cal && !sdmmc->powersave_enabled) if (sdmmc->periodic_calibration && !sdmmc->powersave_enabled)
_sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc)); _sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc));
if (!sdmmc->powersave_enabled) if (!sdmmc->powersave_enabled)
@@ -414,8 +414,8 @@ static void _sdmmc_card_clock_disable(sdmmc_t *sdmmc)
void sdmmc_card_clock_powersave(sdmmc_t *sdmmc, int powersave_enable) void sdmmc_card_clock_powersave(sdmmc_t *sdmmc, int powersave_enable)
{ {
// Recalibrate periodically for SDMMC1. // Recalibrate periodically if needed.
if (sdmmc->manual_cal && !powersave_enable && sdmmc->card_clock_enabled) if (sdmmc->periodic_calibration && !powersave_enable && sdmmc->card_clock_enabled)
_sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc)); _sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc));
sdmmc->powersave_enabled = powersave_enable; sdmmc->powersave_enabled = powersave_enable;
@@ -431,7 +431,7 @@ void sdmmc_card_clock_powersave(sdmmc_t *sdmmc, int powersave_enable)
sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN;
} }
static int _sdmmc_cache_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type) static int _sdmmc_cache_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 type)
{ {
switch (type) switch (type)
{ {
@@ -439,33 +439,14 @@ static int _sdmmc_cache_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
case SDMMC_RSP_TYPE_3: case SDMMC_RSP_TYPE_3:
case SDMMC_RSP_TYPE_4: case SDMMC_RSP_TYPE_4:
case SDMMC_RSP_TYPE_5: case SDMMC_RSP_TYPE_5:
if (size < 4) rsp[0] = sdmmc->regs->rspreg[0];
return 0;
rsp[0] = sdmmc->regs->rspreg0;
break; break;
case SDMMC_RSP_TYPE_2: case SDMMC_RSP_TYPE_2:
if (size < 0x10)
return 0;
// CRC is stripped, so shifting is needed. // CRC is stripped, so shifting is needed.
u32 tempreg; for (u32 i = 0; i < 4; i++)
for (int i = 0; i < 4; i++)
{ {
switch(i) u32 tempreg = sdmmc->regs->rspreg[3 - i];
{
case 0:
tempreg = sdmmc->regs->rspreg3;
break;
case 1:
tempreg = sdmmc->regs->rspreg2;
break;
case 2:
tempreg = sdmmc->regs->rspreg1;
break;
case 3:
tempreg = sdmmc->regs->rspreg0;
break;
}
rsp[i] = tempreg << 8; rsp[i] = tempreg << 8;
if (i != 0) if (i != 0)
@@ -480,7 +461,7 @@ static int _sdmmc_cache_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
return 1; return 1;
} }
int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type) int sdmmc_get_cached_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 type)
{ {
if (!rsp || sdmmc->expected_rsp_type != type) if (!rsp || sdmmc->expected_rsp_type != type)
return 0; return 0;
@@ -491,18 +472,12 @@ int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
case SDMMC_RSP_TYPE_3: case SDMMC_RSP_TYPE_3:
case SDMMC_RSP_TYPE_4: case SDMMC_RSP_TYPE_4:
case SDMMC_RSP_TYPE_5: case SDMMC_RSP_TYPE_5:
if (size < 4)
return 0;
rsp[0] = sdmmc->rsp[0]; rsp[0] = sdmmc->rsp[0];
break; break;
case SDMMC_RSP_TYPE_2: case SDMMC_RSP_TYPE_2:
if (size < 16) for (u32 i = 0; i < 4; i++)
return 0; rsp[i] = sdmmc->rsp[i];
rsp[0] = sdmmc->rsp[0];
rsp[1] = sdmmc->rsp[1];
rsp[2] = sdmmc->rsp[2];
rsp[3] = sdmmc->rsp[3];
break; break;
default: default:
@@ -915,6 +890,7 @@ static void _sdmmc_enable_interrupts(sdmmc_t *sdmmc)
sdmmc->regs->errintstsen |= SDHCI_ERR_INT_ALL_EXCEPT_ADMA_BUSPWR; sdmmc->regs->errintstsen |= SDHCI_ERR_INT_ALL_EXCEPT_ADMA_BUSPWR;
sdmmc->regs->norintsts = sdmmc->regs->norintsts; sdmmc->regs->norintsts = sdmmc->regs->norintsts;
sdmmc->regs->errintsts = sdmmc->regs->errintsts; sdmmc->regs->errintsts = sdmmc->regs->errintsts;
sdmmc->error_sts = 0;
} }
static void _sdmmc_mask_interrupts(sdmmc_t *sdmmc) static void _sdmmc_mask_interrupts(sdmmc_t *sdmmc)
@@ -937,8 +913,9 @@ static u32 _sdmmc_check_mask_interrupt(sdmmc_t *sdmmc, u16 *pout, u16 mask)
if (norintsts & SDHCI_INT_ERROR) if (norintsts & SDHCI_INT_ERROR)
{ {
#ifdef ERROR_EXTRA_PRINTING #ifdef ERROR_EXTRA_PRINTING
EPRINTFARGS("SDMMC%d: norintsts %08X, errintsts %08X", sdmmc->id + 1, norintsts, errintsts); EPRINTFARGS("SDMMC%d: intsts %08X, errintsts %08X", sdmmc->id + 1, norintsts, errintsts);
#endif #endif
sdmmc->error_sts = errintsts;
sdmmc->regs->errintsts = errintsts; sdmmc->regs->errintsts = errintsts;
return SDMMC_MASKINT_ERROR; return SDMMC_MASKINT_ERROR;
} }
@@ -993,7 +970,7 @@ static int _sdmmc_stop_transmission_inner(sdmmc_t *sdmmc, u32 *rsp)
if (!result) if (!result)
return 0; return 0;
_sdmmc_cache_rsp(sdmmc, rsp, 4, SDMMC_RSP_TYPE_1); _sdmmc_cache_rsp(sdmmc, rsp, SDMMC_RSP_TYPE_1);
return _sdmmc_wait_card_busy(sdmmc); return _sdmmc_wait_card_busy(sdmmc);
} }
@@ -1003,8 +980,8 @@ int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp)
if (!sdmmc->card_clock_enabled) if (!sdmmc->card_clock_enabled)
return 0; return 0;
// Recalibrate periodically for SDMMC1. // Recalibrate periodically if needed.
if (sdmmc->manual_cal && sdmmc->powersave_enabled) if (sdmmc->periodic_calibration && sdmmc->powersave_enabled)
_sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc)); _sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc));
bool should_disable_sd_clock = false; bool should_disable_sd_clock = false;
@@ -1120,7 +1097,7 @@ static int _sdmmc_update_sdma(sdmmc_t *sdmmc)
static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out) static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out)
{ {
int has_req_or_check_busy = req || cmd->check_busy; bool has_req_or_check_busy = req || cmd->check_busy;
if (!_sdmmc_wait_cmd_data_inhibit(sdmmc, has_req_or_check_busy)) if (!_sdmmc_wait_cmd_data_inhibit(sdmmc, has_req_or_check_busy))
return 0; return 0;
@@ -1158,13 +1135,13 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
EPRINTFARGS("SDMMC%d: Transfer error!", sdmmc->id + 1); EPRINTFARGS("SDMMC%d: Transfer error!", sdmmc->id + 1);
#endif #endif
DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result, DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
sdmmc->regs->rspreg0, sdmmc->regs->rspreg1, sdmmc->regs->rspreg2, sdmmc->regs->rspreg3); sdmmc->regs->rspreg[0], sdmmc->regs->rspreg[1], sdmmc->regs->rspreg[2], sdmmc->regs->rspreg[3]);
if (result) if (result)
{ {
if (cmd->rsp_type) if (cmd->rsp_type)
{ {
sdmmc->expected_rsp_type = cmd->rsp_type; sdmmc->expected_rsp_type = cmd->rsp_type;
result = _sdmmc_cache_rsp(sdmmc, sdmmc->rsp, 0x10, cmd->rsp_type); result = _sdmmc_cache_rsp(sdmmc, sdmmc->rsp, cmd->rsp_type);
#ifdef ERROR_EXTRA_PRINTING #ifdef ERROR_EXTRA_PRINTING
if (!result) if (!result)
EPRINTFARGS("SDMMC%d: Unknown response type!", sdmmc->id + 1); EPRINTFARGS("SDMMC%d: Unknown response type!", sdmmc->id + 1);
@@ -1193,10 +1170,10 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
*blkcnt_out = blkcnt; *blkcnt_out = blkcnt;
if (req->is_auto_stop_trn) if (req->is_auto_stop_trn)
sdmmc->rsp3 = sdmmc->regs->rspreg3; sdmmc->stop_trn_rsp = sdmmc->regs->rspreg[3];
} }
if (cmd->check_busy || req) if (has_req_or_check_busy)
{ {
result = _sdmmc_wait_card_busy(sdmmc); result = _sdmmc_wait_card_busy(sdmmc);
#ifdef ERROR_EXTRA_PRINTING #ifdef ERROR_EXTRA_PRINTING
@@ -1248,7 +1225,7 @@ static void _sdmmc_config_sdmmc1_pads(bool discharge)
u32 level = GPIO_LOW; u32 level = GPIO_LOW;
u32 output = GPIO_OUTPUT_DISABLE; u32 output = GPIO_OUTPUT_DISABLE;
// Set values for dicharging. // Set values for discharging.
if (discharge) if (discharge)
{ {
function = GPIO_MODE_GPIO; function = GPIO_MODE_GPIO;
@@ -1304,7 +1281,7 @@ static int _sdmmc_config_sdmmc1(bool t210b01)
// Enable SD card power. Powers LDO2 also. // Enable SD card power. Powers LDO2 also.
PINMUX_AUX(PINMUX_AUX_DMIC3_CLK) = PINMUX_PULL_DOWN | 2; PINMUX_AUX(PINMUX_AUX_DMIC3_CLK) = PINMUX_PULL_DOWN | 2;
gpio_direction_output(GPIO_PORT_E, GPIO_PIN_4, GPIO_HIGH); gpio_direction_output(GPIO_PORT_E, GPIO_PIN_4, GPIO_HIGH);
usleep(10000); usleep(10000); // Minimum 3 to 10 ms.
// Inform IO pads that voltage is gonna be 3.3V. // Inform IO pads that voltage is gonna be 3.3V.
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_33V_SDMMC1; PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_33V_SDMMC1;
@@ -1385,7 +1362,7 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type)
if (sdmmc->t210b01) if (sdmmc->t210b01)
vref_sel = 0; vref_sel = 0;
else else
sdmmc->manual_cal = 1; sdmmc->periodic_calibration = 1;
break; break;
case SDMMC_2: case SDMMC_2:
@@ -1419,6 +1396,8 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type)
if (!_sdmmc_autocal_config_offset(sdmmc, power)) if (!_sdmmc_autocal_config_offset(sdmmc, power))
return 0; return 0;
_sdmmc_commit_changes(sdmmc);
// Calibrate pads. // Calibrate pads.
_sdmmc_autocal_execute(sdmmc, power); _sdmmc_autocal_execute(sdmmc, power);
@@ -1506,8 +1485,8 @@ int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *b
if (!sdmmc->card_clock_enabled) if (!sdmmc->card_clock_enabled)
return 0; return 0;
// Recalibrate periodically for SDMMC1. // Recalibrate periodically if needed.
if (sdmmc->manual_cal && sdmmc->powersave_enabled) if (sdmmc->periodic_calibration && sdmmc->powersave_enabled)
_sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc)); _sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc));
int should_disable_sd_clock = 0; int should_disable_sd_clock = 0;

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2023 CTCaer * Copyright (c) 2018-2025 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -101,6 +101,7 @@
#define SDHCI_CMD_TYPE_SUSPEND (1U << 6) #define SDHCI_CMD_TYPE_SUSPEND (1U << 6)
#define SDHCI_CMD_TYPE_RESUME (2U << 6) #define SDHCI_CMD_TYPE_RESUME (2U << 6)
#define SDHCI_CMD_TYPE_ABORT (3U << 6) #define SDHCI_CMD_TYPE_ABORT (3U << 6)
#define SDHCI_CMD_SPI_CS_LOW BIT(7)
#define SDHCI_CMD_IDX(cmd) ((cmd) << 8) #define SDHCI_CMD_IDX(cmd) ((cmd) << 8)
@@ -170,10 +171,10 @@
#define SDHCI_INT_ERROR BIT(15) #define SDHCI_INT_ERROR BIT(15)
/*! SDMMC error interrupt status and control. 0x32/0x36. */ /*! SDMMC error interrupt status and control. 0x32/0x36. */
#define SDHCI_ERR_INT_TIMEOUT BIT(0) #define SDHCI_ERR_INT_CMD_TIMEOUT BIT(0)
#define SDHCI_ERR_INT_CRC BIT(1) #define SDHCI_ERR_INT_CMD_CRC BIT(1)
#define SDHCI_ERR_INT_END_BIT BIT(2) #define SDHCI_ERR_INT_CMD_END_BIT BIT(2)
#define SDHCI_ERR_INT_INDEX BIT(3) #define SDHCI_ERR_INT_CMD_INDEX BIT(3)
#define SDHCI_ERR_INT_DATA_TIMEOUT BIT(4) #define SDHCI_ERR_INT_DATA_TIMEOUT BIT(4)
#define SDHCI_ERR_INT_DATA_CRC BIT(5) #define SDHCI_ERR_INT_DATA_CRC BIT(5)
#define SDHCI_ERR_INT_DATA_END_BIT BIT(6) #define SDHCI_ERR_INT_DATA_END_BIT BIT(6)
@@ -190,8 +191,8 @@
#define SDHCI_ERR_INT_ALL_EXCEPT_ADMA_BUSPWR \ #define SDHCI_ERR_INT_ALL_EXCEPT_ADMA_BUSPWR \
(SDHCI_ERR_INT_AUTO_CMD12 | SDHCI_ERR_INT_DATA_END_BIT | \ (SDHCI_ERR_INT_AUTO_CMD12 | SDHCI_ERR_INT_DATA_END_BIT | \
SDHCI_ERR_INT_DATA_CRC | SDHCI_ERR_INT_DATA_TIMEOUT | \ SDHCI_ERR_INT_DATA_CRC | SDHCI_ERR_INT_DATA_TIMEOUT | \
SDHCI_ERR_INT_INDEX | SDHCI_ERR_INT_END_BIT | \ SDHCI_ERR_INT_CMD_INDEX | SDHCI_ERR_INT_CMD_END_BIT | \
SDHCI_ERR_INT_CRC | SDHCI_ERR_INT_TIMEOUT) SDHCI_ERR_INT_CMD_CRC | SDHCI_ERR_INT_CMD_TIMEOUT)
/*! Host Capability 1. 0x40. */ /*! Host Capability 1. 0x40. */
#define SDHCI_CAP_TM_CLK_FREQ_MASK 0x3F #define SDHCI_CAP_TM_CLK_FREQ_MASK 0x3F
@@ -285,14 +286,15 @@ typedef struct _sdmmc_t
u32 card_clock; u32 card_clock;
u32 clock_stopped; u32 clock_stopped;
int powersave_enabled; int powersave_enabled;
int manual_cal; int periodic_calibration;
int card_clock_enabled; int card_clock_enabled;
int venclkctl_set; int venclkctl_set;
u32 venclkctl_tap; u32 venclkctl_tap;
u32 expected_rsp_type; u32 expected_rsp_type;
u32 dma_addr_next; u32 dma_addr_next;
u32 rsp[4]; u32 rsp[4];
u32 rsp3; u32 stop_trn_rsp;
u32 error_sts;
int t210b01; int t210b01;
} sdmmc_t; } sdmmc_t;
@@ -323,7 +325,7 @@ void sdmmc_save_tap_value(sdmmc_t *sdmmc);
void sdmmc_setup_drv_type(sdmmc_t *sdmmc, u32 type); void sdmmc_setup_drv_type(sdmmc_t *sdmmc, u32 type);
int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type); int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type);
void sdmmc_card_clock_powersave(sdmmc_t *sdmmc, int powersave_enable); void sdmmc_card_clock_powersave(sdmmc_t *sdmmc, int powersave_enable);
int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type); int sdmmc_get_cached_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 type);
int sdmmc_tuning_execute(sdmmc_t *sdmmc, u32 type, u32 cmd); int sdmmc_tuning_execute(sdmmc_t *sdmmc, u32 type, u32 cmd);
int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp); int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp);
bool sdmmc_get_sd_inserted(); bool sdmmc_get_sd_inserted();

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2023 CTCaer * Copyright (c) 2018-2025 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -39,10 +39,7 @@ typedef struct _t210_sdmmc_t
/* 0x08 */ vu32 argument; /* 0x08 */ vu32 argument;
/* 0x0C */ vu16 trnmod; /* 0x0C */ vu16 trnmod;
/* 0x0E */ vu16 cmdreg; /* 0x0E */ vu16 cmdreg;
/* 0x10 */ vu32 rspreg0; /* 0x10 */ vu32 rspreg[4];
/* 0x14 */ vu32 rspreg1;
/* 0x18 */ vu32 rspreg2;
/* 0x1C */ vu32 rspreg3;
/* 0x20 */ vu32 bdata; // Buffer data port. /* 0x20 */ vu32 bdata; // Buffer data port.
/* 0x24 */ vu32 prnsts; /* 0x24 */ vu32 prnsts;
/* 0x28 */ vu8 hostctl; /* 0x28 */ vu8 hostctl;