mirror of
https://github.com/CTCaer/hekate
synced 2024-12-22 19:31:12 +00:00
Refactoring and comment adding
This commit is contained in:
parent
c5b64a2b58
commit
a8d529cf6a
47 changed files with 477 additions and 300 deletions
|
@ -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()
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -315,19 +315,19 @@ static const pkg2_kernel_id_t _pkg2_kernel_ids[] =
|
||||||
|
|
||||||
enum kip_offset_section
|
enum kip_offset_section
|
||||||
{
|
{
|
||||||
KIP_TEXT = 0,
|
KIP_TEXT = 0,
|
||||||
KIP_RODATA = 1,
|
KIP_RODATA = 1,
|
||||||
KIP_DATA = 2,
|
KIP_DATA = 2,
|
||||||
KIP_BSS = 3,
|
KIP_BSS = 3,
|
||||||
KIP_UNKSEC1 = 4,
|
KIP_UNKSEC1 = 4,
|
||||||
KIP_UNKSEC2 = 5
|
KIP_UNKSEC2 = 5
|
||||||
};
|
};
|
||||||
|
|
||||||
#define KIP_PATCH_SECTION_SHIFT (29)
|
#define KIP_PATCH_SECTION_SHIFT (29)
|
||||||
#define KIP_PATCH_SECTION_MASK (7 << KIP_PATCH_SECTION_SHIFT)
|
#define KIP_PATCH_SECTION_MASK (7 << KIP_PATCH_SECTION_SHIFT)
|
||||||
#define KIP_PATCH_OFFSET_MASK (~KIP_PATCH_SECTION_MASK)
|
#define KIP_PATCH_OFFSET_MASK (~KIP_PATCH_SECTION_MASK)
|
||||||
#define GET_KIP_PATCH_SECTION(x) ((x >> KIP_PATCH_SECTION_SHIFT) & 7)
|
#define GET_KIP_PATCH_SECTION(x) ((x >> KIP_PATCH_SECTION_SHIFT) & 7)
|
||||||
#define GET_KIP_PATCH_OFFSET(x) (x & KIP_PATCH_OFFSET_MASK)
|
#define GET_KIP_PATCH_OFFSET(x) (x & KIP_PATCH_OFFSET_MASK)
|
||||||
#define KPS(x) ((u32)(x) << KIP_PATCH_SECTION_SHIFT)
|
#define KPS(x) ((u32)(x) << KIP_PATCH_SECTION_SHIFT)
|
||||||
|
|
||||||
static kip1_patch_t _fs_emummc[] =
|
static kip1_patch_t _fs_emummc[] =
|
||||||
|
|
|
@ -140,7 +140,7 @@ typedef struct _kip1_id_t
|
||||||
} kip1_id_t;
|
} kip1_id_t;
|
||||||
|
|
||||||
void pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2);
|
void pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2);
|
||||||
int pkg2_has_kip(link_t *info, u64 tid);
|
int pkg2_has_kip(link_t *info, u64 tid);
|
||||||
void pkg2_replace_kip(link_t *info, u64 tid, pkg2_kip1_t *kip1);
|
void pkg2_replace_kip(link_t *info, u64 tid, pkg2_kip1_t *kip1);
|
||||||
void pkg2_add_kip(link_t *info, pkg2_kip1_t *kip1);
|
void pkg2_add_kip(link_t *info, pkg2_kip1_t *kip1);
|
||||||
void pkg2_merge_kip(link_t *info, pkg2_kip1_t *kip1);
|
void pkg2_merge_kip(link_t *info, pkg2_kip1_t *kip1);
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
@ -9,21 +10,23 @@
|
||||||
#ifdef HEKATE_LOGO
|
#ifdef HEKATE_LOGO
|
||||||
|
|
||||||
lv_img_dsc_t hekate_logo = {
|
lv_img_dsc_t hekate_logo = {
|
||||||
.header.always_zero = 0,
|
.header.always_zero = 0,
|
||||||
.header.w = 193,
|
.header.w = 193,
|
||||||
.header.h = 76,
|
.header.h = 76,
|
||||||
.data_size = 14668 * LV_IMG_PX_SIZE_ALPHA_BYTE,
|
.data_size = 14668 * LV_IMG_PX_SIZE_ALPHA_BYTE,
|
||||||
.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA,
|
.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA,
|
||||||
.data = (const uint8_t *)(NYX_RES_ADDR + 0x1D900),
|
.data = (const uint8_t *)(NYX_RES_ADDR + 0x1D900),
|
||||||
};
|
};
|
||||||
|
|
||||||
lv_img_dsc_t ctcaer_logo = {
|
lv_img_dsc_t ctcaer_logo = {
|
||||||
.header.always_zero = 0,
|
.header.always_zero = 0,
|
||||||
.header.w = 147,
|
.header.w = 147,
|
||||||
.header.h = 76,
|
.header.h = 76,
|
||||||
.data_size = 11172 * LV_IMG_PX_SIZE_ALPHA_BYTE,
|
.data_size = 11172 * LV_IMG_PX_SIZE_ALPHA_BYTE,
|
||||||
.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA,
|
.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA,
|
||||||
.data = (const uint8_t *)(NYX_RES_ADDR + 0x2BF00),
|
.data = (const uint8_t *)(NYX_RES_ADDR + 0x2BF00),
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -24,12 +24,12 @@
|
||||||
|
|
||||||
/* Memory size which will be used by the library
|
/* Memory size which will be used by the library
|
||||||
* to store the graphical objects and other data */
|
* to store the graphical objects and other data */
|
||||||
#define LV_MEM_CUSTOM 0 /*1: use custom malloc/free, 0: use the built-in lv_mem_alloc/lv_mem_free*/
|
#define LV_MEM_CUSTOM 0 /*1: use custom malloc/free, 0: use the built-in lv_mem_alloc/lv_mem_free*/
|
||||||
#if LV_MEM_CUSTOM == 0
|
#if LV_MEM_CUSTOM == 0
|
||||||
# define LV_MEM_SIZE (0x38000U * 1024U) /*Size memory used by `lv_mem_alloc` in bytes (>= 2kB)*/
|
# define LV_MEM_SIZE (0x38000U * 1024U) /*Size memory used by `lv_mem_alloc` in bytes (>= 2kB)*/
|
||||||
# define LV_MEM_ATTR /*Complier prefix for big array declaration*/
|
# define LV_MEM_ATTR /*Complier prefix for big array declaration*/
|
||||||
# define LV_MEM_ADR 0xF1000000 /*Set an address for memory pool instead of allocation it as an array. Can be in external SRAM too.*/
|
# define LV_MEM_ADR 0xF1000000 /*Set an address for memory pool instead of allocation it as an array. Can be in external SRAM too.*/
|
||||||
# define LV_MEM_AUTO_DEFRAG 1 /*Automatically defrag on free*/
|
# define LV_MEM_AUTO_DEFRAG 1 /*Automatically defrag on free*/
|
||||||
#else /*LV_MEM_CUSTOM*/
|
#else /*LV_MEM_CUSTOM*/
|
||||||
# define LV_MEM_CUSTOM_INCLUDE "../../../mem/heap.h" /*Header for the dynamic memory function*/
|
# define LV_MEM_CUSTOM_INCLUDE "../../../mem/heap.h" /*Header for the dynamic memory function*/
|
||||||
# define LV_MEM_CUSTOM_ALLOC malloc /*Wrapper to malloc*/
|
# define LV_MEM_CUSTOM_ALLOC malloc /*Wrapper to malloc*/
|
||||||
|
@ -119,10 +119,10 @@
|
||||||
#define LV_INDEV_LONG_PRESS_REP_TIME 1000 //Fix keyb /*Repeated trigger period in long press [ms] */
|
#define LV_INDEV_LONG_PRESS_REP_TIME 1000 //Fix keyb /*Repeated trigger period in long press [ms] */
|
||||||
|
|
||||||
/*Color settings*/
|
/*Color settings*/
|
||||||
#define LV_COLOR_DEPTH 32 /*Color depth: 1/8/16/32*/
|
#define LV_COLOR_DEPTH 32 /*Color depth: 1/8/16/32*/
|
||||||
#define LV_COLOR_16_SWAP 0 /*Swap the 2 bytes of RGB565 color. Useful if the display has a 8 bit interface (e.g. SPI)*/
|
#define LV_COLOR_16_SWAP 0 /*Swap the 2 bytes of RGB565 color. Useful if the display has a 8 bit interface (e.g. SPI)*/
|
||||||
#define LV_COLOR_SCREEN_TRANSP 0 /*1: Enable screen transparency. Useful for OSD or other overlapping GUIs. Requires ARGB8888 colors*/
|
#define LV_COLOR_SCREEN_TRANSP 0 /*1: Enable screen transparency. Useful for OSD or other overlapping GUIs. Requires ARGB8888 colors*/
|
||||||
#define LV_COLOR_TRANSP LV_COLOR_LIME /*Images pixels with this color will not be drawn (with chroma keying)*/
|
#define LV_COLOR_TRANSP LV_COLOR_LIME /*Images pixels with this color will not be drawn (with chroma keying)*/
|
||||||
|
|
||||||
/*Text settings*/
|
/*Text settings*/
|
||||||
#define LV_TXT_UTF8 0 /*Enable UTF-8 coded Unicode character usage */
|
#define LV_TXT_UTF8 0 /*Enable UTF-8 coded Unicode character usage */
|
||||||
|
@ -184,10 +184,10 @@
|
||||||
* which will determine the bit-per-pixel. Higher value means smoother fonts */
|
* which will determine the bit-per-pixel. Higher value means smoother fonts */
|
||||||
#define LV_FONT_QUALITY 8
|
#define LV_FONT_QUALITY 8
|
||||||
|
|
||||||
#define USE_UBUNTU_MONO LV_FONT_QUALITY
|
#define USE_UBUNTU_MONO LV_FONT_QUALITY
|
||||||
|
|
||||||
#define USE_INTERUI_20 LV_FONT_QUALITY
|
#define USE_INTERUI_20 LV_FONT_QUALITY
|
||||||
#define USE_INTERUI_30 LV_FONT_QUALITY
|
#define USE_INTERUI_30 LV_FONT_QUALITY
|
||||||
|
|
||||||
#define USE_HEKATE_SYMBOL_20 USE_INTERUI_20
|
#define USE_HEKATE_SYMBOL_20 USE_INTERUI_20
|
||||||
#define USE_HEKATE_SYMBOL_30 USE_INTERUI_30
|
#define USE_HEKATE_SYMBOL_30 USE_INTERUI_30
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -42,7 +42,7 @@ void reconfig_hw_workaround(bool extra_reconfig, u32 magic)
|
||||||
|
|
||||||
// Re-enable clocks to Audio Processing Engine as a workaround to hanging.
|
// Re-enable clocks to Audio Processing Engine as a workaround to hanging.
|
||||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= (1 << 10); // Enable AHUB clock.
|
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= (1 << 10); // Enable AHUB clock.
|
||||||
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= (1 << 6); // Enable APE clock.
|
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= (1 << 6); // Enable APE clock.
|
||||||
|
|
||||||
if (extra_reconfig)
|
if (extra_reconfig)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue