From 22b1fda1d56e0d6301d1fa2b33359a1276617fc9 Mon Sep 17 00:00:00 2001 From: Damien Zhao Date: Mon, 21 Oct 2024 16:21:40 +0800 Subject: [PATCH] uplift bdk Signed-off-by: Damien Zhao --- bdk/bdk.h | 3 +- bdk/display/di.c | 223 ++++++++++++++++++-------------- bdk/display/di.h | 207 +++++++++++++++++++----------- bdk/display/di.inl | 217 ++++++++++++++----------------- bdk/display/vic.c | 13 +- bdk/display/vic.h | 7 +- bdk/input/als.c | 6 +- bdk/input/joycon.c | 138 ++++++++++---------- bdk/input/joycon.h | 50 ++++---- bdk/libs/compr/blz.c | 55 ++++---- bdk/libs/compr/blz.h | 8 +- bdk/libs/compr/lz4.c | 10 -- bdk/libs/fatfs/ff.c | 2 +- bdk/libs/fatfs/ff.h | 2 +- bdk/libs/lv_conf.h | 2 +- bdk/mem/emc.h | 3 +- bdk/mem/minerva.h | 2 +- bdk/mem/sdram.c | 254 +++++++++++++++++++++++-------------- bdk/mem/sdram.h | 10 +- bdk/power/bm92t36.c | 2 +- bdk/power/regulator_5v.c | 10 +- bdk/sec/se.c | 75 ++++++++++- bdk/sec/se.h | 8 +- bdk/sec/tsec.c | 4 +- bdk/soc/bpmp.c | 82 ++++++++---- bdk/soc/bpmp.h | 18 ++- bdk/soc/clock.c | 31 ++++- bdk/soc/clock.h | 2 + bdk/soc/fuse.c | 15 ++- bdk/soc/fuse.h | 1 + bdk/soc/hw_init.c | 117 +++++++++++------ bdk/soc/hw_init.h | 5 +- bdk/soc/i2c.c | 4 +- bdk/soc/i2c.h | 2 +- bdk/soc/irq.c | 19 +-- bdk/soc/pinmux.c | 9 ++ bdk/soc/pinmux.h | 10 ++ bdk/soc/pmc.h | 20 +-- bdk/soc/t210.h | 12 +- bdk/soc/timer.c | 4 +- bdk/soc/uart.c | 6 +- bdk/storage/sd.c | 2 +- bdk/storage/sd.h | 2 +- bdk/storage/sd_def.h | 2 +- bdk/storage/sdmmc.c | 28 ++-- bdk/storage/sdmmc_driver.c | 61 ++++----- bdk/thermal/fan.c | 26 ++-- bdk/thermal/fan.h | 10 +- bdk/usb/usb_gadget_hid.c | 33 +++-- bdk/usb/usb_gadget_ums.c | 36 ++++-- bdk/usb/usbd.c | 8 +- bdk/usb/xusbd.c | 20 ++- bdk/utils/dirlist.c | 42 +++--- bdk/utils/dirlist.h | 12 +- bdk/utils/ini.c | 8 +- bdk/utils/ini.h | 2 +- bdk/utils/sprintf.c | 53 +++++++- bdk/utils/sprintf.h | 20 ++- bdk/utils/types.h | 8 +- bdk/utils/util.c | 32 ++++- bdk/utils/util.h | 12 +- source/hos/sept.c | 2 +- source/main.c | 8 +- source/script/lexer.c | 2 +- 64 files changed, 1289 insertions(+), 808 deletions(-) diff --git a/bdk/bdk.h b/bdk/bdk.h index 1cb315c..1d8a05e 100644 --- a/bdk/bdk.h +++ b/bdk/bdk.h @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -76,4 +77,4 @@ #include -#endif \ No newline at end of file +#endif diff --git a/bdk/display/di.c b/bdk/display/di.c index 0b3301f..80c4d12 100644 --- a/bdk/display/di.c +++ b/bdk/display/di.c @@ -59,7 +59,7 @@ void display_wait_interrupt(u32 intr) // Interrupts are masked. Poll status register for checking if fired. while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & intr)) - ; + ; } static void _display_dsi_wait(u32 timeout, u32 off, u32 mask) @@ -373,24 +373,10 @@ void display_init() // Get Chip ID. bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210; - // T210B01: Power on SD2 regulator for supplying LDO0. - if (!tegra_t210) - { - // Set SD2 regulator voltage. - max7762x_regulator_set_voltage(REGULATOR_SD2, 1325000); - - // Set slew rate and enable SD2 regulator. - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD2_CFG, (1 << MAX77620_SD_SR_SHIFT) | MAX77620_SD_CFG1_FSRADE_SD_ENABLE); - max7762x_regulator_enable(REGULATOR_SD2, true); - } - - // Enable LCD DVDD. + // Enable DSI AVDD. max7762x_regulator_set_voltage(REGULATOR_LDO0, 1200000); max7762x_regulator_enable(REGULATOR_LDO0, true); - if (tegra_t210) - max77620_config_gpio(7, MAX77620_GPIO_OUTPUT_ENABLE); // T210: LD0 -> GPIO7 -> LCD. - // Enable Display Interface specific clocks. CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI); @@ -398,7 +384,7 @@ void display_init() CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_DISP1); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = BIT(CLK_X_UART_FST_MIPI_CAL); - CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL) = CLK_SRC_DIV(6); // Set PLLP_OUT3 and div 6 (17MHz). + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL) = CLK_SRC_DIV(6); // Set PLLP_OUT3 and div 6 (68MHz). CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_SET) = BIT(CLK_W_DSIA_LP); CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP) = CLK_SRC_DIV(6); // Set PLLP_OUT and div 6 (68MHz). @@ -448,26 +434,19 @@ void display_init() clock_enable_plld(3, 20, true, tegra_t210); // Setup Display Interface initial window configuration. - exec_cfg((u32 *)DISPLAY_A_BASE, _di_dc_setup_win_config, CFG_SIZE(_di_dc_setup_win_config)); + reg_write_array((u32 *)DISPLAY_A_BASE, _di_dc_setup_win_config, ARRAY_SIZE(_di_dc_setup_win_config)); // Setup dsi init sequence packets. - exec_cfg((u32 *)DSI_BASE, _di_dsi_init_irq_pkt_config0, CFG_SIZE(_di_dsi_init_irq_pkt_config0)); - if (tegra_t210) - DSI(_DSIREG(DSI_INIT_SEQ_DATA_15)) = 0; - else - DSI(_DSIREG(DSI_INIT_SEQ_DATA_15_B01)) = 0; - exec_cfg((u32 *)DSI_BASE, _di_dsi_init_irq_pkt_config1, CFG_SIZE(_di_dsi_init_irq_pkt_config1)); + reg_write_array((u32 *)DSI_BASE, _di_dsi_seq_pkt_reset_config0, ARRAY_SIZE(_di_dsi_seq_pkt_reset_config0)); + DSI(_DSIREG(tegra_t210 ? DSI_INIT_SEQ_DATA_15 : DSI_INIT_SEQ_DATA_15_B01)) = 0; + reg_write_array((u32 *)DSI_BASE, _di_dsi_seq_pkt_reset_config1, ARRAY_SIZE(_di_dsi_seq_pkt_reset_config1)); // Reset pad trimmers for T210B01. if (!tegra_t210) - exec_cfg((u32 *)DSI_BASE, _di_dsi_init_pads_t210b01, CFG_SIZE(_di_dsi_init_pads_t210b01)); + reg_write_array((u32 *)DSI_BASE, _di_dsi_init_pads_t210b01, ARRAY_SIZE(_di_dsi_init_pads_t210b01)); - // Setup init sequence packets and timings. - exec_cfg((u32 *)DSI_BASE, _di_dsi_init_timing_pkt_config2, CFG_SIZE(_di_dsi_init_timing_pkt_config2)); - DSI(_DSIREG(DSI_PHY_TIMING_0)) = tegra_t210 ? 0x6070601 : 0x6070603; // DSI_THSPREPR: 1 : 3. - exec_cfg((u32 *)DSI_BASE, _di_dsi_init_timing_pwrctrl_config, CFG_SIZE(_di_dsi_init_timing_pwrctrl_config)); - DSI(_DSIREG(DSI_PHY_TIMING_0)) = tegra_t210 ? 0x6070601 : 0x6070603; // DSI_THSPREPR: 1 : 3. - exec_cfg((u32 *)DSI_BASE, _di_dsi_init_timing_pkt_config3, CFG_SIZE(_di_dsi_init_timing_pkt_config3)); + // Setup init seq packet lengths, timings and power on DSI. + reg_write_array((u32 *)DSI_BASE, _di_dsi_init_config, ARRAY_SIZE(_di_dsi_init_config)); usleep(10000); // Enable LCD Reset. @@ -505,9 +484,9 @@ void display_init() { case PANEL_SAM_AMS699VC01: _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000); - // Set color mode to natural. Stock is Saturated (0x00). (Reset value is 0x20). + // Set color mode to basic (natural). Stock is Saturated (0x00). (Reset value is 0x20). _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM, - MIPI_DCS_PRIV_SM_SET_COLOR_MODE | (DCS_SM_COLOR_MODE_NATURAL << 8), 0); + MIPI_DCS_PRIV_SM_SET_COLOR_MODE | (DCS_SM_COLOR_MODE_BASIC << 8), 0); // Enable backlight and smooth PWM. _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM, MIPI_DCS_SET_CONTROL_DISPLAY | ((DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL | DCS_CONTROL_DISPLAY_DIMMING_CTRL) << 8), 0); @@ -537,7 +516,7 @@ void display_init() break; case PANEL_JDI_XXX062M: - exec_cfg((u32 *)DSI_BASE, _di_dsi_panel_init_config_jdi, CFG_SIZE(_di_dsi_panel_init_config_jdi)); + reg_write_array((u32 *)DSI_BASE, _di_dsi_panel_init_config_jdi, ARRAY_SIZE(_di_dsi_panel_init_config_jdi)); _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000); break; @@ -578,21 +557,24 @@ void display_init() clock_enable_plld(1, 24, false, tegra_t210); // Finalize DSI init packet sequence configuration. - DSI(_DSIREG(DSI_PAD_CONTROL_1)) = 0; - DSI(_DSIREG(DSI_PHY_TIMING_0)) = tegra_t210 ? 0x6070601 : 0x6070603; - exec_cfg((u32 *)DSI_BASE, _di_dsi_init_seq_pkt_final_config, CFG_SIZE(_di_dsi_init_seq_pkt_final_config)); + reg_write_array((u32 *)DSI_BASE, _di_dsi_seq_pkt_video_non_burst_no_eot_config, ARRAY_SIZE(_di_dsi_seq_pkt_video_non_burst_no_eot_config)); // Set 1-by-1 pixel/clock and pixel clock to 234 / 3 = 78 MHz. For 60 Hz refresh rate. DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4); // 4: div3. - // Set DSI mode. - exec_cfg((u32 *)DSI_BASE, _di_dsi_mode_config, CFG_SIZE(_di_dsi_mode_config)); + // Set DSI mode to HOST. + reg_write_array((u32 *)DSI_BASE, _di_dsi_host_mode_config, ARRAY_SIZE(_di_dsi_host_mode_config)); usleep(10000); - // Calibrate display communication pads. - u32 loops = tegra_t210 ? 1 : 2; // Calibrate pads 2 times on T210B01. - exec_cfg((u32 *)MIPI_CAL_BASE, _di_mipi_pad_cal_config, CFG_SIZE(_di_mipi_pad_cal_config)); - for (u32 i = 0; i < loops; i++) + /* + * Calibrate display communication pads. + * When switching to the 16ff pad brick, the clock lane termination control + * is separated from data lane termination. This change of the mipi cal + * brings in a bug that the DSI pad clock termination code can't be loaded + * in one time calibration. Trigger calibration twice. + */ + reg_write_array((u32 *)MIPI_CAL_BASE, _di_mipi_pad_cal_config, ARRAY_SIZE(_di_mipi_pad_cal_config)); + for (u32 i = 0; i < 2; i++) { // Set MIPI bias pad config. MIPI_CAL(_DSIREG(MIPI_CAL_MIPI_BIAS_PAD_CFG2)) = 0x10010; @@ -601,22 +583,25 @@ void display_init() // Set pad trimmers and set MIPI DSI cal offsets. if (tegra_t210) { - exec_cfg((u32 *)DSI_BASE, _di_dsi_pad_cal_config_t210, CFG_SIZE(_di_dsi_pad_cal_config_t210)); - exec_cfg((u32 *)MIPI_CAL_BASE, _di_mipi_dsi_cal_offsets_config_t210, CFG_SIZE(_di_mipi_dsi_cal_offsets_config_t210)); + reg_write_array((u32 *)DSI_BASE, _di_dsi_pad_cal_config_t210, ARRAY_SIZE(_di_dsi_pad_cal_config_t210)); + reg_write_array((u32 *)MIPI_CAL_BASE, _di_mipi_dsi_cal_prod_config_t210, ARRAY_SIZE(_di_mipi_dsi_cal_prod_config_t210)); } else { - exec_cfg((u32 *)DSI_BASE, _di_dsi_pad_cal_config_t210b01, CFG_SIZE(_di_dsi_pad_cal_config_t210b01)); - exec_cfg((u32 *)MIPI_CAL_BASE, _di_mipi_dsi_cal_offsets_config_t210b01, CFG_SIZE(_di_mipi_dsi_cal_offsets_config_t210b01)); + reg_write_array((u32 *)DSI_BASE, _di_dsi_pad_cal_config_t210b01, ARRAY_SIZE(_di_dsi_pad_cal_config_t210b01)); + reg_write_array((u32 *)MIPI_CAL_BASE, _di_mipi_dsi_cal_prod_config_t210b01, ARRAY_SIZE(_di_mipi_dsi_cal_prod_config_t210b01)); } - // Reset all MIPI cal offsets and start calibration. - exec_cfg((u32 *)MIPI_CAL_BASE, _di_mipi_start_dsi_cal_config, CFG_SIZE(_di_mipi_start_dsi_cal_config)); + // Reset all unused MIPI cal offsets. + reg_write_array((u32 *)MIPI_CAL_BASE, _di_mipi_dsi_cal_unused_config, ARRAY_SIZE(_di_mipi_dsi_cal_unused_config)); + + // Set Prescale/filter and start calibration. + MIPI_CAL(_DSIREG(MIPI_CAL_MIPI_CAL_CTRL)) = 0x2A000001; } usleep(10000); // Enable video display controller. - exec_cfg((u32 *)DISPLAY_A_BASE, _di_dc_video_enable_config, CFG_SIZE(_di_dc_video_enable_config)); + reg_write_array((u32 *)DISPLAY_A_BASE, _di_dc_video_enable_config, ARRAY_SIZE(_di_dc_video_enable_config)); } void display_backlight_pwm_init() @@ -624,12 +609,15 @@ void display_backlight_pwm_init() if (_display_id == PANEL_SAM_AMS699VC01) return; + // Enable PWM clock. clock_enable_pwm(); // Enable PWM and set it to 25KHz PFM. 29.5KHz is stock. PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN; PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & ~PINMUX_FUNC_MASK) | 1; // Set PWM0 mode. + usleep(2); + gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight power mode. } @@ -650,9 +638,9 @@ static void _display_dsi_backlight_brightness(u32 duty) u16 bl_ctrl = byte_swap_16((u16)candela); display_dsi_vblank_write(MIPI_DCS_SET_BRIGHTNESS, 2, &bl_ctrl); - // Wait for backlight to completely turn off. 6+1 frames. + // Wait for backlight to completely turn off. 6 frames. if (!duty) - usleep(120000); + usleep(100000); _dsi_bl = duty; } @@ -696,7 +684,10 @@ void display_backlight_brightness(u32 brightness, u32 step_delay) u32 display_get_backlight_brightness() { - return ((PWM(PWM_CONTROLLER_PWM_CSR_0) >> 16) & 0xFF); + if (_display_id != PANEL_SAM_AMS699VC01) + return ((PWM(PWM_CONTROLLER_PWM_CSR_0) >> 16) & 0xFF); + else + return _dsi_bl; } static void _display_panel_and_hw_end(bool no_panel_deinit) @@ -713,14 +704,15 @@ static void _display_panel_and_hw_end(bool no_panel_deinit) DSI(_DSIREG(DSI_WR_DATA)) = (MIPI_DCS_SET_DISPLAY_OFF << 8) | MIPI_DSI_DCS_SHORT_WRITE; // Wait for 5 frames (HOST1X_CH0_SYNC_SYNCPT_9). - // Not here. + // Not here. Wait for 1 frame manually. + usleep(20000); // Propagate changes to all register buffers and disable host cmd packets during video. - DISPLAY_A(_DIREG(DC_CMD_STATE_ACCESS)) = READ_MUX | WRITE_MUX; + DISPLAY_A(_DIREG(DC_CMD_STATE_ACCESS)) = READ_MUX_ACTIVE | WRITE_MUX_ACTIVE; DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0; // De-initialize video controller. - exec_cfg((u32 *)DISPLAY_A_BASE, _di_dc_video_disable_config, CFG_SIZE(_di_dc_video_disable_config)); + reg_write_array((u32 *)DISPLAY_A_BASE, _di_dc_video_disable_config, ARRAY_SIZE(_di_dc_video_disable_config)); // Set DISP1 clock source, parent clock and DSI/PCLK to low power mode. // T210: DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 100.0 MHz, PLLD_OUT0 (DSI-PCLK): 50.0 MHz. (PCLK: 16.66 MHz) @@ -728,7 +720,7 @@ static void _display_panel_and_hw_end(bool no_panel_deinit) clock_enable_plld(3, 20, true, hw_get_chip_id() == GP_HIDREV_MAJOR_T210); // Set timings for lowpower clocks. - exec_cfg((u32 *)DSI_BASE, _di_dsi_timing_deinit_config, CFG_SIZE(_di_dsi_timing_deinit_config)); + reg_write_array((u32 *)DSI_BASE, _di_dsi_timing_deinit_config, ARRAY_SIZE(_di_dsi_timing_deinit_config)); if (_display_id != PANEL_SAM_AMS699VC01) usleep(10000); @@ -737,11 +729,12 @@ static void _display_panel_and_hw_end(bool no_panel_deinit) switch (_display_id) { case PANEL_JDI_XXX062M: - exec_cfg((u32 *)DSI_BASE, _di_dsi_panel_deinit_config_jdi, CFG_SIZE(_di_dsi_panel_deinit_config_jdi)); + reg_write_array((u32 *)DSI_BASE, _di_dsi_panel_deinit_config_jdi, ARRAY_SIZE(_di_dsi_panel_deinit_config_jdi)); break; case PANEL_AUO_A062TAN01: - exec_cfg((u32 *)DSI_BASE, _di_dsi_panel_deinit_config_auo, CFG_SIZE(_di_dsi_panel_deinit_config_auo)); + reg_write_array((u32 *)DSI_BASE, _di_dsi_panel_deinit_config_auo, ARRAY_SIZE(_di_dsi_panel_deinit_config_auo)); + usleep(5000); break; case PANEL_INL_2J055IA_27A: @@ -796,6 +789,10 @@ skip_panel_deinit: { gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_LOW); // LCD AVDD -5.4V disable. gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_LOW); // LCD AVDD +5.4V disable. + + // Make sure LCD PWM backlight pin is in PWM0 mode. + gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight PWM. + PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = PINMUX_TRISTATE | PINMUX_PULL_DOWN | 1; // Set PWM0 mode. } usleep(10000); @@ -810,14 +807,7 @@ skip_panel_deinit: DSI_PAD_CONTROL_VS1_PDIO_CLK | DSI_PAD_CONTROL_VS1_PDIO(0xF); DSI(_DSIREG(DSI_POWER_CONTROL)) = 0; - // Switch LCD PWM backlight pin to special function mode and enable PWM0 mode. - if (!_nx_aula) - { - gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight PWM. - PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = PINMUX_TRISTATE | PINMUX_PULL_DOWN | 1; // Set PWM0 mode. - } - - // Disable LCD DVDD. + // Disable DSI AVDD. max7762x_regulator_enable(REGULATOR_LDO0, false); } @@ -846,14 +836,15 @@ void display_set_decoded_panel_id(u32 id) void display_color_screen(u32 color) { - exec_cfg((u32 *)DISPLAY_A_BASE, _di_win_one_color, CFG_SIZE(_di_win_one_color)); + // Disable all windows. + reg_write_array((u32 *)DISPLAY_A_BASE, _di_win_one_color, ARRAY_SIZE(_di_win_one_color)); // Configure display to show single color. - DISPLAY_A(_DIREG(DC_WIN_AD_WIN_OPTIONS)) = 0; - DISPLAY_A(_DIREG(DC_WIN_BD_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_CMD_STATE_CONTROL)) = (DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) & 0xFFFFFFFE) | GENERAL_ACT_REQ; + + // Arm and activate changes. + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE | WIN_D_UPDATE; + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ | WIN_D_ACT_REQ; usleep(35000); // Wait 2 frames. No need on Aula. if (_display_id != PANEL_SAM_AMS699VC01) @@ -862,58 +853,108 @@ void display_color_screen(u32 color) display_backlight_brightness(150, 0); } -u32 *display_init_framebuffer_pitch() +u32 *display_init_window_a_pitch() { // Sanitize framebuffer area. memset((u32 *)IPL_FB_ADDRESS, 0, IPL_FB_SZ); // This configures the framebuffer @ IPL_FB_ADDRESS with a resolution of 720x1280 (line stride 720). - exec_cfg((u32 *)DISPLAY_A_BASE, _di_win_framebuffer_pitch, CFG_SIZE(_di_win_framebuffer_pitch)); + reg_write_array((u32 *)DISPLAY_A_BASE, _di_winA_pitch, ARRAY_SIZE(_di_winA_pitch)); //usleep(35000); // Wait 2 frames. No need on Aula. return (u32 *)DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR)); } -u32 *display_init_framebuffer_pitch_vic() +u32 *display_init_window_a_pitch_vic() { // This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 720x1280 (line stride 720). if (_display_id != PANEL_SAM_AMS699VC01) usleep(8000); // Wait half frame for PWM to apply. - exec_cfg((u32 *)DISPLAY_A_BASE, _di_win_framebuffer_pitch_vic, CFG_SIZE(_di_win_framebuffer_pitch_vic)); + reg_write_array((u32 *)DISPLAY_A_BASE, _di_winA_pitch_vic, ARRAY_SIZE(_di_winA_pitch_vic)); if (_display_id != PANEL_SAM_AMS699VC01) usleep(35000); // Wait 2 frames. return (u32 *)DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR)); } -u32 *display_init_framebuffer_pitch_inv() +u32 *display_init_window_a_pitch_inv() { // This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 720x1280 (line stride 720). - exec_cfg((u32 *)DISPLAY_A_BASE, _di_win_framebuffer_pitch_inv, CFG_SIZE(_di_win_framebuffer_pitch_inv)); + reg_write_array((u32 *)DISPLAY_A_BASE, _di_winA_pitch_inv, ARRAY_SIZE(_di_winA_pitch_inv)); usleep(35000); // Wait 2 frames. No need on Aula. return (u32 *)DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR)); } -u32 *display_init_framebuffer_block() +u32 *display_init_window_a_block() { // This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 720x1280. - exec_cfg((u32 *)DISPLAY_A_BASE, _di_win_framebuffer_block, CFG_SIZE(_di_win_framebuffer_block)); + reg_write_array((u32 *)DISPLAY_A_BASE, _di_winA_block, ARRAY_SIZE(_di_winA_block)); usleep(35000); // Wait 2 frames. No need on Aula. return (u32 *)DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR)); } -u32 *display_init_framebuffer_log() +u32 *display_init_window_d_console() { // This configures the framebuffer @ LOG_FB_ADDRESS with a resolution of 1280x720 (line stride 720). - exec_cfg((u32 *)DISPLAY_A_BASE, _di_win_framebuffer_log, CFG_SIZE(_di_win_framebuffer_log)); + reg_write_array((u32 *)DISPLAY_A_BASE, _di_winD_log, ARRAY_SIZE(_di_winD_log)); return (u32 *)DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR)); } -void display_activate_console() +void display_window_disable(u32 window) { + // Select window C. + DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = BIT(WINDOW_SELECT + window); + + // Disable window C. + DISPLAY_A(_DIREG(DC_WIN_WIN_OPTIONS)) = 0; + + // Arm and activate changes. + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | BIT(WIN_UPDATE + window); + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | BIT(WIN_ACT_REQ + window); +} + +void display_set_framebuffer(u32 window, void *fb) +{ + // Select window. + DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = BIT(WINDOW_SELECT + window); + + // Set new fb address. + DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR)) = (u32)fb; + + // Arm and activate changes. + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | BIT(WIN_UPDATE + window); + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | BIT(WIN_ACT_REQ + window); +} + +void display_move_framebuffer(u32 window, void *fb) +{ + // Select window. + DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = BIT(WINDOW_SELECT + window); + + // Get current framebuffer address. + const void *fb_curr = (void *)DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR)); + u32 win_size = DISPLAY_A(_DIREG(DC_WIN_PRESCALED_SIZE)); + win_size = (win_size & 0x7FFF) * ((win_size >> 16) & 0x1FFF); + + // Copy fb over. + memcpy(fb, fb_curr, win_size); + + // Set new fb address. + DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR)) = (u32)fb; + + // Arm and activate changes. + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | BIT(WIN_UPDATE + window); + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | BIT(WIN_ACT_REQ + window); +} + +void display_window_d_console_enable() +{ + // Only update active registers on vsync. + DISPLAY_A(_DIREG(DC_CMD_REG_ACT_CONTROL)) = DISPLAY_A(_DIREG(DC_CMD_REG_ACT_CONTROL)) & ~WIN_D_ACT_HCNTR_SEL; + // Select window D. DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_D_SELECT; @@ -942,12 +983,9 @@ void display_activate_console() // Arm and activate changes. DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE; DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ; - - // Re-select window A. - DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_A_SELECT; } -void display_deactivate_console() +void display_window_d_console_disable() { // Select window D. DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_D_SELECT; @@ -965,18 +1003,15 @@ void display_deactivate_console() } // Disable window D. - DISPLAY_A(_DIREG(DC_WIN_POSITION)) = 0; + DISPLAY_A(_DIREG(DC_WIN_POSITION)) = 0; DISPLAY_A(_DIREG(DC_WIN_WIN_OPTIONS)) = 0; // Arm and activate changes. DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE; DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | WIN_D_ACT_REQ; - - // Re-select window A. - DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_A_SELECT; } -void display_init_cursor(void *crs_fb, u32 size) +void display_cursor_init(void *crs_fb, u32 size) { // Setup cursor. DISPLAY_A(_DIREG(DC_DISP_CURSOR_START_ADDR)) = CURSOR_CLIPPING(CURSOR_CLIP_WIN_A) | size | ((u32)crs_fb >> 10); @@ -992,7 +1027,7 @@ void display_init_cursor(void *crs_fb, u32 size) DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | CURSOR_ACT_REQ; } -void display_set_pos_cursor(u32 x, u32 y) +void display_cursor_set_pos(u32 x, u32 y) { // Set cursor position. DISPLAY_A(_DIREG(DC_DISP_CURSOR_POSITION)) = x | (y << 16); @@ -1002,7 +1037,7 @@ void display_set_pos_cursor(u32 x, u32 y) DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | CURSOR_ACT_REQ; } -void display_deinit_cursor() +void display_cursor_deinit() { DISPLAY_A(_DIREG(DC_DISP_BLEND_CURSOR_CONTROL)) = 0; DISPLAY_A(_DIREG(DC_DISP_DISP_WIN_OPTIONS)) &= ~CURSOR_ENABLE; diff --git a/bdk/display/di.h b/bdk/display/di.h index d2ea5db..a44e730 100644 --- a/bdk/display/di.h +++ b/bdk/display/di.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2023 CTCaer + * Copyright (c) 2018-2024 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -24,6 +24,11 @@ #define DSI_VIDEO_DISABLED 0 #define DSI_VIDEO_ENABLED 1 +#define WINDOW_A 0 +#define WINDOW_B 1 +#define WINDOW_C 2 +#define WINDOW_D 3 + /*! Display registers. */ #define _DIREG(reg) ((reg) * 4) @@ -43,8 +48,8 @@ // DC_CMD non-shadowed command/sync registers. #define DC_CMD_GENERAL_INCR_SYNCPT 0x00 -#define SYNCPT_GENERAL_INDX(x) (((x) & 0xff) << 0) -#define SYNCPT_GENERAL_COND(x) (((x) & 0xff) << 8) +#define SYNCPT_GENERAL_INDX(x) (((x) & 0xFF) << 0) +#define SYNCPT_GENERAL_COND(x) (((x) & 0xFF) << 8) #define COND_REG_WR_SAFE 3 #define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x01 @@ -52,7 +57,7 @@ #define SYNCPT_CNTRL_NO_STALL BIT(8) #define DC_CMD_CONT_SYNCPT_VSYNC 0x28 -#define SYNCPT_VSYNC_INDX(x) (((x) & 0xff) << 0) +#define SYNCPT_VSYNC_INDX(x) (((x) & 0xFF) << 0) #define SYNCPT_VSYNC_ENABLE BIT(8) #define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031 @@ -77,19 +82,24 @@ #define DC_CMD_INT_ENABLE 0x39 #define DC_CMD_INT_FRAME_END_INT BIT(1) #define DC_CMD_INT_V_BLANK_INT BIT(2) +#define DC_CMD_INT_POLARITY 0x3B #define DC_CMD_STATE_ACCESS 0x40 -#define READ_MUX BIT(0) -#define WRITE_MUX BIT(2) +#define READ_MUX_ASSEMBLY 0x0 +#define WRITE_MUX_ASSEMBLY 0x0 +#define READ_MUX_ACTIVE BIT(0) +#define WRITE_MUX_ACTIVE BIT(2) #define DC_CMD_STATE_CONTROL 0x41 #define GENERAL_ACT_REQ BIT(0) +#define WIN_ACT_REQ 1 #define WIN_A_ACT_REQ BIT(1) #define WIN_B_ACT_REQ BIT(2) #define WIN_C_ACT_REQ BIT(3) #define WIN_D_ACT_REQ BIT(4) #define CURSOR_ACT_REQ BIT(7) #define GENERAL_UPDATE BIT(8) +#define WIN_UPDATE 9 #define WIN_A_UPDATE BIT(9) #define WIN_B_UPDATE BIT(10) #define WIN_C_UPDATE BIT(11) @@ -98,6 +108,7 @@ #define NC_HOST_TRIG BIT(24) #define DC_CMD_DISPLAY_WINDOW_HEADER 0x42 +#define WINDOW_SELECT 4 #define WINDOW_A_SELECT BIT(4) #define WINDOW_B_SELECT BIT(5) #define WINDOW_C_SELECT BIT(6) @@ -137,6 +148,31 @@ #define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x)) #define LSC0_OUTPUT_POLARITY_LOW BIT(24) +// CMU registers. +#define DC_COM_CMU_CSC_KRR 0x32A +#define DC_COM_CMU_CSC_KGR 0x32B +#define DC_COM_CMU_CSC_KBR 0x32C +#define DC_COM_CMU_CSC_KRG 0x32D +#define DC_COM_CMU_CSC_KGG 0x32E +#define DC_COM_CMU_CSC_KBG 0x32F +#define DC_COM_CMU_CSC_KRB 0x330 +#define DC_COM_CMU_CSC_KGB 0x331 +#define DC_COM_CMU_CSC_KBB 0x332 +#define DC_COM_CMU_LUT1 0x336 +#define LUT1_ADDR(x) ((x) & 0xFF) +#define LUT1_DATA(x) (((x) & 0xFFF) << 16) +#define LUT1_READ_DATA(x) (((x) >> 16) & 0xFFF) +#define DC_COM_CMU_LUT2 0x337 +#define LUT2_ADDR(x) ((x) & 0x3FF) +#define LUT2_DATA(x) (((x) & 0xFF) << 16) +#define LUT2_READ_DATA(x) (((x) >> 16) & 0xFF) +#define DC_COM_CMU_LUT1_READ 0x338 +#define LUT1_READ_ADDR(x) (((x) & 0xFF) << 8) +#define LUT1_READ_EN BIT(0) +#define DC_COM_CMU_LUT2_READ 0x339 +#define LUT2_READ_ADDR(x) (((x) & 0x3FF) << 8) +#define LUT2_READ_EN BIT(0) + #define DC_COM_DSC_TOP_CTL 0x33E // DC_DISP shadowed registers. @@ -153,30 +189,30 @@ #define DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER 0x404 #define DC_DISP_DISP_TIMING_OPTIONS 0x405 -#define VSYNC_H_POSITION(x) (((x) & 0x1fff) << 0) +#define VSYNC_H_POSITION(x) (((x) & 0x1FFF) << 0) #define DC_DISP_REF_TO_SYNC 0x406 -#define H_REF_TO_SYNC(x) (((x) & 0x1fff) << 0) // Min 0 pixel clock. -#define V_REF_TO_SYNC(x) (((x) & 0x1fff) << 16) // Min 1 line clock. +#define H_REF_TO_SYNC(x) (((x) & 0x1FFF) << 0) // Min 0 pixel clock. +#define V_REF_TO_SYNC(x) (((x) & 0x1FFF) << 16) // Min 1 line clock. #define DC_DISP_SYNC_WIDTH 0x407 -#define H_SYNC_WIDTH(x) (((x) & 0x1fff) << 0) // Min 1 pixel clock. -#define V_SYNC_WIDTH(x) (((x) & 0x1fff) << 16) // Min 1 line clock. +#define H_SYNC_WIDTH(x) (((x) & 0x1FFF) << 0) // Min 1 pixel clock. +#define V_SYNC_WIDTH(x) (((x) & 0x1FFF) << 16) // Min 1 line clock. #define DC_DISP_BACK_PORCH 0x408 -#define H_BACK_PORCH(x) (((x) & 0x1fff) << 0) -#define V_BACK_PORCH(x) (((x) & 0x1fff) << 16) +#define H_BACK_PORCH(x) (((x) & 0x1FFF) << 0) +#define V_BACK_PORCH(x) (((x) & 0x1FFF) << 16) #define DC_DISP_ACTIVE 0x409 -#define H_DISP_ACTIVE(x) (((x) & 0x1fff) << 0) // Min 16 pixel clock. -#define V_DISP_ACTIVE(x) (((x) & 0x1fff) << 16) // Min 16 line clock. +#define H_DISP_ACTIVE(x) (((x) & 0x1FFF) << 0) // Min 16 pixel clock. +#define V_DISP_ACTIVE(x) (((x) & 0x1FFF) << 16) // Min 16 line clock. #define DC_DISP_FRONT_PORCH 0x40A -#define H_FRONT_PORCH(x) (((x) & 0x1fff) << 0) // Min -=PS_=-H_REF_TO_SYNC + 1 -#define V_FRONT_PORCH(x) (((x) & 0x1fff) << 16) // Min -=PS_=-V_REF_TO_SYNC + 1 +#define H_FRONT_PORCH(x) (((x) & 0x1FFF) << 0) // Min -=PS_=-H_REF_TO_SYNC + 1 +#define V_FRONT_PORCH(x) (((x) & 0x1FFF) << 16) // Min -=PS_=-V_REF_TO_SYNC + 1 #define DC_DISP_DISP_CLOCK_CONTROL 0x42E -#define SHIFT_CLK_DIVIDER(x) ((x) & 0xff) +#define SHIFT_CLK_DIVIDER(x) ((x) & 0xFF) #define PIXEL_CLK_DIVIDER_PCD1 (0 << 8) #define PIXEL_CLK_DIVIDER_PCD1H (1 << 8) #define PIXEL_CLK_DIVIDER_PCD2 (2 << 8) @@ -207,11 +243,7 @@ #define DISP_ORDER_BLUE_RED (1 << 9) #define DC_DISP_DISP_COLOR_CONTROL 0x430 -#define DITHER_CONTROL_MASK (3 << 8) -#define DITHER_CONTROL_DISABLE (0 << 8) -#define DITHER_CONTROL_ORDERED (2 << 8) -#define DITHER_CONTROL_ERRDIFF (3 << 8) -#define BASE_COLOR_SIZE_MASK (0xf << 0) +#define BASE_COLOR_SIZE_MASK (0xF << 0) #define BASE_COLOR_SIZE_666 (0 << 0) #define BASE_COLOR_SIZE_111 (1 << 0) #define BASE_COLOR_SIZE_222 (2 << 0) @@ -221,6 +253,13 @@ #define BASE_COLOR_SIZE_565 (6 << 0) #define BASE_COLOR_SIZE_332 (7 << 0) #define BASE_COLOR_SIZE_888 (8 << 0) +#define DITHER_CONTROL_MASK (3 << 8) +#define DITHER_CONTROL_DISABLE (0 << 8) +#define DITHER_CONTROL_ORDERED (2 << 8) +#define DITHER_CONTROL_ERRDIFF (3 << 8) +#define DISP_COLOR_SWAP BIT(16) +#define BLANK_COLOR_WHITE BIT(17) +#define CMU_ENABLE BIT(20) #define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431 #define SC0_H_QUALIFIER_NONE BIT(0) @@ -242,6 +281,7 @@ #define CURSOR_COLOR(r,g,b) (((r) & 0xFF) | (((g) & 0xFF) << 8) | (((b) & 0xFF) << 16)) #define DC_DISP_CURSOR_START_ADDR 0x43E +#define DC_DISP_CURSOR_START_ADDR_NS 0x43F #define CURSOR_CLIPPING(w) ((w) << 28) #define CURSOR_CLIP_WIN_A 1 #define CURSOR_CLIP_WIN_B 2 @@ -253,6 +293,7 @@ #define DC_DISP_CURSOR_POSITION 0x440 #define DC_DISP_BLEND_BACKGROUND_COLOR 0x4E4 #define DC_DISP_CURSOR_START_ADDR_HI 0x4EC +#define DC_DISP_CURSOR_START_ADDR_HI_NS 0x4ED #define DC_DISP_BLEND_CURSOR_CONTROL 0x4F1 #define CURSOR_BLEND_2BIT (0 << 24) #define CURSOR_BLEND_R8G8B8A8 (1 << 24) @@ -269,17 +310,22 @@ #define DC_DISP_BLEND_BACKGROUND_COLOR 0x4E4 #define DC_WINC_COLOR_PALETTE 0x500 -#define DC_WINC_COLOR_PALETTE_IDX(off) (DC_WINC_COLOR_PALETTE + (off)) +#define COLOR_PALETTE_IDX(off) (DC_WINC_COLOR_PALETTE + (off)) +#define COLOR_PALETTE_RGB(rgb) (byte_swap_32(rgb) >> 8) #define DC_WINC_PALETTE_COLOR_EXT 0x600 -#define DC_WIN_CSC_YOF 0x611 -#define DC_WIN_CSC_KYRGB 0x612 -#define DC_WIN_CSC_KUR 0x613 -#define DC_WIN_CSC_KVR 0x614 -#define DC_WIN_CSC_KUG 0x615 -#define DC_WIN_CSC_KVG 0x616 -#define DC_WIN_CSC_KUB 0x617 -#define DC_WIN_CSC_KVB 0x618 +#define DC_WINC_H_FILTER_P(p) (0x601 + (p)) +#define DC_WINC_V_FILTER_P(p) (0x619 + (p)) +#define DC_WINC_H_FILTER_HI_P(p) (0x629 + (p)) + +#define DC_WINC_CSC_YOF 0x611 +#define DC_WINC_CSC_KYRGB 0x612 +#define DC_WINC_CSC_KUR 0x613 +#define DC_WINC_CSC_KVR 0x614 +#define DC_WINC_CSC_KUG 0x615 +#define DC_WINC_CSC_KVG 0x616 +#define DC_WINC_CSC_KUB 0x617 +#define DC_WINC_CSC_KVB 0x618 #define DC_WIN_AD_WIN_OPTIONS 0xB80 #define DC_WIN_BD_WIN_OPTIONS 0xD80 #define DC_WIN_CD_WIN_OPTIONS 0xF80 @@ -290,15 +336,17 @@ #define V_DIRECTION BIT(2) #define SCAN_COLUMN BIT(4) #define COLOR_EXPAND BIT(6) +#define H_FILTER_ENABLE BIT(8) +#define V_FILTER_ENABLE BIT(10) #define COLOR_PALETTE_ENABLE BIT(16) #define CSC_ENABLE BIT(18) +#define DV_ENABLE BIT(20) #define WIN_ENABLE BIT(30) +#define H_FILTER_EXPAND BIT(31) #define DC_WIN_BUFFER_CONTROL 0x702 #define BUFFER_CONTROL_HOST 0 #define BUFFER_CONTROL_VI 1 -#define BUFFER_CONTROL_EPP 2 -#define BUFFER_CONTROL_MPEGE 3 #define BUFFER_CONTROL_SB2D 4 #define DC_WIN_COLOR_DEPTH 0x703 @@ -324,6 +372,10 @@ #define WIN_COLOR_DEPTH_YUV422R 0x17 #define WIN_COLOR_DEPTH_YCbCr422RA 0x18 #define WIN_COLOR_DEPTH_YUV422RA 0x19 +#define WIN_COLOR_DEPTH_X1R5G5B5 0x1E +#define WIN_COLOR_DEPTH_R5G5B5X1 0x1F +#define WIN_COLOR_DEPTH_X1B5G5R5 0x20 +#define WIN_COLOR_DEPTH_B5G5R5X1 0x21 #define WIN_COLOR_DEPTH_YCbCr444P 0x29 #define WIN_COLOR_DEPTH_YCrCb420SP 0x2A #define WIN_COLOR_DEPTH_YCbCr420SP 0x2B @@ -338,33 +390,37 @@ #define WIN_COLOR_DEPTH_YUV444SP 0x3C #define DC_WIN_POSITION 0x704 -#define H_POSITION(x) (((x) & 0xffff) << 0) // Support negative. -#define V_POSITION(x) (((x) & 0xffff) << 16) // Support negative. +#define H_POSITION(x) (((x) & 0xFFFF) << 0) // Support negative. +#define V_POSITION(x) (((x) & 0xFFFF) << 16) // Support negative. #define DC_WIN_SIZE 0x705 -#define H_SIZE(x) (((x) & 0x1fff) << 0) -#define V_SIZE(x) (((x) & 0x1fff) << 16) +#define H_SIZE(x) (((x) & 0x1FFF) << 0) +#define V_SIZE(x) (((x) & 0x1FFF) << 16) #define DC_WIN_PRESCALED_SIZE 0x706 -#define H_PRESCALED_SIZE(x) (((x) & 0x7fff) << 0) -#define V_PRESCALED_SIZE(x) (((x) & 0x1fff) << 16) +#define H_PRESCALED_SIZE(x) (((x) & 0x7FFF) << 0) +#define V_PRESCALED_SIZE(x) (((x) & 0x1FFF) << 16) #define DC_WIN_H_INITIAL_DDA 0x707 #define DC_WIN_V_INITIAL_DDA 0x708 #define DC_WIN_DDA_INC 0x709 -#define H_DDA_INC(x) (((x) & 0xffff) << 0) -#define V_DDA_INC(x) (((x) & 0xffff) << 16) +#define H_DDA_INC(x) (((x) & 0xFFFF) << 0) +#define V_DDA_INC(x) (((x) & 0xFFFF) << 16) #define DC_WIN_LINE_STRIDE 0x70A #define LINE_STRIDE(x) (x) -#define UV_LINE_STRIDE(x) (((x) & 0xffff) << 16) +#define UV_LINE_STRIDE(x) (((x) & 0xFFFF) << 16) + #define DC_WIN_DV_CONTROL 0x70E +#define DV_CTRL_R(r) (((r) & 7) << 16) +#define DV_CTRL_G(g) (((g) & 7) << 8) +#define DV_CTRL_B(b) (((b) & 7) << 0) #define DC_WINBUF_BLEND_LAYER_CONTROL 0x716 -#define WIN_BLEND_DEPTH(x) (((x) & 0xff) << 0) -#define WIN_K1(x) (((x) & 0xff) << 8) -#define WIN_K2(x) (((x) & 0xff) << 16) +#define WIN_BLEND_DEPTH(x) (((x) & 0xFF) << 0) +#define WIN_K1(x) (((x) & 0xFF) << 8) +#define WIN_K2(x) (((x) & 0xFF) << 16) #define WIN_BLEND_ENABLE (0 << 24) #define WIN_BLEND_BYPASS (1 << 24) @@ -395,8 +451,8 @@ #define WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_K2 (3 << 12) #define DC_WINBUF_BLEND_ALPHA_1BIT 0x719 -#define WIN_ALPHA_1BIT_WEIGHT0(x) (((x) & 0xff) << 0) -#define WIN_ALPHA_1BIT_WEIGHT1(x) (((x) & 0xff) << 8) +#define WIN_ALPHA_1BIT_WEIGHT0(x) (((x) & 0xFF) << 0) +#define WIN_ALPHA_1BIT_WEIGHT1(x) (((x) & 0xFF) << 8) /*! The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). */ #define DC_WINBUF_START_ADDR 0x800 @@ -408,6 +464,8 @@ #define BLOCK (2 << 0) #define BLOCK_HEIGHT(x) (((x) & 0x7) << 4) +#define DC_WINBUF_MEMFETCH_CONTROL 0x82B + /*! Display serial interface registers. */ #define _DSIREG(reg) ((reg) * 4) @@ -486,8 +544,8 @@ #define DSI_PKT_LEN_2_3 0x35 #define DSI_PKT_LEN_4_5 0x36 #define DSI_PKT_LEN_6_7 0x37 -#define PKT0_LEN(x) (((x) & 0xffff) << 0) -#define PKT1_LEN(x) (((x) & 0xffff) << 16) +#define PKT0_LEN(x) (((x) & 0xFFFF) << 0) +#define PKT1_LEN(x) (((x) & 0xFFFF) << 16) #define DSI_PHY_TIMING_0 0x3C #define DSI_PHY_TIMING_1 0x3D @@ -495,20 +553,20 @@ #define DSI_BTA_TIMING 0x3F #define DSI_TIMEOUT_0 0x44 -#define DSI_TIMEOUT_HTX(x) (((x) & 0xffff) << 0) -#define DSI_TIMEOUT_LRX(x) (((x) & 0xffff) << 16) +#define DSI_TIMEOUT_HTX(x) (((x) & 0xFFFF) << 0) +#define DSI_TIMEOUT_LRX(x) (((x) & 0xFFFF) << 16) #define DSI_TIMEOUT_1 0x45 -#define DSI_TIMEOUT_TA(x) (((x) & 0xffff) << 0) -#define DSI_TIMEOUT_PR(x) (((x) & 0xffff) << 16) +#define DSI_TIMEOUT_TA(x) (((x) & 0xFFFF) << 0) +#define DSI_TIMEOUT_PR(x) (((x) & 0xFFFF) << 16) #define DSI_TO_TALLY 0x46 #define DSI_PAD_CONTROL_0 0x4B #define DSI_PAD_CONTROL_VS1_PDIO_CLK BIT(8) -#define DSI_PAD_CONTROL_VS1_PDIO(x) (((x) & 0xf) << 0) +#define DSI_PAD_CONTROL_VS1_PDIO(x) (((x) & 0xF) << 0) #define DSI_PAD_CONTROL_VS1_PULLDN_CLK BIT(24) -#define DSI_PAD_CONTROL_VS1_PULLDN(x) (((x) & 0xf) << 16) +#define DSI_PAD_CONTROL_VS1_PULLDN(x) (((x) & 0xF) << 16) #define DSI_PAD_CONTROL_CD 0x4C #define DSI_VIDEO_MODE_CONTROL 0x4E @@ -810,6 +868,12 @@ void display_wait_interrupt(u32 intr); u16 display_get_decoded_panel_id(); void display_set_decoded_panel_id(u32 id); +/*! MIPI DCS register management */ +int display_dsi_read(u8 cmd, u32 len, void *data); +int display_dsi_vblank_read(u8 cmd, u32 len, void *data); +void display_dsi_write(u8 cmd, u32 len, void *data); +void display_dsi_vblank_write(u8 cmd, u32 len, void *data); + /*! Show one single color on the display. */ void display_color_screen(u32 color); @@ -818,21 +882,22 @@ void display_backlight(bool enable); void display_backlight_brightness(u32 brightness, u32 step_delay); u32 display_get_backlight_brightness(); -/*! Init display in full 720x1280 resolution (B8G8R8A8, line stride 720, framebuffer size = 720*1280*4 bytes). */ -u32 *display_init_framebuffer_pitch(); -u32 *display_init_framebuffer_pitch_vic(); -u32 *display_init_framebuffer_pitch_inv(); -u32 *display_init_framebuffer_block(); -u32 *display_init_framebuffer_log(); -void display_activate_console(); -void display_deactivate_console(); -void display_init_cursor(void *crs_fb, u32 size); -void display_set_pos_cursor(u32 x, u32 y); -void display_deinit_cursor(); +u32 *display_init_window_a_pitch(); +u32 *display_init_window_a_pitch_vic(); +u32 *display_init_window_a_pitch_inv(); +u32 *display_init_window_a_block(); +u32 *display_init_window_d_console(); -int display_dsi_read(u8 cmd, u32 len, void *data); -int display_dsi_vblank_read(u8 cmd, u32 len, void *data); -void display_dsi_write(u8 cmd, u32 len, void *data); -void display_dsi_vblank_write(u8 cmd, u32 len, void *data); +void display_window_disable(u32 window); + +void display_set_framebuffer(u32 window, void *fb); +void display_move_framebuffer(u32 window, void *fb); + +void display_window_d_console_enable(); +void display_window_d_console_disable(); + +void display_cursor_init(void *crs_fb, u32 size); +void display_cursor_set_pos(u32 x, u32 y); +void display_cursor_deinit(); #endif diff --git a/bdk/display/di.inl b/bdk/display/di.inl index 61569a7..d74130e 100644 --- a/bdk/display/di.inl +++ b/bdk/display/di.inl @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert -* Copyright (c) 2018-2022 CTCaer +* Copyright (c) 2018-2024 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -16,37 +16,35 @@ */ // Display A config. -static const cfg_op_t _di_dc_setup_win_config[] = { - {DC_CMD_STATE_ACCESS, 0}, +static const reg_cfg_t _di_dc_setup_win_config[] = { + {DC_CMD_STATE_ACCESS, READ_MUX_ASSEMBLY | WRITE_MUX_ASSEMBLY}, {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, {DC_CMD_REG_ACT_CONTROL, WIN_A_ACT_HCNTR_SEL | WIN_B_ACT_HCNTR_SEL | WIN_C_ACT_HCNTR_SEL}, {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT}, {DC_DISP_DC_MCCIF_FIFOCTRL, 0}, {DC_DISP_DISP_MEM_HIGH_PRIORITY, 0}, {DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER, 0}, {DC_CMD_DISPLAY_POWER_CONTROL, PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | PW4_ENABLE | PM0_ENABLE | PM1_ENABLE}, {DC_CMD_GENERAL_INCR_SYNCPT_CNTRL, SYNCPT_CNTRL_NO_STALL}, {DC_CMD_CONT_SYNCPT_VSYNC, SYNCPT_VSYNC_ENABLE | SYNCPT_VSYNC_INDX(9)}, - {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE}, - {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ}, - {DC_CMD_STATE_ACCESS, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE | WIN_D_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ | WIN_D_ACT_REQ}, /* Setup Windows A/B/C */ - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT | WINDOW_D_SELECT}, {DC_WIN_WIN_OPTIONS, 0}, {DC_WIN_DV_CONTROL, 0}, /* Setup default YUV colorspace conversion coefficients */ - {DC_WIN_CSC_YOF, 0xF0}, - {DC_WIN_CSC_KYRGB, 0x12A}, - {DC_WIN_CSC_KUR, 0}, - {DC_WIN_CSC_KVR, 0x198}, - {DC_WIN_CSC_KUG, 0x39B}, - {DC_WIN_CSC_KVG, 0x32F}, - {DC_WIN_CSC_KUB, 0x204}, - {DC_WIN_CSC_KVB, 0}, + {DC_WINC_CSC_YOF, 0xF0}, + {DC_WINC_CSC_KYRGB, 0x12A}, + {DC_WINC_CSC_KUR, 0}, + {DC_WINC_CSC_KVR, 0x198}, + {DC_WINC_CSC_KUG, 0x39B}, + {DC_WINC_CSC_KVG, 0x32F}, + {DC_WINC_CSC_KUB, 0x204}, + {DC_WINC_CSC_KVB, 0}, /* End of color coefficients */ {DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888}, @@ -55,21 +53,18 @@ static const cfg_op_t _di_dc_setup_win_config[] = { {DC_COM_PIN_OUTPUT_POLARITY(3), 0}, {DC_DISP_BLEND_BACKGROUND_COLOR, 0}, {DC_COM_CRC_CONTROL, 0}, - {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE}, - {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE | WIN_D_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ | WIN_D_ACT_REQ}, {DC_WINBUF_BLEND_LAYER_CONTROL, WIN_BLEND_BYPASS | WIN_BLEND_DEPTH(255)}, {DC_CMD_DISPLAY_COMMAND_OPTION0, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, {DC_DISP_DISP_WIN_OPTIONS, 0}, {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_STOP}, - {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE}, - {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ} + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE | WIN_D_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ | WIN_D_ACT_REQ} }; // DSI Init config. -static const cfg_op_t _di_dsi_init_irq_pkt_config0[] = { +static const reg_cfg_t _di_dsi_seq_pkt_reset_config0[] = { {DSI_WR_DATA, 0}, {DSI_INT_ENABLE, 0}, {DSI_INT_STATUS, 0}, @@ -79,7 +74,7 @@ static const cfg_op_t _di_dsi_init_irq_pkt_config0[] = { {DSI_INIT_SEQ_DATA_2, 0}, {DSI_INIT_SEQ_DATA_3, 0} }; -static const cfg_op_t _di_dsi_init_irq_pkt_config1[] = { +static const reg_cfg_t _di_dsi_seq_pkt_reset_config1[] = { {DSI_DCS_CMDS, 0}, {DSI_PKT_SEQ_0_LO, 0}, {DSI_PKT_SEQ_1_LO, 0}, @@ -95,7 +90,7 @@ static const cfg_op_t _di_dsi_init_irq_pkt_config1[] = { {DSI_PKT_SEQ_5_HI, 0}, {DSI_CONTROL, 0} }; -static const cfg_op_t _di_dsi_init_pads_t210b01[] = { +static const reg_cfg_t _di_dsi_init_pads_t210b01[] = { {DSI_PAD_CONTROL_1, 0}, {DSI_PAD_CONTROL_2, 0}, {DSI_PAD_CONTROL_3, 0}, @@ -104,39 +99,47 @@ static const cfg_op_t _di_dsi_init_pads_t210b01[] = { {DSI_PAD_CONTROL_6_B01, 0}, {DSI_PAD_CONTROL_7_B01, 0} }; -static const cfg_op_t _di_dsi_init_timing_pkt_config2[] = { +static const reg_cfg_t _di_dsi_init_config[] = { {DSI_PAD_CONTROL_CD, 0}, {DSI_SOL_DELAY, 24}, {DSI_MAX_THRESHOLD, 480}, {DSI_TRIGGER, 0}, {DSI_INIT_SEQ_CONTROL, 0}, + {DSI_PKT_LEN_0_1, 0}, {DSI_PKT_LEN_2_3, 0}, {DSI_PKT_LEN_4_5, 0}, {DSI_PKT_LEN_6_7, 0}, - {DSI_PAD_CONTROL_1, 0} -}; -static const cfg_op_t _di_dsi_init_timing_pwrctrl_config[] = { + + {DSI_PAD_CONTROL_1, 0}, + + /* DSI PHY timings */ + {DSI_PHY_TIMING_0, 0x6070603}, {DSI_PHY_TIMING_1, 0x40A0E05}, {DSI_PHY_TIMING_2, 0x30109}, {DSI_BTA_TIMING, 0x190A14}, + /* DSI timeout */ {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)}, {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x765) | DSI_TIMEOUT_TA(0x2000)}, {DSI_TO_TALLY, 0}, - {DSI_PAD_CONTROL_0, DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0)}, // Enable + + {DSI_PAD_CONTROL_0, DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0)}, // Power up. {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, {DSI_POWER_CONTROL, 0}, {DSI_POWER_CONTROL, 0}, - {DSI_PAD_CONTROL_1, 0} -}; -static const cfg_op_t _di_dsi_init_timing_pkt_config3[] = { + {DSI_PAD_CONTROL_1, 0}, + + /* DSI PHY timings */ + {DSI_PHY_TIMING_0, 0x6070603}, {DSI_PHY_TIMING_1, 0x40A0E05}, {DSI_PHY_TIMING_2, 0x30118}, {DSI_BTA_TIMING, 0x190A14}, + /* DSI timeout */ {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)}, {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)}, {DSI_TO_TALLY, 0}, + {DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}, {DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE}, {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, @@ -148,7 +151,7 @@ static const cfg_op_t _di_dsi_init_timing_pkt_config3[] = { }; // DSI panel JDI config. -static const cfg_op_t _di_dsi_panel_init_config_jdi[] = { +static const reg_cfg_t _di_dsi_panel_init_config_jdi[] = { {DSI_WR_DATA, 0x0439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes. {DSI_WR_DATA, 0x9483FFB9}, // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94). {DSI_TRIGGER, DSI_TRIGGER_HOST}, @@ -195,13 +198,19 @@ static const cfg_op_t _di_dsi_panel_init_config_jdi[] = { }; // DSI packet config. -static const cfg_op_t _di_dsi_init_seq_pkt_final_config[] = { +static const reg_cfg_t _di_dsi_seq_pkt_video_non_burst_no_eot_config[] = { + {DSI_PAD_CONTROL_1, 0}, + + /* DSI PHY timings */ + {DSI_PHY_TIMING_0, 0x6070603}, {DSI_PHY_TIMING_1, 0x40A0E05}, {DSI_PHY_TIMING_2, 0x30172}, {DSI_BTA_TIMING, 0x190A14}, + /* DSI timeout */ {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xA40)}, {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x5A2F) | DSI_TIMEOUT_TA(0x2000)}, {DSI_TO_TALLY, 0}, + {DSI_PKT_SEQ_0_LO, 0x40000208}, {DSI_PKT_SEQ_2_LO, 0x40000308}, {DSI_PKT_SEQ_4_LO, 0x40000308}, @@ -218,7 +227,7 @@ static const cfg_op_t _di_dsi_init_seq_pkt_final_config[] = { }; // DSI mode config. -static const cfg_op_t _di_dsi_mode_config[] = { +static const reg_cfg_t _di_dsi_host_mode_config[] = { {DSI_TRIGGER, 0}, {DSI_CONTROL, 0}, {DSI_SOL_DELAY, 6}, @@ -232,7 +241,7 @@ static const cfg_op_t _di_dsi_mode_config[] = { }; // MIPI CAL config. -static const cfg_op_t _di_mipi_pad_cal_config[] = { +static const reg_cfg_t _di_mipi_pad_cal_config[] = { {MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0}, {MIPI_CAL_CIL_MIPI_CAL_STATUS, 0xF3F10000}, {MIPI_CAL_MIPI_BIAS_PAD_CFG0, 0}, @@ -240,13 +249,13 @@ static const cfg_op_t _di_mipi_pad_cal_config[] = { }; // DSI pad config. -static const cfg_op_t _di_dsi_pad_cal_config_t210[] = { +static const reg_cfg_t _di_dsi_pad_cal_config_t210[] = { {DSI_PAD_CONTROL_1, 0}, {DSI_PAD_CONTROL_2, 0}, {DSI_PAD_CONTROL_3, DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) | DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3)}, {DSI_PAD_CONTROL_4, 0} }; -static const cfg_op_t _di_dsi_pad_cal_config_t210b01[] = { +static const reg_cfg_t _di_dsi_pad_cal_config_t210b01[] = { {DSI_PAD_CONTROL_1, 0}, {DSI_PAD_CONTROL_2, 0}, {DSI_PAD_CONTROL_3, 0}, @@ -257,19 +266,19 @@ static const cfg_op_t _di_dsi_pad_cal_config_t210b01[] = { }; // MIPI CAL config. -static const cfg_op_t _di_mipi_dsi_cal_offsets_config_t210[] = { +static const reg_cfg_t _di_mipi_dsi_cal_prod_config_t210[] = { {MIPI_CAL_DSIA_MIPI_CAL_CONFIG, 0x200200}, {MIPI_CAL_DSIB_MIPI_CAL_CONFIG, 0x200200}, {MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2, 0x200002}, {MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0x200002} }; -static const cfg_op_t _di_mipi_dsi_cal_offsets_config_t210b01[] = { +static const reg_cfg_t _di_mipi_dsi_cal_prod_config_t210b01[] = { {MIPI_CAL_DSIA_MIPI_CAL_CONFIG, 0x200006}, {MIPI_CAL_DSIB_MIPI_CAL_CONFIG, 0x200006}, {MIPI_CAL_DSIA_MIPI_CAL_CONFIG_2, 0x260000}, {MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0x260000} }; -static const cfg_op_t _di_mipi_start_dsi_cal_config[] = { +static const reg_cfg_t _di_mipi_dsi_cal_unused_config[] = { {MIPI_CAL_CILA_MIPI_CAL_CONFIG, 0}, {MIPI_CAL_CILB_MIPI_CAL_CONFIG, 0}, {MIPI_CAL_CILC_MIPI_CAL_CONFIG, 0}, @@ -280,48 +289,11 @@ static const cfg_op_t _di_mipi_start_dsi_cal_config[] = { {MIPI_CAL_DSID_MIPI_CAL_CONFIG, 0}, {MIPI_CAL_DSIB_MIPI_CAL_CONFIG_2, 0}, {MIPI_CAL_DSIC_MIPI_CAL_CONFIG_2, 0}, - {MIPI_CAL_DSID_MIPI_CAL_CONFIG_2, 0}, - {MIPI_CAL_MIPI_CAL_CTRL, 0x2A000001} // Set Prescale and filter and start calibration. + {MIPI_CAL_DSID_MIPI_CAL_CONFIG_2, 0} }; // Display A enable config. -static const cfg_op_t _di_dc_video_enable_config[] = { - {DC_CMD_STATE_ACCESS, 0}, - - /* Setup Windows A/B/C */ - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_WIN_DV_CONTROL, 0}, - /* Setup default YUV colorspace conversion coefficients */ - {DC_WIN_CSC_YOF, 0xF0}, - {DC_WIN_CSC_KYRGB, 0x12A}, - {DC_WIN_CSC_KUR, 0}, - {DC_WIN_CSC_KVR, 0x198}, - {DC_WIN_CSC_KUG, 0x39B}, - {DC_WIN_CSC_KVG, 0x32F}, - {DC_WIN_CSC_KUB, 0x204}, - {DC_WIN_CSC_KVB, 0}, - /* End of color coefficients */ - - {DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888}, - {DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C}, - {DC_COM_PIN_OUTPUT_POLARITY(1), LSC0_OUTPUT_POLARITY_LOW}, - {DC_COM_PIN_OUTPUT_POLARITY(3), 0}, - {DC_DISP_BLEND_BACKGROUND_COLOR, 0}, - {DC_COM_CRC_CONTROL, 0}, - {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE}, - {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT}, - {DC_WINBUF_BLEND_LAYER_CONTROL, WIN_BLEND_BYPASS | WIN_BLEND_DEPTH(255)}, - {DC_CMD_DISPLAY_COMMAND_OPTION0, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_DISP_DISP_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_STOP}, - {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE}, - {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ}, - {DC_CMD_STATE_ACCESS, 0}, - +static const reg_cfg_t _di_dc_video_enable_config[] = { /* Set panel timings */ {DC_DISP_DISP_TIMING_OPTIONS, VSYNC_H_POSITION(0)}, {DC_DISP_REF_TO_SYNC, V_REF_TO_SYNC(1) | H_REF_TO_SYNC(0)}, @@ -334,59 +306,60 @@ static const cfg_op_t _di_dc_video_enable_config[] = { {DC_DISP_SHIFT_CLOCK_OPTIONS, SC1_H_QUALIFIER_NONE | SC0_H_QUALIFIER_NONE}, {DC_COM_PIN_OUTPUT_ENABLE(1), 0}, {DC_DISP_DATA_ENABLE_OPTIONS, DE_SELECT_ACTIVE | DE_CONTROL_NORMAL}, - {DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C}, {DC_DISP_DISP_CLOCK_CONTROL, 0}, - {DC_CMD_DISPLAY_COMMAND_OPTION0, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_DISP_DISP_WIN_OPTIONS, 0}, + + /* Start continuous display. */ {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, - {DC_CMD_STATE_ACCESS, READ_MUX | WRITE_MUX}, - {DC_DISP_FRONT_PORCH, V_FRONT_PORCH(10) | H_FRONT_PORCH(136)}, - {DC_CMD_STATE_ACCESS, 0}, {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, {DC_CMD_GENERAL_INCR_SYNCPT, SYNCPT_GENERAL_COND(COND_REG_WR_SAFE) | SYNCPT_GENERAL_INDX(1)}, + {DC_CMD_GENERAL_INCR_SYNCPT, SYNCPT_GENERAL_COND(COND_REG_WR_SAFE) | SYNCPT_GENERAL_INDX(1)}, {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, - {DC_CMD_STATE_ACCESS, 0}, - {DC_DISP_DISP_CLOCK_CONTROL, PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4)}, - {DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888}, - {DC_CMD_DISPLAY_COMMAND_OPTION0, 0} + + {DC_DISP_DISP_CLOCK_CONTROL, PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4)}, // 4: div3. }; // Display A disable config. -static const cfg_op_t _di_dc_video_disable_config[] = { - {DC_DISP_FRONT_PORCH, V_FRONT_PORCH(10) | H_FRONT_PORCH(136)}, +static const reg_cfg_t _di_dc_video_disable_config[] = { {DC_CMD_INT_MASK, 0}, - {DC_CMD_STATE_ACCESS, 0}, + {DC_CMD_STATE_ACCESS, READ_MUX_ASSEMBLY | WRITE_MUX_ASSEMBLY}, {DC_CMD_INT_ENABLE, 0}, {DC_CMD_CONT_SYNCPT_VSYNC, 0}, + + /* Stop display. */ {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_STOP}, {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_GENERAL_INCR_SYNCPT, SYNCPT_GENERAL_COND(COND_REG_WR_SAFE) | SYNCPT_GENERAL_INDX(1)}, {DC_CMD_GENERAL_INCR_SYNCPT, SYNCPT_GENERAL_COND(COND_REG_WR_SAFE) | SYNCPT_GENERAL_INDX(1)}, {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, - // LCD panels should sleep for 40ms here. + // TODO: LCD panels should sleep for 40ms here. {DC_CMD_DISPLAY_POWER_CONTROL, 0}, {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, }; // DSI deinit config. -static const cfg_op_t _di_dsi_timing_deinit_config[] = { +static const reg_cfg_t _di_dsi_timing_deinit_config[] = { {DSI_POWER_CONTROL, 0}, {DSI_PAD_CONTROL_1, 0}, - {DSI_PHY_TIMING_0, 0x6070601}, //mariko changes + + /* DSI PHY timings */ + {DSI_PHY_TIMING_0, 0x6070603}, {DSI_PHY_TIMING_1, 0x40A0E05}, {DSI_PHY_TIMING_2, 0x30118}, {DSI_BTA_TIMING, 0x190A14}, - {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF) }, + /* DSI timeout */ + {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)}, {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)}, {DSI_TO_TALLY, 0}, + {DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}, {DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE}, {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, @@ -397,7 +370,7 @@ static const cfg_op_t _di_dsi_timing_deinit_config[] = { }; // DSI panel JDI deinit config. -static const cfg_op_t _di_dsi_panel_deinit_config_jdi[] = { +static const reg_cfg_t _di_dsi_panel_deinit_config_jdi[] = { {DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes. {DSI_WR_DATA, 0x9483FFB9}, // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94). {DSI_TRIGGER, DSI_TRIGGER_HOST}, @@ -423,7 +396,7 @@ static const cfg_op_t _di_dsi_panel_deinit_config_jdi[] = { }; // DSI panel AUO deinit config. -static const cfg_op_t _di_dsi_panel_deinit_config_auo[] = { +static const reg_cfg_t _di_dsi_panel_deinit_config_auo[] = { {DSI_WR_DATA, 0x439}, // MIPI_DSI_DCS_LONG_WRITE: 4 bytes. {DSI_WR_DATA, 0x9483FFB9}, // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94). {DSI_TRIGGER, DSI_TRIGGER_HOST}, @@ -464,24 +437,24 @@ static const cfg_op_t _di_dsi_panel_deinit_config_auo[] = { {DSI_TRIGGER, DSI_TRIGGER_HOST} }; -static const cfg_op_t _di_init_config_invert[] = { +/* +static const reg_cfg_t _di_init_config_invert[] = { {DSI_WR_DATA, 0x239}, {DSI_WR_DATA, 0x02C1}, // INV_EN. {DSI_TRIGGER, DSI_TRIGGER_HOST}, }; +*/ // Display A Window A one color config. -static const cfg_op_t _di_win_one_color[] = { - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT}, +static const reg_cfg_t _di_win_one_color[] = { + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT | WINDOW_B_SELECT | WINDOW_C_SELECT | WINDOW_D_SELECT}, {DC_WIN_WIN_OPTIONS, 0}, {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY} // Continuous display. }; // Display A Window A linear pitch config. -static const cfg_op_t _di_win_framebuffer_pitch[] = { - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT | WINDOW_B_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, +static const reg_cfg_t _di_winA_pitch[] = { {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, {DC_WIN_WIN_OPTIONS, 0}, {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, @@ -500,14 +473,12 @@ static const cfg_op_t _di_win_framebuffer_pitch[] = { {DC_WINBUF_ADDR_V_OFFSET, 0}, {DC_WIN_WIN_OPTIONS, WIN_ENABLE}, // Enable window AD. {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, // Continuous display. - {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE}, {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ} }; // Display A Window A linear pitch + Win D support config. -static const cfg_op_t _di_win_framebuffer_pitch_vic[] = { - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT | WINDOW_C_SELECT | WINDOW_B_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, +static const reg_cfg_t _di_winA_pitch_vic[] = { {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, {DC_WIN_WIN_OPTIONS, 0}, {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, @@ -526,14 +497,12 @@ static const cfg_op_t _di_win_framebuffer_pitch_vic[] = { {DC_WINBUF_ADDR_V_OFFSET, 0}, {DC_WIN_WIN_OPTIONS, WIN_ENABLE}, // Enable window AD. {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, // Continuous display. - {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE}, {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ} }; // Display A Window A linear pitch inverse + Win D support config. -static const cfg_op_t _di_win_framebuffer_pitch_inv[] = { - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT | WINDOW_C_SELECT | WINDOW_B_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, +static const reg_cfg_t _di_winA_pitch_inv[] = { {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, {DC_WIN_WIN_OPTIONS, 0}, {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, @@ -552,14 +521,12 @@ static const cfg_op_t _di_win_framebuffer_pitch_inv[] = { {DC_WINBUF_ADDR_V_OFFSET, 1279}, // Linear: 1279, Block: 0. {DC_WIN_WIN_OPTIONS, WIN_ENABLE | V_DIRECTION}, // Enable window AD. {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, // Continuous display. - {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE}, {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ} }; // Display A Window A block linear config. -static const cfg_op_t _di_win_framebuffer_block[] = { - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT | WINDOW_C_SELECT | WINDOW_B_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, +static const reg_cfg_t _di_winA_block[] = { {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, {DC_WIN_WIN_OPTIONS, 0}, {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, @@ -578,12 +545,12 @@ static const cfg_op_t _di_win_framebuffer_block[] = { {DC_WINBUF_ADDR_V_OFFSET, 0}, // Linear: 1279, Block: 0. {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}, // Continuous display. - {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE}, {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ} }; // Display A Window D config. -static const cfg_op_t _di_win_framebuffer_log[] = { +static const reg_cfg_t _di_winD_log[] = { {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT}, {DC_WIN_WIN_OPTIONS, 0}, {DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, @@ -601,6 +568,6 @@ static const cfg_op_t _di_win_framebuffer_log[] = { {DC_WINBUF_ADDR_V_OFFSET, 0}, {DC_WINBUF_BLEND_LAYER_CONTROL, WIN_BLEND_ENABLE | WIN_K1(200) | WIN_BLEND_DEPTH(0)}, {DC_WINBUF_BLEND_MATCH_SELECT, WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1 | WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1}, - {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_D_UPDATE}, - {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_D_ACT_REQ} + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_D_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_D_ACT_REQ}, }; diff --git a/bdk/display/vic.c b/bdk/display/vic.c index c9a0c59..1044448 100644 --- a/bdk/display/vic.c +++ b/bdk/display/vic.c @@ -1,7 +1,7 @@ /* * VIC driver for Tegra X1 * - * Copyright (c) 2018-2023 CTCaer + * Copyright (c) 2018-2024 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -390,7 +390,7 @@ static int _vic_wait_idle() return 0; } -void vic_set_surface(vic_surface_t *sfc) +void vic_set_surface(const vic_surface_t *sfc) { u32 flip_x = 0; u32 flip_y = 0; @@ -406,6 +406,9 @@ void vic_set_surface(vic_surface_t *sfc) // Get format alpha type. switch (sfc->pix_fmt) { + case VIC_PIX_FORMAT_L8: + case VIC_PIX_FORMAT_X1B5G5R5: + case VIC_PIX_FORMAT_B5G5R5X1: case VIC_PIX_FORMAT_X8B8G8R8: case VIC_PIX_FORMAT_X8R8G8B8: case VIC_PIX_FORMAT_B8G8R8X8: @@ -536,14 +539,8 @@ int vic_compose() int vic_init() { - // Ease the stress to APB. - bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL); - clock_enable_vic(); - // Restore sys clock. - bpmp_clk_rate_set(prev_fid); - // Load Fetch Control Engine microcode. for (u32 i = 0; i < sizeof(vic_fce_ucode) / sizeof(u32); i++) { diff --git a/bdk/display/vic.h b/bdk/display/vic.h index 0014926..20fbe6c 100644 --- a/bdk/display/vic.h +++ b/bdk/display/vic.h @@ -33,6 +33,10 @@ typedef enum _vic_rotation_t typedef enum _vic_pix_format_t { + VIC_PIX_FORMAT_L8 = 1, // 8-bit LUT. + VIC_PIX_FORMAT_X1B5G5R5 = 21, // 16-bit XBGR. + VIC_PIX_FORMAT_B5G5R5X1 = 23, // 16-bit BGRX. + VIC_PIX_FORMAT_A8B8G8R8 = 31, // 32-bit ABGR. VIC_PIX_FORMAT_A8R8G8B8 = 32, // 32-bit ARGB. VIC_PIX_FORMAT_B8G8R8A8 = 33, // 32-bit BGRA. @@ -42,7 +46,6 @@ typedef enum _vic_pix_format_t VIC_PIX_FORMAT_X8R8G8B8 = 36, // 32-bit XRGB. VIC_PIX_FORMAT_B8G8R8X8 = 37, // 32-bit BGRX. VIC_PIX_FORMAT_R8G8B8X8 = 38, // 32-bit RGBX. - } vic_pix_format_t; typedef struct _vic_surface_t @@ -55,7 +58,7 @@ typedef struct _vic_surface_t u32 rotation; } vic_surface_t; -void vic_set_surface(vic_surface_t *sfc); +void vic_set_surface(const vic_surface_t *sfc); int vic_compose(); int vic_init(); void vic_end(); diff --git a/bdk/input/als.c b/bdk/input/als.c index 54e4464..acb0ac2 100644 --- a/bdk/input/als.c +++ b/bdk/input/als.c @@ -45,7 +45,7 @@ typedef struct _opt_win_cal_t } opt_win_cal_t; // Nintendo Switch Icosa/Iowa Optical Window calibration. -const opt_win_cal_t opt_win_cal_default[] = { +static const opt_win_cal_t opt_win_cal_default[] = { { 500, 5002, 7502 }, { 754, 2250, 2000 }, { 1029, 1999, 1667 }, @@ -54,14 +54,14 @@ const opt_win_cal_t opt_win_cal_default[] = { }; // Nintendo Switch Aula Optical Window calibration. -const opt_win_cal_t opt_win_cal_aula[] = { +static const opt_win_cal_t opt_win_cal_aula[] = { { 231, 9697, 30300 }, { 993, 3333, 2778 }, { 1478, 1621, 1053 }, { 7500, 81, 10 } }; -const u32 als_gain_idx_tbl[4] = { 1, 2, 64, 128 }; +static const u32 als_gain_idx_tbl[4] = { 1, 2, 64, 128 }; void set_als_cfg(als_ctxt_t *als_ctxt, u8 gain, u8 cycle) { diff --git a/bdk/input/joycon.c b/bdk/input/joycon.c index efdcd75..5e3243e 100644 --- a/bdk/input/joycon.c +++ b/bdk/input/joycon.c @@ -1,7 +1,7 @@ /* * Joy-Con UART driver for Nintendo Switch * - * Copyright (c) 2019-2023 CTCaer + * Copyright (c) 2019-2024 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -104,10 +103,10 @@ enum enum { JC_BATT_EMTPY = 0, - JC_BATT_CRIT = 2, - JC_BATT_LOW = 4, - JC_BATT_MID = 6, - JC_BATT_FULL = 8 + JC_BATT_CRIT = 1, + JC_BATT_LOW = 2, + JC_BATT_MID = 3, + JC_BATT_FULL = 4 }; static const u8 sio_init[] = { @@ -223,8 +222,8 @@ typedef struct _jc_hid_in_rpt_t { u8 cmd; u8 pkt_id; - u8 conn_info:4; - u8 batt_info:4; + u8 conn_info:4; // Connection detect. + u8 batt_info:4; // Power info. u8 btn_right; u8 btn_shared; u8 btn_left; @@ -234,7 +233,7 @@ typedef struct _jc_hid_in_rpt_t u8 stick_h_right; u8 stick_m_right; u8 stick_v_right; - u8 vib_decider; // right:8, left:8. (bit3 en, bit2-0 buffer avail). + u8 vib_decider; // right:4, left:4 (bit3 en, bit2-0 buffer avail). u8 submcd_ack; u8 subcmd; u8 subcmd_data[]; @@ -317,9 +316,10 @@ typedef struct _joycon_ctxt_t u8 uart; u8 type; u8 state; - u8 mac[6]; u32 last_received_time; u32 last_status_req_time; + u8 mac[6]; + u8 pkt_id; u8 rumble_sent; u8 connected; u8 detected; @@ -330,11 +330,10 @@ static joycon_ctxt_t jc_l = {0}; static joycon_ctxt_t jc_r = {0}; static bool jc_init_done = false; -static u32 hid_pkt_inc = 0; static jc_gamepad_rpt_t jc_gamepad; -static u8 _jc_crc(u8 *data, u16 len, u8 init) +static u8 _jc_crc(const u8 *data, u16 len, u8 init) { u8 crc = init; for (u16 i = 0; i < len; i++) @@ -407,12 +406,16 @@ static void _jc_detect() if (!jc_gamepad.sio_mode) { // Turn on Joy-Con detect. (UARTB/C TX). UART CTS also if HW flow control and irq is enabled. - PINMUX_AUX(PINMUX_AUX_UART2_TX) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE; - PINMUX_AUX(PINMUX_AUX_UART3_TX) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE; + PINMUX_AUX(PINMUX_AUX_UART2_TX) = PINMUX_INPUT_ENABLE; + PINMUX_AUX(PINMUX_AUX_UART3_TX) = PINMUX_INPUT_ENABLE; gpio_direction_input(GPIO_PORT_G, GPIO_PIN_0); gpio_direction_input(GPIO_PORT_D, GPIO_PIN_1); usleep(20); + //! HW BUG: Unlatch gpio buffer. + (void)gpio_read(GPIO_PORT_H, GPIO_PIN_6); + (void)gpio_read(GPIO_PORT_E, GPIO_PIN_6); + // Read H6/E6 which are shared with UART TX pins. jc_r.detected = !gpio_read(GPIO_PORT_H, GPIO_PIN_6); jc_l.detected = !gpio_read(GPIO_PORT_E, GPIO_PIN_6); @@ -444,7 +447,7 @@ static void _jc_conn_check() if (jc_l.connected) _jc_power_supply(UART_C, false); - hid_pkt_inc = 0; + jc_l.pkt_id = 0; jc_l.connected = false; jc_l.rumble_sent = false; @@ -461,7 +464,7 @@ static void _jc_conn_check() if (jc_r.connected) _jc_power_supply(UART_B, false); - hid_pkt_inc = 0; + jc_r.pkt_id = 0; jc_r.connected = false; jc_r.rumble_sent = false; @@ -480,7 +483,7 @@ static void _joycon_send_raw(u8 uart_port, const u8 *buf, u16 size) uart_wait_xfer(uart_port, UART_TX_IDLE); } -static u16 _jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, u16 size, bool crc) +static u16 _jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, const u8 *data, u16 size, bool crc) { out->uart_hdr.magic[0] = 0x19; out->uart_hdr.magic[1] = 0x01; @@ -500,7 +503,7 @@ static u16 _jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, return sizeof(jc_wired_hdr_t); } -static u16 _jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, u8 *payload, u16 size, bool crc) +static u16 _jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, const u8 *payload, u16 size, bool crc) { u16 pkt_size = _jc_packet_add_uart_hdr(rpt, JC_WIRED_HID, NULL, 0, crc); pkt_size += size; @@ -515,25 +518,21 @@ static u16 _jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, u8 *payload, u16 size, return pkt_size; } -static void _jc_send_hid_output_rpt(u8 uart, u8 *payload, u16 size, bool crc) +static void _jc_send_hid_output_rpt(joycon_ctxt_t *jc, jc_hid_out_rpt_t *hid_pkt, u16 size, bool crc) { u8 rpt[0x50]; memset(rpt, 0, sizeof(rpt)); - u32 rpt_size = _jc_hid_output_rpt_craft((jc_wired_hdr_t *)rpt, payload, size, crc); + hid_pkt->pkt_id = (jc->pkt_id++ & 0xF); + u32 rpt_size = _jc_hid_output_rpt_craft((jc_wired_hdr_t *)rpt, (u8 *)hid_pkt, size, crc); - _joycon_send_raw(uart, rpt, rpt_size); + _joycon_send_raw(jc->uart, rpt, rpt_size); } -static u8 _jc_hid_pkt_id_incr() +static void _jc_send_hid_cmd(joycon_ctxt_t *jc, u8 subcmd, const u8 *data, u16 size) { - return (hid_pkt_inc++ & 0xF); -} - -static void _jc_send_hid_cmd(u8 uart, u8 subcmd, u8 *data, u16 size) -{ - const u8 rumble_neutral[8] = { 0x00, 0x01, 0x40, 0x40, 0x00, 0x01, 0x40, 0x40 }; - const u8 rumble_init[8] = { 0xc2, 0xc8, 0x03, 0x72, 0xc2, 0xc8, 0x03, 0x72 }; + static const u8 rumble_neutral[8] = { 0x00, 0x01, 0x40, 0x40, 0x00, 0x01, 0x40, 0x40 }; + static const u8 rumble_init[8] = { 0xc2, 0xc8, 0x03, 0x72, 0xc2, 0xc8, 0x03, 0x72 }; u8 temp[0x30] = {0}; @@ -547,47 +546,43 @@ static void _jc_send_hid_cmd(u8 uart, u8 subcmd, u8 *data, u16 size) // Enable rumble. hid_pkt->cmd = JC_HID_OUTPUT_RPT; - hid_pkt->pkt_id = _jc_hid_pkt_id_incr(); hid_pkt->subcmd = JC_HID_SUBCMD_RUMBLE_CTL; hid_pkt->subcmd_data[0] = 1; if (send_r_rumble) - _jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10, false); + _jc_send_hid_output_rpt(&jc_r, hid_pkt, 0x10, false); if (send_l_rumble) - _jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10, false); + _jc_send_hid_output_rpt(&jc_l, hid_pkt, 0x10, false); // Send rumble. - hid_pkt->cmd = JC_HID_RUMBLE_RPT; - hid_pkt->pkt_id = _jc_hid_pkt_id_incr(); + hid_pkt->cmd = JC_HID_RUMBLE_RPT; memcpy(hid_pkt->rumble, rumble_init, sizeof(rumble_init)); if (send_r_rumble) - _jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 10, false); + _jc_send_hid_output_rpt(&jc_r, hid_pkt, 10, false); if (send_l_rumble) - _jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 10, false); + _jc_send_hid_output_rpt(&jc_l, hid_pkt, 10, false); msleep(15); // Disable rumble. hid_pkt->cmd = JC_HID_OUTPUT_RPT; - hid_pkt->pkt_id = _jc_hid_pkt_id_incr(); hid_pkt->subcmd = JC_HID_SUBCMD_RUMBLE_CTL; hid_pkt->subcmd_data[0] = 0; memcpy(hid_pkt->rumble, rumble_neutral, sizeof(rumble_neutral)); if (send_r_rumble) - _jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10, false); + _jc_send_hid_output_rpt(&jc_r, hid_pkt, 0x10, false); if (send_l_rumble) - _jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10, false); + _jc_send_hid_output_rpt(&jc_l, hid_pkt, 0x10, false); } else { - bool crc_needed = (jc_l.uart == uart) ? (jc_l.type & JC_ID_HORI) : (jc_r.type & JC_ID_HORI); + bool crc_needed = jc->type & JC_ID_HORI; hid_pkt->cmd = JC_HID_OUTPUT_RPT; - hid_pkt->pkt_id = _jc_hid_pkt_id_incr(); hid_pkt->subcmd = subcmd; if (data) memcpy(hid_pkt->subcmd_data, data, size); - _jc_send_hid_output_rpt(uart, (u8 *)hid_pkt, sizeof(jc_hid_out_rpt_t) + size, crc_needed); + _jc_send_hid_output_rpt(jc, hid_pkt, sizeof(jc_hid_out_rpt_t) + size, crc_needed); } } @@ -596,13 +591,13 @@ static void _jc_charging_decider(u8 batt, u8 uart) u32 system_batt_enough = max17050_get_cached_batt_volt() > 4000; // Power supply control based on battery levels and charging. - if ((batt >> 1 << 1) < JC_BATT_LOW) // Level without checking charging. + if ((batt >> 1) < JC_BATT_LOW) // Level without checking charging. _jc_power_supply(uart, true); - else if (batt > (system_batt_enough ? JC_BATT_FULL : JC_BATT_MID)) // Addresses the charging bit. + else if (batt > (system_batt_enough ? JC_BATT_FULL : JC_BATT_MID) << 1) // Addresses the charging bit. _jc_power_supply(uart, false); } -static void _jc_parse_wired_hid(joycon_ctxt_t *jc, const u8* packet, u32 size) +static void _jc_parse_wired_hid(joycon_ctxt_t *jc, const u8 *packet, int size) { u32 btn_tmp; jc_hid_in_rpt_t *hid_pkt = (jc_hid_in_rpt_t *)packet; @@ -610,7 +605,14 @@ static void _jc_parse_wired_hid(joycon_ctxt_t *jc, const u8* packet, u32 size) switch (hid_pkt->cmd) { case JC_HORI_INPUT_RPT: + if (!(jc->type & JC_ID_HORI)) + return; + case JC_HID_INPUT_RPT: + // Discard incomplete hid packets. + if (size < 12) + break; + btn_tmp = hid_pkt->btn_right | hid_pkt->btn_shared << 8 | hid_pkt->btn_left << 16; if (jc->type & JC_ID_L) @@ -670,8 +672,12 @@ static void _jc_parse_wired_hid(joycon_ctxt_t *jc, const u8* packet, u32 size) } } -static void _jc_parse_wired_init(joycon_ctxt_t *jc, const u8* data, u32 size) +static void _jc_parse_wired_init(joycon_ctxt_t *jc, const u8 *data, int size) { + // Discard empty packets. + if (size <= 0) + return; + switch (data[0]) { case JC_WIRED_CMD_GET_INFO: @@ -694,13 +700,13 @@ static void _jc_parse_wired_init(joycon_ctxt_t *jc, const u8* data, u32 size) } } -static void _jc_uart_pkt_parse(joycon_ctxt_t *jc, const jc_wired_hdr_t *pkt, size_t size) +static void _jc_uart_pkt_parse(joycon_ctxt_t *jc, const jc_wired_hdr_t *pkt, int size) { switch (pkt->cmd) { case JC_HORI_INPUT_RPT_CMD: case JC_WIRED_HID: - _jc_parse_wired_hid(jc, pkt->payload, (pkt->data[0] << 8) | pkt->data[1]); + _jc_parse_wired_hid(jc, pkt->payload, size - sizeof(jc_wired_hdr_t)); break; case JC_WIRED_INIT_REPLY: _jc_parse_wired_init(jc, pkt->data, size - sizeof(jc_uart_hdr_t) - 1); @@ -715,11 +721,15 @@ static void _jc_uart_pkt_parse(joycon_ctxt_t *jc, const jc_wired_hdr_t *pkt, siz jc->last_received_time = get_tmr_ms(); } -static void _jc_sio_parse_payload(joycon_ctxt_t *jc, u8 cmd, const u8* payload, u32 size) +static void _jc_sio_parse_payload(joycon_ctxt_t *jc, u8 cmd, const u8 *payload, int size) { switch (cmd) { case JC_SIO_CMD_STATUS: + // Discard incomplete packets. + if (size < 12) + break; + jc_sio_hid_in_rpt_t *hid_pkt = (jc_sio_hid_in_rpt_t *)payload; jc_gamepad.buttons = hid_pkt->btn_right | hid_pkt->btn_shared << 8 | hid_pkt->btn_left << 16; jc_gamepad.home = !gpio_read(GPIO_PORT_V, GPIO_PIN_3); @@ -740,7 +750,7 @@ static void _jc_sio_parse_payload(joycon_ctxt_t *jc, u8 cmd, const u8* payload, } } -static void _jc_sio_uart_pkt_parse(joycon_ctxt_t *jc, const jc_sio_in_rpt_t *pkt, u32 size) +static void _jc_sio_uart_pkt_parse(joycon_ctxt_t *jc, const jc_sio_in_rpt_t *pkt, int size) { if (pkt->crc_hdr != _jc_crc((u8 *)pkt, sizeof(jc_sio_in_rpt_t) - 1, 0)) return; @@ -757,7 +767,7 @@ static void _jc_sio_uart_pkt_parse(joycon_ctxt_t *jc, const jc_sio_in_rpt_t *pkt break; case JC_SIO_CMD_IAP_VER: case JC_SIO_CMD_STATUS: - _jc_sio_parse_payload(jc, cmd, pkt->payload, pkt->payload_size); + _jc_sio_parse_payload(jc, cmd, pkt->payload, size - sizeof(jc_sio_in_rpt_t)); break; case JC_SIO_CMD_UNK02: case JC_SIO_CMD_UNK20: @@ -784,7 +794,7 @@ static void _jc_rcv_pkt(joycon_ctxt_t *jc) jc_wired_hdr_t *jc_pkt = (jc_wired_hdr_t *)jc->buf; if (!jc->sio_mode && !memcmp(jc_pkt->uart_hdr.magic, "\x19\x81\x03", 3)) { - _jc_uart_pkt_parse(jc, jc_pkt, jc_pkt->uart_hdr.total_size_lsb + sizeof(jc_uart_hdr_t)); + _jc_uart_pkt_parse(jc, jc_pkt, len); return; } @@ -793,7 +803,7 @@ static void _jc_rcv_pkt(joycon_ctxt_t *jc) jc_sio_in_rpt_t *sio_pkt = (jc_sio_in_rpt_t *)(jc->buf); if (jc->sio_mode && sio_pkt->cmd == JC_SIO_INPUT_RPT && (sio_pkt->ack & JC_SIO_CMD_ACK) == JC_SIO_CMD_ACK) { - _jc_sio_uart_pkt_parse(jc, sio_pkt, sio_pkt->payload_size + sizeof(jc_sio_in_rpt_t)); + _jc_sio_uart_pkt_parse(jc, sio_pkt, len); return; } @@ -804,7 +814,7 @@ static bool _jc_send_init_rumble(joycon_ctxt_t *jc) // Send init rumble or request nx pad status report. if ((jc_r.connected && !jc_r.rumble_sent) || (jc_l.connected && !jc_l.rumble_sent)) { - _jc_send_hid_cmd(jc->uart, JC_HID_SUBCMD_SND_RUMBLE, NULL, 0); + _jc_send_hid_cmd(jc, JC_HID_SUBCMD_SND_RUMBLE, NULL, 0); if (jc_l.connected) jc_l.rumble_sent = true; @@ -842,10 +852,10 @@ static void _jc_req_nx_pad_status(joycon_ctxt_t *jc) else _joycon_send_raw(jc->uart, hori_pad_status, sizeof(hori_pad_status)); - jc->last_status_req_time = get_tmr_ms() + 15; + jc->last_status_req_time = get_tmr_ms() + (!jc->sio_mode ? 15 : 7); } -static bool _jc_validate_pairing_info(u8 *buf, bool *is_hos) +static bool _jc_validate_pairing_info(const u8 *buf, bool *is_hos) { u8 crc = 0; for (u32 i = 0; i < 0x22; i++) @@ -914,13 +924,13 @@ retry: { if (!jc_l_found) { - _jc_send_hid_cmd(jc_l.uart, JC_HID_SUBCMD_SPI_READ, (u8 *)&subcmd_data_l, 5); + _jc_send_hid_cmd(&jc_l, JC_HID_SUBCMD_SPI_READ, (u8 *)&subcmd_data_l, 5); jc_l.last_status_req_time = get_tmr_ms() + 15; } if (!jc_r_found) { - _jc_send_hid_cmd(jc_r.uart, JC_HID_SUBCMD_SPI_READ, (u8 *)&subcmd_data_r, 5); + _jc_send_hid_cmd(&jc_r, JC_HID_SUBCMD_SPI_READ, (u8 *)&subcmd_data_r, 5); jc_r.last_status_req_time = get_tmr_ms() + 15; } @@ -1111,7 +1121,7 @@ static void _jc_init_conn(joycon_ctxt_t *jc) // Initialize the controller. u32 retries = 10; - while (!jc->connected) + while (!jc->connected && retries) { _joycon_send_raw(jc->uart, sio_init, sizeof(sio_init)); msleep(5); @@ -1196,17 +1206,11 @@ void jc_init_hw() pinmux_config_uart(UART_B); pinmux_config_uart(UART_C); - // Ease the stress to APB. - bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL); - // Enable UART B and C clocks. if (!jc_gamepad.sio_mode) clock_enable_uart(UART_B); clock_enable_uart(UART_C); - // Restore OC. - bpmp_clk_rate_set(prev_fid); - jc_init_done = true; #endif } @@ -1226,12 +1230,12 @@ void jc_deinit() u8 data = HCI_STATE_SLEEP; if (jc_r.connected && !(jc_r.type & JC_ID_HORI)) { - _jc_send_hid_cmd(UART_B, JC_HID_SUBCMD_HCI_STATE, &data, 1); + _jc_send_hid_cmd(&jc_r, JC_HID_SUBCMD_HCI_STATE, &data, 1); _jc_rcv_pkt(&jc_r); } if (jc_l.connected && !(jc_l.type & JC_ID_HORI)) { - _jc_send_hid_cmd(UART_C, JC_HID_SUBCMD_HCI_STATE, &data, 1); + _jc_send_hid_cmd(&jc_l, JC_HID_SUBCMD_HCI_STATE, &data, 1); _jc_rcv_pkt(&jc_l); } } diff --git a/bdk/input/joycon.h b/bdk/input/joycon.h index af0a849..fbb789f 100644 --- a/bdk/input/joycon.h +++ b/bdk/input/joycon.h @@ -43,34 +43,34 @@ typedef struct _jc_gamepad_rpt_t struct { // Joy-Con (R). - u32 y:1; - u32 x:1; - u32 b:1; - u32 a:1; - u32 sr_r:1; - u32 sl_r:1; - u32 r:1; - u32 zr:1; +/*00*/ u32 y:1; +/*01*/ u32 x:1; +/*02*/ u32 b:1; +/*03*/ u32 a:1; +/*04*/ u32 sr_r:1; +/*05*/ u32 sl_r:1; +/*06*/ u32 r:1; +/*07*/ u32 zr:1; // Shared - u32 minus:1; - u32 plus:1; - u32 r3:1; - u32 l3:1; - u32 home:1; - u32 cap:1; - u32 pad:1; - u32 wired:1; +/*08*/ u32 minus:1; +/*09*/ u32 plus:1; +/*10*/ u32 r3:1; +/*11*/ u32 l3:1; +/*12*/ u32 home:1; +/*13*/ u32 cap:1; +/*14*/ u32 pad:1; +/*15*/ u32 wired:1; // Joy-Con (L). - u32 down:1; - u32 up:1; - u32 right:1; - u32 left:1; - u32 sr_l:1; - u32 sl_l:1; - u32 l:1; - u32 zl:1; +/*16*/ u32 down:1; +/*17*/ u32 up:1; +/*18*/ u32 right:1; +/*19*/ u32 left:1; +/*20*/ u32 sr_l:1; +/*21*/ u32 sl_l:1; +/*22*/ u32 l:1; +/*23*/ u32 zl:1; }; u32 buttons; }; @@ -105,4 +105,4 @@ void jc_deinit(); jc_gamepad_rpt_t *joycon_poll(); jc_gamepad_rpt_t *jc_get_bt_pairing_info(bool *is_l_hos, bool *is_r_hos); -#endif \ No newline at end of file +#endif diff --git a/bdk/libs/compr/blz.c b/bdk/libs/compr/blz.c index 685ef4a..5bc9e49 100644 --- a/bdk/libs/compr/blz.c +++ b/bdk/libs/compr/blz.c @@ -20,33 +20,33 @@ #include "blz.h" -const blz_footer *blz_get_footer(const unsigned char *compData, unsigned int compDataLen, blz_footer *outFooter) +const blz_footer *blz_get_footer(const u8 *comp_data, u32 comp_data_size, blz_footer *out_footer) { - if (compDataLen < sizeof(blz_footer)) + if (comp_data_size < sizeof(blz_footer)) return NULL; - const blz_footer *srcFooter = (const blz_footer*)&compData[compDataLen - sizeof(blz_footer)]; - if (outFooter != NULL) - memcpy(outFooter, srcFooter, sizeof(blz_footer)); // Must be a memcpy because no umaligned accesses on ARMv4. + const blz_footer *src_footer = (const blz_footer *)&comp_data[comp_data_size - sizeof(blz_footer)]; + if (out_footer) + memcpy(out_footer, src_footer, sizeof(blz_footer)); // Must be a memcpy because no unaligned accesses on ARMv4. - return srcFooter; + return src_footer; } // From https://github.com/SciresM/hactool/blob/master/kip.c which is exactly how kernel does it, thanks SciresM! -int blz_uncompress_inplace(unsigned char *dataBuf, unsigned int compSize, const blz_footer *footer) +int blz_uncompress_inplace(u8 *data, u32 comp_size, const blz_footer *footer) { u32 addl_size = footer->addl_size; u32 header_size = footer->header_size; u32 cmp_and_hdr_size = footer->cmp_and_hdr_size; - unsigned char* cmp_start = &dataBuf[compSize] - cmp_and_hdr_size; + u8 *cmp_start = &data[comp_size] - cmp_and_hdr_size; u32 cmp_ofs = cmp_and_hdr_size - header_size; u32 out_ofs = cmp_and_hdr_size + addl_size; while (out_ofs) { - unsigned char control = cmp_start[--cmp_ofs]; - for (unsigned int i=0; i<8; i++) + u8 control = cmp_start[--cmp_ofs]; + for (u32 i = 0; i < 8; i++) { if (control & 0x80) { @@ -54,45 +54,48 @@ int blz_uncompress_inplace(unsigned char *dataBuf, unsigned int compSize, const return 0; // Out of bounds. cmp_ofs -= 2; - u16 seg_val = ((unsigned int)(cmp_start[cmp_ofs + 1]) << 8) | cmp_start[cmp_ofs]; + u16 seg_val = ((u32)(cmp_start[cmp_ofs + 1]) << 8) | cmp_start[cmp_ofs]; u32 seg_size = ((seg_val >> 12) & 0xF) + 3; u32 seg_ofs = (seg_val & 0x0FFF) + 3; - if (out_ofs < seg_size) // Kernel restricts segment copy to stay in bounds. + + // Kernel restricts segment copy to stay in bounds. + if (out_ofs < seg_size) seg_size = out_ofs; out_ofs -= seg_size; - for (unsigned int j = 0; j < seg_size; j++) + for (u32 j = 0; j < seg_size; j++) cmp_start[out_ofs + j] = cmp_start[out_ofs + j + seg_ofs]; } - else + else // Copy directly. { - // Copy directly. if (cmp_ofs < 1) - return 0; //out of bounds + return 0; // Out of bounds. cmp_start[--out_ofs] = cmp_start[--cmp_ofs]; } + control <<= 1; - if (out_ofs == 0) // Blz works backwards, so if it reaches byte 0, it's done. + + if (!out_ofs) // Blz works backwards, so if it reaches byte 0, it's done. return 1; - } } + } return 1; } -int blz_uncompress_srcdest(const unsigned char *compData, unsigned int compDataLen, unsigned char *dstData, unsigned int dstSize) +int blz_uncompress_srcdest(const u8 *comp_data, u32 comp_data_size, u8 *dst_data, u32 dst_size) { blz_footer footer; - const blz_footer *compFooterPtr = blz_get_footer(compData, compDataLen, &footer); - if (compFooterPtr == NULL) + const blz_footer *comp_footer = blz_get_footer(comp_data, comp_data_size, &footer); + if (!comp_footer) return 0; - // Decompression must be done in-place, so need to copy the relevant compressed data first. - unsigned int numCompBytes = (const unsigned char*)(compFooterPtr)-compData; - memcpy(dstData, compData, numCompBytes); - memset(&dstData[numCompBytes], 0, dstSize - numCompBytes); + // Decompression happens in-place, so need to copy the relevant compressed data first. + u32 comp_bytes = (const u8 *)comp_footer - comp_data; + memcpy(dst_data, comp_data, comp_bytes); + memset(&dst_data[comp_bytes], 0, dst_size - comp_bytes); - return blz_uncompress_inplace(dstData, compDataLen, &footer); + return blz_uncompress_inplace(dst_data, comp_data_size, &footer); } diff --git a/bdk/libs/compr/blz.h b/bdk/libs/compr/blz.h index a1cce37..bb058d8 100644 --- a/bdk/libs/compr/blz.h +++ b/bdk/libs/compr/blz.h @@ -26,11 +26,11 @@ typedef struct _blz_footer u32 addl_size; } blz_footer; -// Returns pointer to footer in compData if present, additionally copies it to outFooter if not NULL. -const blz_footer *blz_get_footer(const unsigned char *compData, unsigned int compDataLen, blz_footer *outFooter); +// Returns pointer to footer in comp_data if present, additionally copies it to out_footer if not NULL. +const blz_footer *blz_get_footer(const u8 *comp_data, u32 comp_data_size, blz_footer *out_footer); // Returns 0 on failure. -int blz_uncompress_inplace(unsigned char *dataBuf, unsigned int compSize, const blz_footer *footer); +int blz_uncompress_inplace(u8 *data, u32 comp_size, const blz_footer *footer); // Returns 0 on failure. -int blz_uncompress_srcdest(const unsigned char *compData, unsigned int compDataLen, unsigned char *dstData, unsigned int dstSize); +int blz_uncompress_srcdest(const u8 *comp_data, u32 comp_data_size, u8 *dst_data, u32 dst_size); #endif diff --git a/bdk/libs/compr/lz4.c b/bdk/libs/compr/lz4.c index 689c4d1..d6c22c6 100644 --- a/bdk/libs/compr/lz4.c +++ b/bdk/libs/compr/lz4.c @@ -92,16 +92,6 @@ # define LZ4_FORCE_O2_INLINE_GCC_PPC64LE static #endif -#if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__) -# define expect(expr,value) (__builtin_expect ((expr),(value)) ) -#else -# define expect(expr,value) (expr) -#endif - -#define likely(expr) expect((expr) != 0, 1) -#define unlikely(expr) expect((expr) != 0, 0) - - /*-************************************ * Memory routines **************************************/ diff --git a/bdk/libs/fatfs/ff.c b/bdk/libs/fatfs/ff.c index b9f5851..7f85de7 100644 --- a/bdk/libs/fatfs/ff.c +++ b/bdk/libs/fatfs/ff.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2021 CTCaer + * Copyright (c) 2018-2022 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/bdk/libs/fatfs/ff.h b/bdk/libs/fatfs/ff.h index cb4e97e..9c2f9c3 100644 --- a/bdk/libs/fatfs/ff.h +++ b/bdk/libs/fatfs/ff.h @@ -292,7 +292,7 @@ FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt); /* Allocate a contiguous FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */ FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */ FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */ -FRESULT f_fdisk_mod (BYTE pdrv, const DWORD* szt, void* work); // Modded version of f_fdisk that works:tm: +FRESULT f_fdisk_mod (BYTE pdrv, const DWORD* szt, void* work); /* Modded version of f_fdisk that works:tm: */ FRESULT f_setcp (WORD cp); /* Set current code page */ int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */ int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ diff --git a/bdk/libs/lv_conf.h b/bdk/libs/lv_conf.h index 404f920..89dc555 100644 --- a/bdk/libs/lv_conf.h +++ b/bdk/libs/lv_conf.h @@ -126,7 +126,7 @@ #define LV_COLOR_TRANSP LV_COLOR_LIME /*Images pixels with this color will not be drawn (with chroma keying)*/ /*Text settings*/ -#define LV_TXT_UTF8 1 /*Enable UTF-8 coded Unicode character usage */ +#define LV_TXT_UTF8 0 /*Enable UTF-8 coded Unicode character usage */ #define LV_TXT_BREAK_CHARS " ,.;:-_" /*Can break texts on these chars*/ #define LV_TXT_LINE_BREAK_LONG_LEN 12 /* If a character is at least this long, will break wherever "prettiest" */ #define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3 /* Minimum number of characters of a word to put on a line before a break */ diff --git a/bdk/mem/emc.h b/bdk/mem/emc.h index 24266e2..a1b4c3a 100644 --- a/bdk/mem/emc.h +++ b/bdk/mem/emc.h @@ -2,7 +2,7 @@ * arch/arm/mach-tegra/tegra21_emc.h * * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. - * Copyright (c) 2019-2020, CTCaer. + * Copyright (c) 2019-2024, CTCaer. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,6 +23,7 @@ #ifndef _EMC_H_ #define _EMC_H_ +#define EMC_INTSTATUS 0x0 #define EMC_DBG 0x8 #define EMC_CFG 0xC #define EMC_CONFIG_SAMPLE_DELAY 0x5f0 diff --git a/bdk/mem/minerva.h b/bdk/mem/minerva.h index de32c78..e78bb41 100644 --- a/bdk/mem/minerva.h +++ b/bdk/mem/minerva.h @@ -38,7 +38,7 @@ typedef struct bool emc_2X_clk_src_is_pllmb; bool fsp_for_src_freq; bool train_ram_patterns; - bool init_done; + u32 init_done; } mtc_config_t; enum train_mode_t diff --git a/bdk/mem/sdram.c b/bdk/mem/sdram.c index 868387a..4aa98fa 100644 --- a/bdk/mem/sdram.c +++ b/bdk/mem/sdram.c @@ -34,8 +34,6 @@ #include #include -#define CONFIG_SDRAM_KEEP_ALIVE - #define DRAM_ID(x) BIT(x) #define DRAM_CC(x) BIT(x) @@ -184,16 +182,68 @@ emc_mr_data_t sdram_read_mrx(emc_mr_t mrx) return data; } +void sdram_src_pllc(bool enable) +{ + static bool enabled = false; + + if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210 || enable == enabled) + return; + + enabled = enable; + + // Clear CC interrupt. + EMC(EMC_INTSTATUS) = BIT(4); + (void)EMC(EMC_INTSTATUS); + + u32 clk_src_emc = _dram_cfg_08_10_12_14_samsung_hynix_4gb.emc_clock_source; + + if (enable) + { + // Check if clock source is not the expected one. + if (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) != clk_src_emc) + return; + + // Set source as PLLC_OUT0. + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = 0x20188004; + } + else + { + // Restore MC/EMC clock. + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = clk_src_emc; + } + + // Wait for CC interrupt. + while (!(EMC(EMC_INTSTATUS) & BIT(4))) + usleep(1); +} + static void _sdram_config_t210(const sdram_params_t210_t *params) { + // VDDP Select. + PMC(APBDEV_PMC_VDDP_SEL) = params->pmc_vddp_sel; + usleep(params->pmc_vddp_sel_wait); + + // Set DDR pad voltage. + PMC(APBDEV_PMC_DDR_PWR) = PMC(APBDEV_PMC_DDR_PWR); // Normally params->pmc_ddr_pwr. + + // Turn on MEM IO Power. + PMC(APBDEV_PMC_NO_IOPOWER) &= PMC_NO_IOPOWER_SDMMC1; // Only keep SDMMC1 state. (Was params->pmc_no_io_power). + PMC(APBDEV_PMC_REG_SHORT) = params->pmc_reg_short; + + PMC(APBDEV_PMC_DDR_CNTRL) = params->pmc_ddr_ctrl; + + // Patch 1 using BCT spare variables + if (params->emc_bct_spare0) + *(vu32 *)params->emc_bct_spare0 = params->emc_bct_spare1; + // Program DPD3/DPD4 regs (coldboot path). // Enable sel_dpd on unused pins. - u32 dpd_req = (params->emc_pmc_scratch1 & 0x3FFFFFFF) | (2 << 30u); + u32 dpd_req = (params->emc_pmc_scratch1 & 0x3FFFFFFF) | PMC_IO_DPD_REQ_DPD_ON; PMC(APBDEV_PMC_IO_DPD3_REQ) = (dpd_req ^ 0xFFFF) & 0xC000FFFF; usleep(params->pmc_io_dpd3_req_wait); // Disable e_dpd_vttgen. - dpd_req = (params->emc_pmc_scratch2 & 0x3FFFFFFF) | (2 << 30u); + dpd_req = (params->emc_pmc_scratch2 & 0x3FFFFFFF) | PMC_IO_DPD_REQ_DPD_ON; PMC(APBDEV_PMC_IO_DPD4_REQ) = (dpd_req & 0xFFFF0000) ^ 0x3FFF0000; usleep(params->pmc_io_dpd4_req_wait); @@ -204,28 +254,24 @@ static void _sdram_config_t210(const sdram_params_t210_t *params) PMC(APBDEV_PMC_WEAK_BIAS) = 0; usleep(1); - // Start clocks. + // Start PLLM. CLOCK(CLK_RST_CONTROLLER_PLLM_MISC1) = params->pllm_setup_control; CLOCK(CLK_RST_CONTROLLER_PLLM_MISC2) = 0; -#ifdef CONFIG_SDRAM_KEEP_ALIVE - CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) = - (params->pllm_feedback_divider << 8) | params->pllm_input_divider | ((params->pllm_post_divider & 0xFFFF) << 20) | PLLCX_BASE_ENABLE; -#else u32 pllm_div = (params->pllm_feedback_divider << 8) | params->pllm_input_divider | ((params->pllm_post_divider & 0xFFFF) << 20); CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) = pllm_div; CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) = pllm_div | PLLCX_BASE_ENABLE; -#endif u32 wait_end = get_tmr_us() + 300; - while (!(CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) & 0x8000000)) + while (!(CLOCK(CLK_RST_CONTROLLER_PLLM_BASE) & BIT(27))) { if (get_tmr_us() >= wait_end) - goto break_nosleep; + goto lock_timeout; } usleep(10); -break_nosleep: +lock_timeout: + // Set clock sources. CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = ((params->mc_emem_arb_misc0 >> 11) & 0x10000) | (params->emc_clock_source & 0xFFFEFFFF); if (params->emc_clock_source_dll) CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC_DLL) = params->emc_clock_source_dll; @@ -237,12 +283,13 @@ break_nosleep: CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = BIT(CLK_X_EMC_DLL); CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM); - // Set pad macros. + // Set pad vtt levels. EMC(EMC_PMACRO_VTTGEN_CTRL_0) = params->emc_pmacro_vttgen_ctrl0; EMC(EMC_PMACRO_VTTGEN_CTRL_1) = params->emc_pmacro_vttgen_ctrl1; EMC(EMC_PMACRO_VTTGEN_CTRL_2) = params->emc_pmacro_vttgen_ctrl2; - EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place. + // Trigger timing update so above writes take place. + EMC(EMC_TIMING_CONTROL) = 1; usleep(10); // Ensure the regulators settle. // Select EMC write mux. @@ -279,6 +326,7 @@ break_nosleep: // This is required to do any reads from the pad macros. EMC(EMC_CONFIG_SAMPLE_DELAY) = params->emc_config_sample_delay; + // Set data pipes mode. EMC(EMC_FBIO_CFG8) = params->emc_fbio_cfg8; // Set swizzle for Rank 0. @@ -296,12 +344,12 @@ break_nosleep: if (params->emc_bct_spare6) *(vu32 *)params->emc_bct_spare6 = params->emc_bct_spare7; - // Set pad controls. + // Program calibration impedance. EMC(EMC_XM2COMPPADCTRL) = params->emc_xm2_comp_pad_ctrl; EMC(EMC_XM2COMPPADCTRL2) = params->emc_xm2_comp_pad_ctrl2; EMC(EMC_XM2COMPPADCTRL3) = params->emc_xm2_comp_pad_ctrl3; - // Program Autocal controls with shadowed register fields. + // Program Autocal controls. EMC(EMC_AUTO_CAL_CONFIG2) = params->emc_auto_cal_config2; EMC(EMC_AUTO_CAL_CONFIG3) = params->emc_auto_cal_config3; EMC(EMC_AUTO_CAL_CONFIG4) = params->emc_auto_cal_config4; @@ -310,6 +358,7 @@ break_nosleep: EMC(EMC_AUTO_CAL_CONFIG7) = params->emc_auto_cal_config7; EMC(EMC_AUTO_CAL_CONFIG8) = params->emc_auto_cal_config8; + // Program termination and drive strength EMC(EMC_PMACRO_RX_TERM) = params->emc_pmacro_rx_term; EMC(EMC_PMACRO_DQ_TX_DRV) = params->emc_pmacro_dq_tx_drive; EMC(EMC_PMACRO_CA_TX_DRV) = params->emc_pmacro_ca_tx_drive; @@ -318,10 +367,12 @@ break_nosleep: EMC(EMC_AUTO_CAL_CHANNEL) = params->emc_auto_cal_channel; EMC(EMC_PMACRO_ZCTRL) = params->emc_pmacro_zcrtl; + // Program dll config. EMC(EMC_DLL_CFG_0) = params->emc_dll_cfg0; EMC(EMC_DLL_CFG_1) = params->emc_dll_cfg1; EMC(EMC_CFG_DIG_DLL_1) = params->emc_cfg_dig_dll_1; + // Program barrelshift. EMC(EMC_DATA_BRLSHFT_0) = params->emc_data_brlshft0; EMC(EMC_DATA_BRLSHFT_1) = params->emc_data_brlshft1; EMC(EMC_DQS_BRLSHFT_0) = params->emc_dqs_brlshft0; @@ -335,6 +386,7 @@ break_nosleep: EMC(EMC_QUSE_BRLSHFT_2) = params->emc_quse_brlshft2; EMC(EMC_QUSE_BRLSHFT_3) = params->emc_quse_brlshft3; + // Program pad macros controls and termination. EMC(EMC_PMACRO_BRICK_CTRL_RFU1) = (params->emc_pmacro_brick_ctrl_rfu1 & 0x1BF01BF) | 0x1E401E40; EMC(EMC_PMACRO_PAD_CFG_CTRL) = params->emc_pmacro_pad_cfg_ctrl; @@ -349,6 +401,7 @@ break_nosleep: EMC(EMC_PMACRO_CMD_RX_TERM_MODE) = params->emc_pmacro_cmd_rx_term_mode; EMC(EMC_PMACRO_CMD_PAD_TX_CTRL) = params->emc_pmacro_cmd_pad_tx_ctrl; + // Program pad macro pins/bytes. EMC(EMC_CFG_3) = params->emc_cfg3; EMC(EMC_PMACRO_TX_PWRD_0) = params->emc_pmacro_tx_pwrd0; EMC(EMC_PMACRO_TX_PWRD_1) = params->emc_pmacro_tx_pwrd1; @@ -369,12 +422,15 @@ break_nosleep: EMC(EMC_PMACRO_CMD_CTRL_0) = params->emc_pmacro_cmd_ctrl0; EMC(EMC_PMACRO_CMD_CTRL_1) = params->emc_pmacro_cmd_ctrl1; EMC(EMC_PMACRO_CMD_CTRL_2) = params->emc_pmacro_cmd_ctrl2; + + // Program inbound vref setting. EMC(EMC_PMACRO_IB_VREF_DQ_0) = params->emc_pmacro_ib_vref_dq_0; EMC(EMC_PMACRO_IB_VREF_DQ_1) = params->emc_pmacro_ib_vref_dq_1; EMC(EMC_PMACRO_IB_VREF_DQS_0) = params->emc_pmacro_ib_vref_dqs_0; EMC(EMC_PMACRO_IB_VREF_DQS_1) = params->emc_pmacro_ib_vref_dqs_1; EMC(EMC_PMACRO_IB_RXRT) = params->emc_pmacro_ib_rxrt; + // Program quse trimmers. EMC(EMC_PMACRO_QUSE_DDLL_RANK0_0) = params->emc_pmacro_quse_ddll_rank0_0; EMC(EMC_PMACRO_QUSE_DDLL_RANK0_1) = params->emc_pmacro_quse_ddll_rank0_1; EMC(EMC_PMACRO_QUSE_DDLL_RANK0_2) = params->emc_pmacro_quse_ddll_rank0_2; @@ -389,6 +445,7 @@ break_nosleep: EMC(EMC_PMACRO_QUSE_DDLL_RANK1_5) = params->emc_pmacro_quse_ddll_rank1_5; EMC(EMC_PMACRO_BRICK_CTRL_RFU1) = params->emc_pmacro_brick_ctrl_rfu1; + // Program outbound trimmers. EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0) = params->emc_pmacro_ob_ddll_long_dq_rank0_0; EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1) = params->emc_pmacro_ob_ddll_long_dq_rank0_1; EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2) = params->emc_pmacro_ob_ddll_long_dq_rank0_2; @@ -423,6 +480,7 @@ break_nosleep: EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_2) = params->emc_pmacro_ib_ddll_long_dqs_rank1_2; EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_3) = params->emc_pmacro_ib_ddll_long_dqs_rank1_3; + // Program clock trimmers. EMC(EMC_PMACRO_DDLL_LONG_CMD_0) = params->emc_pmacro_ddll_long_cmd_0; EMC(EMC_PMACRO_DDLL_LONG_CMD_1) = params->emc_pmacro_ddll_long_cmd_1; EMC(EMC_PMACRO_DDLL_LONG_CMD_2) = params->emc_pmacro_ddll_long_cmd_2; @@ -439,7 +497,8 @@ break_nosleep: if (params->emc_bct_spare4) *(vu32 *)params->emc_bct_spare4 = params->emc_bct_spare5; - EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place. + // Trigger timing update so above writes take place. + EMC(EMC_TIMING_CONTROL) = 1; // Initialize MC VPR settings. MC(MC_VIDEO_PROTECT_BOM) = params->mc_video_protect_bom; @@ -504,7 +563,8 @@ break_nosleep: MC(MC_EMEM_ARB_RSV) = params->mc_emem_arb_rsv; MC(MC_DA_CONFIG0) = params->mc_da_cfg0; - MC(MC_TIMING_CONTROL) = 1; // Trigger MC timing update. + // Trigger MC timing update. + MC(MC_TIMING_CONTROL) = 1; // Program second-level clock enable overrides. MC(MC_CLKEN_OVERRIDE) = params->mc_clken_override; @@ -526,6 +586,7 @@ break_nosleep: EMC(EMC_AUTO_CAL_VREF_SEL_0) = params->emc_auto_cal_vref_sel0; EMC(EMC_AUTO_CAL_VREF_SEL_1) = params->emc_auto_cal_vref_sel1; + // Program/Start auto calibration. EMC(EMC_AUTO_CAL_INTERVAL) = params->emc_auto_cal_interval; EMC(EMC_AUTO_CAL_CONFIG) = params->emc_auto_cal_config; usleep(params->emc_auto_cal_wait); @@ -583,10 +644,12 @@ break_nosleep: EMC(EMC_PMACRO_COMMON_PAD_TX_CTRL) = params->emc_pmacro_common_pad_tx_ctrl; EMC(EMC_DBG) = params->emc_dbg; + // Clear read fifo. EMC(EMC_QRST) = params->emc_qrst; EMC(EMC_ISSUE_QRST) = 1; EMC(EMC_ISSUE_QRST) = 0; + // Program the rest of EMC timing configuration. EMC(EMC_QSAFE) = params->emc_qsafe; EMC(EMC_RDV) = params->emc_rdv; EMC(EMC_RDV_MASK) = params->emc_rdv_mask; @@ -635,14 +698,16 @@ break_nosleep: if (params->boot_rom_patch_control & BIT(31)) { *(vu32 *)(APB_MISC_BASE + params->boot_rom_patch_control * 4) = params->boot_rom_patch_data; - MC(MC_TIMING_CONTROL) = 1; // Trigger MC timing update. + + // Trigger MC timing update. + MC(MC_TIMING_CONTROL) = 1; } // Release SEL_DPD_CMD. - PMC(APBDEV_PMC_IO_DPD3_REQ) = (params->emc_pmc_scratch1 & 0xFFF0000) | (1 << 30u); + PMC(APBDEV_PMC_IO_DPD3_REQ) = (params->emc_pmc_scratch1 & 0xFFF0000) | PMC_IO_DPD_REQ_DPD_OFF; usleep(params->pmc_io_dpd3_req_wait); - // Set autocal interval if not configured. + // Stall auto call measurements if periodic calibration is disabled. if (!params->emc_auto_cal_interval) EMC(EMC_AUTO_CAL_CONFIG) = params->emc_auto_cal_config | 0x200; @@ -655,7 +720,8 @@ break_nosleep: EMC(EMC_ZCAL_MRW_CMD) = params->emc_zcal_mrw_cmd; } - EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place. + // Trigger timing update so above writes take place. + EMC(EMC_TIMING_CONTROL) = 1; usleep(params->emc_timing_control_wait); // Deassert HOLD_CKE_LOW. @@ -724,7 +790,8 @@ break_nosleep: if (params->emc_bct_spare12) *(vu32 *)params->emc_bct_spare12 = params->emc_bct_spare13; - EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place. + // Trigger timing update so above writes take place. + EMC(EMC_TIMING_CONTROL) = 1; if (params->emc_extra_refresh_num) EMC(EMC_REF) = (((1 << params->emc_extra_refresh_num) - 1) << 8) | (params->emc_dev_select << 30) | 3; @@ -742,7 +809,8 @@ break_nosleep: // Write addr swizzle lock bit. EMC(EMC_FBIO_SPARE) = params->emc_fbio_spare | BIT(1); - EMC(EMC_TIMING_CONTROL) = 1; // Re-trigger timing to latch power saving functions. + // Re-trigger timing to latch power saving functions. + EMC(EMC_TIMING_CONTROL) = 1; // Enable EMC pipe clock gating. EMC(EMC_CFG_PIPE_CLK) = params->emc_cfg_pipe_clk; @@ -764,8 +832,19 @@ break_nosleep: static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) { - u32 pmc_scratch1 = ~params->emc_pmc_scratch1; - u32 pmc_scratch2 = ~params->emc_pmc_scratch2; + // VDDP Select. + PMC(APBDEV_PMC_VDDP_SEL) = params->pmc_vddp_sel; + usleep(params->pmc_vddp_sel_wait); + + // Turn on MEM IO Power. + PMC(APBDEV_PMC_NO_IOPOWER) &= PMC_NO_IOPOWER_SDMMC1; // Only keep SDMMC1 state. (Was params->pmc_no_io_power). + PMC(APBDEV_PMC_REG_SHORT) = params->pmc_reg_short; + + PMC(APBDEV_PMC_DDR_CNTRL) = params->pmc_ddr_ctrl; + + // Patch 1 using BCT spare variables + if (params->emc_bct_spare0) + *(vu32 *)params->emc_bct_spare0 = params->emc_bct_spare1; // Override HW FSM if needed. if (params->clk_rst_pllm_misc20_override_enable) @@ -773,16 +852,18 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) // Program DPD3/DPD4 regs (coldboot path). // Enable sel_dpd on unused pins. + u32 pmc_scratch1 = ~params->emc_pmc_scratch1; PMC(APBDEV_PMC_WEAK_BIAS) = (pmc_scratch1 & 0x1000) << 19 | (pmc_scratch1 & 0xFFF) << 18 | (pmc_scratch1 & 0x8000) << 15; - PMC(APBDEV_PMC_IO_DPD3_REQ) = (pmc_scratch1 & 0x9FFF) | (2 << 30u); + PMC(APBDEV_PMC_IO_DPD3_REQ) = (pmc_scratch1 & 0x9FFF) | PMC_IO_DPD_REQ_DPD_ON; usleep(params->pmc_io_dpd3_req_wait); // Disable e_dpd_vttgen. - PMC(APBDEV_PMC_IO_DPD4_REQ) = (pmc_scratch2 & 0x3FFF0000) | (2 << 30u); + u32 pmc_scratch2 = ~params->emc_pmc_scratch2; + PMC(APBDEV_PMC_IO_DPD4_REQ) = (pmc_scratch2 & 0x3FFF0000) | PMC_IO_DPD_REQ_DPD_ON; usleep(params->pmc_io_dpd4_req_wait); // Disable e_dpd_bg. - PMC(APBDEV_PMC_IO_DPD4_REQ) = (pmc_scratch2 & 0x1FFF) | (2 << 30u); + PMC(APBDEV_PMC_IO_DPD4_REQ) = (pmc_scratch2 & 0x1FFF) | PMC_IO_DPD_REQ_DPD_ON; usleep(1); // Program CMD mapping. Required before brick mapping, else @@ -823,7 +904,8 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) if (params->emc_bct_spare_secure4) *(vu32 *)params->emc_bct_spare_secure4 = params->emc_bct_spare_secure5; - EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place. + // Trigger timing update so above writes take place. + EMC(EMC_TIMING_CONTROL) = 1; usleep(params->pmc_vddp_sel_wait + 2); // Ensure the regulators settle. // Set clock sources. @@ -840,6 +922,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) // This is required to do any reads from the pad macros. EMC(EMC_CONFIG_SAMPLE_DELAY) = params->emc_config_sample_delay; + // Set data pipes mode. EMC(EMC_FBIO_CFG8) = params->emc_fbio_cfg8; // Set swizzle for Rank 0. @@ -857,12 +940,12 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) if (params->emc_bct_spare6) *(vu32 *)params->emc_bct_spare6 = params->emc_bct_spare7; - // Set pad controls. + // Program calibration impedance. EMC(EMC_XM2COMPPADCTRL) = params->emc_xm2_comp_pad_ctrl; EMC(EMC_XM2COMPPADCTRL2) = params->emc_xm2_comp_pad_ctrl2; EMC(EMC_XM2COMPPADCTRL3) = params->emc_xm2_comp_pad_ctrl3; - // Program Autocal controls with shadowed register fields. + // Program Autocal controls. EMC(EMC_AUTO_CAL_CONFIG2) = params->emc_auto_cal_config2; EMC(EMC_AUTO_CAL_CONFIG3) = params->emc_auto_cal_config3; EMC(EMC_AUTO_CAL_CONFIG4) = params->emc_auto_cal_config4; @@ -871,6 +954,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) EMC(EMC_AUTO_CAL_CONFIG7) = params->emc_auto_cal_config7; EMC(EMC_AUTO_CAL_CONFIG8) = params->emc_auto_cal_config8; + // Program termination and drive strength EMC(EMC_PMACRO_RX_TERM) = params->emc_pmacro_rx_term; EMC(EMC_PMACRO_DQ_TX_DRV) = params->emc_pmacro_dq_tx_drive; EMC(EMC_PMACRO_CA_TX_DRV) = params->emc_pmacro_ca_tx_drive; @@ -879,10 +963,12 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) EMC(EMC_AUTO_CAL_CHANNEL) = params->emc_auto_cal_channel; EMC(EMC_PMACRO_ZCTRL) = params->emc_pmacro_zcrtl; + // Program dll config. EMC(EMC_DLL_CFG_0) = params->emc_dll_cfg0; EMC(EMC_DLL_CFG_1) = params->emc_dll_cfg1; EMC(EMC_CFG_DIG_DLL_1) = params->emc_cfg_dig_dll_1; + // Program barrelshift. EMC(EMC_DATA_BRLSHFT_0) = params->emc_data_brlshft0; EMC(EMC_DATA_BRLSHFT_1) = params->emc_data_brlshft1; EMC(EMC_DQS_BRLSHFT_0) = params->emc_dqs_brlshft0; @@ -896,6 +982,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) EMC(EMC_QUSE_BRLSHFT_2) = params->emc_quse_brlshft2; EMC(EMC_QUSE_BRLSHFT_3) = params->emc_quse_brlshft3; + // Program pad macros controls and termination. EMC(EMC_PMACRO_BRICK_CTRL_RFU1) = params->emc_pmacro_brick_ctrl_rfu1; EMC(EMC_PMACRO_PAD_CFG_CTRL) = params->emc_pmacro_pad_cfg_ctrl; @@ -909,6 +996,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) EMC(EMC_PMACRO_CMD_RX_TERM_MODE) = params->emc_pmacro_cmd_rx_term_mode; EMC(EMC_PMACRO_CMD_PAD_TX_CTRL) = params->emc_pmacro_cmd_pad_tx_ctrl & 0xEFFFFFFF; + // Program pad macro pins/bytes. EMC(EMC_CFG_3) = params->emc_cfg3; EMC(EMC_PMACRO_TX_PWRD_0) = params->emc_pmacro_tx_pwrd0; EMC(EMC_PMACRO_TX_PWRD_1) = params->emc_pmacro_tx_pwrd1; @@ -952,12 +1040,15 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) EMC(EMC_PMACRO_CMD_CTRL_0) = params->emc_pmacro_cmd_ctrl0; EMC(EMC_PMACRO_CMD_CTRL_1) = params->emc_pmacro_cmd_ctrl1; EMC(EMC_PMACRO_CMD_CTRL_2) = params->emc_pmacro_cmd_ctrl2; + + // Program inbound vref setting. EMC(EMC_PMACRO_IB_VREF_DQ_0) = params->emc_pmacro_ib_vref_dq_0; EMC(EMC_PMACRO_IB_VREF_DQ_1) = params->emc_pmacro_ib_vref_dq_1; EMC(EMC_PMACRO_IB_VREF_DQS_0) = params->emc_pmacro_ib_vref_dqs_0; EMC(EMC_PMACRO_IB_VREF_DQS_1) = params->emc_pmacro_ib_vref_dqs_1; EMC(EMC_PMACRO_IB_RXRT) = params->emc_pmacro_ib_rxrt; + // Program quse trimmers. EMC(EMC_PMACRO_QUSE_DDLL_RANK0_0) = params->emc_pmacro_quse_ddll_rank0_0; EMC(EMC_PMACRO_QUSE_DDLL_RANK0_1) = params->emc_pmacro_quse_ddll_rank0_1; EMC(EMC_PMACRO_QUSE_DDLL_RANK0_2) = params->emc_pmacro_quse_ddll_rank0_2; @@ -971,6 +1062,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) EMC(EMC_PMACRO_QUSE_DDLL_RANK1_4) = params->emc_pmacro_quse_ddll_rank1_4; EMC(EMC_PMACRO_QUSE_DDLL_RANK1_5) = params->emc_pmacro_quse_ddll_rank1_5; + // Program outbound trimmers. EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0) = params->emc_pmacro_ob_ddll_long_dq_rank0_0; EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1) = params->emc_pmacro_ob_ddll_long_dq_rank0_1; EMC(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2) = params->emc_pmacro_ob_ddll_long_dq_rank0_2; @@ -1005,6 +1097,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_2) = params->emc_pmacro_ib_ddll_long_dqs_rank1_2; EMC(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_3) = params->emc_pmacro_ib_ddll_long_dqs_rank1_3; + // Program clock trimmers. EMC(EMC_PMACRO_DDLL_LONG_CMD_0) = params->emc_pmacro_ddll_long_cmd_0; EMC(EMC_PMACRO_DDLL_LONG_CMD_1) = params->emc_pmacro_ddll_long_cmd_1; EMC(EMC_PMACRO_DDLL_LONG_CMD_2) = params->emc_pmacro_ddll_long_cmd_2; @@ -1029,7 +1122,8 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) if (params->emc_bct_spare_secure10) *(vu32 *)params->emc_bct_spare_secure10 = params->emc_bct_spare_secure11; - EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place. + // Trigger timing update so above writes take place. + EMC(EMC_TIMING_CONTROL) = 1; // Initialize MC VPR settings. MC(MC_VIDEO_PROTECT_BOM) = params->mc_video_protect_bom; @@ -1094,7 +1188,8 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) MC(MC_EMEM_ARB_RSV) = params->mc_emem_arb_rsv; MC(MC_DA_CONFIG0) = params->mc_da_cfg0; - MC(MC_TIMING_CONTROL) = 1; // Trigger MC timing update. + // Trigger MC timing update. + MC(MC_TIMING_CONTROL) = 1; // Program second-level clock enable overrides. MC(MC_CLKEN_OVERRIDE) = params->mc_clken_override; @@ -1116,6 +1211,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) EMC(EMC_AUTO_CAL_VREF_SEL_0) = params->emc_auto_cal_vref_sel0; EMC(EMC_AUTO_CAL_VREF_SEL_1) = params->emc_auto_cal_vref_sel1; + // Program/Start auto calibration. EMC(EMC_AUTO_CAL_INTERVAL) = params->emc_auto_cal_interval; EMC(EMC_AUTO_CAL_CONFIG) = params->emc_auto_cal_config; usleep(params->emc_auto_cal_wait); @@ -1179,10 +1275,12 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) EMC(EMC_DBG) = params->emc_dbg; + // Clear read fifo. EMC(EMC_QRST) = params->emc_qrst; EMC(EMC_ISSUE_QRST) = 1; EMC(EMC_ISSUE_QRST) = 0; + // Program the rest of EMC timing configuration. EMC(EMC_QSAFE) = params->emc_qsafe; EMC(EMC_RDV) = params->emc_rdv; EMC(EMC_RDV_MASK) = params->emc_rdv_mask; @@ -1232,7 +1330,9 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) if (params->boot_rom_patch_control) { *(vu32 *)params->boot_rom_patch_control = params->boot_rom_patch_data; - MC(MC_TIMING_CONTROL) = 1; // Trigger MC timing update. + + // Trigger MC timing update. + MC(MC_TIMING_CONTROL) = 1; } // Patch 7 to 9 using BCT spare secure variables. @@ -1244,7 +1344,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) *(vu32 *)params->emc_bct_spare_secure16 = params->emc_bct_spare_secure17; // Release SEL_DPD_CMD. - PMC(APBDEV_PMC_IO_DPD3_REQ) = (params->emc_pmc_scratch1 & 0xFFF0000) | (1 << 30u); + PMC(APBDEV_PMC_IO_DPD3_REQ) = (params->emc_pmc_scratch1 & 0xFFF0000) | PMC_IO_DPD_REQ_DPD_OFF; usleep(params->pmc_io_dpd3_req_wait); // Set transmission pad control parameters. @@ -1257,7 +1357,8 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) EMC(EMC_ZCAL_MRW_CMD) = params->emc_zcal_mrw_cmd; } - EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place. + // Trigger timing update so above writes take place. + EMC(EMC_TIMING_CONTROL) = 1; usleep(params->emc_timing_control_wait); // Deassert HOLD_CKE_LOW. @@ -1334,7 +1435,8 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) if (params->emc_bct_spare12) *(vu32 *)params->emc_bct_spare12 = params->emc_bct_spare13; - EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place. + // Trigger timing update so above writes take place. + EMC(EMC_TIMING_CONTROL) = 1; if (params->emc_extra_refresh_num) EMC(EMC_REF) = ((1 << params->emc_extra_refresh_num << 8) - 253) | (params->emc_dev_select << 30); @@ -1351,7 +1453,8 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) // Write addr swizzle lock bit. EMC(EMC_FBIO_SPARE) = params->emc_fbio_spare | BIT(1); - EMC(EMC_TIMING_CONTROL) = 1; // Re-trigger timing to latch power saving functions. + // Re-trigger timing to latch power saving functions. + EMC(EMC_TIMING_CONTROL) = 1; EMC(EMC_CFG_UPDATE) = params->emc_cfg_update; @@ -1452,65 +1555,28 @@ void *sdram_get_params_patched() return (void *)sdram_params; } -static void _sdram_init_t210() -{ - const sdram_params_t210_t *params = (const sdram_params_t210_t *)_sdram_get_params_t210(); - if (params->memory_type != MEMORY_TYPE_LPDDR4) - return; - - // Set DRAM voltage. - max7762x_regulator_set_voltage(REGULATOR_SD1, 1125000); // HOS: 1.125V. Bootloader: 1.1V. - - // VDDP Select. - PMC(APBDEV_PMC_VDDP_SEL) = params->pmc_vddp_sel; - usleep(params->pmc_vddp_sel_wait); - - // Set DDR pad voltage. - PMC(APBDEV_PMC_DDR_PWR) = PMC(APBDEV_PMC_DDR_PWR); // Normally params->pmc_ddr_pwr. - - // Turn on MEM IO Power. - PMC(APBDEV_PMC_NO_IOPOWER) = params->pmc_no_io_power; - PMC(APBDEV_PMC_REG_SHORT) = params->pmc_reg_short; - - PMC(APBDEV_PMC_DDR_CNTRL) = params->pmc_ddr_ctrl; - - // Patch 1 using BCT spare variables - if (params->emc_bct_spare0) - *(vu32 *)params->emc_bct_spare0 = params->emc_bct_spare1; - - _sdram_config_t210(params); -} - -static void _sdram_init_t210b01() -{ - const sdram_params_t210b01_t *params = (const sdram_params_t210b01_t *)sdram_get_params_t210b01(); - if (params->memory_type != MEMORY_TYPE_LPDDR4) - return; - - // VDDP Select. - PMC(APBDEV_PMC_VDDP_SEL) = params->pmc_vddp_sel; - usleep(params->pmc_vddp_sel_wait); - - // Turn on MEM IO Power. - PMC(APBDEV_PMC_NO_IOPOWER) = params->pmc_no_io_power; - PMC(APBDEV_PMC_REG_SHORT) = params->pmc_reg_short; - - PMC(APBDEV_PMC_DDR_CNTRL) = params->pmc_ddr_ctrl; - - // Patch 1 using BCT spare variables - if (params->emc_bct_spare0) - *(vu32 *)params->emc_bct_spare0 = params->emc_bct_spare1; - - _sdram_config_t210b01(params); -} - void sdram_init() { // Disable remote sense for SD1. i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD_CFG2, MAX77620_SD_CNF2_ROVS_EN_SD0 | MAX77620_SD_CNF2_RSVD); if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210) - _sdram_init_t210(); + { + const sdram_params_t210_t *params = (const sdram_params_t210_t *)_sdram_get_params_t210(); + if (params->memory_type != MEMORY_TYPE_LPDDR4) + return; + + // Set DRAM voltage. + max7762x_regulator_set_voltage(REGULATOR_SD1, 1125000); // HOS: 1.125V. Bootloader: 1.1V. + + _sdram_config_t210(params); + } else - _sdram_init_t210b01(); + { + const sdram_params_t210b01_t *params = (const sdram_params_t210b01_t *)sdram_get_params_t210b01(); + if (params->memory_type != MEMORY_TYPE_LPDDR4) + return; + + _sdram_config_t210b01(params); + } } diff --git a/bdk/mem/sdram.h b/bdk/mem/sdram.h index 5e885ab..10fb705 100644 --- a/bdk/mem/sdram.h +++ b/bdk/mem/sdram.h @@ -48,7 +48,14 @@ enum sdram_ids_erista LPDDR4_ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH = 4, // Die-C. (2y-01). - // Custom hekate/L4T supported 8GB. 7 dram id can be easily applied in fuses. + /* + * Custom hekate/L4T supported 8GB. 7 dram id can be easily applied in fuses. + * + * 4GB modules: + * Samsung K4FBE3D4HM-MGCH/CJ/CL. MG/TF/GF/TH/GH: Package + Temperature. + * Hynix H9HCNNNCPUMLXR-NME/NEE/NEI. E/I: Temperature. + * Hynix H54G56BYYVX046/QX046/PX046. V/Q/P: Package + Temperature. + */ LPDDR4_ICOSA_8GB_SAMSUNG_K4FBE3D4HM_MGXX = 7, // XX: CH/CJ/CL. }; @@ -128,6 +135,7 @@ void sdram_init(); void *sdram_get_params_patched(); void *sdram_get_params_t210b01(); void sdram_lp0_save_params(const void *params); +void sdram_src_pllc(bool enable); emc_mr_data_t sdram_read_mrx(emc_mr_t mrx); #endif diff --git a/bdk/power/bm92t36.c b/bdk/power/bm92t36.c index faa1db5..371ed04 100644 --- a/bdk/power/bm92t36.c +++ b/bdk/power/bm92t36.c @@ -75,7 +75,7 @@ void bm92t36_get_sink_info(bool *inserted, usb_pd_objects_t *usb_pd) { memset(buf, 0, sizeof(buf)); _bm92t36_read_reg(buf, 2, STATUS1_REG); - *inserted = buf[0] & STATUS1_INSERT ? true : false; + *inserted = (buf[0] & STATUS1_INSERT) ? true : false; } if (usb_pd) diff --git a/bdk/power/regulator_5v.c b/bdk/power/regulator_5v.c index 557dae9..55f81f7 100644 --- a/bdk/power/regulator_5v.c +++ b/bdk/power/regulator_5v.c @@ -32,24 +32,24 @@ void regulator_5v_enable(u8 dev) // The power supply selection from battery or USB is automatic. if (!reg_5v_dev) { - // Fan and Rail power from battery 5V regulator. + // Fan and Rail power from battery 5V regulator EN. PINMUX_AUX(PINMUX_AUX_SATA_LED_ACTIVE) = 1; gpio_direction_output(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH); // Only Icosa has USB 5V VBUS rails. if (tegra_t210) { - // Fan and Rail power from USB 5V VBUS. + // Fan and Rail power from USB 5V VBUS EN. PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_LPDR | 1; gpio_direction_output(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW); } // Make sure GPIO IO power is enabled. - PMC(APBDEV_PMC_NO_IOPOWER) &= ~PMC_NO_IOPOWER_GPIO_IO_EN; + PMC(APBDEV_PMC_NO_IOPOWER) &= ~PMC_NO_IOPOWER_GPIO; (void)PMC(APBDEV_PMC_NO_IOPOWER); // Commit write. - // Override power detect for GPIO AO IO rails. - PMC(APBDEV_PMC_PWR_DET_VAL) &= ~PMC_PWR_DET_GPIO_IO_EN; + // Inform GPIO IO pads that we switched to 1.8V. + PMC(APBDEV_PMC_PWR_DET_VAL) &= ~PMC_PWR_DET_33V_GPIO; (void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write. usb_src = false; diff --git a/bdk/sec/se.c b/bdk/sec/se.c index e1bcbc2..c8701b3 100644 --- a/bdk/sec/se.c +++ b/bdk/sec/se.c @@ -33,6 +33,9 @@ typedef struct _se_ll_t vu32 size; } se_ll_t; +static u32 _se_rsa_mod_sizes[SE_RSA_KEYSLOT_COUNT]; +static u32 _se_rsa_exp_sizes[SE_RSA_KEYSLOT_COUNT]; + se_ll_t ll_src, ll_dst; se_ll_t *ll_src_ptr, *ll_dst_ptr; // Must be u32 aligned. @@ -194,7 +197,7 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr return res; } -static void _se_aes_ctr_set(void *ctr) +static void _se_aes_ctr_set(const void *ctr) { u32 data[SE_AES_IV_SIZE / 4]; memcpy(data, ctr, SE_AES_IV_SIZE); @@ -213,6 +216,66 @@ void se_rsa_acc_ctrl(u32 rs, u32 flags) SE(SE_RSA_SECURITY_PERKEY_REG) &= ~BIT(rs); } +// se_rsa_key_set() was derived from Atmosphère's set_rsa_keyslot +void se_rsa_key_set(u32 ks, const void *mod, u32 mod_size, const void *exp, u32 exp_size) +{ + u32 *data = (u32 *)mod; + for (u32 i = 0; i < mod_size / 4; i++) + { + SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_MOD) | i; + SE(SE_RSA_KEYTABLE_DATA_REG) = byte_swap_32(data[mod_size / 4 - i - 1]); + } + + data = (u32 *)exp; + for (u32 i = 0; i < exp_size / 4; i++) + { + SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_EXP) | i; + SE(SE_RSA_KEYTABLE_DATA_REG) = byte_swap_32(data[exp_size / 4 - i - 1]); + } + + _se_rsa_mod_sizes[ks] = mod_size; + _se_rsa_exp_sizes[ks] = exp_size; +} + +// se_rsa_key_clear() was derived from Atmosphère's clear_rsa_keyslot +void se_rsa_key_clear(u32 ks) +{ + for (u32 i = 0; i < SE_RSA2048_DIGEST_SIZE / 4; i++) + { + SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_MOD) | i; + SE(SE_RSA_KEYTABLE_DATA_REG) = 0; + } + for (u32 i = 0; i < SE_RSA2048_DIGEST_SIZE / 4; i++) + { + SE(SE_RSA_KEYTABLE_ADDR_REG) = RSA_KEY_NUM(ks) | SE_RSA_KEYTABLE_TYPE(RSA_KEY_TYPE_EXP) | i; + SE(SE_RSA_KEYTABLE_DATA_REG) = 0; + } +} + +// se_rsa_exp_mod() was derived from Atmosphère's se_synchronous_exp_mod and se_get_exp_mod_output +int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size) +{ + int res; + u8 stack_buf[SE_RSA2048_DIGEST_SIZE]; + + for (u32 i = 0; i < src_size; i++) + stack_buf[i] = *((u8 *)src + src_size - i - 1); + + SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_RSA) | SE_CONFIG_DST(DST_RSAREG); + SE(SE_RSA_CONFIG) = RSA_KEY_SLOT(ks); + SE(SE_RSA_KEY_SIZE_REG) = (_se_rsa_mod_sizes[ks] >> 6) - 1; + SE(SE_RSA_EXP_SIZE_REG) = _se_rsa_exp_sizes[ks] >> 2; + + res = _se_execute_oneshot(SE_OP_START, NULL, 0, stack_buf, src_size); + + // Copy output hash. + u32 *dst32 = (u32 *)dst; + for (u32 i = 0; i < dst_size / 4; i++) + dst32[dst_size / 4 - i - 1] = byte_swap_32(SE(SE_RSA_OUTPUT_REG + (i * 4))); + + return res; +} + void se_key_acc_ctrl(u32 ks, u32 flags) { if (flags & SE_KEY_TBL_DIS_KEY_ACCESS_FLAG) @@ -226,7 +289,7 @@ u32 se_key_acc_ctrl_get(u32 ks) return SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + 4 * ks); } -void se_aes_key_set(u32 ks, void *key, u32 size) +void se_aes_key_set(u32 ks, const void *key, u32 size) { u32 data[SE_AES_MAX_KEY_SIZE / 4]; memcpy(data, key, size); @@ -238,7 +301,13 @@ void se_aes_key_set(u32 ks, void *key, u32 size) } } -void se_aes_iv_set(u32 ks, void *iv) +void se_aes_key_partial_set(u32 ks, u32 index, u32 data) +{ + SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | index; + SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data; +} + +void se_aes_iv_set(u32 ks, const void *iv) { u32 data[SE_AES_IV_SIZE / 4]; memcpy(data, iv, SE_AES_IV_SIZE); diff --git a/bdk/sec/se.h b/bdk/sec/se.h index 16ddaa6..06f3c1d 100644 --- a/bdk/sec/se.h +++ b/bdk/sec/se.h @@ -22,11 +22,15 @@ #include void se_rsa_acc_ctrl(u32 rs, u32 flags); +void se_rsa_key_set(u32 ks, const void *mod, u32 mod_size, const void *exp, u32 exp_size); +void se_rsa_key_clear(u32 ks); +int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size); void se_key_acc_ctrl(u32 ks, u32 flags); u32 se_key_acc_ctrl_get(u32 ks); void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize); -void se_aes_key_set(u32 ks, void *key, u32 size); -void se_aes_iv_set(u32 ks, void *iv); +void se_aes_key_set(u32 ks, const void *key, u32 size); +void se_aes_iv_set(u32 ks, const void *iv); +void se_aes_key_partial_set(u32 ks, u32 index, u32 data); void se_aes_key_get(u32 ks, void *key, u32 size); void se_aes_key_clear(u32 ks); void se_aes_iv_clear(u32 ks); diff --git a/bdk/sec/tsec.c b/bdk/sec/tsec.c index 687af40..de2dbbb 100644 --- a/bdk/sec/tsec.c +++ b/bdk/sec/tsec.c @@ -75,7 +75,7 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt) void *ptb; bpmp_mmu_disable(); - bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL); + bpmp_clk_rate_relaxed(true); // Enable clocks. clock_enable_tsec(); @@ -305,7 +305,7 @@ out: clock_disable_sor_safe(); clock_disable_tsec(); bpmp_mmu_enable(); - bpmp_clk_rate_set(prev_fid); + bpmp_clk_rate_relaxed(false); #ifdef BDK_MC_ENABLE_AHB_REDIRECT // Re-enable AHB aperture. diff --git a/bdk/soc/bpmp.c b/bdk/soc/bpmp.c index 669dcc2..3979c2a 100644 --- a/bdk/soc/bpmp.c +++ b/bdk/soc/bpmp.c @@ -1,7 +1,7 @@ /* * BPMP-Lite Cache/MMU and Frequency driver for Tegra X1 * - * Copyright (c) 2019-2023 CTCaer + * Copyright (c) 2019-2024 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -118,7 +118,7 @@ #define MMU_EN_READ BIT(2) #define MMU_EN_WRITE BIT(3) -bpmp_mmu_entry_t mmu_entries[] = +static const bpmp_mmu_entry_t mmu_entries[] = { { DRAM_START, 0xFFFFFFFF, MMU_EN_READ | MMU_EN_WRITE | MMU_EN_EXEC | MMU_EN_CACHED, true }, { IRAM_BASE, 0x4003FFFF, MMU_EN_READ | MMU_EN_WRITE | MMU_EN_EXEC | MMU_EN_CACHED, true } @@ -140,7 +140,7 @@ void bpmp_mmu_maintenance(u32 op, bool force) BPMP_CACHE_CTRL(BPMP_CACHE_INT_CLEAR) = BPMP_CACHE_CTRL(BPMP_CACHE_INT_RAW_EVENT); } -void bpmp_mmu_set_entry(int idx, bpmp_mmu_entry_t *entry, bool apply) +void bpmp_mmu_set_entry(int idx, const bpmp_mmu_entry_t *entry, bool apply) { if (idx > 31) return; @@ -200,10 +200,45 @@ void bpmp_mmu_disable() BPMP_CACHE_CTRL(BPMP_CACHE_CONFIG) = 0; } + +/* + * CLK_RST_CONTROLLER_SCLK_BURST_POLICY: + * 0 = CLKM + * 1 = PLLC_OUT1 + * 2 = PLLC4_OUT3 + * 3 = PLLP_OUT0 + * 4 = PLLP_OUT2 + * 5 = PLLC4_OUT1 + * 6 = CLK_S + * 7 = PLLC4_OUT2 + */ + +bpmp_freq_t bpmp_fid_current = BPMP_CLK_NORMAL; + +void bpmp_clk_rate_relaxed(bool enable) +{ + // This is a glitch-free way to reduce the SCLK timings. + if (enable) + { + // Restore to PLLP source during PLLC configuration. + CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003330; // PLLP_OUT. + usleep(100); // Wait a bit for clock source change. + CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // PCLK = HCLK / (2 + 1). HCLK == SCLK. + } + else if (bpmp_fid_current) + { + // Restore to PLLC_OUT1. + CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 3; // PCLK = HCLK / (3 + 1). HCLK == SCLK. + CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003310; // PLLC_OUT1 and CLKM for idle. + usleep(100); // Wait a bit for clock source change. + } +} + // APB clock affects RTC, PWM, MEMFETCH, APE, USB, SOR PWM, // I2C host, DC/DSI/DISP. UART gives extra stress. // 92: 100% success ratio. 93-94: 595-602MHz has 99% success ratio. 95: 608MHz less. -const u8 pll_divn[] = { +// APB clock max is supposed to be 204 MHz though. +static const u8 pll_divn[] = { 0, // BPMP_CLK_NORMAL: 408MHz 0% - 136MHz APB. 85, // BPMP_CLK_HIGH_BOOST: 544MHz 33% - 136MHz APB. 88, // BPMP_CLK_HIGH2_BOOST: 563MHz 38% - 141MHz APB. @@ -213,8 +248,6 @@ const u8 pll_divn[] = { //95 // BPMP_CLK_DEV_BOOST: 608MHz 49% - 152MHz APB. }; -bpmp_freq_t bpmp_fid_current = BPMP_CLK_NORMAL; - void bpmp_clk_rate_get() { bool clk_src_is_pllp = ((CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) >> 4) & 7) == 3; @@ -237,45 +270,42 @@ void bpmp_clk_rate_get() } } -bpmp_freq_t bpmp_clk_rate_set(bpmp_freq_t fid) +void bpmp_clk_rate_set(bpmp_freq_t fid) { - bpmp_freq_t prev_fid = bpmp_fid_current; - if (fid > (BPMP_CLK_MAX - 1)) fid = BPMP_CLK_MAX - 1; - if (prev_fid == fid) - return prev_fid; + if (bpmp_fid_current == fid) + return; + + bpmp_fid_current = fid; if (fid) { - if (prev_fid) - { - // Restore to PLLP source during PLLC configuration. - CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; // PLLP_OUT. - msleep(1); // Wait a bit for clock source change. - } + // Use default SCLK / HCLK / PCLK clocks. + bpmp_clk_rate_relaxed(true); // Configure and enable PLLC. clock_enable_pllc(pll_divn[fid]); - // Set SCLK / HCLK / PCLK. - CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 3; // PCLK = HCLK / (3 + 1). HCLK == SCLK. - CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003310; // PLLC_OUT1 for active and CLKM for idle. + // Set new source and SCLK / HCLK / PCLK dividers. + bpmp_clk_rate_relaxed(false); } else { - CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003330; // PLLP_OUT for active and CLKM for idle. - msleep(1); // Wait a bit for clock source change. - CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // PCLK = HCLK / (2 + 1). HCLK == SCLK. + // Use default SCLK / HCLK / PCLK clocks. + bpmp_clk_rate_relaxed(true); // Disable PLLC to save power. clock_disable_pllc(); } - bpmp_fid_current = fid; +} - // Return old fid in case of temporary swap. - return prev_fid; +// State is reset to RUN on any clock or source set via SW. +void bpmp_state_set(bpmp_state_t state) +{ + u32 cfg = CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) & ~0xF0000000u; + CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = cfg | (state << 28u); } // The following functions halt BPMP to reduce power while sleeping. diff --git a/bdk/soc/bpmp.h b/bdk/soc/bpmp.h index 0c55147..ace1290 100644 --- a/bdk/soc/bpmp.h +++ b/bdk/soc/bpmp.h @@ -1,7 +1,7 @@ /* * BPMP-Lite Cache/MMU and Frequency driver for Tegra X1 * - * Copyright (c) 2019-2023 CTCaer + * Copyright (c) 2019-2024 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -54,16 +54,28 @@ typedef enum BPMP_CLK_MAX } bpmp_freq_t; +typedef enum +{ + BPMP_STATE_STANDBY = 0, // 32KHz. + BPMP_STATE_IDLE = 1, + BPMP_STATE_RUN = 2, + + BPMP_STATE_IRQ = BIT(2), + BPMP_STATE_FIQ = BIT(3), +} bpmp_state_t; + #define BPMP_CLK_LOWEST_BOOST BPMP_CLK_HIGH2_BOOST #define BPMP_CLK_LOWER_BOOST BPMP_CLK_SUPER_BOOST #define BPMP_CLK_DEFAULT_BOOST BPMP_CLK_HYPER_BOOST void bpmp_mmu_maintenance(u32 op, bool force); -void bpmp_mmu_set_entry(int idx, bpmp_mmu_entry_t *entry, bool apply); +void bpmp_mmu_set_entry(int idx, const bpmp_mmu_entry_t *entry, bool apply); void bpmp_mmu_enable(); void bpmp_mmu_disable(); +void bpmp_clk_rate_relaxed(bool enable); void bpmp_clk_rate_get(); -bpmp_freq_t bpmp_clk_rate_set(bpmp_freq_t fid); +void bpmp_clk_rate_set(bpmp_freq_t fid); +void bpmp_state_set(bpmp_state_t state); void bpmp_usleep(u32 us); void bpmp_msleep(u32 ms); void bpmp_halt(); diff --git a/bdk/soc/clock.c b/bdk/soc/clock.c index 083a0ed..b3a48fa 100644 --- a/bdk/soc/clock.c +++ b/bdk/soc/clock.c @@ -15,6 +15,7 @@ * along with this program. If not, see . */ +#include #include #include #include @@ -153,7 +154,13 @@ void clock_enable_fuse(bool enable) void clock_enable_uart(u32 idx) { + // Ease the stress to APB. + bpmp_clk_rate_relaxed(true); + clock_enable(&_clock_uart[idx]); + + // Restore OC. + bpmp_clk_rate_relaxed(false); } void clock_disable_uart(u32 idx) @@ -247,7 +254,13 @@ void clock_disable_nvjpg() void clock_enable_vic() { + // Ease the stress to APB. + bpmp_clk_rate_relaxed(true); + clock_enable(&_clock_vic); + + // Restore sys clock. + bpmp_clk_rate_relaxed(false); } void clock_disable_vic() @@ -323,7 +336,13 @@ void clock_disable_coresight() void clock_enable_pwm() { + // Ease the stress to APB. + bpmp_clk_rate_relaxed(true); + clock_enable(&_clock_pwm); + + // Restore OC. + bpmp_clk_rate_relaxed(false); } void clock_disable_pwm() @@ -398,10 +417,8 @@ void clock_enable_plld(u32 divp, u32 divn, bool lowpower, bool tegra_t210) if (lowpower && tegra_t210) misc = 0x2D0000 | 0x0AAA; // Clock enable and PLLD_SDM_DIN: 2730 -> DIVN + 0.833. - - // Set DISP1 clock source and parent clock. - if (lowpower) - CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DISP1) = (2 << 29u) | CLK_SRC_DIV(1); // PLLD_OUT0. + // Set DISP1 clock source. + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DISP1) = 2 << 29u; // PLLD_OUT0. // Set dividers and enable PLLD. CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div; @@ -464,10 +481,10 @@ void clock_enable_pllc(u32 divn) ; // Disable PLLC_OUT1, enable reset and set div to 1.5. - CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) = BIT(8); + CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) = 1 << 8; // Enable PLLC_OUT1 and bring it out of reset. - CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) |= (PLLC_OUT1_CLKEN | PLLC_OUT1_RSTN_CLR); + CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) |= PLLC_OUT1_CLKEN | PLLC_OUT1_RSTN_CLR; msleep(1); // Wait a bit for PLL to stabilize. } @@ -684,7 +701,7 @@ static void _clock_sdmmc_clear_enable(u32 id) static void _clock_sdmmc_config_legacy_tm() { - clk_rst_t *clk = &_clock_sdmmc_legacy_tm; + const clk_rst_t *clk = &_clock_sdmmc_legacy_tm; if (!(CLOCK(clk->enable) & BIT(clk->index))) clock_enable(clk); } diff --git a/bdk/soc/clock.h b/bdk/soc/clock.h index 0e91836..14d1df7 100644 --- a/bdk/soc/clock.h +++ b/bdk/soc/clock.h @@ -47,6 +47,7 @@ #define CLK_RST_CONTROLLER_PLLM_MISC1 0x98 #define CLK_RST_CONTROLLER_PLLM_MISC2 0x9C #define CLK_RST_CONTROLLER_PLLP_BASE 0xA0 +#define CLK_RST_CONTROLLER_PLLP_OUTB 0xA8 #define CLK_RST_CONTROLLER_PLLA_BASE 0xB0 #define CLK_RST_CONTROLLER_PLLA_OUT 0xB4 #define CLK_RST_CONTROLLER_PLLA_MISC1 0xB8 @@ -149,6 +150,7 @@ #define CLK_RST_CONTROLLER_PLLC_MISC_2 0x5D0 #define CLK_RST_CONTROLLER_PLLC4_OUT 0x5E4 #define CLK_RST_CONTROLLER_PLLMB_BASE 0x5E8 +#define CLK_RST_CONTROLLER_PLLMB_MISC1 0x5EC #define CLK_RST_CONTROLLER_CLK_SOURCE_XUSB_FS 0x608 #define CLK_RST_CONTROLLER_CLK_SOURCE_XUSB_CORE_DEV 0x60C #define CLK_RST_CONTROLLER_CLK_SOURCE_XUSB_SS 0x610 diff --git a/bdk/soc/fuse.c b/bdk/soc/fuse.c index 60e2fe7..468b905 100644 --- a/bdk/soc/fuse.c +++ b/bdk/soc/fuse.c @@ -86,6 +86,15 @@ u32 fuse_read_odm_keygen_rev() return 0; } +u32 fuse_read_bootrom_rev() +{ + u32 rev = FUSE(FUSE_SOC_SPEEDO_1_CALIB); + if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210) + return rev; + else + return rev | (1 << 12); +} + u32 fuse_read_dramid(bool raw_id) { bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210; @@ -189,7 +198,7 @@ void fuse_read_array(u32 *words) words[i] = fuse_read(i); } -static u32 _parity32_even(u32 *words, u32 count) +static u32 _parity32_even(const u32 *words, u32 count) { u32 acc = words[0]; for (u32 i = 1; i < count; i++) @@ -303,7 +312,7 @@ int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value)) u32 words[80]; u32 word_count; u32 word_addr; - u32 word0 = 0; + u32 word0; u32 total_read = 0; word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE); @@ -363,7 +372,7 @@ int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len) u32 words[80]; u32 word_count; u32 word_addr; - u32 word0 = 0; + u32 word0; u32 total_read = 0; int evp_thunk_written = 0; void *evp_thunk_dst_addr = 0; diff --git a/bdk/soc/fuse.h b/bdk/soc/fuse.h index 48a2c7f..142b106 100644 --- a/bdk/soc/fuse.h +++ b/bdk/soc/fuse.h @@ -304,6 +304,7 @@ enum void fuse_disable_program(); u32 fuse_read_odm(u32 idx); u32 fuse_read_odm_keygen_rev(); +u32 fuse_read_bootrom_rev(); u32 fuse_read_dramid(bool raw_id); u32 fuse_read_hw_state(); u32 fuse_read_hw_type(); diff --git a/bdk/soc/hw_init.c b/bdk/soc/hw_init.c index 62a4446..7bfa599 100644 --- a/bdk/soc/hw_init.c +++ b/bdk/soc/hw_init.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2023 CTCaer + * Copyright (c) 2018-2024 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -93,6 +93,24 @@ static void _config_oscillators() CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // Set HCLK div to 1 and PCLK div to 3. } +void hw_config_arbiter(bool reset) +{ + if (reset) + { + ARB_PRI(ARB_PRIO_CPU_PRIORITY) = 0x0040090; + ARB_PRI(ARB_PRIO_COP_PRIORITY) = 0x12024C2; + ARB_PRI(ARB_PRIO_VCP_PRIORITY) = 0x2201209; + ARB_PRI(ARB_PRIO_DMA_PRIORITY) = 0x320365B; + } + else + { + ARB_PRI(ARB_PRIO_CPU_PRIORITY) = 0x12412D1; + ARB_PRI(ARB_PRIO_COP_PRIORITY) = 0x0000000; + ARB_PRI(ARB_PRIO_VCP_PRIORITY) = 0x220244A; + ARB_PRI(ARB_PRIO_DMA_PRIORITY) = 0x320369B; + } +} + // The uart is skipped for Copper, Hoag and Calcio. Used in Icosa, Iowa and Aula. static void _config_gpios(bool nx_hoag) { @@ -268,7 +286,7 @@ static void _config_se_brom() APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) = (APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) & 0xF0) | (7 << 10); } -static void _config_regulators(bool tegra_t210) +static void _config_regulators(bool tegra_t210, bool nx_hoag) { // Set RTC/AO domain to POR voltage. if (tegra_t210) @@ -277,22 +295,26 @@ static void _config_regulators(bool tegra_t210) // Disable low battery shutdown monitor. max77620_low_battery_monitor_config(false); - // Disable SDMMC1 IO/Core power. + // Power on all relevant rails in case we came out of warmboot. Only keep MEM/MEM_COMP and SDMMC1 states. + PMC(APBDEV_PMC_NO_IOPOWER) &= PMC_NO_IOPOWER_MEM_COMP | PMC_NO_IOPOWER_SDMMC1 | PMC_NO_IOPOWER_MEM; + + // Make sure SDMMC1 IO/Core are powered off. max7762x_regulator_enable(REGULATOR_LDO2, false); gpio_write(GPIO_PORT_E, GPIO_PIN_4, GPIO_LOW); + PMC(APBDEV_PMC_NO_IOPOWER) |= PMC_NO_IOPOWER_SDMMC1; + (void)PMC(APBDEV_PMC_NO_IOPOWER); sd_power_cycle_time_start = get_tmr_ms(); - // Disable LCD DVDD to make sure it's in a reset state. - max7762x_regulator_enable(REGULATOR_LDO0, false); - + // Disable backup battery charger. i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CNFGBBC, MAX77620_CNFGBBC_RESISTOR_1K); - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, - MAX77620_ONOFFCNFG1_RSVD | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off. + + // Set PWR delay for forced shutdown off to 6s. + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_RSVD | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); if (tegra_t210) { // Configure all Flexible Power Sequencers for MAX77620. - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG0, (7 << MAX77620_FPS_TIME_PERIOD_SHIFT)); + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG0, (7 << MAX77620_FPS_TIME_PERIOD_SHIFT) | (0 << MAX77620_FPS_EN_SRC_SHIFT)); i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG1, (7 << MAX77620_FPS_TIME_PERIOD_SHIFT) | (1 << MAX77620_FPS_EN_SRC_SHIFT)); i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG2, (7 << MAX77620_FPS_TIME_PERIOD_SHIFT)); max77620_regulator_config_fps(REGULATOR_LDO4); @@ -301,13 +323,13 @@ static void _config_regulators(bool tegra_t210) max77620_regulator_config_fps(REGULATOR_SD1); max77620_regulator_config_fps(REGULATOR_SD3); - i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_GPIO3, - (4 << MAX77620_FPS_TIME_PERIOD_SHIFT) | (2 << MAX77620_FPS_PD_PERIOD_SHIFT)); // 3.x+ + // Set GPIO3 to FPS0 for SYS 3V3 EN. Enabled when FPS0 is enabled. + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_GPIO3, (4 << MAX77620_FPS_PU_PERIOD_SHIFT) | (2 << MAX77620_FPS_PD_PERIOD_SHIFT)); // Set vdd_core voltage to 1.125V. max7762x_regulator_set_voltage(REGULATOR_SD0, 1125000); - // Fix CPU/GPU after L4T warmboot. + // Power down CPU/GPU regulators after L4T warmboot. max77620_config_gpio(5, MAX77620_GPIO_OUTPUT_DISABLE); max77620_config_gpio(6, MAX77620_GPIO_OUTPUT_DISABLE); @@ -315,8 +337,26 @@ static void _config_regulators(bool tegra_t210) max77621_config_default(REGULATOR_CPU0, MAX77621_CTRL_POR_CFG); max77621_config_default(REGULATOR_GPU0, MAX77621_CTRL_POR_CFG); } - else // Tegra X1+ set vdd_core voltage to 1.05V. + else + { + // Tegra X1+ set vdd_core voltage to 1.05V. max7762x_regulator_set_voltage(REGULATOR_SD0, 1050000); + + // Power on SD2 regulator for supplying LDO0/1/8. + max7762x_regulator_set_voltage(REGULATOR_SD2, 1325000); + + // Set slew rate and enable SD2 regulator. + i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_SD2_CFG, (1 << MAX77620_SD_SR_SHIFT) | + (MAX77620_POWER_MODE_NORMAL << MAX77620_SD_POWER_MODE_SHIFT) | + MAX77620_SD_CFG1_FSRADE_SD_ENABLE); + + // Enable LDO8 on HOAG as it also powers I2C1 IO pads. + if (nx_hoag) + { + max7762x_regulator_set_voltage(REGULATOR_LDO8, 2800000); + max7762x_regulator_enable(REGULATOR_LDO8, true); + } + } } void hw_init() @@ -337,6 +377,9 @@ void hw_init() if (tegra_t210) _mbist_workaround(); + // Make sure PLLP_OUT3/4 is set to 408 MHz and enabled. + CLOCK(CLK_RST_CONTROLLER_PLLP_OUTB) = 0x30003; + // Enable Security Engine clock. clock_enable_se(); @@ -355,18 +398,6 @@ void hw_init() // Initialize pin configuration. _config_gpios(nx_hoag); -#ifdef DEBUG_UART_PORT - #if (DEBUG_UART_PORT == UART_B) - gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO); - #elif (DEBUG_UART_PORT == UART_C) - gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO); - #endif - pinmux_config_uart(DEBUG_UART_PORT); - clock_enable_uart(DEBUG_UART_PORT); - uart_init(DEBUG_UART_PORT, DEBUG_UART_BAUDRATE, UART_AO_TX_AO_RX); - uart_invert(DEBUG_UART_PORT, DEBUG_UART_INVERT, UART_INVERT_TXD); -#endif - // Enable CL-DVFS clock unconditionally to avoid issues with I2C5 sharing. clock_enable_cl_dvfs(); @@ -380,19 +411,12 @@ void hw_init() // Initialize I2C5, mandatory for PMIC. i2c_init(I2C_5); - // Enable LDO8 on HOAG as it also powers I2C1 IO pads. - if (nx_hoag) - { - max7762x_regulator_set_voltage(REGULATOR_LDO8, 2800000); - max7762x_regulator_enable(REGULATOR_LDO8, true); - } + // Initialize various regulators based on Erista/Mariko platform. + _config_regulators(tegra_t210, nx_hoag); // Initialize I2C1 for various power related devices. i2c_init(I2C_1); - // Initialize various regulators based on Erista/Mariko platform. - _config_regulators(tegra_t210); - _config_pmc_scratch(); // Missing from 4.x+ // Set BPMP/SCLK to PLLP_OUT (408MHz). @@ -406,6 +430,9 @@ void hw_init() PMC(APBDEV_PMC_TZRAM_SEC_DISABLE) = PMC_TZRAM_DISABLE_REG_WRITE | PMC_TZRAM_DISABLE_REG_READ; } + // Set arbiter. + hw_config_arbiter(false); + // Initialize External memory controller and configure DRAM parameters. sdram_init(); @@ -413,9 +440,22 @@ void hw_init() // Enable HOST1X used by every display module (DC, VIC, NVDEC, NVENC, TSEC, etc). clock_enable_host1x(); + +#ifdef DEBUG_UART_PORT + // Setup debug uart port. + #if (DEBUG_UART_PORT == UART_B) + gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO); + #elif (DEBUG_UART_PORT == UART_C) + gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO); + #endif + pinmux_config_uart(DEBUG_UART_PORT); + clock_enable_uart(DEBUG_UART_PORT); + uart_init(DEBUG_UART_PORT, DEBUG_UART_BAUDRATE, UART_AO_TX_AO_RX); + uart_invert(DEBUG_UART_PORT, DEBUG_UART_INVERT, UART_INVERT_TXD); +#endif } -void hw_reinit_workaround(bool coreboot, u32 bl_magic) +void hw_deinit(bool coreboot, u32 bl_magic) { bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210; @@ -426,7 +466,7 @@ void hw_reinit_workaround(bool coreboot, u32 bl_magic) // Disable temperature sensor, touchscreen, 5V regulators, Joy-Con and VIC. vic_end(); tmp451_end(); - set_fan_duty(0); + fan_set_duty(0); touch_power_off(); jc_deinit(); regulator_5v_disable(REGULATOR_5V_ALL); @@ -439,6 +479,9 @@ void hw_reinit_workaround(bool coreboot, u32 bl_magic) // Flush/disable MMU cache. bpmp_mmu_disable(); + // Reset arbiter. + hw_config_arbiter(true); + // Re-enable clocks to Audio Processing Engine as a workaround to hanging. if (tegra_t210) { @@ -458,7 +501,7 @@ void hw_reinit_workaround(bool coreboot, u32 bl_magic) gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO); // Reinstate SD controller power. - PMC(APBDEV_PMC_NO_IOPOWER) &= ~(PMC_NO_IOPOWER_SDMMC1_IO_EN); + PMC(APBDEV_PMC_NO_IOPOWER) &= ~PMC_NO_IOPOWER_SDMMC1; } // Seamless display or display power off. diff --git a/bdk/soc/hw_init.h b/bdk/soc/hw_init.h index aebb021..fcd8d10 100644 --- a/bdk/soc/hw_init.h +++ b/bdk/soc/hw_init.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2021 CTCaer + * Copyright (c) 2018-2024 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -27,7 +27,8 @@ extern u32 hw_rst_status; extern u32 hw_rst_reason; void hw_init(); -void hw_reinit_workaround(bool coreboot, u32 magic); +void hw_deinit(bool coreboot, u32 magic); +void hw_config_arbiter(bool reset); u32 hw_get_chip_id(); #endif diff --git a/bdk/soc/i2c.c b/bdk/soc/i2c.c index 81f783c..c38e952 100644 --- a/bdk/soc/i2c.c +++ b/bdk/soc/i2c.c @@ -96,7 +96,7 @@ static void _i2c_load_cfg_wait(vu32 *base) } } -static int _i2c_send_single(u32 i2c_idx, u32 dev_addr, u8 *buf, u32 size) +static int _i2c_send_single(u32 i2c_idx, u32 dev_addr, const u8 *buf, u32 size) { if (size > 8) return 0; @@ -384,7 +384,7 @@ int i2c_recv_buf_big(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg) return _i2c_recv_pkt(i2c_idx, buf, size, dev_addr, reg); } -int i2c_send_buf_small(u32 i2c_idx, u32 dev_addr, u32 reg, u8 *buf, u32 size) +int i2c_send_buf_small(u32 i2c_idx, u32 dev_addr, u32 reg, const u8 *buf, u32 size) { u8 tmp[8]; diff --git a/bdk/soc/i2c.h b/bdk/soc/i2c.h index a04eec1..ab3078e 100644 --- a/bdk/soc/i2c.h +++ b/bdk/soc/i2c.h @@ -31,7 +31,7 @@ void i2c_init(u32 i2c_idx); int i2c_recv_buf(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr); int i2c_send_buf_big(u32 i2c_idx, u32 dev_addr, u8 *buf, u32 size); int i2c_recv_buf_big(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg); -int i2c_send_buf_small(u32 i2c_idx, u32 dev_addr, u32 reg, u8 *buf, u32 size); +int i2c_send_buf_small(u32 i2c_idx, u32 dev_addr, u32 reg, const u8 *buf, u32 size); int i2c_recv_buf_small(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg); int i2c_send_byte(u32 i2c_idx, u32 dev_addr, u32 reg, u8 val); u8 i2c_recv_byte(u32 i2c_idx, u32 dev_addr, u32 reg); diff --git a/bdk/soc/irq.c b/bdk/soc/irq.c index 5ecfb58..f39774e 100644 --- a/bdk/soc/irq.c +++ b/bdk/soc/irq.c @@ -1,7 +1,7 @@ /* * BPMP-Lite IRQ driver for Tegra X1 * - * Copyright (c) 2019 CTCaer + * Copyright (c) 2019-2024 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -71,19 +71,9 @@ static void _irq_disable_and_ack_all() { u32 enabled_irqs = ICTLR(ctrl_idx, PRI_ICTLR_COP_IER); ICTLR(ctrl_idx, PRI_ICTLR_COP_IER_CLR) = enabled_irqs; - ICTLR(ctrl_idx, PRI_ICTLR_FIR_CLR) = enabled_irqs; } } -static void _irq_ack_source(u32 irq) -{ - u32 ctrl_idx = irq >> 5; - u32 bit = irq % 32; - - // Force stop the interrupt as it's serviced here. - ICTLR(ctrl_idx, PRI_ICTLR_FIR_CLR) = BIT(bit); -} - void irq_free(u32 irq) { for (u32 idx = 0; idx < IRQ_MAX_HANDLERS; idx++) @@ -121,7 +111,6 @@ static irq_status_t _irq_handle_source(u32 irq) int status = IRQ_NONE; _irq_disable_source(irq); - _irq_ack_source(irq); u32 idx; for (idx = 0; idx < IRQ_MAX_HANDLERS; idx++) @@ -135,8 +124,8 @@ static irq_status_t _irq_handle_source(u32 irq) } } - // Do not re-enable if not handled. - if (status == IRQ_NONE) + // Do not re-enable if not handled or error. + if (status != IRQ_HANDLED) return status; if (irqs[idx].flags & IRQ_FLAG_ONE_OFF) @@ -155,7 +144,6 @@ void irq_handler() if (!irq_init_done) { _irq_disable_source(irq); - _irq_ack_source(irq); return; } @@ -197,7 +185,6 @@ void irq_wait_event(u32 irq) FLOW_CTLR(FLOW_CTLR_HALT_COP_EVENTS) = HALT_MODE_STOP_UNTIL_IRQ; _irq_disable_source(irq); - _irq_ack_source(irq); irq_enable_cpu_irq_exceptions(); } diff --git a/bdk/soc/pinmux.c b/bdk/soc/pinmux.c index 288a4f7..84969c6 100644 --- a/bdk/soc/pinmux.c +++ b/bdk/soc/pinmux.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 naehrwert + * Copyright (c) 2018-2024 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -30,3 +31,11 @@ void pinmux_config_i2c(u32 idx) PINMUX_AUX(PINMUX_AUX_X_I2C_SCL(idx)) = PINMUX_INPUT_ENABLE; PINMUX_AUX(PINMUX_AUX_X_I2C_SDA(idx)) = PINMUX_INPUT_ENABLE; } + +void pinmux_config_i2s(u32 idx) +{ + PINMUX_AUX(PINMUX_AUX_X_I2S_LRCK(idx)) = PINMUX_DRIVE_4X | PINMUX_PULL_DOWN; + PINMUX_AUX(PINMUX_AUX_X_I2C_DIN(idx)) = PINMUX_DRIVE_4X | PINMUX_INPUT_ENABLE | PINMUX_TRISTATE | PINMUX_PULL_DOWN; + PINMUX_AUX(PINMUX_AUX_X_I2C_DOUT(idx)) = PINMUX_DRIVE_4X | PINMUX_PULL_DOWN; + PINMUX_AUX(PINMUX_AUX_X_I2C_BCLK(idx)) = PINMUX_DRIVE_4X | PINMUX_PULL_DOWN; +} diff --git a/bdk/soc/pinmux.h b/bdk/soc/pinmux.h index 070ce1e..f9ad5af 100644 --- a/bdk/soc/pinmux.h +++ b/bdk/soc/pinmux.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 naehrwert + * Copyright (c) 2018-2024 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -50,6 +51,7 @@ #define PINMUX_AUX_DAP4_DOUT 0x14C #define PINMUX_AUX_DAP4_SCLK 0x150 #define PINMUX_AUX_CLK_32K_OUT 0x164 +#define PINMUX_AUX_AUD_MCLK 0x180 #define PINMUX_AUX_GPIO_X1_AUD 0x18C #define PINMUX_AUX_GPIO_X3_AUD 0x190 #define PINMUX_AUX_SPDIF_IN 0x1A4 @@ -69,6 +71,7 @@ #define PINMUX_AUX_LCD_RST 0x204 #define PINMUX_AUX_LCD_GPIO1 0x208 #define PINMUX_AUX_LCD_GPIO2 0x20C +#define PINMUX_AUX_TOUCH_RST 0x214 #define PINMUX_AUX_TOUCH_CLK 0x218 #define PINMUX_AUX_TOUCH_INT 0x220 #define PINMUX_AUX_MOTION_INT 0x224 @@ -81,6 +84,7 @@ #define PINMUX_AUX_GPIO_PK3 0x260 #define PINMUX_AUX_GPIO_PK7 0x270 #define PINMUX_AUX_GPIO_PZ1 0x280 +#define PINMUX_AUX_GPIO_PZ4 0x28C /* Only in T210B01 */ #define PINMUX_AUX_SDMMC2_DAT0 0x294 #define PINMUX_AUX_SDMMC2_DAT1 0x298 @@ -101,6 +105,11 @@ /*! 0:GEN1, 1:GEN2, 2:GEN3, 3:CAM, 4:PWR */ #define PINMUX_AUX_X_I2C_SCL(x) (0xBC + 8 * (x)) #define PINMUX_AUX_X_I2C_SDA(x) (0xC0 + 8 * (x)) +/*! 0:I2S1, 1:I2S2 */ +#define PINMUX_AUX_X_I2S_LRCK(x) (0x124 + 0x10 * (x)) +#define PINMUX_AUX_X_I2C_DIN(x) (0x128 + 0x10 * (x)) +#define PINMUX_AUX_X_I2C_DOUT(x) (0x12c + 0x10 * (x)) +#define PINMUX_AUX_X_I2C_BCLK(x) (0x130 + 0x10 * (x)) #define PINMUX_FUNC_MASK (3 << 0) @@ -130,5 +139,6 @@ void pinmux_config_uart(u32 idx); void pinmux_config_i2c(u32 idx); +void pinmux_config_i2s(u32 idx); #endif diff --git a/bdk/soc/pmc.h b/bdk/soc/pmc.h index 2bbc598..5721895 100644 --- a/bdk/soc/pmc.h +++ b/bdk/soc/pmc.h @@ -1,7 +1,7 @@ /* * Copyright (c) 2018 naehrwert * Copyright (c) 2018 st4rk - * Copyright (c) 2018-2022 CTCaer + * Copyright (c) 2018-2024 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -39,10 +39,12 @@ #define APBDEV_PMC_PWRGATE_TOGGLE 0x30 #define APBDEV_PMC_PWRGATE_STATUS 0x38 #define APBDEV_PMC_NO_IOPOWER 0x44 -#define PMC_NO_IOPOWER_SDMMC1_IO_EN BIT(12) -#define PMC_NO_IOPOWER_SDMMC4_IO_EN BIT(14) +#define PMC_NO_IOPOWER_MEM BIT(7) +#define PMC_NO_IOPOWER_SDMMC1 BIT(12) +#define PMC_NO_IOPOWER_SDMMC4 BIT(14) +#define PMC_NO_IOPOWER_MEM_COMP BIT(16) #define PMC_NO_IOPOWER_AUDIO_HV BIT(18) -#define PMC_NO_IOPOWER_GPIO_IO_EN BIT(21) +#define PMC_NO_IOPOWER_GPIO BIT(21) #define APBDEV_PMC_SCRATCH0 0x50 #define PMC_SCRATCH0_MODE_WARMBOOT BIT(0) #define PMC_SCRATCH0_MODE_RCM BIT(1) @@ -61,9 +63,9 @@ #define APBDEV_PMC_SECURE_SCRATCH4 0xC0 #define APBDEV_PMC_SECURE_SCRATCH5 0xC4 #define APBDEV_PMC_PWR_DET_VAL 0xE4 -#define PMC_PWR_DET_SDMMC1_IO_EN BIT(12) -#define PMC_PWR_DET_AUDIO_HV BIT(18) -#define PMC_PWR_DET_GPIO_IO_EN BIT(21) +#define PMC_PWR_DET_33V_SDMMC1 BIT(12) +#define PMC_PWR_DET_33V_AUDIO_HV BIT(18) +#define PMC_PWR_DET_33V_GPIO BIT(21) #define APBDEV_PMC_DDR_PWR 0xE8 #define APBDEV_PMC_USB_AO 0xF0 #define APBDEV_PMC_CRYPTO_OP 0xF4 @@ -99,7 +101,9 @@ #define PMC_RST_STATUS_LP0 4 #define PMC_RST_STATUS_AOTAG 5 #define APBDEV_PMC_IO_DPD_REQ 0x1B8 -#define PMC_IO_DPD_REQ_DPD_OFF BIT(30) +#define PMC_IO_DPD_REQ_DPD_IDLE (0 << 30u) +#define PMC_IO_DPD_REQ_DPD_OFF (1 << 30u) +#define PMC_IO_DPD_REQ_DPD_ON (2 << 30u) #define APBDEV_PMC_IO_DPD2_REQ 0x1C0 #define APBDEV_PMC_VDDP_SEL 0x1CC #define APBDEV_PMC_DDR_CFG 0x1D0 diff --git a/bdk/soc/t210.h b/bdk/soc/t210.h index 497b4cf..f549fc2 100644 --- a/bdk/soc/t210.h +++ b/bdk/soc/t210.h @@ -40,7 +40,7 @@ #define GPU_USER_BASE 0x58000000 #define RES_SEMAPH_BASE 0x60001000 #define ARB_SEMAPH_BASE 0x60002000 -#define ARBPRI_BASE 0x60003000 +#define ARB_PRI_BASE 0x60003000 #define ICTLR_BASE 0x60004000 #define TMR_BASE 0x60005000 #define CLOCK_BASE 0x60006000 @@ -81,6 +81,7 @@ #define CL_DVFS_BASE 0x70110000 #define APE_BASE 0x702C0000 #define AHUB_BASE 0x702D0000 +#define ADMAIF_BASE 0x702D0000 #define AXBAR_BASE 0x702D0800 #define I2S_BASE 0x702D1000 #define ADMA_BASE 0x702E2000 @@ -112,6 +113,7 @@ #define SOR1(off) MMIO_REG32(SOR1_BASE, off) #define GPU(off) MMIO_REG32(GPU_BASE, off) #define GPU_USER(off) MMIO_REG32(GPU_USER_BASE, off) +#define ARB_PRI(off) MMIO_REG32(ARB_PRI_BASE, off) #define ICTLR(cidx, off) MMIO_REG32(ICTLR_BASE + (0x100 * (cidx)), off) #define TMR(off) MMIO_REG32(TMR_BASE, off) #define CLOCK(off) MMIO_REG32(CLOCK_BASE, off) @@ -174,6 +176,7 @@ #define EVP_COP_IRQ_STS 0x220 /*! Primary Interrupt Controller registers. */ +#define PRI_ICTLR_ISR 0x10 #define PRI_ICTLR_FIR 0x14 #define PRI_ICTLR_FIR_SET 0x18 #define PRI_ICTLR_FIR_CLR 0x1C @@ -186,6 +189,13 @@ #define PRI_ICTLR_COP_IER_CLR 0x38 #define PRI_ICTLR_COP_IEP_CLASS 0x3C +/* Arbiter registers */ +#define ARB_PRIO_CPU_PRIORITY 0x0 +#define ARB_PRIO_COP_PRIORITY 0x4 +#define ARB_PRIO_VCP_PRIORITY 0x8 +#define ARB_PRIO_DMA_PRIORITY 0xC +#define ARB_PRIO_UCQ_PRIORITY 0x10 + /*! AHB Gizmo registers. */ #define AHB_ARBITRATION_PRIORITY_CTRL 0x8 #define PRIORITY_CTRL_WEIGHT(x) (((x) & 7) << 29) diff --git a/bdk/soc/timer.c b/bdk/soc/timer.c index c6c5b83..786f123 100644 --- a/bdk/soc/timer.c +++ b/bdk/soc/timer.c @@ -25,6 +25,8 @@ #define EXCP_TYPE_ADDR 0x4003FFF8 #define EXCP_TYPE_WDT 0x544457 // "WDT". +#define USE_RTC_TIMER + u32 get_tmr_s() { (void)RTC(APBDEV_RTC_MILLI_SECONDS); @@ -118,4 +120,4 @@ bool watchdog_fired() { // Return if watchdog got fired. User handles clearing. return (*(u32 *)EXCP_TYPE_ADDR == EXCP_TYPE_WDT); -} \ No newline at end of file +} diff --git a/bdk/soc/uart.c b/bdk/soc/uart.c index a2efaab..c76c66e 100644 --- a/bdk/soc/uart.c +++ b/bdk/soc/uart.c @@ -174,14 +174,14 @@ void uart_empty_fifo(u32 idx, u32 which) (void)uart->UART_SPR; usleep(96); - uart->UART_IIR_FCR = UART_IIR_FCR_EN_FIFO | UART_IIR_FCR_TX_CLR | UART_IIR_FCR_RX_CLR; + uart->UART_IIR_FCR = UART_IIR_FCR_EN_FIFO | which; (void)uart->UART_SPR; usleep(18); u32 tries = 0; if (UART_IIR_FCR_TX_CLR & which) { - while (tries < 10 && uart->UART_LSR & UART_LSR_TMTY) + while (tries < 10 && !(uart->UART_LSR & UART_LSR_TMTY)) { tries++; usleep(100); @@ -191,7 +191,7 @@ void uart_empty_fifo(u32 idx, u32 which) if (UART_IIR_FCR_RX_CLR & which) { - while (tries < 10 && !uart->UART_LSR & UART_LSR_RDR) + while (tries < 10 && (uart->UART_LSR & UART_LSR_RDR)) { tries++; usleep(100); diff --git a/bdk/storage/sd.c b/bdk/storage/sd.c index f2a22ed..3ad31fa 100644 --- a/bdk/storage/sd.c +++ b/bdk/storage/sd.c @@ -274,7 +274,7 @@ void *sd_file_read(const char *path, u32 *fsize) return buf; } -int sd_save_to_file(void *buf, u32 size, const char *filename) +int sd_save_to_file(const void *buf, u32 size, const char *filename) { FIL fp; u32 res = 0; diff --git a/bdk/storage/sd.h b/bdk/storage/sd.h index 1008b65..1153996 100644 --- a/bdk/storage/sd.h +++ b/bdk/storage/sd.h @@ -61,6 +61,6 @@ void sd_unmount(); void sd_end(); bool sd_is_gpt(); void *sd_file_read(const char *path, u32 *fsize); -int sd_save_to_file(void *buf, u32 size, const char *filename); +int sd_save_to_file(const void *buf, u32 size, const char *filename); #endif \ No newline at end of file diff --git a/bdk/storage/sd_def.h b/bdk/storage/sd_def.h index 1316b50..14782bf 100644 --- a/bdk/storage/sd_def.h +++ b/bdk/storage/sd_def.h @@ -46,7 +46,7 @@ /* OCR bit definitions */ #define SD_OCR_VDD_18 (1U << 7) /* VDD voltage 1.8 */ -#define SD_VHD_27_36 (1U << 8) /* VDD voltage 2.7 ~ 3.6 */ +#define SD_VHS_27_36 (1U << 8) /* VDD voltage 2.7 ~ 3.6 */ #define SD_OCR_VDD_32_33 (1U << 20) /* VDD voltage 3.2 ~ 3.3 */ #define SD_OCR_S18R (1U << 24) /* 1.8V switching request */ #define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */ diff --git a/bdk/storage/sdmmc.c b/bdk/storage/sdmmc.c index 949a676..ceec41f 100644 --- a/bdk/storage/sdmmc.c +++ b/bdk/storage/sdmmc.c @@ -34,7 +34,7 @@ u32 sd_power_cycle_time_start; -static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size) +static inline u32 unstuff_bits(const u32 *resp, u32 start, u32 size) { const u32 mask = (size < 32 ? 1 << size : 0) - 1; const u32 off = 3 - ((start) / 32); @@ -234,6 +234,8 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out int sdmmc_storage_end(sdmmc_storage_t *storage) { + DPRINTF("[SDMMC%d] end\n", storage->sdmmc->id); + if (!_sdmmc_storage_go_idle_state(storage)) return 0; @@ -276,7 +278,7 @@ reinit_try: // Disk IO failure! Reinit SD/EMMC to a lower speed. if (storage->sdmmc->id == SDMMC_1 || storage->sdmmc->id == SDMMC_4) { - int res; + int res = 0; if (storage->sdmmc->id == SDMMC_1) { @@ -782,7 +784,7 @@ static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp } #ifdef SDMMC_DEBUG_PRINT_SD_REGS -void _sd_storage_debug_print_cid(u32 *raw_cid) +void _sd_storage_debug_print_cid(const u32 *raw_cid) { gfx_printf("Card Identification\n"); @@ -798,7 +800,7 @@ void _sd_storage_debug_print_cid(u32 *raw_cid) gfx_printf("--RSVD-- %X\n", unstuff_bits(raw_cid, 20, 4)); } -void _sd_storage_debug_print_csd(u32 *raw_csd) +void _sd_storage_debug_print_csd(const u32 *raw_csd) { gfx_printf("\n"); @@ -835,7 +837,7 @@ void _sd_storage_debug_print_csd(u32 *raw_csd) unstuff_bits(raw_csd, 16, 5), unstuff_bits(raw_csd, 8, 2)); } -void _sd_storage_debug_print_scr(u32 *raw_scr) +void _sd_storage_debug_print_scr(const u32 *raw_scr) { u32 resp[4]; memcpy(&resp[2], raw_scr, 8); @@ -856,7 +858,7 @@ void _sd_storage_debug_print_scr(u32 *raw_scr) gfx_printf("--RSVD-- %X\n", unstuff_bits(resp, 36, 2)); } -void _sd_storage_debug_print_ssr(u8 *raw_ssr) +void _sd_storage_debug_print_ssr(const u8 *raw_ssr) { u32 raw_ssr0[4]; // 511:384. u32 raw_ssr1[4]; // 383:256. @@ -911,7 +913,7 @@ void _sd_storage_debug_print_ssr(u8 *raw_ssr) static int _sd_storage_send_if_cond(sdmmc_storage_t *storage, bool *is_sdsc) { sdmmc_cmd_t cmdbuf; - u16 vhd_pattern = SD_VHD_27_36 | 0xAA; + u16 vhd_pattern = SD_VHS_27_36 | 0xAA; sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, vhd_pattern, SDMMC_RSP_TYPE_5, 0); if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL)) { @@ -1133,17 +1135,20 @@ static void _sd_storage_set_power_limit(sdmmc_storage_t *storage, u16 power_limi u32 pwr = SD_SET_POWER_LIMIT_0_72; // If UHS-I only, anything above 1.44W defaults to 1.44W. + /* if (power_limit & SD_MAX_POWER_2_88) pwr = SD_SET_POWER_LIMIT_2_88; else if (power_limit & SD_MAX_POWER_2_16) pwr = SD_SET_POWER_LIMIT_2_16; - else if (power_limit & SD_MAX_POWER_1_44) + */ + if (power_limit & SD_MAX_POWER_1_44) pwr = SD_SET_POWER_LIMIT_1_44; _sd_storage_switch(storage, buf, SD_SWITCH_SET, SD_SWITCH_GRP_PWRLIM, pwr); switch ((buf[15] >> 4) & 0x0F) { + /* case SD_SET_POWER_LIMIT_2_88: DPRINTF("[SD] power limit raised to 2880 mW\n"); break; @@ -1151,7 +1156,7 @@ static void _sd_storage_set_power_limit(sdmmc_storage_t *storage, u16 power_limi case SD_SET_POWER_LIMIT_2_16: DPRINTF("[SD] power limit raised to 2160 mW\n"); break; - + */ case SD_SET_POWER_LIMIT_1_44: DPRINTF("[SD] power limit raised to 1440 mW\n"); break; @@ -1397,7 +1402,7 @@ static int _sd_storage_enable_uhs_low_volt(sdmmc_storage_t *storage, u32 type, u } // Try to raise the power limit to let the card perform better. - if (hs_type != UHS_SDR25_BUS_SPEED) + if (hs_type != UHS_SDR25_BUS_SPEED) // Not applicable for SDR12/SDR25. _sd_storage_set_power_limit(storage, fmodes.power_limit, buf); // Setup and set selected card and bus speed. @@ -1425,9 +1430,6 @@ static int _sd_storage_enable_hs_high_volt(sdmmc_storage_t *storage, u8 *buf) DPRINTF("[SD] access: %02X, power: %02X\n", fmodes.access_mode, fmodes.power_limit); - // Try to raise the power limit to let the card perform better. - _sd_storage_set_power_limit(storage, fmodes.power_limit, buf); - if (!(fmodes.access_mode & SD_MODE_HIGH_SPEED)) return 1; diff --git a/bdk/storage/sdmmc_driver.c b/bdk/storage/sdmmc_driver.c index 7243e2a..95336e2 100644 --- a/bdk/storage/sdmmc_driver.c +++ b/bdk/storage/sdmmc_driver.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2023 CTCaer + * Copyright (c) 2018-2024 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -109,8 +109,8 @@ void sdmmc_save_tap_value(sdmmc_t *sdmmc) static int _sdmmc_config_tap_val(sdmmc_t *sdmmc, u32 type) { - const u32 dqs_trim_val = 40; // 24 if HS533/HS667. - const u8 tap_values_t210[4] = { 4, 0, 3, 0 }; + static const u32 dqs_trim_val = 40; // 24 if HS533/HS667. + static const u8 tap_values_t210[4] = { 4, 0, 3, 0 }; u32 tap_val = 0; @@ -222,6 +222,9 @@ static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power) { sdmmc->regs->autocalcfg &= ~SDHCI_TEGRA_AUTOCAL_ENABLE; _sdmmc_pad_config_fallback(sdmmc, power); +#ifdef ERROR_EXTRA_PRINTING + EPRINTFARGS("SDMMC%d: Comp Pad cal timeout!", sdmmc->id + 1); +#endif } // Disable E_INPUT (SD) or enable E_PWRD (eMMC) to conserve power. @@ -403,7 +406,7 @@ static void _sdmmc_card_clock_enable(sdmmc_t *sdmmc) sdmmc->card_clock_enabled = 1; } -static void _sdmmc_sd_clock_disable(sdmmc_t *sdmmc) +static void _sdmmc_card_clock_disable(sdmmc_t *sdmmc) { sdmmc->card_clock_enabled = 0; sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; @@ -572,7 +575,7 @@ static int _sdmmc_setup_read_small_block(sdmmc_t *sdmmc) return 1; } -static int _sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, bool is_data_present) +static int _sdmmc_send_cmd(sdmmc_t *sdmmc, const sdmmc_cmd_t *cmd, bool is_data_present) { u16 cmdflags = 0; @@ -934,7 +937,7 @@ static u32 _sdmmc_check_mask_interrupt(sdmmc_t *sdmmc, u16 *pout, u16 mask) if (norintsts & SDHCI_INT_ERROR) { #ifdef ERROR_EXTRA_PRINTING - EPRINTFARGS("SDMMC%d: norintsts %08X, errintsts %08X\n", sdmmc->id + 1, norintsts, errintsts); + EPRINTFARGS("SDMMC%d: norintsts %08X, errintsts %08X", sdmmc->id + 1, norintsts, errintsts); #endif sdmmc->regs->errintsts = errintsts; return SDMMC_MASKINT_ERROR; @@ -1022,7 +1025,7 @@ int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp) return result; } -static int _sdmmc_config_sdma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req) +static int _sdmmc_config_sdma(sdmmc_t *sdmmc, u32 *blkcnt_out, const sdmmc_req_t *req) { if (!req->blksize || !req->num_sectors) return 0; @@ -1152,7 +1155,7 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_ int result = _sdmmc_wait_response(sdmmc); #ifdef ERROR_EXTRA_PRINTING if (!result) - EPRINTFARGS("SDMMC%d: Transfer timeout!", sdmmc->id + 1); + EPRINTFARGS("SDMMC%d: Transfer error!", sdmmc->id + 1); #endif DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result, sdmmc->regs->rspreg0, sdmmc->regs->rspreg1, sdmmc->regs->rspreg2, sdmmc->regs->rspreg3); @@ -1273,16 +1276,7 @@ static int _sdmmc_config_sdmmc1(bool t210b01) if (!sdmmc_get_sd_inserted()) return 0; - /* - * Pinmux config: - * DRV_TYPE = DRIVE_2X (for 33 Ohm driver) - * E_SCHMT = ENABLE (for 1.8V), DISABLE (for 3.3V) - * E_INPUT = ENABLE - * TRISTATE = PASSTHROUGH - * APB_MISC_GP_SDMMCx_CLK_LPBK_CONTROL = SDMMCx_CLK_PAD_E_LPBK for CLK - */ - - // Enable deep loopback for SDMMC1 CLK pad. + // Enable deep loopback for SDMMC1 CLK pad so reads work. APB_MISC(APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL) = 1; // Configure SDMMC1 CLK pinmux, based on state and SoC type. @@ -1302,18 +1296,18 @@ static int _sdmmc_config_sdmmc1(bool t210b01) _sdmmc_config_sdmmc1_schmitt(); // Make sure the SDMMC1 controller is powered. - PMC(APBDEV_PMC_NO_IOPOWER) |= PMC_NO_IOPOWER_SDMMC1_IO_EN; + PMC(APBDEV_PMC_NO_IOPOWER) |= PMC_NO_IOPOWER_SDMMC1; usleep(1000); - PMC(APBDEV_PMC_NO_IOPOWER) &= ~(PMC_NO_IOPOWER_SDMMC1_IO_EN); + PMC(APBDEV_PMC_NO_IOPOWER) &= ~PMC_NO_IOPOWER_SDMMC1; (void)PMC(APBDEV_PMC_NO_IOPOWER); // Commit write. - // Set enable SD card power. + // Enable SD card power. Powers LDO2 also. PINMUX_AUX(PINMUX_AUX_DMIC3_CLK) = PINMUX_PULL_DOWN | 2; gpio_direction_output(GPIO_PORT_E, GPIO_PIN_4, GPIO_HIGH); usleep(10000); // Inform IO pads that voltage is gonna be 3.3V. - PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_SDMMC1_IO_EN; + PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_33V_SDMMC1; (void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write. // Enable SD card IO power. @@ -1366,8 +1360,8 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type) u16 divisor; u8 vref_sel = 7; - const u8 trim_values_t210[4] = { 2, 8, 3, 8 }; - const u8 trim_values_t210b01[4] = { 14, 13, 15, 13 }; + static const u8 trim_values_t210[4] = { 2, 8, 3, 8 }; + static const u8 trim_values_t210b01[4] = { 14, 13, 15, 13 }; const u8 *trim_values; if (id > SDMMC_4 || id == SDMMC_3) @@ -1403,19 +1397,18 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type) // Disable clock if enabled. if (clock_sdmmc_is_not_reset_and_enabled(id)) { - _sdmmc_sd_clock_disable(sdmmc); + _sdmmc_card_clock_disable(sdmmc); _sdmmc_commit_changes(sdmmc); } // Configure and enable selected clock. clock_sdmmc_get_card_clock_div(&clock, &divisor, type); clock_sdmmc_enable(id, clock); + sdmmc->clock_stopped = 0; // Make sure all sdmmc registers are reset. _sdmmc_reset_all(sdmmc); - sdmmc->clock_stopped = 0; - // Set default pad IO trimming configuration. sdmmc->regs->iospare |= BIT(19); // Enable 1 cycle delayed cmd_oen. sdmmc->regs->veniotrimctl &= ~BIT(2); // Set Band Gap VREG to supply DLL. @@ -1456,23 +1449,23 @@ void sdmmc1_disable_power() // T210B01 WAR: Set pads to discharge state. _sdmmc_config_sdmmc1_pads(true); - // Disable SD card IO power regulator. + // Disable SD card IO power. max7762x_regulator_enable(REGULATOR_LDO2, false); usleep(4000); - // Disable SD card IO power pin. + // Disable SD card power. gpio_write(GPIO_PORT_E, GPIO_PIN_4, GPIO_LOW); // T210/T210B01 WAR: Set start timer for IO and Controller power discharge. sd_power_cycle_time_start = get_tmr_ms(); - usleep(1000); // To power cycle, min 1ms without power is needed. + usleep(10000); // To power cycle, min 1ms without power is needed. // Disable SDMMC1 controller power. - PMC(APBDEV_PMC_NO_IOPOWER) |= PMC_NO_IOPOWER_SDMMC1_IO_EN; + PMC(APBDEV_PMC_NO_IOPOWER) |= PMC_NO_IOPOWER_SDMMC1; (void)PMC(APBDEV_PMC_NO_IOPOWER); // Commit write. // Inform IO pads that next voltage might be 3.3V. - PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_SDMMC1_IO_EN; + PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_33V_SDMMC1; (void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write. // T210B01 WAR: Restore pads to reset state. @@ -1486,7 +1479,7 @@ void sdmmc_end(sdmmc_t *sdmmc) { if (!sdmmc->clock_stopped) { - _sdmmc_sd_clock_disable(sdmmc); + _sdmmc_card_clock_disable(sdmmc); // Disable SDMMC power. _sdmmc_set_io_power(sdmmc, SDMMC_POWER_OFF); _sdmmc_commit_changes(sdmmc); @@ -1547,7 +1540,7 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc) usleep(150); // Inform IO pads that we switched to 1.8V. - PMC(APBDEV_PMC_PWR_DET_VAL) &= ~(PMC_PWR_DET_SDMMC1_IO_EN); + PMC(APBDEV_PMC_PWR_DET_VAL) &= ~PMC_PWR_DET_33V_SDMMC1; (void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write. // Enable schmitt trigger for better duty cycle and low jitter clock. diff --git a/bdk/thermal/fan.c b/bdk/thermal/fan.c index 6927fe4..22bddcc 100644 --- a/bdk/thermal/fan.c +++ b/bdk/thermal/fan.c @@ -1,7 +1,7 @@ /* * Fan driver for Nintendo Switch * - * Copyright (c) 2018-2023 CTCaer + * Copyright (c) 2018-2024 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -27,7 +27,7 @@ #include #include -void set_fan_duty(u32 duty) +void fan_set_duty(u32 duty) { static bool fan_init = false; static u16 curr_duty = -1; @@ -49,16 +49,8 @@ void set_fan_duty(u32 duty) // Enable PWM if disabled. if (fuse_read_hw_type() == FUSE_NX_HW_TYPE_AULA) - { - // Ease the stress to APB. - bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL); - clock_enable_pwm(); - // Restore OC. - bpmp_clk_rate_set(prev_fid); - } - PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (0x100 << 16); // Max PWM to disable fan. PINMUX_AUX(PINMUX_AUX_LCD_GPIO2) = 1; // Set source to PWM1. @@ -91,7 +83,7 @@ void set_fan_duty(u32 duty) } } -void get_fan_speed(u32 *duty, u32 *rpm) +void fan_get_speed(u32 *duty, u32 *rpm) { if (rpm) { @@ -122,3 +114,15 @@ void get_fan_speed(u32 *duty, u32 *rpm) if (duty) *duty = 236 - ((PWM(PWM_CONTROLLER_PWM_CSR_1) >> 16) & 0xFF); } + +void fan_set_from_temp(u32 temp) +{ + if (temp >= 52) + fan_set_duty(102); + else if (temp >= 47) + fan_set_duty(76); + else if (temp >= 42) + fan_set_duty(51); + else if (temp <= 39) + fan_set_duty(0); +} diff --git a/bdk/thermal/fan.h b/bdk/thermal/fan.h index e827975..3c70b30 100644 --- a/bdk/thermal/fan.h +++ b/bdk/thermal/fan.h @@ -1,7 +1,7 @@ /* * Fan driver for Nintendo Switch * - * Copyright (c) 2018 CTCaer + * Copyright (c) 2018-2024 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -22,8 +22,10 @@ #include // Disable: 0 (0 RPM), min duty: 1 (960 RPM), max duty 235 (11000 RPM). -void set_fan_duty(u32 duty); -// Passing NULL ptr on either of the two, disables parsing of it. -void get_fan_speed(u32 *duty, u32 *rpm); +void fan_set_duty(u32 duty); +// Passing NULL ptr on either of the two, disables results. +void fan_get_speed(u32 *duty, u32 *rpm); + +void fan_set_from_temp(u32 temp); #endif /* __FAN_H_ */ diff --git a/bdk/usb/usb_gadget_hid.c b/bdk/usb/usb_gadget_hid.c index 572852c..7929836 100644 --- a/bdk/usb/usb_gadget_hid.c +++ b/bdk/usb/usb_gadget_hid.c @@ -71,10 +71,16 @@ typedef struct _jc_cal_t u16 cry_min; } jc_cal_t; +enum { + INPUT_POLL_HAS_PACKET, + INPUT_POLL_NO_PACKET, + INPUT_POLL_EXIT, +}; + static jc_cal_t jc_cal_ctx; static usb_ops_t usb_ops; -static bool _jc_calibration(jc_gamepad_rpt_t *jc_pad) +static bool _jc_calibration(const jc_gamepad_rpt_t *jc_pad) { // Calibrate left stick. if (jc_cal_ctx.cl_step != JC_CAL_MAX_STEPS) @@ -119,22 +125,24 @@ static bool _jc_calibration(jc_gamepad_rpt_t *jc_pad) return true; } -static bool _jc_poll(gamepad_report_t *rpt) +static int _jc_poll(gamepad_report_t *rpt) { + static gamepad_report_t prev_rpt = {0}; + // Poll Joy-Con. jc_gamepad_rpt_t *jc_pad = joycon_poll(); if (!jc_pad) - return false; + return INPUT_POLL_NO_PACKET; // Exit emulation if Left stick and Home are pressed. if (jc_pad->l3 && jc_pad->home) - return true; + return INPUT_POLL_EXIT; if (jc_cal_ctx.cl_step != JC_CAL_MAX_STEPS || jc_cal_ctx.cr_step != JC_CAL_MAX_STEPS) { if (!_jc_calibration(jc_pad)) - return false; + return INPUT_POLL_NO_PACKET; } // Re-calibrate on disconnection. @@ -282,7 +290,12 @@ static bool _jc_poll(gamepad_report_t *rpt) //rpt->btn13 = jc_pad->cap; //rpt->btn14 = jc_pad->home; - return false; + if (!memcmp(rpt, &prev_rpt, sizeof(gamepad_report_t))) + return INPUT_POLL_NO_PACKET; + + memcpy(&prev_rpt, rpt, sizeof(gamepad_report_t)); + + return INPUT_POLL_HAS_PACKET; } typedef struct _touchpad_report_t @@ -351,12 +364,14 @@ static u8 _hid_transfer_start(usb_ctxt_t *usbs, u32 len) static bool _hid_poll_jc(usb_ctxt_t *usbs) { - if (_jc_poll((gamepad_report_t *)USB_EP_BULK_IN_BUF_ADDR)) + int res = _jc_poll((gamepad_report_t *)USB_EP_BULK_IN_BUF_ADDR); + if (res == INPUT_POLL_EXIT) return true; // Send HID report. - if (_hid_transfer_start(usbs, sizeof(gamepad_report_t))) - return true; // EP Error. + if (res == INPUT_POLL_HAS_PACKET) + if (_hid_transfer_start(usbs, sizeof(gamepad_report_t))) + return true; // EP Error. return false; } diff --git a/bdk/usb/usb_gadget_ums.c b/bdk/usb/usb_gadget_ums.c index e4d8071..d7e146c 100644 --- a/bdk/usb/usb_gadget_ums.c +++ b/bdk/usb/usb_gadget_ums.c @@ -4,7 +4,7 @@ * Copyright (c) 2003-2008 Alan Stern * Copyright (c) 2009 Samsung Electronics * Author: Michal Nazarewicz - * Copyright (c) 2019-2023 CTCaer + * Copyright (c) 2019-2024 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -32,6 +32,7 @@ #include #include #include +#include #include @@ -758,7 +759,7 @@ static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) buf += 4; s_printf((char *)buf, "%04X%s", - ums->lun.storage->cid.serial, ums->lun.type == MMC_SD ? " SD卡 " : " eMMC "); + ums->lun.storage->cid.serial, ums->lun.type == MMC_SD ? " SD " : " eMMC "); switch (ums->lun.partition) { @@ -803,15 +804,15 @@ static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt) break; case EMMC_GPP + 1: s_printf((char *)buf, "%s%s", - ums->lun.type == MMC_SD ? "SD卡 " : "eMMC ", "GPP"); + ums->lun.type == MMC_SD ? "SD " : "eMMC ", "GPP"); break; case EMMC_BOOT0 + 1: s_printf((char *)buf, "%s%s", - ums->lun.type == MMC_SD ? "SD卡 " : "eMMC ", "BOOT0"); + ums->lun.type == MMC_SD ? "SD " : "eMMC ", "BOOT0"); break; case EMMC_BOOT1 + 1: s_printf((char *)buf, "%s%s", - ums->lun.type == MMC_SD ? "SD卡 " : "eMMC ", "BOOT1"); + ums->lun.type == MMC_SD ? "SD " : "eMMC ", "BOOT1"); break; } @@ -1843,10 +1844,11 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs) ums.bulk_ctxt.bulk_out_buf = (u8 *)USB_EP_BULK_OUT_BUF_ADDR; // Set LUN parameters. - ums.lun.ro = usbs->ro; - ums.lun.type = usbs->type; - ums.lun.partition = usbs->partition; - ums.lun.offset = usbs->offset; + ums.lun.ro = usbs->ro; + ums.lun.type = usbs->type; + ums.lun.partition = usbs->partition; + ums.lun.num_sectors = usbs->sectors; + ums.lun.offset = usbs->offset; ums.lun.removable = 1; // Always removable to force OSes to use prevent media removal. ums.lun.unit_attention_data = SS_RESET_OCCURRED; @@ -1899,10 +1901,14 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs) ums.set_text(ums.label, "#C7EA46 状态:#开启UMS"); - if (usbs->sectors) - ums.lun.num_sectors = usbs->sectors; - else - ums.lun.num_sectors = ums.lun.storage->sec_cnt; + // If partition sectors are not set get them from hardware. + if (!ums.lun.num_sectors) + { + if (usbs->type == MMC_EMMC && (ums.lun.partition - 1)) // eMMC BOOT0/1. + ums.lun.num_sectors = emmc_storage.ext_csd.boot_mult << 8; + else + ums.lun.num_sectors = ums.lun.storage->sec_cnt; // eMMC GPP or SD. + } do { @@ -1932,7 +1938,9 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs) _handle_ep0_ctrl(&ums); - if (_parse_scsi_cmd(&ums, &ums.bulk_ctxt) || (ums.state > UMS_STATE_NORMAL)) + _parse_scsi_cmd(&ums, &ums.bulk_ctxt); + + if (ums.state > UMS_STATE_NORMAL) continue; _handle_ep0_ctrl(&ums); diff --git a/bdk/usb/usbd.c b/bdk/usb/usbd.c index 83f9ce7..2a7fe97 100644 --- a/bdk/usb/usbd.c +++ b/bdk/usb/usbd.c @@ -1,7 +1,7 @@ /* * Enhanced USB Device (EDCI) driver for Tegra X1 * - * Copyright (c) 2019-2023 CTCaer + * Copyright (c) 2019-2024 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -355,9 +355,15 @@ int usb_device_init() if (usb_init_done) return USB_RES_OK; + // Ease the stress to APB. + bpmp_clk_rate_relaxed(true); + // Initialize USB2 controller PHY. _usb_init_phy(); + // Restore OC. + bpmp_clk_rate_relaxed(false); + // AHB USB performance cfg. AHB_GIZMO(AHB_GIZMO_AHB_MEM) |= AHB_MEM_DONT_SPLIT_AHB_WR | AHB_MEM_ENB_FAST_REARBITRATE; AHB_GIZMO(AHB_GIZMO_USB) |= AHB_GIZMO_IMMEDIATE; diff --git a/bdk/usb/xusbd.c b/bdk/usb/xusbd.c index c14816d..87df551 100644 --- a/bdk/usb/xusbd.c +++ b/bdk/usb/xusbd.c @@ -1,7 +1,7 @@ /* * eXtensible USB Device driver (XDCI) for Tegra X1 * - * Copyright (c) 2020-2022 CTCaer + * Copyright (c) 2020-2024 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -883,6 +883,9 @@ static void _xusbd_init_device_clocks() int xusb_device_init() { + // Ease the stress to APB. + bpmp_clk_rate_relaxed(true); + // Disable USB2 device controller clocks. CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_USBD); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_USBD); @@ -920,6 +923,9 @@ int xusb_device_init() // Initialize device clocks. _xusbd_init_device_clocks(); + // Restore OC. + bpmp_clk_rate_relaxed(false); + // Enable AHB redirect for access to IRAM for Event/EP ring buffers. mc_enable_ahb_redirect(); @@ -1005,7 +1011,7 @@ static void _xusb_device_power_down() CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = BIT(CLK_W_XUSB); } -static int _xusb_queue_trb(u32 ep_idx, void *trb, bool ring_doorbell) +static int _xusb_queue_trb(u32 ep_idx, const void *trb, bool ring_doorbell) { int res = USB_RES_OK; data_trb_t *next_trb; @@ -1220,7 +1226,7 @@ static int _xusb_wait_ep_stopped(u32 endpoint) return USB_RES_OK; } -static int _xusb_handle_transfer_event(transfer_event_trb_t *trb) +static int _xusb_handle_transfer_event(const transfer_event_trb_t *trb) { // Advance dequeue list. data_trb_t *next_trb; @@ -1455,7 +1461,7 @@ static int _xusb_handle_get_ep_status(u32 ep_idx) return _xusb_issue_data_trb(xusb_ep_status_descriptor, 2, USB_DIR_IN); } -static int _xusb_handle_get_class_request(usb_ctrl_setup_t *ctrl_setup) +static int _xusb_handle_get_class_request(const usb_ctrl_setup_t *ctrl_setup) { u8 _bRequest = ctrl_setup->bRequest; u16 _wIndex = ctrl_setup->wIndex; @@ -1486,7 +1492,7 @@ stall: return USB_RES_OK; } -static int _xusb_handle_get_descriptor(usb_ctrl_setup_t *ctrl_setup) +static int _xusb_handle_get_descriptor(const usb_ctrl_setup_t *ctrl_setup) { u32 size; void *descriptor; @@ -1615,7 +1621,7 @@ static int _xusb_handle_get_descriptor(usb_ctrl_setup_t *ctrl_setup) return _xusb_issue_data_trb(descriptor, size, USB_DIR_IN); } -static void _xusb_handle_set_request_dev_address(usb_ctrl_setup_t *ctrl_setup) +static void _xusb_handle_set_request_dev_address(const usb_ctrl_setup_t *ctrl_setup) { u32 addr = ctrl_setup->wValue & 0xFF; @@ -1627,7 +1633,7 @@ static void _xusb_handle_set_request_dev_address(usb_ctrl_setup_t *ctrl_setup) usbd_xotg->device_state = XUSB_ADDRESSED_STS_WAIT; } -static void _xusb_handle_set_request_configuration(usb_ctrl_setup_t *ctrl_setup) +static void _xusb_handle_set_request_configuration(const usb_ctrl_setup_t *ctrl_setup) { usbd_xotg->config_num = ctrl_setup->wValue; diff --git a/bdk/utils/dirlist.c b/bdk/utils/dirlist.c index 5197c01..77174aa 100644 --- a/bdk/utils/dirlist.c +++ b/bdk/utils/dirlist.c @@ -17,21 +17,23 @@ #include #include +#include "dirlist.h" #include #include #include -#define MAX_ENTRIES 64 - -char *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs) +dirlist_t *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs) { int res = 0; - u32 i = 0, j = 0, k = 0; + u32 k = 0; DIR dir; FILINFO fno; - char *dir_entries = (char *)zalloc(MAX_ENTRIES * 256); - char *temp = (char *)zalloc(256); + dirlist_t *dir_entries = (dirlist_t *)malloc(sizeof(dirlist_t)); + + // Setup pointer tree. + for (u32 i = 0; i < DIR_MAX_ENTRIES; i++) + dir_entries->name[i] = &dir_entries->data[i * 256]; if (!pattern && !f_opendir(&dir, directory)) { @@ -47,9 +49,8 @@ char *dirlist(const char *directory, const char *pattern, bool includeHiddenFile { if ((fno.fname[0] != '.') && (includeHiddenFiles || !(fno.fattrib & AM_HID))) { - strcpy(dir_entries + (k * 256), fno.fname); - k++; - if (k > (MAX_ENTRIES - 1)) + strcpy(&dir_entries->data[k * 256], fno.fname); + if (++k >= DIR_MAX_ENTRIES) break; } } @@ -62,9 +63,8 @@ char *dirlist(const char *directory, const char *pattern, bool includeHiddenFile { if (!(fno.fattrib & AM_DIR) && (fno.fname[0] != '.') && (includeHiddenFiles || !(fno.fattrib & AM_HID))) { - strcpy(dir_entries + (k * 256), fno.fname); - k++; - if (k > (MAX_ENTRIES - 1)) + strcpy(&dir_entries->data[k * 256], fno.fname); + if (++k >= DIR_MAX_ENTRIES) break; } res = f_findnext(&dir, &fno); @@ -74,27 +74,27 @@ char *dirlist(const char *directory, const char *pattern, bool includeHiddenFile if (!k) { - free(temp); free(dir_entries); return NULL; } + // Terminate name list. + dir_entries->name[k] = NULL; + // Reorder ini files by ASCII ordering. - for (i = 0; i < k - 1 ; i++) + for (u32 i = 0; i < k - 1 ; i++) { - for (j = i + 1; j < k; j++) + for (u32 j = i + 1; j < k; j++) { - if (strcmp(&dir_entries[i * 256], &dir_entries[j * 256]) > 0) + if (strcmp(dir_entries->name[i], dir_entries->name[j]) > 0) { - strcpy(temp, &dir_entries[i * 256]); - strcpy(&dir_entries[i * 256], &dir_entries[j * 256]); - strcpy(&dir_entries[j * 256], temp); + char *tmp = dir_entries->name[i]; + dir_entries->name[i] = dir_entries->name[j]; + dir_entries->name[j] = tmp; } } } - free(temp); - return dir_entries; } diff --git a/bdk/utils/dirlist.h b/bdk/utils/dirlist.h index 32197f3..cb250c3 100644 --- a/bdk/utils/dirlist.h +++ b/bdk/utils/dirlist.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 CTCaer + * Copyright (c) 2018-2024 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -16,4 +16,12 @@ #include -char *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs); +#define DIR_MAX_ENTRIES 64 + +typedef struct _dirlist_t +{ + char *name[DIR_MAX_ENTRIES]; + char data[DIR_MAX_ENTRIES * 256]; +} dirlist_t; + +dirlist_t *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs); diff --git a/bdk/utils/ini.c b/bdk/utils/ini.c index 104b261..6832bdc 100644 --- a/bdk/utils/ini.c +++ b/bdk/utils/ini.c @@ -53,7 +53,7 @@ ini_sec_t *_ini_create_section(link_t *dst, ini_sec_t *csec, char *name, u8 type return csec; } -int ini_parse(link_t *dst, char *ini_path, bool is_dir) +int ini_parse(link_t *dst, const char *ini_path, bool is_dir) { FIL fp; u32 lblen; @@ -62,7 +62,7 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir) ini_sec_t *csec = NULL; char *lbuf = NULL; - char *filelist = NULL; + dirlist_t *filelist = NULL; char *filename = (char *)malloc(256); strcpy(filename, ini_path); @@ -85,9 +85,9 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir) // Copy ini filename in path string. if (is_dir) { - if (filelist[k * 256]) + if (filelist->name[k]) { - strcpy(filename + pathlen, &filelist[k * 256]); + strcpy(filename + pathlen, filelist->name[k]); k++; } else diff --git a/bdk/utils/ini.h b/bdk/utils/ini.h index 929a850..35c13c8 100644 --- a/bdk/utils/ini.h +++ b/bdk/utils/ini.h @@ -43,7 +43,7 @@ typedef struct _ini_sec_t u32 color; } ini_sec_t; -int ini_parse(link_t *dst, char *ini_path, bool is_dir); +int ini_parse(link_t *dst, const char *ini_path, bool is_dir); char *ini_check_special_section(ini_sec_t *cfg); void ini_free(link_t *src); diff --git a/bdk/utils/sprintf.c b/bdk/utils/sprintf.c index 0ba1466..d21c5be 100644 --- a/bdk/utils/sprintf.c +++ b/bdk/utils/sprintf.c @@ -28,10 +28,32 @@ static void _s_putc(char c) *sout_buf += 1; } -static void _s_puts(char *s) +static void _s_putspace(int fcnt) { + if (fcnt <= 0) + return; + + for (int i = 0; i < fcnt; i++) + _s_putc(' '); +} + +static void _s_puts(char *s, char fill, int fcnt) +{ + if (fcnt) + { + fcnt = fcnt - strlen(s); + + // Left padding. Check if padding is not space based (dot counts as such). + if (fill != '.') + _s_putspace(fcnt); + } + for (; *s; s++) _s_putc(*s); + + // Right padding. Check if padding is space based (dot counts as such). + if (fill == '.') + _s_putspace(fcnt); } static void _s_putn(u32 v, int base, char fill, int fcnt) @@ -75,9 +97,28 @@ static void _s_putn(u32 v, int base, char fill, int fcnt) } } - _s_puts(p); + _s_puts(p, 0, 0); } +/* + * Padding: + * Numbers: + * %3d: Fill: ' ', Count: 3. + * % 3d: Fill: ' ', Count: 3. + * %.3d: Fill: '.', Count: 3. + * %23d: Fill: '2', Count: 3. + * % 23d: Fill: ' ', Count: 23. + * %223d: Fill: '2', Count: 23. + * + * Strings, Fill: ' ': + * %3s: Count: 5, Left. + * %23s: Count: 5, Left. + * %223s: Count: 25, Left. + * %.3s: Count: 5, Right. + * %.23s: Count: 25, Right. + * %.223s: Count: 225, Right. + */ + void s_printf(char *out_buf, const char *fmt, ...) { va_list ap; @@ -94,8 +135,8 @@ void s_printf(char *out_buf, const char *fmt, ...) fill = 0; fcnt = 0; - // Check for padding. Number or space based. - if ((*fmt >= '0' && *fmt <= '9') || *fmt == ' ') + // Check for padding. Number or space based (dot count as space for string). + if ((*fmt >= '0' && *fmt <= '9') || *fmt == ' ' || *fmt == '.') { fcnt = *fmt; // Padding size or padding type. fmt++; @@ -132,7 +173,7 @@ parse_padding_dec: break; case 's': - _s_puts(va_arg(ap, char *)); + _s_puts(va_arg(ap, char *), fill, fcnt); break; case 'd': @@ -221,7 +262,7 @@ parse_padding_dec: break; case 's': - _s_puts(va_arg(ap, char *)); + _s_puts(va_arg(ap, char *), fill, fcnt); break; case 'd': diff --git a/bdk/utils/sprintf.h b/bdk/utils/sprintf.h index c523267..94ce468 100644 --- a/bdk/utils/sprintf.h +++ b/bdk/utils/sprintf.h @@ -21,7 +21,25 @@ #include +/* + * Padding: + * Numbers: + * %3d: Fill: ' ', Count: 3. + * % 3d: Fill: ' ', Count: 3. + * %23d: Fill: '2', Count: 3. + * % 23d: Fill: ' ', Count: 23. + * %223d: Fill: '2', Count: 23. + * + * Strings, Fill: ' ': + * %3s: Count: 5, Left. + * %23s: Count: 5, Left. + * %223s: Count: 25, Left. + * %.3s: Count: 5, Right. + * %.23s: Count: 25, Right. + * %.223s: Count: 225, Right. + */ + void s_printf(char *out_buf, const char *fmt, ...) __attribute__((format(printf, 2, 3))); void s_vprintf(char *out_buf, const char *fmt, va_list ap); -#endif \ No newline at end of file +#endif diff --git a/bdk/utils/types.h b/bdk/utils/types.h index 0cdb2c4..0798019 100644 --- a/bdk/utils/types.h +++ b/bdk/utils/types.h @@ -98,10 +98,12 @@ typedef unsigned long uptr; #define OFFSET_OF(t, m) ((uptr)&((t *)NULL)->m) #define CONTAINER_OF(mp, t, mn) ((t *)((uptr)mp - OFFSET_OF(t, mn))) -#define byte_swap_16(num) ((((num) >> 8) & 0xff) | (((num) << 8) & 0xff00)) -#define byte_swap_32(num) ((((num) >> 24) & 0xff) | (((num) << 8) & 0xff0000) | \ - (((num) >> 8 ) & 0xff00) | (((num) << 24) & 0xff000000)) +#define byte_swap_16(num) ((((num) >> 8) & 0xFF) | (((num) & 0xFF) << 8)) +#define byte_swap_32(num) ((((num) >> 24) & 0xFF) | (((num) & 0xFF00) << 8 ) | \ + (((num) >> 8 ) & 0xFF00) | (((num) & 0xFF) << 24)) +#define likely(x) (__builtin_expect((x) != 0, 1)) +#define unlikely(x) (__builtin_expect((x) != 0, 0)) /* Bootloader/Nyx */ #define BOOT_CFG_AUTOBOOT_EN BIT(0) diff --git a/bdk/utils/util.c b/bdk/utils/util.c index 0f97971..3f8b817 100644 --- a/bdk/utils/util.c +++ b/bdk/utils/util.c @@ -29,8 +29,6 @@ #include #include -#define USE_RTC_TIMER - u8 bit_count(u32 val) { u8 cnt = 0; @@ -197,10 +195,32 @@ int atoi(const char *nptr) return (int)strtol(nptr, (char **)NULL, 10); } -void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops) +void reg_write_array(u32 *base, const reg_cfg_t *cfg, u32 num_cfg) { - for (u32 i = 0; i < num_ops; i++) - base[ops[i].off] = ops[i].val; + // Expected register offset is a u32 array index. + for (u32 i = 0; i < num_cfg; i++) + base[cfg[i].idx] = cfg[i].val; +} + +u16 crc16_calc(const u8 *buf, u32 len) +{ + const u8 *p, *q; + u16 crc = 0x55aa; + + static u16 table[16] = { + 0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401, + 0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400 + }; + + q = buf + len; + for (p = buf; p < q; p++) + { + u8 oct = *p; + crc = (crc >> 4) ^ table[crc & 0xf] ^ table[(oct >> 0) & 0xf]; + crc = (crc >> 4) ^ table[crc & 0xf] ^ table[(oct >> 4) & 0xf]; + } + + return crc; } u32 crc32_calc(u32 crc, const u8 *buf, u32 len) @@ -262,7 +282,7 @@ void power_set_state(power_state_t state) sd_end(); // De-initialize and power down various hardware. - hw_reinit_workaround(false, 0); + hw_deinit(false, 0); // Set power state. switch (state) diff --git a/bdk/utils/util.h b/bdk/utils/util.h index 2ba268a..c8ef6a3 100644 --- a/bdk/utils/util.h +++ b/bdk/utils/util.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2022 CTCaer + * Copyright (c) 2018-2024 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -21,8 +21,6 @@ #include #include -#define CFG_SIZE(array) (sizeof(array) / sizeof(cfg_op_t)) - #define NYX_NEW_INFO 0x3058594E typedef enum @@ -59,6 +57,12 @@ typedef struct _cfg_op_t u32 val; } cfg_op_t; +typedef struct _reg_cfg_t +{ + u32 idx; + u32 val; +} reg_cfg_t; + typedef struct _nyx_info_t { u32 magic; @@ -88,7 +92,9 @@ u64 sqrt64(u64 num); long strtol(const char *nptr, char **endptr, register int base); int atoi(const char *nptr); +void reg_write_array(u32 *base, const reg_cfg_t *cfg, u32 num_cfg); void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops); +u16 crc16_calc(const u8 *buf, u32 len); u32 crc32_calc(u32 crc, const u8 *buf, u32 len); void panic(u32 val); diff --git a/source/hos/sept.c b/source/hos/sept.c index a086d91..993f671 100644 --- a/source/hos/sept.c +++ b/source/hos/sept.c @@ -175,7 +175,7 @@ int reboot_to_sept(const u8 *tsec_fw, const u32 tsec_size, const u32 kb) PMC(APBDEV_PMC_SCRATCH33) = SEPT_PRI_ADDR; PMC(APBDEV_PMC_SCRATCH40) = 0x6000F208; - hw_reinit_workaround(false, 0); + hw_deinit(false, 0); (*sept)(); diff --git a/source/main.c b/source/main.c index 91950da..21315df 100644 --- a/source/main.c +++ b/source/main.c @@ -138,12 +138,12 @@ int launch_payload(char *path) { reloc_patcher(PATCHED_RELOC_ENTRY, EXT_PAYLOAD_ADDR, ALIGN(size, 0x10)); - hw_reinit_workaround(false, byte_swap_32(*(u32 *)(buf + size - sizeof(u32)))); + hw_deinit(false, byte_swap_32(*(u32 *)(buf + size - sizeof(u32)))); } else { reloc_patcher(PATCHED_RELOC_ENTRY, EXT_PAYLOAD_ADDR, 0x7000); - hw_reinit_workaround(true, 0); + hw_deinit(true, 0); } // Some cards (Sandisk U1), do not like a fast power cycle. Wait min 100ms. @@ -233,7 +233,7 @@ void ipl_main() pivot_stack(IPL_STACK_TOP); // Tegra/Horizon configuration goes to 0x80000000+, package2 goes to 0xA9800000, we place our heap in between. - heap_init(IPL_HEAP_START); + heap_init((void *)IPL_HEAP_START); #ifdef DEBUG_UART_PORT uart_send(DEBUG_UART_PORT, (u8 *)"hekate: Hello!\r\n", 16); @@ -256,7 +256,7 @@ void ipl_main() display_init(); - u32 *fb = display_init_framebuffer_pitch(); + u32 *fb = display_init_window_a_pitch(); gfx_init_ctxt(fb, 720, 1280, 720); gfx_con_init(); diff --git a/source/script/lexer.c b/source/script/lexer.c index 3bc203a..2845f6b 100644 --- a/source/script/lexer.c +++ b/source/script/lexer.c @@ -146,7 +146,7 @@ Vector_t runLexer(const char* in, u32 len) { if (negative) parse *= -1; - vecAddElement(&vec, makeLexarToken(IntLit, parse)); + vecAddElement(&vec, makeLexarToken(IntLit, (char *)parse)); continue; } ELIFC('(') {