Refactoring and comment adding

This commit is contained in:
CTCaer 2019-09-12 23:08:38 +03:00
parent c5b64a2b58
commit a8d529cf6a
47 changed files with 477 additions and 300 deletions

View file

@ -23,6 +23,7 @@
#include "../gfx/tui.h" #include "../gfx/tui.h"
#include "../libs/fatfs/ff.h" #include "../libs/fatfs/ff.h"
#include "../soc/t210.h" #include "../soc/t210.h"
#include "../storage/sdmmc.h"
#include "../utils/btn.h" #include "../utils/btn.h"
#include "../utils/list.h" #include "../utils/list.h"
#include "../utils/util.h" #include "../utils/util.h"
@ -47,8 +48,9 @@ void set_default_configuration()
h_cfg.errors = 0; h_cfg.errors = 0;
h_cfg.sept_run = EMC(EMC_SCRATCH0) & EMC_SEPT_RUN; h_cfg.sept_run = EMC(EMC_SCRATCH0) & EMC_SEPT_RUN;
h_cfg.rcm_patched = true; h_cfg.rcm_patched = true;
h_cfg.sd_timeoff = 0;
h_cfg.emummc_force_disable = false; h_cfg.emummc_force_disable = false;
sd_power_cycle_time_start = 0xFFFFFFF;
} }
int create_config_entry() int create_config_entry()

View file

@ -37,7 +37,6 @@ typedef struct _hekate_config
bool emummc_force_disable; bool emummc_force_disable;
bool rcm_patched; bool rcm_patched;
u32 sbar_time_keeping; u32 sbar_time_keeping;
u32 sd_timeoff;
u32 errors; u32 errors;
} hekate_config; } hekate_config;

View file

@ -47,54 +47,61 @@ void display_init()
max77620_regulator_set_volt_and_flags(REGULATOR_LDO0, 1200000, MAX77620_POWER_MODE_NORMAL); // Configure to 1.2V. max77620_regulator_set_volt_and_flags(REGULATOR_LDO0, 1200000, MAX77620_POWER_MODE_NORMAL); // Configure to 1.2V.
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO7, MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH | MAX77620_CNFG_GPIO_DRV_PUSHPULL); i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO7, MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH | MAX77620_CNFG_GPIO_DRV_PUSHPULL);
// Enable MIPI CAL, DSI, DISP1, HOST1X, UART_FST_MIPI_CAL, DSIA LP clocks. // Enable Display Interface specific clocks.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = 0x1010000; CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = 0x1010000; // Clear reset DSI, MIPI_CAL.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = 0x1010000; CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = 0x1010000; // Set enable clock DSI, MIPI_CAL.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = 0x18000000;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = 0x18000000;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = 0x20000;
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIP_CAL) = 0xA;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_SET) = 0x80000;
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP) = 0xA;
// DPD idle. CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = 0x18000000; // Clear reset DISP1, HOST1X.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = 0x18000000; // Set enable clock DISP1, HOST1X.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = 0x20000; // Set enable clock UART_FST_MIPI_CAL.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL) = 10; // Set PLLP_OUT3 and div 6 (17MHz).
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_SET) = 0x80000; // Set enable clock DSIA_LP.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP) = 10; // Set PLLP_OUT and div 6 (68MHz).
// Disable deap power down.
PMC(APBDEV_PMC_IO_DPD_REQ) = 0x40000000; PMC(APBDEV_PMC_IO_DPD_REQ) = 0x40000000;
PMC(APBDEV_PMC_IO_DPD2_REQ) = 0x40000000; PMC(APBDEV_PMC_IO_DPD2_REQ) = 0x40000000;
// Config pins. // Config LCD and Backlight pins.
PINMUX_AUX(PINMUX_AUX_NFC_EN) &= ~PINMUX_TRISTATE; PINMUX_AUX(PINMUX_AUX_NFC_EN) &= ~PINMUX_TRISTATE;
PINMUX_AUX(PINMUX_AUX_NFC_INT) &= ~PINMUX_TRISTATE; PINMUX_AUX(PINMUX_AUX_NFC_INT) &= ~PINMUX_TRISTATE;
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) &= ~PINMUX_TRISTATE; PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) &= ~PINMUX_TRISTATE;
PINMUX_AUX(PINMUX_AUX_LCD_BL_EN) &= ~PINMUX_TRISTATE; PINMUX_AUX(PINMUX_AUX_LCD_BL_EN) &= ~PINMUX_TRISTATE;
PINMUX_AUX(PINMUX_AUX_LCD_RST) &= ~PINMUX_TRISTATE; PINMUX_AUX(PINMUX_AUX_LCD_RST) &= ~PINMUX_TRISTATE;
gpio_config(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_MODE_GPIO); // Backlight +-5V. // Set Backlight +-5V pins mode and direction
gpio_output_enable(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_OUTPUT_ENABLE); // Backlight +-5V. gpio_config(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_OUTPUT_ENABLE);
// Enable Backlight power.
gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_HIGH); // Backlight +5V enable. gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_HIGH); // Backlight +5V enable.
usleep(10000); usleep(10000);
gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_HIGH); // Backlight -5V enable. gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_HIGH); // Backlight -5V enable.
usleep(10000); usleep(10000);
gpio_config(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_MODE_GPIO); // Backlight PWM, Enable, Reset. // Configure Backlight pins (PWM, EN, RST).
gpio_config(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_OUTPUT_ENABLE); gpio_output_enable(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_OUTPUT_ENABLE);
gpio_write(GPIO_PORT_V, GPIO_PIN_1, GPIO_HIGH); // Backlight Enable enable. gpio_write(GPIO_PORT_V, GPIO_PIN_1, GPIO_HIGH); // Enable Backlight EN.
// Config display interface and display. // Power up supply regulator for display interface.
MIPI_CAL(MIPI_CAL_MIPI_BIAS_PAD_CFG2) = 0; MIPI_CAL(MIPI_CAL_MIPI_BIAS_PAD_CFG2) = 0;
// Set DISP1 clock source and parrent clock.
exec_cfg((u32 *)CLOCK_BASE, _display_config_1, 4); exec_cfg((u32 *)CLOCK_BASE, _display_config_1, 4);
// Setup display communication interfaces.
exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_2, 94); exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_2, 94);
exec_cfg((u32 *)DSI_BASE, _display_config_3, 61); exec_cfg((u32 *)DSI_BASE, _display_config_3, 61);
usleep(10000); usleep(10000);
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_HIGH); // Backlight Reset enable. // Enable Backlight Reset.
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_HIGH);
usleep(60000); usleep(60000);
// Setups DSI packet configuration and request display id.
DSI(_DSIREG(DSI_BTA_TIMING)) = 0x50204; DSI(_DSIREG(DSI_BTA_TIMING)) = 0x50204;
DSI(_DSIREG(DSI_WR_DATA)) = 0x337; // MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE DSI(_DSIREG(DSI_WR_DATA)) = 0x337; // MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST; DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
@ -123,19 +130,22 @@ void display_init()
usleep(20000); usleep(20000);
// Configure PLLD for DISP1.
exec_cfg((u32 *)CLOCK_BASE, _display_config_6, 3); exec_cfg((u32 *)CLOCK_BASE, _display_config_6, 3);
// Finalize DSI configuration.
exec_cfg((u32 *)DSI_BASE, _display_config_5, 21); exec_cfg((u32 *)DSI_BASE, _display_config_5, 21);
DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = 4; DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = 4;
exec_cfg((u32 *)DSI_BASE, _display_config_7, 10); exec_cfg((u32 *)DSI_BASE, _display_config_7, 10);
usleep(10000); usleep(10000);
// Calibrate display communication pads.
exec_cfg((u32 *)MIPI_CAL_BASE, _display_config_8, 6); exec_cfg((u32 *)MIPI_CAL_BASE, _display_config_8, 6);
exec_cfg((u32 *)DSI_BASE, _display_config_9, 4); exec_cfg((u32 *)DSI_BASE, _display_config_9, 4);
exec_cfg((u32 *)MIPI_CAL_BASE, _display_config_10, 16); exec_cfg((u32 *)MIPI_CAL_BASE, _display_config_10, 16);
usleep(10000); usleep(10000);
// Enable video display controller.
exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_11, 113); exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_11, 113);
} }
@ -143,11 +153,10 @@ void display_backlight_pwm_init()
{ {
clock_enable_pwm(); clock_enable_pwm();
PWM(PWM_CONTROLLER_PWM_CSR_0) = (1 << 31); // Enable PWM PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN; // Enable PWM and set it to 25KHz PFM.
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) >> 2) << 2 | 1; // PWM clock source. PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & 0xFFFFFFFC) | 1; // PWM clock source.
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight power mode. gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight power mode.
} }
void display_backlight(bool enable) void display_backlight(bool enable)
@ -168,7 +177,7 @@ void display_backlight_brightness(u32 brightness, u32 step_delay)
{ {
for (u32 i = old_value; i < brightness + 1; i++) for (u32 i = old_value; i < brightness + 1; i++)
{ {
PWM(PWM_CONTROLLER_PWM_CSR_0) = (1 << 31) | (i << 16); // Enable PWM PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN | (i << 16); // Enable PWM and set it to 25KHz PFM.
usleep(step_delay); usleep(step_delay);
} }
} }
@ -176,7 +185,7 @@ void display_backlight_brightness(u32 brightness, u32 step_delay)
{ {
for (u32 i = old_value; i > brightness; i--) for (u32 i = old_value; i > brightness; i--)
{ {
PWM(PWM_CONTROLLER_PWM_CSR_0) = (1 << 31) | (i << 16); // Enable PWM PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN | (i << 16); // Enable PWM and set it to 25KHz PFM.
usleep(step_delay); usleep(step_delay);
} }
} }
@ -192,13 +201,14 @@ void display_end()
DSI(_DSIREG(DSI_WR_DATA)) = 0x2805; // MIPI_DCS_SET_DISPLAY_OFF DSI(_DSIREG(DSI_WR_DATA)) = 0x2805; // MIPI_DCS_SET_DISPLAY_OFF
DISPLAY_A(_DIREG(DC_CMD_STATE_ACCESS)) = READ_MUX | WRITE_MUX; DISPLAY_A(_DIREG(DC_CMD_STATE_ACCESS)) = READ_MUX | WRITE_MUX;
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0; DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0; // Disable host cmd packet.
// De-initialize video controller.
exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_12, 17); exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_12, 17);
exec_cfg((u32 *)DSI_BASE, _display_config_13, 16); exec_cfg((u32 *)DSI_BASE, _display_config_13, 16);
usleep(10000); usleep(10000);
// De-initialize display panel.
if (_display_ver == 0x10) if (_display_ver == 0x10)
exec_cfg((u32 *)DSI_BASE, _display_config_14, 22); exec_cfg((u32 *)DSI_BASE, _display_config_14, 22);
@ -207,31 +217,31 @@ void display_end()
usleep(50000); usleep(50000);
// Disable display and backlight pins.
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW); //Backlight Reset disable. gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW); //Backlight Reset disable.
usleep(10000); usleep(10000);
gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_LOW); //Backlight -5V disable. gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_LOW); //Backlight -5V disable.
usleep(10000); usleep(10000);
gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_LOW); //Backlight +5V disable. gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_LOW); //Backlight +5V disable.
usleep(10000); usleep(10000);
// Disable clocks. // Disable Display Interface specific clocks.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = 0x1010000; CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = 0x1010000; // Set reset clock DSI, MIPI_CAL.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_CLR) = 0x1010000; CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_CLR) = 0x1010000; // Clear enable clock DSI, MIPI_CAL.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = 0x18000000; CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = 0x18000000; // Set reset DISP1, HOST1X.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = 0x18000000; CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = 0x18000000; // Clear enable DISP1, HOST1X.
// Power down pads.
DSI(_DSIREG(DSI_PAD_CONTROL_0)) = DSI_PAD_CONTROL_VS1_PULLDN_CLK | DSI_PAD_CONTROL_VS1_PULLDN(0xF) | DSI_PAD_CONTROL_VS1_PDIO_CLK | DSI_PAD_CONTROL_VS1_PDIO(0xF); DSI(_DSIREG(DSI_PAD_CONTROL_0)) = DSI_PAD_CONTROL_VS1_PULLDN_CLK | DSI_PAD_CONTROL_VS1_PULLDN(0xF) | DSI_PAD_CONTROL_VS1_PDIO_CLK | DSI_PAD_CONTROL_VS1_PDIO(0xF);
DSI(_DSIREG(DSI_POWER_CONTROL)) = 0; DSI(_DSIREG(DSI_POWER_CONTROL)) = 0;
// Switch to automatic function mode.
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight PWM. gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight PWM.
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & ~PINMUX_TRISTATE) | PINMUX_TRISTATE; PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & ~PINMUX_TRISTATE) | PINMUX_TRISTATE;
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) >> 2) << 2 | 1; PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & 0xFFFFFFFC)| 1;
} }
void display_color_screen(u32 color) void display_color_screen(u32 color)
@ -244,7 +254,6 @@ void display_color_screen(u32 color)
DISPLAY_A(_DIREG(DC_WIN_CD_WIN_OPTIONS)) = 0; DISPLAY_A(_DIREG(DC_WIN_CD_WIN_OPTIONS)) = 0;
DISPLAY_A(_DIREG(DC_DISP_BLEND_BACKGROUND_COLOR)) = color; DISPLAY_A(_DIREG(DC_DISP_BLEND_BACKGROUND_COLOR)) = color;
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = (DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) & 0xFFFFFFFE) | GENERAL_ACT_REQ; DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = (DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) & 0xFFFFFFFE) | GENERAL_ACT_REQ;
usleep(35000); usleep(35000);
display_backlight(true); display_backlight(true);
@ -254,10 +263,10 @@ u32 *display_init_framebuffer()
{ {
// Sanitize framebuffer area. // Sanitize framebuffer area.
memset((u32 *)FB_ADDRESS, 0, 0x3C0000); memset((u32 *)FB_ADDRESS, 0, 0x3C0000);
// This configures the framebuffer @ 0xC0000000 with a resolution of 1280x720 (line stride 720). // This configures the framebuffer @ IPL_FB_ADDRESS with a resolution of 1280x720 (line stride 720).
exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer, 32); exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer, 32);
usleep(35000); usleep(35000);
return (u32 *)FB_ADDRESS; return (u32 *)FB_ADDRESS;
} }

View file

@ -127,12 +127,12 @@ void gfx_init_ctxt(u32 *fb, u32 width, u32 height, u32 stride)
void gfx_clear_grey(u8 color) void gfx_clear_grey(u8 color)
{ {
memset(gfx_ctxt.fb, color, 0x3C0000); memset(gfx_ctxt.fb, color, gfx_ctxt.width * gfx_ctxt.height * 4);
} }
void gfx_clear_color(u32 color) void gfx_clear_color(u32 color)
{ {
for (u32 i = 0; i < gfx_ctxt.height * gfx_ctxt.stride; i++) for (u32 i = 0; i < gfx_ctxt.width * gfx_ctxt.height; i++)
gfx_ctxt.fb[i] = color; gfx_ctxt.fb[i] = color;
} }

View file

@ -105,6 +105,12 @@ static const u8 master_keyseed_620[0x10] =
static const u8 console_keyseed_4xx_5xx[0x10] = static const u8 console_keyseed_4xx_5xx[0x10] =
{ 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28 }; { 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28 };
static void _hos_crit_error(const char *text)
{
display_backlight_brightness(h_cfg.backlight, 1000);
gfx_con.mute = false;
gfx_printf("%k%s%k\n", 0xFFFF0000, text, 0xFFCCCCCC);
}
static void _se_lock(bool lock_se) static void _se_lock(bool lock_se)
{ {
@ -218,7 +224,7 @@ int keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt)
// We rely on racing conditions, make sure we cover even the unluckiest cases. // We rely on racing conditions, make sure we cover even the unluckiest cases.
if (retries > 15) if (retries > 15)
{ {
EHPRINTF("\nFailed to get TSEC keys. Please try again.\n"); _hos_crit_error("\nFailed to get TSEC keys. Please try again.");
return 0; return 0;
} }
} }
@ -339,7 +345,7 @@ static int _read_emmc_pkg1(launch_ctxt_t *ctxt)
ctxt->pkg1_id = pkg1_identify(ctxt->pkg1); ctxt->pkg1_id = pkg1_identify(ctxt->pkg1);
if (!ctxt->pkg1_id) if (!ctxt->pkg1_id)
{ {
EHPRINTF("Unknown pkg1 version."); _hos_crit_error("Unknown pkg1 version.");
goto out; goto out;
} }
gfx_printf("Identified pkg1 and Keyblob %d\n\n", ctxt->pkg1_id->kb); gfx_printf("Identified pkg1 and Keyblob %d\n\n", ctxt->pkg1_id->kb);
@ -368,7 +374,7 @@ static u8 *_read_emmc_pkg2(launch_ctxt_t *ctxt)
// Parse eMMC GPT. // Parse eMMC GPT.
LIST_INIT(gpt); LIST_INIT(gpt);
nx_emmc_gpt_parse(&gpt, &storage); nx_emmc_gpt_parse(&gpt, &storage);
DPRINTF("Parsed GPT\n"); DPRINTF("Parsed GPT\n");
// Find package2 partition. // Find package2 partition.
emmc_part_t *pkg2_part = nx_emmc_part_find(&gpt, "BCPKG2-1-Normal-Main"); emmc_part_t *pkg2_part = nx_emmc_part_find(&gpt, "BCPKG2-1-Normal-Main");
if (!pkg2_part) if (!pkg2_part)
@ -381,7 +387,7 @@ static u8 *_read_emmc_pkg2(launch_ctxt_t *ctxt)
nx_emmc_part_read(&storage, pkg2_part, BCT_SIZE / NX_EMMC_BLOCKSIZE, 1, bctBuf); nx_emmc_part_read(&storage, pkg2_part, BCT_SIZE / NX_EMMC_BLOCKSIZE, 1, bctBuf);
u32 *hdr = (u32 *)(bctBuf + 0x100); u32 *hdr = (u32 *)(bctBuf + 0x100);
u32 pkg2_size = hdr[0] ^ hdr[2] ^ hdr[3]; u32 pkg2_size = hdr[0] ^ hdr[2] ^ hdr[3];
DPRINTF("pkg2 size on emmc is %08X\n", pkg2_size); DPRINTF("pkg2 size on emmc is %08X\n", pkg2_size);
// Read in Boot Config. // Read in Boot Config.
memset(bctBuf, 0, BCT_SIZE); memset(bctBuf, 0, BCT_SIZE);
@ -389,7 +395,7 @@ static u8 *_read_emmc_pkg2(launch_ctxt_t *ctxt)
// Read in package2. // Read in package2.
u32 pkg2_size_aligned = ALIGN(pkg2_size, NX_EMMC_BLOCKSIZE); u32 pkg2_size_aligned = ALIGN(pkg2_size, NX_EMMC_BLOCKSIZE);
DPRINTF("pkg2 size aligned is %08X\n", pkg2_size_aligned); DPRINTF("pkg2 size aligned is %08X\n", pkg2_size_aligned);
ctxt->pkg2 = malloc(pkg2_size_aligned); ctxt->pkg2 = malloc(pkg2_size_aligned);
ctxt->pkg2_size = pkg2_size; ctxt->pkg2_size = pkg2_size;
nx_emmc_part_read(&storage, pkg2_part, BCT_SIZE / NX_EMMC_BLOCKSIZE, nx_emmc_part_read(&storage, pkg2_part, BCT_SIZE / NX_EMMC_BLOCKSIZE,
@ -438,7 +444,7 @@ int hos_launch(ini_sec_t *cfg)
// Try to parse config if present. // Try to parse config if present.
if (ctxt.cfg && !parse_boot_config(&ctxt)) if (ctxt.cfg && !parse_boot_config(&ctxt))
{ {
EHPRINTF("Wrong ini cfg or missing files!"); _hos_crit_error("Wrong ini cfg or missing files!");
return 0; return 0;
} }
@ -447,7 +453,7 @@ int hos_launch(ini_sec_t *cfg)
{ {
if (ctxt.stock) if (ctxt.stock)
{ {
EHPRINTF("Stock emuMMC is not supported yet!"); _hos_crit_error("Stock emuMMC is not supported yet!");
return 0; return 0;
} }
@ -471,13 +477,13 @@ int hos_launch(ini_sec_t *cfg)
if (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_700 && !h_cfg.sept_run) if (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_700 && !h_cfg.sept_run)
{ {
gfx_printf("Failed to run sept\n"); _hos_crit_error("Failed to run sept");
return 0; return 0;
} }
if (!keygen(ctxt.keyblob, ctxt.pkg1_id->kb, &tsec_ctxt, &ctxt)) if (!keygen(ctxt.keyblob, ctxt.pkg1_id->kb, &tsec_ctxt, &ctxt))
return 0; return 0;
DPRINTF("Generated keys\n"); DPRINTF("Generated keys\n");
if (ctxt.pkg1_id->kb <= KB_FIRMWARE_VERSION_600) if (ctxt.pkg1_id->kb <= KB_FIRMWARE_VERSION_600)
h_cfg.se_keygen_done = 1; h_cfg.se_keygen_done = 1;
} }
@ -495,7 +501,7 @@ int hos_launch(ini_sec_t *cfg)
} }
else else
{ {
EHPRINTF("No mandatory secmon or warmboot provided!"); _hos_crit_error("No mandatory secmon or warmboot provided!");
return 0; return 0;
} }
} }
@ -507,7 +513,7 @@ int hos_launch(ini_sec_t *cfg)
{ {
if (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_700) if (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_700)
{ {
EHPRINTF("No warmboot provided!"); _hos_crit_error("No warmboot provided!");
return 0; return 0;
} }
// Else we patch it to allow downgrading. // Else we patch it to allow downgrading.
@ -545,7 +551,7 @@ int hos_launch(ini_sec_t *cfg)
pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(ctxt.pkg2); pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(ctxt.pkg2);
if (!pkg2_hdr) if (!pkg2_hdr)
{ {
gfx_printf("Pkg2 decryption failed!\n"); _hos_crit_error("Pkg2 decryption failed!");
return 0; return 0;
} }
@ -573,11 +579,10 @@ int hos_launch(ini_sec_t *cfg)
ctxt.pkg2_kernel_id = pkg2_identify(kernel_hash); ctxt.pkg2_kernel_id = pkg2_identify(kernel_hash);
if (!ctxt.pkg2_kernel_id) if (!ctxt.pkg2_kernel_id)
{ {
EHPRINTF("Failed to identify kernel!"); _hos_crit_error("Failed to identify kernel!");
return 0; return 0;
} }
// In case a kernel patch option is set; allows to disable SVC verification or/and enable debug mode. // In case a kernel patch option is set; allows to disable SVC verification or/and enable debug mode.
kernel_patch_t *kernel_patchset = ctxt.pkg2_kernel_id->kernel_patchset; kernel_patch_t *kernel_patchset = ctxt.pkg2_kernel_id->kernel_patchset;
if (kernel_patchset != NULL) if (kernel_patchset != NULL)

View file

@ -34,7 +34,6 @@
#define MERGE2(a, b) a ## b #define MERGE2(a, b) a ## b
#define CVTBL(tbl, cp) MERGE2(tbl, cp) #define CVTBL(tbl, cp) MERGE2(tbl, cp)
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
/* Code Conversion Tables */ /* Code Conversion Tables */
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
@ -623,5 +622,4 @@ DWORD ff_wtoupper ( /* Returns up-converted code point */
return uni; return uni;
} }
#endif /* #if FF_USE_LFN */ #endif /* #if FF_USE_LFN */

View file

@ -1264,6 +1264,7 @@ void ipl_main()
if (!ianos_loader(false, "bootloader/sys/libsys_lp0.bso", DRAM_LIB, (void *)sdram_get_params_patched())) if (!ianos_loader(false, "bootloader/sys/libsys_lp0.bso", DRAM_LIB, (void *)sdram_get_params_patched()))
h_cfg.errors |= ERR_LIBSYS_LP0; h_cfg.errors |= ERR_LIBSYS_LP0;
// Train DRAM and switch to max frequency.
minerva_init(); minerva_init();
minerva_change_freq(FREQ_1600); minerva_change_freq(FREQ_1600);

View file

@ -127,7 +127,7 @@ void mc_disable_ahb_redirect()
void mc_enable() void mc_enable()
{ {
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF) | 0x40000000; CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF) | 0x40000000;
// Enable MIPI CAL clock. // Enable EMC clock.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & 0xFDFFFFFF) | 0x2000000; CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & 0xFDFFFFFF) | 0x2000000;
// Enable MC clock. // Enable MC clock.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & 0xFFFFFFFE) | 1; CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & 0xFFFFFFFE) | 1;

View file

@ -64,6 +64,7 @@ void minerva_change_freq(minerva_freq_t freq)
{ {
if (!minerva_cfg) if (!minerva_cfg)
return; return;
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg; mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
if (minerva_cfg && (mtc_cfg->rate_from != freq)) if (minerva_cfg && (mtc_cfg->rate_from != freq))
{ {
@ -77,6 +78,7 @@ void minerva_periodic_training()
{ {
if (!minerva_cfg) if (!minerva_cfg)
return; return;
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg; mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
if (minerva_cfg && mtc_cfg->rate_from == FREQ_1600) if (minerva_cfg && mtc_cfg->rate_from == FREQ_1600)
{ {

View file

@ -20,6 +20,9 @@
#include "../soc/i2c.h" #include "../soc/i2c.h"
#include "../utils/util.h" #include "../utils/util.h"
#pragma GCC push_options
#pragma GCC optimize ("Os")
int bq24193_get_property(enum BQ24193_reg_prop prop, int *value) int bq24193_get_property(enum BQ24193_reg_prop prop, int *value)
{ {
u8 data; u8 data;
@ -160,3 +163,5 @@ void bq24193_fake_battery_removal()
value |= BQ24193_MISC_BATFET_DI_MASK; value |= BQ24193_MISC_BATFET_DI_MASK;
i2c_send_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_Misc, value); i2c_send_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_Misc, value);
} }
#pragma GCC pop_options

View file

@ -43,6 +43,9 @@
#define MAX17050_VMAX_TOLERANCE 50 /* 50 mV */ #define MAX17050_VMAX_TOLERANCE 50 /* 50 mV */
#pragma GCC push_options
#pragma GCC optimize ("Os")
int max17050_get_property(enum MAX17050_reg reg, int *value) int max17050_get_property(enum MAX17050_reg reg, int *value)
{ {
u16 data; u16 data;
@ -264,3 +267,5 @@ int max17050_fix_configuration()
return 0; return 0;
} }
#pragma GCC pop_options

View file

@ -52,7 +52,7 @@ void max77620_rtc_get_time(rtc_time_t *time)
} }
// Get date. // Get date.
time->date = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_DATE_REG) & 0x1f; time->day = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_DATE_REG) & 0x1f;
time->month = (i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_MONTH_REG) & 0xF) - 1; time->month = (i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_MONTH_REG) & 0xF) - 1;
time->year = (i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_YEAR_REG) & 0x7F) + 2000; time->year = (i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_YEAR_REG) & 0x7F) + 2000;
} }

View file

@ -64,7 +64,7 @@ typedef struct _rtc_time_t {
u8 sec; u8 sec;
u8 min; u8 min;
u8 hour; u8 hour;
u8 date; u8 day;
u8 month; u8 month;
u16 year; u16 year;
} rtc_time_t; } rtc_time_t;

View file

@ -149,7 +149,7 @@ void bpmp_mmu_disable()
// Clean and invalidate cache. // Clean and invalidate cache.
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY); bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY);
// Enable cache. // Disable cache.
BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) = 0; BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) = 0;
// HW bug. Invalidate cache again. // HW bug. Invalidate cache again.

View file

@ -366,7 +366,6 @@ static void _clock_sdmmc_clear_enable(u32 id)
static u32 _clock_sdmmc_table[8] = { 0 }; static u32 _clock_sdmmc_table[8] = { 0 };
#define PLLP_OUT0 0x0 #define PLLP_OUT0 0x0
static int _clock_sdmmc_config_clock_source_inner(u32 *pout, u32 id, u32 val) static int _clock_sdmmc_config_clock_source_inner(u32 *pout, u32 id, u32 val)
{ {
u32 divisor = 0; u32 divisor = 0;

View file

@ -123,7 +123,7 @@
#define CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP 0x620 #define CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP 0x620
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C6 0x65C #define CLK_RST_CONTROLLER_CLK_SOURCE_I2C6 0x65C
#define CLK_RST_CONTROLLER_CLK_SOURCE_EMC_DLL 0x664 #define CLK_RST_CONTROLLER_CLK_SOURCE_EMC_DLL 0x664
#define CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIP_CAL 0x66C #define CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL 0x66C
#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM 0x694 #define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM 0x694
#define CLK_RST_CONTROLLER_CLK_SOURCE_NVENC 0x6A0 #define CLK_RST_CONTROLLER_CLK_SOURCE_NVENC 0x6A0
#define CLK_RST_CONTROLLER_SE_SUPER_CLK_DIVIDER 0x704 #define CLK_RST_CONTROLLER_SE_SUPER_CLK_DIVIDER 0x704

View file

@ -116,8 +116,7 @@ int emummc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc)
if (f_stat(emu_cfg.emummc_file_based_path, &fno)) if (f_stat(emu_cfg.emummc_file_based_path, &fno))
{ {
gfx_printf("e1\n"); EPRINTF("Failed to open eMMC folder.");
gfx_printf(" %X\n ", emu_cfg.sector);
goto out; goto out;
} }
f_chmod(emu_cfg.emummc_file_based_path, AM_ARC, AM_ARC); f_chmod(emu_cfg.emummc_file_based_path, AM_ARC, AM_ARC);
@ -125,7 +124,7 @@ int emummc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc)
strcat(emu_cfg.emummc_file_based_path, "/00"); strcat(emu_cfg.emummc_file_based_path, "/00");
if (f_stat(emu_cfg.emummc_file_based_path, &fno)) if (f_stat(emu_cfg.emummc_file_based_path, &fno))
{ {
gfx_printf("e2\n"); EPRINTF("Failed to open emuMMC rawnand.");
goto out; goto out;
} }
emu_cfg.file_based_part_size = fno.fsize >> 9; emu_cfg.file_based_part_size = fno.fsize >> 9;

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (C) 2018 CTCaer * Copyright (C) 2018-2019 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,
@ -19,7 +19,6 @@
#include "sdmmc.h" #include "sdmmc.h"
#include "mmc.h" #include "mmc.h"
#include "sd.h" #include "sd.h"
#include "../config/config.h"
#include "../gfx/gfx.h" #include "../gfx/gfx.h"
#include "../mem/heap.h" #include "../mem/heap.h"
#include "../utils/util.h" #include "../utils/util.h"
@ -27,8 +26,6 @@
//#define DPRINTF(...) gfx_printf(__VA_ARGS__) //#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DPRINTF(...) #define DPRINTF(...)
extern hekate_config h_cfg;
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;
@ -72,6 +69,7 @@ static int _sdmmc_storage_execute_cmd_type1_ex(sdmmc_storage_t *storage, u32 *re
if (_sdmmc_storage_check_result(*resp)) if (_sdmmc_storage_check_result(*resp))
if (expected_state == 0x10 || R1_CURRENT_STATE(*resp) == expected_state) if (expected_state == 0x10 || R1_CURRENT_STATE(*resp) == expected_state)
return 1; return 1;
return 0; return 0;
} }
@ -85,6 +83,7 @@ static int _sdmmc_storage_go_idle_state(sdmmc_storage_t *storage)
{ {
sdmmc_cmd_t cmd; sdmmc_cmd_t cmd;
sdmmc_init_cmd(&cmd, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0); sdmmc_init_cmd(&cmd, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0);
return sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0); return sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0);
} }
@ -94,7 +93,9 @@ static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage, void *buf)
sdmmc_init_cmd(&cmd, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0); sdmmc_init_cmd(&cmd, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0))
return 0; return 0;
sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2); sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2);
return 1; return 1;
} }
@ -109,7 +110,9 @@ static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage, void *buf)
sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0); sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0))
return 0; return 0;
sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2); sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2);
return 1; return 1;
} }
@ -147,8 +150,10 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
u32 tmp = 0; u32 tmp = 0;
sdmmc_stop_transmission(storage->sdmmc, &tmp); sdmmc_stop_transmission(storage->sdmmc, &tmp);
_sdmmc_storage_get_status(storage, &tmp, 0); _sdmmc_storage_get_status(storage, &tmp, 0);
return 0; return 0;
} }
return 1; return 1;
} }
@ -156,7 +161,9 @@ int sdmmc_storage_end(sdmmc_storage_t *storage)
{ {
if (!_sdmmc_storage_go_idle_state(storage)) if (!_sdmmc_storage_go_idle_state(storage))
return 0; return 0;
sdmmc_end(storage->sdmmc); sdmmc_end(storage->sdmmc);
return 1; return 1;
} }
@ -178,14 +185,16 @@ static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 nu
msleep(100); msleep(100);
} while (retries); } while (retries);
return 0; return 0;
out:; out:;
DPRINTF("readwrite: %08X\n", blkcnt); DPRINTF("readwrite: %08X\n", blkcnt);
sector += blkcnt; sector += blkcnt;
num_sectors -= blkcnt; num_sectors -= blkcnt;
bbuf += 512 * blkcnt; bbuf += 512 * blkcnt;
} }
return 1; return 1;
} }
@ -236,14 +245,17 @@ static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power)
u32 cond = 0; u32 cond = 0;
if (!_mmc_storage_get_op_cond_inner(storage, &cond, power)) if (!_mmc_storage_get_op_cond_inner(storage, &cond, power))
break; break;
if (cond & MMC_CARD_BUSY) if (cond & MMC_CARD_BUSY)
{ {
if (cond & 0x40000000) if (cond & 0x40000000)
storage->has_sector_access = 1; storage->has_sector_access = 1;
return 1; return 1;
} }
if (get_tmr_ms() > timeout) if (get_tmr_ms() > timeout)
break; break;
usleep(1000); usleep(1000);
} }
@ -373,6 +385,7 @@ static int _mmc_storage_switch_buswidth(sdmmc_storage_t *storage, u32 bus_width)
if (_sdmmc_storage_check_status(storage)) if (_sdmmc_storage_check_status(storage))
{ {
sdmmc_set_bus_width(storage->sdmmc, bus_width); sdmmc_set_bus_width(storage->sdmmc, bus_width);
return 1; return 1;
} }
@ -383,14 +396,19 @@ static int _mmc_storage_enable_HS(sdmmc_storage_t *storage, int check)
{ {
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS))) if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS)))
return 0; return 0;
if (check && !_sdmmc_storage_check_status(storage)) if (check && !_sdmmc_storage_check_status(storage))
return 0; return 0;
if (!sdmmc_setup_clock(storage->sdmmc, 2)) if (!sdmmc_setup_clock(storage->sdmmc, 2))
return 0; return 0;
DPRINTF("[MMC] switched to HS\n");
DPRINTF("[MMC] switched to HS\n");
storage->csd.busspeed = 52; storage->csd.busspeed = 52;
if (check || _sdmmc_storage_check_status(storage)) if (check || _sdmmc_storage_check_status(storage))
return 1; return 1;
return 0; return 0;
} }
@ -398,12 +416,16 @@ static int _mmc_storage_enable_HS200(sdmmc_storage_t *storage)
{ {
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS200))) if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS200)))
return 0; return 0;
if (!sdmmc_setup_clock(storage->sdmmc, 3)) if (!sdmmc_setup_clock(storage->sdmmc, 3))
return 0; return 0;
if (!sdmmc_config_tuning(storage->sdmmc, 3, MMC_SEND_TUNING_BLOCK_HS200)) if (!sdmmc_config_tuning(storage->sdmmc, 3, 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);
} }
@ -411,17 +433,24 @@ static int _mmc_storage_enable_HS400(sdmmc_storage_t *storage)
{ {
if (!_mmc_storage_enable_HS200(storage)) if (!_mmc_storage_enable_HS200(storage))
return 0; return 0;
sdmmc_get_venclkctl(storage->sdmmc); sdmmc_get_venclkctl(storage->sdmmc);
if (!_mmc_storage_enable_HS(storage, 0)) if (!_mmc_storage_enable_HS(storage, 0))
return 0; return 0;
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_BUS_WIDTH, EXT_CSD_DDR_BUS_WIDTH_8))) if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_BUS_WIDTH, EXT_CSD_DDR_BUS_WIDTH_8)))
return 0; return 0;
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS400))) if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS400)))
return 0; return 0;
if (!sdmmc_setup_clock(storage->sdmmc, 4)) if (!sdmmc_setup_clock(storage->sdmmc, 4))
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);
} }
@ -433,8 +462,7 @@ static int _mmc_storage_enable_highspeed(sdmmc_storage_t *storage, u32 card_type
goto out; goto out;
if (sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_8 && if (sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_8 &&
card_type & EXT_CSD_CARD_TYPE_HS400_1_8V && card_type & EXT_CSD_CARD_TYPE_HS400_1_8V && type == 4)
type == 4)
return _mmc_storage_enable_HS400(storage); return _mmc_storage_enable_HS400(storage);
if (sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_8 || if (sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_8 ||
@ -446,6 +474,7 @@ static int _mmc_storage_enable_highspeed(sdmmc_storage_t *storage, u32 card_type
out:; out:;
if (card_type & EXT_CSD_CARD_TYPE_HS_52) if (card_type & EXT_CSD_CARD_TYPE_HS_52)
return _mmc_storage_enable_HS(storage, 1); return _mmc_storage_enable_HS(storage, 1);
return 1; return 1;
} }
@ -453,6 +482,7 @@ static int _mmc_storage_enable_bkops(sdmmc_storage_t *storage)
{ {
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_BKOPS_LEVEL_2))) if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_BKOPS_LEVEL_2)))
return 0; return 0;
return _sdmmc_storage_check_status(storage); return _sdmmc_storage_check_status(storage);
} }
@ -464,42 +494,42 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
if (!sdmmc_init(sdmmc, id, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, 0, 0)) if (!sdmmc_init(sdmmc, id, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, 0, 0))
return 0; return 0;
DPRINTF("[MMC] after init\n"); DPRINTF("[MMC] after init\n");
usleep(1000 + (74000 + sdmmc->divisor - 1) / sdmmc->divisor); usleep(1000 + (74000 + sdmmc->divisor - 1) / sdmmc->divisor);
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, storage->raw_cid)) if (!_sdmmc_storage_get_cid(storage, storage->raw_cid))
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, storage->raw_csd)) if (!_sdmmc_storage_get_csd(storage, storage->raw_csd))
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, 1)) if (!sdmmc_setup_clock(storage->sdmmc, 1))
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");
u32 *csd = (u32 *)storage->raw_csd; u32 *csd = (u32 *)storage->raw_csd;
//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.
@ -511,7 +541,7 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
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");
u8 *ext_csd = (u8 *)malloc(512); u8 *ext_csd = (u8 *)malloc(512);
if (!_mmc_storage_get_ext_csd(storage, ext_csd)) if (!_mmc_storage_get_ext_csd(storage, ext_csd))
@ -520,7 +550,7 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
return 0; return 0;
} }
free(ext_csd); free(ext_csd);
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
//gfx_hexdump(0, ext_csd, 512); //gfx_hexdump(0, ext_csd, 512);
@ -530,16 +560,16 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
if (storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_BKOPS_LEVEL_2) && 0) if (storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_BKOPS_LEVEL_2) && 0)
{ {
_mmc_storage_enable_bkops(storage); _mmc_storage_enable_bkops(storage);
DPRINTF("[MMC] BKOPS enabled\n"); DPRINTF("[MMC] BKOPS enabled\n");
} }
else else
{ {
DPRINTF("[MMC] BKOPS disabled\n"); DPRINTF("[MMC] BKOPS disabled\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] succesfully switched to highspeed mode\n"); DPRINTF("[MMC] succesfully switched to highspeed mode\n");
sdmmc_sd_clock_ctrl(storage->sdmmc, 1); sdmmc_sd_clock_ctrl(storage->sdmmc, 1);
@ -550,8 +580,10 @@ int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition)
{ {
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_PART_CONFIG, partition))) if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_PART_CONFIG, partition)))
return 0; return 0;
if (!_sdmmc_storage_check_status(storage)) if (!_sdmmc_storage_check_status(storage))
return 0; return 0;
storage->partition = partition; storage->partition = partition;
return 1; return 1;
} }
@ -565,6 +597,7 @@ static int _sd_storage_execute_app_cmd(sdmmc_storage_t *storage, u32 expected_st
u32 tmp; u32 tmp;
if (!_sdmmc_storage_execute_cmd_type1_ex(storage, &tmp, MMC_APP_CMD, storage->rca << 16, 0, expected_state, mask)) if (!_sdmmc_storage_execute_cmd_type1_ex(storage, &tmp, MMC_APP_CMD, storage->rca << 16, 0, expected_state, mask))
return 0; return 0;
return sdmmc_execute_cmd(storage->sdmmc, cmd, req, blkcnt_out); return sdmmc_execute_cmd(storage->sdmmc, cmd, req, blkcnt_out);
} }
@ -572,6 +605,7 @@ static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp
{ {
if (!_sdmmc_storage_execute_cmd_type1(storage, MMC_APP_CMD, storage->rca << 16, 0, R1_STATE_TRAN)) if (!_sdmmc_storage_execute_cmd_type1(storage, MMC_APP_CMD, storage->rca << 16, 0, R1_STATE_TRAN))
return 0; return 0;
return _sdmmc_storage_execute_cmd_type1_ex(storage, resp, cmd, arg, check_busy, expected_state, 0); return _sdmmc_storage_execute_cmd_type1_ex(storage, resp, cmd, arg, check_busy, expected_state, 0);
} }
@ -603,6 +637,7 @@ static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int
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, 0x10, is_version_1 ? 0x400000 : 0, &cmdbuf, 0, 0)) if (!_sd_storage_execute_app_cmd(storage, 0x10, is_version_1 ? 0x400000 : 0, &cmdbuf, 0, 0))
return 0; return 0;
return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3); return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3);
} }
@ -630,7 +665,7 @@ static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, i
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");
} }
} }
@ -784,17 +819,17 @@ void _sd_storage_set_current_limit(sdmmc_storage_t *storage, u8 *buf)
switch (pwr) switch (pwr)
{ {
case SD_SET_CURRENT_LIMIT_800: case SD_SET_CURRENT_LIMIT_800:
DPRINTF("[SD] Power limit raised to 800mA\n"); DPRINTF("[SD] Power limit raised to 800mA\n");
break; break;
case SD_SET_CURRENT_LIMIT_600: case SD_SET_CURRENT_LIMIT_600:
DPRINTF("[SD] Power limit raised to 600mA\n"); DPRINTF("[SD] Power limit raised to 600mA\n");
break; break;
case SD_SET_CURRENT_LIMIT_400: case SD_SET_CURRENT_LIMIT_400:
DPRINTF("[SD] Power limit raised to 800mA\n"); DPRINTF("[SD] Power limit raised to 800mA\n");
break; break;
default: default:
case SD_SET_CURRENT_LIMIT_200: case SD_SET_CURRENT_LIMIT_200:
DPRINTF("[SD] Power limit defaulted to 200mA\n"); DPRINTF("[SD] Power limit defaulted to 200mA\n");
break; break;
} }
} }
@ -803,10 +838,12 @@ int _sd_storage_enable_highspeed(sdmmc_storage_t *storage, u32 hs_type, u8 *buf)
{ {
if (!_sd_storage_switch(storage, buf, SD_SWITCH_CHECK, 0, hs_type)) if (!_sd_storage_switch(storage, buf, SD_SWITCH_CHECK, 0, hs_type))
return 0; return 0;
DPRINTF("[SD] SD supports switch to (U)HS check\n");
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] SD supports selected (U)HS mode\n");
if ((((u16)buf[0] << 8) | buf[1]) < 0x320) if ((((u16)buf[0] << 8) | buf[1]) < 0x320)
{ {
@ -841,7 +878,7 @@ int _sd_storage_enable_highspeed_low_volt(sdmmc_storage_t *storage, u32 type, u8
{ {
type = 11; type = 11;
hs_type = UHS_SDR104_BUS_SPEED; hs_type = UHS_SDR104_BUS_SPEED;
DPRINTF("[SD] Bus speed set to SDR104\n"); DPRINTF("[SD] Bus speed set to SDR104\n");
storage->csd.busspeed = 104; storage->csd.busspeed = 104;
break; break;
} }
@ -850,7 +887,7 @@ int _sd_storage_enable_highspeed_low_volt(sdmmc_storage_t *storage, u32 type, u8
{ {
type = 10; type = 10;
hs_type = UHS_SDR50_BUS_SPEED; hs_type = UHS_SDR50_BUS_SPEED;
DPRINTF("[SD] Bus speed set to SDR50\n"); DPRINTF("[SD] Bus speed set to SDR50\n");
storage->csd.busspeed = 50; storage->csd.busspeed = 50;
break; break;
} }
@ -859,7 +896,7 @@ int _sd_storage_enable_highspeed_low_volt(sdmmc_storage_t *storage, u32 type, u8
return 0; return 0;
type = 8; type = 8;
hs_type = UHS_SDR12_BUS_SPEED; hs_type = UHS_SDR12_BUS_SPEED;
DPRINTF("[SD] Bus speed set to SDR12\n"); DPRINTF("[SD] Bus speed set to SDR12\n");
storage->csd.busspeed = 12; storage->csd.busspeed = 12;
break; break;
default: default:
@ -869,10 +906,13 @@ int _sd_storage_enable_highspeed_low_volt(sdmmc_storage_t *storage, u32 type, u8
if (!_sd_storage_enable_highspeed(storage, hs_type, buf)) if (!_sd_storage_enable_highspeed(storage, hs_type, buf))
return 0; return 0;
DPRINTF("[SD] 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] setup clock\n");
if (!sdmmc_config_tuning(storage->sdmmc, type, MMC_SEND_TUNING_BLOCK)) if (!sdmmc_config_tuning(storage->sdmmc, type, MMC_SEND_TUNING_BLOCK))
return 0; return 0;
DPRINTF("[SD] config tuning\n");
return _sdmmc_storage_check_status(storage); return _sdmmc_storage_check_status(storage);
} }
@ -886,8 +926,10 @@ int _sd_storage_enable_highspeed_high_volt(sdmmc_storage_t *storage, u8 *buf)
if (!_sd_storage_enable_highspeed(storage, 1, buf)) if (!_sd_storage_enable_highspeed(storage, 1, buf))
return 0; return 0;
if (!_sdmmc_storage_check_status(storage)) if (!_sdmmc_storage_check_status(storage))
return 0; return 0;
return sdmmc_setup_clock(storage->sdmmc, 7); return sdmmc_setup_clock(storage->sdmmc, 7);
} }
@ -950,7 +992,7 @@ static 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: Card lacks mandatory SD Status function\n"); DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n");
return 0; return 0;
} }
@ -1014,7 +1056,7 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
void sdmmc_storage_init_wait_sd() void sdmmc_storage_init_wait_sd()
{ {
u32 sd_poweroff_time = (u32)get_tmr_ms() - h_cfg.sd_timeoff; u32 sd_poweroff_time = (u32)get_tmr_ms() - sd_power_cycle_time_start;
if (sd_poweroff_time < 100) if (sd_poweroff_time < 100)
msleep(100 - sd_poweroff_time); msleep(100 - sd_poweroff_time);
} }
@ -1031,35 +1073,35 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
if (!sdmmc_init(sdmmc, id, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, 5, 0)) if (!sdmmc_init(sdmmc, id, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, 5, 0))
return 0; return 0;
DPRINTF("[SD] after init\n"); DPRINTF("[SD] after init\n");
usleep(1000 + (74000 + sdmmc->divisor - 1) / sdmmc->divisor); usleep(1000 + (74000 + sdmmc->divisor - 1) / sdmmc->divisor);
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");
is_version_1 = _sd_storage_send_if_cond(storage); is_version_1 = _sd_storage_send_if_cond(storage);
if (is_version_1 == 2) if (is_version_1 == 2)
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_version_1, bus_width == SDMMC_BUS_WIDTH_4 && type == 11)) if (!_sd_storage_get_op_cond(storage, is_version_1, bus_width == SDMMC_BUS_WIDTH_4 && type == 11))
return 0; return 0;
DPRINTF("[SD] got op cond\n"); DPRINTF("[SD] got op cond\n");
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid)) if (!_sdmmc_storage_get_cid(storage, storage->raw_cid))
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, storage->raw_csd)) if (!_sdmmc_storage_get_csd(storage, storage->raw_csd))
return 0; return 0;
DPRINTF("[SD] got csd\n"); DPRINTF("[SD] got csd\n");
//Parse CSD. //Parse CSD.
_sd_storage_parse_csd(storage); _sd_storage_parse_csd(storage);
@ -1072,7 +1114,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
storage->sec_cnt = storage->csd.c_size << 10; storage->sec_cnt = storage->csd.c_size << 10;
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;
} }
@ -1080,21 +1122,21 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
{ {
if (!sdmmc_setup_clock(storage->sdmmc, 6)) if (!sdmmc_setup_clock(storage->sdmmc, 6))
return 0; return 0;
DPRINTF("[SD] after setup clock\n"); DPRINTF("[SD] after setup 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");
u32 tmp = 0; u32 tmp = 0;
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");
u8 *buf = (u8 *)malloc(512); u8 *buf = (u8 *)malloc(512);
if (!_sd_storage_get_scr(storage, buf)) if (!_sd_storage_get_scr(storage, buf))
@ -1104,7 +1146,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
} }
//gfx_hexdump(0, storage->raw_scr, 8); //gfx_hexdump(0, storage->raw_scr, 8);
DPRINTF("[SD] got scr\n"); DPRINTF("[SD] got scr\n");
// Check if card supports a wider bus and if it's not SD Version 1.X // Check if card supports a wider bus and if it's not SD Version 1.X
if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & 4) && (storage->scr.sda_vsn & 0xF)) if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & 4) && (storage->scr.sda_vsn & 0xF))
@ -1115,11 +1157,11 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
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
{ {
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)
@ -1129,7 +1171,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
free(buf); free(buf);
return 0; return 0;
} }
DPRINTF("[SD] enabled highspeed (low voltage)\n"); DPRINTF("[SD] enabled UHS\n");
} }
else if (type != 6 && (storage->scr.sda_vsn & 0xF) != 0) else if (type != 6 && (storage->scr.sda_vsn & 0xF) != 0)
{ {
@ -1138,7 +1180,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
free(buf); free(buf);
return 0; return 0;
} }
DPRINTF("[SD] enabled highspeed (high voltage)\n"); DPRINTF("[SD] enabled HS\n");
storage->csd.busspeed = 25; storage->csd.busspeed = 25;
} }
@ -1147,7 +1189,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
// 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");
} }
free(buf); free(buf);
@ -1192,13 +1234,13 @@ int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc)
if (!sdmmc_init(sdmmc, SDMMC_2, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_8, 14, 0)) if (!sdmmc_init(sdmmc, SDMMC_2, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_8, 14, 0))
return 0; return 0;
DPRINTF("[gc] after init\n"); DPRINTF("[gc] after init\n");
usleep(1000 + (10000 + sdmmc->divisor - 1) / sdmmc->divisor); usleep(1000 + (10000 + sdmmc->divisor - 1) / sdmmc->divisor);
if (!sdmmc_config_tuning(storage->sdmmc, 14, MMC_SEND_TUNING_BLOCK_HS200)) if (!sdmmc_config_tuning(storage->sdmmc, 14, MMC_SEND_TUNING_BLOCK_HS200))
return 0; return 0;
DPRINTF("[gc] after tuning\n"); DPRINTF("[gc] after tuning\n");
sdmmc_sd_clock_ctrl(sdmmc, 1); sdmmc_sd_clock_ctrl(sdmmc, 1);

View file

@ -21,6 +21,8 @@
#include "../utils/types.h" #include "../utils/types.h"
#include "sdmmc_driver.h" #include "sdmmc_driver.h"
u32 sd_power_cycle_time_start;
typedef struct _mmc_cid typedef struct _mmc_cid
{ {
u32 manfid; u32 manfid;

View file

@ -19,7 +19,6 @@
#include "mmc.h" #include "mmc.h"
#include "sdmmc.h" #include "sdmmc.h"
#include "../config/config.h"
#include "../gfx/gfx.h" #include "../gfx/gfx.h"
#include "../power/max7762x.h" #include "../power/max7762x.h"
#include "../soc/bpmp.h" #include "../soc/bpmp.h"
@ -33,8 +32,6 @@
//#define DPRINTF(...) gfx_printf(__VA_ARGS__) //#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DPRINTF(...) #define DPRINTF(...)
extern hekate_config h_cfg;
/*! SCMMC controller base addresses. */ /*! SCMMC controller base addresses. */
static const u32 _sdmmc_bases[4] = { static const u32 _sdmmc_bases[4] = {
0x700B0000, 0x700B0000,
@ -125,6 +122,7 @@ static int _sdmmc_config_ven_ceata_clk(sdmmc_t *sdmmc, u32 id)
{ {
if (!sdmmc->venclkctl_set) if (!sdmmc->venclkctl_set)
return 0; return 0;
tap_val = sdmmc->venclkctl_tap; tap_val = sdmmc->venclkctl_tap;
} }
else else
@ -235,7 +233,7 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180; sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180;
break; break;
case 4: case 4:
// Non standard // 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;
@ -513,13 +511,17 @@ static int _sdmmc_config_tuning_once(sdmmc_t *sdmmc, u32 cmd)
return 0; return 0;
_sdmmc_setup_read_small_block(sdmmc); _sdmmc_setup_read_small_block(sdmmc);
sdmmc->regs->norintstsen |= TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY; sdmmc->regs->norintstsen |= TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY;
sdmmc->regs->norintsts = sdmmc->regs->norintsts; sdmmc->regs->norintsts = sdmmc->regs->norintsts;
sdmmc->regs->clkcon &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE; sdmmc->regs->clkcon &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
_sdmmc_parse_cmd_48(sdmmc, cmd); _sdmmc_parse_cmd_48(sdmmc, cmd);
_sdmmc_get_clkcon(sdmmc); _sdmmc_get_clkcon(sdmmc);
usleep(1); usleep(1);
_sdmmc_reset(sdmmc); _sdmmc_reset(sdmmc);
sdmmc->regs->clkcon |= TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE; sdmmc->regs->clkcon |= TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
_sdmmc_get_clkcon(sdmmc); _sdmmc_get_clkcon(sdmmc);
@ -535,10 +537,13 @@ static int _sdmmc_config_tuning_once(sdmmc_t *sdmmc, u32 cmd)
return 1; return 1;
} }
} }
_sdmmc_reset(sdmmc); _sdmmc_reset(sdmmc);
sdmmc->regs->norintstsen &= 0xFFDF; sdmmc->regs->norintstsen &= 0xFFDF;
_sdmmc_get_clkcon(sdmmc); _sdmmc_get_clkcon(sdmmc);
usleep((1000 * 8 + sdmmc->divisor - 1) / sdmmc->divisor); usleep((1000 * 8 + sdmmc->divisor - 1) / sdmmc->divisor);
return 0; return 0;
} }
@ -565,8 +570,8 @@ int sdmmc_config_tuning(sdmmc_t *sdmmc, u32 type, u32 cmd)
return 0; return 0;
} }
sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFF1FFF) | flag; sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFF1FFF) | flag; // Tries.
sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFFE03F) | 0x40; sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFFE03F) | 0x40; // Multiplier.
sdmmc->regs->ventunctl0 |= 0x20000; sdmmc->regs->ventunctl0 |= 0x20000;
sdmmc->regs->hostctl2 |= SDHCI_CTRL_EXEC_TUNING; sdmmc->regs->hostctl2 |= SDHCI_CTRL_EXEC_TUNING;
@ -579,6 +584,7 @@ int sdmmc_config_tuning(sdmmc_t *sdmmc, u32 type, u32 cmd)
if (sdmmc->regs->hostctl2 & SDHCI_CTRL_TUNED_CLK) if (sdmmc->regs->hostctl2 & SDHCI_CTRL_TUNED_CLK)
return 1; return 1;
return 0; return 0;
} }
@ -748,11 +754,14 @@ static int _sdmmc_stop_transmission_inner(sdmmc_t *sdmmc, u32 *rsp)
return 0; return 0;
_sdmmc_enable_interrupts(sdmmc); _sdmmc_enable_interrupts(sdmmc);
cmd.cmd = MMC_STOP_TRANSMISSION; cmd.cmd = MMC_STOP_TRANSMISSION;
cmd.arg = 0; cmd.arg = 0;
cmd.rsp_type = SDMMC_RSP_TYPE_1; cmd.rsp_type = SDMMC_RSP_TYPE_1;
cmd.check_busy = 1; cmd.check_busy = 1;
_sdmmc_parse_cmdbuf(sdmmc, &cmd, false); _sdmmc_parse_cmdbuf(sdmmc, &cmd, false);
int res = _sdmmc_wait_request(sdmmc); int res = _sdmmc_wait_request(sdmmc);
_sdmmc_mask_interrupts(sdmmc); _sdmmc_mask_interrupts(sdmmc);
@ -760,6 +769,7 @@ static int _sdmmc_stop_transmission_inner(sdmmc_t *sdmmc, u32 *rsp)
return 0; return 0;
_sdmmc_cache_rsp(sdmmc, rsp, 4, SDMMC_RSP_TYPE_1); _sdmmc_cache_rsp(sdmmc, rsp, 4, SDMMC_RSP_TYPE_1);
return _sdmmc_wait_prnsts_type1(sdmmc); return _sdmmc_wait_prnsts_type1(sdmmc);
} }
@ -779,6 +789,7 @@ int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp)
int res = _sdmmc_stop_transmission_inner(sdmmc, rsp); int res = _sdmmc_stop_transmission_inner(sdmmc, rsp);
usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor); usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor);
if (should_disable_sd_clock) if (should_disable_sd_clock)
sdmmc->regs->clkcon &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE; sdmmc->regs->clkcon &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
@ -911,6 +922,7 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
{ {
if (blkcnt_out) if (blkcnt_out)
*blkcnt_out = blkcnt; *blkcnt_out = blkcnt;
if (req->is_auto_cmd12) if (req->is_auto_cmd12)
sdmmc->rsp3 = sdmmc->regs->rspreg3; sdmmc->rsp3 = sdmmc->regs->rspreg3;
} }
@ -930,6 +942,8 @@ static int _sdmmc_config_sdmmc1()
gpio_config(GPIO_PORT_Z, GPIO_PIN_1, GPIO_MODE_GPIO); gpio_config(GPIO_PORT_Z, GPIO_PIN_1, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_Z, GPIO_PIN_1, GPIO_OUTPUT_DISABLE); gpio_output_enable(GPIO_PORT_Z, GPIO_PIN_1, GPIO_OUTPUT_DISABLE);
usleep(100); usleep(100);
// Check if SD card is inserted.
if(!!gpio_read(GPIO_PORT_Z, GPIO_PIN_1)) if(!!gpio_read(GPIO_PORT_Z, GPIO_PIN_1))
return 0; return 0;
@ -943,7 +957,7 @@ static int _sdmmc_config_sdmmc1()
*/ */
// Configure SDMMC1 pinmux. // Configure SDMMC1 pinmux.
APB_MISC(APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL) = 1; APB_MISC(APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL) = 1; // Enable deep loopback for SDMMC1 CLK pad.
PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED; PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED;
PINMUX_AUX(PINMUX_AUX_SDMMC1_CMD) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP; PINMUX_AUX(PINMUX_AUX_SDMMC1_CMD) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP;
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT3) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP; PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT3) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP;
@ -1014,18 +1028,23 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int n
sdmmc->regs->sdmemcmppadctl = (sdmmc->regs->sdmemcmppadctl & 0xF) | 7; sdmmc->regs->sdmemcmppadctl = (sdmmc->regs->sdmemcmppadctl & 0xF) | 7;
if (!_sdmmc_autocal_config_offset(sdmmc, power)) if (!_sdmmc_autocal_config_offset(sdmmc, power))
return 0; return 0;
_sdmmc_autocal_execute(sdmmc, power); _sdmmc_autocal_execute(sdmmc, power);
if (_sdmmc_enable_internal_clock(sdmmc)) if (_sdmmc_enable_internal_clock(sdmmc))
{ {
sdmmc_set_bus_width(sdmmc, bus_width); sdmmc_set_bus_width(sdmmc, bus_width);
_sdmmc_set_voltage(sdmmc, power); _sdmmc_set_voltage(sdmmc, power);
if (sdmmc_setup_clock(sdmmc, type)) if (sdmmc_setup_clock(sdmmc, type))
{ {
sdmmc_sd_clock_ctrl(sdmmc, no_sd); sdmmc_sd_clock_ctrl(sdmmc, no_sd);
_sdmmc_sd_clock_enable(sdmmc); _sdmmc_sd_clock_enable(sdmmc);
_sdmmc_get_clkcon(sdmmc); _sdmmc_get_clkcon(sdmmc);
return 1; return 1;
} }
return 0; return 0;
} }
return 0; return 0;
@ -1044,8 +1063,8 @@ void sdmmc_end(sdmmc_t *sdmmc)
{ {
gpio_output_enable(GPIO_PORT_E, GPIO_PIN_4, GPIO_OUTPUT_DISABLE); gpio_output_enable(GPIO_PORT_E, GPIO_PIN_4, GPIO_OUTPUT_DISABLE);
max77620_regulator_enable(REGULATOR_LDO2, 0); max77620_regulator_enable(REGULATOR_LDO2, 0);
h_cfg.sd_timeoff = get_tmr_ms(); // Some sandisc U1 cards need 100ms for a power cycle. sd_power_cycle_time_start = get_tmr_ms(); // Some sandisc U1 cards need 100ms for a power cycle.
msleep(1); // To power cycle, min 1ms without power is needed. usleep(1000); // To power cycle, min 1ms without power is needed.
} }
_sdmmc_get_clkcon(sdmmc); _sdmmc_get_clkcon(sdmmc);
@ -1082,6 +1101,7 @@ int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *b
int res = _sdmmc_execute_cmd_inner(sdmmc, cmd, req, blkcnt_out); int res = _sdmmc_execute_cmd_inner(sdmmc, cmd, req, blkcnt_out);
usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor); usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor);
if (should_disable_sd_clock) if (should_disable_sd_clock)
sdmmc->regs->clkcon &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE; sdmmc->regs->clkcon &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
@ -1119,7 +1139,7 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc)
{ {
sdmmc->regs->clkcon |= TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE; sdmmc->regs->clkcon |= TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
_sdmmc_get_clkcon(sdmmc); _sdmmc_get_clkcon(sdmmc);
msleep(1); usleep(1000);
if ((sdmmc->regs->prnsts & 0xF00000) == 0xF00000) if ((sdmmc->regs->prnsts & 0xF00000) == 0xF00000)
return 1; return 1;
} }

View file

@ -23,6 +23,7 @@
#include "../libs/fatfs/ff.h" #include "../libs/fatfs/ff.h"
#include "../soc/fuse.h" #include "../soc/fuse.h"
#include "../soc/t210.h" #include "../soc/t210.h"
#include "../storage/sdmmc.h"
#include "../utils/btn.h" #include "../utils/btn.h"
#include "../utils/list.h" #include "../utils/list.h"
#include "../utils/util.h" #include "../utils/util.h"
@ -50,8 +51,9 @@ void set_default_configuration()
h_cfg.errors = 0; h_cfg.errors = 0;
h_cfg.sept_run = EMC(EMC_SCRATCH0) & EMC_SEPT_RUN; h_cfg.sept_run = EMC(EMC_SCRATCH0) & EMC_SEPT_RUN;
h_cfg.rcm_patched = fuse_check_patched_rcm(); h_cfg.rcm_patched = fuse_check_patched_rcm();
h_cfg.sd_timeoff = 0;
h_cfg.emummc_force_disable = false; h_cfg.emummc_force_disable = false;
sd_power_cycle_time_start = 0xFFFFFFF;
} }
int create_config_entry() int create_config_entry()

View file

@ -37,7 +37,6 @@ typedef struct _hekate_config
bool emummc_force_disable; bool emummc_force_disable;
bool rcm_patched; bool rcm_patched;
u32 sbar_time_keeping; u32 sbar_time_keeping;
u32 sd_timeoff;
u32 errors; u32 errors;
} hekate_config; } hekate_config;

View file

@ -1181,6 +1181,7 @@ static lv_res_t _create_window_home_launch(lv_obj_t *btn)
} }
else else
no_boot_entries = true; no_boot_entries = true;
sd_unmount(false); sd_unmount(false);
free(tmp_path); free(tmp_path);

View file

@ -20,6 +20,7 @@
#include "fe_emummc_tools.h" #include "fe_emummc_tools.h"
#include "../config/ini.h" #include "../config/ini.h"
#include "../libs/fatfs/ff.h" #include "../libs/fatfs/ff.h"
#include "../mem/heap.h"
#include "../storage/sdmmc.h" #include "../storage/sdmmc.h"
#include "../utils/dirlist.h" #include "../utils/dirlist.h"
#include "../utils/list.h" #include "../utils/list.h"

View file

@ -51,54 +51,61 @@ void display_init()
max77620_regulator_set_volt_and_flags(REGULATOR_LDO0, 1200000, MAX77620_POWER_MODE_NORMAL); // Configure to 1.2V. max77620_regulator_set_volt_and_flags(REGULATOR_LDO0, 1200000, MAX77620_POWER_MODE_NORMAL); // Configure to 1.2V.
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO7, MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH | MAX77620_CNFG_GPIO_DRV_PUSHPULL); i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO7, MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH | MAX77620_CNFG_GPIO_DRV_PUSHPULL);
// Enable MIPI CAL, DSI, DISP1, HOST1X, UART_FST_MIPI_CAL, DSIA LP clocks. // Enable Display Interface specific clocks.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = 0x1010000; CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = 0x1010000; // Clear reset DSI, MIPI_CAL.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = 0x1010000; CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = 0x1010000; // Set enable clock DSI, MIPI_CAL.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = 0x18000000;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = 0x18000000;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = 0x20000;
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIP_CAL) = 0xA;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_SET) = 0x80000;
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP) = 0xA;
// DPD idle. CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = 0x18000000; // Clear reset DISP1, HOST1X.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = 0x18000000; // Set enable clock DISP1, HOST1X.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = 0x20000; // Set enable clock UART_FST_MIPI_CAL.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL) = 10; // Set PLLP_OUT3 and div 6 (17MHz).
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_SET) = 0x80000; // Set enable clock DSIA_LP.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP) = 10; // Set PLLP_OUT and div 6 (68MHz).
// Disable deap power down.
PMC(APBDEV_PMC_IO_DPD_REQ) = 0x40000000; PMC(APBDEV_PMC_IO_DPD_REQ) = 0x40000000;
PMC(APBDEV_PMC_IO_DPD2_REQ) = 0x40000000; PMC(APBDEV_PMC_IO_DPD2_REQ) = 0x40000000;
// Config pins. // Config LCD and Backlight pins.
PINMUX_AUX(PINMUX_AUX_NFC_EN) &= ~PINMUX_TRISTATE; PINMUX_AUX(PINMUX_AUX_NFC_EN) &= ~PINMUX_TRISTATE;
PINMUX_AUX(PINMUX_AUX_NFC_INT) &= ~PINMUX_TRISTATE; PINMUX_AUX(PINMUX_AUX_NFC_INT) &= ~PINMUX_TRISTATE;
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) &= ~PINMUX_TRISTATE; PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) &= ~PINMUX_TRISTATE;
PINMUX_AUX(PINMUX_AUX_LCD_BL_EN) &= ~PINMUX_TRISTATE; PINMUX_AUX(PINMUX_AUX_LCD_BL_EN) &= ~PINMUX_TRISTATE;
PINMUX_AUX(PINMUX_AUX_LCD_RST) &= ~PINMUX_TRISTATE; PINMUX_AUX(PINMUX_AUX_LCD_RST) &= ~PINMUX_TRISTATE;
gpio_config(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_MODE_GPIO); // Backlight +-5V. // Set Backlight +-5V pins mode and direction
gpio_output_enable(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_OUTPUT_ENABLE); // Backlight +-5V. gpio_config(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_OUTPUT_ENABLE);
// Enable Backlight power.
gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_HIGH); // Backlight +5V enable. gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_HIGH); // Backlight +5V enable.
usleep(10000); usleep(10000);
gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_HIGH); // Backlight -5V enable. gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_HIGH); // Backlight -5V enable.
usleep(10000); usleep(10000);
gpio_config(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_MODE_GPIO); // Backlight PWM, Enable, Reset. // Configure Backlight pins (PWM, EN, RST).
gpio_config(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_OUTPUT_ENABLE); gpio_output_enable(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_OUTPUT_ENABLE);
gpio_write(GPIO_PORT_V, GPIO_PIN_1, GPIO_HIGH); // Backlight Enable enable. gpio_write(GPIO_PORT_V, GPIO_PIN_1, GPIO_HIGH); // Enable Backlight EN.
// Config display interface and display. // Power up supply regulator for display interface.
MIPI_CAL(MIPI_CAL_MIPI_BIAS_PAD_CFG2) = 0; MIPI_CAL(MIPI_CAL_MIPI_BIAS_PAD_CFG2) = 0;
// Set DISP1 clock source and parrent clock.
exec_cfg((u32 *)CLOCK_BASE, _display_config_1, 4); exec_cfg((u32 *)CLOCK_BASE, _display_config_1, 4);
// Setup display communication interfaces.
exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_2, 94); exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_2, 94);
exec_cfg((u32 *)DSI_BASE, _display_config_3, 61); exec_cfg((u32 *)DSI_BASE, _display_config_3, 61);
usleep(10000); usleep(10000);
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_HIGH); // Backlight Reset enable. // Enable Backlight Reset.
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_HIGH);
usleep(60000); usleep(60000);
// Setups DSI packet configuration and request display id.
DSI(_DSIREG(DSI_BTA_TIMING)) = 0x50204; DSI(_DSIREG(DSI_BTA_TIMING)) = 0x50204;
DSI(_DSIREG(DSI_WR_DATA)) = 0x337; // MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE DSI(_DSIREG(DSI_WR_DATA)) = 0x337; // MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST; DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
@ -127,19 +134,22 @@ void display_init()
usleep(20000); usleep(20000);
// Configure PLLD for DISP1.
exec_cfg((u32 *)CLOCK_BASE, _display_config_6, 3); exec_cfg((u32 *)CLOCK_BASE, _display_config_6, 3);
// Finalize DSI configuration.
exec_cfg((u32 *)DSI_BASE, _display_config_5, 21); exec_cfg((u32 *)DSI_BASE, _display_config_5, 21);
DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = 4; DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = 4;
exec_cfg((u32 *)DSI_BASE, _display_config_7, 10); exec_cfg((u32 *)DSI_BASE, _display_config_7, 10);
usleep(10000); usleep(10000);
// Calibrate display communication pads.
exec_cfg((u32 *)MIPI_CAL_BASE, _display_config_8, 6); exec_cfg((u32 *)MIPI_CAL_BASE, _display_config_8, 6);
exec_cfg((u32 *)DSI_BASE, _display_config_9, 4); exec_cfg((u32 *)DSI_BASE, _display_config_9, 4);
exec_cfg((u32 *)MIPI_CAL_BASE, _display_config_10, 16); exec_cfg((u32 *)MIPI_CAL_BASE, _display_config_10, 16);
usleep(10000); usleep(10000);
// Enable video display controller.
exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_11, 113); exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_11, 113);
} }
@ -147,11 +157,10 @@ void display_backlight_pwm_init()
{ {
clock_enable_pwm(); clock_enable_pwm();
PWM(PWM_CONTROLLER_PWM_CSR_0) = (1 << 31); // Enable PWM PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN; // Enable PWM and set it to 25KHz PFM.
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) >> 2) << 2 | 1; // PWM clock source. PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & 0xFFFFFFFC) | 1; // PWM clock source.
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight power mode. gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight power mode.
} }
void display_backlight(bool enable) void display_backlight(bool enable)
@ -172,7 +181,7 @@ void display_backlight_brightness(u32 brightness, u32 step_delay)
{ {
for (u32 i = old_value; i < brightness + 1; i++) for (u32 i = old_value; i < brightness + 1; i++)
{ {
PWM(PWM_CONTROLLER_PWM_CSR_0) = (1 << 31) | (i << 16); // Enable PWM PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN | (i << 16); // Enable PWM and set it to 25KHz PFM.
usleep(step_delay); usleep(step_delay);
} }
} }
@ -180,7 +189,7 @@ void display_backlight_brightness(u32 brightness, u32 step_delay)
{ {
for (u32 i = old_value; i > brightness; i--) for (u32 i = old_value; i > brightness; i--)
{ {
PWM(PWM_CONTROLLER_PWM_CSR_0) = (1 << 31) | (i << 16); // Enable PWM PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN | (i << 16); // Enable PWM and set it to 25KHz PFM.
usleep(step_delay); usleep(step_delay);
} }
} }
@ -196,13 +205,14 @@ void display_end()
DSI(_DSIREG(DSI_WR_DATA)) = 0x2805; // MIPI_DCS_SET_DISPLAY_OFF DSI(_DSIREG(DSI_WR_DATA)) = 0x2805; // MIPI_DCS_SET_DISPLAY_OFF
DISPLAY_A(_DIREG(DC_CMD_STATE_ACCESS)) = READ_MUX | WRITE_MUX; DISPLAY_A(_DIREG(DC_CMD_STATE_ACCESS)) = READ_MUX | WRITE_MUX;
DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0; DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0; // Disable host cmd packet.
// De-initialize video controller.
exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_12, 17); exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_12, 17);
exec_cfg((u32 *)DSI_BASE, _display_config_13, 16); exec_cfg((u32 *)DSI_BASE, _display_config_13, 16);
usleep(10000); usleep(10000);
// De-initialize display panel.
if (_display_ver == 0x10) if (_display_ver == 0x10)
exec_cfg((u32 *)DSI_BASE, _display_config_14, 22); exec_cfg((u32 *)DSI_BASE, _display_config_14, 22);
@ -211,31 +221,31 @@ void display_end()
usleep(50000); usleep(50000);
// Disable display and backlight pins.
gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW); //Backlight Reset disable. gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW); //Backlight Reset disable.
usleep(10000); usleep(10000);
gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_LOW); //Backlight -5V disable. gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_LOW); //Backlight -5V disable.
usleep(10000); usleep(10000);
gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_LOW); //Backlight +5V disable. gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_LOW); //Backlight +5V disable.
usleep(10000); usleep(10000);
// Disable clocks. // Disable Display Interface specific clocks.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = 0x1010000; CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = 0x1010000; // Set reset clock DSI, MIPI_CAL.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_CLR) = 0x1010000; CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_CLR) = 0x1010000; // Clear enable clock DSI, MIPI_CAL.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = 0x18000000; CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = 0x18000000; // Set reset DISP1, HOST1X.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = 0x18000000; CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = 0x18000000; // Clear enable DISP1, HOST1X.
// Power down pads.
DSI(_DSIREG(DSI_PAD_CONTROL_0)) = DSI_PAD_CONTROL_VS1_PULLDN_CLK | DSI_PAD_CONTROL_VS1_PULLDN(0xF) | DSI_PAD_CONTROL_VS1_PDIO_CLK | DSI_PAD_CONTROL_VS1_PDIO(0xF); DSI(_DSIREG(DSI_PAD_CONTROL_0)) = DSI_PAD_CONTROL_VS1_PULLDN_CLK | DSI_PAD_CONTROL_VS1_PULLDN(0xF) | DSI_PAD_CONTROL_VS1_PDIO_CLK | DSI_PAD_CONTROL_VS1_PDIO(0xF);
DSI(_DSIREG(DSI_POWER_CONTROL)) = 0; DSI(_DSIREG(DSI_POWER_CONTROL)) = 0;
// Switch to automatic function mode.
gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight PWM. gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight PWM.
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & ~PINMUX_TRISTATE) | PINMUX_TRISTATE; PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & ~PINMUX_TRISTATE) | PINMUX_TRISTATE;
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) >> 2) << 2 | 1; PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & 0xFFFFFFFC)| 1;
} }
void display_color_screen(u32 color) void display_color_screen(u32 color)
@ -248,7 +258,6 @@ void display_color_screen(u32 color)
DISPLAY_A(_DIREG(DC_WIN_CD_WIN_OPTIONS)) = 0; DISPLAY_A(_DIREG(DC_WIN_CD_WIN_OPTIONS)) = 0;
DISPLAY_A(_DIREG(DC_DISP_BLEND_BACKGROUND_COLOR)) = color; DISPLAY_A(_DIREG(DC_DISP_BLEND_BACKGROUND_COLOR)) = color;
DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = (DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) & 0xFFFFFFFE) | GENERAL_ACT_REQ; DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = (DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) & 0xFFFFFFFE) | GENERAL_ACT_REQ;
usleep(35000); usleep(35000);
display_backlight(true); display_backlight(true);

View file

@ -235,7 +235,7 @@
#define UV_LINE_STRIDE(x) (((x) & 0xffff) << 16) #define UV_LINE_STRIDE(x) (((x) & 0xffff) << 16)
#define DC_WIN_DV_CONTROL 0x70E #define DC_WIN_DV_CONTROL 0x70E
// The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). /*! The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). */
#define DC_WINBUF_START_ADDR 0x800 #define DC_WINBUF_START_ADDR 0x800
#define DC_WINBUF_ADDR_H_OFFSET 0x806 #define DC_WINBUF_ADDR_H_OFFSET 0x806
#define DC_WINBUF_ADDR_V_OFFSET 0x808 #define DC_WINBUF_ADDR_V_OFFSET 0x808

View file

@ -548,7 +548,6 @@ static const cfg_op_t cfg_display_framebuffer[32] = {
{DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, //768*2x768*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, //768*2x768*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements.
{DC_WIN_BUFFER_CONTROL, 0}, {DC_WIN_BUFFER_CONTROL, 0},
{DC_WINBUF_SURFACE_KIND, 0}, //Regular surface. {DC_WINBUF_SURFACE_KIND, 0}, //Regular surface.
//{DC_WINBUF_SURFACE_KIND, BLOCK_HEIGHT(4) | BLOCK}, //Regular surface.
{DC_WINBUF_START_ADDR, FB_ADDRESS}, //Framebuffer address. {DC_WINBUF_START_ADDR, FB_ADDRESS}, //Framebuffer address.
{DC_WINBUF_ADDR_H_OFFSET, 0}, //Linear: 0x383FFC, Block: 0x3813FC {DC_WINBUF_ADDR_H_OFFSET, 0}, //Linear: 0x383FFC, Block: 0x3813FC
{DC_WINBUF_ADDR_V_OFFSET, 1279}, //Linear: 1279, Block: 0 {DC_WINBUF_ADDR_V_OFFSET, 1279}, //Linear: 1279, Block: 0
@ -559,7 +558,6 @@ static const cfg_op_t cfg_display_framebuffer[32] = {
{DC_WIN_WIN_OPTIONS, 0}, {DC_WIN_WIN_OPTIONS, 0},
{DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE
{DC_WIN_WIN_OPTIONS, WIN_ENABLE | V_DIRECTION}, //Enable window AD. {DC_WIN_WIN_OPTIONS, WIN_ENABLE | V_DIRECTION}, //Enable window AD.
//{DC_WIN_WIN_OPTIONS, WIN_ENABLE | | SCAN_COLUMN | H_DIRECTION}, //Enable window AD. | SCAN_COLUMN | H_DIRECTION
{DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, //DISPLAY_CTRL_MODE: continuous display. {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, //DISPLAY_CTRL_MODE: continuous display.
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE}, //General update; window A update. {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE}, //General update; window A update.
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ} //General activation request; window A activation request. {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ} //General activation request; window A activation request.

View file

@ -131,12 +131,12 @@ void gfx_init_ctxt(u32 *fb, u32 width, u32 height, u32 stride)
void gfx_clear_grey(u8 color) void gfx_clear_grey(u8 color)
{ {
memset(gfx_ctxt.fb, color, 0x3C0000); memset(gfx_ctxt.fb, color, gfx_ctxt.width * gfx_ctxt.height * 4);
} }
void gfx_clear_color(u32 color) void gfx_clear_color(u32 color)
{ {
for (u32 i = 0; i < gfx_ctxt.height * gfx_ctxt.stride; i++) for (u32 i = 0; i < gfx_ctxt.width * gfx_ctxt.height; i++)
gfx_ctxt.fb[i] = color; gfx_ctxt.fb[i] = color;
} }

View file

@ -1,4 +1,5 @@
#pragma once #ifndef _LOGOS_GUI_H_
#define _LOGOS_GUI_H_
#include "../libs/lv_conf.h" #include "../libs/lv_conf.h"
#include "../libs/lvgl/lv_draw/lv_draw_img.h" #include "../libs/lvgl/lv_draw/lv_draw_img.h"
@ -27,3 +28,5 @@ lv_img_dsc_t ctcaer_logo = {
}; };
#endif #endif
#endif

View file

@ -127,7 +127,7 @@ void mc_disable_ahb_redirect()
void mc_enable() void mc_enable()
{ {
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF) | 0x40000000; CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF) | 0x40000000;
// Enable MIPI CAL clock. // Enable EMC clock.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & 0xFDFFFFFF) | 0x2000000; CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & 0xFDFFFFFF) | 0x2000000;
// Enable MC clock. // Enable MC clock.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & 0xFFFFFFFE) | 1; CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & 0xFFFFFFFE) | 1;

View file

@ -77,6 +77,7 @@ void minerva_change_freq(minerva_freq_t freq)
{ {
if (!minerva_cfg) if (!minerva_cfg)
return; return;
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg; mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
if (minerva_cfg && (mtc_cfg->rate_from != freq)) if (minerva_cfg && (mtc_cfg->rate_from != freq))
{ {
@ -90,6 +91,7 @@ void minerva_periodic_training()
{ {
if (!minerva_cfg) if (!minerva_cfg)
return; return;
mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg; mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
if (minerva_cfg && mtc_cfg->rate_from == FREQ_1600) if (minerva_cfg && mtc_cfg->rate_from == FREQ_1600)
{ {

View file

@ -59,6 +59,7 @@ u8 *Kc_MENU_LOGO;
#endif //MENU_LOGO_ENABLE #endif //MENU_LOGO_ENABLE
hekate_config h_cfg; hekate_config h_cfg;
const volatile ipl_ver_meta_t __attribute__((section ("._ipl_version"))) ipl_ver = { const volatile ipl_ver_meta_t __attribute__((section ("._ipl_version"))) ipl_ver = {
.magic = BL_MAGIC, .magic = BL_MAGIC,
.version = (BL_VER_MJ + '0') | ((BL_VER_MN + '0') << 8) | ((BL_VER_HF + '0') << 16), .version = (BL_VER_MJ + '0') | ((BL_VER_MN + '0') << 8) | ((BL_VER_HF + '0') << 16),
@ -168,6 +169,9 @@ int sd_save_to_file(void *buf, u32 size, const char *filename)
return 0; return 0;
} }
#pragma GCC push_options
#pragma GCC target ("thumb")
void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage) void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage)
{ {
sdmmc_storage_t storage2; sdmmc_storage_t storage2;
@ -307,14 +311,13 @@ out:
void load_saved_configuration() void load_saved_configuration()
{ {
LIST_INIT(ini_sections); LIST_INIT(ini_sections);
LIST_INIT(ini_list_sections);
if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false)) if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
{ {
// Load configuration. // Load configuration.
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link) LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
{ {
// Skip other ini entries for autoboot. // Skip other ini entries.
if (ini_sec->type == INI_CHOICE) if (ini_sec->type == INI_CHOICE)
{ {
if (!strcmp(ini_sec->name, "config")) if (!strcmp(ini_sec->name, "config"))
@ -430,3 +433,5 @@ void ipl_main()
while (true) while (true)
bpmp_halt(); bpmp_halt();
} }
#pragma GCC pop_options

View file

@ -20,6 +20,9 @@
#include "../soc/i2c.h" #include "../soc/i2c.h"
#include "../utils/util.h" #include "../utils/util.h"
#pragma GCC push_options
#pragma GCC target ("thumb")
int bq24193_get_property(enum BQ24193_reg_prop prop, int *value) int bq24193_get_property(enum BQ24193_reg_prop prop, int *value)
{ {
u8 data; u8 data;
@ -160,3 +163,5 @@ void bq24193_fake_battery_removal()
value |= BQ24193_MISC_BATFET_DI_MASK; value |= BQ24193_MISC_BATFET_DI_MASK;
i2c_send_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_Misc, value); i2c_send_byte(I2C_1, BQ24193_I2C_ADDR, BQ24193_Misc, value);
} }
#pragma GCC pop_options

View file

@ -43,6 +43,9 @@
#define MAX17050_VMAX_TOLERANCE 50 /* 50 mV */ #define MAX17050_VMAX_TOLERANCE 50 /* 50 mV */
#pragma GCC push_options
#pragma GCC target ("thumb")
int max17050_get_property(enum MAX17050_reg reg, int *value) int max17050_get_property(enum MAX17050_reg reg, int *value)
{ {
u16 data; u16 data;
@ -264,3 +267,5 @@ int max17050_fix_configuration()
return 0; return 0;
} }
#pragma GCC pop_options

View file

@ -52,7 +52,7 @@ void max77620_rtc_get_time(rtc_time_t *time)
} }
// Get date. // Get date.
time->date = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_DATE_REG) & 0x1f; time->day = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_DATE_REG) & 0x1f;
time->month = (i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_MONTH_REG) & 0xF) - 1; time->month = (i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_MONTH_REG) & 0xF) - 1;
time->year = (i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_YEAR_REG) & 0x7F) + 2000; time->year = (i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_YEAR_REG) & 0x7F) + 2000;
} }

View file

@ -64,7 +64,7 @@ typedef struct _rtc_time_t {
u8 sec; u8 sec;
u8 min; u8 min;
u8 hour; u8 hour;
u8 date; u8 day;
u8 month; u8 month;
u16 year; u16 year;
} rtc_time_t; } rtc_time_t;

View file

@ -152,7 +152,7 @@ void bpmp_mmu_disable()
// Clean and invalidate cache. // Clean and invalidate cache.
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY); bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY);
// Enable cache. // Disable cache.
BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) = 0; BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) = 0;
// HW bug. Invalidate cache again. // HW bug. Invalidate cache again.

View file

@ -369,7 +369,6 @@ static void _clock_sdmmc_clear_enable(u32 id)
static u32 _clock_sdmmc_table[8] = { 0 }; static u32 _clock_sdmmc_table[8] = { 0 };
#define PLLP_OUT0 0x0 #define PLLP_OUT0 0x0
static int _clock_sdmmc_config_clock_source_inner(u32 *pout, u32 id, u32 val) static int _clock_sdmmc_config_clock_source_inner(u32 *pout, u32 id, u32 val)
{ {
u32 divisor = 0; u32 divisor = 0;

View file

@ -123,7 +123,7 @@
#define CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP 0x620 #define CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP 0x620
#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C6 0x65C #define CLK_RST_CONTROLLER_CLK_SOURCE_I2C6 0x65C
#define CLK_RST_CONTROLLER_CLK_SOURCE_EMC_DLL 0x664 #define CLK_RST_CONTROLLER_CLK_SOURCE_EMC_DLL 0x664
#define CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIP_CAL 0x66C #define CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL 0x66C
#define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM 0x694 #define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM 0x694
#define CLK_RST_CONTROLLER_CLK_SOURCE_NVENC 0x6A0 #define CLK_RST_CONTROLLER_CLK_SOURCE_NVENC 0x6A0
#define CLK_RST_CONTROLLER_SE_SUPER_CLK_DIVIDER 0x704 #define CLK_RST_CONTROLLER_SE_SUPER_CLK_DIVIDER 0x704

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (C) 2018 CTCaer * Copyright (C) 2018-2019 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,
@ -19,7 +19,6 @@
#include "sdmmc.h" #include "sdmmc.h"
#include "mmc.h" #include "mmc.h"
#include "sd.h" #include "sd.h"
#include "../config/config.h"
#include "../gfx/gfx.h" #include "../gfx/gfx.h"
#include "../mem/heap.h" #include "../mem/heap.h"
#include "../utils/util.h" #include "../utils/util.h"
@ -27,8 +26,6 @@
//#define DPRINTF(...) gfx_printf(__VA_ARGS__) //#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DPRINTF(...) #define DPRINTF(...)
extern hekate_config h_cfg;
#pragma GCC push_options #pragma GCC push_options
#pragma GCC target ("thumb") #pragma GCC target ("thumb")
@ -75,6 +72,7 @@ static int _sdmmc_storage_execute_cmd_type1_ex(sdmmc_storage_t *storage, u32 *re
if (_sdmmc_storage_check_result(*resp)) if (_sdmmc_storage_check_result(*resp))
if (expected_state == 0x10 || R1_CURRENT_STATE(*resp) == expected_state) if (expected_state == 0x10 || R1_CURRENT_STATE(*resp) == expected_state)
return 1; return 1;
return 0; return 0;
} }
@ -88,6 +86,7 @@ static int _sdmmc_storage_go_idle_state(sdmmc_storage_t *storage)
{ {
sdmmc_cmd_t cmd; sdmmc_cmd_t cmd;
sdmmc_init_cmd(&cmd, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0); sdmmc_init_cmd(&cmd, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0);
return sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0); return sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0);
} }
@ -97,7 +96,9 @@ static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage, void *buf)
sdmmc_init_cmd(&cmd, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0); sdmmc_init_cmd(&cmd, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, 0, 0))
return 0; return 0;
sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2); sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2);
return 1; return 1;
} }
@ -112,7 +113,9 @@ static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage, void *buf)
sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0); sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0))
return 0; return 0;
sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2); sdmmc_get_rsp(storage->sdmmc, buf, 0x10, SDMMC_RSP_TYPE_2);
return 1; return 1;
} }
@ -150,8 +153,10 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
u32 tmp = 0; u32 tmp = 0;
sdmmc_stop_transmission(storage->sdmmc, &tmp); sdmmc_stop_transmission(storage->sdmmc, &tmp);
_sdmmc_storage_get_status(storage, &tmp, 0); _sdmmc_storage_get_status(storage, &tmp, 0);
return 0; return 0;
} }
return 1; return 1;
} }
@ -159,7 +164,9 @@ int sdmmc_storage_end(sdmmc_storage_t *storage)
{ {
if (!_sdmmc_storage_go_idle_state(storage)) if (!_sdmmc_storage_go_idle_state(storage))
return 0; return 0;
sdmmc_end(storage->sdmmc); sdmmc_end(storage->sdmmc);
return 1; return 1;
} }
@ -181,14 +188,16 @@ static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 nu
msleep(100); msleep(100);
} while (retries); } while (retries);
return 0; return 0;
out:; out:;
DPRINTF("readwrite: %08X\n", blkcnt); DPRINTF("readwrite: %08X\n", blkcnt);
sector += blkcnt; sector += blkcnt;
num_sectors -= blkcnt; num_sectors -= blkcnt;
bbuf += 512 * blkcnt; bbuf += 512 * blkcnt;
} }
return 1; return 1;
} }
@ -239,14 +248,17 @@ static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power)
u32 cond = 0; u32 cond = 0;
if (!_mmc_storage_get_op_cond_inner(storage, &cond, power)) if (!_mmc_storage_get_op_cond_inner(storage, &cond, power))
break; break;
if (cond & MMC_CARD_BUSY) if (cond & MMC_CARD_BUSY)
{ {
if (cond & 0x40000000) if (cond & 0x40000000)
storage->has_sector_access = 1; storage->has_sector_access = 1;
return 1; return 1;
} }
if (get_tmr_ms() > timeout) if (get_tmr_ms() > timeout)
break; break;
usleep(1000); usleep(1000);
} }
@ -376,6 +388,7 @@ static int _mmc_storage_switch_buswidth(sdmmc_storage_t *storage, u32 bus_width)
if (_sdmmc_storage_check_status(storage)) if (_sdmmc_storage_check_status(storage))
{ {
sdmmc_set_bus_width(storage->sdmmc, bus_width); sdmmc_set_bus_width(storage->sdmmc, bus_width);
return 1; return 1;
} }
@ -386,14 +399,19 @@ static int _mmc_storage_enable_HS(sdmmc_storage_t *storage, int check)
{ {
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS))) if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS)))
return 0; return 0;
if (check && !_sdmmc_storage_check_status(storage)) if (check && !_sdmmc_storage_check_status(storage))
return 0; return 0;
if (!sdmmc_setup_clock(storage->sdmmc, 2)) if (!sdmmc_setup_clock(storage->sdmmc, 2))
return 0; return 0;
DPRINTF("[MMC] switched to HS\n");
DPRINTF("[MMC] switched to HS\n");
storage->csd.busspeed = 52; storage->csd.busspeed = 52;
if (check || _sdmmc_storage_check_status(storage)) if (check || _sdmmc_storage_check_status(storage))
return 1; return 1;
return 0; return 0;
} }
@ -401,12 +419,16 @@ static int _mmc_storage_enable_HS200(sdmmc_storage_t *storage)
{ {
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS200))) if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS200)))
return 0; return 0;
if (!sdmmc_setup_clock(storage->sdmmc, 3)) if (!sdmmc_setup_clock(storage->sdmmc, 3))
return 0; return 0;
if (!sdmmc_config_tuning(storage->sdmmc, 3, MMC_SEND_TUNING_BLOCK_HS200)) if (!sdmmc_config_tuning(storage->sdmmc, 3, 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);
} }
@ -414,17 +436,24 @@ static int _mmc_storage_enable_HS400(sdmmc_storage_t *storage)
{ {
if (!_mmc_storage_enable_HS200(storage)) if (!_mmc_storage_enable_HS200(storage))
return 0; return 0;
sdmmc_get_venclkctl(storage->sdmmc); sdmmc_get_venclkctl(storage->sdmmc);
if (!_mmc_storage_enable_HS(storage, 0)) if (!_mmc_storage_enable_HS(storage, 0))
return 0; return 0;
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_BUS_WIDTH, EXT_CSD_DDR_BUS_WIDTH_8))) if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_BUS_WIDTH, EXT_CSD_DDR_BUS_WIDTH_8)))
return 0; return 0;
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS400))) if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS400)))
return 0; return 0;
if (!sdmmc_setup_clock(storage->sdmmc, 4)) if (!sdmmc_setup_clock(storage->sdmmc, 4))
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);
} }
@ -436,8 +465,7 @@ static int _mmc_storage_enable_highspeed(sdmmc_storage_t *storage, u32 card_type
goto out; goto out;
if (sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_8 && if (sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_8 &&
card_type & EXT_CSD_CARD_TYPE_HS400_1_8V && card_type & EXT_CSD_CARD_TYPE_HS400_1_8V && type == 4)
type == 4)
return _mmc_storage_enable_HS400(storage); return _mmc_storage_enable_HS400(storage);
if (sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_8 || if (sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_8 ||
@ -449,6 +477,7 @@ static int _mmc_storage_enable_highspeed(sdmmc_storage_t *storage, u32 card_type
out:; out:;
if (card_type & EXT_CSD_CARD_TYPE_HS_52) if (card_type & EXT_CSD_CARD_TYPE_HS_52)
return _mmc_storage_enable_HS(storage, 1); return _mmc_storage_enable_HS(storage, 1);
return 1; return 1;
} }
@ -456,6 +485,7 @@ static int _mmc_storage_enable_bkops(sdmmc_storage_t *storage)
{ {
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_BKOPS_LEVEL_2))) if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_BKOPS_LEVEL_2)))
return 0; return 0;
return _sdmmc_storage_check_status(storage); return _sdmmc_storage_check_status(storage);
} }
@ -467,42 +497,42 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
if (!sdmmc_init(sdmmc, id, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, 0, 0)) if (!sdmmc_init(sdmmc, id, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, 0, 0))
return 0; return 0;
DPRINTF("[MMC] after init\n"); DPRINTF("[MMC] after init\n");
usleep(1000 + (74000 + sdmmc->divisor - 1) / sdmmc->divisor); usleep(1000 + (74000 + sdmmc->divisor - 1) / sdmmc->divisor);
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, storage->raw_cid)) if (!_sdmmc_storage_get_cid(storage, storage->raw_cid))
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, storage->raw_csd)) if (!_sdmmc_storage_get_csd(storage, storage->raw_csd))
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, 1)) if (!sdmmc_setup_clock(storage->sdmmc, 1))
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");
u32 *csd = (u32 *)storage->raw_csd; u32 *csd = (u32 *)storage->raw_csd;
//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.
@ -514,7 +544,7 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
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");
u8 *ext_csd = (u8 *)malloc(512); u8 *ext_csd = (u8 *)malloc(512);
if (!_mmc_storage_get_ext_csd(storage, ext_csd)) if (!_mmc_storage_get_ext_csd(storage, ext_csd))
@ -523,7 +553,7 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
return 0; return 0;
} }
free(ext_csd); free(ext_csd);
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
//gfx_hexdump(0, ext_csd, 512); //gfx_hexdump(0, ext_csd, 512);
@ -533,16 +563,16 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
if (storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_BKOPS_LEVEL_2) && 0) if (storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_BKOPS_LEVEL_2) && 0)
{ {
_mmc_storage_enable_bkops(storage); _mmc_storage_enable_bkops(storage);
DPRINTF("[MMC] BKOPS enabled\n"); DPRINTF("[MMC] BKOPS enabled\n");
} }
else else
{ {
DPRINTF("[MMC] BKOPS disabled\n"); DPRINTF("[MMC] BKOPS disabled\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] succesfully switched to highspeed mode\n"); DPRINTF("[MMC] succesfully switched to highspeed mode\n");
sdmmc_sd_clock_ctrl(storage->sdmmc, 1); sdmmc_sd_clock_ctrl(storage->sdmmc, 1);
@ -553,8 +583,10 @@ int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition)
{ {
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_PART_CONFIG, partition))) if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_PART_CONFIG, partition)))
return 0; return 0;
if (!_sdmmc_storage_check_status(storage)) if (!_sdmmc_storage_check_status(storage))
return 0; return 0;
storage->partition = partition; storage->partition = partition;
return 1; return 1;
} }
@ -568,6 +600,7 @@ static int _sd_storage_execute_app_cmd(sdmmc_storage_t *storage, u32 expected_st
u32 tmp; u32 tmp;
if (!_sdmmc_storage_execute_cmd_type1_ex(storage, &tmp, MMC_APP_CMD, storage->rca << 16, 0, expected_state, mask)) if (!_sdmmc_storage_execute_cmd_type1_ex(storage, &tmp, MMC_APP_CMD, storage->rca << 16, 0, expected_state, mask))
return 0; return 0;
return sdmmc_execute_cmd(storage->sdmmc, cmd, req, blkcnt_out); return sdmmc_execute_cmd(storage->sdmmc, cmd, req, blkcnt_out);
} }
@ -575,6 +608,7 @@ static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp
{ {
if (!_sdmmc_storage_execute_cmd_type1(storage, MMC_APP_CMD, storage->rca << 16, 0, R1_STATE_TRAN)) if (!_sdmmc_storage_execute_cmd_type1(storage, MMC_APP_CMD, storage->rca << 16, 0, R1_STATE_TRAN))
return 0; return 0;
return _sdmmc_storage_execute_cmd_type1_ex(storage, resp, cmd, arg, check_busy, expected_state, 0); return _sdmmc_storage_execute_cmd_type1_ex(storage, resp, cmd, arg, check_busy, expected_state, 0);
} }
@ -606,6 +640,7 @@ static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int
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, 0x10, is_version_1 ? 0x400000 : 0, &cmdbuf, 0, 0)) if (!_sd_storage_execute_app_cmd(storage, 0x10, is_version_1 ? 0x400000 : 0, &cmdbuf, 0, 0))
return 0; return 0;
return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3); return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3);
} }
@ -633,7 +668,7 @@ static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, i
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");
} }
} }
@ -787,17 +822,17 @@ void _sd_storage_set_current_limit(sdmmc_storage_t *storage, u8 *buf)
switch (pwr) switch (pwr)
{ {
case SD_SET_CURRENT_LIMIT_800: case SD_SET_CURRENT_LIMIT_800:
DPRINTF("[SD] Power limit raised to 800mA\n"); DPRINTF("[SD] Power limit raised to 800mA\n");
break; break;
case SD_SET_CURRENT_LIMIT_600: case SD_SET_CURRENT_LIMIT_600:
DPRINTF("[SD] Power limit raised to 600mA\n"); DPRINTF("[SD] Power limit raised to 600mA\n");
break; break;
case SD_SET_CURRENT_LIMIT_400: case SD_SET_CURRENT_LIMIT_400:
DPRINTF("[SD] Power limit raised to 800mA\n"); DPRINTF("[SD] Power limit raised to 800mA\n");
break; break;
default: default:
case SD_SET_CURRENT_LIMIT_200: case SD_SET_CURRENT_LIMIT_200:
DPRINTF("[SD] Power limit defaulted to 200mA\n"); DPRINTF("[SD] Power limit defaulted to 200mA\n");
break; break;
} }
} }
@ -806,10 +841,12 @@ int _sd_storage_enable_highspeed(sdmmc_storage_t *storage, u32 hs_type, u8 *buf)
{ {
if (!_sd_storage_switch(storage, buf, SD_SWITCH_CHECK, 0, hs_type)) if (!_sd_storage_switch(storage, buf, SD_SWITCH_CHECK, 0, hs_type))
return 0; return 0;
DPRINTF("[SD] SD supports switch to (U)HS check\n");
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] SD supports selected (U)HS mode\n");
if ((((u16)buf[0] << 8) | buf[1]) < 0x320) if ((((u16)buf[0] << 8) | buf[1]) < 0x320)
{ {
@ -844,7 +881,7 @@ int _sd_storage_enable_highspeed_low_volt(sdmmc_storage_t *storage, u32 type, u8
{ {
type = 11; type = 11;
hs_type = UHS_SDR104_BUS_SPEED; hs_type = UHS_SDR104_BUS_SPEED;
DPRINTF("[SD] Bus speed set to SDR104\n"); DPRINTF("[SD] Bus speed set to SDR104\n");
storage->csd.busspeed = 104; storage->csd.busspeed = 104;
break; break;
} }
@ -853,7 +890,7 @@ int _sd_storage_enable_highspeed_low_volt(sdmmc_storage_t *storage, u32 type, u8
{ {
type = 10; type = 10;
hs_type = UHS_SDR50_BUS_SPEED; hs_type = UHS_SDR50_BUS_SPEED;
DPRINTF("[SD] Bus speed set to SDR50\n"); DPRINTF("[SD] Bus speed set to SDR50\n");
storage->csd.busspeed = 50; storage->csd.busspeed = 50;
break; break;
} }
@ -862,7 +899,7 @@ int _sd_storage_enable_highspeed_low_volt(sdmmc_storage_t *storage, u32 type, u8
return 0; return 0;
type = 8; type = 8;
hs_type = UHS_SDR12_BUS_SPEED; hs_type = UHS_SDR12_BUS_SPEED;
DPRINTF("[SD] Bus speed set to SDR12\n"); DPRINTF("[SD] Bus speed set to SDR12\n");
storage->csd.busspeed = 12; storage->csd.busspeed = 12;
break; break;
default: default:
@ -872,10 +909,13 @@ int _sd_storage_enable_highspeed_low_volt(sdmmc_storage_t *storage, u32 type, u8
if (!_sd_storage_enable_highspeed(storage, hs_type, buf)) if (!_sd_storage_enable_highspeed(storage, hs_type, buf))
return 0; return 0;
DPRINTF("[SD] 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] setup clock\n");
if (!sdmmc_config_tuning(storage->sdmmc, type, MMC_SEND_TUNING_BLOCK)) if (!sdmmc_config_tuning(storage->sdmmc, type, MMC_SEND_TUNING_BLOCK))
return 0; return 0;
DPRINTF("[SD] config tuning\n");
return _sdmmc_storage_check_status(storage); return _sdmmc_storage_check_status(storage);
} }
@ -889,8 +929,10 @@ int _sd_storage_enable_highspeed_high_volt(sdmmc_storage_t *storage, u8 *buf)
if (!_sd_storage_enable_highspeed(storage, 1, buf)) if (!_sd_storage_enable_highspeed(storage, 1, buf))
return 0; return 0;
if (!_sdmmc_storage_check_status(storage)) if (!_sdmmc_storage_check_status(storage))
return 0; return 0;
return sdmmc_setup_clock(storage->sdmmc, 7); return sdmmc_setup_clock(storage->sdmmc, 7);
} }
@ -953,7 +995,7 @@ static 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: Card lacks mandatory SD Status function\n"); DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n");
return 0; return 0;
} }
@ -1017,7 +1059,7 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
void sdmmc_storage_init_wait_sd() void sdmmc_storage_init_wait_sd()
{ {
u32 sd_poweroff_time = (u32)get_tmr_ms() - h_cfg.sd_timeoff; u32 sd_poweroff_time = (u32)get_tmr_ms() - sd_power_cycle_time_start;
if (sd_poweroff_time < 100) if (sd_poweroff_time < 100)
msleep(100 - sd_poweroff_time); msleep(100 - sd_poweroff_time);
} }
@ -1034,35 +1076,35 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
if (!sdmmc_init(sdmmc, id, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, 5, 0)) if (!sdmmc_init(sdmmc, id, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, 5, 0))
return 0; return 0;
DPRINTF("[SD] after init\n"); DPRINTF("[SD] after init\n");
usleep(1000 + (74000 + sdmmc->divisor - 1) / sdmmc->divisor); usleep(1000 + (74000 + sdmmc->divisor - 1) / sdmmc->divisor);
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");
is_version_1 = _sd_storage_send_if_cond(storage); is_version_1 = _sd_storage_send_if_cond(storage);
if (is_version_1 == 2) if (is_version_1 == 2)
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_version_1, bus_width == SDMMC_BUS_WIDTH_4 && type == 11)) if (!_sd_storage_get_op_cond(storage, is_version_1, bus_width == SDMMC_BUS_WIDTH_4 && type == 11))
return 0; return 0;
DPRINTF("[SD] got op cond\n"); DPRINTF("[SD] got op cond\n");
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid)) if (!_sdmmc_storage_get_cid(storage, storage->raw_cid))
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, storage->raw_csd)) if (!_sdmmc_storage_get_csd(storage, storage->raw_csd))
return 0; return 0;
DPRINTF("[SD] got csd\n"); DPRINTF("[SD] got csd\n");
//Parse CSD. //Parse CSD.
_sd_storage_parse_csd(storage); _sd_storage_parse_csd(storage);
@ -1075,7 +1117,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
storage->sec_cnt = storage->csd.c_size << 10; storage->sec_cnt = storage->csd.c_size << 10;
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;
} }
@ -1083,21 +1125,21 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
{ {
if (!sdmmc_setup_clock(storage->sdmmc, 6)) if (!sdmmc_setup_clock(storage->sdmmc, 6))
return 0; return 0;
DPRINTF("[SD] after setup clock\n"); DPRINTF("[SD] after setup 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");
u32 tmp = 0; u32 tmp = 0;
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");
u8 *buf = (u8 *)malloc(512); u8 *buf = (u8 *)malloc(512);
if (!_sd_storage_get_scr(storage, buf)) if (!_sd_storage_get_scr(storage, buf))
@ -1107,7 +1149,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
} }
//gfx_hexdump(0, storage->raw_scr, 8); //gfx_hexdump(0, storage->raw_scr, 8);
DPRINTF("[SD] got scr\n"); DPRINTF("[SD] got scr\n");
// Check if card supports a wider bus and if it's not SD Version 1.X // Check if card supports a wider bus and if it's not SD Version 1.X
if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & 4) && (storage->scr.sda_vsn & 0xF)) if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & 4) && (storage->scr.sda_vsn & 0xF))
@ -1118,11 +1160,11 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
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
{ {
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)
@ -1132,7 +1174,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
free(buf); free(buf);
return 0; return 0;
} }
DPRINTF("[SD] enabled highspeed (low voltage)\n"); DPRINTF("[SD] enabled UHS\n");
} }
else if (type != 6 && (storage->scr.sda_vsn & 0xF) != 0) else if (type != 6 && (storage->scr.sda_vsn & 0xF) != 0)
{ {
@ -1141,7 +1183,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
free(buf); free(buf);
return 0; return 0;
} }
DPRINTF("[SD] enabled highspeed (high voltage)\n"); DPRINTF("[SD] enabled HS\n");
storage->csd.busspeed = 25; storage->csd.busspeed = 25;
} }
@ -1150,7 +1192,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
// 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");
} }
free(buf); free(buf);
@ -1195,13 +1237,13 @@ int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc)
if (!sdmmc_init(sdmmc, SDMMC_2, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_8, 14, 0)) if (!sdmmc_init(sdmmc, SDMMC_2, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_8, 14, 0))
return 0; return 0;
DPRINTF("[gc] after init\n"); DPRINTF("[gc] after init\n");
usleep(1000 + (10000 + sdmmc->divisor - 1) / sdmmc->divisor); usleep(1000 + (10000 + sdmmc->divisor - 1) / sdmmc->divisor);
if (!sdmmc_config_tuning(storage->sdmmc, 14, MMC_SEND_TUNING_BLOCK_HS200)) if (!sdmmc_config_tuning(storage->sdmmc, 14, MMC_SEND_TUNING_BLOCK_HS200))
return 0; return 0;
DPRINTF("[gc] after tuning\n"); DPRINTF("[gc] after tuning\n");
sdmmc_sd_clock_ctrl(sdmmc, 1); sdmmc_sd_clock_ctrl(sdmmc, 1);

View file

@ -21,6 +21,8 @@
#include "../utils/types.h" #include "../utils/types.h"
#include "sdmmc_driver.h" #include "sdmmc_driver.h"
u32 sd_power_cycle_time_start;
typedef struct _mmc_cid typedef struct _mmc_cid
{ {
u32 manfid; u32 manfid;

View file

@ -19,7 +19,6 @@
#include "mmc.h" #include "mmc.h"
#include "sdmmc.h" #include "sdmmc.h"
#include "../config/config.h"
#include "../gfx/gfx.h" #include "../gfx/gfx.h"
#include "../power/max7762x.h" #include "../power/max7762x.h"
#include "../soc/bpmp.h" #include "../soc/bpmp.h"
@ -33,8 +32,6 @@
//#define DPRINTF(...) gfx_printf(__VA_ARGS__) //#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DPRINTF(...) #define DPRINTF(...)
extern hekate_config h_cfg;
/*! SCMMC controller base addresses. */ /*! SCMMC controller base addresses. */
static const u32 _sdmmc_bases[4] = { static const u32 _sdmmc_bases[4] = {
0x700B0000, 0x700B0000,
@ -125,6 +122,7 @@ static int _sdmmc_config_ven_ceata_clk(sdmmc_t *sdmmc, u32 id)
{ {
if (!sdmmc->venclkctl_set) if (!sdmmc->venclkctl_set)
return 0; return 0;
tap_val = sdmmc->venclkctl_tap; tap_val = sdmmc->venclkctl_tap;
} }
else else
@ -235,7 +233,7 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180; sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180;
break; break;
case 4: case 4:
// Non standard // 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;
@ -513,13 +511,17 @@ static int _sdmmc_config_tuning_once(sdmmc_t *sdmmc, u32 cmd)
return 0; return 0;
_sdmmc_setup_read_small_block(sdmmc); _sdmmc_setup_read_small_block(sdmmc);
sdmmc->regs->norintstsen |= TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY; sdmmc->regs->norintstsen |= TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY;
sdmmc->regs->norintsts = sdmmc->regs->norintsts; sdmmc->regs->norintsts = sdmmc->regs->norintsts;
sdmmc->regs->clkcon &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE; sdmmc->regs->clkcon &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
_sdmmc_parse_cmd_48(sdmmc, cmd); _sdmmc_parse_cmd_48(sdmmc, cmd);
_sdmmc_get_clkcon(sdmmc); _sdmmc_get_clkcon(sdmmc);
usleep(1); usleep(1);
_sdmmc_reset(sdmmc); _sdmmc_reset(sdmmc);
sdmmc->regs->clkcon |= TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE; sdmmc->regs->clkcon |= TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
_sdmmc_get_clkcon(sdmmc); _sdmmc_get_clkcon(sdmmc);
@ -535,10 +537,13 @@ static int _sdmmc_config_tuning_once(sdmmc_t *sdmmc, u32 cmd)
return 1; return 1;
} }
} }
_sdmmc_reset(sdmmc); _sdmmc_reset(sdmmc);
sdmmc->regs->norintstsen &= 0xFFDF; sdmmc->regs->norintstsen &= 0xFFDF;
_sdmmc_get_clkcon(sdmmc); _sdmmc_get_clkcon(sdmmc);
usleep((1000 * 8 + sdmmc->divisor - 1) / sdmmc->divisor); usleep((1000 * 8 + sdmmc->divisor - 1) / sdmmc->divisor);
return 0; return 0;
} }
@ -565,8 +570,8 @@ int sdmmc_config_tuning(sdmmc_t *sdmmc, u32 type, u32 cmd)
return 0; return 0;
} }
sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFF1FFF) | flag; sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFF1FFF) | flag; // Tries.
sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFFE03F) | 0x40; sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFFE03F) | 0x40; // Multiplier.
sdmmc->regs->ventunctl0 |= 0x20000; sdmmc->regs->ventunctl0 |= 0x20000;
sdmmc->regs->hostctl2 |= SDHCI_CTRL_EXEC_TUNING; sdmmc->regs->hostctl2 |= SDHCI_CTRL_EXEC_TUNING;
@ -579,6 +584,7 @@ int sdmmc_config_tuning(sdmmc_t *sdmmc, u32 type, u32 cmd)
if (sdmmc->regs->hostctl2 & SDHCI_CTRL_TUNED_CLK) if (sdmmc->regs->hostctl2 & SDHCI_CTRL_TUNED_CLK)
return 1; return 1;
return 0; return 0;
} }
@ -748,11 +754,14 @@ static int _sdmmc_stop_transmission_inner(sdmmc_t *sdmmc, u32 *rsp)
return 0; return 0;
_sdmmc_enable_interrupts(sdmmc); _sdmmc_enable_interrupts(sdmmc);
cmd.cmd = MMC_STOP_TRANSMISSION; cmd.cmd = MMC_STOP_TRANSMISSION;
cmd.arg = 0; cmd.arg = 0;
cmd.rsp_type = SDMMC_RSP_TYPE_1; cmd.rsp_type = SDMMC_RSP_TYPE_1;
cmd.check_busy = 1; cmd.check_busy = 1;
_sdmmc_parse_cmdbuf(sdmmc, &cmd, false); _sdmmc_parse_cmdbuf(sdmmc, &cmd, false);
int res = _sdmmc_wait_request(sdmmc); int res = _sdmmc_wait_request(sdmmc);
_sdmmc_mask_interrupts(sdmmc); _sdmmc_mask_interrupts(sdmmc);
@ -760,6 +769,7 @@ static int _sdmmc_stop_transmission_inner(sdmmc_t *sdmmc, u32 *rsp)
return 0; return 0;
_sdmmc_cache_rsp(sdmmc, rsp, 4, SDMMC_RSP_TYPE_1); _sdmmc_cache_rsp(sdmmc, rsp, 4, SDMMC_RSP_TYPE_1);
return _sdmmc_wait_prnsts_type1(sdmmc); return _sdmmc_wait_prnsts_type1(sdmmc);
} }
@ -779,6 +789,7 @@ int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp)
int res = _sdmmc_stop_transmission_inner(sdmmc, rsp); int res = _sdmmc_stop_transmission_inner(sdmmc, rsp);
usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor); usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor);
if (should_disable_sd_clock) if (should_disable_sd_clock)
sdmmc->regs->clkcon &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE; sdmmc->regs->clkcon &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
@ -911,6 +922,7 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
{ {
if (blkcnt_out) if (blkcnt_out)
*blkcnt_out = blkcnt; *blkcnt_out = blkcnt;
if (req->is_auto_cmd12) if (req->is_auto_cmd12)
sdmmc->rsp3 = sdmmc->regs->rspreg3; sdmmc->rsp3 = sdmmc->regs->rspreg3;
} }
@ -930,6 +942,8 @@ static int _sdmmc_config_sdmmc1()
gpio_config(GPIO_PORT_Z, GPIO_PIN_1, GPIO_MODE_GPIO); gpio_config(GPIO_PORT_Z, GPIO_PIN_1, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_Z, GPIO_PIN_1, GPIO_OUTPUT_DISABLE); gpio_output_enable(GPIO_PORT_Z, GPIO_PIN_1, GPIO_OUTPUT_DISABLE);
usleep(100); usleep(100);
// Check if SD card is inserted.
if(!!gpio_read(GPIO_PORT_Z, GPIO_PIN_1)) if(!!gpio_read(GPIO_PORT_Z, GPIO_PIN_1))
return 0; return 0;
@ -943,7 +957,7 @@ static int _sdmmc_config_sdmmc1()
*/ */
// Configure SDMMC1 pinmux. // Configure SDMMC1 pinmux.
APB_MISC(APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL) = 1; APB_MISC(APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL) = 1; // Enable deep loopback for SDMMC1 CLK pad.
PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED; PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED;
PINMUX_AUX(PINMUX_AUX_SDMMC1_CMD) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP; PINMUX_AUX(PINMUX_AUX_SDMMC1_CMD) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP;
PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT3) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP; PINMUX_AUX(PINMUX_AUX_SDMMC1_DAT3) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_PULL_UP;
@ -1014,18 +1028,23 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int n
sdmmc->regs->sdmemcmppadctl = (sdmmc->regs->sdmemcmppadctl & 0xF) | 7; sdmmc->regs->sdmemcmppadctl = (sdmmc->regs->sdmemcmppadctl & 0xF) | 7;
if (!_sdmmc_autocal_config_offset(sdmmc, power)) if (!_sdmmc_autocal_config_offset(sdmmc, power))
return 0; return 0;
_sdmmc_autocal_execute(sdmmc, power); _sdmmc_autocal_execute(sdmmc, power);
if (_sdmmc_enable_internal_clock(sdmmc)) if (_sdmmc_enable_internal_clock(sdmmc))
{ {
sdmmc_set_bus_width(sdmmc, bus_width); sdmmc_set_bus_width(sdmmc, bus_width);
_sdmmc_set_voltage(sdmmc, power); _sdmmc_set_voltage(sdmmc, power);
if (sdmmc_setup_clock(sdmmc, type)) if (sdmmc_setup_clock(sdmmc, type))
{ {
sdmmc_sd_clock_ctrl(sdmmc, no_sd); sdmmc_sd_clock_ctrl(sdmmc, no_sd);
_sdmmc_sd_clock_enable(sdmmc); _sdmmc_sd_clock_enable(sdmmc);
_sdmmc_get_clkcon(sdmmc); _sdmmc_get_clkcon(sdmmc);
return 1; return 1;
} }
return 0; return 0;
} }
return 0; return 0;
@ -1044,8 +1063,8 @@ void sdmmc_end(sdmmc_t *sdmmc)
{ {
gpio_output_enable(GPIO_PORT_E, GPIO_PIN_4, GPIO_OUTPUT_DISABLE); gpio_output_enable(GPIO_PORT_E, GPIO_PIN_4, GPIO_OUTPUT_DISABLE);
max77620_regulator_enable(REGULATOR_LDO2, 0); max77620_regulator_enable(REGULATOR_LDO2, 0);
h_cfg.sd_timeoff = get_tmr_ms(); // Some sandisc U1 cards need 100ms for a power cycle. sd_power_cycle_time_start = get_tmr_ms(); // Some sandisc U1 cards need 100ms for a power cycle.
msleep(1); // To power cycle, min 1ms without power is needed. usleep(1000); // To power cycle, min 1ms without power is needed.
} }
_sdmmc_get_clkcon(sdmmc); _sdmmc_get_clkcon(sdmmc);
@ -1082,6 +1101,7 @@ int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *b
int res = _sdmmc_execute_cmd_inner(sdmmc, cmd, req, blkcnt_out); int res = _sdmmc_execute_cmd_inner(sdmmc, cmd, req, blkcnt_out);
usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor); usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor);
if (should_disable_sd_clock) if (should_disable_sd_clock)
sdmmc->regs->clkcon &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE; sdmmc->regs->clkcon &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
@ -1119,7 +1139,7 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc)
{ {
sdmmc->regs->clkcon |= TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE; sdmmc->regs->clkcon |= TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE;
_sdmmc_get_clkcon(sdmmc); _sdmmc_get_clkcon(sdmmc);
msleep(1); usleep(1000);
if ((sdmmc->regs->prnsts & 0xF00000) == 0xF00000) if ((sdmmc->regs->prnsts & 0xF00000) == 0xF00000)
return 1; return 1;
} }

View file

@ -63,13 +63,9 @@ void set_fan_duty(u32 duty)
// If disabled send a 0 duty. // If disabled send a 0 duty.
if (inv_duty == 236) if (inv_duty == 236)
inv_duty = 255; PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (1 << 24);
else // Set PWM duty.
// Set PWM duty. PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (inv_duty << 16);
if (inv_duty == 255)
PWM(PWM_CONTROLLER_PWM_CSR_1) = 0;
else
PWM(PWM_CONTROLLER_PWM_CSR_1) = (1 << 31) | (inv_duty << 16);
} }
void get_fan_speed(u32 *duty, u32 *rpm) void get_fan_speed(u32 *duty, u32 *rpm)