@@ -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))
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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*/
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
128
bdk/soc/clock.c
128
bdk/soc/clock.c
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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 :)
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
Reference in New Issue
Block a user