uplift bdk

Signed-off-by: Damien Zhao <zdm65477730@126.com>
This commit is contained in:
Damien Zhao
2023-04-02 13:21:57 +08:00
parent cf553f87dd
commit c9b22b2a36
24 changed files with 868 additions and 467 deletions

View File

@@ -76,7 +76,7 @@ static void _display_dsi_wait_vblank(bool enable)
} }
else else
{ {
// Wait for vblank before reseting sync points. // Wait for vblank before resetting sync points.
DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT; // Clear interrupt. DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT; // Clear interrupt.
while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT)) while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT))
; ;

View File

@@ -401,23 +401,29 @@ static int touch_init()
int touch_power_on() int touch_power_on()
{ {
// Enable LDO6 for touchscreen AVDD supply.
max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000);
max7762x_regulator_enable(REGULATOR_LDO6, true);
// Configure touchscreen VDD GPIO.
PINMUX_AUX(PINMUX_AUX_DAP4_SCLK) = PINMUX_PULL_DOWN | 1;
gpio_direction_output(GPIO_PORT_J, GPIO_PIN_7, GPIO_HIGH);
// Configure Touscreen and GCAsic shared GPIO. // Configure Touscreen and GCAsic shared GPIO.
PINMUX_AUX(PINMUX_AUX_CAM_I2C_SDA) = PINMUX_LPDR | PINMUX_INPUT_ENABLE | PINMUX_TRISTATE | PINMUX_PULL_UP | 2; PINMUX_AUX(PINMUX_AUX_CAM_I2C_SDA) = PINMUX_LPDR | PINMUX_INPUT_ENABLE | PINMUX_TRISTATE | PINMUX_PULL_UP | 2;
PINMUX_AUX(PINMUX_AUX_CAM_I2C_SCL) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_TRISTATE | PINMUX_PULL_DOWN | 2; PINMUX_AUX(PINMUX_AUX_CAM_I2C_SCL) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_TRISTATE | PINMUX_PULL_DOWN | 2; // Unused.
gpio_config(GPIO_PORT_S, GPIO_PIN_3, GPIO_MODE_GPIO); // GC detect. gpio_config(GPIO_PORT_S, GPIO_PIN_3, GPIO_MODE_GPIO); // GC detect.
// Configure touchscreen Touch Reset pin.
PINMUX_AUX(PINMUX_AUX_DAP4_SCLK) = PINMUX_PULL_DOWN | 1;
gpio_direction_output(GPIO_PORT_J, GPIO_PIN_7, GPIO_LOW);
usleep(20);
// Enable LDO6 for touchscreen AVDD and DVDD supply.
max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000);
max7762x_regulator_enable(REGULATOR_LDO6, true);
// Initialize I2C3. // Initialize I2C3.
pinmux_config_i2c(I2C_3); pinmux_config_i2c(I2C_3);
clock_enable_i2c(I2C_3); clock_enable_i2c(I2C_3);
i2c_init(I2C_3); i2c_init(I2C_3);
usleep(1000);
// Set Touch Reset pin.
gpio_write(GPIO_PORT_J, GPIO_PIN_7, GPIO_HIGH);
usleep(10000);
// Wait for the touchscreen module to get ready. // Wait for the touchscreen module to get ready.
touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20, NULL); touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20, NULL);

View File

@@ -149,7 +149,7 @@
/*HAL settings*/ /*HAL settings*/
#define LV_TICK_CUSTOM 1 /*1: use a custom tick source (removing the need to manually update the tick with `lv_tick_inc`) */ #define LV_TICK_CUSTOM 1 /*1: use a custom tick source (removing the need to manually update the tick with `lv_tick_inc`) */
#if LV_TICK_CUSTOM == 1 #if LV_TICK_CUSTOM == 1
#define LV_TICK_CUSTOM_INCLUDE <utils/util.h> /*Header for the sys time function*/ #define LV_TICK_CUSTOM_INCLUDE <soc/timer.h> /*Header for the sys time function*/
#define LV_TICK_CUSTOM_SYS_TIME_EXPR (get_tmr_ms()) /*Expression evaluating to current systime in ms*/ #define LV_TICK_CUSTOM_SYS_TIME_EXPR (get_tmr_ms()) /*Expression evaluating to current systime in ms*/
#endif /*LV_TICK_CUSTOM*/ #endif /*LV_TICK_CUSTOM*/

View File

@@ -20,13 +20,11 @@
#include <utils/types.h> #include <utils/types.h>
#define TSEC_KEY_DATA_OFFSET 0x300
enum tsec_fw_type enum tsec_fw_type
{ {
// Retail Hovi Keygen. // Retail Hovi Keygen.
TSEC_FW_TYPE_OLD = 0, // 1.0.0 - 6.1.0. TSEC_FW_TYPE_OLD = 0, // 1.0.0 - 6.1.0.
TSEC_FW_TYPE_EMU = 1, // 6.2.0 emulated enviroment. TSEC_FW_TYPE_EMU = 1, // 6.2.0 emulated environment.
TSEC_FW_TYPE_NEW = 2, // 7.0.0+. TSEC_FW_TYPE_NEW = 2, // 7.0.0+.
}; };
@@ -40,23 +38,6 @@ typedef struct _tsec_ctxt_t
u32 secmon_base; u32 secmon_base;
} tsec_ctxt_t; } tsec_ctxt_t;
typedef struct _tsec_key_data_t
{
u8 debug_key[0x10];
u8 blob0_auth_hash[0x10];
u8 blob1_auth_hash[0x10];
u8 blob2_auth_hash[0x10];
u8 blob2_aes_iv[0x10];
u8 hovi_eks_seed[0x10];
u8 hovi_common_seed[0x10];
u32 blob0_size;
u32 blob1_size;
u32 blob2_size;
u32 blob3_size;
u32 blob4_size;
u8 reserved[0x7C];
} tsec_key_data_t;
int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt); int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt);
#endif #endif

View File

@@ -39,9 +39,9 @@ static const clock_osc_t _clock_osc_cnt[] = {
{ 48000, 2836, 3023 } { 48000, 2836, 3023 }
}; };
/* clock_t: reset, enable, source, index, clk_src, clk_div */ /* clk_rst_t: reset, enable, source, index, clk_src, clk_div */
static const clock_t _clock_uart[] = { static const clk_rst_t _clock_uart[] = {
{ CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTA, CLK_L_UARTA, 0, 2 }, { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTA, CLK_L_UARTA, 0, 2 },
{ CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTB, CLK_L_UARTB, 0, 2 }, { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTB, CLK_L_UARTB, 0, 2 },
{ CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_UARTC, CLK_H_UARTC, 0, 2 }, { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_UARTC, CLK_H_UARTC, 0, 2 },
@@ -50,7 +50,7 @@ static const clock_t _clock_uart[] = {
}; };
//I2C default parameters - TLOW: 4, THIGH: 2, DEBOUNCE: 0, FM_DIV: 26. //I2C default parameters - TLOW: 4, THIGH: 2, DEBOUNCE: 0, FM_DIV: 26.
static const clock_t _clock_i2c[] = { static const clk_rst_t _clock_i2c[] = {
{ CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_I2C1, CLK_L_I2C1, 0, 19 }, //20.4MHz -> 100KHz { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_I2C1, CLK_L_I2C1, 0, 19 }, //20.4MHz -> 100KHz
{ CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C2, CLK_H_I2C2, 0, 4 }, //81.6MHz -> 400KHz { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C2, CLK_H_I2C2, 0, 4 }, //81.6MHz -> 400KHz
{ CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_I2C3, CLK_U_I2C3, 0, 4 }, //81.6MHz -> 400KHz { CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_I2C3, CLK_U_I2C3, 0, 4 }, //81.6MHz -> 400KHz
@@ -59,68 +59,68 @@ static const clock_t _clock_i2c[] = {
{ CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_I2C6, CLK_X_I2C6, 0, 19 } //20.4MHz -> 100KHz { CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_I2C6, CLK_X_I2C6, 0, 19 } //20.4MHz -> 100KHz
}; };
static clock_t _clock_se = { static clk_rst_t _clock_se = {
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, CLK_V_SE, 0, 0 // 408MHz. Default: 408MHz. Max: 627.2 MHz. CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, CLK_V_SE, 0, 0 // 408MHz. Default: 408MHz. Max: 627.2 MHz.
}; };
static clock_t _clock_tzram = { static clk_rst_t _clock_tzram = {
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_NO_SOURCE, CLK_V_TZRAM, 0, 0 CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_NO_SOURCE, CLK_V_TZRAM, 0, 0
}; };
static clock_t _clock_host1x = { static clk_rst_t _clock_host1x = {
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_L_HOST1X, 4, 3 // 163.2MHz. Max: 408MHz. CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_L_HOST1X, 4, 3 // 163.2MHz. Max: 408MHz.
}; };
static clock_t _clock_tsec = { static clk_rst_t _clock_tsec = {
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, CLK_U_TSEC, 0, 2 // 204MHz. Max: 408MHz. CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, CLK_U_TSEC, 0, 2 // 204MHz. Max: 408MHz.
}; };
static clock_t _clock_nvdec = { static clk_rst_t _clock_nvdec = {
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_NVDEC, CLK_Y_NVDEC, 4, 0 // 408 MHz. Max: 716.8/979.2MHz. CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_NVDEC, CLK_Y_NVDEC, 4, 0 // 408 MHz. Max: 716.8/979.2MHz.
}; };
static clock_t _clock_nvjpg = { static clk_rst_t _clock_nvjpg = {
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_NVJPG, CLK_Y_NVJPG, 4, 0 // 408 MHz. Max: 627.2/652.8MHz. CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_NVJPG, CLK_Y_NVJPG, 4, 0 // 408 MHz. Max: 627.2/652.8MHz.
}; };
static clock_t _clock_vic = { static clk_rst_t _clock_vic = {
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_VIC, CLK_X_VIC, 2, 0 // 408 MHz. Max: 627.2/652.8MHz. CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_VIC, CLK_X_VIC, 2, 0 // 408 MHz. Max: 627.2/652.8MHz.
}; };
static clock_t _clock_sor_safe = { static clk_rst_t _clock_sor_safe = {
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_NO_SOURCE, CLK_Y_SOR_SAFE, 0, 0 CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_NO_SOURCE, CLK_Y_SOR_SAFE, 0, 0
}; };
static clock_t _clock_sor0 = { static clk_rst_t _clock_sor0 = {
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NOT_USED, CLK_X_SOR0, 0, 0 CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NOT_USED, CLK_X_SOR0, 0, 0
}; };
static clock_t _clock_sor1 = { static clk_rst_t _clock_sor1 = {
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_X_SOR1, 0, 2 // 204MHz. CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_X_SOR1, 0, 2 // 204MHz.
}; };
static clock_t _clock_kfuse = { static clk_rst_t _clock_kfuse = {
CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_KFUSE, 0, 0 CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_KFUSE, 0, 0
}; };
static clock_t _clock_cl_dvfs = { static clk_rst_t _clock_cl_dvfs = {
CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_NO_SOURCE, CLK_W_DVFS, 0, 0 CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_NO_SOURCE, CLK_W_DVFS, 0, 0
}; };
static clock_t _clock_coresight = { static clk_rst_t _clock_coresight = {
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, CLK_U_CSITE, 0, 4 // 136MHz. CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, CLK_U_CSITE, 0, 4 // 136MHz.
}; };
static clock_t _clock_pwm = { static clk_rst_t _clock_pwm = {
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, CLK_L_PWM, 6, 4 // Fref: 6.4MHz. HOS: PLLP / 54 = 7.55MHz. CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, CLK_L_PWM, 6, 4 // Fref: 6.4MHz. HOS: PLLP / 54 = 7.55MHz.
}; };
static clock_t _clock_sdmmc_legacy_tm = { static clk_rst_t _clock_sdmmc_legacy_tm = {
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM, CLK_Y_SDMMC_LEGACY_TM, 4, 66 CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM, CLK_Y_SDMMC_LEGACY_TM, 4, 66
}; };
static clock_t _clock_apbdma = { static clk_rst_t _clock_apbdma = {
CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_APBDMA, 0, 0 // Max: 204MHz. CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_APBDMA, 0, 0 // Max: 204MHz.
}; };
static clock_t _clock_ahbdma = { static clk_rst_t _clock_ahbdma = {
CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_AHBDMA, 0, 0 CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_AHBDMA, 0, 0
}; };
static clock_t _clock_actmon = { static clk_rst_t _clock_actmon = {
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_ACTMON, CLK_V_ACTMON, 6, 0 // 19.2MHz. CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_ACTMON, CLK_V_ACTMON, 6, 0 // 19.2MHz.
}; };
static clock_t _clock_extperiph1 = { static clk_rst_t _clock_extperiph1 = {
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH1, CLK_V_EXTPERIPH1, 0, 0 CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH1, CLK_V_EXTPERIPH1, 0, 0
}; };
static clock_t _clock_extperiph2 = { static clk_rst_t _clock_extperiph2 = {
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH2, CLK_V_EXTPERIPH2, 2, 202 // 4.0MHz CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH2, CLK_V_EXTPERIPH2, 2, 202 // 4.0MHz
}; };
void clock_enable(const clock_t *clk) void clock_enable(const clk_rst_t *clk)
{ {
// Put clock into reset. // Put clock into reset.
CLOCK(clk->reset) = (CLOCK(clk->reset) & ~BIT(clk->index)) | BIT(clk->index); CLOCK(clk->reset) = (CLOCK(clk->reset) & ~BIT(clk->index)) | BIT(clk->index);
@@ -137,7 +137,7 @@ void clock_enable(const clock_t *clk)
CLOCK(clk->reset) &= ~BIT(clk->index); CLOCK(clk->reset) &= ~BIT(clk->index);
} }
void clock_disable(const clock_t *clk) void clock_disable(const clk_rst_t *clk)
{ {
// Put clock into reset. // Put clock into reset.
CLOCK(clk->reset) = (CLOCK(clk->reset) & ~BIT(clk->index)) | BIT(clk->index); CLOCK(clk->reset) = (CLOCK(clk->reset) & ~BIT(clk->index)) | BIT(clk->index);
@@ -503,7 +503,7 @@ static void _clock_enable_pllc4(u32 mask)
usleep(10); usleep(10);
// Set PLLC4 dividers. // Set PLLC4 dividers.
CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) = (104 << 8) | 4; // DIVM: 4, DIVP: 1. CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) = (0 << 19) | (104 << 8) | 4; // DIVP: 1, DIVN: 104, DIVM: 4. 998MHz OUT0, 199MHz OUT2.
// Enable PLLC4 and wait for Phase and Frequency lock. // Enable PLLC4 and wait for Phase and Frequency lock.
CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) |= PLLCX_BASE_ENABLE; CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) |= PLLCX_BASE_ENABLE;
@@ -684,7 +684,7 @@ static void _clock_sdmmc_clear_enable(u32 id)
static void _clock_sdmmc_config_legacy_tm() static void _clock_sdmmc_config_legacy_tm()
{ {
clock_t *clk = &_clock_sdmmc_legacy_tm; clk_rst_t *clk = &_clock_sdmmc_legacy_tm;
if (!(CLOCK(clk->enable) & BIT(clk->index))) if (!(CLOCK(clk->enable) & BIT(clk->index)))
clock_enable(clk); clock_enable(clk);
} }
@@ -699,6 +699,7 @@ static clock_sdmmc_t _clock_sdmmc_table[4] = { 0 };
#define SDMMC_CLOCK_SRC_PLLP_OUT0 0x0 #define SDMMC_CLOCK_SRC_PLLP_OUT0 0x0
#define SDMMC_CLOCK_SRC_PLLC4_OUT2 0x3 #define SDMMC_CLOCK_SRC_PLLC4_OUT2 0x3
#define SDMMC_CLOCK_SRC_PLLC4_OUT0 0x7
#define SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ 0x1 #define SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ 0x1
static int _clock_sdmmc_config_clock_host(u32 *pclock, u32 id, u32 val) static int _clock_sdmmc_config_clock_host(u32 *pclock, u32 id, u32 val)
@@ -716,79 +717,88 @@ static int _clock_sdmmc_config_clock_host(u32 *pclock, u32 id, u32 val)
*pclock = 24728; *pclock = 24728;
divisor = 31; // 16.5 div. divisor = 31; // 16.5 div.
break; break;
case 26000: case 26000:
*pclock = 25500; *pclock = 25500;
divisor = 30; // 16 div. divisor = 30; // 16 div.
break; break;
case 50000: case 50000:
*pclock = 48000; *pclock = 48000;
divisor = 15; // 8.5 div. divisor = 15; // 8.5 div.
break; break;
case 52000: case 52000:
*pclock = 51000; *pclock = 51000;
divisor = 14; // 8 div. divisor = 14; // 8 div.
break; break;
case 81600: // Originally MMC_HS50 for GC FPGA at 40800 KHz, div 18 (real 10).
case 82000:
*pclock = 81600; *pclock = 81600;
divisor = 8; // 5 div. divisor = 8; // 5 div.
break; break;
case 100000: case 100000:
source = SDMMC_CLOCK_SRC_PLLC4_OUT2; source = SDMMC_CLOCK_SRC_PLLC4_OUT2;
*pclock = 99840; *pclock = 99840;
divisor = 2; // 2 div. divisor = 2; // 2 div.
break; break;
case 164000: case 164000:
*pclock = 163200; *pclock = 163200;
divisor = 3; // 2.5 div. divisor = 3; // 2.5 div.
break; break;
case 200000: // 240MHz evo+.
case 200000:
switch (id) switch (id)
{ {
case SDMMC_1: case SDMMC_1:
source = SDMMC_CLOCK_SRC_PLLC4_OUT2;
break;
case SDMMC_2:
source = SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ;
break;
case SDMMC_3: case SDMMC_3:
source = SDMMC_CLOCK_SRC_PLLC4_OUT2; source = SDMMC_CLOCK_SRC_PLLC4_OUT2;
break; break;
case SDMMC_2:
case SDMMC_4: case SDMMC_4:
source = SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ; source = SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ; // div is ignored.
break; break;
} }
*pclock = 199680; *pclock = 199680;
divisor = 0; // 1 div. divisor = 0; // 1 div.
break; break;
default:
*pclock = 24728; #ifdef BDK_SDMMC_UHS_DDR200_SUPPORT
divisor = 31; // 16.5 div. case 400000:
source = SDMMC_CLOCK_SRC_PLLC4_OUT0;
*pclock = 399360;
divisor = 3; // 2.5 div
break;
#endif
} }
_clock_sdmmc_table[id].clock = val; _clock_sdmmc_table[id].clock = val;
_clock_sdmmc_table[id].real_clock = *pclock; _clock_sdmmc_table[id].real_clock = *pclock;
// Enable PLLC4 if in use by any SDMMC. // Enable PLLC4 if in use by any SDMMC.
if (source) if (source != SDMMC_CLOCK_SRC_PLLP_OUT0)
_clock_enable_pllc4(BIT(id)); _clock_enable_pllc4(BIT(id));
// Set SDMMC legacy timeout clock. // Set SDMMC legacy timeout clock.
_clock_sdmmc_config_legacy_tm(); _clock_sdmmc_config_legacy_tm();
// Set SDMMC clock. // Set SDMMC clock.
u32 src_div = (source << 29) | divisor;
switch (id) switch (id)
{ {
case SDMMC_1: case SDMMC_1:
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC1) = (source << 29) | divisor; CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC1) = src_div;
break; break;
case SDMMC_2: case SDMMC_2:
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC2) = (source << 29) | divisor; CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC2) = src_div;
break; break;
case SDMMC_3: case SDMMC_3:
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3) = (source << 29) | divisor; CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3) = src_div;
break; break;
case SDMMC_4: case SDMMC_4:
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC4) = (source << 29) | divisor; CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC4) = src_div;
break; break;
} }
@@ -818,54 +828,71 @@ void clock_sdmmc_get_card_clock_div(u32 *pclock, u16 *pdivisor, u32 type)
// Get Card clock divisor. // Get Card clock divisor.
switch (type) switch (type)
{ {
case SDHCI_TIMING_MMC_ID: // Actual IO Freq: 380.59 KHz. case SDHCI_TIMING_MMC_ID: // Actual card clock: 386.36 KHz.
*pclock = 26000; *pclock = 26000;
*pdivisor = 66; *pdivisor = 66;
break; break;
case SDHCI_TIMING_MMC_LS26: case SDHCI_TIMING_MMC_LS26:
*pclock = 26000; *pclock = 26000;
*pdivisor = 1; *pdivisor = 1;
break; break;
case SDHCI_TIMING_MMC_HS52: case SDHCI_TIMING_MMC_HS52:
*pclock = 52000; *pclock = 52000;
*pdivisor = 1; *pdivisor = 1;
break; break;
case SDHCI_TIMING_MMC_HS200: case SDHCI_TIMING_MMC_HS200:
case SDHCI_TIMING_MMC_HS400: case SDHCI_TIMING_MMC_HS400:
case SDHCI_TIMING_UHS_SDR104: case SDHCI_TIMING_UHS_SDR104:
*pclock = 200000; *pclock = 200000;
*pdivisor = 1; *pdivisor = 1;
break; break;
case SDHCI_TIMING_SD_ID: // Actual IO Freq: 380.43 KHz.
case SDHCI_TIMING_SD_ID: // Actual card clock: 386.38 KHz.
*pclock = 25000; *pclock = 25000;
*pdivisor = 64; *pdivisor = 64;
break; break;
case SDHCI_TIMING_SD_DS12: case SDHCI_TIMING_SD_DS12:
case SDHCI_TIMING_UHS_SDR12: case SDHCI_TIMING_UHS_SDR12:
*pclock = 25000; *pclock = 25000;
*pdivisor = 1; *pdivisor = 1;
break; break;
case SDHCI_TIMING_SD_HS25: case SDHCI_TIMING_SD_HS25:
case SDHCI_TIMING_UHS_SDR25: case SDHCI_TIMING_UHS_SDR25:
*pclock = 50000; *pclock = 50000;
*pdivisor = 1; *pdivisor = 1;
break; break;
case SDHCI_TIMING_UHS_SDR50: case SDHCI_TIMING_UHS_SDR50:
*pclock = 100000; *pclock = 100000;
*pdivisor = 1; *pdivisor = 1;
break; break;
case SDHCI_TIMING_UHS_SDR82: case SDHCI_TIMING_UHS_SDR82:
*pclock = 164000; *pclock = 164000;
*pdivisor = 1; *pdivisor = 1;
break; break;
case SDHCI_TIMING_UHS_DDR50:
*pclock = 81600; // Originally MMC_HS50 for GC FPGA at 40800 KHz, div 1. case SDHCI_TIMING_UHS_DDR50: // Actual card clock: 40.80 MHz.
*pclock = 82000;
*pdivisor = 2; *pdivisor = 2;
break; break;
case SDHCI_TIMING_MMC_DDR100: // Actual IO Freq: 99.84 MHz.
case SDHCI_TIMING_MMC_HS100: // Actual card clock: 99.84 MHz.
*pclock = 200000; *pclock = 200000;
*pdivisor = 2; *pdivisor = 2;
break; break;
#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT
case SDHCI_TIMING_UHS_DDR200: // Actual card clock: 199.68 KHz.
*pclock = 400000;
*pdivisor = 2;
break;
#endif
} }
} }
@@ -884,7 +911,8 @@ void clock_sdmmc_enable(u32 id, u32 val)
_clock_sdmmc_config_clock_host(&clock, id, val); _clock_sdmmc_config_clock_host(&clock, id, val);
_clock_sdmmc_set_enable(id); _clock_sdmmc_set_enable(id);
_clock_sdmmc_is_reset(id); _clock_sdmmc_is_reset(id);
usleep((100000 + clock - 1) / clock); // Wait 100 cycles for reset and for clocks to stabilize.
usleep((100 * 1000 + clock - 1) / clock);
_clock_sdmmc_clear_reset(id); _clock_sdmmc_clear_reset(id);
_clock_sdmmc_is_reset(id); _clock_sdmmc_is_reset(id);
} }

View File

@@ -625,7 +625,7 @@ enum CLK_Y_DEV
}; };
/*! Generic clock descriptor. */ /*! Generic clock descriptor. */
typedef struct _clock_t typedef struct _clk_rst_t
{ {
u16 reset; u16 reset;
u16 enable; u16 enable;
@@ -633,11 +633,11 @@ typedef struct _clock_t
u8 index; u8 index;
u8 clk_src; u8 clk_src;
u8 clk_div; u8 clk_div;
} clock_t; } clk_rst_t;
/*! Generic clock enable/disable. */ /*! Generic clock enable/disable. */
void clock_enable(const clock_t *clk); void clock_enable(const clk_rst_t *clk);
void clock_disable(const clock_t *clk); void clock_disable(const clk_rst_t *clk);
/*! Clock control for specific hardware portions. */ /*! Clock control for specific hardware portions. */
void clock_enable_fuse(bool enable); void clock_enable_fuse(bool enable);

View File

@@ -18,23 +18,27 @@
#include <soc/gpio.h> #include <soc/gpio.h>
#include <soc/t210.h> #include <soc/t210.h>
#define GPIO_BANK_IDX(port) ((port) >> 2) #define GPIO_BANK_IDX(port) ((port) >> 2)
#define GPIO_PORT_OFFSET(port) ((GPIO_BANK_IDX(port) << 8) + (((port) % 4) << 2))
#define GPIO_CNF_OFFSET(port) (0x00 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_CNF_OFFSET(port) (0x00 + GPIO_PORT_OFFSET(port))
#define GPIO_OE_OFFSET(port) (0x10 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_OE_OFFSET(port) (0x10 + GPIO_PORT_OFFSET(port))
#define GPIO_OUT_OFFSET(port) (0x20 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_OUT_OFFSET(port) (0x20 + GPIO_PORT_OFFSET(port))
#define GPIO_IN_OFFSET(port) (0x30 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_IN_OFFSET(port) (0x30 + GPIO_PORT_OFFSET(port))
#define GPIO_INT_STA_OFFSET(port) (0x40 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_INT_STA_OFFSET(port) (0x40 + GPIO_PORT_OFFSET(port))
#define GPIO_INT_ENB_OFFSET(port) (0x50 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_INT_ENB_OFFSET(port) (0x50 + GPIO_PORT_OFFSET(port))
#define GPIO_INT_LVL_OFFSET(port) (0x60 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_INT_LVL_OFFSET(port) (0x60 + GPIO_PORT_OFFSET(port))
#define GPIO_INT_CLR_OFFSET(port) (0x70 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_INT_CLR_OFFSET(port) (0x70 + GPIO_PORT_OFFSET(port))
#define GPIO_CNF_MASKED_OFFSET(port) (0x80 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_CNF_MASKED_OFFSET(port) (0x80 + GPIO_PORT_OFFSET(port))
#define GPIO_OE_MASKED_OFFSET(port) (0x90 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_OE_MASKED_OFFSET(port) (0x90 + GPIO_PORT_OFFSET(port))
#define GPIO_OUT_MASKED_OFFSET(port) (0xA0 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_OUT_MASKED_OFFSET(port) (0xA0 + GPIO_PORT_OFFSET(port))
#define GPIO_INT_STA_MASKED_OFFSET(port) (0xC0 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_INT_STA_MASKED_OFFSET(port) (0xC0 + GPIO_PORT_OFFSET(port))
#define GPIO_INT_ENB_MASKED_OFFSET(port) (0xD0 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_INT_ENB_MASKED_OFFSET(port) (0xD0 + GPIO_PORT_OFFSET(port))
#define GPIO_INT_LVL_MASKED_OFFSET(port) (0xE0 + (((port) >> 2) << 8) + (((port) % 4) << 2)) #define GPIO_INT_LVL_MASKED_OFFSET(port) (0xE0 + GPIO_PORT_OFFSET(port))
#define GPIO_DB_CTRL_OFFSET(port) (0xB0 + GPIO_PORT_OFFSET(port))
#define GPIO_DB_CNT_OFFSET(port) (0xF0 + GPIO_PORT_OFFSET(port))
#define GPIO_IRQ_BANK1 32 #define GPIO_IRQ_BANK1 32
#define GPIO_IRQ_BANK2 33 #define GPIO_IRQ_BANK2 33
@@ -52,7 +56,7 @@ static u8 gpio_bank_irq_ids[8] = {
void gpio_config(u32 port, u32 pins, int mode) void gpio_config(u32 port, u32 pins, int mode)
{ {
u32 offset = GPIO_CNF_OFFSET(port); const u32 offset = GPIO_CNF_OFFSET(port);
if (mode) if (mode)
GPIO(offset) |= pins; GPIO(offset) |= pins;
@@ -64,7 +68,7 @@ void gpio_config(u32 port, u32 pins, int mode)
void gpio_output_enable(u32 port, u32 pins, int enable) void gpio_output_enable(u32 port, u32 pins, int enable)
{ {
u32 port_offset = GPIO_OE_OFFSET(port); const u32 port_offset = GPIO_OE_OFFSET(port);
if (enable) if (enable)
GPIO(port_offset) |= pins; GPIO(port_offset) |= pins;
@@ -76,7 +80,7 @@ void gpio_output_enable(u32 port, u32 pins, int enable)
void gpio_write(u32 port, u32 pins, int high) void gpio_write(u32 port, u32 pins, int high)
{ {
u32 port_offset = GPIO_OUT_OFFSET(port); const u32 port_offset = GPIO_OUT_OFFSET(port);
if (high) if (high)
GPIO(port_offset) |= pins; GPIO(port_offset) |= pins;
@@ -88,27 +92,47 @@ void gpio_write(u32 port, u32 pins, int high)
void gpio_direction_input(u32 port, u32 pins) void gpio_direction_input(u32 port, u32 pins)
{ {
gpio_output_enable(port, pins, GPIO_OUTPUT_DISABLE);
gpio_config(port, pins, GPIO_MODE_GPIO); gpio_config(port, pins, GPIO_MODE_GPIO);
gpio_output_enable(port, pins, GPIO_OUTPUT_DISABLE);
} }
void gpio_direction_output(u32 port, u32 pins, int high) void gpio_direction_output(u32 port, u32 pins, int high)
{ {
gpio_output_enable(port, pins, GPIO_OUTPUT_ENABLE);
gpio_config(port, pins, GPIO_MODE_GPIO); gpio_config(port, pins, GPIO_MODE_GPIO);
gpio_write(port, pins, high); gpio_write(port, pins, high);
gpio_output_enable(port, pins, GPIO_OUTPUT_ENABLE);
} }
int gpio_read(u32 port, u32 pins) int gpio_read(u32 port, u32 pins)
{ {
u32 port_offset = GPIO_IN_OFFSET(port); const u32 port_offset = GPIO_IN_OFFSET(port);
return (GPIO(port_offset) & pins) ? 1 : 0; return (GPIO(port_offset) & pins) ? 1 : 0;
} }
void gpio_set_debounce(u32 port, u32 pins, u32 ms)
{
const u32 db_ctrl_offset = GPIO_DB_CTRL_OFFSET(port);
const u32 db_cnt_offset = GPIO_DB_CNT_OFFSET(port);
if (ms)
{
if (ms > 255)
ms = 255;
// Debounce time affects all pins of the same port.
GPIO(db_cnt_offset) = ms;
GPIO(db_ctrl_offset) = (pins << 8) | pins;
}
else
GPIO(db_ctrl_offset) = (pins << 8) | 0;
(void)GPIO(db_ctrl_offset); // Commit the write.
}
static void _gpio_interrupt_clear(u32 port, u32 pins) static void _gpio_interrupt_clear(u32 port, u32 pins)
{ {
u32 port_offset = GPIO_INT_CLR_OFFSET(port); const u32 port_offset = GPIO_INT_CLR_OFFSET(port);
GPIO(port_offset) |= pins; GPIO(port_offset) |= pins;
@@ -117,10 +141,10 @@ static void _gpio_interrupt_clear(u32 port, u32 pins)
int gpio_interrupt_status(u32 port, u32 pins) int gpio_interrupt_status(u32 port, u32 pins)
{ {
u32 port_offset = GPIO_INT_STA_OFFSET(port); const u32 port_offset = GPIO_INT_STA_OFFSET(port);
u32 enabled = GPIO(GPIO_INT_ENB_OFFSET(port)) & pins; const u32 enabled_mask = GPIO(GPIO_INT_ENB_OFFSET(port)) & pins;
int status = ((GPIO(port_offset) & pins) && enabled) ? 1 : 0; int status = ((GPIO(port_offset) & pins) && enabled_mask) ? 1 : 0;
// Clear the interrupt status. // Clear the interrupt status.
if (status) if (status)
@@ -131,7 +155,7 @@ int gpio_interrupt_status(u32 port, u32 pins)
void gpio_interrupt_enable(u32 port, u32 pins, int enable) void gpio_interrupt_enable(u32 port, u32 pins, int enable)
{ {
u32 port_offset = GPIO_INT_ENB_OFFSET(port); const u32 port_offset = GPIO_INT_ENB_OFFSET(port);
// Clear any possible stray interrupt. // Clear any possible stray interrupt.
_gpio_interrupt_clear(port, pins); _gpio_interrupt_clear(port, pins);
@@ -146,7 +170,7 @@ void gpio_interrupt_enable(u32 port, u32 pins, int enable)
void gpio_interrupt_level(u32 port, u32 pins, int high, int edge, int delta) void gpio_interrupt_level(u32 port, u32 pins, int high, int edge, int delta)
{ {
u32 port_offset = GPIO_INT_LVL_OFFSET(port); const u32 port_offset = GPIO_INT_LVL_OFFSET(port);
u32 val = GPIO(port_offset); u32 val = GPIO(port_offset);
@@ -175,7 +199,7 @@ void gpio_interrupt_level(u32 port, u32 pins, int high, int edge, int delta)
u32 gpio_get_bank_irq_id(u32 port) u32 gpio_get_bank_irq_id(u32 port)
{ {
u32 bank_idx = GPIO_BANK_IDX(port); const u32 bank_idx = GPIO_BANK_IDX(port);
return gpio_bank_irq_ids[bank_idx]; return gpio_bank_irq_ids[bank_idx];
} }

View File

@@ -89,6 +89,7 @@ void gpio_direction_input(u32 port, u32 pins);
void gpio_direction_output(u32 port, u32 pins, int high); void gpio_direction_output(u32 port, u32 pins, int high);
void gpio_write(u32 port, u32 pins, int high); void gpio_write(u32 port, u32 pins, int high);
int gpio_read(u32 port, u32 pins); int gpio_read(u32 port, u32 pins);
void gpio_set_debounce(u32 port, u32 pins, u32 ms);
int gpio_interrupt_status(u32 port, u32 pins); int gpio_interrupt_status(u32 port, u32 pins);
void gpio_interrupt_enable(u32 port, u32 pins, int enable); void gpio_interrupt_enable(u32 port, u32 pins, int enable);
void gpio_interrupt_level(u32 port, u32 pins, int high, int edge, int delta); void gpio_interrupt_level(u32 port, u32 pins, int high, int edge, int delta);

View File

@@ -254,15 +254,17 @@ static void _config_se_brom()
// This memset needs to happen here, else TZRAM will behave weirdly later on. // This memset needs to happen here, else TZRAM will behave weirdly later on.
memset((void *)TZRAM_BASE, 0, TZRAM_SIZE); memset((void *)TZRAM_BASE, 0, TZRAM_SIZE);
PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_ENABLE; PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_ENABLE;
SE(SE_INT_STATUS_REG) = 0x1F; // Clear all SE interrupts.
// Clear SE interrupts.
SE(SE_INT_STATUS_REG) = SE_INT_OP_DONE | SE_INT_OUT_DONE | SE_INT_OUT_LL_BUF_WR | SE_INT_IN_DONE | SE_INT_IN_LL_BUF_RD;
// Save reset reason. // Save reset reason.
hw_rst_status = PMC(APBDEV_PMC_SCRATCH200); hw_rst_status = PMC(APBDEV_PMC_SCRATCH200);
hw_rst_reason = PMC(APBDEV_PMC_RST_STATUS) & PMC_RST_STATUS_MASK; hw_rst_reason = PMC(APBDEV_PMC_RST_STATUS) & PMC_RST_STATUS_MASK;
// Clear the boot reason to avoid problems later. // Clear the boot reason to avoid problems later.
PMC(APBDEV_PMC_SCRATCH200) = 0x0; PMC(APBDEV_PMC_SCRATCH200) = 0;
PMC(APBDEV_PMC_RST_STATUS) = 0x0; PMC(APBDEV_PMC_RST_STATUS) = PMC_RST_STATUS_POR;
APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) = (APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) & 0xF0) | (7 << 10); APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) = (APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) & 0xF0) | (7 << 10);
} }

View File

@@ -22,11 +22,18 @@
#include <libs/fatfs/ff.h> #include <libs/fatfs/ff.h>
#include <mem/heap.h> #include <mem/heap.h>
#ifndef BDK_SDMMC_UHS_DDR200_SUPPORT
#define SD_DEFAULT_SPEED SD_UHS_SDR104
#else
#define SD_DEFAULT_SPEED SD_UHS_DDR208
#endif
static bool sd_mounted = false; static bool sd_mounted = false;
static bool sd_init_done = false; static bool sd_init_done = false;
static bool insertion_event = false; static bool insertion_event = false;
static u16 sd_errors[3] = { 0 }; // Init and Read/Write errors. static u16 sd_errors[3] = { 0 }; // Init and Read/Write errors.
static u32 sd_mode = SD_UHS_SDR104; static u32 sd_mode = SD_DEFAULT_SPEED;
sdmmc_t sd_sdmmc; sdmmc_t sd_sdmmc;
sdmmc_storage_t sd_storage; sdmmc_storage_t sd_storage;
@@ -79,7 +86,11 @@ u32 sd_get_mode()
int sd_init_retry(bool power_cycle) int sd_init_retry(bool power_cycle)
{ {
u32 bus_width = SDMMC_BUS_WIDTH_4; u32 bus_width = SDMMC_BUS_WIDTH_4;
#ifndef BDK_SDMMC_UHS_DDR200_SUPPORT
u32 type = SDHCI_TIMING_UHS_SDR104; u32 type = SDHCI_TIMING_UHS_SDR104;
#else
u32 type = SDHCI_TIMING_UHS_DDR200;
#endif
// Power cycle SD card. // Power cycle SD card.
if (power_cycle) if (power_cycle)
@@ -93,21 +104,33 @@ int sd_init_retry(bool power_cycle)
{ {
case SD_INIT_FAIL: // Reset to max. case SD_INIT_FAIL: // Reset to max.
return 0; return 0;
case SD_1BIT_HS25: case SD_1BIT_HS25:
bus_width = SDMMC_BUS_WIDTH_1; bus_width = SDMMC_BUS_WIDTH_1;
type = SDHCI_TIMING_SD_HS25; type = SDHCI_TIMING_SD_HS25;
break; break;
case SD_4BIT_HS25: case SD_4BIT_HS25:
type = SDHCI_TIMING_SD_HS25; type = SDHCI_TIMING_SD_HS25;
break; break;
case SD_UHS_SDR82: case SD_UHS_SDR82:
type = SDHCI_TIMING_UHS_SDR82; type = SDHCI_TIMING_UHS_SDR82;
break; break;
case SD_UHS_SDR104: case SD_UHS_SDR104:
type = SDHCI_TIMING_UHS_SDR104; type = SDHCI_TIMING_UHS_SDR104;
break; break;
#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT
case SD_UHS_DDR208:
type = SDHCI_TIMING_UHS_DDR200;
break;
#endif
default: default:
sd_mode = SD_UHS_SDR104; sd_mode = SD_DEFAULT_SPEED;
break;
} }
int res = sdmmc_storage_init_sd(&sd_storage, &sd_sdmmc, bus_width, type); int res = sdmmc_storage_init_sd(&sd_storage, &sd_sdmmc, bus_width, type);
@@ -135,7 +158,7 @@ bool sd_initialize(bool power_cycle)
return true; return true;
else if (!sdmmc_get_sd_inserted()) // SD Card is not inserted. else if (!sdmmc_get_sd_inserted()) // SD Card is not inserted.
{ {
sd_mode = SD_UHS_SDR104; sd_mode = SD_DEFAULT_SPEED;
break; break;
} }
else else
@@ -194,8 +217,12 @@ bool sd_mount()
static void _sd_deinit(bool deinit) static void _sd_deinit(bool deinit)
{ {
if (deinit && sd_mode == SD_INIT_FAIL) if (deinit)
sd_mode = SD_UHS_SDR104; {
insertion_event = false;
if (sd_mode == SD_INIT_FAIL)
sd_mode = SD_DEFAULT_SPEED;
}
if (sd_init_done) if (sd_init_done)
{ {
@@ -205,8 +232,7 @@ static void _sd_deinit(bool deinit)
if (deinit) if (deinit)
{ {
sdmmc_storage_end(&sd_storage); sdmmc_storage_end(&sd_storage);
sd_init_done = false; sd_init_done = false;
insertion_event = false;
} }
} }
sd_mounted = false; sd_mounted = false;

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2021 CTCaer * Copyright (c) 2018-2023 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,
@@ -30,7 +30,11 @@ enum
SD_1BIT_HS25 = 1, SD_1BIT_HS25 = 1,
SD_4BIT_HS25 = 2, SD_4BIT_HS25 = 2,
SD_UHS_SDR82 = 3, SD_UHS_SDR82 = 3,
SD_UHS_SDR104 = 4 SD_UHS_SDR104 = 4,
#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT
SD_UHS_DDR208 = 5
#endif
}; };
enum enum

View File

@@ -45,15 +45,14 @@
#define SD_APP_CHANGE_SECURE_AREA 49 /* adtc R1b */ #define SD_APP_CHANGE_SECURE_AREA 49 /* adtc R1b */
/* OCR bit definitions */ /* OCR bit definitions */
#define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */ #define SD_OCR_VDD_18 (1U << 7) /* VDD voltage 1.8 */
#define SD_VHD_27_36 (1 << 8) /* VDD voltage 2.7 ~ 3.6 */ #define SD_VHD_27_36 (1U << 8) /* VDD voltage 2.7 ~ 3.6 */
#define SD_OCR_VDD_27_34 (0x7F << 15) /* VDD voltage 2.7 ~ 3.4 */ #define SD_OCR_VDD_32_33 (1U << 20) /* VDD voltage 3.2 ~ 3.3 */
#define SD_OCR_VDD_32_33 (1 << 20) /* VDD voltage 3.2 ~ 3.3 */ #define SD_OCR_S18R (1U << 24) /* 1.8V switching request */
#define SD_OCR_S18R (1 << 24) /* 1.8V switching request */ #define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */
#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */ #define SD_OCR_XPC (1U << 28) /* SDXC power control */
#define SD_OCR_XPC (1 << 28) /* SDXC power control */ #define SD_OCR_CCS (1U << 30) /* Card Capacity Status */
#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */ #define SD_OCR_BUSY (1U << 31) /* Card Power up Status */
#define SD_OCR_BUSY (1 << 31) /* Card Power up Status */
/* /*
* SD_SWITCH argument format: * SD_SWITCH argument format:
@@ -90,8 +89,8 @@
#define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */ #define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */
#define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */ #define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */
#define SCR_SPEC_VER_2 2 /* Implements system specification 2.00-3.0X */ #define SCR_SPEC_VER_2 2 /* Implements system specification 2.00-3.0X */
#define SD_SCR_BUS_WIDTH_1 (1<<0) #define SD_SCR_BUS_WIDTH_1 (1U << 0)
#define SD_SCR_BUS_WIDTH_4 (1<<2) #define SD_SCR_BUS_WIDTH_4 (1U << 2)
/* /*
* SD bus widths * SD bus widths
@@ -102,33 +101,55 @@
/* /*
* SD bus speeds * SD bus speeds
*/ */
#define UHS_SDR12_BUS_SPEED 0 #define UHS_SDR12_BUS_SPEED 0
#define HIGH_SPEED_BUS_SPEED 1 #define HIGH_SPEED_BUS_SPEED 1
#define UHS_SDR25_BUS_SPEED 1 #define UHS_SDR25_BUS_SPEED 1
#define UHS_SDR50_BUS_SPEED 2 #define UHS_SDR50_BUS_SPEED 2
#define UHS_SDR104_BUS_SPEED 3 #define UHS_SDR104_BUS_SPEED 3
#define UHS_DDR50_BUS_SPEED 4 #define UHS_DDR50_BUS_SPEED 4
#define HS400_BUS_SPEED 5 #define HS400_BUS_SPEED 5
#define SD_MODE_HIGH_SPEED (1 << HIGH_SPEED_BUS_SPEED) #define SD_MODE_HIGH_SPEED (1U << HIGH_SPEED_BUS_SPEED)
#define SD_MODE_UHS_SDR12 (1 << UHS_SDR12_BUS_SPEED) #define SD_MODE_UHS_SDR12 (1U << UHS_SDR12_BUS_SPEED)
#define SD_MODE_UHS_SDR25 (1 << UHS_SDR25_BUS_SPEED) #define SD_MODE_UHS_SDR25 (1U << UHS_SDR25_BUS_SPEED)
#define SD_MODE_UHS_SDR50 (1 << UHS_SDR50_BUS_SPEED) #define SD_MODE_UHS_SDR50 (1U << UHS_SDR50_BUS_SPEED)
#define SD_MODE_UHS_SDR104 (1 << UHS_SDR104_BUS_SPEED) #define SD_MODE_UHS_SDR104 (1U << UHS_SDR104_BUS_SPEED)
#define SD_MODE_UHS_DDR50 (1 << UHS_DDR50_BUS_SPEED) #define SD_MODE_UHS_DDR50 (1U << UHS_DDR50_BUS_SPEED)
#define SD_DRIVER_TYPE_B 0x01
#define SD_DRIVER_TYPE_A 0x02 #define SD_SET_DRIVER_TYPE_B 0
#define SD_SET_DRIVER_TYPE_A 1
#define SD_SET_DRIVER_TYPE_C 2
#define SD_SET_DRIVER_TYPE_D 3
#define SD_DRIVER_TYPE_B (1U << SD_SET_DRIVER_TYPE_B)
#define SD_DRIVER_TYPE_A (1U << SD_SET_DRIVER_TYPE_A)
#define SD_DRIVER_TYPE_C (1U << SD_SET_DRIVER_TYPE_C)
#define SD_DRIVER_TYPE_D (1U << SD_SET_DRIVER_TYPE_D)
#define SD_SET_POWER_LIMIT_0_72 0 #define SD_SET_POWER_LIMIT_0_72 0
#define SD_SET_POWER_LIMIT_1_44 1 #define SD_SET_POWER_LIMIT_1_44 1
#define SD_SET_POWER_LIMIT_2_16 2 #define SD_SET_POWER_LIMIT_2_16 2
#define SD_SET_POWER_LIMIT_2_88 3 #define SD_SET_POWER_LIMIT_2_88 3
#define SD_MAX_POWER_0_72 (1 << SD_SET_POWER_LIMIT_0_72) #define SD_MAX_POWER_0_72 (1U << SD_SET_POWER_LIMIT_0_72)
#define SD_MAX_POWER_1_44 (1 << SD_SET_POWER_LIMIT_1_44) #define SD_MAX_POWER_1_44 (1U << SD_SET_POWER_LIMIT_1_44)
#define SD_MAX_POWER_2_16 (1 << SD_SET_POWER_LIMIT_2_16) #define SD_MAX_POWER_2_16 (1U << SD_SET_POWER_LIMIT_2_16)
#define SD_MAX_POWER_2_88 (1 << SD_SET_POWER_LIMIT_2_88) #define SD_MAX_POWER_2_88 (1U << SD_SET_POWER_LIMIT_2_88)
#define SD_SET_CMD_SYSTEM_DEF 0
#define SD_SET_CMD_SYSTEM_MEC 1
#define SD_SET_CMD_SYSTEM_OTP 3
#define SD_SET_CMD_SYSTEM_OSD 3
#define SD_SET_CMD_SYSTEM_VND 14
#define UHS_DDR200_BUS_SPEED SD_SET_CMD_SYSTEM_VND
#define SD_CMD_SYSTEM_DEF (1U << SD_SET_CMD_SYSTEM_DEF)
#define SD_CMD_SYSTEM_MEC (1U << SD_SET_CMD_SYSTEM_MEC)
#define SD_CMD_SYSTEM_OTP (1U << SD_SET_CMD_SYSTEM_OTP)
#define SD_CMD_SYSTEM_OSD (1U << SD_SET_CMD_SYSTEM_OSD)
#define SD_CMD_SYSTEM_VND (1U << SD_SET_CMD_SYSTEM_VND)
#define SD_MODE_UHS_DDR200 SD_CMD_SYSTEM_VND
/* /*
* SD_SWITCH mode * SD_SWITCH mode
@@ -140,14 +161,14 @@
* SD_SWITCH function groups * SD_SWITCH function groups
*/ */
#define SD_SWITCH_GRP_ACCESS 0 #define SD_SWITCH_GRP_ACCESS 0
#define SD_SWITCH_GRP_CMDSYS 1 #define SD_SWITCH_GRP_CMDSYS 1
#define SD_SWITCH_GRP_DRVSTR 2 #define SD_SWITCH_GRP_DRVSTR 2
#define SD_SWITCH_GRP_PWRLIM 3 #define SD_SWITCH_GRP_PWRLIM 3
/* /*
* SD_SWITCH access modes * SD_SWITCH access modes
*/ */
#define SD_SWITCH_ACCESS_DEF 0 #define SD_SWITCH_ACCESS_DEF 0
#define SD_SWITCH_ACCESS_HS 1 #define SD_SWITCH_ACCESS_HS 1
#endif /* SD_DEF_H */ #endif /* SD_DEF_H */

View File

@@ -24,6 +24,7 @@
#include <storage/mmc.h> #include <storage/mmc.h>
#include <storage/sd.h> #include <storage/sd.h>
#include <storage/sd_def.h> #include <storage/sd_def.h>
#include <mem/mc.h>
#include <memory_map.h> #include <memory_map.h>
#include <gfx_utils.h> #include <gfx_utils.h>
@@ -35,8 +36,9 @@ u32 sd_power_cycle_time_start;
static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size) static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size)
{ {
const u32 mask = (size < 32 ? 1 << size : 0) - 1; const u32 mask = (size < 32 ? 1 << size : 0) - 1;
const u32 off = 3 - ((start) / 32); const u32 off = 3 - ((start) / 32);
const u32 shft = (start) & 31; const u32 shft = (start) & 31;
u32 res = resp[off] >> shft; u32 res = resp[off] >> shft;
if (size + shft > 32) if (size + shft > 32)
res |= resp[off - 1] << ((32 - shft) % 32); res |= resp[off - 1] << ((32 - shft) % 32);
@@ -577,7 +579,7 @@ static int _mmc_storage_enable_HS(sdmmc_storage_t *storage, bool check_sts_befor
if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_MMC_HS52)) if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_MMC_HS52))
return 0; return 0;
DPRINTF("[MMC] switched to HS52\n"); DPRINTF("[MMC] switched to HS52\n");
storage->csd.busspeed = 52; storage->csd.busspeed = 52;
if (check_sts_before_clk_setup || _sdmmc_storage_check_status(storage)) if (check_sts_before_clk_setup || _sdmmc_storage_check_status(storage))
@@ -597,7 +599,7 @@ static int _mmc_storage_enable_HS200(sdmmc_storage_t *storage)
if (!sdmmc_tuning_execute(storage->sdmmc, SDHCI_TIMING_MMC_HS200, MMC_SEND_TUNING_BLOCK_HS200)) if (!sdmmc_tuning_execute(storage->sdmmc, SDHCI_TIMING_MMC_HS200, MMC_SEND_TUNING_BLOCK_HS200))
return 0; return 0;
DPRINTF("[MMC] switched to HS200\n"); DPRINTF("[MMC] switched to HS200\n");
storage->csd.busspeed = 200; storage->csd.busspeed = 200;
return _sdmmc_storage_check_status(storage); return _sdmmc_storage_check_status(storage);
@@ -622,7 +624,7 @@ static int _mmc_storage_enable_HS400(sdmmc_storage_t *storage)
if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_MMC_HS400)) if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_MMC_HS400))
return 0; return 0;
DPRINTF("[MMC] switched to HS400\n"); DPRINTF("[MMC] switched to HS400\n");
storage->csd.busspeed = 400; storage->csd.busspeed = 400;
return _sdmmc_storage_check_status(storage); return _sdmmc_storage_check_status(storage);
@@ -668,44 +670,47 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_wid
storage->sdmmc = sdmmc; storage->sdmmc = sdmmc;
storage->rca = 2; // Set default device address. This could be a config item. storage->rca = 2; // Set default device address. This could be a config item.
if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_MMC_ID, SDMMC_POWER_SAVE_DISABLE)) DPRINTF("[MMC]-[init: bus: %d, type: %d]\n", bus_width, type);
return 0;
DPRINTF("[MMC] after init\n");
usleep(1000 + (74000 + sdmmc->divisor - 1) / sdmmc->divisor); if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_MMC_ID))
return 0;
DPRINTF("[MMC] after init\n");
// Wait 1ms + 74 cycles.
usleep(1000 + (74 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock);
if (!_sdmmc_storage_go_idle_state(storage)) if (!_sdmmc_storage_go_idle_state(storage))
return 0; return 0;
DPRINTF("[MMC] went to idle state\n"); DPRINTF("[MMC] went to idle state\n");
if (!_mmc_storage_get_op_cond(storage, SDMMC_POWER_1_8)) if (!_mmc_storage_get_op_cond(storage, SDMMC_POWER_1_8))
return 0; return 0;
DPRINTF("[MMC] got op cond\n"); DPRINTF("[MMC] got op cond\n");
if (!_sdmmc_storage_get_cid(storage)) if (!_sdmmc_storage_get_cid(storage))
return 0; return 0;
DPRINTF("[MMC] got cid\n"); DPRINTF("[MMC] got cid\n");
if (!_mmc_storage_set_relative_addr(storage)) if (!_mmc_storage_set_relative_addr(storage))
return 0; return 0;
DPRINTF("[MMC] set relative addr\n"); DPRINTF("[MMC] set relative addr\n");
if (!_sdmmc_storage_get_csd(storage)) if (!_sdmmc_storage_get_csd(storage))
return 0; return 0;
DPRINTF("[MMC] got csd\n"); DPRINTF("[MMC] got csd\n");
_mmc_storage_parse_csd(storage); _mmc_storage_parse_csd(storage);
if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_MMC_LS26)) if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_MMC_LS26))
return 0; return 0;
DPRINTF("[MMC] after setup clock\n"); DPRINTF("[MMC] after setup clock\n");
if (!_sdmmc_storage_select_card(storage)) if (!_sdmmc_storage_select_card(storage))
return 0; return 0;
DPRINTF("[MMC] card selected\n"); DPRINTF("[MMC] card selected\n");
if (!_sdmmc_storage_set_blocklen(storage, 512)) if (!_sdmmc_storage_set_blocklen(storage, 512))
return 0; return 0;
DPRINTF("[MMC] set blocklen to 512\n"); DPRINTF("[MMC] set blocklen to 512\n");
// Check system specification version, only version 4.0 and later support below features. // Check system specification version, only version 4.0 and later support below features.
if (storage->csd.mmca_vsn < CSD_SPEC_VER_4) if (storage->csd.mmca_vsn < CSD_SPEC_VER_4)
@@ -713,11 +718,11 @@ DPRINTF("[MMC] set blocklen to 512\n");
if (!_mmc_storage_switch_buswidth(storage, bus_width)) if (!_mmc_storage_switch_buswidth(storage, bus_width))
return 0; return 0;
DPRINTF("[MMC] switched buswidth\n"); DPRINTF("[MMC] switched buswidth\n");
if (!mmc_storage_get_ext_csd(storage, (u8 *)SDMMC_UPPER_BUFFER)) if (!mmc_storage_get_ext_csd(storage, (u8 *)SDMMC_UPPER_BUFFER))
return 0; return 0;
DPRINTF("[MMC] got ext_csd\n"); DPRINTF("[MMC] got ext_csd\n");
_mmc_storage_parse_cid(storage); // This needs to be after csd and ext_csd. _mmc_storage_parse_cid(storage); // This needs to be after csd and ext_csd.
@@ -725,13 +730,13 @@ DPRINTF("[MMC] got ext_csd\n");
if (storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_AUTO_BKOPS_MASK)) if (storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_AUTO_BKOPS_MASK))
{ {
_mmc_storage_enable_auto_bkops(storage); _mmc_storage_enable_auto_bkops(storage);
DPRINTF("[MMC] BKOPS enabled\n"); DPRINTF("[MMC] BKOPS enabled\n");
} }
*/ */
if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type)) if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type))
return 0; return 0;
DPRINTF("[MMC] successfully switched to HS mode\n"); DPRINTF("[MMC] successfully switched to HS mode\n");
sdmmc_card_clock_powersave(storage->sdmmc, SDMMC_POWER_SAVE_ENABLE); sdmmc_card_clock_powersave(storage->sdmmc, SDMMC_POWER_SAVE_ENABLE);
@@ -800,15 +805,17 @@ static int _sd_storage_send_if_cond(sdmmc_storage_t *storage, bool *is_sdsc)
static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, bool is_sdsc, int bus_uhs_support) static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, bool is_sdsc, int bus_uhs_support)
{ {
sdmmc_cmd_t cmdbuf; sdmmc_cmd_t cmdbuf;
// Support for Current > 150mA // Support for Current > 150mA.
u32 arg = !is_sdsc ? SD_OCR_XPC : 0; u32 arg = !is_sdsc ? SD_OCR_XPC : 0;
// Support for handling block-addressed SDHC cards // Support for handling block-addressed SDHC cards.
arg |= !is_sdsc ? SD_OCR_CCS : 0; arg |= !is_sdsc ? SD_OCR_CCS : 0;
// Support for 1.8V // Support for 1.8V signaling.
arg |= (bus_uhs_support && !is_sdsc) ? SD_OCR_S18R : 0; arg |= (bus_uhs_support && !is_sdsc) ? SD_OCR_S18R : 0;
// This is needed for most cards. Do not set bit7 even if 1.8V is supported. // Support for 3.3V power supply (VDD1).
arg |= SD_OCR_VDD_32_33; arg |= SD_OCR_VDD_32_33;
sdmmc_init_cmd(&cmdbuf, SD_APP_OP_COND, arg, SDMMC_RSP_TYPE_3, 0); sdmmc_init_cmd(&cmdbuf, SD_APP_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
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;
@@ -828,7 +835,7 @@ static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, bool is_sdsc, int b
// Check if power up is done. // Check if power up is done.
if (cond & SD_OCR_BUSY) if (cond & SD_OCR_BUSY)
{ {
DPRINTF("[SD] op cond: %08X, lv: %d\n", cond, bus_uhs_support); DPRINTF("[SD] op cond: %08X, lv: %d\n", cond, bus_uhs_support);
// Check if card is high capacity. // Check if card is high capacity.
if (cond & SD_OCR_CCS) if (cond & SD_OCR_CCS)
@@ -840,16 +847,20 @@ DPRINTF("[SD] op cond: %08X, lv: %d\n", cond, bus_uhs_support);
// 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))
{ {
if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_UHS_SDR12))
return 0;
if (!sdmmc_enable_low_voltage(storage->sdmmc)) if (!sdmmc_enable_low_voltage(storage->sdmmc))
return 0; return 0;
storage->is_low_voltage = 1; storage->is_low_voltage = 1;
DPRINTF("-> switched to low voltage\n"); DPRINTF("-> switched to low voltage\n");
} }
} }
else else
{ {
DPRINTF("[SD] no low voltage support\n"); DPRINTF("[SD] no low voltage support\n");
} }
return 1; return 1;
@@ -897,8 +908,7 @@ static void _sd_storage_parse_scr(sdmmc_storage_t *storage)
// unstuff_bits can parse only 4 u32 // unstuff_bits can parse only 4 u32
u32 resp[4]; u32 resp[4];
resp[3] = *(u32 *)&storage->raw_scr[4]; memcpy(&resp[2], storage->raw_scr, 8);
resp[2] = *(u32 *)&storage->raw_scr[0];
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);
@@ -957,8 +967,6 @@ static int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf)
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
return 0; return 0;
//gfx_hexdump(0, (u8 *)buf, 64);
u32 tmp = 0; u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
return _sdmmc_storage_check_card_status(tmp); return _sdmmc_storage_check_card_status(tmp);
@@ -992,59 +1000,139 @@ static void _sd_storage_set_power_limit(sdmmc_storage_t *storage, u16 power_limi
{ {
u32 pwr = SD_SET_POWER_LIMIT_0_72; u32 pwr = SD_SET_POWER_LIMIT_0_72;
// If UHS-I only, anything above 1.44W defaults to 1.44W. // If UHS-I only, anything above 1.44W defaults to 1.44W.
#if SDMMC_UHS2_SUPPORT
if (power_limit & SD_MAX_POWER_2_88) if (power_limit & SD_MAX_POWER_2_88)
pwr = SD_SET_POWER_LIMIT_2_88; pwr = SD_SET_POWER_LIMIT_2_88;
else if (power_limit & SD_MAX_POWER_2_16) else if (power_limit & SD_MAX_POWER_2_16)
pwr = SD_SET_POWER_LIMIT_2_16; pwr = SD_SET_POWER_LIMIT_2_16;
else if (power_limit & SD_MAX_POWER_1_44) else if (power_limit & SD_MAX_POWER_1_44)
pwr = SD_SET_POWER_LIMIT_1_44; pwr = SD_SET_POWER_LIMIT_1_44;
#else
if (power_limit & SD_MAX_POWER_1_44)
pwr = SD_SET_POWER_LIMIT_1_44;
#endif
_sd_storage_switch(storage, buf, SD_SWITCH_SET, SD_SWITCH_GRP_PWRLIM, pwr); _sd_storage_switch(storage, buf, SD_SWITCH_SET, SD_SWITCH_GRP_PWRLIM, pwr);
if (((buf[15] >> 4) & 0x0F) == pwr) switch ((buf[15] >> 4) & 0x0F)
{ {
switch (pwr) case SD_SET_POWER_LIMIT_2_88:
{ DPRINTF("[SD] power limit raised to 2880 mW\n");
#if SDMMC_UHS2_SUPPORT break;
case SD_SET_POWER_LIMIT_2_88:
DPRINTF("[SD] power limit raised to 2880 mW\n");
break;
case SD_SET_POWER_LIMIT_2_16: case SD_SET_POWER_LIMIT_2_16:
DPRINTF("[SD] power limit raised to 2160 mW\n"); DPRINTF("[SD] power limit raised to 2160 mW\n");
break; break;
#endif
case SD_SET_POWER_LIMIT_1_44:
DPRINTF("[SD] power limit raised to 1440 mW\n");
break;
default: case SD_SET_POWER_LIMIT_1_44:
case SD_SET_POWER_LIMIT_0_72: DPRINTF("[SD] power limit raised to 1440 mW\n");
DPRINTF("[SD] power limit defaulted to 720 mW\n"); break;
break;
} default:
case SD_SET_POWER_LIMIT_0_72:
DPRINTF("[SD] power limit defaulted to 720 mW\n");
break;
} }
} }
static int _sd_storage_enable_highspeed(sdmmc_storage_t *storage, u32 hs_type, u8 *buf) int _sd_storage_set_driver_type(sdmmc_storage_t *storage, u32 driver, u8 *buf)
{
if (!_sd_storage_switch(storage, buf, SD_SWITCH_CHECK, SD_SWITCH_GRP_DRVSTR, driver))
return 0;
u32 driver_out = buf[15] & 0xF;
if (driver_out != driver)
return 0;
DPRINTF("[SD] supports Driver Strength %d\n", driver);
if (!_sd_storage_switch(storage, buf, SD_SWITCH_SET, SD_SWITCH_GRP_DRVSTR, driver))
return 0;
if (driver_out != (buf[15] & 0xF))
return 0;
DPRINTF("[SD] card accepted Driver Strength %d\n", driver);
sdmmc_setup_drv_type(storage->sdmmc, driver);
return 1;
}
/*
* SD Card DDR200 (DDR208) support
*
* Proper procedure:
* 1. Check that Vendor Specific Command System is supported.
* Used as Enable DDR200 Bus.
* 2. Enable DDR200 bus mode via setting 14 to Group 2 via CMD6.
* Access Mode group is left to default 0 (SDR12).
* 3. Setup clock to 200 or 208 MHz.
* 4. Set host to DDR bus mode that supports such high clocks.
* Some hosts have special mode, others use DDR50 and others HS400.
* 5. Execute Tuning.
*
* The true validation that this value in Group 2 activates it, is that DDR50 bus
* and clocks/timings work fully after that point.
*
* On Tegra X1, that can be done with DDR50 host mode.
* Tuning though can't be done automatically on any DDR mode.
* So it needs to be done manually and selected tap will be applied from the biggest
* sampling window.
*
* Finally, all that simply works, because the marketing materials for DDR200 are
* basically overstatements to sell the feature. DDR200 is simply SDR104 in DDR mode,
* so sampling on rising and falling edge and with variable output data window.
* It can be supported by any host that is fast enough to support DDR at 200/208MHz
* and can do hw/sw tuning for finding the proper sampling window in that mode.
*/
#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT
static int _sd_storage_enable_DDR200(sdmmc_storage_t *storage, u8 *buf)
{
u32 cmd_system = UHS_DDR200_BUS_SPEED;
if (!_sd_storage_switch(storage, buf, SD_SWITCH_CHECK, SD_SWITCH_GRP_CMDSYS, cmd_system))
return 0;
u32 system_out = (buf[16] >> 4) & 0xF;
if (system_out != cmd_system)
return 0;
DPRINTF("[SD] supports DDR200 mode\n");
u16 total_pwr_consumption = ((u16)buf[0] << 8) | buf[1];
DPRINTF("[SD] max power: %d mW\n", total_pwr_consumption * 3600 / 1000);
storage->card_power_limit = total_pwr_consumption;
if (total_pwr_consumption <= 800)
{
if (!_sd_storage_switch(storage, buf, SD_SWITCH_SET, SD_SWITCH_GRP_CMDSYS, cmd_system))
return 0;
if (system_out != ((buf[16] >> 4) & 0xF))
return 0;
DPRINTF("[SD] card accepted DDR200\n");
if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_UHS_DDR200))
return 0;
DPRINTF("[SD] after setup clock DDR200\n");
if (!sdmmc_tuning_execute(storage->sdmmc, SDHCI_TIMING_UHS_DDR200, MMC_SEND_TUNING_BLOCK))
return 0;
DPRINTF("[SD] after tuning DDR200\n");
return _sdmmc_storage_check_status(storage);
}
DPRINTF("[SD] card max power over limit\n");
return 0;
}
#endif
static int _sd_storage_set_card_bus_speed(sdmmc_storage_t *storage, u32 hs_type, u8 *buf)
{ {
if (!_sd_storage_switch(storage, buf, SD_SWITCH_CHECK, SD_SWITCH_GRP_ACCESS, hs_type)) if (!_sd_storage_switch(storage, buf, SD_SWITCH_CHECK, SD_SWITCH_GRP_ACCESS, hs_type))
return 0; return 0;
DPRINTF("[SD] supports (U)HS mode: %d\n", buf[16] & 0xF);
u32 type_out = buf[16] & 0xF; u32 type_out = buf[16] & 0xF;
if (type_out != hs_type) if (type_out != hs_type)
return 0; return 0;
DPRINTF("[SD] supports selected (U)HS mode\n"); DPRINTF("[SD] supports selected (U)HS mode %d\n", buf[16] & 0xF);
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->card_power_limit = total_pwr_consumption;
if (total_pwr_consumption <= 800) if (total_pwr_consumption <= 800)
@@ -1058,7 +1146,7 @@ DPRINTF("[SD] max power: %d mW\n", total_pwr_consumption * 3600 / 1000);
return 1; return 1;
} }
DPRINTF("[SD] card max power over limit\n"); DPRINTF("[SD] card max power over limit\n");
return 0; return 0;
} }
@@ -1071,22 +1159,35 @@ static int _sd_storage_enable_uhs_low_volt(sdmmc_storage_t *storage, u32 type, u
return 0; return 0;
u8 access_mode = buf[13]; u8 access_mode = buf[13];
u16 power_limit = buf[7] | buf[6] << 8; u16 power_limit = buf[7] | buf[6] << 8;
DPRINTF("[SD] access: %02X, power: %02X\n", access_mode, power_limit); #ifdef BDK_SDMMC_UHS_DDR200_SUPPORT
u16 cmd_system = buf[11] | buf[10] << 8;
// Try to raise the power limit to let the card perform better. #endif
_sd_storage_set_power_limit(storage, power_limit, buf); DPRINTF("[SD] access: %02X, power: %02X\n", access_mode, power_limit);
u32 hs_type = 0; u32 hs_type = 0;
switch (type) switch (type)
{ {
#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT
case SDHCI_TIMING_UHS_DDR200:
// Fall through if DDR200 is not supported.
if (cmd_system & SD_MODE_UHS_DDR200)
{
DPRINTF("[SD] setting bus speed to DDR200\n");
storage->csd.busspeed = 200;
_sd_storage_set_power_limit(storage, power_limit, buf);
return _sd_storage_enable_DDR200(storage, buf);
}
#endif
case SDHCI_TIMING_UHS_SDR104: case SDHCI_TIMING_UHS_SDR104:
case SDHCI_TIMING_UHS_SDR82: case SDHCI_TIMING_UHS_SDR82:
// Fall through if not supported. // Fall through if not supported.
if (access_mode & SD_MODE_UHS_SDR104) if (access_mode & SD_MODE_UHS_SDR104)
{ {
type = SDHCI_TIMING_UHS_SDR104;
hs_type = UHS_SDR104_BUS_SPEED; hs_type = UHS_SDR104_BUS_SPEED;
DPRINTF("[SD] bus speed set to SDR104\n"); DPRINTF("[SD] setting bus speed to SDR104\n");
switch (type) switch (type)
{ {
case SDHCI_TIMING_UHS_SDR104: case SDHCI_TIMING_UHS_SDR104:
@@ -1098,49 +1199,60 @@ DPRINTF("[SD] bus speed set to SDR104\n");
} }
break; break;
} }
case SDHCI_TIMING_UHS_SDR50: case SDHCI_TIMING_UHS_SDR50:
if (access_mode & SD_MODE_UHS_SDR50) if (access_mode & SD_MODE_UHS_SDR50)
{ {
type = SDHCI_TIMING_UHS_SDR50; type = SDHCI_TIMING_UHS_SDR50;
hs_type = UHS_SDR50_BUS_SPEED; hs_type = UHS_SDR50_BUS_SPEED;
DPRINTF("[SD] bus speed set to SDR50\n"); DPRINTF("[SD] setting bus speed to SDR50\n");
storage->csd.busspeed = 50; storage->csd.busspeed = 50;
break; break;
} }
/* /*
case SDHCI_TIMING_UHS_DDR50:
if (access_mode & SD_MODE_UHS_DDR50)
{
type = SDHCI_TIMING_UHS_DDR50;
hs_type = UHS_DDR50_BUS_SPEED;
DPRINTF("[SD] setting bus speed to DDR50\n");
storage->csd.busspeed = 50;
break;
}
*/
case SDHCI_TIMING_UHS_SDR25: case SDHCI_TIMING_UHS_SDR25:
if (access_mode & SD_MODE_UHS_SDR25) if (access_mode & SD_MODE_UHS_SDR25)
{ {
type = SDHCI_TIMING_UHS_SDR25; type = SDHCI_TIMING_UHS_SDR25;
hs_type = UHS_SDR25_BUS_SPEED; hs_type = UHS_SDR25_BUS_SPEED;
DPRINTF("[SD] bus speed set to SDR25\n"); DPRINTF("[SD] setting bus speed to SDR25\n");
storage->csd.busspeed = 25; storage->csd.busspeed = 25;
break; break;
} }
*/
case SDHCI_TIMING_UHS_SDR12:
if (!(access_mode & SD_MODE_UHS_SDR12))
return 0;
type = SDHCI_TIMING_UHS_SDR12;
hs_type = UHS_SDR12_BUS_SPEED;
DPRINTF("[SD] bus speed set to SDR12\n");
storage->csd.busspeed = 12;
break;
default: default:
return 0; DPRINTF("[SD] bus speed defaulted to SDR12\n");
break; storage->csd.busspeed = 12;
return 1;
} }
if (!_sd_storage_enable_highspeed(storage, hs_type, buf)) // Try to raise the power limit to let the card perform better.
if (hs_type != UHS_SDR25_BUS_SPEED)
_sd_storage_set_power_limit(storage, power_limit, buf);
// Setup and set selected card and bus speed.
if (!_sd_storage_set_card_bus_speed(storage, hs_type, buf))
return 0; return 0;
DPRINTF("[SD] card accepted UHS\n"); DPRINTF("[SD] card accepted UHS\n");
if (!sdmmc_setup_clock(storage->sdmmc, type)) if (!sdmmc_setup_clock(storage->sdmmc, type))
return 0; return 0;
DPRINTF("[SD] after setup clock\n"); DPRINTF("[SD] after setup clock\n");
if (!sdmmc_tuning_execute(storage->sdmmc, type, MMC_SEND_TUNING_BLOCK)) if (!sdmmc_tuning_execute(storage->sdmmc, type, MMC_SEND_TUNING_BLOCK))
return 0; return 0;
DPRINTF("[SD] after tuning\n"); DPRINTF("[SD] after tuning\n");
return _sdmmc_storage_check_status(storage); return _sdmmc_storage_check_status(storage);
} }
@@ -1151,7 +1263,7 @@ static int _sd_storage_enable_hs_high_volt(sdmmc_storage_t *storage, u8 *buf)
u8 access_mode = buf[13]; u8 access_mode = buf[13];
u16 power_limit = buf[7] | buf[6] << 8; u16 power_limit = buf[7] | buf[6] << 8;
DPRINTF("[SD] access: %02X, power: %02X\n", access_mode, power_limit); DPRINTF("[SD] access: %02X, power: %02X\n", access_mode, power_limit);
// Try to raise the power limit to let the card perform better. // Try to raise the power limit to let the card perform better.
_sd_storage_set_power_limit(storage, power_limit, buf); _sd_storage_set_power_limit(storage, power_limit, buf);
@@ -1159,7 +1271,7 @@ DPRINTF("[SD] access: %02X, power: %02X\n", access_mode, power_limit);
if (!(access_mode & SD_MODE_HIGH_SPEED)) if (!(access_mode & SD_MODE_HIGH_SPEED))
return 1; return 1;
if (!_sd_storage_enable_highspeed(storage, HIGH_SPEED_BUS_SPEED, buf)) if (!_sd_storage_set_card_bus_speed(storage, HIGH_SPEED_BUS_SPEED, buf))
return 0; return 0;
if (!_sdmmc_storage_check_status(storage)) if (!_sdmmc_storage_check_status(storage))
@@ -1259,7 +1371,7 @@ int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
if (!(storage->csd.cmdclass & CCC_APP_SPEC)) if (!(storage->csd.cmdclass & CCC_APP_SPEC))
{ {
DPRINTF("[SD] ssr: Not supported\n"); DPRINTF("[SD] ssr: Not supported\n");
return 0; return 0;
} }
@@ -1323,7 +1435,7 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
break; break;
default: default:
DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure); DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure);
break; break;
} }
@@ -1340,6 +1452,7 @@ static bool _sdmmc_storage_get_bus_uhs_support(u32 bus_width, u32 type)
case SDHCI_TIMING_UHS_SDR104: case SDHCI_TIMING_UHS_SDR104:
case SDHCI_TIMING_UHS_SDR82: case SDHCI_TIMING_UHS_SDR82:
case SDHCI_TIMING_UHS_DDR50: case SDHCI_TIMING_UHS_DDR50:
case SDHCI_TIMING_UHS_DDR200:
if (bus_width == SDMMC_BUS_WIDTH_4) if (bus_width == SDMMC_BUS_WIDTH_4)
return true; return true;
default: default:
@@ -1362,7 +1475,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_widt
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);
DPRINTF("[SD] init: bus: %d, type: %d\n", bus_width, type); DPRINTF("[SD]-[init: bus: %d, type: %d]\n", bus_width, type);
// Some cards (SanDisk U1), do not like a fast power cycle. Wait min 100ms. // Some cards (SanDisk U1), do not like a fast power cycle. Wait min 100ms.
sdmmc_storage_init_wait_sd(); sdmmc_storage_init_wait_sd();
@@ -1370,61 +1483,62 @@ DPRINTF("[SD] init: bus: %d, type: %d\n", bus_width, type);
memset(storage, 0, sizeof(sdmmc_storage_t)); memset(storage, 0, sizeof(sdmmc_storage_t));
storage->sdmmc = sdmmc; storage->sdmmc = sdmmc;
if (!sdmmc_init(sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, SDMMC_POWER_SAVE_DISABLE)) if (!sdmmc_init(sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID))
return 0; return 0;
DPRINTF("[SD] after init\n"); DPRINTF("[SD] after init\n");
usleep(1000 + (74000 + sdmmc->divisor - 1) / sdmmc->divisor); // Wait 1ms + 74 cycles.
usleep(1000 + (74 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock);
if (!_sdmmc_storage_go_idle_state(storage)) if (!_sdmmc_storage_go_idle_state(storage))
return 0; return 0;
DPRINTF("[SD] went to idle state\n"); DPRINTF("[SD] went to idle state\n");
if (!_sd_storage_send_if_cond(storage, &is_sdsc)) if (!_sd_storage_send_if_cond(storage, &is_sdsc))
return 0; return 0;
DPRINTF("[SD] after send if cond\n"); DPRINTF("[SD] after send if cond\n");
if (!_sd_storage_get_op_cond(storage, is_sdsc, bus_uhs_support)) if (!_sd_storage_get_op_cond(storage, is_sdsc, bus_uhs_support))
return 0; return 0;
DPRINTF("[SD] got op cond\n"); DPRINTF("[SD] got op cond\n");
if (!_sdmmc_storage_get_cid(storage)) if (!_sdmmc_storage_get_cid(storage))
return 0; return 0;
DPRINTF("[SD] got cid\n"); DPRINTF("[SD] got cid\n");
_sd_storage_parse_cid(storage); _sd_storage_parse_cid(storage);
if (!_sd_storage_get_rca(storage)) if (!_sd_storage_get_rca(storage))
return 0; return 0;
DPRINTF("[SD] got rca (= %04X)\n", storage->rca); DPRINTF("[SD] got rca (= %04X)\n", storage->rca);
if (!_sdmmc_storage_get_csd(storage)) if (!_sdmmc_storage_get_csd(storage))
return 0; return 0;
DPRINTF("[SD] got csd\n"); DPRINTF("[SD] got csd\n");
_sd_storage_parse_csd(storage); _sd_storage_parse_csd(storage);
if (!storage->is_low_voltage) if (!storage->is_low_voltage)
{ {
if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_DS12)) if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_DS12))
return 0; return 0;
DPRINTF("[SD] after setup default clock\n"); DPRINTF("[SD] after setup default clock\n");
} }
if (!_sdmmc_storage_select_card(storage)) if (!_sdmmc_storage_select_card(storage))
return 0; return 0;
DPRINTF("[SD] card selected\n"); DPRINTF("[SD] card selected\n");
if (!_sdmmc_storage_set_blocklen(storage, 512)) if (!_sdmmc_storage_set_blocklen(storage, 512))
return 0; return 0;
DPRINTF("[SD] set blocklen to 512\n"); DPRINTF("[SD] set blocklen to 512\n");
// Disconnect Card Detect resistor from DAT3. // Disconnect Card Detect resistor from DAT3.
if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_CLR_CARD_DETECT, 0, 0, R1_STATE_TRAN)) if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_CLR_CARD_DETECT, 0, 0, R1_STATE_TRAN))
return 0; return 0;
DPRINTF("[SD] cleared card detect\n"); DPRINTF("[SD] cleared card detect\n");
if (!sd_storage_get_scr(storage, buf)) if (!sd_storage_get_scr(storage, buf))
return 0; return 0;
DPRINTF("[SD] got scr\n"); DPRINTF("[SD] got scr\n");
// If card supports a wider bus and if it's not SD Version 1.0 switch bus width. // If card supports a wider bus and if it's not SD Version 1.0 switch bus width.
if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & BIT(SD_BUS_WIDTH_4)) && storage->scr.sda_vsn) if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & BIT(SD_BUS_WIDTH_4)) && storage->scr.sda_vsn)
@@ -1433,26 +1547,26 @@ DPRINTF("[SD] got scr\n");
return 0; return 0;
sdmmc_set_bus_width(storage->sdmmc, SDMMC_BUS_WIDTH_4); sdmmc_set_bus_width(storage->sdmmc, SDMMC_BUS_WIDTH_4);
DPRINTF("[SD] switched to wide bus width\n"); DPRINTF("[SD] switched to wide bus width\n");
} }
else else
{ {
bus_width = SDMMC_BUS_WIDTH_1; bus_width = SDMMC_BUS_WIDTH_1;
DPRINTF("[SD] SD does not support wide bus width\n"); DPRINTF("[SD] SD does not support wide bus width\n");
} }
if (storage->is_low_voltage) if (storage->is_low_voltage)
{ {
if (!_sd_storage_enable_uhs_low_volt(storage, type, buf)) if (!_sd_storage_enable_uhs_low_volt(storage, type, buf))
return 0; return 0;
DPRINTF("[SD] enabled UHS\n"); DPRINTF("[SD] enabled UHS\n");
} }
else if (type != SDHCI_TIMING_SD_DS12 && storage->scr.sda_vsn) // Not default speed and not SD Version 1.0. else if (type != SDHCI_TIMING_SD_DS12 && storage->scr.sda_vsn) // Not default speed and not SD Version 1.0.
{ {
if (!_sd_storage_enable_hs_high_volt(storage, buf)) if (!_sd_storage_enable_hs_high_volt(storage, buf))
return 0; return 0;
DPRINTF("[SD] enabled HS\n"); DPRINTF("[SD] enabled HS\n");
switch (bus_width) switch (bus_width)
{ {
case SDMMC_BUS_WIDTH_4: case SDMMC_BUS_WIDTH_4:
@@ -1468,7 +1582,7 @@ DPRINTF("[SD] enabled HS\n");
// Parse additional card info from sd status. // Parse additional card info from sd status.
if (sd_storage_get_ssr(storage, buf)) if (sd_storage_get_ssr(storage, buf))
{ {
DPRINTF("[SD] got sd status\n"); DPRINTF("[SD] got sd status\n");
} }
sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE); sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE);
@@ -1514,15 +1628,16 @@ int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc)
memset(storage, 0, sizeof(sdmmc_storage_t)); memset(storage, 0, sizeof(sdmmc_storage_t));
storage->sdmmc = sdmmc; storage->sdmmc = sdmmc;
if (!sdmmc_init(sdmmc, SDMMC_2, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_DDR100, SDMMC_POWER_SAVE_DISABLE)) if (!sdmmc_init(sdmmc, SDMMC_2, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS100))
return 0; return 0;
DPRINTF("[gc] after init\n"); DPRINTF("[GC] after init\n");
usleep(1000 + (10000 + sdmmc->divisor - 1) / sdmmc->divisor); // Wait 1ms + 10 clock cycles.
usleep(1000 + (10 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock);
if (!sdmmc_tuning_execute(storage->sdmmc, SDHCI_TIMING_MMC_DDR100, MMC_SEND_TUNING_BLOCK_HS200)) if (!sdmmc_tuning_execute(storage->sdmmc, SDHCI_TIMING_MMC_HS100, MMC_SEND_TUNING_BLOCK_HS200))
return 0; return 0;
DPRINTF("[gc] after tuning\n"); DPRINTF("[GC] after tuning\n");
sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE); sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE);

View File

@@ -34,9 +34,8 @@
//#define ERROR_EXTRA_PRINTING //#define ERROR_EXTRA_PRINTING
#define DPRINTF(...) #define DPRINTF(...)
#ifdef BDK_SDMMC_OC_AND_EXTRA_PRINT #ifdef BDK_SDMMC_EXTRA_PRINT
#define ERROR_EXTRA_PRINTING #define ERROR_EXTRA_PRINTING
#define SDMMC_EMMC_OC
#endif #endif
/*! SCMMC controller base addresses. */ /*! SCMMC controller base addresses. */
@@ -109,13 +108,13 @@ void sdmmc_set_bus_width(sdmmc_t *sdmmc, u32 bus_width)
void sdmmc_save_tap_value(sdmmc_t *sdmmc) void sdmmc_save_tap_value(sdmmc_t *sdmmc)
{ {
sdmmc->venclkctl_tap = sdmmc->regs->venclkctl >> 16; sdmmc->venclkctl_tap = (sdmmc->regs->venclkctl & 0xFF0000) >> 16;
sdmmc->venclkctl_set = 1; sdmmc->venclkctl_set = 1;
} }
static int _sdmmc_config_tap_val(sdmmc_t *sdmmc, u32 type) static int _sdmmc_config_tap_val(sdmmc_t *sdmmc, u32 type)
{ {
const u32 dqs_trim_val = 0x28; const u32 dqs_trim_val = 40; // 24 if HS533/HS667.
const u8 tap_values_t210[4] = { 4, 0, 3, 0 }; const u8 tap_values_t210[4] = { 4, 0, 3, 0 };
u32 tap_val = 0; u32 tap_val = 0;
@@ -123,7 +122,7 @@ static int _sdmmc_config_tap_val(sdmmc_t *sdmmc, u32 type)
if (type == SDHCI_TIMING_MMC_HS400) if (type == SDHCI_TIMING_MMC_HS400)
sdmmc->regs->vencapover = (sdmmc->regs->vencapover & 0xFFFFC0FF) | (dqs_trim_val << 8); sdmmc->regs->vencapover = (sdmmc->regs->vencapover & 0xFFFFC0FF) | (dqs_trim_val << 8);
sdmmc->regs->ventunctl0 &= ~TEGRA_MMC_VNDR_TUN_CTRL0_TAP_VAL_UPDATED_BY_HW; sdmmc->regs->ventunctl0 &= ~SDHCI_TEGRA_TUNING_TAP_HW_UPDATED;
if (type == SDHCI_TIMING_MMC_HS400) if (type == SDHCI_TIMING_MMC_HS400)
{ {
@@ -189,21 +188,21 @@ static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power)
sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN;
} }
// Enable E_INPUT power. // Enable E_INPUT (SD) or Disable E_PWRD (eMMC) power.
if (!(sdmmc->regs->sdmemcmppadctl & TEGRA_MMC_SDMEMCOMPPADCTRL_PAD_E_INPUT_PWRD)) if (!(sdmmc->regs->sdmemcmppadctl & SDHCI_TEGRA_PADCTRL_E_INPUT_PWRD))
{ {
sdmmc->regs->sdmemcmppadctl |= TEGRA_MMC_SDMEMCOMPPADCTRL_PAD_E_INPUT_PWRD; sdmmc->regs->sdmemcmppadctl |= SDHCI_TEGRA_PADCTRL_E_INPUT_PWRD;
_sdmmc_commit_changes(sdmmc); _sdmmc_commit_changes(sdmmc);
usleep(1); usleep(1);
} }
// Enable auto calibration and start auto configuration. // Enable auto calibration and start auto configuration.
sdmmc->regs->autocalcfg |= TEGRA_MMC_AUTOCALCFG_AUTO_CAL_ENABLE | TEGRA_MMC_AUTOCALCFG_AUTO_CAL_START; sdmmc->regs->autocalcfg |= SDHCI_TEGRA_AUTOCAL_ENABLE | SDHCI_TEGRA_AUTOCAL_START;
_sdmmc_commit_changes(sdmmc); _sdmmc_commit_changes(sdmmc);
usleep(2); usleep(2);
u32 timeout = get_tmr_ms() + 10; u32 timeout = get_tmr_ms() + 10;
while (sdmmc->regs->autocalsts & TEGRA_MMC_AUTOCALSTS_AUTO_CAL_ACTIVE) while (sdmmc->regs->autocalsts & SDHCI_TEGRA_AUTOCAL_ACTIVE)
{ {
if (get_tmr_ms() > timeout) if (get_tmr_ms() > timeout)
{ {
@@ -226,22 +225,18 @@ static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power)
// In case auto calibration fails, we load suggested standard values. // In case auto calibration fails, we load suggested standard values.
if (!timeout) if (!timeout)
{ {
sdmmc->regs->autocalcfg &= ~SDHCI_TEGRA_AUTOCAL_ENABLE;
_sdmmc_pad_config_fallback(sdmmc, power); _sdmmc_pad_config_fallback(sdmmc, power);
sdmmc->regs->autocalcfg &= ~TEGRA_MMC_AUTOCALCFG_AUTO_CAL_ENABLE;
} }
// Disable E_INPUT to conserve power. // Disable E_INPUT (SD) or enable E_PWRD (eMMC) to conserve power.
sdmmc->regs->sdmemcmppadctl &= ~TEGRA_MMC_SDMEMCOMPPADCTRL_PAD_E_INPUT_PWRD; sdmmc->regs->sdmemcmppadctl &= ~SDHCI_TEGRA_PADCTRL_E_INPUT_PWRD;
if (should_enable_sd_clock) if (should_enable_sd_clock)
sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN;
} }
#ifdef SDMMC_EMMC_OC
static int _sdmmc_dll_cal_execute(sdmmc_t *sdmmc, bool overclock)
#else
static int _sdmmc_dll_cal_execute(sdmmc_t *sdmmc) static int _sdmmc_dll_cal_execute(sdmmc_t *sdmmc)
#endif
{ {
int result = 1, should_disable_sd_clock = 0; int result = 1, should_disable_sd_clock = 0;
@@ -251,17 +246,15 @@ static int _sdmmc_dll_cal_execute(sdmmc_t *sdmmc)
sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN;
} }
#ifdef SDMMC_EMMC_OC // Add -4 TX_DLY_CODE_OFFSET if HS533/HS667.
// Add -4 TX_DLY_CODE_OFFSET if HS533. // if (sdmmc->id == SDMMC_4 && sdmmc->card_clock > 208000)
if (sdmmc->id == SDMMC_4 && overclock) // sdmmc->regs->vendllctl0 = sdmmc->regs->vendllctl0 &= 0xFFFFC07F | (0x7C << 7);
sdmmc->regs->vendllcalcfg = sdmmc->regs->vendllcalcfg &= 0xFFFFC07F | (0x7C << 7);
#endif
sdmmc->regs->vendllcalcfg |= TEGRA_MMC_DLLCAL_CFG_EN_CALIBRATE; sdmmc->regs->vendllcalcfg |= SDHCI_TEGRA_DLLCAL_CALIBRATE;
_sdmmc_commit_changes(sdmmc); _sdmmc_commit_changes(sdmmc);
u32 timeout = get_tmr_ms() + 5; u32 timeout = get_tmr_ms() + 5;
while (sdmmc->regs->vendllcalcfg & TEGRA_MMC_DLLCAL_CFG_EN_CALIBRATE) while (sdmmc->regs->vendllcalcfg & SDHCI_TEGRA_DLLCAL_CALIBRATE)
{ {
if (get_tmr_ms() > timeout) if (get_tmr_ms() > timeout)
{ {
@@ -271,7 +264,7 @@ static int _sdmmc_dll_cal_execute(sdmmc_t *sdmmc)
} }
timeout = get_tmr_ms() + 10; timeout = get_tmr_ms() + 10;
while (sdmmc->regs->vendllcalcfgsts & TEGRA_MMC_DLLCAL_CFG_STATUS_DLL_ACTIVE) while (sdmmc->regs->vendllcalcfgsts & SDHCI_TEGRA_DLLCAL_ACTIVE)
{ {
if (get_tmr_ms() > timeout) if (get_tmr_ms() > timeout)
{ {
@@ -286,7 +279,7 @@ out:;
return result; return result;
} }
static void _sdmmc_reset(sdmmc_t *sdmmc) static void _sdmmc_reset_cmd_data(sdmmc_t *sdmmc)
{ {
sdmmc->regs->swrst |= SDHCI_RESET_CMD | SDHCI_RESET_DATA; sdmmc->regs->swrst |= SDHCI_RESET_CMD | SDHCI_RESET_DATA;
_sdmmc_commit_changes(sdmmc); _sdmmc_commit_changes(sdmmc);
@@ -304,6 +297,13 @@ static void _sdmmc_reset_all(sdmmc_t *sdmmc)
; ;
} }
void sdmmc_setup_drv_type(sdmmc_t *sdmmc, u32 type)
{
sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & (~SDHCI_CTRL_DRV_TYPE_MASK)) | SDHCI_CTRL_DRV_TYPE(type);
_sdmmc_commit_changes(sdmmc);
}
int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type) int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
{ {
// Disable the SD clock if it was enabled, and reenable it later. // Disable the SD clock if it was enabled, and reenable it later.
@@ -316,7 +316,7 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
_sdmmc_config_tap_val(sdmmc, type); _sdmmc_config_tap_val(sdmmc, type);
_sdmmc_reset(sdmmc); _sdmmc_reset_cmd_data(sdmmc);
switch (type) switch (type)
{ {
@@ -330,22 +330,20 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
case SDHCI_TIMING_MMC_HS52: case SDHCI_TIMING_MMC_HS52:
case SDHCI_TIMING_SD_HS25: case SDHCI_TIMING_SD_HS25:
sdmmc->regs->hostctl |= SDHCI_CTRL_HISPD; // SD only? sdmmc->regs->hostctl |= SDHCI_CTRL_HISPD;
sdmmc->regs->hostctl2 &= ~SDHCI_CTRL_VDD_180; sdmmc->regs->hostctl2 &= ~SDHCI_CTRL_VDD_180;
break; break;
case SDHCI_TIMING_MMC_HS200: case SDHCI_TIMING_MMC_HS200:
case SDHCI_TIMING_UHS_SDR50: // T210 Errata for SDR50, the host must be set to SDR104. case SDHCI_TIMING_UHS_SDR50: // T210 Errata: the host must be set to SDR104 to WAR a CRC issue.
case SDHCI_TIMING_UHS_SDR104: case SDHCI_TIMING_UHS_SDR104:
case SDHCI_TIMING_UHS_SDR82: case SDHCI_TIMING_UHS_SDR82:
case SDHCI_TIMING_UHS_DDR50: case SDHCI_TIMING_MMC_HS100:
case SDHCI_TIMING_MMC_DDR100:
sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & (~SDHCI_CTRL_UHS_MASK)) | UHS_SDR104_BUS_SPEED; sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & (~SDHCI_CTRL_UHS_MASK)) | UHS_SDR104_BUS_SPEED;
sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180; sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180;
break; break;
case SDHCI_TIMING_MMC_HS400: case SDHCI_TIMING_MMC_HS400:
// Non standard.
sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & (~SDHCI_CTRL_UHS_MASK)) | HS400_BUS_SPEED; sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & (~SDHCI_CTRL_UHS_MASK)) | HS400_BUS_SPEED;
sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180; sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180;
break; break;
@@ -359,6 +357,14 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & (~SDHCI_CTRL_UHS_MASK)) | UHS_SDR12_BUS_SPEED; sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & (~SDHCI_CTRL_UHS_MASK)) | UHS_SDR12_BUS_SPEED;
sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180; sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180;
break; break;
case SDHCI_TIMING_UHS_DDR50:
#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT
case SDHCI_TIMING_UHS_DDR200:
#endif
sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & (~SDHCI_CTRL_UHS_MASK)) | UHS_DDR50_BUS_SPEED;
sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180;
break;
} }
_sdmmc_commit_changes(sdmmc); _sdmmc_commit_changes(sdmmc);
@@ -367,31 +373,24 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
u16 divisor; u16 divisor;
clock_sdmmc_get_card_clock_div(&clock, &divisor, type); clock_sdmmc_get_card_clock_div(&clock, &divisor, type);
clock_sdmmc_config_clock_source(&clock, sdmmc->id, clock); clock_sdmmc_config_clock_source(&clock, sdmmc->id, clock);
sdmmc->divisor = (clock + divisor - 1) / divisor; sdmmc->card_clock = (clock + divisor - 1) / divisor;
//if divisor != 1 && divisor << 31 -> error //if divisor != 1 && divisor << 31 -> error
u16 div = divisor >> 1; u16 div_lo = divisor >> 1;
divisor = 0; u16 div_hi = 0;
if (div > 0xFF) if (div_lo > 0xFF)
divisor = div >> SDHCI_DIVIDER_SHIFT; div_hi = div_lo >> SDHCI_DIV_LO_SHIFT;
sdmmc->regs->clkcon = (sdmmc->regs->clkcon & ~(SDHCI_DIV_MASK | SDHCI_DIV_HI_MASK)) sdmmc->regs->clkcon = (sdmmc->regs->clkcon & ~(SDHCI_DIV_MASK | SDHCI_DIV_HI_MASK)) |
| (div << SDHCI_DIVIDER_SHIFT) | (divisor << SDHCI_DIVIDER_HI_SHIFT); (div_lo << SDHCI_DIV_LO_SHIFT) | (div_hi << SDHCI_DIV_HI_SHIFT);
// Enable the SD clock again. // Enable the SD clock again.
if (should_enable_sd_clock) if (should_enable_sd_clock)
sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN;
if (type == SDHCI_TIMING_MMC_HS400) if (type == SDHCI_TIMING_MMC_HS400)
{
#ifdef SDMMC_EMMC_OC
bool overclock_en = clock > 208000;
return _sdmmc_dll_cal_execute(sdmmc, overclock_en);
#else
return _sdmmc_dll_cal_execute(sdmmc); return _sdmmc_dll_cal_execute(sdmmc);
#endif
}
return 1; return 1;
} }
@@ -524,7 +523,7 @@ static int _sdmmc_wait_cmd_data_inhibit(sdmmc_t *sdmmc, bool wait_dat)
while (sdmmc->regs->prnsts & SDHCI_CMD_INHIBIT) while (sdmmc->regs->prnsts & SDHCI_CMD_INHIBIT)
if (get_tmr_ms() > timeout) if (get_tmr_ms() > timeout)
{ {
_sdmmc_reset(sdmmc); _sdmmc_reset_cmd_data(sdmmc);
return 0; return 0;
} }
@@ -534,7 +533,7 @@ static int _sdmmc_wait_cmd_data_inhibit(sdmmc_t *sdmmc, bool wait_dat)
while (sdmmc->regs->prnsts & SDHCI_DATA_INHIBIT) while (sdmmc->regs->prnsts & SDHCI_DATA_INHIBIT)
if (get_tmr_ms() > timeout) if (get_tmr_ms() > timeout)
{ {
_sdmmc_reset(sdmmc); _sdmmc_reset_cmd_data(sdmmc);
return 0; return 0;
} }
} }
@@ -550,7 +549,7 @@ static int _sdmmc_wait_card_busy(sdmmc_t *sdmmc)
while (!(sdmmc->regs->prnsts & SDHCI_DATA_0_LVL)) while (!(sdmmc->regs->prnsts & SDHCI_DATA_0_LVL))
if (get_tmr_ms() > timeout) if (get_tmr_ms() > timeout)
{ {
_sdmmc_reset(sdmmc); _sdmmc_reset_cmd_data(sdmmc);
return 0; return 0;
} }
@@ -611,8 +610,9 @@ static int _sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, bool is_data_presen
if (is_data_present) if (is_data_present)
cmdflags |= SDHCI_CMD_DATA; cmdflags |= SDHCI_CMD_DATA;
sdmmc->regs->argument = cmd->arg; sdmmc->regs->argument = cmd->arg;
sdmmc->regs->cmdreg = (cmd->cmd << 8) | cmdflags; sdmmc->regs->cmdreg = SDHCI_CMD_IDX(cmd->cmd) | cmdflags;
return 1; return 1;
} }
@@ -627,10 +627,8 @@ static void _sdmmc_send_tuning_cmd(sdmmc_t *sdmmc, u32 cmd)
_sdmmc_send_cmd(sdmmc, &cmdbuf, true); _sdmmc_send_cmd(sdmmc, &cmdbuf, true);
} }
static int _sdmmc_tuning_execute_once(sdmmc_t *sdmmc, u32 cmd) static int _sdmmc_tuning_execute_once(sdmmc_t *sdmmc, u32 cmd, u32 tap)
{ {
if (sdmmc->powersave_enabled)
return 0;
if (!_sdmmc_wait_cmd_data_inhibit(sdmmc, true)) if (!_sdmmc_wait_cmd_data_inhibit(sdmmc, true))
return 0; return 0;
@@ -640,11 +638,21 @@ static int _sdmmc_tuning_execute_once(sdmmc_t *sdmmc, u32 cmd)
sdmmc->regs->norintsts = sdmmc->regs->norintsts; sdmmc->regs->norintsts = sdmmc->regs->norintsts;
sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN;
#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT
// Set tap if manual tuning.
if (tap != HW_TAP_TUNING)
{
sdmmc->regs->ventunctl0 &= ~SDHCI_TEGRA_TUNING_TAP_HW_UPDATED;
sdmmc->regs->venclkctl = (sdmmc->regs->venclkctl & 0xFF00FFFF) | (tap << 16);
sdmmc->regs->ventunctl0 |= SDHCI_TEGRA_TUNING_TAP_HW_UPDATED;
}
#endif
_sdmmc_send_tuning_cmd(sdmmc, cmd); _sdmmc_send_tuning_cmd(sdmmc, cmd);
_sdmmc_commit_changes(sdmmc); _sdmmc_commit_changes(sdmmc);
usleep(1); usleep(1);
_sdmmc_reset(sdmmc); _sdmmc_reset_cmd_data(sdmmc);
sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN;
_sdmmc_commit_changes(sdmmc); _sdmmc_commit_changes(sdmmc);
@@ -657,59 +665,167 @@ static int _sdmmc_tuning_execute_once(sdmmc_t *sdmmc, u32 cmd)
sdmmc->regs->norintsts = SDHCI_INT_DATA_AVAIL; sdmmc->regs->norintsts = SDHCI_INT_DATA_AVAIL;
sdmmc->regs->norintstsen &= ~SDHCI_INT_DATA_AVAIL; sdmmc->regs->norintstsen &= ~SDHCI_INT_DATA_AVAIL;
_sdmmc_commit_changes(sdmmc); _sdmmc_commit_changes(sdmmc);
usleep((1000 * 8 + sdmmc->divisor - 1) / sdmmc->divisor); usleep((8 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock); // Wait 8 cycles.
return 1; return 1;
} }
} }
_sdmmc_reset(sdmmc); _sdmmc_reset_cmd_data(sdmmc);
sdmmc->regs->norintstsen &= ~SDHCI_INT_DATA_AVAIL; sdmmc->regs->norintstsen &= ~SDHCI_INT_DATA_AVAIL;
_sdmmc_commit_changes(sdmmc); _sdmmc_commit_changes(sdmmc);
usleep((1000 * 8 + sdmmc->divisor - 1) / sdmmc->divisor); usleep((8 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock); // Wait 8 cycles.
return 0; return 0;
} }
#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT
typedef struct _sdmmc_manual_tuning_t
{
u32 result[8];
u32 num_iter;
u32 tap_start;
u32 tap_end;
} sdmmc_manual_tuning_t;
static int _sdmmc_manual_tuning_set_tap(sdmmc_t *sdmmc, sdmmc_manual_tuning_t *tuning)
{
u32 tap_start = INVALID_TAP;
u32 win_size = 0;
u32 best_tap = 0;
u32 best_size = 0;
for (u32 i = 0; i < tuning->num_iter; i++)
{
u32 iter_end = i == (tuning->num_iter - 1) ? 1 : 0;
u32 stable = tuning->result[i / 32] & BIT(i % 32);
if (stable && !iter_end)
{
if (tap_start == INVALID_TAP)
tap_start = i;
win_size++;
}
else
{
if (tap_start != INVALID_TAP)
{
u32 tap_end = !iter_end ? (i - 1) : i;
// Check if window is wider.
if (win_size > best_size)
{
best_tap = (tap_start + tap_end) / 2;
best_size = win_size + iter_end;
}
tap_start = INVALID_TAP;
win_size = 0;
}
}
}
// Check if failed.
if (!best_tap)
return 0;
sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN;
sdmmc->regs->ventunctl0 &= ~SDHCI_TEGRA_TUNING_TAP_HW_UPDATED;
// Set tap.
sdmmc->regs->venclkctl = (sdmmc->regs->venclkctl & 0xFF00FFFF) | (best_tap << 16);
sdmmc->regs->ventunctl0 |= SDHCI_TEGRA_TUNING_TAP_HW_UPDATED;
sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN;
return 1;
}
/*
* SD Card DDR200 (DDR208) support
*
* On Tegra X1, that can be done with DDR50 host mode.
* Tuning though can't be done automatically on any DDR mode.
* So it needs to be done manually and selected tap will be applied from the biggest
* sampling window.
*/
static int sdmmc_tuning_execute_ddr200(sdmmc_t *sdmmc)
{
sdmmc_manual_tuning_t manual_tuning = { 0 };
manual_tuning.num_iter = 128;
sdmmc->regs->ventunctl1 = 0; // step_size 1.
sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFF1FFF) | (2 << 13); // 128 Tries.
sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFFE03F) | (1 << 6); // 1x Multiplier.
sdmmc->regs->ventunctl0 |= SDHCI_TEGRA_TUNING_TAP_HW_UPDATED;
sdmmc->regs->hostctl2 |= SDHCI_CTRL_EXEC_TUNING;
for (u32 i = 0; i < manual_tuning.num_iter; i++)
{
_sdmmc_tuning_execute_once(sdmmc, MMC_SEND_TUNING_BLOCK, i);
// Save result for manual tuning.
int sampled = (sdmmc->regs->hostctl2 >> SDHCI_CTRL_TUNED_CLK_SHIFT) & 1;
manual_tuning.result[i / 32] |= sampled << (i % 32);
if (!(sdmmc->regs->hostctl2 & SDHCI_CTRL_EXEC_TUNING))
break;
}
return _sdmmc_manual_tuning_set_tap(sdmmc, &manual_tuning);
}
#endif
int sdmmc_tuning_execute(sdmmc_t *sdmmc, u32 type, u32 cmd) int sdmmc_tuning_execute(sdmmc_t *sdmmc, u32 type, u32 cmd)
{ {
u32 max = 0, flag = 0; u32 num_iter, flag;
if (sdmmc->powersave_enabled)
return 0;
switch (type) switch (type)
{ {
case SDHCI_TIMING_MMC_HS200: case SDHCI_TIMING_MMC_HS200:
case SDHCI_TIMING_MMC_HS400:
case SDHCI_TIMING_UHS_SDR104: case SDHCI_TIMING_UHS_SDR104:
case SDHCI_TIMING_UHS_SDR82: case SDHCI_TIMING_UHS_SDR82:
max = 128; num_iter = 128;
flag = (2 << 13); // 128 iterations. flag = (2 << 13); // 128 iterations.
break; break;
case SDHCI_TIMING_UHS_SDR50: case SDHCI_TIMING_UHS_SDR50:
case SDHCI_TIMING_UHS_DDR50: case SDHCI_TIMING_UHS_DDR50: // HW tuning is not supported on DDR modes. But it sets tap to 0 which is proper.
case SDHCI_TIMING_MMC_DDR100: case SDHCI_TIMING_MMC_HS100:
max = 256; num_iter = 256;
flag = (4 << 13); // 256 iterations. flag = (4 << 13); // 256 iterations.
break; break;
case SDHCI_TIMING_MMC_HS400:
case SDHCI_TIMING_UHS_SDR12: case SDHCI_TIMING_UHS_SDR12:
case SDHCI_TIMING_UHS_SDR25: case SDHCI_TIMING_UHS_SDR25:
return 1; return 1;
#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT
case SDHCI_TIMING_UHS_DDR200:
return sdmmc_tuning_execute_ddr200(sdmmc);
#endif
default: default:
return 0; return 0;
} }
sdmmc->regs->ventunctl1 = 0; // step_size 1. sdmmc->regs->ventunctl1 = 0; // step_size 1.
sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFF1FFF) | flag; // Tries.
sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFFE03F) | (1 << 6); // 1x Multiplier.
sdmmc->regs->ventunctl0 |= SDHCI_TEGRA_TUNING_TAP_HW_UPDATED;
sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFF1FFF) | flag; // Tries.
sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFFE03F) | (1 << 6); // 1x Multiplier.
sdmmc->regs->ventunctl0 |= TEGRA_MMC_VNDR_TUN_CTRL0_TAP_VAL_UPDATED_BY_HW;
sdmmc->regs->hostctl2 |= SDHCI_CTRL_EXEC_TUNING; sdmmc->regs->hostctl2 |= SDHCI_CTRL_EXEC_TUNING;
for (u32 i = 0; i < max; i++) for (u32 i = 0; i < num_iter; i++)
{ {
_sdmmc_tuning_execute_once(sdmmc, cmd); _sdmmc_tuning_execute_once(sdmmc, cmd, HW_TAP_TUNING);
if (!(sdmmc->regs->hostctl2 & SDHCI_CTRL_EXEC_TUNING)) if (!(sdmmc->regs->hostctl2 & SDHCI_CTRL_EXEC_TUNING))
break; break;
} }
@@ -737,7 +853,7 @@ static int _sdmmc_enable_internal_clock(sdmmc_t *sdmmc)
// Enable 32bit addressing if used (sysad. if blkcnt it fallbacks to 16bit). // Enable 32bit addressing if used (sysad. if blkcnt it fallbacks to 16bit).
sdmmc->regs->hostctl2 |= SDHCI_HOST_VERSION_4_EN; sdmmc->regs->hostctl2 |= SDHCI_HOST_VERSION_4_EN;
if (!(sdmmc->regs->capareg & SDHCI_CAN_64BIT)) if (!(sdmmc->regs->capareg & SDHCI_CAP_64BIT))
return 0; return 0;
sdmmc->regs->hostctl2 |= SDHCI_ADDRESSING_64BIT_EN; sdmmc->regs->hostctl2 |= SDHCI_ADDRESSING_64BIT_EN;
@@ -767,8 +883,8 @@ static int _sdmmc_autocal_config_offset(sdmmc_t *sdmmc, u32 power)
{ {
if (!sdmmc->t210b01) if (!sdmmc->t210b01)
{ {
off_pd = 123; off_pd = 0x7B; // -5.
off_pu = 123; off_pu = 0x7B; // -5.
} }
else else
{ {
@@ -780,7 +896,7 @@ static int _sdmmc_autocal_config_offset(sdmmc_t *sdmmc, u32 power)
{ {
if (!sdmmc->t210b01) if (!sdmmc->t210b01)
{ {
off_pd = 125; off_pd = 0x7D; // -3.
off_pu = 0; off_pu = 0;
} }
} }
@@ -812,7 +928,7 @@ static u32 _sdmmc_check_mask_interrupt(sdmmc_t *sdmmc, u16 *pout, u16 mask)
u16 norintsts = sdmmc->regs->norintsts; u16 norintsts = sdmmc->regs->norintsts;
u16 errintsts = sdmmc->regs->errintsts; u16 errintsts = sdmmc->regs->errintsts;
DPRINTF("norintsts %08X, errintsts %08X\n", norintsts, errintsts); DPRINTF("norintsts %08X, errintsts %08X\n", norintsts, errintsts);
if (pout) if (pout)
*pout = norintsts; *pout = norintsts;
@@ -847,7 +963,7 @@ static int _sdmmc_wait_response(sdmmc_t *sdmmc)
break; break;
if (result != SDMMC_MASKINT_NOERROR || get_tmr_ms() > timeout) if (result != SDMMC_MASKINT_NOERROR || get_tmr_ms() > timeout)
{ {
_sdmmc_reset(sdmmc); _sdmmc_reset_cmd_data(sdmmc);
return 0; return 0;
} }
} }
@@ -897,11 +1013,11 @@ int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp)
should_disable_sd_clock = true; should_disable_sd_clock = true;
sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN;
_sdmmc_commit_changes(sdmmc); _sdmmc_commit_changes(sdmmc);
usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor); usleep((8 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock); // Wait 8 cycles.
} }
int result = _sdmmc_stop_transmission_inner(sdmmc, rsp); int result = _sdmmc_stop_transmission_inner(sdmmc, rsp);
usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor); usleep((8 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock); // Wait 8 cycles.
if (should_disable_sd_clock) if (should_disable_sd_clock)
sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN;
@@ -934,9 +1050,9 @@ static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req)
if (blkcnt_out) if (blkcnt_out)
*blkcnt_out = blkcnt; *blkcnt_out = blkcnt;
u32 trnmode = SDHCI_TRNS_DMA; u32 trnmode = SDHCI_TRNS_DMA | SDHCI_TRNS_RTYPE_R1;
// Set mulitblock request. // Set multiblock request.
if (req->is_multi_block) if (req->is_multi_block)
trnmode |= SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN; trnmode |= SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN;
@@ -988,15 +1104,17 @@ static int _sdmmc_update_dma(sdmmc_t *sdmmc)
if (result != SDMMC_MASKINT_NOERROR) if (result != SDMMC_MASKINT_NOERROR)
{ {
#ifdef ERROR_EXTRA_PRINTING #ifdef ERROR_EXTRA_PRINTING
EPRINTFARGS("SDMMC%d: %08X!", sdmmc->id + 1, result); EPRINTFARGS("SDMMC%d: int error!", sdmmc->id + 1);
#endif #endif
_sdmmc_reset(sdmmc); _sdmmc_reset_cmd_data(sdmmc);
return 0; return 0;
} }
} while (get_tmr_ms() < timeout); } while (get_tmr_ms() < timeout);
} while (sdmmc->regs->blkcnt != blkcnt); } while (sdmmc->regs->blkcnt != blkcnt);
_sdmmc_reset(sdmmc); _sdmmc_reset_cmd_data(sdmmc);
return 0; return 0;
} }
@@ -1039,7 +1157,7 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
if (!result) if (!result)
EPRINTFARGS("SDMMC%d: Transfer timeout!", sdmmc->id + 1); EPRINTFARGS("SDMMC%d: Transfer timeout!", 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->rspreg0, sdmmc->regs->rspreg1, sdmmc->regs->rspreg2, sdmmc->regs->rspreg3);
if (result) if (result)
{ {
@@ -1171,6 +1289,7 @@ static int _sdmmc_config_sdmmc1(bool t210b01)
APB_MISC(APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL) = 1; APB_MISC(APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL) = 1;
// Configure SDMMC1 CLK pinmux, based on state and SoC type. // Configure SDMMC1 CLK pinmux, based on state and SoC type.
PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) &= ~PINMUX_SCHMT;
if (PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) != (PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PULL_DOWN)) // Check if CLK pad is already configured. if (PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) != (PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PULL_DOWN)) // Check if CLK pad is already configured.
PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | (t210b01 ? PINMUX_PULL_NONE : PINMUX_PULL_DOWN); PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | (t210b01 ? PINMUX_PULL_NONE : PINMUX_PULL_DOWN);
@@ -1244,7 +1363,7 @@ static void _sdmmc_config_emmc(u32 id, bool t210b01)
} }
} }
int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int powersave_enable) int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type)
{ {
u32 clock; u32 clock;
u16 divisor; u16 divisor;
@@ -1301,11 +1420,10 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int p
sdmmc->clock_stopped = 0; sdmmc->clock_stopped = 0;
// Set default pad IO trimming configuration. // Set default pad IO trimming configuration.
sdmmc->regs->iospare |= 0x80000; // Enable muxing. sdmmc->regs->iospare |= BIT(19); // Enable 1 cycle delayed cmd_oen.
sdmmc->regs->veniotrimctl &= 0xFFFFFFFB; // Set Band Gap VREG to supply DLL. sdmmc->regs->veniotrimctl &= ~BIT(2); // Set Band Gap VREG to supply DLL.
sdmmc->regs->venclkctl = (sdmmc->regs->venclkctl & 0xE0FFFFFB) | ((u32)trim_values[sdmmc->id] << 24); sdmmc->regs->venclkctl = (sdmmc->regs->venclkctl & 0xE0FFFFFB) | ((u32)trim_values[sdmmc->id] << 24);
sdmmc->regs->sdmemcmppadctl = sdmmc->regs->sdmemcmppadctl = (sdmmc->regs->sdmemcmppadctl & ~SDHCI_TEGRA_PADCTRL_VREF_SEL_MASK) | vref_sel;
(sdmmc->regs->sdmemcmppadctl & TEGRA_MMC_SDMEMCOMPPADCTRL_COMP_VREF_SEL_MASK) | vref_sel;
// Configure auto calibration values. // Configure auto calibration values.
if (!_sdmmc_autocal_config_offset(sdmmc, power)) if (!_sdmmc_autocal_config_offset(sdmmc, power))
@@ -1322,7 +1440,7 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int p
if (sdmmc_setup_clock(sdmmc, type)) if (sdmmc_setup_clock(sdmmc, type))
{ {
sdmmc_card_clock_powersave(sdmmc, powersave_enable); sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_DISABLE);
_sdmmc_card_clock_enable(sdmmc); _sdmmc_card_clock_enable(sdmmc);
_sdmmc_commit_changes(sdmmc); _sdmmc_commit_changes(sdmmc);
@@ -1408,11 +1526,11 @@ int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *b
should_disable_sd_clock = 1; should_disable_sd_clock = 1;
sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN;
_sdmmc_commit_changes(sdmmc); _sdmmc_commit_changes(sdmmc);
usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor); usleep((8 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock); // Wait 8 cycles.
} }
int result = _sdmmc_execute_cmd_inner(sdmmc, cmd, req, blkcnt_out); int result = _sdmmc_execute_cmd_inner(sdmmc, cmd, req, blkcnt_out);
usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor); usleep((8 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock); // Wait 8 cycles.
if (should_disable_sd_clock) if (should_disable_sd_clock)
sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN;
@@ -1425,9 +1543,6 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc)
if (sdmmc->id != SDMMC_1) if (sdmmc->id != SDMMC_1)
return 0; return 0;
if (!sdmmc_setup_clock(sdmmc, SDHCI_TIMING_UHS_SDR12))
return 0;
_sdmmc_commit_changes(sdmmc); _sdmmc_commit_changes(sdmmc);
// Switch to 1.8V and wait for regulator to stabilize. Assume max possible wait needed. // Switch to 1.8V and wait for regulator to stabilize. Assume max possible wait needed.

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2022 CTCaer * Copyright (c) 2018-2023 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,
@@ -32,11 +32,6 @@
#define SDMMC_POWER_1_8 1 #define SDMMC_POWER_1_8 1
#define SDMMC_POWER_3_3 2 #define SDMMC_POWER_3_3 2
/*! SDMMC bus widths. */
#define SDMMC_BUS_WIDTH_1 0
#define SDMMC_BUS_WIDTH_4 1
#define SDMMC_BUS_WIDTH_8 2
/*! SDMMC response types. */ /*! SDMMC response types. */
#define SDMMC_RSP_TYPE_0 0 #define SDMMC_RSP_TYPE_0 0
#define SDMMC_RSP_TYPE_1 1 #define SDMMC_RSP_TYPE_1 1
@@ -45,25 +40,30 @@
#define SDMMC_RSP_TYPE_4 4 #define SDMMC_RSP_TYPE_4 4
#define SDMMC_RSP_TYPE_5 5 #define SDMMC_RSP_TYPE_5 5
/*! SDMMC bus widths. */
#define SDMMC_BUS_WIDTH_1 0
#define SDMMC_BUS_WIDTH_4 1
#define SDMMC_BUS_WIDTH_8 2
/*! SDMMC mask interrupt status. */ /*! SDMMC mask interrupt status. */
#define SDMMC_MASKINT_MASKED 0 #define SDMMC_MASKINT_MASKED 0
#define SDMMC_MASKINT_NOERROR 1 #define SDMMC_MASKINT_NOERROR 1
#define SDMMC_MASKINT_ERROR 2 #define SDMMC_MASKINT_ERROR 2
/*! SDMMC present state. */ /*! SDMMC present state. 0x24. */
#define SDHCI_CMD_INHIBIT BIT(0) #define SDHCI_CMD_INHIBIT BIT(0)
#define SDHCI_DATA_INHIBIT BIT(1) #define SDHCI_DATA_INHIBIT BIT(1)
#define SDHCI_DAT_LINE_ACTIVE BIT(2) #define SDHCI_DAT_LINE_ACTIVE BIT(2)
#define SDHCI_RETUNING_REQUEST BIT(3) #define SDHCI_RETUNING_REQUEST BIT(3)
#define SDHCI_EMMC_LINE_LVL_MASK 0xF0 #define SDHCI_EMMC_LINE_LVL_MASK (0xFU << 4)
#define SDHCI_DATA_4_LVL BIT(4) // eMMC only. #define SDHCI_DATA_4_LVL BIT(4) // eMMC only.
#define SDHCI_DATA_5_LVL BIT(5) // eMMC only. #define SDHCI_DATA_5_LVL BIT(5) // eMMC only.
#define SDHCI_DATA_6_LVL BIT(6) // eMMC only. #define SDHCI_DATA_6_LVL BIT(6) // eMMC only.
#define SDHCI_DATA_7_LVL BIT(7) // eMMC only. #define SDHCI_DATA_7_LVL BIT(7) // eMMC only.
#define SDHCI_DOING_WRITE BIT(8) #define SDHCI_DOING_WRITE BIT(8)
#define SDHCI_DOING_READ BIT(9) // SD only. #define SDHCI_DOING_READ BIT(9) // SD only.
#define SDHCI_SPACE_AVAILABLE BIT(10) #define SDHCI_SPACE_AVAILABLE BIT(10) // Write buffer empty.
#define SDHCI_DATA_AVAILABLE BIT(11) #define SDHCI_DATA_AVAILABLE BIT(11) // Read buffer has data.
#define SDHCI_CARD_PRESENT BIT(16) #define SDHCI_CARD_PRESENT BIT(16)
#define SDHCI_CD_STABLE BIT(17) #define SDHCI_CD_STABLE BIT(17)
#define SDHCI_CD_LVL BIT(18) #define SDHCI_CD_LVL BIT(18)
@@ -74,18 +74,21 @@
#define SDHCI_DATA_2_LVL BIT(22) #define SDHCI_DATA_2_LVL BIT(22)
#define SDHCI_DATA_3_LVL BIT(23) #define SDHCI_DATA_3_LVL BIT(23)
#define SDHCI_CMD_LVL BIT(24) #define SDHCI_CMD_LVL BIT(24)
#define SDHCI_CMD_NOT_ISSUED BIT(27)
/*! SDMMC transfer mode. */ /*! SDMMC transfer mode. 0x0C. */
#define SDHCI_TRNS_DMA BIT(0) #define SDHCI_TRNS_DMA BIT(0)
#define SDHCI_TRNS_BLK_CNT_EN BIT(1) #define SDHCI_TRNS_BLK_CNT_EN BIT(1)
#define SDHCI_TRNS_AUTO_CMD12 BIT(2) #define SDHCI_TRNS_AUTO_CMD12 (1U << 2)
#define SDHCI_TRNS_AUTO_CMD23 BIT(3) #define SDHCI_TRNS_AUTO_CMD23 (2U << 2)
#define SDHCI_TRNS_WRITE 0x00 // Bit4. #define SDHCI_TRNS_WRITE (0U << 4)
#define SDHCI_TRNS_READ BIT(4) #define SDHCI_TRNS_READ BIT(4)
#define SDHCI_TRNS_MULTI BIT(5) #define SDHCI_TRNS_MULTI BIT(5)
#define SDHCI_TRNS_RTYPE_R1 (0U << 6)
#define SDHCI_TRNS_RTYPE_R5 BIT(6)
#define SDHCI_TRNS_RSP_ERR_CHK BIT(7)
#define SDHCI_TRNS_RSP_INT_DIS BIT(8)
/*! SDMMC command. */ /*! SDMMC command. 0x0E. */
#define SDHCI_CMD_RESP_MASK 0x3 #define SDHCI_CMD_RESP_MASK 0x3
#define SDHCI_CMD_RESP_NO_RESP 0x0 #define SDHCI_CMD_RESP_NO_RESP 0x0
#define SDHCI_CMD_RESP_LEN136 0x1 #define SDHCI_CMD_RESP_LEN136 0x1
@@ -94,77 +97,79 @@
#define SDHCI_CMD_CRC BIT(3) #define SDHCI_CMD_CRC BIT(3)
#define SDHCI_CMD_INDEX BIT(4) #define SDHCI_CMD_INDEX BIT(4)
#define SDHCI_CMD_DATA BIT(5) #define SDHCI_CMD_DATA BIT(5)
#define SDHCI_CMD_ABORTCMD 0xC0 #define SDHCI_CMD_TYPE_NORMAL (0U << 6)
#define SDHCI_CMD_TYPE_SUSPEND (1U << 6)
#define SDHCI_CMD_TYPE_RESUME (2U << 6)
#define SDHCI_CMD_TYPE_ABORT (3U << 6)
#define SDHCI_CMD_IDX(cmd) ((cmd) << 8)
/*! SDMMC host control. */
/*! SDMMC host control. 0x28. */
#define SDHCI_CTRL_LED BIT(0) #define SDHCI_CTRL_LED BIT(0)
#define SDHCI_CTRL_4BITBUS BIT(1) // SD only. #define SDHCI_CTRL_4BITBUS BIT(1) // SD only.
#define SDHCI_CTRL_HISPD BIT(2) // SD only. #define SDHCI_CTRL_HISPD BIT(2) // SD only.
#define SDHCI_CTRL_DMA_MASK 0x18 #define SDHCI_CTRL_DMA_MASK (3U << 3)
#define SDHCI_CTRL_SDMA 0x00 #define SDHCI_CTRL_SDMA (0U << 3)
#define SDHCI_CTRL_ADMA1 0x08 #define SDHCI_CTRL_ADMA1 (1U << 3)
#define SDHCI_CTRL_ADMA32 0x10 #define SDHCI_CTRL_ADMA32 (2U << 3)
#define SDHCI_CTRL_ADMA64 0x18 #define SDHCI_CTRL_ADMA64 (3U << 3)
#define SDHCI_CTRL_8BITBUS BIT(5) // eMMC only (or UHS-II). #define SDHCI_CTRL_8BITBUS BIT(5) // eMMC only (or UHS-II).
#define SDHCI_CTRL_CDTEST_INS BIT(6) #define SDHCI_CTRL_CDTEST_INS BIT(6)
#define SDHCI_CTRL_CDTEST_EN BIT(7) #define SDHCI_CTRL_CDTEST_EN BIT(7)
/*! SDMMC host control 2. */ /*! SDMMC host control 2. 0x3E. */
#define SDHCI_CTRL_UHS_MASK 0x7 #define SDHCI_CTRL_UHS_MASK 0x7
#define SDHCI_CTRL_VDD_180 BIT(3) #define SDHCI_CTRL_VDD_180 BIT(3)
#define SDHCI_CTRL_DRV_TYPE_B (0U << 4) #define SDHCI_CTRL_DRV_TYPE_MASK (3U << 4)
#define SDHCI_CTRL_DRV_TYPE_A (1U << 4) #define SDHCI_CTRL_DRV_TYPE_B (0U << 4)
#define SDHCI_CTRL_DRV_TYPE_C (2U << 4) #define SDHCI_CTRL_DRV_TYPE_A (1U << 4)
#define SDHCI_CTRL_DRV_TYPE_D (3U << 4) #define SDHCI_CTRL_DRV_TYPE_C (2U << 4)
#define SDHCI_CTRL_EXEC_TUNING BIT(6) #define SDHCI_CTRL_DRV_TYPE_D (3U << 4)
#define SDHCI_CTRL_TUNED_CLK BIT(7) #define SDHCI_CTRL_DRV_TYPE(type) ((type) << 4)
#define SDHCI_HOST_VERSION_4_EN BIT(12) #define SDHCI_CTRL_EXEC_TUNING BIT(6)
#define SDHCI_ADDRESSING_64BIT_EN BIT(13) #define SDHCI_CTRL_TUNED_CLK_SHIFT 7
#define SDHCI_CTRL_PRESET_VAL_EN BIT(15) #define SDHCI_CTRL_TUNED_CLK BIT(7)
#define SDHCI_HOST_VERSION_4_EN BIT(12)
#define SDHCI_ADDRESSING_64BIT_EN BIT(13)
#define SDHCI_CTRL_PRESET_VAL_EN BIT(15)
/*! SDMMC power control. */ /*! SDMMC power control. 0x29. */
#define SDHCI_POWER_ON BIT(0) #define SDHCI_POWER_ON BIT(0)
#define SDHCI_POWER_180 0x0A #define SDHCI_POWER_180 (5U << 1)
#define SDHCI_POWER_300 0x0C #define SDHCI_POWER_300 (6U << 1)
#define SDHCI_POWER_330 0x0E #define SDHCI_POWER_330 (7U << 1)
#define SDHCI_POWER_MASK 0xF1 // UHS-II only. #define SDHCI_POWER_MASK 0xF1 // UHS-II only.
// /*! SDMMC max current. */ /*! SDMMC clock control. 0x2C. */
// #define SDHCI_MAX_CURRENT_330_MASK 0xFF #define SDHCI_CLOCK_INT_EN BIT(0) // Internal Clock.
// #define SDHCI_MAX_CURRENT_180_MASK 0xFF0000 #define SDHCI_CLOCK_INT_STABLE BIT(1) // Internal Clock Stable.
// #define SDHCI_MAX_CURRENT_MULTIPLIER 4
/*! SDMMC clock control. */
#define SDHCI_CLOCK_INT_EN BIT(0)
#define SDHCI_CLOCK_INT_STABLE BIT(1)
#define SDHCI_CLOCK_CARD_EN BIT(2) #define SDHCI_CLOCK_CARD_EN BIT(2)
#define SDHCI_PROG_CLOCK_MODE BIT(5) #define SDHCI_PROG_CLOCK_MODE BIT(5)
#define SDHCI_DIVIDER_HI_SHIFT 6 #define SDHCI_DIV_HI_SHIFT 6
#define SDHCI_DIV_HI_MASK (3U << SDHCI_DIVIDER_HI_SHIFT) #define SDHCI_DIV_HI_MASK (3U << SDHCI_DIV_HI_SHIFT)
#define SDHCI_DIVIDER_SHIFT 8 #define SDHCI_DIV_LO_SHIFT 8
#define SDHCI_DIV_MASK (0xFFU << SDHCI_DIVIDER_SHIFT) #define SDHCI_DIV_MASK (0xFFU << SDHCI_DIV_LO_SHIFT)
/*! SDMMC software reset. */ /*! SDMMC software reset. 0x2F. */
#define SDHCI_RESET_ALL BIT(0) #define SDHCI_RESET_ALL BIT(0)
#define SDHCI_RESET_CMD BIT(1) #define SDHCI_RESET_CMD BIT(1)
#define SDHCI_RESET_DATA BIT(2) #define SDHCI_RESET_DATA BIT(2)
/*! SDMMC interrupt status and control. */ /*! SDMMC interrupt status and control. 0x30/0x34. */
#define SDHCI_INT_RESPONSE BIT(0) #define SDHCI_INT_RESPONSE BIT(0)
#define SDHCI_INT_DATA_END BIT(1) #define SDHCI_INT_DATA_END BIT(1)
#define SDHCI_INT_BLK_GAP BIT(2) #define SDHCI_INT_BLK_GAP BIT(2)
#define SDHCI_INT_DMA_END BIT(3) #define SDHCI_INT_DMA_END BIT(3)
#define SDHCI_INT_SPACE_AVAIL BIT(4) #define SDHCI_INT_SPACE_AVAIL BIT(4) // Write buffer empty.
#define SDHCI_INT_DATA_AVAIL BIT(5) #define SDHCI_INT_DATA_AVAIL BIT(5) // Read buffer has data.
#define SDHCI_INT_CARD_INSERT BIT(6) #define SDHCI_INT_CARD_INSERT BIT(6)
#define SDHCI_INT_CARD_REMOVE BIT(7) #define SDHCI_INT_CARD_REMOVE BIT(7)
#define SDHCI_INT_CARD_INT BIT(8) #define SDHCI_INT_CARD_INT BIT(8)
#define SDHCI_INT_RETUNE BIT(12) #define SDHCI_INT_RETUNE BIT(12)
#define SDHCI_INT_CQE BIT(14)
#define SDHCI_INT_ERROR BIT(15) #define SDHCI_INT_ERROR BIT(15)
/*! SDMMC error interrupt status and control. */ /*! SDMMC error interrupt status and control. 0x32/0x36. */
#define SDHCI_ERR_INT_TIMEOUT BIT(0) #define SDHCI_ERR_INT_TIMEOUT BIT(0)
#define SDHCI_ERR_INT_CRC BIT(1) #define SDHCI_ERR_INT_CRC BIT(1)
#define SDHCI_ERR_INT_END_BIT BIT(2) #define SDHCI_ERR_INT_END_BIT BIT(2)
@@ -173,16 +178,65 @@
#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)
#define SDHCI_ERR_INT_BUS_POWER BIT(7) #define SDHCI_ERR_INT_BUS_POWER BIT(7)
#define SDHCI_ERR_INT_AUTO_CMD_ERR BIT(8) #define SDHCI_ERR_INT_AUTO_CMD12 BIT(8)
#define SDHCI_ERR_INT_ADMA_ERROR BIT(9) #define SDHCI_ERR_INT_ADMA BIT(9)
#define SDHCI_ERR_INT_TUNE_ERROR BIT(10) #define SDHCI_ERR_INT_TUNE BIT(10)
#define SDHCI_ERR_INT_RSP_ERROR BIT(11) #define SDHCI_ERR_INT_RSP BIT(11)
#define SDHCI_ERR_INT_TARGET_RSP BIT(12)
#define SDHCI_ERR_INT_SPI BIT(13)
#define SDHCI_ERR_INT_VND_BOOT_TMO BIT(14)
#define SDHCI_ERR_INT_VND_BOOT_ACK BIT(15)
#define SDHCI_ERR_INT_ALL_EXCEPT_ADMA_BUSPWR \ #define SDHCI_ERR_INT_ALL_EXCEPT_ADMA_BUSPWR \
(SDHCI_ERR_INT_AUTO_CMD_ERR | 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_INDEX | SDHCI_ERR_INT_END_BIT | \
SDHCI_ERR_INT_CRC | SDHCI_ERR_INT_TIMEOUT) SDHCI_ERR_INT_CRC | SDHCI_ERR_INT_TIMEOUT)
/*! Host Capability 1. 0x40. */
#define SDHCI_CAP_TM_CLK_FREQ_MASK 0x3F
#define SDHCI_CAP_TM_UNIT_MHZ BIT(7)
#define SDHCI_CAP_BASE_CLK_FREQ_MASK (0xFFU << 8)
#define SDHCI_CAP_MAX_BLK_LEN_MASK (3U << 16)
#define SDHCI_CAP_EMMC_8BIT BIT(18)
#define SDHCI_CAP_ADMA2 BIT(19)
#define SDHCI_CAP_HISPD BIT(21)
#define SDHCI_CAP_SDMA BIT(22)
#define SDHCI_CAP_SUSPEND_RESUME BIT(23)
#define SDHCI_CAP_3_3_V BIT(24)
#define SDHCI_CAP_3_0_V BIT(25)
#define SDHCI_CAP_1_8_V BIT(26)
#define SDHCI_CAP_64BIT BIT(28)
#define SDHCI_CAP_ASYNC_INT BIT(29)
#define SDHCI_CAP_SLOT_TYPE_MASK (3U << 30)
#define SDHCI_CAP_SLOT_TYPE_REMOVABLE (0U << 30)
#define SDHCI_CAP_SLOT_TYPE_EMBEDDED (1U << 30)
#define SDHCI_CAP_SLOT_TYPE_SHARED (2U << 30)
#define SDHCI_CAP_SLOT_TYPE_UHS2 (3U << 30)
/*! Host Capability 2. 0x44. */
#define SDHCI_CAP_SDR50 BIT(0)
#define SDHCI_CAP_SDR5104 BIT(1)
#define SDHCI_CAP_DDR50 BIT(2)
#define SDHCI_CAP_UHS2 BIT(3)
#define SDHCI_CAP_DRV_TYPE_A BIT(4)
#define SDHCI_CAP_DRV_TYPE_C BIT(5)
#define SDHCI_CAP_DRV_TYPE_D BIT(6)
#define SDHCI_CAP_RSP_TIMER_CNT_MASK (0xFU << 8)
#define SDHCI_CAP_SDR50_TUNING BIT(13)
#define SDHCI_CAP_RSP_MODES_MASK (3U << 14)
#define SDHCI_CAP_CLK_MULT (0xFFU << 16)
#define SDHCI_CAP_ADMA3 BIT(27)
#define SDHCI_CAP_VDD2_1_8V BIT(28)
/*! SDMMC max current. 0x48 */
#define SDHCI_MAX_CURRENT_3_3_V_MASK (0xFFU << 0)
#define SDHCI_MAX_CURRENT_3_0_V_MASK (0xFFU << 8)
#define SDHCI_MAX_CURRENT_1_8_V_MASK (0xFFU << 16)
#define SDHCI_MAX_CURRENT_MULTIPLIER 4
/*! SDMMC max current. 0x4C */
#define SDHCI_MAX_CURRENT_1_8_V_VDD2_MASK (0xFFU << 0)
/*! SD bus speeds. */ /*! SD bus speeds. */
#define UHS_SDR12_BUS_SPEED 0 #define UHS_SDR12_BUS_SPEED 0
@@ -209,9 +263,8 @@
#define SDHCI_TIMING_UHS_DDR50 12 #define SDHCI_TIMING_UHS_DDR50 12
// SDR104 with a 163.2MHz -> 81.6MHz clock. // SDR104 with a 163.2MHz -> 81.6MHz clock.
#define SDHCI_TIMING_UHS_SDR82 13 // GC FPGA. Obsolete and Repurposed. MMC_HS50 -> SDR82. #define SDHCI_TIMING_UHS_SDR82 13 // GC FPGA. Obsolete and Repurposed. MMC_HS50 -> SDR82.
#define SDHCI_TIMING_MMC_DDR100 14 // GC ASIC. #define SDHCI_TIMING_MMC_HS100 14 // GC ASIC.
#define SDHCI_TIMING_UHS_DDR200 15
#define SDHCI_CAN_64BIT BIT(28)
/*! SDMMC Low power features. */ /*! SDMMC Low power features. */
#define SDMMC_POWER_SAVE_DISABLE 0 #define SDMMC_POWER_SAVE_DISABLE 0
@@ -220,12 +273,15 @@
/*! Helper for SWITCH command argument. */ /*! Helper for SWITCH command argument. */
#define SDMMC_SWITCH(mode, index, value) (((mode) << 24) | ((index) << 16) | ((value) << 8)) #define SDMMC_SWITCH(mode, index, value) (((mode) << 24) | ((index) << 16) | ((value) << 8))
#define HW_TAP_TUNING 0x100
#define INVALID_TAP 0x100
/*! SDMMC controller context. */ /*! SDMMC controller context. */
typedef struct _sdmmc_t typedef struct _sdmmc_t
{ {
t210_sdmmc_t *regs; t210_sdmmc_t *regs;
u32 id; u32 id;
u32 divisor; u32 card_clock;
u32 clock_stopped; u32 clock_stopped;
int powersave_enabled; int powersave_enabled;
int manual_cal; int manual_cal;
@@ -263,13 +319,14 @@ int sdmmc_get_io_power(sdmmc_t *sdmmc);
u32 sdmmc_get_bus_width(sdmmc_t *sdmmc); u32 sdmmc_get_bus_width(sdmmc_t *sdmmc);
void sdmmc_set_bus_width(sdmmc_t *sdmmc, u32 bus_width); void sdmmc_set_bus_width(sdmmc_t *sdmmc, u32 bus_width);
void sdmmc_save_tap_value(sdmmc_t *sdmmc); void sdmmc_save_tap_value(sdmmc_t *sdmmc);
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_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, 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();
int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int powersave_enable); int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type);
void sdmmc_end(sdmmc_t *sdmmc); void sdmmc_end(sdmmc_t *sdmmc);
void sdmmc_init_cmd(sdmmc_cmd_t *cmdbuf, u16 cmd, u32 arg, u32 rsp_type, u32 check_busy); void sdmmc_init_cmd(sdmmc_cmd_t *cmdbuf, u16 cmd, u32 arg, u32 rsp_type, u32 check_busy);
int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out); int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out);

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2019 CTCaer * Copyright (c) 2018-2023 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,
@@ -21,14 +21,15 @@
#include <assert.h> #include <assert.h>
#include <utils/types.h> #include <utils/types.h>
#define TEGRA_MMC_VNDR_TUN_CTRL0_TAP_VAL_UPDATED_BY_HW 0x20000 #define SDHCI_TEGRA_TUNING_TAP_HW_UPDATED BIT(17)
#define TEGRA_MMC_DLLCAL_CFG_EN_CALIBRATE 0x80000000 #define SDHCI_TEGRA_DLLCAL_CALIBRATE BIT(31)
#define TEGRA_MMC_DLLCAL_CFG_STATUS_DLL_ACTIVE 0x80000000 #define SDHCI_TEGRA_DLLCAL_ACTIVE BIT(31)
#define TEGRA_MMC_SDMEMCOMPPADCTRL_PAD_E_INPUT_PWRD 0x80000000 #define SDHCI_TEGRA_PADCTRL_E_INPUT_PWRD BIT(31)
#define TEGRA_MMC_SDMEMCOMPPADCTRL_COMP_VREF_SEL_MASK 0xFFFFFFF0 #define SDHCI_TEGRA_PADCTRL_VREF_SEL_MASK 0xF
#define TEGRA_MMC_AUTOCALCFG_AUTO_CAL_ENABLE 0x20000000 #define SDHCI_TEGRA_AUTOCAL_SLW_OVERRIDE BIT(28)
#define TEGRA_MMC_AUTOCALCFG_AUTO_CAL_START 0x80000000 #define SDHCI_TEGRA_AUTOCAL_ENABLE BIT(29)
#define TEGRA_MMC_AUTOCALSTS_AUTO_CAL_ACTIVE 0x80000000 #define SDHCI_TEGRA_AUTOCAL_START BIT(31)
#define SDHCI_TEGRA_AUTOCAL_ACTIVE BIT(31)
typedef struct _t210_sdmmc_t typedef struct _t210_sdmmc_t
{ {
@@ -72,21 +73,21 @@ typedef struct _t210_sdmmc_t
// ADMA3 not supported. 1.8V VDD2 supported. // ADMA3 not supported. 1.8V VDD2 supported.
/* 0x44 */ vu32 capareg_hi; /* 0x44 */ vu32 capareg_hi;
/* 0x48 */ vu32 maxcurr; // Get information by another method. Can be overriden via maxcurrover and maxcurrover_hi. /* 0x48 */ vu32 maxcurr; // Get information by another method. Can be overriden via maxcurrover and maxcurrover_hi.
/* 0x4C */ vu8 rsvd0[4]; // 4C-4F reserved for more max current. /* 0x4C */ vu32 maxcurr_hi;
/* 0x50 */ vu16 setacmd12err; /* 0x50 */ vu16 setacmd12err; // Force error in acmd12errsts.
/* 0x52 */ vu16 setinterr; /* 0x52 */ vu16 setinterr;
/* 0x54 */ vu8 admaerr; /* 0x54 */ vu8 admaerr;
/* 0x55 */ vu8 rsvd1[3]; // 55-57 reserved. /* 0x55 */ vu8 rsvd1[3]; // 55-57 reserved.
/* 0x58 */ vu32 admaaddr; /* 0x58 */ vu32 admaaddr;
/* 0x5C */ vu32 admaaddr_hi; /* 0x5C */ vu32 admaaddr_hi;
/* 0x60 */ vu16 presets[11]; /* 0x60 */ vu16 presets[11];
/* 0x76 */ vu16 rsvd2; /* 0x76 */ vu16 rsvd2;
/* 0x78 */ vu32 adma3addr; /* 0x78 */ vu32 adma3addr;
/* 0x7C */ vu32 adma3addr_hi; /* 0x7C */ vu32 adma3addr_hi;
/* 0x80 */ vu8 uhs2[124]; // 80-FB UHS-II. /* 0x80 */ vu8 uhs2[124]; // 80-FB UHS-II.
/* 0xFC */ vu16 slotintsts; /* 0xFC */ vu16 slotintsts;
/* 0xFE */ vu16 hcver; // 0x303 (4.00). /* 0xFE */ vu16 hcver; // 0x303 (4.00).
/* UHS-II range. Used for Vendor registers here */ /* UHS-II range. Used for Vendor registers here */
/* 0x100 */ vu32 venclkctl; /* 0x100 */ vu32 venclkctl;

View File

@@ -263,9 +263,6 @@ void power_set_state(power_state_t state)
// De-initialize and power down various hardware. // De-initialize and power down various hardware.
hw_reinit_workaround(false, 0); hw_reinit_workaround(false, 0);
// Stop the alarm, in case we injected and powered off too fast.
max77620_rtc_stop_alarm();
// Set power state. // Set power state.
switch (state) switch (state)
{ {

View File

@@ -3,6 +3,7 @@
#include "gfx.h" #include "gfx.h"
#include "gfxutils.h" #include "gfxutils.h"
#include "../hid/hid.h" #include "../hid/hid.h"
#include <soc/timer.h>
#include <utils/util.h> #include <utils/util.h>
#include <utils/btn.h> #include <utils/btn.h>
#include <utils/sprintf.h> #include <utils/sprintf.h>

View File

@@ -34,6 +34,25 @@
#include <string.h> #include <string.h>
#define TSEC_KEY_DATA_OFFSET 0x300
typedef struct _tsec_key_data_t
{
u8 debug_key[0x10];
u8 blob0_auth_hash[0x10];
u8 blob1_auth_hash[0x10];
u8 blob2_auth_hash[0x10];
u8 blob2_aes_iv[0x10];
u8 hovi_eks_seed[0x10];
u8 hovi_common_seed[0x10];
u32 blob0_size;
u32 blob1_size;
u32 blob2_size;
u32 blob3_size;
u32 blob4_size;
u8 reserved[0x7C];
} tsec_key_data_t;
extern hekate_config h_cfg; extern hekate_config h_cfg;
#define DPRINTF(x) #define DPRINTF(x)

View File

@@ -7,6 +7,7 @@
#include "lexer.h" #include "lexer.h"
#include <storage/sd.h> #include <storage/sd.h>
#include <soc/timer.h>
#include "../fs/fsutils.h" #include "../fs/fsutils.h"
#include "../gfx/gfxutils.h" #include "../gfx/gfxutils.h"
#include "../hid/hid.h" #include "../hid/hid.h"

View File

@@ -167,7 +167,7 @@ ErrCode_t DumpOrWriteEmmcPart(const char *path, const char *part, u8 write, u8 f
else { else {
emummc_storage_set_mmc_partition(&emmc_storage, 0); emummc_storage_set_mmc_partition(&emmc_storage, 0);
emmc_part_t *system_part = nx_emmc_part_find(GetCurGPT(), part); emmc_part_t *system_part = emmc_part_find(GetCurGPT(), part);
if (!system_part) if (!system_part)
return newErrCode(TE_ERR_PARTITION_NOT_FOUND); return newErrCode(TE_ERR_PARTITION_NOT_FOUND);

View File

@@ -40,7 +40,7 @@ void disconnectMMC(){
if (TConf.currentMMCConnected != MMC_CONN_None){ if (TConf.currentMMCConnected != MMC_CONN_None){
TConf.currentMMCConnected = MMC_CONN_None; TConf.currentMMCConnected = MMC_CONN_None;
emummc_storage_end(&emmc_storage); emummc_storage_end(&emmc_storage);
nx_emmc_gpt_free(&curGpt); emmc_gpt_free(&curGpt);
} }
} }
@@ -55,7 +55,7 @@ int connectMMC(u8 mmcType){
if (!res){ if (!res){
TConf.currentMMCConnected = mmcType; TConf.currentMMCConnected = mmcType;
emummc_storage_set_mmc_partition(&emmc_storage, 0); emummc_storage_set_mmc_partition(&emmc_storage, 0);
nx_emmc_gpt_parse(&curGpt, &emmc_storage); emmc_gpt_parse(&curGpt);
} }
return res; // deal with the errors later lol return res; // deal with the errors later lol
@@ -69,7 +69,7 @@ ErrCode_t mountMMCPart(const char *partition){
emummc_storage_set_mmc_partition(&emmc_storage, 0); // why i have to do this twice beats me emummc_storage_set_mmc_partition(&emmc_storage, 0); // why i have to do this twice beats me
emmc_part_t *system_part = nx_emmc_part_find(&curGpt, partition); emmc_part_t *system_part = emmc_part_find(&curGpt, partition);
if (!system_part) if (!system_part)
return newErrCode(TE_ERR_PARTITION_NOT_FOUND); return newErrCode(TE_ERR_PARTITION_NOT_FOUND);

View File

@@ -19,6 +19,7 @@
#include <string.h> #include <string.h>
#include "../fs/fscopy.h" #include "../fs/fscopy.h"
#include "../utils/utils.h" #include "../utils/utils.h"
#include <soc/timer.h>
void DumpSysFw(){ void DumpSysFw(){
char sysPath[25 + 36 + 3 + 1]; // 24 for "bis:/Contents/registered", 36 for ncaName.nca, 3 for /00, and 1 to make sure :) char sysPath[25 + 36 + 3 + 1]; // 24 for "bis:/Contents/registered", 36 for ncaName.nca, 3 for /00, and 1 to make sure :)

View File

@@ -3,6 +3,7 @@
#include <utils/types.h> #include <utils/types.h>
#include <mem/heap.h> #include <mem/heap.h>
#include <utils/util.h> #include <utils/util.h>
#include <soc/timer.h>
#include "vector.h" #include "vector.h"
#include "../gfx/gfxutils.h" #include "../gfx/gfxutils.h"
#include "../gfx/gfx.h" #include "../gfx/gfx.h"