From ee6ea3e64c37eaa78db8a089fbeac672bc3ff7f4 Mon Sep 17 00:00:00 2001 From: suchmememanyskill <38142618+suchmememanyskill@users.noreply.github.com> Date: Thu, 20 Jul 2023 16:45:07 +0200 Subject: [PATCH] Update BDK to Hekate 6.0.5 --- Modified BDK files.md | 5 + bdk/bdk.h | 2 + bdk/display/di.c | 648 +++++++------ bdk/display/di.h | 136 ++- bdk/display/di.inl | 452 +++------ bdk/display/vic.c | 563 +++++++++++ bdk/display/vic.h | 63 ++ bdk/exception_handlers.S | 16 +- bdk/ianos/elfload/elf.h | 2 +- bdk/ianos/ianos.c | 17 +- bdk/input/als.c | 18 +- bdk/input/joycon.c | 960 +++++++++++++------ bdk/input/joycon.h | 16 +- bdk/input/touch.c | 62 +- bdk/libs/lv_conf.h | 11 +- bdk/libs/lvgl/lv_core/lv_group.c | 4 +- bdk/libs/lvgl/lv_core/lv_indev.c | 4 +- bdk/libs/lvgl/lv_misc/lv_color.h | 14 +- bdk/libs/lvgl/lv_misc/lv_ll.c | 7 +- bdk/libs/lvgl/lv_misc/lv_ll.h | 3 +- bdk/libs/lvgl/lv_themes/lv_theme_hekate.c | 58 +- bdk/libs/lvgl/lv_themes/lv_theme_hekate.h | 14 +- bdk/libs/nx_savedata/header.h | 6 +- bdk/libs/nx_savedata/remap_storage.h | 4 +- bdk/libs/nx_savedata/save.c | 9 +- bdk/libs/nx_savedata/save_data_file.c | 7 +- bdk/libs/nx_savedata/save_fs_list.c | 2 +- bdk/libs/nx_savedata/save_fs_list.h | 2 +- bdk/mem/emc.h | 2 + bdk/mem/heap.c | 70 +- bdk/mem/heap.h | 13 +- bdk/mem/mc.c | 36 +- bdk/mem/mc.h | 3 +- bdk/mem/mc_t210.h | 121 ++- bdk/mem/minerva.c | 65 +- bdk/mem/minerva.h | 4 +- bdk/mem/sdram.c | 1043 ++++++++++----------- bdk/mem/sdram.h | 114 ++- bdk/mem/sdram_config.inl | 53 +- bdk/mem/sdram_config_t210b01.inl | 375 ++------ bdk/mem/smmu.c | 16 +- bdk/memory_map.h | 17 +- bdk/power/bm92t36.c | 7 +- bdk/power/bq24193.h | 2 +- bdk/power/max17050.c | 2 +- bdk/power/max77620.h | 2 +- bdk/power/max7762x.c | 37 +- bdk/power/max7762x.h | 54 +- bdk/power/max77812.h | 21 +- bdk/power/regulator_5v.c | 62 +- bdk/rtc/max77620-rtc.c | 70 +- bdk/rtc/max77620-rtc.h | 45 +- bdk/sec/se.c | 246 +++-- bdk/sec/se.h | 4 +- bdk/sec/tsec.c | 90 +- bdk/sec/tsec.h | 2 +- bdk/sec/tsec_t210.h | 6 +- bdk/soc/bpmp.c | 15 +- bdk/soc/bpmp.h | 4 +- bdk/soc/ccplex.c | 17 +- bdk/soc/clock.c | 286 ++++-- bdk/soc/clock.h | 306 ++++-- bdk/soc/fuse.c | 115 ++- bdk/soc/fuse.h | 7 +- bdk/soc/gpio.c | 93 +- bdk/soc/gpio.h | 5 +- bdk/soc/hw_init.c | 152 +-- bdk/soc/hw_init.h | 3 +- bdk/soc/i2c.c | 12 +- bdk/soc/irq.c | 32 +- bdk/soc/pinmux.c | 6 +- bdk/soc/pinmux.h | 12 + bdk/soc/pmc.c | 43 +- bdk/soc/pmc.h | 267 ++++-- bdk/soc/t210.h | 265 +++--- bdk/soc/timer.c | 121 +++ bdk/soc/timer.h | 64 ++ bdk/soc/uart.c | 74 +- bdk/soc/uart.h | 63 +- bdk/storage/emmc.c | 16 +- bdk/storage/emmc.h | 18 +- bdk/storage/mbr_gpt.h | 52 +- bdk/storage/mmc.h | 5 +- bdk/storage/nx_emmc_bis.c | 14 +- bdk/storage/nx_emmc_bis.h | 18 +- bdk/storage/sd.c | 83 +- bdk/storage/sd.h | 10 +- bdk/storage/sd_def.h | 92 +- bdk/storage/sdmmc.c | 746 ++++++++++----- bdk/storage/sdmmc.h | 9 +- bdk/storage/sdmmc_driver.c | 438 +++++---- bdk/storage/sdmmc_driver.h | 314 ++++--- bdk/storage/sdmmc_t210.h | 184 ++-- bdk/thermal/fan.c | 35 +- bdk/utils/btn.c | 3 +- bdk/utils/ini.c | 59 +- bdk/utils/ini.h | 5 +- bdk/utils/list.h | 19 +- bdk/utils/sprintf.c | 35 +- bdk/utils/sprintf.h | 2 +- bdk/utils/types.h | 23 +- bdk/utils/util.c | 175 +++- bdk/utils/util.h | 13 +- 103 files changed, 6271 insertions(+), 3746 deletions(-) create mode 100644 bdk/display/vic.c create mode 100644 bdk/display/vic.h create mode 100644 bdk/soc/timer.c create mode 100644 bdk/soc/timer.h diff --git a/Modified BDK files.md b/Modified BDK files.md index 12ba54f..4a8d392 100644 --- a/Modified BDK files.md +++ b/Modified BDK files.md @@ -19,5 +19,10 @@ For future reference if updating the BDK ## /bdk/utils/ini.c - Added initial 'unknown' section to parse prod.keys +## /bdk/utils/types.h +- Added colors from lockpick-rcm +- Add ALWAYS_INLINE, LOG2, DIV_ROUND_UP defs +- Add 'open_mode_t' and 'validity_t' enums + ## /bdk/libs - Added nx-savedata from [Lockpick_RCM](https://github.com/shchmue/Lockpick_RCM) \ No newline at end of file diff --git a/bdk/bdk.h b/bdk/bdk.h index 3c7810e..80911dd 100644 --- a/bdk/bdk.h +++ b/bdk/bdk.h @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -51,6 +52,7 @@ #include #include #include +#include #include #include #include diff --git a/bdk/display/di.c b/bdk/display/di.c index 061a0ca..f8742a9 100644 --- a/bdk/display/di.c +++ b/bdk/display/di.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2022 CTCaer + * Copyright (c) 2018-2023 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -35,8 +36,9 @@ extern volatile nyx_storage_t *nyx_str; -static u32 _display_id = 0; -static bool nx_aula = false; +static u32 _display_id = 0; +static u32 _dsi_bl = -1; +static bool _nx_aula = false; static void _display_panel_and_hw_end(bool no_panel_deinit); @@ -57,34 +59,10 @@ static void _display_dsi_send_cmd(u8 cmd, u32 param, u32 wait) usleep(wait); } -static void _display_dsi_read_rx_fifo(u32 *data) +static void _display_dsi_wait_vblank(bool enable) { - u32 fifo_count = DSI(_DSIREG(DSI_STATUS)) & DSI_STATUS_RX_FIFO_SIZE; - for (u32 i = 0; i < fifo_count; i++) + if (enable) { - // Read or Drain RX FIFO. - if (data) - data[i] = DSI(_DSIREG(DSI_RD_DATA)); - else - (void)DSI(_DSIREG(DSI_RD_DATA)); - } -} - -int display_dsi_read(u8 cmd, u32 len, void *data, bool video_enabled) -{ - int res = 0; - u32 host_control = 0; - u32 cmd_timeout = video_enabled ? 0 : 250000; - u32 fifo[DSI_STATUS_RX_FIFO_SIZE] = {0}; - - // Drain RX FIFO. - _display_dsi_read_rx_fifo(NULL); - - // Save host control and enable host cmd packets during video. - if (video_enabled) - { - host_control = DSI(_DSIREG(DSI_HOST_CONTROL)); - // Enable vblank interrupt. DISPLAY_A(_DIREG(DC_CMD_INT_ENABLE)) = DC_CMD_INT_FRAME_END_INT; @@ -96,18 +74,67 @@ int display_dsi_read(u8 cmd, u32 len, void *data, bool video_enabled) while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT)) ; } + else + { + // Wait for vblank before resetting sync points. + DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT; // Clear interrupt. + while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT)) + ; + usleep(14); + + // Reset all states of syncpt block. + DSI(_DSIREG(DSI_INCR_SYNCPT_CNTRL)) = DSI_INCR_SYNCPT_SOFT_RESET; + usleep(300); // Stabilization delay. + + // Clear syncpt block reset. + DSI(_DSIREG(DSI_INCR_SYNCPT_CNTRL)) = 0; + usleep(300); // Stabilization delay. + + // Restore video mode and host control. + DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0; + + // Disable and clear vblank interrupt. + DISPLAY_A(_DIREG(DC_CMD_INT_ENABLE)) = 0; + DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT; + } +} + +static void _display_dsi_read_rx_fifo(u32 *data) +{ + u32 fifo_count = DSI(_DSIREG(DSI_STATUS)) & DSI_STATUS_RX_FIFO_SIZE; + if (fifo_count) + DSI(_DSIREG(DSI_TRIGGER)) = 0; + + for (u32 i = 0; i < fifo_count; i++) + { + // Read or Drain RX FIFO. + if (data) + data[i] = DSI(_DSIREG(DSI_RD_DATA)); + else + (void)DSI(_DSIREG(DSI_RD_DATA)); + } +} + +int display_dsi_read(u8 cmd, u32 len, void *data) +{ + int res = 0; + u32 fifo[DSI_STATUS_RX_FIFO_SIZE] = {0}; + + // Drain RX FIFO. + _display_dsi_read_rx_fifo(NULL); // Set reply size. _display_dsi_send_cmd(MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, len, 0); - _display_dsi_wait(cmd_timeout, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO); + _display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO); // Request register read. _display_dsi_send_cmd(MIPI_DSI_DCS_READ, cmd, 0); - _display_dsi_wait(cmd_timeout, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO); + _display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO); // Transfer bus control to device for transmitting the reply. - u32 high_speed = video_enabled ? DSI_HOST_CONTROL_HS : 0; - DSI(_DSIREG(DSI_HOST_CONTROL)) = DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_IMM_BTA | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC | high_speed; + DSI(_DSIREG(DSI_HOST_CONTROL)) |= DSI_HOST_CONTROL_IMM_BTA; + + // Wait for reply to complete. DSI_HOST_CONTROL_IMM_BTA bit acts as a DSI host read busy. _display_dsi_wait(150000, _DSIREG(DSI_HOST_CONTROL), DSI_HOST_CONTROL_IMM_BTA); // Wait a bit for the reply. @@ -146,51 +173,107 @@ int display_dsi_read(u8 cmd, u32 len, void *data, bool video_enabled) else res = 1; - // Disable host cmd packets during video and restore host control. - if (video_enabled) + return res; +} + +int display_dsi_vblank_read(u8 cmd, u32 len, void *data) +{ + int res = 0; + u32 host_control = 0; + u32 fifo[DSI_STATUS_RX_FIFO_SIZE] = {0}; + + // Drain RX FIFO. + _display_dsi_read_rx_fifo(NULL); + + // Save host control and enable host cmd packets during video. + host_control = DSI(_DSIREG(DSI_HOST_CONTROL)); + + _display_dsi_wait_vblank(true); + + // Set reply size. + _display_dsi_send_cmd(MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, len, 0); + _display_dsi_wait(0, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO); + + // Request register read. + _display_dsi_send_cmd(MIPI_DSI_DCS_READ, cmd, 0); + _display_dsi_wait(0, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO); + + _display_dsi_wait_vblank(false); + + // Transfer bus control to device for transmitting the reply. + DSI(_DSIREG(DSI_HOST_CONTROL)) |= DSI_HOST_CONTROL_IMM_BTA; + + // Wait for reply to complete. DSI_HOST_CONTROL_IMM_BTA bit acts as a DSI host read busy. + _display_dsi_wait(150000, _DSIREG(DSI_HOST_CONTROL), DSI_HOST_CONTROL_IMM_BTA); + + // Wait a bit for the reply. + usleep(5000); + + // Read RX FIFO. + _display_dsi_read_rx_fifo(fifo); + + // Parse packet and copy over the data. + if ((fifo[0] & 0xFF) == DSI_ESCAPE_CMD) { - // Wait for vblank before reseting sync points. - DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT; // Clear interrupt. - while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT)) - ; + // Act based on reply type. + switch (fifo[1] & 0xFF) + { + case GEN_LONG_RD_RES: + case DCS_LONG_RD_RES: + memcpy(data, &fifo[2], MIN((fifo[1] >> 8) & 0xFFFF, len)); + break; - // Reset all states of syncpt block. - DSI(_DSIREG(DSI_INCR_SYNCPT_CNTRL)) = DSI_INCR_SYNCPT_SOFT_RESET; - usleep(300); // Stabilization delay. + case GEN_1_BYTE_SHORT_RD_RES: + case DCS_1_BYTE_SHORT_RD_RES: + memcpy(data, &fifo[2], 1); + break; - // Clear syncpt block reset. - DSI(_DSIREG(DSI_INCR_SYNCPT_CNTRL)) = 0; - usleep(300); // Stabilization delay. + case GEN_2_BYTE_SHORT_RD_RES: + case DCS_2_BYTE_SHORT_RD_RES: + memcpy(data, &fifo[2], 2); + break; - // Restore video mode and host control. - DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0; - DSI(_DSIREG(DSI_HOST_CONTROL)) = host_control; - - // Disable and clear vblank interrupt. - DISPLAY_A(_DIREG(DC_CMD_INT_ENABLE)) = 0; - DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT; + case ACK_ERROR_RES: + default: + res = 1; + break; + } } + else + res = 1; + + // Restore host control. + DSI(_DSIREG(DSI_HOST_CONTROL)) = host_control; return res; } -void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled) +void display_dsi_write(u8 cmd, u32 len, void *data) { + static u8 *fifo8 = NULL; static u32 *fifo32 = NULL; - u8 *fifo8; u32 host_control; // Allocate fifo buffer. if (!fifo32) + { fifo32 = malloc(DSI_STATUS_RX_FIFO_SIZE * 8 * sizeof(u32)); + fifo8 = (u8 *)fifo32; + } - // Enable host cmd packets during video and save host control. - if (video_enabled) - DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = DSI_CMD_PKT_VID_ENABLE; + // Prepare data for long write. + if (len >= 2) + { + memcpy(&fifo8[5], data, len); + memset(&fifo8[5] + len, 0, len % sizeof(u32)); + len++; // Increase length by CMD. + } + + // Save host control. host_control = DSI(_DSIREG(DSI_HOST_CONTROL)); // Enable host transfer trigger. - DSI(_DSIREG(DSI_HOST_CONTROL)) = host_control | DSI_HOST_CONTROL_TX_TRIG_HOST; + DSI(_DSIREG(DSI_HOST_CONTROL)) = (host_control & ~(DSI_HOST_CONTROL_TX_TRIG_MASK)) | DSI_HOST_CONTROL_TX_TRIG_HOST; switch (len) { @@ -203,13 +286,10 @@ void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled) break; default: - memset(fifo32, 0, DSI_STATUS_RX_FIFO_SIZE * 8 * sizeof(u32)); - fifo8 = (u8 *)fifo32; fifo32[0] = (len << 8) | MIPI_DSI_DCS_LONG_WRITE; fifo8[4] = cmd; - memcpy(&fifo8[5], data, len); - len += 4 + 1; // Increase length by CMD/length word and DCS CMD. - for (u32 i = 0; i < (ALIGN(len, 4) / 4); i++) + len += sizeof(u32); // Increase length by length word and DCS CMD. + for (u32 i = 0; i < (ALIGN(len, sizeof(u32)) / sizeof(u32)); i++) DSI(_DSIREG(DSI_WR_DATA)) = fifo32[i]; DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST; break; @@ -218,31 +298,31 @@ void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled) // Wait for the write to happen. _display_dsi_wait(250000, _DSIREG(DSI_TRIGGER), DSI_TRIGGER_HOST); - // Disable host cmd packets during video and restore host control. - if (video_enabled) - DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0; + // Restore host control. DSI(_DSIREG(DSI_HOST_CONTROL)) = host_control; } void display_dsi_vblank_write(u8 cmd, u32 len, void *data) { + static u8 *fifo8 = NULL; static u32 *fifo32 = NULL; - u8 *fifo8; // Allocate fifo buffer. if (!fifo32) + { fifo32 = malloc(DSI_STATUS_RX_FIFO_SIZE * 8 * sizeof(u32)); + fifo8 = (u8 *)fifo32; + } - // Enable vblank interrupt. - DISPLAY_A(_DIREG(DC_CMD_INT_ENABLE)) = DC_CMD_INT_FRAME_END_INT; + // Prepare data for long write. + if (len >= 2) + { + memcpy(&fifo8[5], data, len); + memset(&fifo8[5] + len, 0, len % sizeof(u32)); + len++; // Increase length by CMD. + } - // Use the 4th line to transmit the host cmd packet. - DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = DSI_CMD_PKT_VID_ENABLE | DSI_DSI_LINE_TYPE(4); - - // Wait for vblank before starting the transfer. - DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT; // Clear interrupt. - while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT)) - ; + _display_dsi_wait_vblank(true); switch (len) { @@ -255,42 +335,21 @@ void display_dsi_vblank_write(u8 cmd, u32 len, void *data) break; default: - memset(fifo32, 0, DSI_STATUS_RX_FIFO_SIZE * 8 * sizeof(u32)); - fifo8 = (u8 *)fifo32; fifo32[0] = (len << 8) | MIPI_DSI_DCS_LONG_WRITE; fifo8[4] = cmd; - memcpy(&fifo8[5], data, len); - len += 4 + 1; // Increase length by CMD/length word and DCS CMD. - for (u32 i = 0; i < (ALIGN(len, 4) / 4); i++) + len += sizeof(u32); // Increase length by length word and DCS CMD. + for (u32 i = 0; i < (ALIGN(len, sizeof(u32)) / sizeof(u32)); i++) DSI(_DSIREG(DSI_WR_DATA)) = fifo32[i]; break; } - // Wait for vblank before reseting sync points. - DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT; // Clear interrupt. - while (!(DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) & DC_CMD_INT_FRAME_END_INT)) - ; - - // Reset all states of syncpt block. - DSI(_DSIREG(DSI_INCR_SYNCPT_CNTRL)) = DSI_INCR_SYNCPT_SOFT_RESET; - usleep(300); // Stabilization delay. - - // Clear syncpt block reset. - DSI(_DSIREG(DSI_INCR_SYNCPT_CNTRL)) = 0; - usleep(300); // Stabilization delay. - - // Restore video mode and host control. - DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0; - - // Disable and clear vblank interrupt. - DISPLAY_A(_DIREG(DC_CMD_INT_ENABLE)) = 0; - DISPLAY_A(_DIREG(DC_CMD_INT_STATUS)) = DC_CMD_INT_FRAME_END_INT; + _display_dsi_wait_vblank(false); } void display_init() { // Get Hardware type, as it's used in various DI functions. - nx_aula = fuse_read_hw_type() == FUSE_NX_HW_TYPE_AULA; + _nx_aula = fuse_read_hw_type() == FUSE_NX_HW_TYPE_AULA; // Check if display is already initialized. if (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & BIT(CLK_L_DISP1)) @@ -308,68 +367,57 @@ void display_init() // 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 power to display panel controller. + // Enable LCD DVDD. 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 -> Display panel. + 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); - - CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = BIT(CLK_L_HOST1X) | BIT(CLK_L_DISP1); - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_HOST1X) | BIT(CLK_L_DISP1); + CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = BIT(CLK_L_DISP1); + 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) = 10; // Set PLLP_OUT3 and div 6 (17MHz). CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_SET) = BIT(CLK_W_DSIA_LP); - CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP) = 10; // Set PLLP_OUT and div 6 (68MHz). + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP) = 10; // Set PLLP_OUT and div 6 (68MHz). // Bring every IO rail out of deep power down. PMC(APBDEV_PMC_IO_DPD_REQ) = PMC_IO_DPD_REQ_DPD_OFF; PMC(APBDEV_PMC_IO_DPD2_REQ) = PMC_IO_DPD_REQ_DPD_OFF; - // Configure LCD pins. - PINMUX_AUX(PINMUX_AUX_NFC_EN) &= ~PINMUX_TRISTATE; // PULL_DOWN - PINMUX_AUX(PINMUX_AUX_NFC_INT) &= ~PINMUX_TRISTATE; // PULL_DOWN - PINMUX_AUX(PINMUX_AUX_LCD_RST) &= ~PINMUX_TRISTATE; // PULL_DOWN - - // Configure Backlight pins. - PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) &= ~PINMUX_TRISTATE; // PULL_DOWN | 1 - PINMUX_AUX(PINMUX_AUX_LCD_BL_EN) &= ~PINMUX_TRISTATE; // PULL_DOWN - - if (nx_aula) + // Configure LCD/BL pins. + if (!_nx_aula) { - // Configure LCD RST pin. - gpio_config(GPIO_PORT_V, GPIO_PIN_2, GPIO_MODE_GPIO); - gpio_output_enable(GPIO_PORT_V, GPIO_PIN_2, GPIO_OUTPUT_ENABLE); - } - else - { - // Set LCD +-5V pins mode and direction - gpio_config(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_MODE_GPIO); - gpio_output_enable(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_OUTPUT_ENABLE); + // Configure LCD pins. + PINMUX_AUX(PINMUX_AUX_NFC_EN) = PINMUX_PULL_DOWN; + PINMUX_AUX(PINMUX_AUX_NFC_INT) = PINMUX_PULL_DOWN; - // Enable LCD power. - gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_HIGH); // LCD +5V enable. - usleep(10000); - gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_HIGH); // LCD -5V enable. - usleep(10000); + // Configure Backlight pins. + PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = PINMUX_PULL_DOWN; + PINMUX_AUX(PINMUX_AUX_LCD_BL_EN) = PINMUX_PULL_DOWN; - // Configure Backlight PWM/EN and LCD RST pins (BL PWM, BL EN, LCD RST). - gpio_config(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_MODE_GPIO); - gpio_output_enable(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2, GPIO_OUTPUT_ENABLE); + // Enable LCD AVDD. + gpio_direction_output(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_HIGH); + usleep(10000); // Wait minimum 4.2ms to stabilize. + + // Configure Backlight PWM/EN pins (BL PWM, BL EN). + gpio_direction_output(GPIO_PORT_V, GPIO_PIN_0 | GPIO_PIN_1, GPIO_LOW); // Enable Backlight power. gpio_write(GPIO_PORT_V, GPIO_PIN_1, GPIO_HIGH); } + // Configure LCD RST pin. + PINMUX_AUX(PINMUX_AUX_LCD_RST) = PINMUX_PULL_DOWN; + gpio_direction_output(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW); + // Power up supply regulator for display interface. MIPI_CAL(_DSIREG(MIPI_CAL_MIPI_BIAS_PAD_CFG2)) = 0; @@ -379,39 +427,32 @@ void display_init() APB_MISC(APB_MISC_GP_DSI_PAD_CONTROL) = 0; } - // Set DISP1 clock source and parent clock. - CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DISP1) = 0x40000000; // PLLD_OUT. - u32 plld_div = (3 << 20) | (20 << 11) | 1; // DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 97.5 MHz (offset). - CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div; - - if (tegra_t210) - { - CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0x20; // PLLD_SETUP. - CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = 0x2D0AAA; // PLLD_ENABLE_CLK. - } - else - { - CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0; - CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = 0x2DFC00; // PLLD_ENABLE_CLK. - } + // 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) + // T210B01: DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 97.8 MHz, PLLD_OUT0 (DSI-PCLK): 48.9 MHz. (PCLK: 16.30 MHz) + clock_enable_plld(3, 20, true, tegra_t210); // Setup Display Interface initial window configuration. - exec_cfg((u32 *)DISPLAY_A_BASE, _display_dc_setup_win_config, 94); + exec_cfg((u32 *)DISPLAY_A_BASE, _di_dc_setup_win_config, CFG_SIZE(_di_dc_setup_win_config)); - // Setup display communication interfaces. - exec_cfg((u32 *)DSI_BASE, _display_dsi_init_config_part1, 8); + // 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, _display_dsi_init_config_part2, 14); + exec_cfg((u32 *)DSI_BASE, _di_dsi_init_irq_pkt_config1, CFG_SIZE(_di_dsi_init_irq_pkt_config1)); + + // Reset pad trimmers for T210B01. if (!tegra_t210) - exec_cfg((u32 *)DSI_BASE, _display_dsi_init_config_part3_t210b01, 7); - exec_cfg((u32 *)DSI_BASE, _display_dsi_init_config_part4, 10); - DSI(_DSIREG(DSI_PHY_TIMING_0)) = tegra_t210 ? 0x6070601 : 0x6070603; - exec_cfg((u32 *)DSI_BASE, _display_dsi_init_config_part5, 12); - DSI(_DSIREG(DSI_PHY_TIMING_0)) = tegra_t210 ? 0x6070601 : 0x6070603; - exec_cfg((u32 *)DSI_BASE, _display_dsi_init_config_part6, 14); + exec_cfg((u32 *)DSI_BASE, _di_dsi_init_pads_t210b01, CFG_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)); usleep(10000); // Enable LCD Reset. @@ -419,13 +460,13 @@ void display_init() usleep(60000); // Setup DSI device takeover timeout. - DSI(_DSIREG(DSI_BTA_TIMING)) = nx_aula ? 0x40103 : 0x50204; + DSI(_DSIREG(DSI_BTA_TIMING)) = _nx_aula ? 0x40103 : 0x50204; // Get Display ID. _display_id = 0xCCCCCC; for (u32 i = 0; i < 3; i++) { - if (!display_dsi_read(MIPI_DCS_GET_DISPLAY_ID, 3, &_display_id, DSI_VIDEO_DISABLED)) + if (!display_dsi_read(MIPI_DCS_GET_DISPLAY_ID, 3, &_display_id)) break; usleep(10000); @@ -441,7 +482,7 @@ void display_init() _display_id = PANEL_JDI_XXX062M; // For Aula ensure that we have a compatible panel id. - if (nx_aula && _display_id == 0xCCCC) + if (_nx_aula && _display_id == 0xCCCC) _display_id = PANEL_SAM_AMS699VC01; // Initialize display panel. @@ -449,16 +490,39 @@ void display_init() { case PANEL_SAM_AMS699VC01: _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000); - _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM, 0xA0, 0); // Write 0 to 0xA0. - _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM, MIPI_DCS_SET_CONTROL_DISPLAY | (DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL << 8), 0); // Enable brightness control. + // Set color mode to 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); + // 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); + + // Unlock Level 2 registers. + DSI(_DSIREG(DSI_WR_DATA)) = 0x539; // MIPI_DSI_DCS_LONG_WRITE: 5 bytes. + DSI(_DSIREG(DSI_WR_DATA)) = 0x5A5A5AE2; // MIPI_DCS_PRIV_SM_SET_REGS_LOCK: Unlock Level 2 registers. + DSI(_DSIREG(DSI_WR_DATA)) = 0x5A; + DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST; + + // Set registers offset and set PWM transition to 6 frames (100ms). + _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM, MIPI_DCS_PRIV_SM_SET_REG_OFFSET | (7 << 8), 0); + _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM, MIPI_DCS_PRIV_SM_SET_ELVSS | (6 << 8), 0); + + // Relock Level 2 registers. + DSI(_DSIREG(DSI_WR_DATA)) = 0x539; // MIPI_DSI_DCS_LONG_WRITE: 5 bytes. + DSI(_DSIREG(DSI_WR_DATA)) = 0xA55A5AE2; // MIPI_DCS_PRIV_SM_SET_REGS_LOCK: Lock Level 2 registers. + DSI(_DSIREG(DSI_WR_DATA)) = 0xA5; + DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST; + + // Set backlight to 0%. DSI(_DSIREG(DSI_WR_DATA)) = 0x339; // MIPI_DSI_DCS_LONG_WRITE: 3 bytes. DSI(_DSIREG(DSI_WR_DATA)) = 0x000051; // MIPI_DCS_SET_BRIGHTNESS 0000: 0%. FF07: 100%. DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST; usleep(5000); + _dsi_bl = 0; break; case PANEL_JDI_XXX062M: - exec_cfg((u32 *)DSI_BASE, _display_init_config_jdi, 43); + exec_cfg((u32 *)DSI_BASE, _di_dsi_panel_init_config_jdi, CFG_SIZE(_di_dsi_panel_init_config_jdi)); _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 180000); break; @@ -485,7 +549,7 @@ void display_init() case PANEL_INL_2J055IA_27A: case PANEL_AUO_A055TAN01: - case PANEL_V40_55_UNK: + case PANEL_SHP_LQ055T1SW10: default: // Allow spare part displays to work. _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 120000); break; @@ -494,28 +558,25 @@ void display_init() // Unblank display. _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_SET_DISPLAY_ON, 20000); - // Configure PLLD for DISP1. - plld_div = (1 << 20) | (24 << 11) | 1; // DIVM: 1, DIVN: 24, DIVP: 1. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 234 MHz (offset, it's ddr btw, so normally div2). - CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div; + // Setup final dsi clock. + // DIVM: 1, DIVN: 24, DIVP: 1. PLLD_OUT: 468.0 MHz, PLLD_OUT0 (DSI): 234.0 MHz. + clock_enable_plld(1, 24, false, tegra_t210); - if (tegra_t210) - CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0x20; // PLLD_SETUP. - else - CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0; - CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = 0x2DFC00; // Use new PLLD_SDM_DIN. - - // Finalize DSI configuration. + // 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, _display_dsi_packet_config, 19); - // Set pixel clock dividers: 234 / 3 / 1 = 78 MHz (offset) for 60 Hz. + exec_cfg((u32 *)DSI_BASE, _di_dsi_init_seq_pkt_final_config, CFG_SIZE(_di_dsi_init_seq_pkt_final_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. - exec_cfg((u32 *)DSI_BASE, _display_dsi_mode_config, 10); + + // Set DSI mode. + exec_cfg((u32 *)DSI_BASE, _di_dsi_mode_config, CFG_SIZE(_di_dsi_mode_config)); usleep(10000); // Calibrate display communication pads. - u32 loops = tegra_t210 ? 1 : 2; // Find out why this is done 2 times on Mariko. - exec_cfg((u32 *)MIPI_CAL_BASE, _display_mipi_pad_cal_config, 4); + 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++) { // Set MIPI bias pad config. @@ -525,22 +586,22 @@ void display_init() // Set pad trimmers and set MIPI DSI cal offsets. if (tegra_t210) { - exec_cfg((u32 *)DSI_BASE, _display_dsi_pad_cal_config_t210, 4); - exec_cfg((u32 *)MIPI_CAL_BASE, _display_mipi_dsi_cal_offsets_config_t210, 4); + 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)); } else { - exec_cfg((u32 *)DSI_BASE, _display_dsi_pad_cal_config_t210b01, 7); - exec_cfg((u32 *)MIPI_CAL_BASE, _display_mipi_dsi_cal_offsets_config_t210b01, 4); + 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)); } - // Set the rest of MIPI cal offsets and apply calibration. - exec_cfg((u32 *)MIPI_CAL_BASE, _display_mipi_apply_dsi_cal_config, 12); + // 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)); } usleep(10000); // Enable video display controller. - exec_cfg((u32 *)DISPLAY_A_BASE, _display_video_disp_controller_enable_config, 113); + exec_cfg((u32 *)DISPLAY_A_BASE, _di_dc_video_enable_config, CFG_SIZE(_di_dc_video_enable_config)); } void display_backlight_pwm_init() @@ -550,7 +611,8 @@ void display_backlight_pwm_init() clock_enable_pwm(); - PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN; // Enable PWM and set it to 25KHz PFM. 29.5KHz is stock. + // 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. gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight power mode. @@ -558,28 +620,37 @@ void display_backlight_pwm_init() void display_backlight(bool enable) { - gpio_write(GPIO_PORT_V, GPIO_PIN_0, enable ? GPIO_HIGH : GPIO_LOW); // Backlight PWM GPIO. + // Backlight PWM GPIO. + gpio_write(GPIO_PORT_V, GPIO_PIN_0, enable ? GPIO_HIGH : GPIO_LOW); } -void display_dsi_backlight_brightness(u32 brightness) +static void _display_dsi_backlight_brightness(u32 duty) { - // Normalize brightness value by 82% and a base of 45 duty. - if (brightness) - brightness = (brightness * PANEL_OLED_BL_COEFF / 100) + PANEL_OLED_BL_OFFSET; - - u16 bl_ctrl = byte_swap_16((u16)(brightness * 8)); - display_dsi_vblank_write(MIPI_DCS_SET_BRIGHTNESS, 2, &bl_ctrl); -} - -void display_pwm_backlight_brightness(u32 brightness, u32 step_delay) -{ - u32 old_value = (PWM(PWM_CONTROLLER_PWM_CSR_0) >> 16) & 0xFF; - if (brightness == old_value) + if (_dsi_bl == duty) return; - if (old_value < brightness) + // Convert duty to candela. + u32 candela = duty * PANEL_SM_BL_CANDELA_MAX / 255; + + 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. + if (!duty) + usleep(120000); + + _dsi_bl = duty; +} + +static void _display_pwm_backlight_brightness(u32 duty, u32 step_delay) +{ + u32 old_value = (PWM(PWM_CONTROLLER_PWM_CSR_0) >> 16) & 0xFF; + if (duty == old_value) + return; + + if (old_value < duty) { - for (u32 i = old_value; i < brightness + 1; i++) + for (u32 i = old_value; i < duty + 1; i++) { PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN | (i << 16); usleep(step_delay); @@ -587,13 +658,13 @@ void display_pwm_backlight_brightness(u32 brightness, u32 step_delay) } else { - for (u32 i = old_value; i > brightness; i--) + for (u32 i = old_value; i > duty; i--) { PWM(PWM_CONTROLLER_PWM_CSR_0) = PWM_CSR_EN | (i << 16); usleep(step_delay); } } - if (!brightness) + if (!duty) PWM(PWM_CONTROLLER_PWM_CSR_0) = 0; } @@ -603,9 +674,9 @@ void display_backlight_brightness(u32 brightness, u32 step_delay) brightness = 255; if (_display_id != PANEL_SAM_AMS699VC01) - display_pwm_backlight_brightness(brightness, step_delay); + _display_pwm_backlight_brightness(brightness, step_delay); else - display_dsi_backlight_brightness(brightness); + _display_dsi_backlight_brightness(brightness); } u32 display_get_backlight_brightness() @@ -626,13 +697,23 @@ static void _display_panel_and_hw_end(bool no_panel_deinit) // Blank display. 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. + // Propagate changes to all register buffers and disable host cmd packets during video. DISPLAY_A(_DIREG(DC_CMD_STATE_ACCESS)) = READ_MUX | WRITE_MUX; DSI(_DSIREG(DSI_VIDEO_MODE_CONTROL)) = 0; // De-initialize video controller. - exec_cfg((u32 *)DISPLAY_A_BASE, _display_video_disp_controller_disable_config, 17); - exec_cfg((u32 *)DSI_BASE, _display_dsi_timing_deinit_config, 16); + exec_cfg((u32 *)DISPLAY_A_BASE, _di_dc_video_disable_config, CFG_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) + // T210B01: DIVM: 1, DIVN: 20, DIVP: 3. PLLD_OUT: 97.8 MHz, PLLD_OUT0 (DSI-PCLK): 48.9 MHz. (PCLK: 16.30 MHz) + 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)); if (_display_id != PANEL_SAM_AMS699VC01) usleep(10000); @@ -641,16 +722,16 @@ static void _display_panel_and_hw_end(bool no_panel_deinit) switch (_display_id) { case PANEL_JDI_XXX062M: - exec_cfg((u32 *)DSI_BASE, _display_deinit_config_jdi, 22); + exec_cfg((u32 *)DSI_BASE, _di_dsi_panel_deinit_config_jdi, CFG_SIZE(_di_dsi_panel_deinit_config_jdi)); break; case PANEL_AUO_A062TAN01: - exec_cfg((u32 *)DSI_BASE, _display_deinit_config_auo, 37); + exec_cfg((u32 *)DSI_BASE, _di_dsi_panel_deinit_config_auo, CFG_SIZE(_di_dsi_panel_deinit_config_auo)); break; case PANEL_INL_2J055IA_27A: case PANEL_AUO_A055TAN01: - case PANEL_V40_55_UNK: + case PANEL_SHP_LQ055T1SW10: // Unlock extension cmds. DSI(_DSIREG(DSI_WR_DATA)) = 0x439; // MIPI_DSI_DCS_LONG_WRITE: 4 bytes. DSI(_DSIREG(DSI_WR_DATA)) = 0x9483FFB9; // MIPI_DCS_PRIV_SET_EXTC. (Pass: FF 83 94). @@ -663,7 +744,7 @@ static void _display_panel_and_hw_end(bool no_panel_deinit) DSI(_DSIREG(DSI_WR_DATA)) = 0x751548B1; // MIPI_DCS_PRIV_SET_POWER_CONTROL. (Not deep standby, BT5 / XDK, VRH gamma volt adj 53 / x40). else if (_display_id == PANEL_AUO_A055TAN01) DSI(_DSIREG(DSI_WR_DATA)) = 0x711148B1; // MIPI_DCS_PRIV_SET_POWER_CONTROL. (Not deep standby, BT1 / XDK, VRH gamma volt adj 49 / x40). - else // PANEL_V40_55_UNK. + else // PANEL_SHP_LQ055T1SW10. DSI(_DSIREG(DSI_WR_DATA)) = 0x731348B1; // MIPI_DCS_PRIV_SET_POWER_CONTROL. (Not deep standby, BT3 / XDK, VRH gamma volt adj 51 / x40). if (_display_id == PANEL_INL_2J055IA_27A || _display_id == PANEL_AUO_A055TAN01) { @@ -671,7 +752,7 @@ static void _display_panel_and_hw_end(bool no_panel_deinit) DSI(_DSIREG(DSI_WR_DATA)) = 0x71143209; DSI(_DSIREG(DSI_WR_DATA)) = 0x114D31; // (Unknown). } - else // PANEL_V40_55_UNK. + else // PANEL_SHP_LQ055T1SW10. { // (NVRH gamma volt adj 9, Amplifier current small / x30, FS0 freq Fosc/80 / FS1 freq Fosc/48, Enter standby / PON / VCOMG). DSI(_DSIREG(DSI_WR_DATA)) = 0x71243209; @@ -682,6 +763,7 @@ static void _display_panel_and_hw_end(bool no_panel_deinit) break; case PANEL_INL_P062CCA_AZ1: + case PANEL_SAM_AMS699VC01: default: break; } @@ -693,35 +775,35 @@ static void _display_panel_and_hw_end(bool no_panel_deinit) skip_panel_deinit: // Disable LCD power pins. gpio_write(GPIO_PORT_V, GPIO_PIN_2, GPIO_LOW); // LCD Reset disable. + usleep(10000); - if (!nx_aula) // HOS uses panel id. + if (!_nx_aula) // HOS uses panel id. { - usleep(10000); - gpio_write(GPIO_PORT_I, GPIO_PIN_1, GPIO_LOW); // LCD -5V disable. - usleep(10000); - gpio_write(GPIO_PORT_I, GPIO_PIN_0, GPIO_LOW); // LCD +5V disable. - usleep(10000); + 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. } - else - usleep(30000); // Aula Panel. + usleep(10000); // Disable Display Interface specific clocks. CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_CLR) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI); - CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_HOST1X) | BIT(CLK_L_DISP1); - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_HOST1X) | BIT(CLK_L_DISP1); + CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_DISP1); + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_DISP1); // Power down pads. - DSI(_DSIREG(DSI_PAD_CONTROL_0)) = DSI_PAD_CONTROL_VS1_PULLDN_CLK | DSI_PAD_CONTROL_VS1_PULLDN(0xF) | DSI_PAD_CONTROL_VS1_PDIO_CLK | DSI_PAD_CONTROL_VS1_PDIO(0xF); + DSI(_DSIREG(DSI_PAD_CONTROL_0)) = DSI_PAD_CONTROL_VS1_PULLDN_CLK | DSI_PAD_CONTROL_VS1_PULLDN(0xF) | + DSI_PAD_CONTROL_VS1_PDIO_CLK | DSI_PAD_CONTROL_VS1_PDIO(0xF); DSI(_DSIREG(DSI_POWER_CONTROL)) = 0; // Switch LCD PWM backlight pin to special function mode and enable PWM0 mode. - if (!nx_aula) + if (!_nx_aula) { gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_SPIO); // Backlight PWM. - PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & ~PINMUX_TRISTATE) | PINMUX_TRISTATE; - PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = (PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) & ~PINMUX_FUNC_MASK) | 1; // Set PWM0 mode. + PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) = PINMUX_TRISTATE | PINMUX_PULL_DOWN | 1; // Set PWM0 mode. } + + // Disable LCD DVDD. + max7762x_regulator_enable(REGULATOR_LDO0, false); } void display_end() { _display_panel_and_hw_end(false); }; @@ -734,7 +816,7 @@ u16 display_get_decoded_panel_id() void display_set_decoded_panel_id(u32 id) { // Get Hardware type, as it's used in various DI functions. - nx_aula = fuse_read_hw_type() == FUSE_NX_HW_TYPE_AULA; + _nx_aula = fuse_read_hw_type() == FUSE_NX_HW_TYPE_AULA; // Decode Display ID. _display_id = ((id >> 8) & 0xFF00) | (id & 0xFF); @@ -743,13 +825,13 @@ void display_set_decoded_panel_id(u32 id) _display_id = PANEL_JDI_XXX062M; // For Aula ensure that we have a compatible panel id. - if (nx_aula && _display_id == 0xCCCC) + if (_nx_aula && _display_id == 0xCCCC) _display_id = PANEL_SAM_AMS699VC01; } void display_color_screen(u32 color) { - exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_one_color, 8); + exec_cfg((u32 *)DISPLAY_A_BASE, _di_win_one_color, CFG_SIZE(_di_win_one_color)); // Configure display to show single color. DISPLAY_A(_DIREG(DC_WIN_AD_WIN_OPTIONS)) = 0; @@ -757,12 +839,12 @@ void display_color_screen(u32 color) 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; - usleep(35000); // No need to wait on Aula. + usleep(35000); // Wait 2 frames. No need on Aula. if (_display_id != PANEL_SAM_AMS699VC01) display_backlight(true); else - display_backlight_brightness(255, 0); + display_backlight_brightness(150, 0); } u32 *display_init_framebuffer_pitch() @@ -770,27 +852,39 @@ u32 *display_init_framebuffer_pitch() // Sanitize framebuffer area. memset((u32 *)IPL_FB_ADDRESS, 0, IPL_FB_SZ); - // This configures the framebuffer @ IPL_FB_ADDRESS with a resolution of 1280x720 (line stride 720). - exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_pitch, 32); - //usleep(35000); // No need to wait on Aula. + // 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)); + //usleep(35000); // Wait 2 frames. No need on Aula. + + return (u32 *)DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR)); +} + +u32 *display_init_framebuffer_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)); + 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() { - // This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 1280x720 (line stride 720). - exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_pitch_inv, 34); - //usleep(35000); // No need to wait on Aula. + // 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)); + usleep(35000); // Wait 2 frames. No need on Aula. return (u32 *)DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR)); } u32 *display_init_framebuffer_block() { - // This configures the framebuffer @ NYX_FB_ADDRESS with a resolution of 1280x720 (line stride 720). - exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_block, 34); - //usleep(35000); // No need to wait on Aula. + // 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)); + usleep(35000); // Wait 2 frames. No need on Aula. return (u32 *)DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR)); } @@ -798,69 +892,98 @@ u32 *display_init_framebuffer_block() u32 *display_init_framebuffer_log() { // This configures the framebuffer @ LOG_FB_ADDRESS with a resolution of 1280x720 (line stride 720). - exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_framebuffer_log, 20); + exec_cfg((u32 *)DISPLAY_A_BASE, _di_win_framebuffer_log, CFG_SIZE(_di_win_framebuffer_log)); return (u32 *)DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR)); } void display_activate_console() { - DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_D_SELECT; // Select window D. - DISPLAY_A(_DIREG(DC_WIN_WIN_OPTIONS)) = WIN_ENABLE; // Enable window DD. - DISPLAY_A(_DIREG(DC_WIN_POSITION)) = 0xFF80; - DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE; + // Select window D. + DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_D_SELECT; + + // Enable and setup window D. + DISPLAY_A(_DIREG(DC_WIN_WIN_OPTIONS)) = WIN_ENABLE; + DISPLAY_A(_DIREG(DC_WIN_POSITION)) = 0xFF80; // X: -128. + + // 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; + // Pull-down effect. for (u32 i = 0xFF80; i < 0x10000; i++) { + // Set window position. DISPLAY_A(_DIREG(DC_WIN_POSITION)) = i & 0xFFFF; - DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE; + + // 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; usleep(1000); } DISPLAY_A(_DIREG(DC_WIN_POSITION)) = 0; - DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE; + + // 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() { - DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_D_SELECT; // Select window D. + // Select window D. + DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = WINDOW_D_SELECT; + // Pull-up effect. for (u32 i = 0xFFFF; i > 0xFF7F; i--) { + // Set window position. DISPLAY_A(_DIREG(DC_WIN_POSITION)) = i & 0xFFFF; - DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE; + + // 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; usleep(500); } + // Disable window D. DISPLAY_A(_DIREG(DC_WIN_POSITION)) = 0; - DISPLAY_A(_DIREG(DC_WIN_WIN_OPTIONS)) = 0; // Disable window DD. - DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | WIN_D_UPDATE; + 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) { // Setup cursor. - DISPLAY_A(_DIREG(DC_DISP_CURSOR_START_ADDR)) = CURSOR_CLIPPING(CURSOR_CLIP_WIN_A) | size | ((u32)crs_fb >> 10); - DISPLAY_A(_DIREG(DC_DISP_BLEND_CURSOR_CONTROL)) = - CURSOR_BLEND_R8G8B8A8 | CURSOR_BLEND_DST_FACTOR(CURSOR_BLEND_K1) | CURSOR_BLEND_SRC_FACTOR(CURSOR_BLEND_K1) | 0xFF; + DISPLAY_A(_DIREG(DC_DISP_CURSOR_START_ADDR)) = CURSOR_CLIPPING(CURSOR_CLIP_WIN_A) | size | ((u32)crs_fb >> 10); + DISPLAY_A(_DIREG(DC_DISP_BLEND_CURSOR_CONTROL)) = CURSOR_BLEND_R8G8B8A8 | + CURSOR_BLEND_DST_FACTOR(CURSOR_BLEND_K1) | + CURSOR_BLEND_SRC_FACTOR(CURSOR_BLEND_K1) | 0xFF; + // Enable cursor window. DISPLAY_A(_DIREG(DC_DISP_DISP_WIN_OPTIONS)) |= CURSOR_ENABLE; // Arm and activate changes. - DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | CURSOR_UPDATE; + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | CURSOR_UPDATE; DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | CURSOR_ACT_REQ; } void display_set_pos_cursor(u32 x, u32 y) { + // Set cursor position. DISPLAY_A(_DIREG(DC_DISP_CURSOR_POSITION)) = x | (y << 16); - DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | CURSOR_UPDATE; + // Arm and activate changes. + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | CURSOR_UPDATE; DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | CURSOR_ACT_REQ; } @@ -868,6 +991,7 @@ void display_deinit_cursor() { DISPLAY_A(_DIREG(DC_DISP_BLEND_CURSOR_CONTROL)) = 0; DISPLAY_A(_DIREG(DC_DISP_DISP_WIN_OPTIONS)) &= ~CURSOR_ENABLE; - DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | CURSOR_UPDATE; + + DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_UPDATE | CURSOR_UPDATE; DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = GENERAL_ACT_REQ | CURSOR_ACT_REQ; } diff --git a/bdk/display/di.h b/bdk/display/di.h index cf4f0de..4a19ecb 100644 --- a/bdk/display/di.h +++ b/bdk/display/di.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2021 CTCaer + * Copyright (c) 2018-2023 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -43,13 +43,17 @@ // 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 COND_REG_WR_SAFE 3 #define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x01 #define SYNCPT_CNTRL_SOFT_RESET BIT(0) #define SYNCPT_CNTRL_NO_STALL BIT(8) #define DC_CMD_CONT_SYNCPT_VSYNC 0x28 -#define SYNCPT_VSYNC_ENABLE BIT(8) +#define SYNCPT_VSYNC_INDX(x) (((x) & 0xff) << 0) +#define SYNCPT_VSYNC_ENABLE BIT(8) #define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031 @@ -72,6 +76,7 @@ #define DC_CMD_INT_MASK 0x38 #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_STATE_ACCESS 0x40 #define READ_MUX BIT(0) @@ -98,7 +103,13 @@ #define WINDOW_C_SELECT BIT(6) #define WINDOW_D_SELECT BIT(7) -#define DC_CMD_REG_ACT_CONTROL 0x043 +#define DC_CMD_REG_ACT_CONTROL 0x43 +#define GENERAL_ACT_HCNTR_SEL BIT(0) +#define WIN_A_ACT_HCNTR_SEL BIT(2) +#define WIN_B_ACT_HCNTR_SEL BIT(4) +#define WIN_C_ACT_HCNTR_SEL BIT(6) +#define CURSOR_ACT_HCNTR_SEL BIT(7) +#define WIN_D_ACT_HCNTR_SEL BIT(10) // DC_D_WIN_DD window D instance of DC_WIN #define DC_D_WIN_DD_WIN_OPTIONS 0x80 @@ -124,6 +135,7 @@ #define DC_COM_CRC_CONTROL 0x300 #define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x)) #define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x)) +#define LSC0_OUTPUT_POLARITY_LOW BIT(24) #define DC_COM_DSC_TOP_CTL 0x33E @@ -139,12 +151,29 @@ #define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403 #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 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 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 DC_DISP_BACK_PORCH 0x408 +#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 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 DC_DISP_DISP_CLOCK_CONTROL 0x42E #define SHIFT_CLK_DIVIDER(x) ((x) & 0xff) @@ -239,6 +268,10 @@ #define DC_DISP_SD_BL_CONTROL 0x4DC #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 DC_WINC_PALETTE_COLOR_EXT 0x600 + #define DC_WIN_CSC_YOF 0x611 #define DC_WIN_CSC_KYRGB 0x612 #define DC_WIN_CSC_KUR 0x613 @@ -253,12 +286,13 @@ // The following registers are A/B/C shadows of the 0xB80/0xD80/0xF80 registers (see DISPLAY_WINDOW_HEADER). #define DC_WIN_WIN_OPTIONS 0x700 -#define H_DIRECTION BIT(0) -#define V_DIRECTION BIT(2) -#define SCAN_COLUMN BIT(4) -#define COLOR_EXPAND BIT(6) -#define CSC_ENABLE BIT(18) -#define WIN_ENABLE BIT(30) +#define H_DIRECTION BIT(0) +#define V_DIRECTION BIT(2) +#define SCAN_COLUMN BIT(4) +#define COLOR_EXPAND BIT(6) +#define COLOR_PALETTE_ENABLE BIT(16) +#define CSC_ENABLE BIT(18) +#define WIN_ENABLE BIT(30) #define DC_WIN_BUFFER_CONTROL 0x702 #define BUFFER_CONTROL_HOST 0 @@ -290,10 +324,22 @@ #define WIN_COLOR_DEPTH_YUV422R 0x17 #define WIN_COLOR_DEPTH_YCbCr422RA 0x18 #define WIN_COLOR_DEPTH_YUV422RA 0x19 +#define WIN_COLOR_DEPTH_YCbCr444P 0x29 +#define WIN_COLOR_DEPTH_YCrCb420SP 0x2A +#define WIN_COLOR_DEPTH_YCbCr420SP 0x2B +#define WIN_COLOR_DEPTH_YCrCb422SP 0x2C +#define WIN_COLOR_DEPTH_YCbCr422SP 0x2D +#define WIN_COLOR_DEPTH_YUV444P 0x34 +#define WIN_COLOR_DEPTH_YVU420SP 0x35 +#define WIN_COLOR_DEPTH_YUV420SP 0x36 +#define WIN_COLOR_DEPTH_YVU422SP 0x37 +#define WIN_COLOR_DEPTH_YUV422SP 0x38 +#define WIN_COLOR_DEPTH_YVU444SP 0x3B +#define WIN_COLOR_DEPTH_YUV444SP 0x3C #define DC_WIN_POSITION 0x704 -#define H_POSITION(x) (((x) & 0xFfff) << 0) -#define V_POSITION(x) (((x) & 0x1fff) << 16) +#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) @@ -316,6 +362,7 @@ #define DC_WIN_DV_CONTROL 0x70E #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_ENABLE (0 << 24) @@ -386,6 +433,7 @@ #define DSI_HOST_CONTROL_FIFO_SEL BIT(4) #define DSI_HOST_CONTROL_HS BIT(5) #define DSI_HOST_CONTROL_RAW BIT(6) +#define DSI_HOST_CONTROL_TX_TRIG_MASK (3 << 12) #define DSI_HOST_CONTROL_TX_TRIG_SOL (0 << 12) #define DSI_HOST_CONTROL_TX_TRIG_FIFO (1 << 12) #define DSI_HOST_CONTROL_TX_TRIG_HOST (2 << 12) @@ -433,10 +481,14 @@ #define DSI_PKT_SEQ_5_LO 0x2D #define DSI_PKT_SEQ_5_HI 0x2E #define DSI_DCS_CMDS 0x33 + #define DSI_PKT_LEN_0_1 0x34 #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 DSI_PHY_TIMING_0 0x3C #define DSI_PHY_TIMING_1 0x3D #define DSI_PHY_TIMING_2 0x3E @@ -593,6 +645,7 @@ #define MIPI_DCS_GET_SCANLINE 0x45 #define MIPI_DCS_SET_TEAR_SCANLINE_WIDTH 0x46 #define MIPI_DCS_GET_SCANLINE_WIDTH 0x47 +#define MIPI_DSI_AREA_COLOR_MODE 0x4C #define MIPI_DCS_SET_BRIGHTNESS 0x51 // DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL. 1 byte. 0-7: DBV. #define MIPI_DCS_GET_BRIGHTNESS 0x52 // 1 byte. 0-7: DBV. #define MIPI_DCS_SET_CONTROL_DISPLAY 0x53 // 1 byte. 2: BL, 3: DD, 5: BCTRL. @@ -606,7 +659,9 @@ #define MIPI_DCS_READ_DDB_CONTINUE 0xA8 // 0x100 size. /*! MIPI DCS Panel Private CMDs. */ -#define MIPI_DCS_PRIV_UNK_A0 0xA0 +#define MIPI_DCS_PRIV_SM_SET_COLOR_MODE 0xA0 +#define MIPI_DCS_PRIV_SM_SET_REG_OFFSET 0xB0 +#define MIPI_DCS_PRIV_SM_SET_ELVSS 0xB1 // OLED backlight tuning. Byte7: PWM transition time in frames. #define MIPI_DCS_PRIV_SET_POWER_CONTROL 0xB1 #define MIPI_DCS_PRIV_SET_EXTC 0xB9 // Enable extended commands. #define MIPI_DCS_PRIV_UNK_BD 0xBD @@ -614,6 +669,8 @@ #define MIPI_DCS_PRIV_UNK_D6 0xD6 #define MIPI_DCS_PRIV_UNK_D8 0xD8 #define MIPI_DCS_PRIV_UNK_D9 0xD9 + // LVL1 LVL2 LVL3 UNK0 UNK1 +#define MIPI_DCS_PRIV_SM_SET_REGS_LOCK 0xE2 // Samsung: Lock (default): 5A5A A5A5 A5A5 A500 A500. Unlock: A5A5 5A5A 5A5A UNK UNK. #define MIPI_DCS_PRIV_READ_EXTC_CMD_SPI 0xFE // Read EXTC Command In SPI. 1 byte. 0-6: EXT_SPI_CNT, 7:EXT_SP. #define MIPI_DCS_PRIV_SET_EXTC_CMD_REG 0xFF // EXTC Command Set enable register. 5 bytes. Pass: FF 98 06 04, PAGE. @@ -648,12 +705,25 @@ #define DCS_GAMMA_CURVE_GC2_1_0 BIT(2) #define DCS_GAMMA_CURVE_GC3_1_0 BIT(3) // Are there more? +#define DCS_CONTROL_DISPLAY_SM_FLASHLIGHT BIT(2) #define DCS_CONTROL_DISPLAY_BACKLIGHT_CTRL BIT(2) #define DCS_CONTROL_DISPLAY_DIMMING_CTRL BIT(3) #define DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL BIT(5) -#define PANEL_OLED_BL_COEFF 82 // 82%. -#define PANEL_OLED_BL_OFFSET 45 // Least legible backlight duty. +#define DCS_SM_COLOR_MODE_SATURATED 0x00 // Disabled. Similar to vivid but over-saturated. Wide gamut? +#define DCS_SM_COLOR_MODE_WASHED 0x45 +#define DCS_SM_COLOR_MODE_BASIC 0x03 +#define DCS_SM_COLOR_MODE_POR_RESET 0x20 // Reset value on power on. +#define DCS_SM_COLOR_MODE_NATURAL 0x23 // Not actually natural.. +#define DCS_SM_COLOR_MODE_VIVID 0x65 +#define DCS_SM_COLOR_MODE_NIGHT0 0x43 // Based on washed out. +#define DCS_SM_COLOR_MODE_NIGHT1 0x15 // Based on basic. +#define DCS_SM_COLOR_MODE_NIGHT2 0x35 // Based on natural. +#define DCS_SM_COLOR_MODE_NIGHT3 0x75 // Based on vivid. + +#define DCS_SM_COLOR_MODE_ENABLE BIT(0) + +#define PANEL_SM_BL_CANDELA_MAX 2047 /* Switch Panels: * @@ -662,19 +732,28 @@ * [10] 96 [09]: JDI LAM062M109A * [20] 93 [0F]: InnoLux P062CCA-AZ1 (Rev A1) * [20] 95 [0F]: InnoLux P062CCA-AZ2 (Rev B1) - * [20] 96 [0F]: InnoLux P062CCA-AZ3 [UNCONFIRMED MODEL REV] - * [20] 97 [0F]: InnoLux P062CCA-??? [UNCONFIRMED MODEL REV] - * [20] 98 [0F]: InnoLux P062CCA-??? [UNCONFIRMED MODEL REV] + * [20] 96 [0F]: InnoLux P062CCA-AZ3 (Rev XX) [UNCONFIRMED MODEL+REV] + * [20] 97 [0F]: InnoLux P062CCA-??? (Rev XX) [UNCONFIRMED MODEL+REV] + * [20] 98 [0F]: InnoLux P062CCA-??? (Rev XX) [UNCONFIRMED MODEL+REV] + * [30] 93 [0F]: AUO A062TAN00 (59.06A33.000) * [30] 94 [0F]: AUO A062TAN01 (59.06A33.001) * [30] 95 [0F]: AUO A062TAN02 (59.06A33.002) + * [30] 97 [0F]: AUO A062TAN02 (59.06A33.002) [From photo of assumed same panel] + * [30] 98 [0F]: AUO A062TAN0? [UNCONFIRMED MODEL] * [30] XX [0F]: AUO A062TAN03 (59.06A33.003) [UNCONFIRMED ID] * - * 5.5" panels for Hoag SKUs: - * [20] 94 [10]: InnoLux 2J055IA-27A (Rev B1) - * [30] 93 [10]: AUO A055TAN01 (59.05A30.001) - * [40] XX [10]: Vendor 40 [UNCONFIRMED ID] * - * 7.0" OLED panels for Aula SKUs: + * 5.5" panels for Hoag SKU: + * [20] 94 [10]: InnoLux 2J055IA-27A (Rev B1) (6203B001P4000) + * [20] 95 [10]: InnoLux 2J055IA-27A (Rev XX) [UNCONFIRMED MODEL+REV] + * [20] 96 [10]: InnoLux 2J055IA-27A (Rev XX) [UNCONFIRMED MODEL+REV] + * [30] 93 [10]: AUO A055TAN01 (59.05A30.001) + * [30] 94 [10]: AUO A055TAN02 (59.05A30.002) + * [30] 95 [10]: AUO A055TAN03 (59.05A30.003) + * [40] 94 [10]: Sharp LQ055T1SW10 (Rev P) + * + * + * 7.0" OLED panels for Aula SKU: * [50] 9B [20]: Samsung AMS699VC01-0 (Rev 2.5) */ @@ -688,7 +767,7 @@ * 10h: Japan Display Inc. * 20h: InnoLux Corporation * 30h: AU Optronics - * 40h: Unknown0 + * 40h: Sharp * 50h: Samsung * * Boards, Panel Size: @@ -706,7 +785,7 @@ enum PANEL_AUO_A062TAN01 = 0x0F30, PANEL_INL_2J055IA_27A = 0x1020, PANEL_AUO_A055TAN01 = 0x1030, - PANEL_V40_55_UNK = 0x1040, + PANEL_SHP_LQ055T1SW10 = 0x1040, PANEL_SAM_AMS699VC01 = 0x2050 }; @@ -726,8 +805,9 @@ void display_backlight(bool enable); void display_backlight_brightness(u32 brightness, u32 step_delay); u32 display_get_backlight_brightness(); -/*! Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */ +/*! 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(); @@ -737,7 +817,9 @@ void display_init_cursor(void *crs_fb, u32 size); void display_set_pos_cursor(u32 x, u32 y); void display_deinit_cursor(); -void display_dsi_write(u8 cmd, u32 len, void *data, bool video_enabled); -int display_dsi_read(u8 cmd, u32 len, void *data, bool video_enabled); +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); #endif diff --git a/bdk/display/di.inl b/bdk/display/di.inl index c1e5d84..61569a7 100644 --- a/bdk/display/di.inl +++ b/bdk/display/di.inl @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert -* Copyright (c) 2018-2020 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, @@ -15,33 +15,29 @@ * along with this program. If not, see . */ -//Display A config. -static const cfg_op_t _display_dc_setup_win_config[94] = { +// Display A config. +static const cfg_op_t _di_dc_setup_win_config[] = { {DC_CMD_STATE_ACCESS, 0}, {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, - {DC_CMD_REG_ACT_CONTROL, 0x54}, // Select H counter for win A/B/C. + {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}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {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 | 0x9}, // 9: SYNCPT + {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_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + + /* 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_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, - {DC_WIN_DV_CONTROL, 0}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_DV_CONTROL, 0}, /* Setup default YUV colorspace conversion coefficients */ {DC_WIN_CSC_YOF, 0xF0}, {DC_WIN_CSC_KYRGB, 0x12A}, @@ -52,66 +48,19 @@ static const cfg_op_t _display_dc_setup_win_config[94] = { {DC_WIN_CSC_KUB, 0x204}, {DC_WIN_CSC_KVB, 0}, /* End of color coefficients */ - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, - {DC_WIN_DV_CONTROL, 0}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, - /* 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_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, - {DC_WIN_DV_CONTROL, 0}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, - /* 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_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888}, {DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C}, - {DC_COM_PIN_OUTPUT_POLARITY(1), 0x1000000}, + {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}, - {DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, - {DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, - {DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF}, + {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}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {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}, @@ -119,18 +68,18 @@ static const cfg_op_t _display_dc_setup_win_config[94] = { {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ} }; -//DSI Init config. -static const cfg_op_t _display_dsi_init_config_part1[8] = { +// DSI Init config. +static const cfg_op_t _di_dsi_init_irq_pkt_config0[] = { {DSI_WR_DATA, 0}, {DSI_INT_ENABLE, 0}, {DSI_INT_STATUS, 0}, - {DSI_INT_MASK, 0}, + {DSI_INT_MASK, 0}, {DSI_INIT_SEQ_DATA_0, 0}, {DSI_INIT_SEQ_DATA_1, 0}, {DSI_INIT_SEQ_DATA_2, 0}, {DSI_INIT_SEQ_DATA_3, 0} }; -static const cfg_op_t _display_dsi_init_config_part2[14] = { +static const cfg_op_t _di_dsi_init_irq_pkt_config1[] = { {DSI_DCS_CMDS, 0}, {DSI_PKT_SEQ_0_LO, 0}, {DSI_PKT_SEQ_1_LO, 0}, @@ -146,7 +95,7 @@ static const cfg_op_t _display_dsi_init_config_part2[14] = { {DSI_PKT_SEQ_5_HI, 0}, {DSI_CONTROL, 0} }; -static const cfg_op_t _display_dsi_init_config_part3_t210b01[7] = { +static const cfg_op_t _di_dsi_init_pads_t210b01[] = { {DSI_PAD_CONTROL_1, 0}, {DSI_PAD_CONTROL_2, 0}, {DSI_PAD_CONTROL_3, 0}, @@ -155,10 +104,10 @@ static const cfg_op_t _display_dsi_init_config_part3_t210b01[7] = { {DSI_PAD_CONTROL_6_B01, 0}, {DSI_PAD_CONTROL_7_B01, 0} }; -static const cfg_op_t _display_dsi_init_config_part4[10] = { +static const cfg_op_t _di_dsi_init_timing_pkt_config2[] = { {DSI_PAD_CONTROL_CD, 0}, - {DSI_SOL_DELAY, 0x18}, - {DSI_MAX_THRESHOLD, 0x1E0}, + {DSI_SOL_DELAY, 24}, + {DSI_MAX_THRESHOLD, 480}, {DSI_TRIGGER, 0}, {DSI_INIT_SEQ_CONTROL, 0}, {DSI_PKT_LEN_0_1, 0}, @@ -167,12 +116,12 @@ static const cfg_op_t _display_dsi_init_config_part4[10] = { {DSI_PKT_LEN_6_7, 0}, {DSI_PAD_CONTROL_1, 0} }; -static const cfg_op_t _display_dsi_init_config_part5[12] = { +static const cfg_op_t _di_dsi_init_timing_pwrctrl_config[] = { {DSI_PHY_TIMING_1, 0x40A0E05}, {DSI_PHY_TIMING_2, 0x30109}, - {DSI_BTA_TIMING, 0x190A14}, + {DSI_BTA_TIMING, 0x190A14}, {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)}, - {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x765) | DSI_TIMEOUT_TA(0x2000)}, + {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_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, @@ -181,25 +130,25 @@ static const cfg_op_t _display_dsi_init_config_part5[12] = { {DSI_POWER_CONTROL, 0}, {DSI_PAD_CONTROL_1, 0} }; -static const cfg_op_t _display_dsi_init_config_part6[14] = { +static const cfg_op_t _di_dsi_init_timing_pkt_config3[] = { {DSI_PHY_TIMING_1, 0x40A0E05}, {DSI_PHY_TIMING_2, 0x30118}, - {DSI_BTA_TIMING, 0x190A14}, + {DSI_BTA_TIMING, 0x190A14}, {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)}, - {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)}, + {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}, {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, - {DSI_MAX_THRESHOLD, 0x40}, + {DSI_MAX_THRESHOLD, 64}, {DSI_TRIGGER, 0}, {DSI_TX_CRC, 0}, {DSI_INIT_SEQ_CONTROL, 0} }; -//DSI panel config. -static const cfg_op_t _display_init_config_jdi[43] = { +// DSI panel JDI config. +static const cfg_op_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}, @@ -245,13 +194,13 @@ static const cfg_op_t _display_init_config_jdi[43] = { {DSI_TRIGGER, DSI_TRIGGER_HOST} }; -//DSI packet config. -static const cfg_op_t _display_dsi_packet_config[19] = { +// DSI packet config. +static const cfg_op_t _di_dsi_init_seq_pkt_final_config[] = { {DSI_PHY_TIMING_1, 0x40A0E05}, {DSI_PHY_TIMING_2, 0x30172}, - {DSI_BTA_TIMING, 0x190A14}, + {DSI_BTA_TIMING, 0x190A14}, {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xA40)}, - {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x5A2F) | DSI_TIMEOUT_TA(0x2000)}, + {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}, @@ -261,66 +210,66 @@ static const cfg_op_t _display_dsi_packet_config[19] = { {DSI_PKT_SEQ_3_HI, 0x2CC}, {DSI_PKT_SEQ_5_LO, 0x3F3B2B08}, {DSI_PKT_SEQ_5_HI, 0x2CC}, - {DSI_PKT_LEN_0_1, 0xCE0000}, - {DSI_PKT_LEN_2_3, 0x87001A2}, - {DSI_PKT_LEN_4_5, 0x190}, - {DSI_PKT_LEN_6_7, 0x190}, + {DSI_PKT_LEN_0_1, PKT1_LEN(206) | PKT0_LEN(0)}, + {DSI_PKT_LEN_2_3, PKT1_LEN(2160) | PKT0_LEN(418)}, + {DSI_PKT_LEN_4_5, PKT1_LEN(0) | PKT0_LEN(400)}, + {DSI_PKT_LEN_6_7, PKT1_LEN(0) | PKT0_LEN(400)}, {DSI_HOST_CONTROL, 0} }; -//DSI mode config. -static const cfg_op_t _display_dsi_mode_config[10] = { +// DSI mode config. +static const cfg_op_t _di_dsi_mode_config[] = { {DSI_TRIGGER, 0}, {DSI_CONTROL, 0}, {DSI_SOL_DELAY, 6}, - {DSI_MAX_THRESHOLD, 0x1E0}, + {DSI_MAX_THRESHOLD, 480}, {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, {DSI_CONTROL, DSI_CONTROL_HS_CLK_CTRL | DSI_CONTROL_FORMAT(3) | DSI_CONTROL_LANES(3) | DSI_CONTROL_VIDEO_ENABLE}, - {DSI_HOST_CONTROL, DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_FIFO_SEL| DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}, + {DSI_HOST_CONTROL, DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_FIFO_SEL | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}, {DSI_CONTROL, DSI_CONTROL_HS_CLK_CTRL | DSI_CONTROL_FORMAT(3) | DSI_CONTROL_LANES(3) | DSI_CONTROL_VIDEO_ENABLE}, - {DSI_HOST_CONTROL, DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}, - {DSI_HOST_CONTROL, DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC} + {DSI_HOST_CONTROL, DSI_HOST_CONTROL_TX_TRIG_SOL | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}, + {DSI_HOST_CONTROL, DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_TX_TRIG_SOL | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC} }; -//MIPI CAL config. -static const cfg_op_t _display_mipi_pad_cal_config[4] = { +// MIPI CAL config. +static const cfg_op_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}, {MIPI_CAL_MIPI_BIAS_PAD_CFG2, 0} }; -//DSI config. -static const cfg_op_t _display_dsi_pad_cal_config_t210[4] = { +// DSI pad config. +static const cfg_op_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 _display_dsi_pad_cal_config_t210b01[7] = { - {DSI_PAD_CONTROL_1, 0}, - {DSI_PAD_CONTROL_2, 0}, - {DSI_PAD_CONTROL_3, 0}, - {DSI_PAD_CONTROL_4, 0x77777}, +static const cfg_op_t _di_dsi_pad_cal_config_t210b01[] = { + {DSI_PAD_CONTROL_1, 0}, + {DSI_PAD_CONTROL_2, 0}, + {DSI_PAD_CONTROL_3, 0}, + {DSI_PAD_CONTROL_4, 0x77777}, {DSI_PAD_CONTROL_5_B01, 0x77777}, - {DSI_PAD_CONTROL_6_B01, 0x1111}, + {DSI_PAD_CONTROL_6_B01, DSI_PAD_PREEMP_PD_CLK(0x1) | DSI_PAD_PREEMP_PU_CLK(0x1) | DSI_PAD_PREEMP_PD(0x01) | DSI_PAD_PREEMP_PU(0x1)}, {DSI_PAD_CONTROL_7_B01, 0} }; -//MIPI CAL config. -static const cfg_op_t _display_mipi_dsi_cal_offsets_config_t210[4] = { +// MIPI CAL config. +static const cfg_op_t _di_mipi_dsi_cal_offsets_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 _display_mipi_dsi_cal_offsets_config_t210b01[4] = { +static const cfg_op_t _di_mipi_dsi_cal_offsets_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 _display_mipi_apply_dsi_cal_config[12] = { +static const cfg_op_t _di_mipi_start_dsi_cal_config[] = { {MIPI_CAL_CILA_MIPI_CAL_CONFIG, 0}, {MIPI_CAL_CILB_MIPI_CAL_CONFIG, 0}, {MIPI_CAL_CILC_MIPI_CAL_CONFIG, 0}, @@ -332,19 +281,17 @@ static const cfg_op_t _display_mipi_apply_dsi_cal_config[12] = { {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} + {MIPI_CAL_MIPI_CAL_CTRL, 0x2A000001} // Set Prescale and filter and start calibration. }; -//Display A config. -static const cfg_op_t _display_video_disp_controller_enable_config[113] = { +// Display A enable config. +static const cfg_op_t _di_dc_video_enable_config[] = { {DC_CMD_STATE_ACCESS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + + /* 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_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, - {DC_WIN_DV_CONTROL, 0}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_DV_CONTROL, 0}, /* Setup default YUV colorspace conversion coefficients */ {DC_WIN_CSC_YOF, 0xF0}, {DC_WIN_CSC_KYRGB, 0x12A}, @@ -355,66 +302,19 @@ static const cfg_op_t _display_video_disp_controller_enable_config[113] = { {DC_WIN_CSC_KUB, 0x204}, {DC_WIN_CSC_KVB, 0}, /* End of color coefficients */ - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, - {DC_WIN_DV_CONTROL, 0}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, - /* 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_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, - {DC_WIN_DV_CONTROL, 0}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, - /* 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_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888}, {DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C}, - {DC_COM_PIN_OUTPUT_POLARITY(1), 0x1000000}, + {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}, - {DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, - {DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, - {DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF}, + {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}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {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}, @@ -422,34 +322,13 @@ static const cfg_op_t _display_video_disp_controller_enable_config[113] = { {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ}, {DC_CMD_STATE_ACCESS, 0}, - /* Set Display timings - * - * DC_DISP_REF_TO_SYNC: - * V_REF_TO_SYNC - 1 - * H_REF_TO_SYNC - 0 - * - * DC_DISP_SYNC_WIDTH: - * V_SYNC_WIDTH - 1 - * H_SYNC_WIDTH - 72 - * - * DC_DISP_BACK_PORCH: - * V_BACK_PORCH - 9 - * H_BACK_PORCH - 72 - * - * DC_DISP_ACTIVE: - * V_DISP_ACTIVE - 1280 - * H_DISP_ACTIVE - 720 - * - * DC_DISP_FRONT_PORCH: - * V_FRONT_PORCH - 10 - * H_FRONT_PORCH - 136 - */ - {DC_DISP_DISP_TIMING_OPTIONS, 0}, - {DC_DISP_REF_TO_SYNC, 0x10000}, - {DC_DISP_SYNC_WIDTH, 0x10048}, - {DC_DISP_BACK_PORCH, 0x90048}, - {DC_DISP_ACTIVE, 0x50002D0}, - {DC_DISP_FRONT_PORCH, 0xA0088}, // Sources say that this should happen before DC_DISP_ACTIVE cmd. + /* 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)}, + {DC_DISP_SYNC_WIDTH, V_SYNC_WIDTH(1) | H_SYNC_WIDTH(72)}, + {DC_DISP_BACK_PORCH, V_BACK_PORCH(9) | H_BACK_PORCH(72)}, + {DC_DISP_FRONT_PORCH, V_FRONT_PORCH(10) | H_FRONT_PORCH(136)}, + {DC_DISP_ACTIVE, V_DISP_ACTIVE(1280) | H_DISP_ACTIVE(720)}, /* End of Display timings */ {DC_DISP_SHIFT_CLOCK_OPTIONS, SC1_H_QUALIFIER_NONE | SC0_H_QUALIFIER_NONE}, @@ -458,23 +337,18 @@ static const cfg_op_t _display_video_disp_controller_enable_config[113] = { {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}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {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_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, 0xA0088}, + {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, 0x301}, - {DC_CMD_GENERAL_INCR_SYNCPT, 0x301}, + {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}, @@ -483,9 +357,9 @@ static const cfg_op_t _display_video_disp_controller_enable_config[113] = { {DC_CMD_DISPLAY_COMMAND_OPTION0, 0} }; -////Display A config. -static const cfg_op_t _display_video_disp_controller_disable_config[17] = { - {DC_DISP_FRONT_PORCH, 0xA0088}, +// 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)}, {DC_CMD_INT_MASK, 0}, {DC_CMD_STATE_ACCESS, 0}, {DC_CMD_INT_ENABLE, 0}, @@ -493,39 +367,37 @@ static const cfg_op_t _display_video_disp_controller_disable_config[17] = { {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_STOP}, {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_STATE_CONTROL, GENERAL_UPDATE}, {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, - {DC_CMD_GENERAL_INCR_SYNCPT, 0x301}, - {DC_CMD_GENERAL_INCR_SYNCPT, 0x301}, - {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, - {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + // 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 config. -static const cfg_op_t _display_dsi_timing_deinit_config[16] = { +// DSI deinit config. +static const cfg_op_t _di_dsi_timing_deinit_config[] = { {DSI_POWER_CONTROL, 0}, {DSI_PAD_CONTROL_1, 0}, - {DSI_PHY_TIMING_0, 0x6070601}, + {DSI_PHY_TIMING_0, 0x6070601}, //mariko changes {DSI_PHY_TIMING_1, 0x40A0E05}, {DSI_PHY_TIMING_2, 0x30118}, - {DSI_BTA_TIMING, 0x190A14}, + {DSI_BTA_TIMING, 0x190A14}, {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF) }, - {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)}, + {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}, - {DSI_MAX_THRESHOLD, 0x40}, + {DSI_MAX_THRESHOLD, 64}, {DSI_TRIGGER, 0}, {DSI_TX_CRC, 0}, {DSI_INIT_SEQ_CONTROL, 0} }; -//DSI config (if ver == 0x10). -static const cfg_op_t _display_deinit_config_jdi[22] = { +// DSI panel JDI deinit config. +static const cfg_op_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}, @@ -550,7 +422,8 @@ static const cfg_op_t _display_deinit_config_jdi[22] = { {DSI_TRIGGER, DSI_TRIGGER_HOST} }; -static const cfg_op_t _display_deinit_config_auo[37] = { +// DSI panel AUO deinit config. +static const cfg_op_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}, @@ -591,156 +464,143 @@ static const cfg_op_t _display_deinit_config_auo[37] = { {DSI_TRIGGER, DSI_TRIGGER_HOST} }; -static const cfg_op_t _display_init_config_invert[3] = { +static const cfg_op_t _di_init_config_invert[] = { {DSI_WR_DATA, 0x239}, {DSI_WR_DATA, 0x02C1}, // INV_EN. {DSI_TRIGGER, DSI_TRIGGER_HOST}, }; -//Display A config. -static const cfg_op_t cfg_display_one_color[8] = { - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, +// 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}, {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 config linear pitch. -static const cfg_op_t cfg_display_framebuffer_pitch[32] = { - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, +// 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}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, {DC_WIN_WIN_OPTIONS, 0}, {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, {DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, // NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8. - {DC_WIN_WIN_OPTIONS, 0}, - {DC_WIN_WIN_OPTIONS, 0}, {DC_WIN_POSITION, 0}, //(0,0) {DC_WIN_H_INITIAL_DDA, 0}, {DC_WIN_V_INITIAL_DDA, 0}, - {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)}, - {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x. - {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, - {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, // 720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. + {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)}, + {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x. + {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, + {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, // 720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. {DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST}, {DC_WINBUF_SURFACE_KIND, PITCH}, {DC_WINBUF_START_ADDR, IPL_FB_ADDRESS}, // Framebuffer address. {DC_WINBUF_ADDR_H_OFFSET, 0}, {DC_WINBUF_ADDR_V_OFFSET, 0}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, {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_ACT_REQ | WIN_A_ACT_REQ} }; -//Display A config linear pitch inverse + Win D support. -static const cfg_op_t cfg_display_framebuffer_pitch_inv[34] = { - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, +// 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}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, {DC_WIN_WIN_OPTIONS, 0}, {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, {DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, // NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8. - {DC_WIN_WIN_OPTIONS, 0}, - {DC_WIN_WIN_OPTIONS, 0}, {DC_WIN_POSITION, 0}, //(0,0) {DC_WIN_H_INITIAL_DDA, 0}, {DC_WIN_V_INITIAL_DDA, 0}, - {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)}, - {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x. - {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, - {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, // 720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. + {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)}, + {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x. + {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, + {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, // 720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. + {DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST}, + {DC_WINBUF_SURFACE_KIND, PITCH}, + {DC_WINBUF_START_ADDR, NYX_FB_ADDRESS}, // Framebuffer address. + {DC_WINBUF_ADDR_H_OFFSET, 0}, + {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_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}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, + {DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, // NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8. + {DC_WIN_POSITION, 0}, //(0,0) + {DC_WIN_H_INITIAL_DDA, 0}, + {DC_WIN_V_INITIAL_DDA, 0}, + {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)}, + {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x. + {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, + {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(720 * 2) | LINE_STRIDE(720 * 4)}, // 720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. {DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST}, {DC_WINBUF_SURFACE_KIND, PITCH}, {DC_WINBUF_START_ADDR, NYX_FB_ADDRESS}, // Framebuffer address. {DC_WINBUF_ADDR_H_OFFSET, 0}, // Linear: 0x383FFC, Block: 0x3813FC. {DC_WINBUF_ADDR_V_OFFSET, 1279}, // Linear: 1279, Block: 0. - {DC_WIN_WIN_OPTIONS, 0}, - {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, {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_ACT_REQ | WIN_A_ACT_REQ} }; -//Display A config block linear. -static const cfg_op_t cfg_display_framebuffer_block[34] = { - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, +// 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}, {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, {DC_WIN_WIN_OPTIONS, 0}, {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, {DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, // NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8. - {DC_WIN_WIN_OPTIONS, 0}, - {DC_WIN_WIN_OPTIONS, 0}, {DC_WIN_POSITION, 0}, //(0,0) {DC_WIN_H_INITIAL_DDA, 0}, {DC_WIN_V_INITIAL_DDA, 0}, - {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)}, - {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x. - {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, - {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(1280 * 2) | LINE_STRIDE(1280 * 4)}, //720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. + {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(720 * 4)}, + {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x. + {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, + {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(1280 * 2) | LINE_STRIDE(1280 * 4)}, //720*2x720*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. {DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST}, {DC_WINBUF_SURFACE_KIND, BLOCK_HEIGHT(4) | BLOCK}, {DC_WINBUF_START_ADDR, NYX_FB_ADDRESS}, // Framebuffer address. - {DC_WINBUF_ADDR_H_OFFSET, 0x3813FC}, // Linear: 0x383FFC, Block: 0x3813FC. + {DC_WINBUF_ADDR_H_OFFSET, 0x3813FC}, // Linear: 0x383FFC, Block: 0x3813FC. Block in HOS: 0x13FF. {DC_WINBUF_ADDR_V_OFFSET, 0}, // Linear: 1279, Block: 0. - {DC_WIN_WIN_OPTIONS, 0}, - {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, - {DC_WIN_WIN_OPTIONS, 0}, - {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, {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_ACT_REQ | WIN_A_ACT_REQ} }; -//Display D config. -static const cfg_op_t cfg_display_framebuffer_log[20] = { +// Display A Window D config. +static const cfg_op_t _di_win_framebuffer_log[] = { {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_D_SELECT}, {DC_WIN_WIN_OPTIONS, 0}, {DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, {DC_WIN_POSITION, 0}, //(0,0) {DC_WIN_H_INITIAL_DDA, 0}, {DC_WIN_V_INITIAL_DDA, 0}, - {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(656 * 4)}, - {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x. - {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(656)}, - {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(656 * 2) | LINE_STRIDE(656 * 4)}, //656*2x656*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. + {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(656 * 4)}, + {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, // 1.0x. + {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(656)}, + {DC_WIN_LINE_STRIDE, UV_LINE_STRIDE(656 * 2) | LINE_STRIDE(656 * 4)}, //656*2x656*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. {DC_WIN_BUFFER_CONTROL, BUFFER_CONTROL_HOST}, {DC_WINBUF_SURFACE_KIND, PITCH}, {DC_WINBUF_START_ADDR, LOG_FB_ADDRESS}, // Framebuffer address. {DC_WINBUF_ADDR_H_OFFSET, 0}, {DC_WINBUF_ADDR_V_OFFSET, 0}, - {DC_WINBUF_BLEND_LAYER_CONTROL, WIN_BLEND_ENABLE | WIN_K1(200)}, + {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_WIN_WIN_OPTIONS, 0}, // Enable window DD. {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 new file mode 100644 index 0000000..c9a0c59 --- /dev/null +++ b/bdk/display/vic.c @@ -0,0 +1,563 @@ +/* + * VIC driver for Tegra X1 + * + * Copyright (c) 2018-2023 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, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include "vic.h" +#include +#include +#include +#include +#include +#include + +/* VIC Private registers */ +#define PVIC_FALCON_PA_OFFSET 0x1000 +#define PVIC_FALCON_ADDR 0x10AC +#define PVIC_FALCON_IDLESTATE 0x104C + +/* VIC Control and Status registers. */ +/* Fetch Control registers. */ +#define VIC_FC_COMPOSE 0x10000 +#define COMPOSE_START BIT(0) + +#define VIC_FC_CFG_STRUCT_SLOT_INDEX 0x10B00 + +#define VIC_FC_CFG_STRUCT_SLOT_CFG0 0x10B04 +#define SLOT_ENABLE BIT(0) +#define FIELD_CURRENT_ENABLE BIT(8) + +#define VIC_FC_CFG_STRUCT_SLOT_CFG2 0x10B0C +#define CACHE_WIDTH(n) ((n) << 16) +#define CACHE_WIDTH_16BX16 0 // Block Linear. +#define CACHE_WIDTH_32BX8 1 // Block Linear. Recommended for Block Linear. +#define CACHE_WIDTH_64BX4 2 // Block Linear, Pitch. Recommended for Pitch. +#define CACHE_WIDTH_128BX2 3 // Block Linear, Pitch. +#define OUTPUT_FLIP_X BIT(20) +#define OUTPUT_FLIP_Y BIT(21) +#define OUTPUT_TRANSPOSE BIT(22) + +#define VIC_FC_CFG_STRUCT_SLOT_SFC_SIZE 0x10B10 +#define VIC_FC_CFG_STRUCT_SLOT_LUMA_SIZE 0x10B14 +#define VIC_FC_CFG_STRUCT_SLOT_CHROMA_SIZE 0x10B18 +#define VIC_FC_CFG_STRUCT_SLOT_SRC_RECT_LR 0x10B1C +#define VIC_FC_CFG_STRUCT_SLOT_SRC_RECT_TB 0x10B20 +#define VIC_FC_CFG_STRUCT_SLOT_DST_RECT_LR 0x10B30 +#define VIC_FC_CFG_STRUCT_SLOT_DST_RECT_TB 0x10B34 +#define VIC_FC_CFG_STRUCT_TGT_RECT_LR 0x10B38 +#define VIC_FC_CFG_STRUCT_TGT_RECT_TB 0x10B3C +#define VIC_FC_SLOT_MAP 0x10C00 + +#define VIC_FC_FCE_CTRL 0x11000 +#define START_TRIGGER BIT(0) +#define HALT_TRIGGER BIT(1) +#define CLEAR_ERROR BIT(8) + +#define VIC_FC_FCE_UCODE_ADDR 0x11200 +#define VIC_FC_FCE_UCODE_INST 0x11300 + +/* Surface List registers. */ +#define VIC_SL_CFG_STRUCT_SLOT_INDEX 0x12100 +#define VIC_SL_CFG_STRUCT_SLOT_DST_RECT_LR 0x12200 +#define VIC_SL_CFG_STRUCT_SLOT_DST_RECT_TB 0x12300 +#define VIC_SL_CFG_STRUCT_TGT_RECT_LR 0x12400 +#define VIC_SL_CFG_STRUCT_TGT_RECT_TB 0x12500 +#define VIC_SL_CFG_STRUCT_SLOT_CFG0 0x12600 + +/* Surface Cache registers. */ +#define VIC_SC_PRAMBASE 0x14000 +#define VIC_SC_PRAMSIZE 0x14100 +#define VIC_SC_SFC0_BASE_LUMA(n) (0x14300 + (n) * 0x100) + +/* Blending Output registers. */ +#define VIC_BL_TARGET_BASADR 0x22000 +#define VIC_BL_CONFIG 0x22800 +#define SUBPARTITION_MODE BIT(0) +#define PROCESS_CFG_STRUCT_TRIGGER BIT(2) +#define SLOTMASK(n) ((n) << 8) + +#define VIC_BL_CFG_STRUCT_CFG0 0x22C00 +#define VIC_BL_CFG_STRUCT_SFC_SIZE 0x22C04 +#define VIC_BL_CFG_STRUCT_LUMA_SIZE 0x22C08 +#define VIC_BL_CFG_STRUCT_CHROMA_SIZE 0x22C0C +#define VIC_BL_CFG_STRUCT_TGT_RECT_LR 0x22C10 +#define VIC_BL_CFG_STRUCT_TGT_RECT_TB 0x22C14 + +// VIC_FC_CFG_STRUCT_SLOT_CFG2 & VIC_BL_CFG_STRUCT_CFG0. +#define BLK_KIND(n) ((n) << 8) +#define BLK_KIND_PITCH 0 +#define BLK_KIND_GENERIC_16BX2 1 +#define BLK_HEIGHT(n) ((n) << 12) +#define BLK_HEIGHT_ONE_GOB 0 +#define BLK_HEIGHT_SIXTEEN_GOBS 4 + +// Generic size macros. +#define SIZE_WIDTH(n) (((n) - 1) << 0) +#define SIZE_HEIGHT(n) (((n) - 1) << 16) +#define RECT_LEFT(n) ((n) << 0) +#define RECT_RIGHT(n) (((n) - 1) << 16) +#define RECT_TOP(n) ((n) << 0) +#define RECT_BOTTOM(n) (((n) - 1) << 16) + +#define FORMAT_PROGRESSIVE 0 +#define SOFT_CLAMP_MIN 0 +#define SOFT_CLAMP_MAX 0x3FFu +#define ALPHA_1_0 0x3FFu + +typedef struct _OutputConfig { + u64 AlphaFillMode:3; + u64 AlphaFillSlot:3; + u64 BackgroundAlpha:10; + u64 BackgroundR:10; + u64 BackgroundG:10; + u64 BackgroundB:10; + u64 RegammaMode:2; + u64 OutputFlipX:1; + u64 OutputFlipY:1; + u64 OutputTranspose:1; + u64 rsvd1:1; + u64 rsvd2:12; + u64 TargetRectLeft:14; + u64 rsvd3:2; + u64 TargetRectRight:14; + u64 rsvd4:2; + u64 TargetRectTop:14; + u64 rsvd5:2; + u64 TargetRectBottom:14; + u64 rsvd6:2; +} OutputConfig; + +typedef struct _OutputSurfaceConfig { + u64 OutPixelFormat:7; + u64 OutChromaLocHoriz:2; + u64 OutChromaLocVert:2; + u64 OutBlkKind:4; + u64 OutBlkHeight:4; + u64 rsvd0:3; + u64 rsvd1:10; + u64 OutSurfaceWidth:14; + u64 OutSurfaceHeight:14; + u64 rsvd2:4; + u64 OutLumaWidth:14; + u64 OutLumaHeight:14; + u64 rsvd3:4; + u64 OutChromaWidth:14; + u64 OutChromaHeight:14; + u64 rsvd4:4; +} OutputSurfaceConfig; + +typedef struct _SlotConfig { + u64 SlotEnable:1; + u64 DeNoise:1; + u64 AdvancedDenoise:1; + u64 CadenceDetect:1; + u64 MotionMap:1; + u64 MMapCombine:1; + u64 IsEven:1; + u64 ChromaEven:1; + u64 CurrentFieldEnable:1; + u64 PrevFieldEnable:1; + u64 NextFieldEnable:1; + u64 NextNrFieldEnable:1; + u64 CurMotionFieldEnable:1; + u64 PrevMotionFieldEnable:1; + u64 PpMotionFieldEnable:1; + u64 CombMotionFieldEnable:1; + u64 FrameFormat:4; + u64 FilterLengthY:2; + u64 FilterLengthX:2; + u64 Panoramic:12; + u64 rsvd1:22; + u64 DetailFltClamp:6; + u64 FilterNoise:10; + u64 FilterDetail:10; + u64 ChromaNoise:10; + u64 ChromaDetail:10; + u64 DeinterlaceMode:4; + u64 MotionAccumWeight:3; + u64 NoiseIir:11; + u64 LightLevel:4; + u64 rsvd4:2; + u64 SoftClampLow:10; + u64 SoftClampHigh:10; + u64 rsvd5:3; + u64 rsvd6:9; + u64 PlanarAlpha:10; + u64 ConstantAlpha:1; + u64 StereoInterleave:3; + u64 ClipEnabled:1; + u64 ClearRectMask:8; + u64 DegammaMode:2; + u64 rsvd7:1; + u64 DecompressEnable:1; + u64 rsvd9:5; + u64 DecompressCtbCount:8; + u64 DecompressZbcColor:32; + u64 rsvd12:24; + u64 SourceRectLeft:30; + u64 rsvd14:2; + u64 SourceRectRight:30; + u64 rsvd15:2; + u64 SourceRectTop:30; + u64 rsvd16:2; + u64 SourceRectBottom:30; + u64 rsvd17:2; + u64 DestRectLeft:14; + u64 rsvd18:2; + u64 DestRectRight:14; + u64 rsvd19:2; + u64 DestRectTop:14; + u64 rsvd20:2; + u64 DestRectBottom:14; + u64 rsvd21:2; + u64 rsvd22:32; + u64 rsvd23:32; +} SlotConfig; + +typedef struct _SlotSurfaceConfig { + u64 SlotPixelFormat:7; + u64 SlotChromaLocHoriz:2; + u64 SlotChromaLocVert:2; + u64 SlotBlkKind:4; + u64 SlotBlkHeight:4; + u64 SlotCacheWidth:3; + u64 rsvd0:10; + u64 SlotSurfaceWidth:14; + u64 SlotSurfaceHeight:14; + u64 rsvd1:4; + u64 SlotLumaWidth:14; + u64 SlotLumaHeight:14; + u64 rsvd2:4; + u64 SlotChromaWidth:14; + u64 SlotChromaHeight:14; + u64 rsvd3:4; +} SlotSurfaceConfig; + +typedef struct _SlotStruct { + SlotConfig slot_cfg; + SlotSurfaceConfig slot_sfc_cfg; + + // No need to configure. Reset to zeros. + u8 lumaKeyStruct[0x10]; + u8 colorMatrixStruct[0x20]; + u8 gamutMatrixStruct[0x20]; + u8 blendingSlotStruct[0x10]; +} SlotStruct; + +typedef struct _vic_config_t { + // No need to configure. Reset to zeros. + u8 pipeConfig[0x10]; + + OutputConfig out_cfg; + OutputSurfaceConfig out_sfc_cfg; + + // No need to configure. Reset to zeros. + u8 out_color_matrix[0x20]; + u8 clear_rect[0x10 * 4]; + + SlotStruct slots[8]; +} vic_config_t; + +// VIC Fetch Control Engine microcode. Dumped from L4T r33. +u8 vic_fce_ucode[] = { + 0x66, 0x00, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00, 0x42, 0x40, 0x10, 0x00, 0x4E, 0x01, 0x40, 0x00, + 0x6A, 0x07, 0x00, 0x00, 0x6E, 0x23, 0x04, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x4E, 0x01, 0x04, 0x00, + 0x6A, 0x0B, 0x00, 0x00, 0x6E, 0x1F, 0x04, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x4E, 0x01, 0x10, 0x00, + 0x6A, 0x0F, 0x00, 0x00, 0x6E, 0x1F, 0x04, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x48, 0x80, 0x02, 0x00, + 0x0E, 0x11, 0x00, 0x00, 0x6A, 0x14, 0x00, 0x00, 0x6E, 0x08, 0x06, 0x00, 0x6C, 0x00, 0x00, 0x00, + 0x4E, 0x01, 0x08, 0x00, 0x6A, 0x18, 0x00, 0x00, 0x6E, 0x26, 0x04, 0x00, 0x6C, 0x00, 0x00, 0x00, + 0x4E, 0x01, 0x20, 0x00, 0x6A, 0x1C, 0x00, 0x00, 0x6E, 0x26, 0x04, 0x00, 0x6C, 0x00, 0x00, 0x00, + 0x4E, 0x01, 0x02, 0x00, 0x6A, 0x20, 0x00, 0x00, 0x6E, 0x24, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, + 0x56, 0x00, 0x10, 0x00, 0x56, 0x40, 0x10, 0x00, 0x22, 0x41, 0x01, 0x00, 0x6C, 0x00, 0x00, 0x00, + 0x62, 0x80, 0x01, 0x00, 0x60, 0x47, 0x00, 0x00, 0x60, 0x87, 0x00, 0x00, 0x01, 0x4A, 0x00, 0x00, + 0x55, 0xC0, 0x20, 0x00, 0x00, 0x59, 0x00, 0x00, 0x60, 0x87, 0x00, 0x00, 0x60, 0xC7, 0x00, 0x00, + 0x01, 0x93, 0x00, 0x00, 0x40, 0x82, 0x02, 0x00, 0x4E, 0x02, 0x00, 0x00, 0x6B, 0x34, 0x00, 0x00, + 0x43, 0xC1, 0x10, 0x00, 0x42, 0x02, 0x03, 0x00, 0x00, 0x23, 0x01, 0x00, 0x24, 0xD4, 0x00, 0x00, + 0x56, 0x40, 0x3D, 0x00, 0x04, 0xEB, 0x00, 0x00, 0x60, 0x07, 0x01, 0x00, 0x60, 0x47, 0x00, 0x00, + 0x6A, 0x3E, 0x00, 0x00, 0x55, 0xC0, 0x30, 0x00, 0x48, 0x00, 0x01, 0x00, 0x48, 0x40, 0x01, 0x00, + 0x48, 0x80, 0x01, 0x00, 0x6B, 0x28, 0x02, 0x00, 0x56, 0x40, 0x09, 0x00, 0x04, 0x4D, 0x01, 0x00, + 0x06, 0x4D, 0x00, 0x00, 0x42, 0xC0, 0x03, 0x00, 0x56, 0x80, 0x09, 0x00, 0x04, 0xFE, 0x01, 0x00, + 0x00, 0xF9, 0x01, 0x00, 0x4E, 0x02, 0x00, 0x00, 0x6B, 0x32, 0x02, 0x00, 0x55, 0x40, 0x2F, 0x00, + 0x56, 0x80, 0x0D, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x6A, 0x0D, 0x02, 0x00, 0x55, 0x40, 0x31, 0x00, + 0x56, 0x80, 0x0B, 0x00, 0x0C, 0x2B, 0x00, 0x00, 0x6A, 0x13, 0x02, 0x00, 0x43, 0x45, 0x03, 0x00, + 0x42, 0x86, 0x03, 0x00, 0x4D, 0x06, 0x02, 0x00, 0x6A, 0x0D, 0x02, 0x00, 0x42, 0x86, 0x03, 0x00, + 0x22, 0x7E, 0x01, 0x00, 0x4E, 0x04, 0x00, 0x00, 0x6B, 0x32, 0x02, 0x00, 0x55, 0x40, 0x17, 0x00, + 0x0D, 0x2C, 0x00, 0x00, 0x56, 0xC0, 0x09, 0x00, 0x6A, 0x1E, 0x02, 0x00, 0x48, 0xC0, 0x01, 0x00, + 0x43, 0x04, 0x03, 0x00, 0x6C, 0x20, 0x02, 0x00, 0x55, 0x40, 0x19, 0x00, 0x01, 0x2C, 0x01, 0x00, + 0x65, 0x23, 0x01, 0x00, 0x42, 0x42, 0x03, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x24, 0x14, 0x01, 0x00, + 0x00, 0x2C, 0x01, 0x00, 0x24, 0x14, 0x01, 0x00, 0x00, 0x3C, 0x01, 0x00, 0x42, 0x04, 0x09, 0x00, + 0x42, 0xC3, 0x02, 0x00, 0x65, 0x54, 0x01, 0x00, 0x65, 0x55, 0x01, 0x00, 0x42, 0x45, 0x0D, 0x00, + 0x62, 0x03, 0x00, 0x00, 0x62, 0x44, 0x00, 0x00, 0x62, 0x85, 0x00, 0x00, 0x62, 0xC2, 0x00, 0x00, + 0x22, 0x48, 0x1F, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x48, 0x00, 0x01, 0x00, 0x6C, 0x28, 0x02, 0x00, + 0x62, 0x80, 0x01, 0x00, 0x60, 0x07, 0x00, 0x00, 0x60, 0x47, 0x00, 0x00, 0x60, 0x87, 0x00, 0x00, + 0x01, 0x01, 0x00, 0x00, 0x43, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x01, 0xCA, 0x01, 0x00, + 0x60, 0x03, 0x01, 0x00, 0x01, 0xA0, 0x01, 0x00, 0x60, 0x40, 0x00, 0x00, 0x65, 0x01, 0x00, 0x00, + 0x55, 0xC0, 0x2E, 0x00, 0x01, 0x18, 0x00, 0x00, 0x43, 0x00, 0x04, 0x00, 0x43, 0x41, 0x06, 0x00, + 0x6F, 0x00, 0x00, 0x00, 0x61, 0xC1, 0x00, 0x00, 0x61, 0x42, 0x01, 0x00, 0x65, 0xB5, 0x00, 0x00, + 0x65, 0x73, 0x01, 0x00, 0x65, 0x35, 0x01, 0x00, 0x65, 0x34, 0x01, 0x00, 0x42, 0x04, 0x0D, 0x00, + 0x01, 0x14, 0x01, 0x00, 0x42, 0x04, 0x03, 0x00, 0x00, 0x20, 0x00, 0x00, 0x43, 0x03, 0x05, 0x00, + 0x43, 0x85, 0x02, 0x00, 0x00, 0xAA, 0x00, 0x00, 0x48, 0x46, 0x01, 0x00, 0x65, 0xEB, 0x00, 0x00, + 0x00, 0x9A, 0x00, 0x00, 0x65, 0xB2, 0x01, 0x00, 0x00, 0xA6, 0x01, 0x00, 0x42, 0x86, 0x0D, 0x00, + 0x61, 0x42, 0x01, 0x00, 0x01, 0xAE, 0x01, 0x00, 0x00, 0x71, 0x00, 0x00, 0x42, 0x82, 0x08, 0x00, + 0x42, 0xC3, 0x08, 0x00, 0x48, 0x40, 0x01, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x6E, 0x34, 0x02, 0x00, + 0x65, 0x79, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x6C, 0x36, 0x04, 0x00, 0x6E, 0x34, 0x02, 0x00, + 0x48, 0x7F, 0x01, 0x00, 0x6C, 0x0A, 0x06, 0x00, 0x6E, 0x34, 0x02, 0x00, 0x6E, 0x05, 0x04, 0x00, + 0x65, 0x79, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x41, 0x87, 0x03, 0x00, 0x65, 0xBA, 0x00, 0x00, + 0x65, 0xB2, 0x00, 0x00, 0x42, 0x82, 0x02, 0x00, 0x00, 0x51, 0x00, 0x00, 0x61, 0xC1, 0x00, 0x00, + 0x65, 0xFB, 0x00, 0x00, 0x65, 0xF3, 0x00, 0x00, 0x41, 0x87, 0x05, 0x00, 0x65, 0xF3, 0x00, 0x00, + 0x42, 0xC3, 0x08, 0x00, 0x00, 0x59, 0x00, 0x00, 0x60, 0xC7, 0x00, 0x00, 0x60, 0xC7, 0x00, 0x00, + 0x56, 0xC0, 0x21, 0x00, 0x04, 0xDF, 0x01, 0x00, 0x43, 0xC7, 0x15, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x00, 0x79, 0x00, 0x00, 0x42, 0xC3, 0x20, 0x00, 0x43, 0xC3, 0x04, 0x00, 0x42, 0x00, 0x30, 0x00, + 0x42, 0x41, 0x30, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x60, 0xC7, 0x01, 0x00, + 0x22, 0x78, 0x01, 0x00, 0x22, 0x79, 0x03, 0x00, 0x22, 0x7F, 0x1F, 0x00, 0x6F, 0x00, 0x00, 0x00, + 0x6E, 0x34, 0x02, 0x00, 0x6E, 0x05, 0x04, 0x00, 0x4B, 0x41, 0x00, 0x00, 0x60, 0xC7, 0x01, 0x00, + 0x60, 0x87, 0x01, 0x00, 0x43, 0x86, 0x15, 0x00, 0x00, 0x30, 0x00, 0x00, 0x65, 0x39, 0x01, 0x00, + 0x42, 0x04, 0x05, 0x00, 0x4E, 0x05, 0x7E, 0x00, 0x6A, 0x1B, 0x06, 0x00, 0x55, 0xC0, 0x3D, 0x00, + 0x0A, 0x3C, 0x01, 0x00, 0x60, 0xC7, 0x01, 0x00, 0x22, 0x78, 0x01, 0x00, 0x22, 0x79, 0x03, 0x00, + 0x22, 0x7C, 0x09, 0x00, 0x22, 0x7F, 0x1F, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x65, 0x7A, 0x01, 0x00, + 0x42, 0x45, 0x05, 0x00, 0x65, 0xBB, 0x01, 0x00, 0x42, 0x86, 0x05, 0x00, 0x55, 0xC0, 0x3D, 0x00, + 0x0A, 0x7D, 0x01, 0x00, 0x0A, 0xBE, 0x01, 0x00, 0x07, 0xC7, 0x01, 0x00, 0x0B, 0x7D, 0x01, 0x00, + 0x0B, 0xBE, 0x01, 0x00, 0x55, 0xC0, 0x3D, 0x00, 0x0A, 0x3C, 0x01, 0x00, 0x60, 0xC7, 0x01, 0x00, + 0x22, 0x78, 0x01, 0x00, 0x22, 0x79, 0x03, 0x00, 0x22, 0x7A, 0x05, 0x00, 0x22, 0x7B, 0x07, 0x00, + 0x22, 0x7C, 0x09, 0x00, 0x22, 0x7D, 0x0B, 0x00, 0x22, 0x7E, 0x0D, 0x00, 0x22, 0x7F, 0x1F, 0x00, + 0x6F, 0x00, 0x00, 0x00 +}; + +vic_config_t __attribute__((aligned (0x100))) vic_cfg = {0}; + +u32 _vic_read_priv(u32 addr) +{ + u32 addr_lsb = addr & 0xFF; + + // Set address LSB. + if (addr_lsb) + VIC(PVIC_FALCON_ADDR) = addr_lsb >> 2; + + // Set address. + u32 val = VIC(PVIC_FALCON_PA_OFFSET + (addr >> 6)); + + // Unset address LSB. + if (addr_lsb) + VIC(PVIC_FALCON_ADDR) = 0; + + return val; +} + +static void _vic_write_priv(u32 addr, u32 data) +{ + u32 addr_lsb = addr & 0xFF; + + // Set address LSB. + if (addr_lsb) + VIC(PVIC_FALCON_ADDR) = addr_lsb >> 2; + + // Set address. + VIC(PVIC_FALCON_PA_OFFSET + (addr >> 6)) = data; + + // Unset address LSB. + if (addr_lsb) + VIC(PVIC_FALCON_ADDR) = 0; +} + +static int _vic_wait_idle() +{ + u32 timeout_count = 15000; // 150ms. + + while (VIC(PVIC_FALCON_IDLESTATE)) + { + usleep(10); + + timeout_count--; + if (!timeout_count) + return -1; + }; + + return 0; +} + +void vic_set_surface(vic_surface_t *sfc) +{ + u32 flip_x = 0; + u32 flip_y = 0; + u32 swap_xy = 0; + u32 const_alpha = 0; + + u32 width = sfc->width; + u32 height = sfc->height; + u32 pix_fmt = sfc->pix_fmt; + u32 src_buf = sfc->src_buf; + u32 dst_buf = sfc->dst_buf; + + // Get format alpha type. + switch (sfc->pix_fmt) + { + case VIC_PIX_FORMAT_X8B8G8R8: + case VIC_PIX_FORMAT_X8R8G8B8: + case VIC_PIX_FORMAT_B8G8R8X8: + case VIC_PIX_FORMAT_R8G8B8X8: + const_alpha = 1; + break; + + case VIC_PIX_FORMAT_A8B8G8R8: + case VIC_PIX_FORMAT_A8R8G8B8: + case VIC_PIX_FORMAT_B8G8R8A8: + case VIC_PIX_FORMAT_R8G8B8A8: + default: + break; + } + + // Get rotation parameters. + switch (sfc->rotation) + { + case VIC_ROTATION_90: + swap_xy = 1; + break; + + case VIC_ROTATION_180: + flip_x = 1; + flip_y = 1; + break; + + case VIC_ROTATION_270: + flip_x = 1; + swap_xy = 1; + break; + + case VIC_ROTATION_0: + default: + break; + } + + // Set output surface format. + vic_cfg.out_sfc_cfg.OutPixelFormat = pix_fmt; + vic_cfg.out_sfc_cfg.OutBlkKind = BLK_KIND_PITCH; + vic_cfg.out_sfc_cfg.OutBlkHeight = 0; + + // Set output rotation/flip. + vic_cfg.out_cfg.OutputFlipX = flip_x; + vic_cfg.out_cfg.OutputFlipY = flip_y; + vic_cfg.out_cfg.OutputTranspose = swap_xy; + + // Set output surface resolution. + vic_cfg.out_sfc_cfg.OutSurfaceWidth = width - 1; + vic_cfg.out_sfc_cfg.OutSurfaceHeight = height - 1; + vic_cfg.out_sfc_cfg.OutLumaWidth = width - 1; + vic_cfg.out_sfc_cfg.OutLumaHeight = height - 1; + + // Set output destination rectangle. Anything outside will not be touched at output buffer. + vic_cfg.out_cfg.TargetRectLeft = 0; + vic_cfg.out_cfg.TargetRectRight = width - 1; + vic_cfg.out_cfg.TargetRectTop = 0; + vic_cfg.out_cfg.TargetRectBottom = height - 1; + + // Initialize slot parameters. + vic_cfg.slots[0].slot_cfg.SlotEnable = 1; + vic_cfg.slots[0].slot_cfg.SoftClampLow = SOFT_CLAMP_MIN; + vic_cfg.slots[0].slot_cfg.SoftClampHigh = SOFT_CLAMP_MAX; + vic_cfg.slots[0].slot_cfg.PlanarAlpha = ALPHA_1_0; + vic_cfg.slots[0].slot_cfg.ConstantAlpha = const_alpha; + vic_cfg.slots[0].slot_cfg.FrameFormat = FORMAT_PROGRESSIVE; + + // Set input source rectangle. + vic_cfg.slots[0].slot_cfg.SourceRectLeft = 0; + vic_cfg.slots[0].slot_cfg.SourceRectRight = (width - 1) << 16; + vic_cfg.slots[0].slot_cfg.SourceRectTop = 0; + vic_cfg.slots[0].slot_cfg.SourceRectBottom = (height - 1) << 16; + + // Set input destination rectangle. + vic_cfg.slots[0].slot_cfg.DestRectLeft = 0; + vic_cfg.slots[0].slot_cfg.DestRectRight = (width - 1); + vic_cfg.slots[0].slot_cfg.DestRectTop = 0; + vic_cfg.slots[0].slot_cfg.DestRectBottom = (height - 1); + + // Set input surface format. + vic_cfg.slots[0].slot_sfc_cfg.SlotPixelFormat = pix_fmt; + vic_cfg.slots[0].slot_sfc_cfg.SlotBlkKind = BLK_KIND_PITCH; + vic_cfg.slots[0].slot_sfc_cfg.SlotBlkHeight = 0; + vic_cfg.slots[0].slot_sfc_cfg.SlotCacheWidth = CACHE_WIDTH_64BX4; + + // Set input surface resolution. + vic_cfg.slots[0].slot_sfc_cfg.SlotSurfaceWidth = width - 1; + vic_cfg.slots[0].slot_sfc_cfg.SlotSurfaceHeight = height - 1; + vic_cfg.slots[0].slot_sfc_cfg.SlotLumaWidth = width - 1; + vic_cfg.slots[0].slot_sfc_cfg.SlotLumaHeight = height - 1; + + // Flush data. + bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLEAN_WAY, false); + + // Set parameters base and size. Causes a parse by surface cache. + _vic_write_priv(VIC_SC_PRAMBASE, (u32)&vic_cfg >> 8); + _vic_write_priv(VIC_SC_PRAMSIZE, sizeof(vic_config_t) >> 6); + + // Wait for surface cache to get ready. + _vic_wait_idle(); + + // Set slot mapping. + _vic_write_priv(VIC_FC_SLOT_MAP, 0xFFFFFFF0); + + // Set input surface buffer. + _vic_write_priv(VIC_SC_SFC0_BASE_LUMA(0), src_buf >> 8); + + // Set output surface buffer. + _vic_write_priv(VIC_BL_TARGET_BASADR, dst_buf >> 8); + + // Set blending config and push changes to surface cache. + _vic_write_priv(VIC_BL_CONFIG, SLOTMASK(0x1F) | PROCESS_CFG_STRUCT_TRIGGER | SUBPARTITION_MODE); + + // Wait for surface cache to get ready. + _vic_wait_idle(); +} + +int vic_compose() +{ + // Wait for surface cache to get ready. Otherwise VIC will hang. + int res = _vic_wait_idle(); + + // Start composition of a single frame. + _vic_write_priv(VIC_FC_COMPOSE, COMPOSE_START); + + return res; +} + +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++) + { + _vic_write_priv(VIC_FC_FCE_UCODE_ADDR, (i * sizeof(u32))); + _vic_write_priv(VIC_FC_FCE_UCODE_INST, *(u32 *)&vic_fce_ucode[i * sizeof(u32)]); + } + + // Start Fetch Control Engine. + _vic_write_priv(VIC_FC_FCE_CTRL, START_TRIGGER); + + return _vic_wait_idle(); +} + +void vic_end() +{ + clock_disable_vic(); +} diff --git a/bdk/display/vic.h b/bdk/display/vic.h new file mode 100644 index 0000000..0014926 --- /dev/null +++ b/bdk/display/vic.h @@ -0,0 +1,63 @@ +/* + * VIC driver for Tegra X1 + * + * Copyright (c) 2018-2019 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, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _VIC_H_ +#define _VIC_H_ + +#include + +#define VIC_THI_SLCG_OVERRIDE_LOW_A 0x8C + +typedef enum _vic_rotation_t +{ + VIC_ROTATION_0 = 0, + VIC_ROTATION_90 = 1, + VIC_ROTATION_180 = 2, + VIC_ROTATION_270 = 3, +} vic_rotation_t; + +typedef enum _vic_pix_format_t +{ + VIC_PIX_FORMAT_A8B8G8R8 = 31, // 32-bit ABGR. + VIC_PIX_FORMAT_A8R8G8B8 = 32, // 32-bit ARGB. + VIC_PIX_FORMAT_B8G8R8A8 = 33, // 32-bit BGRA. + VIC_PIX_FORMAT_R8G8B8A8 = 34, // 32-bit RGBA. + + VIC_PIX_FORMAT_X8B8G8R8 = 35, // 32-bit XBGR. + 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 +{ + u32 src_buf; + u32 dst_buf; + u32 width; + u32 height; + u32 pix_fmt; + u32 rotation; +} vic_surface_t; + +void vic_set_surface(vic_surface_t *sfc); +int vic_compose(); +int vic_init(); +void vic_end(); + +#endif diff --git a/bdk/exception_handlers.S b/bdk/exception_handlers.S index 97d1ec6..2f38bb3 100644 --- a/bdk/exception_handlers.S +++ b/bdk/exception_handlers.S @@ -97,6 +97,10 @@ _irq_setup: MSR CPSR, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */ LDR SP, =0x40040000 + /* Setup FIQ stack pointer */ + MSR CPSR, #(MODE_FIQ | IRQ | FIQ) /* FIQ mode, IRQ/FIQ disabled */ + LDR SP, =0x40040000 + /* Setup SYS stack pointer */ MSR CPSR, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */ LDR SP, =0x4003FF00 /* Will be changed later to DRAM */ @@ -111,7 +115,9 @@ _irq_setup: B ipl_main B . -_reset: +.globl excp_reset +.type excp_reset, %function +excp_reset: LDR R0, =EXCP_EN_ADDR LDR R1, =0x30505645 /* EVP0 */ STR R1, [R0] /* EVP0 in EXCP_EN_ADDR */ @@ -129,25 +135,25 @@ _reset_handler: LDR R0, =EXCP_TYPE_ADDR LDR R1, =0x545352 /* RST */ STR R1, [R0] /* RST in EXCP_TYPE_ADDR */ - B _reset + B excp_reset _undefined_handler: LDR R0, =EXCP_TYPE_ADDR LDR R1, =0x464455 /* UDF */ STR R1, [R0] /* UDF in EXCP_TYPE_ADDR */ - B _reset + B excp_reset _prefetch_abort_handler: LDR R0, =EXCP_TYPE_ADDR LDR R1, =0x54424150 /* PABT */ STR R1, [R0] /* PABT in EXCP_TYPE_ADDR */ - B _reset + B excp_reset _data_abort_handler: LDR R0, =EXCP_TYPE_ADDR LDR R1, =0x54424144 /* DABT */ STR R1, [R0] /* DABT in EXCP_TYPE_ADDR */ - B _reset + B excp_reset .globl irq_enable_cpu_irq_exceptions .type irq_enable_cpu_irq_exceptions, %function diff --git a/bdk/ianos/elfload/elf.h b/bdk/ianos/elfload/elf.h index 0dcfecc..2a7111e 100644 --- a/bdk/ianos/elfload/elf.h +++ b/bdk/ianos/elfload/elf.h @@ -445,7 +445,7 @@ typedef struct /* Dynamic structure */ typedef struct { - Elf32_Sword d_tag; /* controls meaning of d_val */ + Elf32_Word d_tag; /* controls meaning of d_val */ union { Elf32_Word d_val; /* Multiple meanings - see d_tag */ Elf32_Addr d_ptr; /* program virtual address */ diff --git a/bdk/ianos/ianos.c b/bdk/ianos/ianos.c index fdc3488..99a996d 100644 --- a/bdk/ianos/ianos.c +++ b/bdk/ianos/ianos.c @@ -74,19 +74,16 @@ uintptr_t ianos_loader(char *path, elfType_t type, void *moduleConfig) el_ctx ctx; uintptr_t epaddr = 0; - if (!sd_mount()) - goto elfLoadFinalOut; - // Read library. fileBuf = sd_file_read(path, NULL); if (!fileBuf) - goto elfLoadFinalOut; + goto out; ctx.pread = _ianos_read_cb; if (el_init(&ctx)) - goto elfLoadFinalOut; + goto out; // Set our relocated library's buffer. switch (type & 0xFFFF) @@ -100,15 +97,15 @@ uintptr_t ianos_loader(char *path, elfType_t type, void *moduleConfig) } if (!elfBuf) - goto elfLoadFinalOut; + goto out; // Load and relocate library. ctx.base_load_vaddr = ctx.base_load_paddr = (uintptr_t)elfBuf; if (el_load(&ctx, _ianos_alloc_cb)) - goto elfFreeOut; + goto out_free; if (el_relocate(&ctx)) - goto elfFreeOut; + goto out_free; // Launch. epaddr = ctx.ehdr.e_entry + (uintptr_t)elfBuf; @@ -116,11 +113,11 @@ uintptr_t ianos_loader(char *path, elfType_t type, void *moduleConfig) _ianos_call_ep(ep, moduleConfig); -elfFreeOut: +out_free: free(fileBuf); elfBuf = NULL; fileBuf = NULL; -elfLoadFinalOut: +out: return epaddr; } \ No newline at end of file diff --git a/bdk/input/als.c b/bdk/input/als.c index be55426..54e4464 100644 --- a/bdk/input/als.c +++ b/bdk/input/als.c @@ -73,7 +73,7 @@ void set_als_cfg(als_ctxt_t *als_ctxt, u8 gain, u8 cycle) else if (cycle > 255) cycle = 255; - i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_GAIN_REG), gain); + i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_GAIN_REG), gain); i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_TIMING_REG), (256 - cycle)); als_ctxt->gain = gain; @@ -83,25 +83,25 @@ void set_als_cfg(als_ctxt_t *als_ctxt, u8 gain, u8 cycle) void get_als_lux(als_ctxt_t *als_ctxt) { u32 data[2]; - u32 visible_light; + u32 vi_light; u32 ir_light; u64 lux = 0; u32 itime_us = BH1730_ITIME_CYCLE_TO_US * als_ctxt->cycle; // Get visible and ir light raw data. Mode is continuous so waiting for new values doesn't matter. data[0] = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA0LOW_REG)) + - (i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA0HIGH_REG)) << 8); + (i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA0HIGH_REG)) << 8); data[1] = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA1LOW_REG)) + - (i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA1HIGH_REG)) << 8); + (i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_DATA1HIGH_REG)) << 8); - visible_light = data[0]; + vi_light = data[0]; ir_light = data[1]; - als_ctxt->over_limit = visible_light > 65534 || ir_light > 65534; - als_ctxt->vi_light = visible_light; + als_ctxt->vi_light = vi_light; als_ctxt->ir_light = ir_light; + als_ctxt->over_limit = vi_light > 65534 || ir_light > 65534; - if (!visible_light) + if (!vi_light) { als_ctxt->lux = 0; @@ -116,7 +116,7 @@ void get_als_lux(als_ctxt_t *als_ctxt) // Apply optical window calibration coefficients. for (u32 i = 0; i < opt_win_cal_count; i++) { - if (1000 * ir_light / visible_light < opt_win_cal[i].rc) + if (1000 * ir_light / vi_light < opt_win_cal[i].rc) { lux = ((u64)opt_win_cal[i].cv * data[0]) - (opt_win_cal[i].ci * data[1]); break; diff --git a/bdk/input/joycon.c b/bdk/input/joycon.c index 825e347..a33a6ad 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-2021 CTCaer + * Copyright (c) 2019-2023 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,9 +27,9 @@ #include #include #include +#include #include #include -#include // For disabling driver when logging is enabled. #include @@ -42,8 +42,13 @@ #define JC_HORI_INPUT_RPT_CMD 0x9A #define JC_HORI_INPUT_RPT 0x00 -#define JC_WIRED_CMD_MAC 0x01 -#define JC_WIRED_CMD_10 0x10 +#define JC_WIRED_CMD_GET_INFO 0x01 +#define JC_WIRED_CMD_CHRG_CFG 0x02 +#define JC_WIRED_CMD_WAKE_REASON 0x07 +#define JC_WIRED_CMD_HID_CONN 0x10 +#define JC_WIRED_CMD_HID_DISC 0x11 +#define JC_WIRED_CMD_SET_HIDRATE 0x12 // Output report rate. +#define JC_WIRED_CMD_SET_BRATE 0x20 #define JC_HID_OUTPUT_RPT 0x01 #define JC_HID_RUMBLE_RPT 0x10 @@ -61,15 +66,38 @@ #define JC_HID_SUBCMD_RUMBLE_CTL 0x48 #define JC_HID_SUBCMD_SND_RUMBLE 0xFF +#define JC_SIO_OUTPUT_RPT 0x91 +#define JC_SIO_INPUT_RPT 0x92 +#define JC_SIO_CMD_ACK 0x80 + +#define JC_SIO_CMD_INIT 0x01 +#define JC_SIO_CMD_UNK02 0x02 +#define JC_SIO_CMD_VER_RPT 0x03 +#define JC_SIO_CMD_UNK20 0x20 // JC_WIRED_CMD_SET_BRATE +#define JC_SIO_CMD_UNK21 0x21 +#define JC_SIO_CMD_UNK22 0x22 +#define JC_SIO_CMD_UNK40 0x40 +#define JC_SIO_CMD_STATUS 0x41 +#define JC_SIO_CMD_IAP_VER 0x42 + + #define JC_BTN_MASK_L 0xFF2900 // 0xFFE900: with charge status. #define JC_BTN_MASK_R 0x0056FF -#define JC_ID_L 0x01 -#define JC_ID_R 0x02 -#define JC_ID_HORI 0x20 +#define JC_ID_L 0x01 // Joycon (L). Mask for Hori (L). +#define JC_ID_R 0x02 // Joycon (R). Mask for Hori (R). +#define JC_ID_HORI 0x20 // Mask for Hori. Actual ids: 0x21, 0x22. -#define JC_CRC8_INIT 0x00 -#define JC_CRC8_POLY 0x8D +#define JC_CRC8_POLY 0x8D + +enum +{ + JC_STATE_START = 0, + JC_STATE_HANDSHAKED = 1, + JC_STATE_BRATE_CHANGED = 2, + JC_STATE_BRATE_OK = 3, + JC_STATE_INIT_DONE = 4 +}; enum { @@ -80,7 +108,25 @@ enum JC_BATT_FULL = 8 }; -static const u8 init_jc[] = { +static const u8 sio_init[] = { + JC_SIO_OUTPUT_RPT, JC_SIO_CMD_INIT, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x95 +}; + +static const u8 sio_set_rpt_version[] = { + JC_SIO_OUTPUT_RPT, JC_SIO_CMD_VER_RPT, + // old fw: 0x00, 0x0D (0.13). New 3.4. + // force_update_en: 0x01 + 0x00, 0x00, 0x03, 0x04, 0x00, 0xDA +}; + +// Every 8ms. +static const u8 sio_pad_status[] = { + JC_SIO_OUTPUT_RPT, JC_SIO_CMD_STATUS, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0 +}; + +static const u8 init_wake[] = { 0xA1, 0xA2, 0xA3, 0xA4 }; @@ -91,21 +137,47 @@ static const u8 init_handshake[] = { }; static const u8 init_get_info[] = { - 0x19, 0x01, 0x03, 0x07, 0x00, // Uart header. - JC_WIRED_CMD, JC_WIRED_CMD_MAC, // Wired cmd and subcmd. - 0x00, 0x00, 0x00, 0x00, 0x24 // Wired subcmd data and crc. + 0x19, 0x01, 0x03, 0x07, 0x00, // Uart header. + JC_WIRED_CMD, JC_WIRED_CMD_GET_INFO, // Wired cmd and subcmd. + 0x00, 0x00, 0x00, 0x00, 0x24 // Wired subcmd data and crc. }; -static const u8 init_finalize[] = { - 0x19, 0x01, 0x03, 0x07, 0x00, // Uart header. - JC_WIRED_CMD, JC_WIRED_CMD_10, // Wired cmd and subcmd. - 0x00, 0x00, 0x00, 0x00, 0x3D // Wired subcmd data and crc. +static const u8 init_switch_brate[] = { + 0x19, 0x01, 0x03, 0x0F, 0x00, // Uart header. + JC_WIRED_CMD, JC_WIRED_CMD_SET_BRATE, // Wired cmd and subcmd. + 0x08, 0x00, 0x00, 0xBD, 0xB1, // Wired subcmd data, data crc and crc. + // Baudrate 3 megabaud. + 0xC0, 0xC6, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const u8 init_hid_disconnect[] = { + 0x19, 0x01, 0x03, 0x07, 0x00, // Uart header. + JC_WIRED_CMD, JC_WIRED_CMD_HID_DISC, // Wired cmd and subcmd. + 0x00, 0x00, 0x00, 0x00, 0x0E // Wired subcmd data and crc. +}; + +static const u8 init_set_hid_rate[] = { + 0x19, 0x01, 0x03, 0x0B, 0x00, // Uart header. + JC_WIRED_CMD, JC_WIRED_CMD_SET_HIDRATE, // Wired cmd and subcmd. + 0x04, 0x00, 0x00, 0x12, 0xA6, // Wired subcmd data, data crc and crc. + // Output report rate 15 ms. + 0x0F, 0x00, 0x00, 0x00 + + // 5 ms. + // 0x04, 0x00, 0x00, 0x0E, 0xD5, + // 0x05, 0x00, 0x00, 0x00 +}; + +static const u8 init_hid_connect[] = { + 0x19, 0x01, 0x03, 0x07, 0x00, // Uart header. + JC_WIRED_CMD, JC_WIRED_CMD_HID_CONN, // Wired cmd and subcmd. + 0x00, 0x00, 0x00, 0x00, 0x3D // Wired subcmd data and crc. }; static const u8 nx_pad_status[] = { 0x19, 0x01, 0x03, 0x08, 0x00, // Uart header. JC_WIRED_HID, 0x00, // Wired cmd and hid cmd. - 0x01, 0x00, 0x00, 0x69, 0x2D, 0x1F // hid data and crc. + 0x01, 0x00, 0x00, 0x69, 0x2D, 0x1F // hid data, data crc and crc. }; static const u8 hori_pad_status[] = { @@ -160,7 +232,7 @@ typedef struct _jc_hid_in_rpt_t u8 stick_h_right; u8 stick_m_right; u8 stick_v_right; - u8 vib_decider; + u8 vib_decider; // right:8, left:8. (bit3 en, bit2-0 buffer avail). u8 submcd_ack; u8 subcmd; u8 subcmd_data[]; @@ -185,17 +257,71 @@ typedef struct _jc_hid_in_pair_data_t u8 pad1; } jc_hid_in_pair_data_t; +typedef struct _jc_sio_out_rpt_t +{ + u8 cmd; + u8 subcmd; + u16 payload_size; + u8 data[2]; + u8 crc_payload; + u8 crc_hdr; + u8 payload[]; +} jc_sio_out_rpt_t; + +typedef struct _jc_sio_in_rpt_t +{ + u8 cmd; + u8 ack; + u16 payload_size; + u8 status; + u8 unk; + u8 crc_payload; + u8 crc_hdr; + u8 payload[]; +} jc_sio_in_rpt_t; + +typedef struct _jc_hid_in_sixaxis_rpt_t +{ + s16 acc_x; + s16 acc_y; + s16 acc_z; + s16 gyr_x; + s16 gyr_y; + s16 gyr_z; +} __attribute__((packed)) jc_hid_in_sixaxis_rpt_t; + +typedef struct _jc_sio_hid_in_rpt_t +{ + u8 type; + u8 pkt_id; + u8 unk; + u8 btn_right; + u8 btn_shared; + u8 btn_left; + u8 stick_h_left; + u8 stick_m_left; + u8 stick_v_left; + u8 stick_h_right; + u8 stick_m_right; + u8 stick_v_right; + u8 siaxis_rpt_num; // Max 15. + // Each report is 800 us? + jc_hid_in_sixaxis_rpt_t sixaxis[15]; +} jc_sio_hid_in_rpt_t; + typedef struct _joycon_ctxt_t { - u8 buf[0x100]; //FIXME: If heap is used, dumping breaks. - u8 uart; - u8 type; - u8 mac[6]; - u32 hw_init_done; + u8 buf[0x100]; //FIXME: If heap is used, dumping breaks. + u8 uart; + u8 type; + u8 state; + u8 mac[6]; u32 last_received_time; u32 last_status_req_time; - u8 rumble_sent; - u8 connected; + u8 rumble_sent; + u8 connected; + u8 detected; + u8 sio_mode; } joycon_ctxt_t; static joycon_ctxt_t jc_l = {0}; @@ -206,15 +332,14 @@ static u32 hid_pkt_inc = 0; static jc_gamepad_rpt_t jc_gamepad; -void jc_power_supply(u8 uart, bool enable); - -static u8 jc_crc(u8 *data, u16 len) +static u8 _jc_crc(u8 *data, u16 len, u8 init) { - u8 crc = JC_CRC8_INIT; - u16 i, j; - for (i = 0; i < len; i++) { + u8 crc = init; + for (u16 i = 0; i < len; i++) + { crc ^= data[i]; - for (j = 0; j < 8; j++) { + for (u16 j = 0; j < 8; j++) + { if ((crc & 0x80) != 0) crc = (u8)((crc << 1) ^ JC_CRC8_POLY); else @@ -224,13 +349,136 @@ static u8 jc_crc(u8 *data, u16 len) return crc; } -void joycon_send_raw(u8 uart_port, const u8 *buf, u16 size) +static void _jc_power_supply(u8 uart, bool enable) { - uart_send(uart_port, buf, size); - uart_wait_idle(uart_port, UART_TX_IDLE); + if (enable) + { + if (regulator_5v_get_dev_enabled(1 << uart)) + return; + + regulator_5v_enable(1 << uart); + + if (jc_gamepad.sio_mode) + return; + + if (jc_init_done) + { + if (uart == UART_C) + gpio_write(GPIO_PORT_CC, GPIO_PIN_3, GPIO_HIGH); + else + gpio_write(GPIO_PORT_K, GPIO_PIN_3, GPIO_HIGH); + return; + } + + if (uart == UART_C) + { + // Joy-Con(L) Charge Enable. + PINMUX_AUX(PINMUX_AUX_SPDIF_IN) = PINMUX_PULL_DOWN | 1; + gpio_direction_output(GPIO_PORT_CC, GPIO_PIN_3, GPIO_HIGH); + } + else + { + // Joy-Con(R) Charge Enable. + PINMUX_AUX(PINMUX_AUX_GPIO_PK3) = PINMUX_DRIVE_4X | PINMUX_PULL_DOWN | 2; + gpio_direction_output(GPIO_PORT_K, GPIO_PIN_3, GPIO_HIGH); + } + } + else + { + if (!regulator_5v_get_dev_enabled(1 << uart)) + return; + + regulator_5v_disable(1 << uart); + + if (jc_gamepad.sio_mode) + return; + + if (uart == UART_C) + gpio_write(GPIO_PORT_CC, GPIO_PIN_3, GPIO_LOW); + else + gpio_write(GPIO_PORT_K, GPIO_PIN_3, GPIO_LOW); + } } -static u16 jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, u16 size, bool crc) +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; + gpio_direction_input(GPIO_PORT_G, GPIO_PIN_0); + gpio_direction_input(GPIO_PORT_D, GPIO_PIN_1); + usleep(20); + + // 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); + + // Turn off Joy-Con detect. (UARTB/C TX). + PINMUX_AUX(PINMUX_AUX_UART2_TX) = 0; + PINMUX_AUX(PINMUX_AUX_UART3_TX) = 0; + gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO); + gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO); + usleep(20); + } + else + { + //! TODO: Is there a way to detect a broken Sio? + jc_l.detected = true; + } +} + +static void _jc_conn_check() +{ + _jc_detect(); + + if (jc_gamepad.sio_mode) + return; + + // Check if a Joy-Con was disconnected. + if (!jc_l.detected) + { + if (jc_l.connected) + _jc_power_supply(UART_C, false); + + hid_pkt_inc = 0; + + jc_l.connected = false; + jc_l.rumble_sent = false; + + jc_gamepad.conn_l = false; + + jc_gamepad.batt_info_l = 0; + jc_gamepad.bt_conn_l.type = 0; + jc_gamepad.buttons &= ~JC_BTN_MASK_L; + } + + if (!jc_r.detected) + { + if (jc_r.connected) + _jc_power_supply(UART_B, false); + + hid_pkt_inc = 0; + + jc_r.connected = false; + jc_r.rumble_sent = false; + + jc_gamepad.conn_r = false; + + jc_gamepad.batt_info_r = 0; + jc_gamepad.bt_conn_r.type = 0; + jc_gamepad.buttons &= ~JC_BTN_MASK_R; + } +} + +static void _joycon_send_raw(u8 uart_port, const u8 *buf, u16 size) +{ + uart_send(uart_port, buf, 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) { out->uart_hdr.magic[0] = 0x19; out->uart_hdr.magic[1] = 0x01; @@ -243,14 +491,16 @@ static u16 jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, u if (data) memcpy(out->data, data, size); - out->crc = crc ? jc_crc(&out->uart_hdr.total_size_msb, sizeof(out->uart_hdr.total_size_msb) + sizeof(out->cmd) + sizeof(out->data)) : 0; + out->crc = crc ? _jc_crc(&out->uart_hdr.total_size_msb, + sizeof(out->uart_hdr.total_size_msb) + + sizeof(out->cmd) + sizeof(out->data), 0) : 0; 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, u8 *payload, u16 size, bool crc) { - u16 pkt_size = jc_packet_add_uart_hdr(rpt, JC_WIRED_HID, NULL, 0, crc); + u16 pkt_size = _jc_packet_add_uart_hdr(rpt, JC_WIRED_HID, NULL, 0, crc); pkt_size += size; rpt->uart_hdr.total_size_lsb += size; @@ -263,34 +513,29 @@ static u16 jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, u8 *payload, u16 size, b return pkt_size; } -void jc_send_hid_output_rpt(u8 uart, u8 *payload, u16 size, bool crc) +static void _jc_send_hid_output_rpt(u8 uart, u8 *payload, 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); + u32 rpt_size = _jc_hid_output_rpt_craft((jc_wired_hdr_t *)rpt, payload, size, crc); - joycon_send_raw(uart, rpt, rpt_size); + _joycon_send_raw(uart, rpt, rpt_size); } -static u8 jc_hid_pkt_id_incr() +static u8 _jc_hid_pkt_id_incr() { - u8 curr_id = hid_pkt_inc; - hid_pkt_inc++; - - return (curr_id & 0xF); + return (hid_pkt_inc++ & 0xF); } -void jc_send_hid_cmd(u8 uart, u8 subcmd, u8 *data, u16 size) +static void _jc_send_hid_cmd(u8 uart, u8 subcmd, u8 *data, u16 size) { - u8 temp[0x30]; - u8 rumble_neutral[8] = {0x00, 0x01, 0x40, 0x40, 0x00, 0x01, 0x40, 0x40}; - u8 rumble_init[8] = {0xc2, 0xc8, 0x03, 0x72, 0xc2, 0xc8, 0x03, 0x72}; + 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 }; - memset(temp, 0, sizeof(temp)); + u8 temp[0x30] = {0}; jc_hid_out_rpt_t *hid_pkt = (jc_hid_out_rpt_t *)temp; - memcpy(hid_pkt->rumble, rumble_neutral, sizeof(rumble_neutral)); if (subcmd == JC_HID_SUBCMD_SND_RUMBLE) @@ -299,63 +544,63 @@ void jc_send_hid_cmd(u8 uart, u8 subcmd, u8 *data, u16 size) bool send_l_rumble = jc_l.connected && !jc_l.rumble_sent; // Enable rumble. - hid_pkt->cmd = JC_HID_OUTPUT_RPT; - hid_pkt->pkt_id = jc_hid_pkt_id_incr(); + 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(UART_B, (u8 *)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(UART_C, (u8 *)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; + hid_pkt->pkt_id = _jc_hid_pkt_id_incr(); 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(UART_B, (u8 *)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(UART_C, (u8 *)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->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(UART_B, (u8 *)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(UART_C, (u8 *)hid_pkt, 0x10, false); } else { bool crc_needed = (jc_l.uart == uart) ? (jc_l.type & JC_ID_HORI) : (jc_r.type & JC_ID_HORI); - hid_pkt->cmd = JC_HID_OUTPUT_RPT; - hid_pkt->pkt_id = jc_hid_pkt_id_incr(); + 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(uart, (u8 *)hid_pkt, sizeof(jc_hid_out_rpt_t) + size, crc_needed); } } -static void jc_charging_decider(u8 batt, u8 uart) +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. - jc_power_supply(uart, true); + _jc_power_supply(uart, true); else if (batt > (system_batt_enough ? JC_BATT_FULL : JC_BATT_MID)) // Addresses the charging bit. - jc_power_supply(uart, false); + _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, u32 size) { u32 btn_tmp; jc_hid_in_rpt_t *hid_pkt = (jc_hid_in_rpt_t *)packet; @@ -390,7 +635,8 @@ static void jc_parse_wired_hid(joycon_ctxt_t *jc, const u8* packet, u32 size) jc_gamepad.conn_l = jc_l.connected; jc_gamepad.conn_r = jc_r.connected; - jc_charging_decider(hid_pkt->batt_info, jc->uart); + if (hid_pkt->cmd == JC_HID_INPUT_RPT) + _jc_charging_decider(hid_pkt->batt_info, jc->uart); break; case JC_HID_SUBMCD_RPT: if (hid_pkt->subcmd == JC_HID_SUBCMD_SPI_READ) @@ -402,10 +648,10 @@ static void jc_parse_wired_hid(joycon_ctxt_t *jc, const u8* packet, u32 size) else bt_conn = &jc_gamepad.bt_conn_r; - jc_hid_in_spi_read_t *spi_info = (jc_hid_in_spi_read_t *)hid_pkt->subcmd_data; + jc_hid_in_spi_read_t *spi_info = (jc_hid_in_spi_read_t *)hid_pkt->subcmd_data; jc_hid_in_pair_data_t *pair_data = (jc_hid_in_pair_data_t *)spi_info->data; - // Check if we reply is pairing info. + // Check if the reply is pairing info. if (spi_info->size == 0x1A && pair_data->magic == 0x95 && pair_data->size == 0x22) { bt_conn->type = jc->type; @@ -420,120 +666,179 @@ static void jc_parse_wired_hid(joycon_ctxt_t *jc, const u8* packet, u32 size) default: break; } - jc->last_received_time = get_tmr_ms(); } -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, u32 size) { switch (data[0]) { - case JC_WIRED_CMD_MAC: + case JC_WIRED_CMD_GET_INFO: for (int i = 12; i > 6; i--) jc->mac[12 - i] = data[i]; jc->type = data[6]; jc->connected = true; + break; + case JC_WIRED_CMD_SET_BRATE: + jc->state = JC_STATE_BRATE_CHANGED; + break; + case JC_WIRED_CMD_HID_DISC: + jc->state = JC_STATE_BRATE_OK; + break; + case JC_WIRED_CMD_HID_CONN: + case JC_WIRED_CMD_SET_HIDRATE: + // done. default: break; } } -static void jc_uart_pkt_parse(joycon_ctxt_t *jc, const u8* packet, size_t size) +static void _jc_uart_pkt_parse(joycon_ctxt_t *jc, const jc_wired_hdr_t *pkt, size_t size) { - jc_wired_hdr_t *pkt = (jc_wired_hdr_t *)packet; 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, (pkt->data[0] << 8) | pkt->data[1]); break; case JC_WIRED_INIT_REPLY: - jc_parse_wired_init(jc, pkt->data, size - sizeof(jc_uart_hdr_t) - 1); + _jc_parse_wired_init(jc, pkt->data, size - sizeof(jc_uart_hdr_t) - 1); + break; + case JC_INIT_HANDSHAKE: + jc->state = JC_STATE_HANDSHAKED; + break; + default: + break; + } + + jc->last_received_time = get_tmr_ms(); +} + +static void _jc_sio_parse_payload(joycon_ctxt_t *jc, u8 cmd, const u8* payload, u32 size) +{ + switch (cmd) + { + case JC_SIO_CMD_STATUS: + 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); + + jc_gamepad.lstick_x = hid_pkt->stick_h_left | ((hid_pkt->stick_m_left & 0xF) << 8); + jc_gamepad.lstick_y = (hid_pkt->stick_m_left >> 4) | (hid_pkt->stick_v_left << 4); + jc_gamepad.rstick_x = hid_pkt->stick_h_right | ((hid_pkt->stick_m_right & 0xF) << 8); + jc_gamepad.rstick_y = (hid_pkt->stick_m_right >> 4) | (hid_pkt->stick_v_right << 4); + + jc_gamepad.batt_info_l = jc_l.connected; + jc_gamepad.batt_info_r = gpio_read(GPIO_PORT_E, GPIO_PIN_7); // Set IRQ status. + + jc_gamepad.conn_l = jc_l.connected; + jc_gamepad.conn_r = jc_l.connected; break; default: break; } } -static void jc_rcv_pkt(joycon_ctxt_t *jc) +static void _jc_sio_uart_pkt_parse(joycon_ctxt_t *jc, const jc_sio_in_rpt_t *pkt, u32 size) { - if (gpio_read(GPIO_PORT_E, GPIO_PIN_6) && jc->uart == UART_C) - return; - else if (gpio_read(GPIO_PORT_H, GPIO_PIN_6) && jc->uart == UART_B) + if (pkt->crc_hdr != _jc_crc((u8 *)pkt, sizeof(jc_sio_in_rpt_t) - 1, 0)) return; - // Check if device stopped sending data. - u32 uart_irq = uart_get_IIR(jc->uart); - if (uart_irq != UART_IIR_REDI) + u8 cmd = pkt->ack & (~JC_SIO_CMD_ACK); + switch (cmd) + { + case JC_SIO_CMD_INIT: + jc->connected = pkt->status == 0; + break; + case JC_SIO_CMD_VER_RPT: + if (jc->connected) + jc->connected = pkt->status == 0; + break; + case JC_SIO_CMD_IAP_VER: + case JC_SIO_CMD_STATUS: + _jc_sio_parse_payload(jc, cmd, pkt->payload, pkt->payload_size); + break; + case JC_SIO_CMD_UNK02: + case JC_SIO_CMD_UNK20: + case JC_SIO_CMD_UNK21: + case JC_SIO_CMD_UNK22: + case JC_SIO_CMD_UNK40: + default: + break; + } + + jc->last_received_time = get_tmr_ms(); +} + +static void _jc_rcv_pkt(joycon_ctxt_t *jc) +{ + if (!jc->detected) return; u32 len = uart_recv(jc->uart, (u8 *)jc->buf, 0x100); + if (len < 8) + return; - // Check valid size and uart reply magic. - if (len > 7 && !memcmp(jc->buf, "\x19\x81\x03", 3)) + // For Joycon, check uart reply magic. + 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_wired_hdr_t *pkt = (jc_wired_hdr_t *)(jc->buf); + _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->buf, pkt->uart_hdr.total_size_lsb + sizeof(jc_uart_hdr_t)); + return; + } + + // For Sio, check uart output report and command ack. + 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)); + + return; } } -static bool jc_send_init_rumble(joycon_ctxt_t *jc) +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)) { - gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO); - gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO); - - jc_send_hid_cmd(jc->uart, JC_HID_SUBCMD_SND_RUMBLE, NULL, 0); + _jc_send_hid_cmd(jc->uart, JC_HID_SUBCMD_SND_RUMBLE, NULL, 0); if (jc_l.connected) jc_l.rumble_sent = true; if (jc_r.connected) jc_r.rumble_sent = true; - if (jc->uart != UART_B) - gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO); - else - gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_GPIO); - return 1; } return 0; } -static void jc_req_nx_pad_status(joycon_ctxt_t *jc) +static void _jc_req_nx_pad_status(joycon_ctxt_t *jc) { - bool is_nxpad = !(jc->type & JC_ID_HORI); + if (!jc->detected) + return; + + bool is_nxpad = !(jc->type & JC_ID_HORI) && !jc->sio_mode; + + if (jc->last_status_req_time > get_tmr_ms() || !jc->connected) + return; if (is_nxpad) { - bool sent_rumble = jc_send_init_rumble(jc); + bool sent_rumble = _jc_send_init_rumble(jc); if (sent_rumble) return; } - if (jc->last_status_req_time > get_tmr_ms() || !jc->connected) - return; - - // Turn off Joy-Con detect. - if (jc->uart == UART_B) - gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO); - else - gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO); - if (is_nxpad) - joycon_send_raw(jc->uart, nx_pad_status, sizeof(nx_pad_status)); + _joycon_send_raw(jc->uart, nx_pad_status, sizeof(nx_pad_status)); + else if (jc->sio_mode) + _joycon_send_raw(jc->uart, sio_pad_status, sizeof(sio_pad_status)); else - joycon_send_raw(jc->uart, hori_pad_status, sizeof(hori_pad_status)); - - // Turn Joy-Con detect on. - if (jc->uart == UART_B) - gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO); - else - gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_GPIO); + _joycon_send_raw(jc->uart, hori_pad_status, sizeof(hori_pad_status)); jc->last_status_req_time = get_tmr_ms() + 15; } @@ -563,21 +868,23 @@ jc_gamepad_rpt_t *jc_get_bt_pairing_info(bool *is_l_hos, bool *is_r_hos) u8 retries; jc_bt_conn_t *bt_conn; - if (!jc_init_done) + if (!jc_init_done || jc_gamepad.sio_mode) return NULL; bt_conn = &jc_gamepad.bt_conn_l; memset(bt_conn->host_mac, 0, 6); - memset(bt_conn->ltk, 0, 16); + memset(bt_conn->ltk, 0, 16); bt_conn = &jc_gamepad.bt_conn_r; memset(bt_conn->host_mac, 0, 6); - memset(bt_conn->ltk, 0, 16); + memset(bt_conn->ltk, 0, 16); + + _jc_conn_check(); while (jc_l.last_status_req_time > get_tmr_ms()) { - jc_rcv_pkt(&jc_r); - jc_rcv_pkt(&jc_l); + _jc_rcv_pkt(&jc_r); + _jc_rcv_pkt(&jc_l); } jc_hid_in_spi_read_t subcmd_data_l; @@ -588,13 +895,13 @@ jc_gamepad_rpt_t *jc_get_bt_pairing_info(bool *is_l_hos, bool *is_r_hos) subcmd_data_r.addr = 0x2000; subcmd_data_r.size = 0x1A; - // Turn off Joy-Con detect. - gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO); - gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO); - bool jc_r_found = jc_r.connected ? false : true; bool jc_l_found = jc_l.connected ? false : true; + // Set mode to HW controlled RTS. + uart_set_mode(jc_l.uart, UART_AO_TX_HW_RX); + uart_set_mode(jc_r.uart, UART_AO_TX_HW_RX); + u32 total_retries = 10; retry: retries = 10; @@ -605,23 +912,26 @@ 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.uart, 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.uart, JC_HID_SUBCMD_SPI_READ, (u8 *)&subcmd_data_r, 5); jc_r.last_status_req_time = get_tmr_ms() + 15; } retries--; } + // Wait for the first 36 bytes to arrive. + msleep(5); + if (!jc_l_found) { memset(jc_l.buf, 0, 0x100); - jc_rcv_pkt(&jc_l); + _jc_rcv_pkt(&jc_l); bool is_hos = false; if (_jc_validate_pairing_info(&jc_l.buf[SPI_READ_OFFSET], &is_hos)) @@ -641,7 +951,7 @@ retry: if (!jc_r_found) { memset(jc_r.buf, 0, 0x100); - jc_rcv_pkt(&jc_r); + _jc_rcv_pkt(&jc_r); bool is_hos = false; if (_jc_validate_pairing_info(&jc_r.buf[SPI_READ_OFFSET], &is_hos)) @@ -674,189 +984,156 @@ retry: { bt_conn = &jc_gamepad.bt_conn_l; memset(bt_conn->host_mac, 0, 6); - memset(bt_conn->ltk, 0, 16); + memset(bt_conn->ltk, 0, 16); } if (!jc_r_found) { bt_conn = &jc_gamepad.bt_conn_r; memset(bt_conn->host_mac, 0, 6); - memset(bt_conn->ltk, 0, 16); + memset(bt_conn->ltk, 0, 16); } } - // Turn Joy-Con detect on. - gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO); - gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_GPIO); + // Restore mode to manual RTS. + uart_set_mode(jc_l.uart, UART_AO_TX_MN_RX); + uart_set_mode(jc_r.uart, UART_AO_TX_MN_RX); return &jc_gamepad; } -void jc_deinit() +static void _jc_init_conn(joycon_ctxt_t *jc) { - // Disable power. - jc_power_supply(UART_B, false); - jc_power_supply(UART_C, false); + if (!jc->detected) + return; - // Turn off Joy-Con detect. - gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO); - gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO); - - // Send sleep command. - 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_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_rcv_pkt(&jc_l); - } - - // Disable UART B and C clocks. - clock_disable_uart(UART_B); - clock_disable_uart(UART_C); -} - -static void jc_init_conn(joycon_ctxt_t *jc) -{ if (((u32)get_tmr_ms() - jc->last_received_time) > 1000) { - jc_power_supply(jc->uart, true); + _jc_power_supply(jc->uart, true); - // Turn off Joy-Con detect. + // Mask out buttons and set connected to false. if (jc->uart == UART_B) { jc_gamepad.buttons &= ~JC_BTN_MASK_R; jc_gamepad.conn_r = false; - gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO); } else { jc_gamepad.buttons &= ~JC_BTN_MASK_L; jc_gamepad.conn_l = false; - gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO); } - uart_init(jc->uart, 1000000); - uart_invert(jc->uart, true, UART_INVERT_TXD); - uart_set_IIR(jc->uart); + // Initialize uart to 1 megabaud and manual RTS. + uart_init(jc->uart, 1000000, UART_AO_TX_MN_RX); - joycon_send_raw(jc->uart, init_jc, 4); - joycon_send_raw(jc->uart, init_handshake, sizeof(init_handshake)); - - msleep(5); - jc_rcv_pkt(jc); - - joycon_send_raw(jc->uart, init_get_info, sizeof(init_get_info)); - msleep(5); - jc_rcv_pkt(jc); - - if (!(jc->type & JC_ID_HORI)) + if (!jc->sio_mode) { - joycon_send_raw(jc->uart, init_finalize, sizeof(init_finalize)); + jc->state = JC_STATE_START; + + // Set TX and RTS inversion for Joycon. + uart_invert(jc->uart, true, UART_INVERT_TXD | UART_INVERT_RTS); + + // Wake up the controller. + _joycon_send_raw(jc->uart, init_wake, sizeof(init_wake)); + _jc_rcv_pkt(jc); // Clear RX FIFO. + + // Do a handshake. + u32 retries = 10; + while (retries && jc->state != JC_STATE_HANDSHAKED) + { + _joycon_send_raw(jc->uart, init_handshake, sizeof(init_handshake)); + msleep(5); + _jc_rcv_pkt(jc); + retries--; + } + + if (jc->state != JC_STATE_HANDSHAKED) + goto out; + + // Get info about the controller. + _joycon_send_raw(jc->uart, init_get_info, sizeof(init_get_info)); + msleep(2); + _jc_rcv_pkt(jc); + + if (!(jc->type & JC_ID_HORI)) + { + // Request 3 megabaud change. + _joycon_send_raw(jc->uart, init_switch_brate, sizeof(init_switch_brate)); + msleep(2); + _jc_rcv_pkt(jc); + + if (jc->state == JC_STATE_BRATE_CHANGED) + { + // Reinitialize uart to 3 megabaud and manual RTS. + uart_init(jc->uart, 3000000, UART_AO_TX_MN_RX); + uart_invert(jc->uart, true, UART_INVERT_TXD | UART_INVERT_RTS); + + // Disconnect HID. + retries = 10; + while (retries && jc->state != JC_STATE_BRATE_OK) + { + _joycon_send_raw(jc->uart, init_hid_disconnect, sizeof(init_hid_disconnect)); + msleep(5); + _jc_rcv_pkt(jc); + retries--; + } + + if (jc->state != JC_STATE_BRATE_OK) + goto out; + } + + // Create HID connection with the new rate. + _joycon_send_raw(jc->uart, init_hid_connect, sizeof(init_hid_connect)); + msleep(2); + _jc_rcv_pkt(jc); + + // Set hid packet rate. + _joycon_send_raw(jc->uart, init_set_hid_rate, sizeof(init_set_hid_rate)); + msleep(2); + _jc_rcv_pkt(jc); + } + else // Hori. Unset RTS inversion. + uart_invert(jc->uart, false, UART_INVERT_RTS); + } + else + { + // Set Sio NPOR low to configure BOOT0 mode. + gpio_write(GPIO_PORT_CC, GPIO_PIN_5, GPIO_LOW); + usleep(300); + gpio_write(GPIO_PORT_T, GPIO_PIN_0, GPIO_LOW); + gpio_write(GPIO_PORT_CC, GPIO_PIN_5, GPIO_HIGH); + msleep(100); + + // Clear RX FIFO. + _jc_rcv_pkt(jc); + + // Initialize the controller. + u32 retries = 10; + while (!jc->connected) + { + _joycon_send_raw(jc->uart, sio_init, sizeof(sio_init)); + msleep(5); + _jc_rcv_pkt(jc); + retries--; + } + + if (!jc->connected) + goto out; + + // Set output report version. + _joycon_send_raw(jc->uart, sio_set_rpt_version, sizeof(sio_set_rpt_version)); msleep(5); - jc_rcv_pkt(jc); + _jc_rcv_pkt(jc); } - // Turn Joy-Con detect on. - if (jc->uart == UART_B) - gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO); - else - gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_GPIO); + // Initialization done. + jc->state = JC_STATE_INIT_DONE; +out: jc->last_received_time = get_tmr_ms(); - if (jc->connected) - jc_power_supply(jc->uart, false); - } -} - -static void jc_conn_check() -{ - // Check if a Joy-Con was disconnected. - if (gpio_read(GPIO_PORT_E, GPIO_PIN_6)) - { - jc_power_supply(UART_C, false); - - hid_pkt_inc = 0; - - jc_l.connected = false; - jc_l.rumble_sent = false; - - jc_gamepad.buttons &= ~JC_BTN_MASK_L; - jc_gamepad.conn_l = false; - - jc_gamepad.batt_info_l = 0; - jc_gamepad.bt_conn_l.type = 0; - } - - if (gpio_read(GPIO_PORT_H, GPIO_PIN_6)) - { - jc_power_supply(UART_B, false); - - hid_pkt_inc = 0; - - jc_r.connected = false; - jc_r.rumble_sent = false; - - jc_gamepad.buttons &= ~JC_BTN_MASK_R; - jc_gamepad.conn_r = false; - - jc_gamepad.batt_info_r = 0; - jc_gamepad.bt_conn_r.type = 0; - } -} - -void jc_power_supply(u8 uart, bool enable) -{ - if (enable) - { - if (regulator_5v_get_dev_enabled(1 << uart)) - return; - - regulator_5v_enable(1 << uart); - - if (jc_init_done) - { - if (uart == UART_C) - gpio_write(GPIO_PORT_CC, GPIO_PIN_3, GPIO_HIGH); - else - gpio_write(GPIO_PORT_K, GPIO_PIN_3, GPIO_HIGH); - return; - } - - if (uart == UART_C) - { - // Joy-Con(L) Charge Detect. - PINMUX_AUX(PINMUX_AUX_SPDIF_IN) = PINMUX_PULL_DOWN | 1; - gpio_config(GPIO_PORT_CC, GPIO_PIN_3, GPIO_MODE_GPIO); - gpio_output_enable(GPIO_PORT_CC, GPIO_PIN_3, GPIO_OUTPUT_ENABLE); - gpio_write(GPIO_PORT_CC, GPIO_PIN_3, GPIO_HIGH); - } - else - { - // Joy-Con(R) Charge Detect. - PINMUX_AUX(PINMUX_AUX_GPIO_PK3) = PINMUX_DRIVE_4X | PINMUX_PULL_DOWN | 2; - gpio_config(GPIO_PORT_K, GPIO_PIN_3, GPIO_MODE_GPIO); - gpio_output_enable(GPIO_PORT_K, GPIO_PIN_3, GPIO_OUTPUT_ENABLE); - gpio_write(GPIO_PORT_K, GPIO_PIN_3, GPIO_HIGH); - } - } - else - { - if (!regulator_5v_get_dev_enabled(1 << uart)) - return; - - regulator_5v_disable(1 << uart); - - if (uart == UART_C) - gpio_write(GPIO_PORT_CC, GPIO_PIN_3, GPIO_LOW); - else - gpio_write(GPIO_PORT_K, GPIO_PIN_3, GPIO_LOW); + if (!jc->sio_mode && jc->connected && !(jc->type & JC_ID_HORI)) + _jc_power_supply(jc->uart, false); } } @@ -865,64 +1142,127 @@ void jc_init_hw() jc_l.uart = UART_C; jc_r.uart = UART_B; + jc_l.sio_mode = fuse_read_hw_type() == FUSE_NX_HW_TYPE_HOAG; + jc_gamepad.sio_mode = jc_l.sio_mode; + #if !defined(DEBUG_UART_PORT) || !(DEBUG_UART_PORT) - if (fuse_read_hw_type() == FUSE_NX_HW_TYPE_HOAG) - return; + _jc_power_supply(UART_C, true); + _jc_power_supply(UART_B, true); - jc_power_supply(UART_C, true); - jc_power_supply(UART_B, true); + // Sio Initialization. + if (jc_gamepad.sio_mode) + { + // Enable 4 MHz clock to Sio. + clock_enable_extperiph2(); + PINMUX_AUX(PINMUX_AUX_TOUCH_CLK) = PINMUX_PULL_DOWN; - // Joy-Con (R) IsAttached. - PINMUX_AUX(PINMUX_AUX_GPIO_PH6) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE; - gpio_config(GPIO_PORT_H, GPIO_PIN_6, GPIO_MODE_GPIO); + // Configure Sio HOME BUTTON. + PINMUX_AUX(PINMUX_AUX_LCD_GPIO1) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE | PINMUX_PULL_UP | 1; + gpio_direction_input(GPIO_PORT_V, GPIO_PIN_3); - // Joy-Con (L) IsAttached. + // Configure Sio IRQ + PINMUX_AUX(PINMUX_AUX_GPIO_PE7) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE | PINMUX_PULL_UP; + gpio_direction_input(GPIO_PORT_E, GPIO_PIN_7); + + // Configure Sio NRST and BOOT0. + PINMUX_AUX(PINMUX_AUX_CAM1_STROBE) = PINMUX_PULL_DOWN | 1; + PINMUX_AUX(PINMUX_AUX_CAM2_PWDN) = PINMUX_PULL_DOWN | 1; + + // Set BOOT0 to flash mode. (output high is sram mode). + gpio_direction_output(GPIO_PORT_T, GPIO_PIN_0, GPIO_LOW); + + // NRST to pull down. + gpio_direction_input(GPIO_PORT_T, GPIO_PIN_1); + + // Configure Sio NPOR. + PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN1) = PINMUX_IO_HV | PINMUX_LPDR | 1; + gpio_direction_output(GPIO_PORT_CC, GPIO_PIN_5, GPIO_LOW); + } + +#if 0 // Already set by hw init. + // Set Joy-Con IsAttached pinmux. Shared with UARTB/UARTC TX. PINMUX_AUX(PINMUX_AUX_GPIO_PE6) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE; + PINMUX_AUX(PINMUX_AUX_GPIO_PH6) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE; + + // Set Joy-Con IsAttached mode. Shared with UARTB/UARTC TX. gpio_config(GPIO_PORT_E, GPIO_PIN_6, GPIO_MODE_GPIO); + gpio_config(GPIO_PORT_H, GPIO_PIN_6, GPIO_MODE_GPIO); +#endif // Configure pinmuxing for UART B and C. - pinmux_config_uart(UART_B); + if (!jc_gamepad.sio_mode) + 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. - clock_enable_uart(UART_B); + if (!jc_gamepad.sio_mode) + clock_enable_uart(UART_B); clock_enable_uart(UART_C); // Restore OC. bpmp_clk_rate_set(prev_fid); - // Turn Joy-Con detect on. - gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO); - gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_GPIO); - jc_init_done = true; #endif } +void jc_deinit() +{ + if (!jc_init_done) + return; + + // Disable power. + _jc_power_supply(UART_B, false); + _jc_power_supply(UART_C, false); + + if (!jc_gamepad.sio_mode) + { + // Send sleep command. + 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_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_rcv_pkt(&jc_l); + } + } + else + { + // Disable Sio NPOR. + gpio_write(GPIO_PORT_CC, GPIO_PIN_5, GPIO_LOW); + + // Disable 4 MHz clock to Sio. + clock_disable_extperiph2(); + } + + // Disable UART B and C clocks. + if (!jc_gamepad.sio_mode) + clock_disable_uart(UART_B); + clock_disable_uart(UART_C); +} + jc_gamepad_rpt_t *joycon_poll() { if (!jc_init_done) return NULL; - if (!gpio_read(GPIO_PORT_H, GPIO_PIN_6)) - jc_init_conn(&jc_r); - if (!gpio_read(GPIO_PORT_E, GPIO_PIN_6)) - jc_init_conn(&jc_l); + _jc_conn_check(); - if (!gpio_read(GPIO_PORT_H, GPIO_PIN_6)) - jc_req_nx_pad_status(&jc_r); - if (!gpio_read(GPIO_PORT_E, GPIO_PIN_6)) - jc_req_nx_pad_status(&jc_l); + _jc_init_conn(&jc_r); + _jc_init_conn(&jc_l); - if (!gpio_read(GPIO_PORT_H, GPIO_PIN_6)) - jc_rcv_pkt(&jc_r); - if (!gpio_read(GPIO_PORT_E, GPIO_PIN_6)) - jc_rcv_pkt(&jc_l); + _jc_req_nx_pad_status(&jc_r); + _jc_req_nx_pad_status(&jc_l); - jc_conn_check(); + _jc_rcv_pkt(&jc_r); + _jc_rcv_pkt(&jc_l); return &jc_gamepad; } diff --git a/bdk/input/joycon.h b/bdk/input/joycon.h index 932c836..af0a849 100644 --- a/bdk/input/joycon.h +++ b/bdk/input/joycon.h @@ -83,13 +83,23 @@ typedef struct _jc_gamepad_rpt_t bool center_stick_r; bool conn_l; bool conn_r; - u8 batt_info_l; - u8 batt_info_r; + bool sio_mode; + u8 batt_info_l; // Also Sio Connected status. + u8 batt_info_r; // Also Sio IRQ. jc_bt_conn_t bt_conn_l; jc_bt_conn_t bt_conn_r; } jc_gamepad_rpt_t; -void jc_power_supply(u8 uart, bool enable); +typedef struct _jc_calib_t +{ + u16 x_max:12; + u16 y_max:12; + u16 x_center:12; + u16 y_center:12; + u16 x_min:12; + u16 y_min:12; +} __attribute__((packed)) jc_calib_t; + void jc_init_hw(); void jc_deinit(); jc_gamepad_rpt_t *joycon_poll(); diff --git a/bdk/input/touch.c b/bdk/input/touch.c index af696d9..7a986f3 100644 --- a/bdk/input/touch.c +++ b/bdk/input/touch.c @@ -2,7 +2,7 @@ * Touch driver for Nintendo Switch's STM FingerTip S (4CD60D) touch controller * * Copyright (c) 2018 langerhans - * Copyright (c) 2018-2020 CTCaer + * Copyright (c) 2018-2023 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,9 +24,9 @@ #include #include #include +#include #include #include -#include #include "touch.h" @@ -35,12 +35,12 @@ static touch_panel_info_t _panels[] = { - { 0, 1, 1, 1, "NISSHA NFT-K12D" }, - { 1, 0, 1, 1, "GiS GGM6 B2X" }, - { 2, 0, 0, 0, "NISSHA NBF-K9A" }, - { 3, 1, 0, 0, "GiS 5.5\"" }, - { 4, 0, 0, 1, "Samsung BH2109" }, - { -1, 1, 0, 1, "GiS VA 6.2\"" } + { 0, 1, 1, 1, "NISSHA NFT-K12D" },// 0. + { 1, 0, 1, 1, "GiS GGM6 B2X" },// 1. + { 2, 0, 0, 0, "NISSHA NBF-K9A" },// 3. + { 3, 1, 0, 0, "GiS 5.5\"" },// 4. + { 4, 0, 0, 1, "Samsung BH2109" },// 5? + { -1, 1, 0, 1, "GiS VA 6.2\"" } // 2. }; static int touch_command(u8 cmd, u8 *buf, u8 size) @@ -87,19 +87,19 @@ static int touch_wait_event(u8 event, u8 status, u32 timeout, u8 *buf) static void _touch_compensate_limits(touch_event *event, bool touching) { - event->x = MAX(event->x, EDGE_OFFSET); - event->x = MIN(event->x, X_REAL_MAX); + event->x = MAX(event->x, EDGE_OFFSET); + event->x = MIN(event->x, X_REAL_MAX); event->x -= EDGE_OFFSET; u32 x_adj = (1280 * 1000) / (X_REAL_MAX - EDGE_OFFSET); - event->x = ((u32)event->x * x_adj) / 1000; + event->x = ((u32)event->x * x_adj) / 1000; if (touching) { - event->y = MAX(event->y, EDGE_OFFSET); - event->y = MIN(event->y, Y_REAL_MAX); + event->y = MAX(event->y, EDGE_OFFSET); + event->y = MIN(event->y, Y_REAL_MAX); event->y -= EDGE_OFFSET; u32 y_adj = (720 * 1000) / (Y_REAL_MAX - EDGE_OFFSET); - event->y = ((u32)event->y * y_adj) / 1000; + event->y = ((u32)event->y * y_adj) / 1000; } } @@ -115,6 +115,7 @@ static void _touch_process_contact_event(touch_event *event, bool touching) event->z = event->raw[5] | (event->raw[6] << 8); event->z = event->z << 6; + u16 tmp = 0x40; if ((event->raw[7] & 0x3F) != 1 && (event->raw[7] & 0x3F) != 0x3F) tmp = event->raw[7] & 0x3F; @@ -245,7 +246,7 @@ int touch_get_fw_info(touch_fw_info_t *fw) res = touch_read_reg(cmd, 3, buf, 8); if (!res) { - fw->fw_id = (buf[1] << 24) | (buf[2] << 16) | (buf[3] << 8) | buf[4]; + fw->fw_id = (buf[1] << 24) | (buf[2] << 16) | (buf[3] << 8) | buf[4]; fw->ftb_ver = (buf[6] << 8) | buf[5]; } @@ -400,30 +401,29 @@ static int touch_init() int touch_power_on() { - // Enable LDO6 for touchscreen AVDD supply. - max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000); - max7762x_regulator_enable(REGULATOR_LDO6, true); - - // Configure touchscreen VDD GPIO. - PINMUX_AUX(PINMUX_AUX_DAP4_SCLK) = PINMUX_PULL_DOWN | 1; - gpio_config(GPIO_PORT_J, GPIO_PIN_7, GPIO_MODE_GPIO); - gpio_output_enable(GPIO_PORT_J, GPIO_PIN_7, GPIO_OUTPUT_ENABLE); - gpio_write(GPIO_PORT_J, GPIO_PIN_7, GPIO_HIGH); - - // Touscreen IRQ. - // PINMUX_AUX(PINMUX_AUX_TOUCH_INT) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE | PINMUX_PULL_UP | 3; - // gpio_config(GPIO_PORT_X, GPIO_PIN_1, GPIO_MODE_GPIO); - // gpio_write(GPIO_PORT_X, GPIO_PIN_1, GPIO_LOW); - // Configure Touscreen and GCAsic shared GPIO. PINMUX_AUX(PINMUX_AUX_CAM_I2C_SDA) = PINMUX_LPDR | PINMUX_INPUT_ENABLE | PINMUX_TRISTATE | PINMUX_PULL_UP | 2; - PINMUX_AUX(PINMUX_AUX_CAM_I2C_SCL) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_TRISTATE | PINMUX_PULL_DOWN | 2; + PINMUX_AUX(PINMUX_AUX_CAM_I2C_SCL) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_TRISTATE | PINMUX_PULL_DOWN | 2; // Unused. gpio_config(GPIO_PORT_S, GPIO_PIN_3, GPIO_MODE_GPIO); // GC detect. + // Configure touchscreen Touch Reset pin. + PINMUX_AUX(PINMUX_AUX_DAP4_SCLK) = PINMUX_PULL_DOWN | 1; + gpio_direction_output(GPIO_PORT_J, GPIO_PIN_7, GPIO_LOW); + usleep(20); + + // Enable LDO6 for touchscreen AVDD and DVDD supply. + max7762x_regulator_set_voltage(REGULATOR_LDO6, 2900000); + max7762x_regulator_enable(REGULATOR_LDO6, true); + // Initialize I2C3. pinmux_config_i2c(I2C_3); clock_enable_i2c(I2C_3); i2c_init(I2C_3); + usleep(1000); + + // Set Touch Reset pin. + gpio_write(GPIO_PORT_J, GPIO_PIN_7, GPIO_HIGH); + usleep(10000); // Wait for the touchscreen module to get ready. touch_wait_event(STMFTS_EV_CONTROLLER_READY, 0, 20, NULL); diff --git a/bdk/libs/lv_conf.h b/bdk/libs/lv_conf.h index 7af36a4..89dc555 100644 --- a/bdk/libs/lv_conf.h +++ b/bdk/libs/lv_conf.h @@ -17,7 +17,7 @@ #ifndef LV_CONF_H #define LV_CONF_H -#include +#include #include /*=================== Dynamic memory @@ -147,10 +147,10 @@ #define LV_COMPILER_VLA_SUPPORTED 1 /* 1: Variable length array is supported*/ /*HAL settings*/ -#define LV_TICK_CUSTOM 1 /*1: use a custom tick source (removing the need to manually update the tick with `lv_tick_inc`) */ +#define LV_TICK_CUSTOM 1 /*1: use a custom tick source (removing the need to manually update the tick with `lv_tick_inc`) */ #if LV_TICK_CUSTOM == 1 -#define LV_TICK_CUSTOM_INCLUDE /*Header for the sys time function*/ -#define LV_TICK_CUSTOM_SYS_TIME_EXPR (get_tmr_ms()) /*Expression evaluating to current systime in ms*/ +#define LV_TICK_CUSTOM_INCLUDE /*Header for the sys time function*/ +#define LV_TICK_CUSTOM_SYS_TIME_EXPR ((u32)get_tmr_ms()) /*Expression evaluating to current systime in ms*/ #endif /*LV_TICK_CUSTOM*/ @@ -296,6 +296,9 @@ /*Message box (dependencies: lv_rect, lv_btnm, lv_label)*/ #define USE_LV_MBOX 1 +#if USE_LV_MBOX != 0 +# define LV_MBOX_CLOSE_ANIM_TIME 200 /*ms*/ +#endif /*Text area (dependencies: lv_label, lv_page)*/ #define USE_LV_TA 1 diff --git a/bdk/libs/lvgl/lv_core/lv_group.c b/bdk/libs/lvgl/lv_core/lv_group.c index 3fd4120..cedef7f 100644 --- a/bdk/libs/lvgl/lv_core/lv_group.c +++ b/bdk/libs/lvgl/lv_core/lv_group.c @@ -546,8 +546,8 @@ static void obj_to_foreground(lv_obj_t * obj) /*Move the last_top object to the foreground*/ lv_obj_t * par = lv_obj_get_parent(last_top); /*After list change it will be the new head*/ - lv_ll_chg_list(&par->child_ll, &par->child_ll, last_top); - lv_obj_invalidate(last_top); + if (lv_ll_chg_list(&par->child_ll, &par->child_ll, last_top)) + lv_obj_invalidate(last_top); /*Only invalidate if not top*/ } } diff --git a/bdk/libs/lvgl/lv_core/lv_indev.c b/bdk/libs/lvgl/lv_core/lv_indev.c index 763abf7..d1dc582 100644 --- a/bdk/libs/lvgl/lv_core/lv_indev.c +++ b/bdk/libs/lvgl/lv_core/lv_indev.c @@ -646,8 +646,8 @@ static void indev_proc_press(lv_indev_proc_t * proc) /*Move the last_top object to the foreground*/ lv_obj_t * par = lv_obj_get_parent(last_top); /*After list change it will be the new head*/ - lv_ll_chg_list(&par->child_ll, &par->child_ll, last_top); - lv_obj_invalidate(last_top); + if (lv_ll_chg_list(&par->child_ll, &par->child_ll, last_top)) + lv_obj_invalidate(last_top); /*Only invalidate if not top*/ } /*Send a signal about the press*/ diff --git a/bdk/libs/lvgl/lv_misc/lv_color.h b/bdk/libs/lvgl/lv_misc/lv_color.h index 3459b63..59f038f 100644 --- a/bdk/libs/lvgl/lv_misc/lv_color.h +++ b/bdk/libs/lvgl/lv_misc/lv_color.h @@ -412,17 +412,17 @@ static inline uint8_t lv_color_brightness(lv_color_t color) #endif #if LV_COLOR_DEPTH == 32 // Concatenate into one 32-bit set. -#define LV_COLOR_HEX(c) ((lv_color_t){.full = (c | 0xFF000000)}) +#define LV_COLOR_HEX(c) ((lv_color_t){.full = ((c) | 0xFF000000)}) #else -#define LV_COLOR_HEX(c) LV_COLOR_MAKE(((uint32_t)((uint32_t)c >> 16) & 0xFF), \ - ((uint32_t)((uint32_t)c >> 8) & 0xFF), \ - ((uint32_t) c & 0xFF)) +#define LV_COLOR_HEX(c) LV_COLOR_MAKE(((uint32_t)((uint32_t)(c) >> 16) & 0xFF), \ + ((uint32_t)((uint32_t)(c) >> 8) & 0xFF), \ + ((uint32_t) (c) & 0xFF)) #endif /*Usage LV_COLOR_HEX3(0x16C) which means LV_COLOR_HEX(0x1166CC)*/ -#define LV_COLOR_HEX3(c) LV_COLOR_MAKE((((c >> 4) & 0xF0) | ((c >> 8) & 0xF)), \ - ((uint32_t)(c & 0xF0) | ((c & 0xF0) >> 4)), \ - ((uint32_t)(c & 0xF) | ((c & 0xF) << 4))) +#define LV_COLOR_HEX3(c) LV_COLOR_MAKE(((((c) >> 4) & 0xF0) | (((c) >> 8) & 0xF)), \ + ((uint32_t)((c) & 0xF0) | (((c) & 0xF0) >> 4)), \ + ((uint32_t)((c) & 0xF) | (((c) & 0xF) << 4))) /** diff --git a/bdk/libs/lvgl/lv_misc/lv_ll.c b/bdk/libs/lvgl/lv_misc/lv_ll.c index 43d8847..5583311 100644 --- a/bdk/libs/lvgl/lv_misc/lv_ll.c +++ b/bdk/libs/lvgl/lv_misc/lv_ll.c @@ -215,9 +215,12 @@ void lv_ll_clear(lv_ll_t * ll_p) * @param ll_ori_p pointer to the original (old) linked list * @param ll_new_p pointer to the new linked list * @param node pointer to a node + * @return head changed */ -void lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node) +bool lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node) { + bool changed = ll_new_p->head != node; + lv_ll_rem(ll_ori_p, node); /*Set node as head*/ @@ -232,6 +235,8 @@ void lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node) if(ll_new_p->tail == NULL) { /*If there is no tail (first node) set the tail too*/ ll_new_p->tail = node; } + + return changed; } /** diff --git a/bdk/libs/lvgl/lv_misc/lv_ll.h b/bdk/libs/lvgl/lv_misc/lv_ll.h index 086ba40..5bde7e5 100644 --- a/bdk/libs/lvgl/lv_misc/lv_ll.h +++ b/bdk/libs/lvgl/lv_misc/lv_ll.h @@ -89,8 +89,9 @@ void lv_ll_clear(lv_ll_t * ll_p); * @param ll_ori_p pointer to the original (old) linked list * @param ll_new_p pointer to the new linked list * @param node pointer to a node + * @return head changed */ -void lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node); +bool lv_ll_chg_list(lv_ll_t * ll_ori_p, lv_ll_t * ll_new_p, void * node); /** * Return with head node of the linked list diff --git a/bdk/libs/lvgl/lv_themes/lv_theme_hekate.c b/bdk/libs/lvgl/lv_themes/lv_theme_hekate.c index d12732c..f151dbe 100644 --- a/bdk/libs/lvgl/lv_themes/lv_theme_hekate.c +++ b/bdk/libs/lvgl/lv_themes/lv_theme_hekate.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 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, @@ -32,13 +32,16 @@ #define COLOR_HOS_TEAL_LIGHT (lv_color_hsv_to_rgb(_hue, 100, 72)) // 0x00B78F #define COLOR_HOS_TEAL (lv_color_hsv_to_rgb(_hue, 100, 64)) // 0x00A273 #define COLOR_HOS_ORANGE LV_COLOR_HEX(0xFF5500) -#define COLOR_HOS_BG_DARKER LV_COLOR_HEX(0x1B1B1B) -#define COLOR_HOS_BG_DARK LV_COLOR_HEX(0x222222) -#define COLOR_HOS_BG LV_COLOR_HEX(0x2D2D2D) -#define COLOR_HOS_BG_LIGHT LV_COLOR_HEX(0x3D3D3D) -#define COLOR_HOS_LIGHT_BORDER LV_COLOR_HEX(0x4D4D4D) #define COLOR_HOS_TXT_WHITE LV_COLOR_HEX(0xFBFBFB) +#define COLOR_BG_DARKER LV_COLOR_HEX(theme_bg_color ? (theme_bg_color - 0x121212) : 0x0B0B0B) // 0x1B1B1B. +#define COLOR_BG_DARK LV_COLOR_HEX(theme_bg_color ? (theme_bg_color - 0x0B0B0B) : 0x121212) // 0x222222. +#define COLOR_BG LV_COLOR_HEX(theme_bg_color) // 0x2D2D2D. +#define COLOR_BG_LIGHT LV_COLOR_HEX(theme_bg_color ? (theme_bg_color + 0x101010) : 0x2D2D2D) // 0x3D3D3D. +#define COLOR_BG_LIGHTER LV_COLOR_HEX(theme_bg_color ? (theme_bg_color + 0x191919) : 0x363636) // 0x464646. +#define COLOR_LIGHT_BORDER LV_COLOR_HEX(theme_bg_color ? (theme_bg_color + 0x202020) : 0x3D3D3D) // 0x4D4D4D. + + /********************** * TYPEDEFS **********************/ @@ -57,8 +60,9 @@ static lv_style_t def; static lv_style_t sb; /*Saved input parameters*/ -static uint16_t _hue; +static uint16_t _hue; static lv_font_t * _font; +uint32_t theme_bg_color; /********************** * MACROS @@ -80,18 +84,17 @@ static void basic_init(void) //def.image.opa = LV_OPA_COVER; lv_style_copy(&bg, &def); - bg.body.main_color = COLOR_HOS_BG; - //bg.body.main_color = LV_COLOR_BLACK; + bg.body.main_color = COLOR_BG; bg.body.grad_color = bg.body.main_color; bg.body.radius = 0; bg.body.empty = 1; lv_style_copy(&panel, &def); panel.body.radius = DEF_RADIUS; - panel.body.main_color = COLOR_HOS_BG; - panel.body.grad_color = COLOR_HOS_BG; + panel.body.main_color = COLOR_BG; + panel.body.grad_color = COLOR_BG; panel.body.border.width = 1; - panel.body.border.color = COLOR_HOS_LIGHT_BORDER; + panel.body.border.color = COLOR_LIGHT_BORDER; panel.body.border.opa = LV_OPA_COVER; panel.body.shadow.color = COLOR_SHADOW_LIGHT; panel.body.shadow.type = LV_SHADOW_BOTTOM; @@ -129,7 +132,7 @@ static void btn_init(void) static lv_style_t rel, pr, tgl_rel, tgl_pr, ina; lv_style_copy(&rel, &def); - rel.body.main_color = COLOR_HOS_BG_LIGHT; + rel.body.main_color = COLOR_BG_LIGHT; rel.body.grad_color = rel.body.main_color; rel.body.radius = 6; rel.body.padding.hor = LV_DPI / 3; @@ -139,7 +142,7 @@ static void btn_init(void) rel.body.shadow.type = LV_SHADOW_BOTTOM; rel.body.shadow.width = 6; rel.body.border.width = 0; - rel.body.border.color = COLOR_HOS_BG_LIGHT; + rel.body.border.color = COLOR_BG_LIGHT; rel.body.border.part = LV_BORDER_FULL; //rel.text.color = COLOR_HOS_TXT_WHITE; @@ -162,7 +165,7 @@ static void btn_init(void) tgl_pr.body.shadow.width = 0; lv_style_copy(&ina, &rel); - ina.body.main_color = COLOR_HOS_BG_DARK; + ina.body.main_color = COLOR_BG_DARK; ina.body.grad_color = ina.body.main_color; //ina.body.shadow.width = 0; ina.text.color = LV_COLOR_HEX(0x888888); @@ -207,7 +210,7 @@ static void img_init(void) img_light.image.intense = LV_OPA_80; lv_style_copy(&img_dark, &def); - img_dark.image.color = COLOR_HOS_BG_DARKER; + img_dark.image.color = COLOR_BG_DARKER; img_dark.image.intense = LV_OPA_80; @@ -250,7 +253,7 @@ static void bar_init(void) static lv_style_t bar_bg, bar_indic; lv_style_copy(&bar_bg, &def); - bar_bg.body.main_color = COLOR_HOS_LIGHT_BORDER; + bar_bg.body.main_color = COLOR_LIGHT_BORDER; bar_bg.body.grad_color = bar_bg.body.main_color; bar_bg.body.radius = 3; bar_bg.body.border.width = 0; @@ -536,9 +539,9 @@ static void mbox_init(void) static lv_style_t bg; lv_style_copy(&bg, theme.panel); - bg.body.main_color = LV_COLOR_HEX(0x464646); + bg.body.main_color = COLOR_BG_LIGHTER; bg.body.grad_color = bg.body.main_color; - bg.body.shadow.color = COLOR_HOS_BG; + bg.body.shadow.color = COLOR_BG; bg.body.shadow.type = LV_SHADOW_FULL; bg.body.shadow.width = 8; @@ -628,7 +631,7 @@ static void list_init(void) // pr.text.font = _font; lv_style_copy(&tgl_rel, &pr); - tgl_rel.body.main_color = COLOR_HOS_BG_LIGHT; + tgl_rel.body.main_color = COLOR_BG_LIGHT; tgl_rel.body.grad_color = tgl_rel.body.main_color; //tgl_rel.text.color = lv_color_hsv_to_rgb(_hue, 5, 95); tgl_rel.text.color = COLOR_HOS_TEAL_LIGHTER; @@ -639,7 +642,7 @@ static void list_init(void) tgl_pr.body.border.width = 0; lv_style_copy(&ina, &pr); - ina.body.main_color = COLOR_HOS_BG_DARK; + ina.body.main_color = COLOR_BG_DARK; ina.body.grad_color = ina.body.main_color; theme.list.sb = &sb; @@ -667,7 +670,7 @@ static void ddlist_init(void) bg.text.color = COLOR_HOS_TURQUOISE; lv_style_copy(&sel, &bg); - sel.body.main_color = COLOR_HOS_BG_LIGHT; + sel.body.main_color = COLOR_BG_LIGHT; sel.body.grad_color = sel.body.main_color; theme.ddlist.bg = &bg; @@ -713,7 +716,7 @@ static void tabview_init(void) indic.body.opa = LV_OPA_0; lv_style_copy(&btn_bg, &def); - btn_bg.body.main_color = COLOR_HOS_BG; + btn_bg.body.main_color = COLOR_BG; btn_bg.body.grad_color = btn_bg.body.main_color; btn_bg.body.radius = 0; btn_bg.body.empty = 1; @@ -734,7 +737,7 @@ static void tabview_init(void) rel.text.font = _font; lv_style_copy(&pr, &def); - pr.body.main_color = COLOR_HOS_BG_LIGHT; + pr.body.main_color = COLOR_BG_LIGHT; pr.body.grad_color = pr.body.main_color; pr.body.border.width = 0; pr.body.empty = 0; @@ -750,7 +753,7 @@ static void tabview_init(void) tgl_rel.text.color = COLOR_HOS_TURQUOISE; lv_style_copy(&tgl_pr, &def); - tgl_pr.body.main_color = COLOR_HOS_BG_LIGHT; + tgl_pr.body.main_color = COLOR_BG_LIGHT; tgl_pr.body.grad_color = tgl_pr.body.main_color; tgl_pr.body.border.width = 0; tgl_pr.body.empty = 0; @@ -797,7 +800,7 @@ static void win_init(void) static lv_style_t header, rel, pr; lv_style_copy(&header, &def); - header.body.main_color = COLOR_HOS_BG; + header.body.main_color = COLOR_BG; header.body.grad_color = header.body.main_color; header.body.radius = 0; header.body.border.width = 0; @@ -843,10 +846,11 @@ static void win_init(void) * @param font pointer to a font (NULL to use the default) * @return pointer to the initialized theme */ -lv_theme_t * lv_theme_hekate_init(uint16_t hue, lv_font_t * font) +lv_theme_t * lv_theme_hekate_init(uint32_t bg_color, uint16_t hue, lv_font_t * font) { if(font == NULL) font = LV_FONT_DEFAULT; + theme_bg_color = bg_color; _hue = hue; _font = font; diff --git a/bdk/libs/lvgl/lv_themes/lv_theme_hekate.h b/bdk/libs/lvgl/lv_themes/lv_theme_hekate.h index cc61d2d..45448b9 100644 --- a/bdk/libs/lvgl/lv_themes/lv_theme_hekate.h +++ b/bdk/libs/lvgl/lv_themes/lv_theme_hekate.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 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, @@ -35,6 +35,14 @@ extern "C" { /********************* * DEFINES *********************/ +#define COLOR_HOS_BG_BASE_DEFAULT 0x1B1B1B +#define COLOR_HOS_BG_BASE_BLACK 0x000000 + +#define COLOR_HOS_BG_DARKER 0x1B1B1B +#define COLOR_HOS_BG_DARK 0x222222 +#define COLOR_HOS_BG 0x2D2D2D +#define COLOR_HOS_BG_LIGHT 0x3D3D3D +#define COLOR_HOS_LIGHT_BORDER 0x4D4D4D /********************** * TYPEDEFS @@ -44,13 +52,15 @@ extern "C" { * GLOBAL PROTOTYPES **********************/ +extern uint32_t theme_bg_color; + /** * Initialize the material theme * @param hue [0..360] hue value from HSV color space to define the theme's base color * @param font pointer to a font (NULL to use the default) * @return pointer to the initialized theme */ -lv_theme_t * lv_theme_hekate_init(uint16_t hue, lv_font_t *font); +lv_theme_t * lv_theme_hekate_init(uint32_t bg_color, uint16_t hue, lv_font_t *font); /** * Get a pointer to the theme diff --git a/bdk/libs/nx_savedata/header.h b/bdk/libs/nx_savedata/header.h index 3d65d83..76e4c31 100644 --- a/bdk/libs/nx_savedata/header.h +++ b/bdk/libs/nx_savedata/header.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020 shchmue + * Copyright (c) 2019-2022 shchmue * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -61,7 +61,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #define VERSION_RMAP 0x10000 #define VERSION_IVFC 0x20000 -#define SAVE_BLOCK_SIZE_DEFAULT 0x4000 +#define SAVE_BLOCK_SIZE_DEFAULT SZ_16K #define SAVE_NUM_HEADERS 2 @@ -232,6 +232,6 @@ typedef struct { }; } save_header_t; -static_assert(sizeof(save_header_t) == 0x4000, "Save header size is wrong!"); +static_assert(sizeof(save_header_t) == SZ_16K, "Save header size is wrong!"); #endif diff --git a/bdk/libs/nx_savedata/remap_storage.h b/bdk/libs/nx_savedata/remap_storage.h index 2f67e04..fc048a3 100644 --- a/bdk/libs/nx_savedata/remap_storage.h +++ b/bdk/libs/nx_savedata/remap_storage.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020 shchmue + * Copyright (c) 2019-2022 shchmue * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -41,7 +41,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #define RMAP_ALIGN_SMALL 0x200 -#define RMAP_ALIGN_LARGE 0x4000 +#define RMAP_ALIGN_LARGE SZ_16K typedef struct { uint32_t magic; /* RMAP */ diff --git a/bdk/libs/nx_savedata/save.c b/bdk/libs/nx_savedata/save.c index 5cc4b9f..8b0256e 100644 --- a/bdk/libs/nx_savedata/save.c +++ b/bdk/libs/nx_savedata/save.c @@ -34,7 +34,14 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "save.h" -#include +#include +#include +#include +#include +#include +#include +#include + #include #include diff --git a/bdk/libs/nx_savedata/save_data_file.c b/bdk/libs/nx_savedata/save_data_file.c index 7f3645d..edf85ba 100644 --- a/bdk/libs/nx_savedata/save_data_file.c +++ b/bdk/libs/nx_savedata/save_data_file.c @@ -99,9 +99,10 @@ bool save_data_file_write(save_data_file_ctx_t *ctx, uint64_t *out_bytes_written if (!save_data_file_validate_write_params(ctx, offset, count, ctx->mode, &is_resize_needed)) return false; - if (!save_data_file_set_size(ctx, offset + count)) - return false; - + if (is_resize_needed) { + if (!save_data_file_set_size(ctx, offset + count)) + return false; + } *out_bytes_written = save_allocation_table_storage_write(&ctx->base_storage, buffer, offset, count); return true; diff --git a/bdk/libs/nx_savedata/save_fs_list.c b/bdk/libs/nx_savedata/save_fs_list.c index 78e2abe..69cc915 100644 --- a/bdk/libs/nx_savedata/save_fs_list.c +++ b/bdk/libs/nx_savedata/save_fs_list.c @@ -250,7 +250,7 @@ uint32_t save_fs_list_allocate_entry(save_filesystem_list_ctx_t *ctx) { if (capacity == 0 || length >= capacity) { uint64_t current_size, new_size; save_allocation_table_storage_get_size(&ctx->storage, ¤t_size); - if (!save_allocation_table_storage_set_size(&ctx->storage, current_size + 0x4000)) + if (!save_allocation_table_storage_set_size(&ctx->storage, current_size + SZ_16K)) return 0; save_allocation_table_storage_get_size(&ctx->storage, &new_size); if (!save_fs_list_set_capacity(ctx, (uint32_t)(new_size / sizeof(save_fs_list_entry_t)))) diff --git a/bdk/libs/nx_savedata/save_fs_list.h b/bdk/libs/nx_savedata/save_fs_list.h index 72b4e4b..da98736 100644 --- a/bdk/libs/nx_savedata/save_fs_list.h +++ b/bdk/libs/nx_savedata/save_fs_list.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020 shchmue + * Copyright (c) 2019-2022 shchmue * * 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/mem/emc.h b/bdk/mem/emc.h index ea5420a..e4ff626 100644 --- a/bdk/mem/emc.h +++ b/bdk/mem/emc.h @@ -698,6 +698,8 @@ typedef enum _emc_mr_t { + MR0_FEAT = 0, + MR4_TEMP = 4, MR5_MAN_ID = 5, MR6_REV_ID1 = 6, MR7_REV_ID2 = 7, diff --git a/bdk/mem/heap.c b/bdk/mem/heap.c index d249140..9c5b406 100644 --- a/bdk/mem/heap.c +++ b/bdk/mem/heap.c @@ -19,33 +19,44 @@ #include "heap.h" #include -static void _heap_create(heap_t *heap, u32 start) +heap_t _heap; + +static void _heap_create(void *start) { - heap->start = start; - heap->first = NULL; + _heap.start = start; + _heap.first = NULL; + _heap.last = NULL; } // Node info is before node address. -static u32 _heap_alloc(heap_t *heap, u32 size) +static void *_heap_alloc(u32 size) { hnode_t *node, *new_node; // Align to cache line size. size = ALIGN(size, sizeof(hnode_t)); - if (!heap->first) + // First allocation. + if (!_heap.first) { - node = (hnode_t *)heap->start; + node = (hnode_t *)_heap.start; node->used = 1; node->size = size; node->prev = NULL; node->next = NULL; - heap->first = node; - return (u32)node + sizeof(hnode_t); + _heap.first = node; + _heap.last = node; + + return (void *)node + sizeof(hnode_t); } - node = heap->first; +#ifdef BDK_MALLOC_NO_DEFRAG + // Get the last allocated block. + node = _heap.last; +#else + // Get first block and find the first available one. + node = _heap.first; while (true) { // Check if there's available unused node. @@ -53,7 +64,7 @@ static u32 _heap_alloc(heap_t *heap, u32 size) { // Size and offset of the new unused node. u32 new_size = node->size - size; - new_node = (hnode_t *)((u32)node + sizeof(hnode_t) + size); + new_node = (hnode_t *)((void *)node + sizeof(hnode_t) + size); // If there's aligned unused space from the old node, // create a new one and set the leftover size. @@ -76,7 +87,7 @@ static u32 _heap_alloc(heap_t *heap, u32 size) node->size = size; node->used = 1; - return (u32)node + sizeof(hnode_t); + return (void *)node + sizeof(hnode_t); } // No unused node found, try the next one. @@ -85,23 +96,29 @@ static u32 _heap_alloc(heap_t *heap, u32 size) else break; } +#endif // No unused node found, create a new one. - new_node = (hnode_t *)((u32)node + sizeof(hnode_t) + node->size); + new_node = (hnode_t *)((void *)node + sizeof(hnode_t) + node->size); new_node->used = 1; new_node->size = size; new_node->prev = node; new_node->next = NULL; - node->next = new_node; - return (u32)new_node + sizeof(hnode_t); + node->next = new_node; + _heap.last = new_node; + + return (void *)new_node + sizeof(hnode_t); } -static void _heap_free(heap_t *heap, u32 addr) +static void _heap_free(void *addr) { hnode_t *node = (hnode_t *)(addr - sizeof(hnode_t)); node->used = 0; - node = heap->first; + node = _heap.first; + +#ifndef BDK_MALLOC_NO_DEFRAG + // Do simple defragmentation on next blocks. while (node) { if (!node->used) @@ -117,36 +134,35 @@ static void _heap_free(heap_t *heap, u32 addr) } node = node->next; } +#endif } -heap_t _heap; - -void heap_init(u32 base) +void heap_init(void *base) { - _heap_create(&_heap, base); + _heap_create(base); } -void heap_copy(heap_t *heap) +void heap_set(heap_t *heap) { memcpy(&_heap, heap, sizeof(heap_t)); } void *malloc(u32 size) { - return (void *)_heap_alloc(&_heap, size); + return _heap_alloc(size); } void *calloc(u32 num, u32 size) { - void *res = (void *)_heap_alloc(&_heap, num * size); + void *res = (void *)_heap_alloc(num * size); memset(res, 0, ALIGN(num * size, sizeof(hnode_t))); // Clear the aligned size. return res; } void free(void *buf) { - if ((u32)buf >= _heap.start) - _heap_free(&_heap, (u32)buf); + if (buf >= _heap.start) + _heap_free(buf); } void heap_monitor(heap_monitor_t *mon, bool print_node_stats) @@ -158,7 +174,10 @@ void heap_monitor(heap_monitor_t *mon, bool print_node_stats) while (true) { if (node->used) + { + mon->nodes_used++; mon->used += node->size + sizeof(hnode_t); + } else mon->total += node->size + sizeof(hnode_t); @@ -174,4 +193,5 @@ void heap_monitor(heap_monitor_t *mon, bool print_node_stats) break; } mon->total += mon->used; + mon->nodes_total = count; } diff --git a/bdk/mem/heap.h b/bdk/mem/heap.h index 811f13d..9150104 100644 --- a/bdk/mem/heap.h +++ b/bdk/mem/heap.h @@ -31,18 +31,21 @@ typedef struct _hnode typedef struct _heap { - u32 start; + void *start; hnode_t *first; + hnode_t *last; } heap_t; typedef struct { - u32 total; - u32 used; + u32 total; + u32 used; + u32 nodes_total; + u32 nodes_used; } heap_monitor_t; -void heap_init(u32 base); -void heap_copy(heap_t *heap); +void heap_init(void *base); +void heap_set(heap_t *heap); void *malloc(u32 size); void *calloc(u32 num, u32 size); void free(void *buf); diff --git a/bdk/mem/mc.c b/bdk/mem/mc.c index d577bd7..d8949bc 100644 --- a/bdk/mem/mc.c +++ b/bdk/mem/mc.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, @@ -17,11 +17,9 @@ #include #include +#include #include #include -#include - -//#define CONFIG_ENABLE_AHB_REDIRECT void mc_config_tsec_carveout(u32 bom, u32 size1mb, bool lock) { @@ -125,13 +123,13 @@ void mc_config_carveout() MC(MC_SECURITY_CARVEOUT5_CFG0) = 0x8F; } -void mc_enable_ahb_redirect(bool full_aperture) +void mc_enable_ahb_redirect() { // Enable ARC_CLK_OVR_ON. - CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) = (CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) & 0xFFF7FFFF) | 0x80000; - //MC(MC_IRAM_REG_CTRL) &= 0xFFFFFFFE; - MC(MC_IRAM_BOM) = 0x40000000; - MC(MC_IRAM_TOM) = full_aperture ? DRAM_START : 0x4003F000; + CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) |= BIT(19); + //MC(MC_IRAM_REG_CTRL) &= ~BIT(0); + MC(MC_IRAM_BOM) = IRAM_BASE; + MC(MC_IRAM_TOM) = DRAM_START; // Default is only IRAM: 0x4003F000. } void mc_disable_ahb_redirect() @@ -139,15 +137,27 @@ void mc_disable_ahb_redirect() MC(MC_IRAM_BOM) = 0xFFFFF000; MC(MC_IRAM_TOM) = 0; // Disable IRAM_CFG_WRITE_ACCESS (sticky). - //MC(MC_IRAM_REG_CTRL) = MC(MC_IRAM_REG_CTRL) & 0xFFFFFFFE | 1; + //MC(MC_IRAM_REG_CTRL) |= BIT(0); // Disable ARC_CLK_OVR_ON. - CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) &= 0xFFF7FFFF; + CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD) &= ~BIT(19); +} + +bool mc_client_has_access(void *address) +{ + // Check if address is in DRAM or if arbitration for IRAM is enabled. + if ((u32)address >= DRAM_START) + return true; // Access by default. + else if ((u32)address >= IRAM_BASE && MC(MC_IRAM_BOM) == IRAM_BASE) + return true; // Access by AHB arbitration. + + // No access to address space. + return false; } void mc_enable() { // Reset EMC source to PLLP. - CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF) | 0x40000000; + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF) | (2 << 29); // Enable memory clocks. CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_EMC); CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_MEM); @@ -156,7 +166,7 @@ void mc_enable() CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM); usleep(5); -#ifdef CONFIG_ENABLE_AHB_REDIRECT +#ifdef BDK_MC_ENABLE_AHB_REDIRECT mc_enable_ahb_redirect(); #else mc_disable_ahb_redirect(); diff --git a/bdk/mem/mc.h b/bdk/mem/mc.h index d873c7d..300bbfd 100644 --- a/bdk/mem/mc.h +++ b/bdk/mem/mc.h @@ -23,8 +23,9 @@ void mc_config_tsec_carveout(u32 bom, u32 size1mb, bool lock); void mc_config_carveout(); void mc_config_carveout_finalize(); -void mc_enable_ahb_redirect(bool full_aperture); +void mc_enable_ahb_redirect(); void mc_disable_ahb_redirect(); +bool mc_client_has_access(void *address); void mc_enable(); #endif diff --git a/bdk/mem/mc_t210.h b/bdk/mem/mc_t210.h index 5bf8ce8..ed96852 100644 --- a/bdk/mem/mc_t210.h +++ b/bdk/mem/mc_t210.h @@ -464,6 +464,98 @@ #define MC_UNTRANSLATED_REGION_CHECK 0x948 #define MC_DA_CONFIG0 0x9dc +/* MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS0 */ +#define SEC_CARVEOUT_CA0_R_PTCR BIT(0) +#define SEC_CARVEOUT_CA0_R_DISPLAY0A BIT(1) +#define SEC_CARVEOUT_CA0_R_DISPLAY0AB BIT(2) +#define SEC_CARVEOUT_CA0_R_DISPLAY0B BIT(3) +#define SEC_CARVEOUT_CA0_R_DISPLAY0BB BIT(4) +#define SEC_CARVEOUT_CA0_R_DISPLAY0C BIT(5) +#define SEC_CARVEOUT_CA0_R_DISPLAY0CB BIT(6) +#define SEC_CARVEOUT_CA0_R_AFI BIT(14) +#define SEC_CARVEOUT_CA0_R_BPMP_C BIT(15) +#define SEC_CARVEOUT_CA0_R_DISPLAYHC BIT(16) +#define SEC_CARVEOUT_CA0_R_DISPLAYHCB BIT(17) +#define SEC_CARVEOUT_CA0_R_HDA BIT(21) +#define SEC_CARVEOUT_CA0_R_HOST1XDMA BIT(22) +#define SEC_CARVEOUT_CA0_R_HOST1X BIT(23) +#define SEC_CARVEOUT_CA0_R_NVENC BIT(28) +#define SEC_CARVEOUT_CA0_R_PPCSAHBDMA BIT(29) +#define SEC_CARVEOUT_CA0_R_PPCSAHBSLV BIT(30) +#define SEC_CARVEOUT_CA0_R_SATAR BIT(31) + +/* MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS1 */ +#define SEC_CARVEOUT_CA1_R_VDEBSEV BIT(2) +#define SEC_CARVEOUT_CA1_R_VDEMBE BIT(3) +#define SEC_CARVEOUT_CA1_R_VDEMCE BIT(4) +#define SEC_CARVEOUT_CA1_R_VDETPE BIT(5) +#define SEC_CARVEOUT_CA1_R_CCPLEXLP_C BIT(6) +#define SEC_CARVEOUT_CA1_R_CCPLEX_C BIT(7) +#define SEC_CARVEOUT_CA1_W_NVENC BIT(11) +#define SEC_CARVEOUT_CA1_W_AFI BIT(17) +#define SEC_CARVEOUT_CA1_W_BPMP_C BIT(18) +#define SEC_CARVEOUT_CA1_W_HDA BIT(21) +#define SEC_CARVEOUT_CA1_W_HOST1X BIT(22) +#define SEC_CARVEOUT_CA1_W_CCPLEXLP_C BIT(24) +#define SEC_CARVEOUT_CA1_W_CCPLEX_C BIT(25) +#define SEC_CARVEOUT_CA1_W_PPCSAHBDMA BIT(27) +#define SEC_CARVEOUT_CA1_W_PPCSAHBSLV BIT(28) +#define SEC_CARVEOUT_CA1_W_SATA BIT(29) +#define SEC_CARVEOUT_CA1_W_VDEBSEV BIT(30) +#define SEC_CARVEOUT_CA1_W_VDEDBG BIT(31) + +/* MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS2 */ +#define SEC_CARVEOUT_CA2_W_VDEMBE BIT(0) +#define SEC_CARVEOUT_CA2_W_VDETPM BIT(1) +#define SEC_CARVEOUT_CA2_R_ISPRA BIT(4) +#define SEC_CARVEOUT_CA2_W_ISPWA BIT(6) +#define SEC_CARVEOUT_CA2_W_ISPWB BIT(7) +#define SEC_CARVEOUT_CA2_R_XUSB_HOST BIT(10) +#define SEC_CARVEOUT_CA2_W_XUSB_HOST BIT(11) +#define SEC_CARVEOUT_CA2_R_XUSB_DEV BIT(12) +#define SEC_CARVEOUT_CA2_W_XUSB_DEV BIT(13) +#define SEC_CARVEOUT_CA2_R_SE2 BIT(14) +#define SEC_CARVEOUT_CA2_W_SE2 BIT(16) +#define SEC_CARVEOUT_CA2_R_TSEC BIT(20) +#define SEC_CARVEOUT_CA2_W_TSEC BIT(21) +#define SEC_CARVEOUT_CA2_R_ADSP_SC BIT(22) +#define SEC_CARVEOUT_CA2_W_ADSP_SC BIT(23) +#define SEC_CARVEOUT_CA2_R_GPU BIT(24) +#define SEC_CARVEOUT_CA2_W_GPU BIT(25) +#define SEC_CARVEOUT_CA2_R_DISPLAYT BIT(26) + +/* MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS3 */ +#define SEC_CARVEOUT_CA3_R_SDMMCA BIT(0) +#define SEC_CARVEOUT_CA3_R_SDMMCAA BIT(1) +#define SEC_CARVEOUT_CA3_R_SDMMC BIT(2) +#define SEC_CARVEOUT_CA3_R_SDMMCAB BIT(3) +#define SEC_CARVEOUT_CA3_W_SDMMCA BIT(4) +#define SEC_CARVEOUT_CA3_W_SDMMCAA BIT(5) +#define SEC_CARVEOUT_CA3_W_SDMMC BIT(6) +#define SEC_CARVEOUT_CA3_W_SDMMCAB BIT(7) +#define SEC_CARVEOUT_CA3_R_VIC BIT(12) +#define SEC_CARVEOUT_CA3_W_VIC BIT(13) +#define SEC_CARVEOUT_CA3_W_VIW BIT(18) +#define SEC_CARVEOUT_CA3_R_DISPLAYD BIT(19) +#define SEC_CARVEOUT_CA3_R_NVDEC BIT(24) +#define SEC_CARVEOUT_CA3_W_NVDEC BIT(25) +#define SEC_CARVEOUT_CA3_R_APE BIT(26) +#define SEC_CARVEOUT_CA3_W_APE BIT(27) +#define SEC_CARVEOUT_CA3_R_NVJPG BIT(30) +#define SEC_CARVEOUT_CA3_W_NVJPG BIT(31) + +/* MC_SECURITY_CARVEOUTX_CLIENT_FORCE_INTERNAL_ACCESS4 */ +#define SEC_CARVEOUT_CA4_R_SE BIT(0) +#define SEC_CARVEOUT_CA4_W_SE BIT(1) +#define SEC_CARVEOUT_CA4_R_AXIAP BIT(2) +#define SEC_CARVEOUT_CA4_W_AXIAP BIT(3) +#define SEC_CARVEOUT_CA4_R_ETR BIT(4) +#define SEC_CARVEOUT_CA4_W_ETR BIT(5) +#define SEC_CARVEOUT_CA4_R_TSECB BIT(6) +#define SEC_CARVEOUT_CA4_W_TSECB BIT(7) +#define SEC_CARVEOUT_CA4_R_GPU2 BIT(8) +#define SEC_CARVEOUT_CA4_W_GPU2 BIT(9) + // MC_VIDEO_PROTECT_REG_CTRL #define VPR_LOCK_MODE_SHIFT 0 #define VPR_CTRL_UNLOCKED (0 << VPR_LOCK_MODE_SHIFT) @@ -475,8 +567,8 @@ // MC_SECURITY_CARVEOUTX_CFG0 // Mode of LOCK_MODE. #define PROTECT_MODE_SHIFT 0 -#define SEC_CARVEOUT_CFG_SECURE (0 << PROTECT_MODE_SHIFT) -#define SEC_CARVEOUT_CFG_TZ_SECURE (1 << PROTECT_MODE_SHIFT) +#define SEC_CARVEOUT_CFG_ALL_SECURE (0 << PROTECT_MODE_SHIFT) +#define SEC_CARVEOUT_CFG_TZ_SECURE (1 << PROTECT_MODE_SHIFT) // Enables PROTECT_MODE. #define LOCK_MODE_SHIFT 1 #define SEC_CARVEOUT_CFG_UNLOCKED (0 << LOCK_MODE_SHIFT) @@ -487,30 +579,31 @@ #define SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY (1 << ADDRESS_TYPE_SHIFT) #define READ_ACCESS_LEVEL_SHIFT 3 -#define SEC_CARVEOUT_CFG_RD_ALL (1 << READ_ACCESS_LEVEL_SHIFT) -#define SEC_CARVEOUT_CFG_RD_UNK (2 << READ_ACCESS_LEVEL_SHIFT) +#define SEC_CARVEOUT_CFG_RD_NS (1 << READ_ACCESS_LEVEL_SHIFT) +#define SEC_CARVEOUT_CFG_RD_SEC (2 << READ_ACCESS_LEVEL_SHIFT) #define SEC_CARVEOUT_CFG_RD_FALCON_LS (4 << READ_ACCESS_LEVEL_SHIFT) #define SEC_CARVEOUT_CFG_RD_FALCON_HS (8 << READ_ACCESS_LEVEL_SHIFT) #define WRITE_ACCESS_LEVEL_SHIFT 7 -#define SEC_CARVEOUT_CFG_WR_ALL (1 << WRITE_ACCESS_LEVEL_SHIFT) -#define SEC_CARVEOUT_CFG_WR_UNK (2 << WRITE_ACCESS_LEVEL_SHIFT) +#define SEC_CARVEOUT_CFG_WR_NS (1 << WRITE_ACCESS_LEVEL_SHIFT) +#define SEC_CARVEOUT_CFG_WR_SEC (2 << WRITE_ACCESS_LEVEL_SHIFT) #define SEC_CARVEOUT_CFG_WR_FALCON_LS (4 << WRITE_ACCESS_LEVEL_SHIFT) #define SEC_CARVEOUT_CFG_WR_FALCON_HS (8 << WRITE_ACCESS_LEVEL_SHIFT) #define SEC_CARVEOUT_CFG_APERTURE_ID_MASK (3 << 11) +#define SEC_CARVEOUT_CFG_APERTURE_ID(id) ((id) << 11) #define DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT 14 -#define SEC_CARVEOUT_CFG_DIS_RD_CHECK_L0 (1 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT) -#define SEC_CARVEOUT_CFG_DIS_RD_CHECK_L1 (2 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT) -#define SEC_CARVEOUT_CFG_DIS_RD_CHECK_L2 (4 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT) -#define SEC_CARVEOUT_CFG_DIS_RD_CHECK_L3 (8 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT) +#define SEC_CARVEOUT_CFG_DIS_RD_CHECK_NS (1 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT) +#define SEC_CARVEOUT_CFG_DIS_RD_CHECK_SEC (2 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT) +#define SEC_CARVEOUT_CFG_DIS_RD_CHECK_FLCN_LS (4 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT) +#define SEC_CARVEOUT_CFG_DIS_RD_CHECK_FLCN_HS (8 << DISABLE_READ_CHECK_ACCESS_LEVEL_SHIFT) #define DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT 18 -#define SEC_CARVEOUT_CFG_DIS_WR_CHECK_L0 (1 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT) -#define SEC_CARVEOUT_CFG_DIS_WR_CHECK_L1 (2 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT) -#define SEC_CARVEOUT_CFG_DIS_WR_CHECK_L2 (4 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT) -#define SEC_CARVEOUT_CFG_DIS_WR_CHECK_L3 (8 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT) +#define SEC_CARVEOUT_CFG_DIS_WR_CHECK_NS (1 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT) +#define SEC_CARVEOUT_CFG_DIS_WR_CHECK_SEC (2 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT) +#define SEC_CARVEOUT_CFG_DIS_WR_CHECK_FLCN_LS (4 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT) +#define SEC_CARVEOUT_CFG_DIS_WR_CHECK_FLCN_HS (8 << DISABLE_WRITE_CHECK_ACCESS_LEVEL_SHIFT) #define SEC_CARVEOUT_CFG_SEND_CFG_TO_GPU BIT(22) diff --git a/bdk/mem/minerva.c b/bdk/mem/minerva.c index 301eced..184689e 100644 --- a/bdk/mem/minerva.c +++ b/bdk/mem/minerva.c @@ -27,13 +27,18 @@ #include #include +#define LA_REGS_OFFSET_T210 0x1284 +#define LA_REGS_OFFSET_T210B01 0xFA4 +#define LA_SDMMC1_INDEX 6 +#define LA_SDMMC4_INDEX 9 + extern volatile nyx_storage_t *nyx_str; void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *); u32 minerva_init() { - u32 curr_ram_idx = 0; + u32 tbl_idx = 0; minerva_cfg = NULL; mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg; @@ -98,13 +103,13 @@ u32 minerva_init() // Get current frequency u32 current_emc_clk_src = CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC); - for (curr_ram_idx = 0; curr_ram_idx < 10; curr_ram_idx++) + for (tbl_idx = 0; tbl_idx < mtc_cfg->table_entries; tbl_idx++) { - if (current_emc_clk_src == mtc_cfg->mtc_table[curr_ram_idx].clk_src_emc) + if (current_emc_clk_src == mtc_cfg->mtc_table[tbl_idx].clk_src_emc) break; } - mtc_cfg->rate_from = mtc_cfg->mtc_table[curr_ram_idx].rate_khz; + mtc_cfg->rate_from = mtc_cfg->mtc_table[tbl_idx].rate_khz; mtc_cfg->rate_to = FREQ_204; mtc_cfg->train_mode = OP_TRAIN; minerva_cfg(mtc_cfg, NULL); @@ -140,6 +145,15 @@ void minerva_change_freq(minerva_freq_t freq) } } +void minerva_sdmmc_la_program(void *table, bool t210b01) +{ + + u32 *la_scale_regs = (u32 *)(table + (t210b01 ? LA_REGS_OFFSET_T210B01 : LA_REGS_OFFSET_T210)); + + // Promote SDMMC1 latency allowance to SDMMC4 (SD to eMMC). + la_scale_regs[LA_SDMMC1_INDEX] = la_scale_regs[LA_SDMMC4_INDEX]; +} + void minerva_prep_boot_freq() { if (!minerva_cfg) @@ -157,13 +171,27 @@ void minerva_prep_boot_freq() minerva_change_freq(FREQ_800); } -void minerva_prep_boot_l4t() +void minerva_prep_boot_l4t(int oc_freq) { if (!minerva_cfg) return; mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg; + // Program SDMMC LA regs. + for (u32 i = 0; i < mtc_cfg->table_entries; i++) + minerva_sdmmc_la_program(&mtc_cfg->mtc_table[i], false); + + // Add OC frequency. + if (oc_freq && mtc_cfg->mtc_table[mtc_cfg->table_entries - 1].rate_khz == FREQ_1600) + { + memcpy(&mtc_cfg->mtc_table[mtc_cfg->table_entries], + &mtc_cfg->mtc_table[mtc_cfg->table_entries - 1], + sizeof(emc_table_t)); + mtc_cfg->mtc_table[mtc_cfg->table_entries].rate_khz = oc_freq; + mtc_cfg->table_entries++; + } + // Set init frequency. minerva_change_freq(FREQ_204); @@ -181,11 +209,25 @@ void minerva_prep_boot_l4t() } // Do FSP WAR and scale to 800 MHz as boot freq. - bool fsp_opwr_enabled = !!(EMC(EMC_MRW3) & 0xC0); - if (fsp_opwr_enabled) + bool fsp_opwr_disabled = !(EMC(EMC_MRW3) & 0xC0); + if (fsp_opwr_disabled) minerva_change_freq(FREQ_666); minerva_change_freq(FREQ_800); + // Trim table. + int entries = 0; + for (u32 i = 0; i < mtc_cfg->table_entries; i++) + { + // Copy freqs from 204 MHz to 800 MHz and 1600 MHz and above. + int rate = mtc_cfg->mtc_table[i].rate_khz; + if ((rate >= FREQ_204 && rate <= FREQ_800) || rate >= FREQ_1600) + { + memcpy(&mtc_cfg->mtc_table[entries], &mtc_cfg->mtc_table[i], sizeof(emc_table_t)); + entries++; + } + } + mtc_cfg->table_entries = entries; + // Do not let other mtc ops. mtc_cfg->init_done = 0; } @@ -211,3 +253,12 @@ emc_table_t *minerva_get_mtc_table() mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg; return mtc_cfg->mtc_table; } + +int minerva_get_mtc_table_entries() +{ + if (!minerva_cfg) + return 0; + + mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg; + return mtc_cfg->table_entries; +} diff --git a/bdk/mem/minerva.h b/bdk/mem/minerva.h index 9e7f684..9f71e83 100644 --- a/bdk/mem/minerva.h +++ b/bdk/mem/minerva.h @@ -61,9 +61,11 @@ typedef enum extern void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *); u32 minerva_init(); void minerva_change_freq(minerva_freq_t freq); +void minerva_sdmmc_la_program(void *table, bool t210b01); void minerva_prep_boot_freq(); -void minerva_prep_boot_l4t(); +void minerva_prep_boot_l4t(int oc_freq); void minerva_periodic_training(); emc_table_t *minerva_get_mtc_table(); +int minerva_get_mtc_table_entries(); #endif diff --git a/bdk/mem/sdram.c b/bdk/mem/sdram.c index 00ec355..2f33f7b 100644 --- a/bdk/mem/sdram.c +++ b/bdk/mem/sdram.c @@ -1,7 +1,7 @@ /* * Copyright (c) 2018 naehrwert * Copyright (c) 2018 balika011 - * Copyright (c) 2019-2021 CTCaer + * Copyright (c) 2019-2023 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, @@ -31,11 +31,14 @@ #include #include #include +#include #include -#include #define CONFIG_SDRAM_KEEP_ALIVE +#define DRAM_ID(x) BIT(x) +#define DRAM_CC(x) BIT(x) + typedef struct _sdram_vendor_patch_t { u32 val; @@ -44,35 +47,41 @@ typedef struct _sdram_vendor_patch_t } sdram_vendor_patch_t; static const u8 dram_encoding_t210b01[] = { - LPDDR4X_UNUSED, - LPDDR4X_UNUSED, - LPDDR4X_UNUSED, - LPDDR4X_4GB_HYNIX_1Y_A, - LPDDR4X_UNUSED, - LPDDR4X_4GB_HYNIX_1Y_A, - LPDDR4X_4GB_HYNIX_1Y_A, - LPDDR4X_4GB_SAMSUNG_X1X2, - LPDDR4X_NO_PATCH, - LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ, - LPDDR4X_NO_PATCH, - LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE, - LPDDR4X_NO_PATCH, - LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ, - LPDDR4X_NO_PATCH, - LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE, - LPDDR4X_4GB_SAMSUNG_Y, - LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL, - LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL, - LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL, - LPDDR4X_4GB_SAMSUNG_1Y_Y, - LPDDR4X_8GB_SAMSUNG_1Y_Y, - LPDDR4X_UNUSED, // Removed. - LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL, - LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL, - LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF, - LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF, - LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF, - LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL, +/* 00 */ LPDDR4X_UNUSED, +/* 01 */ LPDDR4X_UNUSED, +/* 02 */ LPDDR4X_UNUSED, +/* 03 */ LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEE, +/* 04 */ LPDDR4X_UNUSED, +/* 05 */ LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEE, +/* 06 */ LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEE, +/* 07 */ LPDDR4X_UNUSED, +/* 08 */ LPDDR4X_NO_PATCH, +/* 09 */ LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ, +/* 10 */ LPDDR4X_NO_PATCH, +/* 11 */ LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE, +/* 12 */ LPDDR4X_NO_PATCH, +/* 13 */ LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ, +/* 14 */ LPDDR4X_NO_PATCH, +/* 15 */ LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE, +/* 16 */ LPDDR4X_UNUSED, +/* 17 */ LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL, +/* 18 */ LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL, +/* 19 */ LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL, +/* 20 */ LPDDR4X_4GB_SAMSUNG_K4U6E3S4AB_MGCL, +/* 21 */ LPDDR4X_4GB_SAMSUNG_K4U6E3S4AB_MGCL, +/* 22 */ LPDDR4X_4GB_SAMSUNG_K4U6E3S4AB_MGCL, +/* 23 */ LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL, +/* 24 */ LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL, +/* 25 */ LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF, +/* 26 */ LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF, +/* 27 */ LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF, +/* 28 */ LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL, +/* 29 */ LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEI, +/* 30 */ LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEI, +/* 31 */ LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEI, +/* 32 */ LPDDR4X_4GB_MICRON_1A, +/* 33 */ LPDDR4X_4GB_MICRON_1A, +/* 34 */ LPDDR4X_4GB_MICRON_1A, }; #include "sdram_config.inl" @@ -118,6 +127,14 @@ static void _sdram_req_mrr_data(u32 data, bool dual_channel) emc_mr_data_t sdram_read_mrx(emc_mr_t mrx) { emc_mr_data_t data; + u32 dual_channel = (EMC(EMC_FBIO_CFG7) >> 2) & 1; + + // Clear left overs. + for (u32 i = 0; i < 32; i++) + { + (void)EMC(EMC_MRR); + usleep(1); + } /* * When a dram chip has only one rank, then the info from the 2 ranks differs. @@ -125,14 +142,23 @@ emc_mr_data_t sdram_read_mrx(emc_mr_t mrx) */ // Get Device 0 (Rank 0) info from both dram chips (channels). - _sdram_req_mrr_data(BIT(31) | (mrx << 16), EMC_CHAN0); + _sdram_req_mrr_data((2u << 30) | (mrx << 16), dual_channel); data.rank0_ch0 = EMC(EMC_MRR) & 0xFF; data.rank0_ch1 = (EMC(EMC_MRR) & 0xFF00 >> 8); - // Get Device 1 (Rank 1) info from both dram chips (channels). - _sdram_req_mrr_data(BIT(30) | (mrx << 16), EMC_CHAN1); - data.rank1_ch0 = EMC(EMC_MRR) & 0xFF; - data.rank1_ch1 = (EMC(EMC_MRR) & 0xFF00 >> 8); + // If Rank 1 exists, get info. + if (EMC(EMC_ADR_CFG) & 1) + { + // Get Device 1 (Rank 1) info from both dram chips (channels). + _sdram_req_mrr_data((1u << 30) | (mrx << 16), dual_channel); + data.rank1_ch0 = EMC(EMC_MRR) & 0xFF; + data.rank1_ch1 = (EMC(EMC_MRR) & 0xFF00 >> 8); + } + else + { + data.rank1_ch0 = 0xFF; + data.rank1_ch1 = 0xFF; + } return data; } @@ -250,7 +276,7 @@ break_nosleep: *(vu32 *)params->emc_bct_spare6 = params->emc_bct_spare7; // Set pad controls. - EMC(EMC_XM2COMPPADCTRL) = params->emc_xm2_comp_pad_ctrl; + 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; @@ -263,70 +289,70 @@ break_nosleep: EMC(EMC_AUTO_CAL_CONFIG7) = params->emc_auto_cal_config7; EMC(EMC_AUTO_CAL_CONFIG8) = params->emc_auto_cal_config8; - 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; + 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; EMC(EMC_PMACRO_CMD_TX_DRV) = params->emc_pmacro_cmd_tx_drive; EMC(EMC_PMACRO_AUTOCAL_CFG_COMMON) = params->emc_pmacro_auto_cal_common; - EMC(EMC_AUTO_CAL_CHANNEL) = params->emc_auto_cal_channel; - EMC(EMC_PMACRO_ZCTRL) = params->emc_pmacro_zcrtl; + EMC(EMC_AUTO_CAL_CHANNEL) = params->emc_auto_cal_channel; + EMC(EMC_PMACRO_ZCTRL) = params->emc_pmacro_zcrtl; - EMC(EMC_DLL_CFG_0) = params->emc_dll_cfg0; - EMC(EMC_DLL_CFG_1) = params->emc_dll_cfg1; + 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; 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; - EMC(EMC_DQS_BRLSHFT_1) = params->emc_dqs_brlshft1; - EMC(EMC_CMD_BRLSHFT_0) = params->emc_cmd_brlshft0; - EMC(EMC_CMD_BRLSHFT_1) = params->emc_cmd_brlshft1; - EMC(EMC_CMD_BRLSHFT_2) = params->emc_cmd_brlshft2; - EMC(EMC_CMD_BRLSHFT_3) = params->emc_cmd_brlshft3; + EMC(EMC_DQS_BRLSHFT_0) = params->emc_dqs_brlshft0; + EMC(EMC_DQS_BRLSHFT_1) = params->emc_dqs_brlshft1; + EMC(EMC_CMD_BRLSHFT_0) = params->emc_cmd_brlshft0; + EMC(EMC_CMD_BRLSHFT_1) = params->emc_cmd_brlshft1; + EMC(EMC_CMD_BRLSHFT_2) = params->emc_cmd_brlshft2; + EMC(EMC_CMD_BRLSHFT_3) = params->emc_cmd_brlshft3; EMC(EMC_QUSE_BRLSHFT_0) = params->emc_quse_brlshft0; EMC(EMC_QUSE_BRLSHFT_1) = params->emc_quse_brlshft1; EMC(EMC_QUSE_BRLSHFT_2) = params->emc_quse_brlshft2; EMC(EMC_QUSE_BRLSHFT_3) = params->emc_quse_brlshft3; 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; + EMC(EMC_PMACRO_PAD_CFG_CTRL) = params->emc_pmacro_pad_cfg_ctrl; - EMC(EMC_PMACRO_CMD_BRICK_CTRL_FDPD) = params->emc_pmacro_cmd_brick_ctrl_fdpd; - EMC(EMC_PMACRO_BRICK_CTRL_RFU2) = params->emc_pmacro_brick_ctrl_rfu2 & 0xFF7FFF7F; + EMC(EMC_PMACRO_CMD_BRICK_CTRL_FDPD) = params->emc_pmacro_cmd_brick_ctrl_fdpd; + EMC(EMC_PMACRO_BRICK_CTRL_RFU2) = params->emc_pmacro_brick_ctrl_rfu2 & 0xFF7FFF7F; EMC(EMC_PMACRO_DATA_BRICK_CTRL_FDPD) = params->emc_pmacro_data_brick_ctrl_fdpd; - EMC(EMC_PMACRO_BG_BIAS_CTRL_0) = params->emc_pmacro_bg_bias_ctrl0; - EMC(EMC_PMACRO_DATA_PAD_RX_CTRL) = params->emc_pmacro_data_pad_rx_ctrl; - EMC(EMC_PMACRO_CMD_PAD_RX_CTRL) = params->emc_pmacro_cmd_pad_rx_ctrl; - EMC(EMC_PMACRO_DATA_PAD_TX_CTRL) = params->emc_pmacro_data_pad_tx_ctrl; - EMC(EMC_PMACRO_DATA_RX_TERM_MODE) = params->emc_pmacro_data_rx_term_mode; - 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; + EMC(EMC_PMACRO_BG_BIAS_CTRL_0) = params->emc_pmacro_bg_bias_ctrl0; + EMC(EMC_PMACRO_DATA_PAD_RX_CTRL) = params->emc_pmacro_data_pad_rx_ctrl; + EMC(EMC_PMACRO_CMD_PAD_RX_CTRL) = params->emc_pmacro_cmd_pad_rx_ctrl; + EMC(EMC_PMACRO_DATA_PAD_TX_CTRL) = params->emc_pmacro_data_pad_tx_ctrl; + EMC(EMC_PMACRO_DATA_RX_TERM_MODE) = params->emc_pmacro_data_rx_term_mode; + 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; 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; - EMC(EMC_PMACRO_TX_PWRD_2) = params->emc_pmacro_tx_pwrd2; - EMC(EMC_PMACRO_TX_PWRD_3) = params->emc_pmacro_tx_pwrd3; - EMC(EMC_PMACRO_TX_PWRD_4) = params->emc_pmacro_tx_pwrd4; - EMC(EMC_PMACRO_TX_PWRD_5) = params->emc_pmacro_tx_pwrd5; + EMC(EMC_PMACRO_TX_PWRD_0) = params->emc_pmacro_tx_pwrd0; + EMC(EMC_PMACRO_TX_PWRD_1) = params->emc_pmacro_tx_pwrd1; + EMC(EMC_PMACRO_TX_PWRD_2) = params->emc_pmacro_tx_pwrd2; + EMC(EMC_PMACRO_TX_PWRD_3) = params->emc_pmacro_tx_pwrd3; + EMC(EMC_PMACRO_TX_PWRD_4) = params->emc_pmacro_tx_pwrd4; + EMC(EMC_PMACRO_TX_PWRD_5) = params->emc_pmacro_tx_pwrd5; EMC(EMC_PMACRO_TX_SEL_CLK_SRC_0) = params->emc_pmacro_tx_sel_clk_src0; EMC(EMC_PMACRO_TX_SEL_CLK_SRC_1) = params->emc_pmacro_tx_sel_clk_src1; EMC(EMC_PMACRO_TX_SEL_CLK_SRC_2) = params->emc_pmacro_tx_sel_clk_src2; EMC(EMC_PMACRO_TX_SEL_CLK_SRC_3) = params->emc_pmacro_tx_sel_clk_src3; EMC(EMC_PMACRO_TX_SEL_CLK_SRC_4) = params->emc_pmacro_tx_sel_clk_src4; EMC(EMC_PMACRO_TX_SEL_CLK_SRC_5) = params->emc_pmacro_tx_sel_clk_src5; - EMC(EMC_PMACRO_DDLL_BYPASS) = params->emc_pmacro_ddll_bypass; - EMC(EMC_PMACRO_DDLL_PWRD_0) = params->emc_pmacro_ddll_pwrd0; - EMC(EMC_PMACRO_DDLL_PWRD_1) = params->emc_pmacro_ddll_pwrd1; - EMC(EMC_PMACRO_DDLL_PWRD_2) = params->emc_pmacro_ddll_pwrd2; - 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; - 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; + EMC(EMC_PMACRO_DDLL_BYPASS) = params->emc_pmacro_ddll_bypass; + EMC(EMC_PMACRO_DDLL_PWRD_0) = params->emc_pmacro_ddll_pwrd0; + EMC(EMC_PMACRO_DDLL_PWRD_1) = params->emc_pmacro_ddll_pwrd1; + EMC(EMC_PMACRO_DDLL_PWRD_2) = params->emc_pmacro_ddll_pwrd2; + 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; + 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; 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; @@ -340,7 +366,7 @@ break_nosleep: EMC(EMC_PMACRO_QUSE_DDLL_RANK1_3) = params->emc_pmacro_quse_ddll_rank1_3; 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; - EMC(EMC_PMACRO_BRICK_CTRL_RFU1) = params->emc_pmacro_brick_ctrl_rfu1; + EMC(EMC_PMACRO_BRICK_CTRL_RFU1) = params->emc_pmacro_brick_ctrl_rfu1; 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; @@ -376,11 +402,11 @@ 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; - 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; - EMC(EMC_PMACRO_DDLL_LONG_CMD_3) = params->emc_pmacro_ddll_long_cmd_3; - EMC(EMC_PMACRO_DDLL_LONG_CMD_4) = params->emc_pmacro_ddll_long_cmd_4; + 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; + EMC(EMC_PMACRO_DDLL_LONG_CMD_3) = params->emc_pmacro_ddll_long_cmd_3; + EMC(EMC_PMACRO_DDLL_LONG_CMD_4) = params->emc_pmacro_ddll_long_cmd_4; EMC(EMC_PMACRO_DDLL_SHORT_CMD_0) = params->emc_pmacro_ddll_short_cmd_0; EMC(EMC_PMACRO_DDLL_SHORT_CMD_1) = params->emc_pmacro_ddll_short_cmd_1; EMC(EMC_PMACRO_DDLL_SHORT_CMD_2) = params->emc_pmacro_ddll_short_cmd_2; @@ -395,18 +421,18 @@ break_nosleep: EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place. // Initialize MC VPR settings. - MC(MC_VIDEO_PROTECT_BOM) = params->mc_video_protect_bom; - MC(MC_VIDEO_PROTECT_BOM_ADR_HI) = params->mc_video_protect_bom_adr_hi; - MC(MC_VIDEO_PROTECT_SIZE_MB) = params->mc_video_protect_size_mb; - MC(MC_VIDEO_PROTECT_VPR_OVERRIDE) = params->mc_video_protect_vpr_override; - MC(MC_VIDEO_PROTECT_VPR_OVERRIDE1) = params->mc_video_protect_vpr_override1; + MC(MC_VIDEO_PROTECT_BOM) = params->mc_video_protect_bom; + MC(MC_VIDEO_PROTECT_BOM_ADR_HI) = params->mc_video_protect_bom_adr_hi; + MC(MC_VIDEO_PROTECT_SIZE_MB) = params->mc_video_protect_size_mb; + MC(MC_VIDEO_PROTECT_VPR_OVERRIDE) = params->mc_video_protect_vpr_override; + MC(MC_VIDEO_PROTECT_VPR_OVERRIDE1) = params->mc_video_protect_vpr_override1; MC(MC_VIDEO_PROTECT_GPU_OVERRIDE_0) = params->mc_video_protect_gpu_override0; MC(MC_VIDEO_PROTECT_GPU_OVERRIDE_1) = params->mc_video_protect_gpu_override1; // Program SDRAM geometry parameters. - MC(MC_EMEM_ADR_CFG) = params->mc_emem_adr_cfg; - MC(MC_EMEM_ADR_CFG_DEV0) = params->mc_emem_adr_cfg_dev0; - MC(MC_EMEM_ADR_CFG_DEV1) = params->mc_emem_adr_cfg_dev1; + MC(MC_EMEM_ADR_CFG) = params->mc_emem_adr_cfg; + MC(MC_EMEM_ADR_CFG_DEV0) = params->mc_emem_adr_cfg_dev0; + MC(MC_EMEM_ADR_CFG_DEV1) = params->mc_emem_adr_cfg_dev1; MC(MC_EMEM_ADR_CFG_CHANNEL_MASK) = params->mc_emem_adr_cfg_channel_mask; // Program bank swizzling. @@ -418,44 +444,44 @@ break_nosleep: MC(MC_EMEM_CFG) = params->mc_emem_cfg; // Program SEC carveout (base and size). - MC(MC_SEC_CARVEOUT_BOM) = params->mc_sec_carveout_bom; - MC(MC_SEC_CARVEOUT_ADR_HI) = params->mc_sec_carveout_adr_hi; + MC(MC_SEC_CARVEOUT_BOM) = params->mc_sec_carveout_bom; + MC(MC_SEC_CARVEOUT_ADR_HI) = params->mc_sec_carveout_adr_hi; MC(MC_SEC_CARVEOUT_SIZE_MB) = params->mc_sec_carveout_size_mb; // Program MTS carveout (base and size). - MC(MC_MTS_CARVEOUT_BOM) = params->mc_mts_carveout_bom; - MC(MC_MTS_CARVEOUT_ADR_HI) = params->mc_mts_carveout_adr_hi; + MC(MC_MTS_CARVEOUT_BOM) = params->mc_mts_carveout_bom; + MC(MC_MTS_CARVEOUT_ADR_HI) = params->mc_mts_carveout_adr_hi; MC(MC_MTS_CARVEOUT_SIZE_MB) = params->mc_mts_carveout_size_mb; // Program the memory arbiter. - MC(MC_EMEM_ARB_CFG) = params->mc_emem_arb_cfg; + MC(MC_EMEM_ARB_CFG) = params->mc_emem_arb_cfg; MC(MC_EMEM_ARB_OUTSTANDING_REQ) = params->mc_emem_arb_outstanding_req; - MC(MC_EMEM_ARB_REFPB_HP_CTRL) = params->emc_emem_arb_refpb_hp_ctrl; + MC(MC_EMEM_ARB_REFPB_HP_CTRL) = params->emc_emem_arb_refpb_hp_ctrl; MC(MC_EMEM_ARB_REFPB_BANK_CTRL) = params->emc_emem_arb_refpb_bank_ctrl; - MC(MC_EMEM_ARB_TIMING_RCD) = params->mc_emem_arb_timing_rcd; - MC(MC_EMEM_ARB_TIMING_RP) = params->mc_emem_arb_timing_rp; - MC(MC_EMEM_ARB_TIMING_RC) = params->mc_emem_arb_timing_rc; - MC(MC_EMEM_ARB_TIMING_RAS) = params->mc_emem_arb_timing_ras; - MC(MC_EMEM_ARB_TIMING_FAW) = params->mc_emem_arb_timing_faw; - MC(MC_EMEM_ARB_TIMING_RRD) = params->mc_emem_arb_timing_rrd; - MC(MC_EMEM_ARB_TIMING_RAP2PRE) = params->mc_emem_arb_timing_rap2pre; - MC(MC_EMEM_ARB_TIMING_WAP2PRE) = params->mc_emem_arb_timing_wap2pre; - MC(MC_EMEM_ARB_TIMING_R2R) = params->mc_emem_arb_timing_r2r; - MC(MC_EMEM_ARB_TIMING_W2W) = params->mc_emem_arb_timing_w2w; - MC(MC_EMEM_ARB_TIMING_CCDMW) = params->mc_emem_arb_timing_ccdmw; - MC(MC_EMEM_ARB_TIMING_R2W) = params->mc_emem_arb_timing_r2w; - MC(MC_EMEM_ARB_TIMING_W2R) = params->mc_emem_arb_timing_w2r; - MC(MC_EMEM_ARB_TIMING_RFCPB) = params->mc_emem_arb_timing_rfcpb; - MC(MC_EMEM_ARB_DA_TURNS) = params->mc_emem_arb_da_turns; - MC(MC_EMEM_ARB_DA_COVERS) = params->mc_emem_arb_da_covers; - MC(MC_EMEM_ARB_MISC0) = params->mc_emem_arb_misc0; - MC(MC_EMEM_ARB_MISC1) = params->mc_emem_arb_misc1; - MC(MC_EMEM_ARB_MISC2) = params->mc_emem_arb_misc2; - MC(MC_EMEM_ARB_RING1_THROTTLE) = params->mc_emem_arb_ring1_throttle; - MC(MC_EMEM_ARB_OVERRIDE) = params->mc_emem_arb_override; - MC(MC_EMEM_ARB_OVERRIDE_1) = params->mc_emem_arb_override1; - MC(MC_EMEM_ARB_RSV) = params->mc_emem_arb_rsv; - MC(MC_DA_CONFIG0) = params->mc_da_cfg0; + MC(MC_EMEM_ARB_TIMING_RCD) = params->mc_emem_arb_timing_rcd; + MC(MC_EMEM_ARB_TIMING_RP) = params->mc_emem_arb_timing_rp; + MC(MC_EMEM_ARB_TIMING_RC) = params->mc_emem_arb_timing_rc; + MC(MC_EMEM_ARB_TIMING_RAS) = params->mc_emem_arb_timing_ras; + MC(MC_EMEM_ARB_TIMING_FAW) = params->mc_emem_arb_timing_faw; + MC(MC_EMEM_ARB_TIMING_RRD) = params->mc_emem_arb_timing_rrd; + MC(MC_EMEM_ARB_TIMING_RAP2PRE) = params->mc_emem_arb_timing_rap2pre; + MC(MC_EMEM_ARB_TIMING_WAP2PRE) = params->mc_emem_arb_timing_wap2pre; + MC(MC_EMEM_ARB_TIMING_R2R) = params->mc_emem_arb_timing_r2r; + MC(MC_EMEM_ARB_TIMING_W2W) = params->mc_emem_arb_timing_w2w; + MC(MC_EMEM_ARB_TIMING_CCDMW) = params->mc_emem_arb_timing_ccdmw; + MC(MC_EMEM_ARB_TIMING_R2W) = params->mc_emem_arb_timing_r2w; + MC(MC_EMEM_ARB_TIMING_W2R) = params->mc_emem_arb_timing_w2r; + MC(MC_EMEM_ARB_TIMING_RFCPB) = params->mc_emem_arb_timing_rfcpb; + MC(MC_EMEM_ARB_DA_TURNS) = params->mc_emem_arb_da_turns; + MC(MC_EMEM_ARB_DA_COVERS) = params->mc_emem_arb_da_covers; + MC(MC_EMEM_ARB_MISC0) = params->mc_emem_arb_misc0; + MC(MC_EMEM_ARB_MISC1) = params->mc_emem_arb_misc1; + MC(MC_EMEM_ARB_MISC2) = params->mc_emem_arb_misc2; + MC(MC_EMEM_ARB_RING1_THROTTLE) = params->mc_emem_arb_ring1_throttle; + MC(MC_EMEM_ARB_OVERRIDE) = params->mc_emem_arb_override; + MC(MC_EMEM_ARB_OVERRIDE_1) = params->mc_emem_arb_override1; + 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. @@ -480,7 +506,7 @@ break_nosleep: EMC(EMC_AUTO_CAL_VREF_SEL_1) = params->emc_auto_cal_vref_sel1; EMC(EMC_AUTO_CAL_INTERVAL) = params->emc_auto_cal_interval; - EMC(EMC_AUTO_CAL_CONFIG) = params->emc_auto_cal_config; + EMC(EMC_AUTO_CAL_CONFIG) = params->emc_auto_cal_config; usleep(params->emc_auto_cal_wait); // Patch 5 using BCT spare variables. @@ -488,96 +514,96 @@ break_nosleep: *(vu32 *)params->emc_bct_spare8 = params->emc_bct_spare9; // Program EMC timing configuration. - EMC(EMC_CFG_2) = params->emc_cfg2; - EMC(EMC_CFG_PIPE) = params->emc_cfg_pipe; - EMC(EMC_CFG_PIPE_1) = params->emc_cfg_pipe1; - EMC(EMC_CFG_PIPE_2) = params->emc_cfg_pipe2; - EMC(EMC_CMDQ) = params->emc_cmd_q; - EMC(EMC_MC2EMCQ) = params->emc_mc2emc_q; - EMC(EMC_MRS_WAIT_CNT) = params->emc_mrs_wait_cnt; - EMC(EMC_MRS_WAIT_CNT2) = params->emc_mrs_wait_cnt2; - EMC(EMC_FBIO_CFG5) = params->emc_fbio_cfg5; - EMC(EMC_RC) = params->emc_rc; - EMC(EMC_RFC) = params->emc_rfc; - EMC(EMC_RFCPB) = params->emc_rfc_pb; - EMC(EMC_REFCTRL2) = params->emc_ref_ctrl2; - EMC(EMC_RFC_SLR) = params->emc_rfc_slr; - EMC(EMC_RAS) = params->emc_ras; - EMC(EMC_RP) = params->emc_rp; - EMC(EMC_TPPD) = params->emc_tppd; - EMC(EMC_R2R) = params->emc_r2r; - EMC(EMC_W2W) = params->emc_w2w; - EMC(EMC_R2W) = params->emc_r2w; - EMC(EMC_W2R) = params->emc_w2r; - EMC(EMC_R2P) = params->emc_r2p; - EMC(EMC_W2P) = params->emc_w2p; - EMC(EMC_CCDMW) = params->emc_ccdmw; - EMC(EMC_RD_RCD) = params->emc_rd_rcd; - EMC(EMC_WR_RCD) = params->emc_wr_rcd; - EMC(EMC_RRD) = params->emc_rrd; - EMC(EMC_REXT) = params->emc_rext; - EMC(EMC_WEXT) = params->emc_wext; - EMC(EMC_WDV) = params->emc_wdv; - EMC(EMC_WDV_CHK) = params->emc_wdv_chk; - EMC(EMC_WSV) = params->emc_wsv; - EMC(EMC_WEV) = params->emc_wev; - EMC(EMC_WDV_MASK) = params->emc_wdv_mask; - EMC(EMC_WS_DURATION) = params->emc_ws_duration; - EMC(EMC_WE_DURATION) = params->emc_we_duration; - EMC(EMC_QUSE) = params->emc_quse; - EMC(EMC_QUSE_WIDTH) = params->emc_quse_width; - EMC(EMC_IBDLY) = params->emc_ibdly; - EMC(EMC_OBDLY) = params->emc_obdly; - EMC(EMC_EINPUT) = params->emc_einput; + EMC(EMC_CFG_2) = params->emc_cfg2; + EMC(EMC_CFG_PIPE) = params->emc_cfg_pipe; + EMC(EMC_CFG_PIPE_1) = params->emc_cfg_pipe1; + EMC(EMC_CFG_PIPE_2) = params->emc_cfg_pipe2; + EMC(EMC_CMDQ) = params->emc_cmd_q; + EMC(EMC_MC2EMCQ) = params->emc_mc2emc_q; + EMC(EMC_MRS_WAIT_CNT) = params->emc_mrs_wait_cnt; + EMC(EMC_MRS_WAIT_CNT2) = params->emc_mrs_wait_cnt2; + EMC(EMC_FBIO_CFG5) = params->emc_fbio_cfg5; + EMC(EMC_RC) = params->emc_rc; + EMC(EMC_RFC) = params->emc_rfc; + EMC(EMC_RFCPB) = params->emc_rfc_pb; + EMC(EMC_REFCTRL2) = params->emc_ref_ctrl2; + EMC(EMC_RFC_SLR) = params->emc_rfc_slr; + EMC(EMC_RAS) = params->emc_ras; + EMC(EMC_RP) = params->emc_rp; + EMC(EMC_TPPD) = params->emc_tppd; + EMC(EMC_R2R) = params->emc_r2r; + EMC(EMC_W2W) = params->emc_w2w; + EMC(EMC_R2W) = params->emc_r2w; + EMC(EMC_W2R) = params->emc_w2r; + EMC(EMC_R2P) = params->emc_r2p; + EMC(EMC_W2P) = params->emc_w2p; + EMC(EMC_CCDMW) = params->emc_ccdmw; + EMC(EMC_RD_RCD) = params->emc_rd_rcd; + EMC(EMC_WR_RCD) = params->emc_wr_rcd; + EMC(EMC_RRD) = params->emc_rrd; + EMC(EMC_REXT) = params->emc_rext; + EMC(EMC_WEXT) = params->emc_wext; + EMC(EMC_WDV) = params->emc_wdv; + EMC(EMC_WDV_CHK) = params->emc_wdv_chk; + EMC(EMC_WSV) = params->emc_wsv; + EMC(EMC_WEV) = params->emc_wev; + EMC(EMC_WDV_MASK) = params->emc_wdv_mask; + EMC(EMC_WS_DURATION) = params->emc_ws_duration; + EMC(EMC_WE_DURATION) = params->emc_we_duration; + EMC(EMC_QUSE) = params->emc_quse; + EMC(EMC_QUSE_WIDTH) = params->emc_quse_width; + EMC(EMC_IBDLY) = params->emc_ibdly; + EMC(EMC_OBDLY) = params->emc_obdly; + EMC(EMC_EINPUT) = params->emc_einput; EMC(EMC_EINPUT_DURATION) = params->emc_einput_duration; - EMC(EMC_PUTERM_EXTRA) = params->emc_puterm_extra; - EMC(EMC_PUTERM_WIDTH) = params->emc_puterm_width; + EMC(EMC_PUTERM_EXTRA) = params->emc_puterm_extra; + EMC(EMC_PUTERM_WIDTH) = params->emc_puterm_width; EMC(EMC_PMACRO_COMMON_PAD_TX_CTRL) = params->emc_pmacro_common_pad_tx_ctrl; - EMC(EMC_DBG) = params->emc_dbg; - EMC(EMC_QRST) = params->emc_qrst; - EMC(EMC_ISSUE_QRST) = 1; - EMC(EMC_ISSUE_QRST) = 0; - EMC(EMC_QSAFE) = params->emc_qsafe; - EMC(EMC_RDV) = params->emc_rdv; - EMC(EMC_RDV_MASK) = params->emc_rdv_mask; - EMC(EMC_RDV_EARLY) = params->emc_rdv_early; - EMC(EMC_RDV_EARLY_MASK) = params->emc_rdv_early_mask; - EMC(EMC_QPOP) = params->emc_qpop; - EMC(EMC_REFRESH) = params->emc_refresh; - EMC(EMC_BURST_REFRESH_NUM) = params->emc_burst_refresh_num; + EMC(EMC_DBG) = params->emc_dbg; + EMC(EMC_QRST) = params->emc_qrst; + EMC(EMC_ISSUE_QRST) = 1; + EMC(EMC_ISSUE_QRST) = 0; + EMC(EMC_QSAFE) = params->emc_qsafe; + EMC(EMC_RDV) = params->emc_rdv; + EMC(EMC_RDV_MASK) = params->emc_rdv_mask; + EMC(EMC_RDV_EARLY) = params->emc_rdv_early; + EMC(EMC_RDV_EARLY_MASK) = params->emc_rdv_early_mask; + EMC(EMC_QPOP) = params->emc_qpop; + EMC(EMC_REFRESH) = params->emc_refresh; + EMC(EMC_BURST_REFRESH_NUM) = params->emc_burst_refresh_num; EMC(EMC_PRE_REFRESH_REQ_CNT) = params->emc_prerefresh_req_cnt; - EMC(EMC_PDEX2WR) = params->emc_pdex2wr; - EMC(EMC_PDEX2RD) = params->emc_pdex2rd; - EMC(EMC_PCHG2PDEN) = params->emc_pchg2pden; - EMC(EMC_ACT2PDEN) = params->emc_act2pden; - EMC(EMC_AR2PDEN) = params->emc_ar2pden; - EMC(EMC_RW2PDEN) = params->emc_rw2pden; - EMC(EMC_CKE2PDEN) = params->emc_cke2pden; - EMC(EMC_PDEX2CKE) = params->emc_pdex2che; - EMC(EMC_PDEX2MRR) = params->emc_pdex2mrr; - EMC(EMC_TXSR) = params->emc_txsr; - EMC(EMC_TXSRDLL) = params->emc_txsr_dll; - EMC(EMC_TCKE) = params->emc_tcke; - EMC(EMC_TCKESR) = params->emc_tckesr; - EMC(EMC_TPD) = params->emc_tpd; - EMC(EMC_TFAW) = params->emc_tfaw; - EMC(EMC_TRPAB) = params->emc_trpab; - EMC(EMC_TCLKSTABLE) = params->emc_tclkstable; - EMC(EMC_TCLKSTOP) = params->emc_tclkstop; - EMC(EMC_TREFBW) = params->emc_trefbw; - EMC(EMC_ODT_WRITE) = params->emc_odt_write; - EMC(EMC_CFG_DIG_DLL) = params->emc_cfg_dig_dll; - EMC(EMC_CFG_DIG_DLL_PERIOD) = params->emc_cfg_dig_dll_period; + EMC(EMC_PDEX2WR) = params->emc_pdex2wr; + EMC(EMC_PDEX2RD) = params->emc_pdex2rd; + EMC(EMC_PCHG2PDEN) = params->emc_pchg2pden; + EMC(EMC_ACT2PDEN) = params->emc_act2pden; + EMC(EMC_AR2PDEN) = params->emc_ar2pden; + EMC(EMC_RW2PDEN) = params->emc_rw2pden; + EMC(EMC_CKE2PDEN) = params->emc_cke2pden; + EMC(EMC_PDEX2CKE) = params->emc_pdex2che; + EMC(EMC_PDEX2MRR) = params->emc_pdex2mrr; + EMC(EMC_TXSR) = params->emc_txsr; + EMC(EMC_TXSRDLL) = params->emc_txsr_dll; + EMC(EMC_TCKE) = params->emc_tcke; + EMC(EMC_TCKESR) = params->emc_tckesr; + EMC(EMC_TPD) = params->emc_tpd; + EMC(EMC_TFAW) = params->emc_tfaw; + EMC(EMC_TRPAB) = params->emc_trpab; + EMC(EMC_TCLKSTABLE) = params->emc_tclkstable; + EMC(EMC_TCLKSTOP) = params->emc_tclkstop; + EMC(EMC_TREFBW) = params->emc_trefbw; + EMC(EMC_ODT_WRITE) = params->emc_odt_write; + EMC(EMC_CFG_DIG_DLL) = params->emc_cfg_dig_dll; + EMC(EMC_CFG_DIG_DLL_PERIOD) = params->emc_cfg_dig_dll_period; // Don't write CFG_ADR_EN (bit 1) here - lock bit written later. - EMC(EMC_FBIO_SPARE) = params->emc_fbio_spare & 0xFFFFFFFD; - EMC(EMC_CFG_RSV) = params->emc_cfg_rsv; + EMC(EMC_FBIO_SPARE) = params->emc_fbio_spare & 0xFFFFFFFD; + EMC(EMC_CFG_RSV) = params->emc_cfg_rsv; EMC(EMC_PMC_SCRATCH1) = params->emc_pmc_scratch1; EMC(EMC_PMC_SCRATCH2) = params->emc_pmc_scratch2; EMC(EMC_PMC_SCRATCH3) = params->emc_pmc_scratch3; EMC(EMC_ACPD_CONTROL) = params->emc_acpd_control; - EMC(EMC_TXDSRVTTGEN) = params->emc_txdsrvttgen; + EMC(EMC_TXDSRVTTGEN) = params->emc_txdsrvttgen; // Set pipe bypass enable bits before sending any DRAM commands. EMC(EMC_CFG) = (params->emc_cfg & 0xE) | 0x3C00000; @@ -602,13 +628,8 @@ break_nosleep: // ZQ CAL setup (not actually issuing ZQ CAL now). if (params->emc_zcal_warm_cold_boot_enables & 1) { - if (params->memory_type == MEMORY_TYPE_DDR3L) - EMC(EMC_ZCAL_WAIT_CNT) = params->emc_zcal_wait_cnt << 3; - if (params->memory_type == MEMORY_TYPE_LPDDR4) - { - EMC(EMC_ZCAL_WAIT_CNT) = params->emc_zcal_wait_cnt; - EMC(EMC_ZCAL_MRW_CMD) = params->emc_zcal_mrw_cmd; - } + EMC(EMC_ZCAL_WAIT_CNT) = params->emc_zcal_wait_cnt; + EMC(EMC_ZCAL_MRW_CMD) = params->emc_zcal_mrw_cmd; } EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place. @@ -620,68 +641,51 @@ break_nosleep: // Set clock enable signal. u32 pin_gpio_cfg = (params->emc_pin_gpio_enable << 16) | (params->emc_pin_gpio << 12); - if (params->memory_type == MEMORY_TYPE_DDR3L || params->memory_type == MEMORY_TYPE_LPDDR4) - { - EMC(EMC_PIN) = pin_gpio_cfg; - (void)EMC(EMC_PIN); - usleep(params->emc_pin_extra_wait + 200); - EMC(EMC_PIN) = pin_gpio_cfg | 0x100; - (void)EMC(EMC_PIN); - } + EMC(EMC_PIN) = pin_gpio_cfg; + (void)EMC(EMC_PIN); + usleep(params->emc_pin_extra_wait + 200); + EMC(EMC_PIN) = pin_gpio_cfg | 0x100; + (void)EMC(EMC_PIN); - if (params->memory_type == MEMORY_TYPE_LPDDR4) - usleep(params->emc_pin_extra_wait + 2000); - else if (params->memory_type == MEMORY_TYPE_DDR3L) - usleep(params->emc_pin_extra_wait + 500); + usleep(params->emc_pin_extra_wait + 2000); // Enable clock enable signal. EMC(EMC_PIN) = pin_gpio_cfg | 0x101; (void)EMC(EMC_PIN); usleep(params->emc_pin_program_wait); - // Send NOP (trigger just needs to be non-zero). - if (params->memory_type != MEMORY_TYPE_LPDDR4) - EMC(EMC_NOP) = (params->emc_dev_select << 30) + 1; - - // On coldboot w/LPDDR2/3, wait 200 uSec after asserting CKE high. - if (params->memory_type == MEMORY_TYPE_LPDDR2) - usleep(params->emc_pin_extra_wait + 200); - // Init zq calibration, - if (params->memory_type == MEMORY_TYPE_LPDDR4) + // Patch 6 using BCT spare variables. + if (params->emc_bct_spare10) + *(vu32 *)params->emc_bct_spare10 = params->emc_bct_spare11; + + // Write mode registers. + EMC(EMC_MRW2) = params->emc_mrw2; + EMC(EMC_MRW) = params->emc_mrw1; + EMC(EMC_MRW3) = params->emc_mrw3; + EMC(EMC_MRW4) = params->emc_mrw4; + EMC(EMC_MRW6) = params->emc_mrw6; + EMC(EMC_MRW14) = params->emc_mrw14; + + EMC(EMC_MRW8) = params->emc_mrw8; + EMC(EMC_MRW12) = params->emc_mrw12; + EMC(EMC_MRW9) = params->emc_mrw9; + EMC(EMC_MRW13) = params->emc_mrw13; + + if (params->emc_zcal_warm_cold_boot_enables & 1) { - // Patch 6 using BCT spare variables. - if (params->emc_bct_spare10) - *(vu32 *)params->emc_bct_spare10 = params->emc_bct_spare11; + // Issue ZQCAL start, device 0. + EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev0; + usleep(params->emc_zcal_init_wait); - // Write mode registers. - EMC(EMC_MRW2) = params->emc_mrw2; - EMC(EMC_MRW) = params->emc_mrw1; - EMC(EMC_MRW3) = params->emc_mrw3; - EMC(EMC_MRW4) = params->emc_mrw4; - EMC(EMC_MRW6) = params->emc_mrw6; - EMC(EMC_MRW14) = params->emc_mrw14; - - EMC(EMC_MRW8) = params->emc_mrw8; - EMC(EMC_MRW12) = params->emc_mrw12; - EMC(EMC_MRW9) = params->emc_mrw9; - EMC(EMC_MRW13) = params->emc_mrw13; - - if (params->emc_zcal_warm_cold_boot_enables & 1) + // Issue ZQCAL latch. + EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev0 ^ 3; + // Same for device 1. + if (!(params->emc_dev_select & 2)) { - // Issue ZQCAL start, device 0. - EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev0; + EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev1; usleep(params->emc_zcal_init_wait); - - // Issue ZQCAL latch. - EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev0 ^ 3; - // Same for device 1. - if (!(params->emc_dev_select & 2)) - { - EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev1; - usleep(params->emc_zcal_init_wait); - EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev1 ^ 3; - } + EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev1 ^ 3; } } @@ -689,12 +693,9 @@ break_nosleep: PMC(APBDEV_PMC_DDR_CFG) = params->pmc_ddr_cfg; // Start periodic ZQ calibration (LPDDRx only). - if (params->memory_type && params->memory_type <= MEMORY_TYPE_LPDDR4) - { - EMC(EMC_ZCAL_INTERVAL) = params->emc_zcal_interval; - EMC(EMC_ZCAL_WAIT_CNT) = params->emc_zcal_wait_cnt; - EMC(EMC_ZCAL_MRW_CMD) = params->emc_zcal_mrw_cmd; - } + EMC(EMC_ZCAL_INTERVAL) = params->emc_zcal_interval; + EMC(EMC_ZCAL_WAIT_CNT) = params->emc_zcal_wait_cnt; + EMC(EMC_ZCAL_MRW_CMD) = params->emc_zcal_mrw_cmd; // Patch 7 using BCT spare variables. if (params->emc_bct_spare12) @@ -709,11 +710,11 @@ break_nosleep: EMC(EMC_REFCTRL) = params->emc_dev_select | 0x80000000; EMC(EMC_DYN_SELF_REF_CONTROL) = params->emc_dyn_self_ref_control; - EMC(EMC_CFG_UPDATE) = params->emc_cfg_update; - EMC(EMC_CFG) = params->emc_cfg; - EMC(EMC_FDPD_CTRL_DQ) = params->emc_fdpd_ctrl_dq; + EMC(EMC_CFG_UPDATE) = params->emc_cfg_update; + EMC(EMC_CFG) = params->emc_cfg; + EMC(EMC_FDPD_CTRL_DQ) = params->emc_fdpd_ctrl_dq; EMC(EMC_FDPD_CTRL_CMD) = params->emc_fdpd_ctrl_cmd; - EMC(EMC_SEL_DPD_CTRL) = params->emc_sel_dpd_ctrl; + EMC(EMC_SEL_DPD_CTRL) = params->emc_sel_dpd_ctrl; // Write addr swizzle lock bit. EMC(EMC_FBIO_SPARE) = params->emc_fbio_spare | 2; @@ -731,8 +732,8 @@ break_nosleep: // Lock carveouts per BCT cfg. MC(MC_VIDEO_PROTECT_REG_CTRL) = params->mc_video_protect_write_access; - MC(MC_SEC_CARVEOUT_REG_CTRL) = params->mc_sec_carveout_protect_write_access; - MC(MC_MTS_CARVEOUT_REG_CTRL) = params->mc_mts_carveout_reg_ctrl; + MC(MC_SEC_CARVEOUT_REG_CTRL) = params->mc_sec_carveout_protect_write_access; + MC(MC_MTS_CARVEOUT_REG_CTRL) = params->mc_mts_carveout_reg_ctrl; // Disable write access to a bunch of EMC registers. MC(MC_EMEM_CFG_ACCESS_CTRL) = 1; @@ -749,7 +750,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) // Program DPD3/DPD4 regs (coldboot path). // Enable sel_dpd on unused pins. - PMC(APBDEV_PMC_WEAK_BIAS) = (pmc_scratch1 & 0x1000) << 19 | (pmc_scratch1 & 0xFFF) << 18 | (pmc_scratch1 & 0x8000) << 15; + 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) + 0x80000000; usleep(params->pmc_io_dpd3_req_wait); @@ -763,7 +764,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) // Program CMD mapping. Required before brick mapping, else // we can't guarantee CK will be differential at all times. - EMC(EMC_FBIO_CFG7) = params->emc_fbio_cfg7; + EMC(EMC_FBIO_CFG7) = params->emc_fbio_cfg7; EMC(EMC_CMD_MAPPING_CMD0_0) = params->emc_cmd_mapping_cmd0_0; EMC(EMC_CMD_MAPPING_CMD0_1) = params->emc_cmd_mapping_cmd0_1; EMC(EMC_CMD_MAPPING_CMD0_2) = params->emc_cmd_mapping_cmd0_2; @@ -776,7 +777,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) EMC(EMC_CMD_MAPPING_CMD3_0) = params->emc_cmd_mapping_cmd3_0; EMC(EMC_CMD_MAPPING_CMD3_1) = params->emc_cmd_mapping_cmd3_1; EMC(EMC_CMD_MAPPING_CMD3_2) = params->emc_cmd_mapping_cmd3_2; - EMC(EMC_CMD_MAPPING_BYTE) = params->emc_cmd_mapping_byte; + EMC(EMC_CMD_MAPPING_BYTE) = params->emc_cmd_mapping_byte; // Program brick mapping. EMC(EMC_PMACRO_BRICK_MAPPING_0) = params->emc_pmacro_brick_mapping0; @@ -803,7 +804,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) usleep(params->pmc_vddp_sel_wait + 2); // Ensure the regulators settle. // Set clock sources. - CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = params->emc_clock_source; + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = params->emc_clock_source; CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC_DLL) = params->emc_clock_source_dll; // Select EMC write mux. @@ -834,7 +835,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) *(vu32 *)params->emc_bct_spare6 = params->emc_bct_spare7; // Set pad controls. - EMC(EMC_XM2COMPPADCTRL) = params->emc_xm2_comp_pad_ctrl; + 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; @@ -847,51 +848,51 @@ 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; - 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; - EMC(EMC_PMACRO_CMD_TX_DRV) = params->emc_pmacro_cmd_tx_drive; + 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; + EMC(EMC_PMACRO_CMD_TX_DRV) = params->emc_pmacro_cmd_tx_drive; EMC(EMC_PMACRO_AUTOCAL_CFG_COMMON) = params->emc_pmacro_auto_cal_common; - EMC(EMC_AUTO_CAL_CHANNEL) = params->emc_auto_cal_channel; - EMC(EMC_PMACRO_ZCTRL) = params->emc_pmacro_zcrtl; + EMC(EMC_AUTO_CAL_CHANNEL) = params->emc_auto_cal_channel; + EMC(EMC_PMACRO_ZCTRL) = params->emc_pmacro_zcrtl; - EMC(EMC_DLL_CFG_0) = params->emc_dll_cfg0; - EMC(EMC_DLL_CFG_1) = params->emc_dll_cfg1; + 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; 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; - EMC(EMC_DQS_BRLSHFT_1) = params->emc_dqs_brlshft1; - EMC(EMC_CMD_BRLSHFT_0) = params->emc_cmd_brlshft0; - EMC(EMC_CMD_BRLSHFT_1) = params->emc_cmd_brlshft1; - EMC(EMC_CMD_BRLSHFT_2) = params->emc_cmd_brlshft2; - EMC(EMC_CMD_BRLSHFT_3) = params->emc_cmd_brlshft3; + EMC(EMC_DQS_BRLSHFT_0) = params->emc_dqs_brlshft0; + EMC(EMC_DQS_BRLSHFT_1) = params->emc_dqs_brlshft1; + EMC(EMC_CMD_BRLSHFT_0) = params->emc_cmd_brlshft0; + EMC(EMC_CMD_BRLSHFT_1) = params->emc_cmd_brlshft1; + EMC(EMC_CMD_BRLSHFT_2) = params->emc_cmd_brlshft2; + EMC(EMC_CMD_BRLSHFT_3) = params->emc_cmd_brlshft3; EMC(EMC_QUSE_BRLSHFT_0) = params->emc_quse_brlshft0; EMC(EMC_QUSE_BRLSHFT_1) = params->emc_quse_brlshft1; EMC(EMC_QUSE_BRLSHFT_2) = params->emc_quse_brlshft2; EMC(EMC_QUSE_BRLSHFT_3) = params->emc_quse_brlshft3; EMC(EMC_PMACRO_BRICK_CTRL_RFU1) = params->emc_pmacro_brick_ctrl_rfu1; - EMC(EMC_PMACRO_PAD_CFG_CTRL) = params->emc_pmacro_pad_cfg_ctrl; + EMC(EMC_PMACRO_PAD_CFG_CTRL) = params->emc_pmacro_pad_cfg_ctrl; - EMC(EMC_PMACRO_CMD_BRICK_CTRL_FDPD) = params->emc_pmacro_cmd_brick_ctrl_fdpd; - EMC(EMC_PMACRO_BRICK_CTRL_RFU2) = params->emc_pmacro_brick_ctrl_rfu2; + EMC(EMC_PMACRO_CMD_BRICK_CTRL_FDPD) = params->emc_pmacro_cmd_brick_ctrl_fdpd; + EMC(EMC_PMACRO_BRICK_CTRL_RFU2) = params->emc_pmacro_brick_ctrl_rfu2; EMC(EMC_PMACRO_DATA_BRICK_CTRL_FDPD) = params->emc_pmacro_data_brick_ctrl_fdpd; - EMC(EMC_PMACRO_DATA_PAD_RX_CTRL) = params->emc_pmacro_data_pad_rx_ctrl; - EMC(EMC_PMACRO_CMD_PAD_RX_CTRL) = params->emc_pmacro_cmd_pad_rx_ctrl; - EMC(EMC_PMACRO_DATA_PAD_TX_CTRL) = params->emc_pmacro_data_pad_tx_ctrl; - EMC(EMC_PMACRO_DATA_RX_TERM_MODE) = params->emc_pmacro_data_rx_term_mode; - 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; + EMC(EMC_PMACRO_DATA_PAD_RX_CTRL) = params->emc_pmacro_data_pad_rx_ctrl; + EMC(EMC_PMACRO_CMD_PAD_RX_CTRL) = params->emc_pmacro_cmd_pad_rx_ctrl; + EMC(EMC_PMACRO_DATA_PAD_TX_CTRL) = params->emc_pmacro_data_pad_tx_ctrl; + EMC(EMC_PMACRO_DATA_RX_TERM_MODE) = params->emc_pmacro_data_rx_term_mode; + 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; - 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; - EMC(EMC_PMACRO_TX_PWRD_2) = params->emc_pmacro_tx_pwrd2; - EMC(EMC_PMACRO_TX_PWRD_3) = params->emc_pmacro_tx_pwrd3; - EMC(EMC_PMACRO_TX_PWRD_4) = params->emc_pmacro_tx_pwrd4; - EMC(EMC_PMACRO_TX_PWRD_5) = params->emc_pmacro_tx_pwrd5; + 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; + EMC(EMC_PMACRO_TX_PWRD_2) = params->emc_pmacro_tx_pwrd2; + EMC(EMC_PMACRO_TX_PWRD_3) = params->emc_pmacro_tx_pwrd3; + EMC(EMC_PMACRO_TX_PWRD_4) = params->emc_pmacro_tx_pwrd4; + EMC(EMC_PMACRO_TX_PWRD_5) = params->emc_pmacro_tx_pwrd5; EMC(EMC_PMACRO_TX_SEL_CLK_SRC_0) = params->emc_pmacro_tx_sel_clk_src0; EMC(EMC_PMACRO_TX_SEL_CLK_SRC_1) = params->emc_pmacro_tx_sel_clk_src1; EMC(EMC_PMACRO_TX_SEL_CLK_SRC_2) = params->emc_pmacro_tx_sel_clk_src2; @@ -906,33 +907,33 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) EMC(EMC_PMACRO_PERBIT_FGCG_CTRL_3) = params->emc_pmacro_perbit_fgcg_ctrl3; EMC(EMC_PMACRO_PERBIT_FGCG_CTRL_4) = params->emc_pmacro_perbit_fgcg_ctrl4; EMC(EMC_PMACRO_PERBIT_FGCG_CTRL_5) = params->emc_pmacro_perbit_fgcg_ctrl5; - EMC(EMC_PMACRO_PERBIT_RFU_CTRL_0) = params->emc_pmacro_perbit_rfu_ctrl0; - EMC(EMC_PMACRO_PERBIT_RFU_CTRL_1) = params->emc_pmacro_perbit_rfu_ctrl1; - EMC(EMC_PMACRO_PERBIT_RFU_CTRL_2) = params->emc_pmacro_perbit_rfu_ctrl2; - EMC(EMC_PMACRO_PERBIT_RFU_CTRL_3) = params->emc_pmacro_perbit_rfu_ctrl3; - EMC(EMC_PMACRO_PERBIT_RFU_CTRL_4) = params->emc_pmacro_perbit_rfu_ctrl4; - EMC(EMC_PMACRO_PERBIT_RFU_CTRL_5) = params->emc_pmacro_perbit_rfu_ctrl5; + EMC(EMC_PMACRO_PERBIT_RFU_CTRL_0) = params->emc_pmacro_perbit_rfu_ctrl0; + EMC(EMC_PMACRO_PERBIT_RFU_CTRL_1) = params->emc_pmacro_perbit_rfu_ctrl1; + EMC(EMC_PMACRO_PERBIT_RFU_CTRL_2) = params->emc_pmacro_perbit_rfu_ctrl2; + EMC(EMC_PMACRO_PERBIT_RFU_CTRL_3) = params->emc_pmacro_perbit_rfu_ctrl3; + EMC(EMC_PMACRO_PERBIT_RFU_CTRL_4) = params->emc_pmacro_perbit_rfu_ctrl4; + EMC(EMC_PMACRO_PERBIT_RFU_CTRL_5) = params->emc_pmacro_perbit_rfu_ctrl5; EMC(EMC_PMACRO_PERBIT_RFU1_CTRL_0) = params->emc_pmacro_perbit_rfu1_ctrl0; EMC(EMC_PMACRO_PERBIT_RFU1_CTRL_1) = params->emc_pmacro_perbit_rfu1_ctrl1; EMC(EMC_PMACRO_PERBIT_RFU1_CTRL_2) = params->emc_pmacro_perbit_rfu1_ctrl2; EMC(EMC_PMACRO_PERBIT_RFU1_CTRL_3) = params->emc_pmacro_perbit_rfu1_ctrl3; EMC(EMC_PMACRO_PERBIT_RFU1_CTRL_4) = params->emc_pmacro_perbit_rfu1_ctrl4; EMC(EMC_PMACRO_PERBIT_RFU1_CTRL_5) = params->emc_pmacro_perbit_rfu1_ctrl5; - EMC(EMC_PMACRO_DATA_PI_CTRL) = params->emc_pmacro_data_pi_ctrl; - EMC(EMC_PMACRO_CMD_PI_CTRL) = params->emc_pmacro_cmd_pi_ctrl; + EMC(EMC_PMACRO_DATA_PI_CTRL) = params->emc_pmacro_data_pi_ctrl; + EMC(EMC_PMACRO_CMD_PI_CTRL) = params->emc_pmacro_cmd_pi_ctrl; - EMC(EMC_PMACRO_DDLL_BYPASS) = params->emc_pmacro_ddll_bypass; - EMC(EMC_PMACRO_DDLL_PWRD_0) = params->emc_pmacro_ddll_pwrd0; - EMC(EMC_PMACRO_DDLL_PWRD_1) = params->emc_pmacro_ddll_pwrd1; - EMC(EMC_PMACRO_DDLL_PWRD_2) = params->emc_pmacro_ddll_pwrd2; - 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; - 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_DDLL_BYPASS) = params->emc_pmacro_ddll_bypass; + EMC(EMC_PMACRO_DDLL_PWRD_0) = params->emc_pmacro_ddll_pwrd0; + EMC(EMC_PMACRO_DDLL_PWRD_1) = params->emc_pmacro_ddll_pwrd1; + EMC(EMC_PMACRO_DDLL_PWRD_2) = params->emc_pmacro_ddll_pwrd2; + 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; + 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; + EMC(EMC_PMACRO_IB_RXRT) = params->emc_pmacro_ib_rxrt; 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; @@ -981,11 +982,11 @@ 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; - 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; - EMC(EMC_PMACRO_DDLL_LONG_CMD_3) = params->emc_pmacro_ddll_long_cmd_3; - EMC(EMC_PMACRO_DDLL_LONG_CMD_4) = params->emc_pmacro_ddll_long_cmd_4; + 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; + EMC(EMC_PMACRO_DDLL_LONG_CMD_3) = params->emc_pmacro_ddll_long_cmd_3; + EMC(EMC_PMACRO_DDLL_LONG_CMD_4) = params->emc_pmacro_ddll_long_cmd_4; EMC(EMC_PMACRO_DDLL_SHORT_CMD_0) = params->emc_pmacro_ddll_short_cmd_0; EMC(EMC_PMACRO_DDLL_SHORT_CMD_1) = params->emc_pmacro_ddll_short_cmd_1; EMC(EMC_PMACRO_DDLL_SHORT_CMD_2) = params->emc_pmacro_ddll_short_cmd_2; @@ -999,27 +1000,27 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) // Patch 4 to 6 using BCT spare secure variables. if (params->emc_bct_spare_secure6) - *(vu32 *)params->emc_bct_spare_secure6 = params->emc_bct_spare_secure7; + *(vu32 *)params->emc_bct_spare_secure6 = params->emc_bct_spare_secure7; if (params->emc_bct_spare_secure8) - *(vu32 *)params->emc_bct_spare_secure8 = params->emc_bct_spare_secure9; + *(vu32 *)params->emc_bct_spare_secure8 = params->emc_bct_spare_secure9; 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. // Initialize MC VPR settings. - MC(MC_VIDEO_PROTECT_BOM) = params->mc_video_protect_bom; - MC(MC_VIDEO_PROTECT_BOM_ADR_HI) = params->mc_video_protect_bom_adr_hi; - MC(MC_VIDEO_PROTECT_SIZE_MB) = params->mc_video_protect_size_mb; - MC(MC_VIDEO_PROTECT_VPR_OVERRIDE) = params->mc_video_protect_vpr_override; - MC(MC_VIDEO_PROTECT_VPR_OVERRIDE1) = params->mc_video_protect_vpr_override1; + MC(MC_VIDEO_PROTECT_BOM) = params->mc_video_protect_bom; + MC(MC_VIDEO_PROTECT_BOM_ADR_HI) = params->mc_video_protect_bom_adr_hi; + MC(MC_VIDEO_PROTECT_SIZE_MB) = params->mc_video_protect_size_mb; + MC(MC_VIDEO_PROTECT_VPR_OVERRIDE) = params->mc_video_protect_vpr_override; + MC(MC_VIDEO_PROTECT_VPR_OVERRIDE1) = params->mc_video_protect_vpr_override1; MC(MC_VIDEO_PROTECT_GPU_OVERRIDE_0) = params->mc_video_protect_gpu_override0; MC(MC_VIDEO_PROTECT_GPU_OVERRIDE_1) = params->mc_video_protect_gpu_override1; // Program SDRAM geometry parameters. - MC(MC_EMEM_ADR_CFG) = params->mc_emem_adr_cfg; - MC(MC_EMEM_ADR_CFG_DEV0) = params->mc_emem_adr_cfg_dev0; - MC(MC_EMEM_ADR_CFG_DEV1) = params->mc_emem_adr_cfg_dev1; + MC(MC_EMEM_ADR_CFG) = params->mc_emem_adr_cfg; + MC(MC_EMEM_ADR_CFG_DEV0) = params->mc_emem_adr_cfg_dev0; + MC(MC_EMEM_ADR_CFG_DEV1) = params->mc_emem_adr_cfg_dev1; MC(MC_EMEM_ADR_CFG_CHANNEL_MASK) = params->mc_emem_adr_cfg_channel_mask; // Program bank swizzling. @@ -1031,44 +1032,44 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) MC(MC_EMEM_CFG) = params->mc_emem_cfg; // Program SEC carveout (base and size). - MC(MC_SEC_CARVEOUT_BOM) = params->mc_sec_carveout_bom; - MC(MC_SEC_CARVEOUT_ADR_HI) = params->mc_sec_carveout_adr_hi; + MC(MC_SEC_CARVEOUT_BOM) = params->mc_sec_carveout_bom; + MC(MC_SEC_CARVEOUT_ADR_HI) = params->mc_sec_carveout_adr_hi; MC(MC_SEC_CARVEOUT_SIZE_MB) = params->mc_sec_carveout_size_mb; // Program MTS carveout (base and size). - MC(MC_MTS_CARVEOUT_BOM) = params->mc_mts_carveout_bom; - MC(MC_MTS_CARVEOUT_ADR_HI) = params->mc_mts_carveout_adr_hi; + MC(MC_MTS_CARVEOUT_BOM) = params->mc_mts_carveout_bom; + MC(MC_MTS_CARVEOUT_ADR_HI) = params->mc_mts_carveout_adr_hi; MC(MC_MTS_CARVEOUT_SIZE_MB) = params->mc_mts_carveout_size_mb; // Program the memory arbiter. - MC(MC_EMEM_ARB_CFG) = params->mc_emem_arb_cfg; + MC(MC_EMEM_ARB_CFG) = params->mc_emem_arb_cfg; MC(MC_EMEM_ARB_OUTSTANDING_REQ) = params->mc_emem_arb_outstanding_req; - MC(MC_EMEM_ARB_REFPB_HP_CTRL) = params->emc_emem_arb_refpb_hp_ctrl; + MC(MC_EMEM_ARB_REFPB_HP_CTRL) = params->emc_emem_arb_refpb_hp_ctrl; MC(MC_EMEM_ARB_REFPB_BANK_CTRL) = params->emc_emem_arb_refpb_bank_ctrl; - MC(MC_EMEM_ARB_TIMING_RCD) = params->mc_emem_arb_timing_rcd; - MC(MC_EMEM_ARB_TIMING_RP) = params->mc_emem_arb_timing_rp; - MC(MC_EMEM_ARB_TIMING_RC) = params->mc_emem_arb_timing_rc; - MC(MC_EMEM_ARB_TIMING_RAS) = params->mc_emem_arb_timing_ras; - MC(MC_EMEM_ARB_TIMING_FAW) = params->mc_emem_arb_timing_faw; - MC(MC_EMEM_ARB_TIMING_RRD) = params->mc_emem_arb_timing_rrd; - MC(MC_EMEM_ARB_TIMING_RAP2PRE) = params->mc_emem_arb_timing_rap2pre; - MC(MC_EMEM_ARB_TIMING_WAP2PRE) = params->mc_emem_arb_timing_wap2pre; - MC(MC_EMEM_ARB_TIMING_R2R) = params->mc_emem_arb_timing_r2r; - MC(MC_EMEM_ARB_TIMING_W2W) = params->mc_emem_arb_timing_w2w; - MC(MC_EMEM_ARB_TIMING_CCDMW) = params->mc_emem_arb_timing_ccdmw; - MC(MC_EMEM_ARB_TIMING_R2W) = params->mc_emem_arb_timing_r2w; - MC(MC_EMEM_ARB_TIMING_W2R) = params->mc_emem_arb_timing_w2r; - MC(MC_EMEM_ARB_TIMING_RFCPB) = params->mc_emem_arb_timing_rfcpb; - MC(MC_EMEM_ARB_DA_TURNS) = params->mc_emem_arb_da_turns; - MC(MC_EMEM_ARB_DA_COVERS) = params->mc_emem_arb_da_covers; - MC(MC_EMEM_ARB_MISC0) = params->mc_emem_arb_misc0; - MC(MC_EMEM_ARB_MISC1) = params->mc_emem_arb_misc1; - MC(MC_EMEM_ARB_MISC2) = params->mc_emem_arb_misc2; - MC(MC_EMEM_ARB_RING1_THROTTLE) = params->mc_emem_arb_ring1_throttle; - MC(MC_EMEM_ARB_OVERRIDE) = params->mc_emem_arb_override; - MC(MC_EMEM_ARB_OVERRIDE_1) = params->mc_emem_arb_override1; - MC(MC_EMEM_ARB_RSV) = params->mc_emem_arb_rsv; - MC(MC_DA_CONFIG0) = params->mc_da_cfg0; + MC(MC_EMEM_ARB_TIMING_RCD) = params->mc_emem_arb_timing_rcd; + MC(MC_EMEM_ARB_TIMING_RP) = params->mc_emem_arb_timing_rp; + MC(MC_EMEM_ARB_TIMING_RC) = params->mc_emem_arb_timing_rc; + MC(MC_EMEM_ARB_TIMING_RAS) = params->mc_emem_arb_timing_ras; + MC(MC_EMEM_ARB_TIMING_FAW) = params->mc_emem_arb_timing_faw; + MC(MC_EMEM_ARB_TIMING_RRD) = params->mc_emem_arb_timing_rrd; + MC(MC_EMEM_ARB_TIMING_RAP2PRE) = params->mc_emem_arb_timing_rap2pre; + MC(MC_EMEM_ARB_TIMING_WAP2PRE) = params->mc_emem_arb_timing_wap2pre; + MC(MC_EMEM_ARB_TIMING_R2R) = params->mc_emem_arb_timing_r2r; + MC(MC_EMEM_ARB_TIMING_W2W) = params->mc_emem_arb_timing_w2w; + MC(MC_EMEM_ARB_TIMING_CCDMW) = params->mc_emem_arb_timing_ccdmw; + MC(MC_EMEM_ARB_TIMING_R2W) = params->mc_emem_arb_timing_r2w; + MC(MC_EMEM_ARB_TIMING_W2R) = params->mc_emem_arb_timing_w2r; + MC(MC_EMEM_ARB_TIMING_RFCPB) = params->mc_emem_arb_timing_rfcpb; + MC(MC_EMEM_ARB_DA_TURNS) = params->mc_emem_arb_da_turns; + MC(MC_EMEM_ARB_DA_COVERS) = params->mc_emem_arb_da_covers; + MC(MC_EMEM_ARB_MISC0) = params->mc_emem_arb_misc0; + MC(MC_EMEM_ARB_MISC1) = params->mc_emem_arb_misc1; + MC(MC_EMEM_ARB_MISC2) = params->mc_emem_arb_misc2; + MC(MC_EMEM_ARB_RING1_THROTTLE) = params->mc_emem_arb_ring1_throttle; + MC(MC_EMEM_ARB_OVERRIDE) = params->mc_emem_arb_override; + MC(MC_EMEM_ARB_OVERRIDE_1) = params->mc_emem_arb_override1; + 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. @@ -1093,7 +1094,7 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) EMC(EMC_AUTO_CAL_VREF_SEL_1) = params->emc_auto_cal_vref_sel1; EMC(EMC_AUTO_CAL_INTERVAL) = params->emc_auto_cal_interval; - EMC(EMC_AUTO_CAL_CONFIG) = params->emc_auto_cal_config; + EMC(EMC_AUTO_CAL_CONFIG) = params->emc_auto_cal_config; usleep(params->emc_auto_cal_wait); // Patch 5 using BCT spare variables. @@ -1103,99 +1104,100 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) EMC(EMC_AUTO_CAL_CONFIG9) = params->emc_auto_cal_config9; // Program EMC timing configuration. - EMC(EMC_CFG_2) = params->emc_cfg2; - EMC(EMC_CFG_PIPE) = params->emc_cfg_pipe; - EMC(EMC_CFG_PIPE_1) = params->emc_cfg_pipe1; - EMC(EMC_CFG_PIPE_2) = params->emc_cfg_pipe2; - EMC(EMC_CMDQ) = params->emc_cmd_q; - EMC(EMC_MC2EMCQ) = params->emc_mc2emc_q; - EMC(EMC_MRS_WAIT_CNT) = params->emc_mrs_wait_cnt; - EMC(EMC_MRS_WAIT_CNT2) = params->emc_mrs_wait_cnt2; - EMC(EMC_FBIO_CFG5) = params->emc_fbio_cfg5; - EMC(EMC_RC) = params->emc_rc; - EMC(EMC_RFC) = params->emc_rfc; - EMC(EMC_RFCPB) = params->emc_rfc_pb; - EMC(EMC_REFCTRL2) = params->emc_ref_ctrl2; - EMC(EMC_RFC_SLR) = params->emc_rfc_slr; - EMC(EMC_RAS) = params->emc_ras; - EMC(EMC_RP) = params->emc_rp; - EMC(EMC_TPPD) = params->emc_tppd; - EMC(EMC_CTT) = params->emc_trtm; - EMC(EMC_FBIO_TWTM) = params->emc_twtm; - EMC(EMC_FBIO_TRATM) = params->emc_tratm; - EMC(EMC_FBIO_TWATM) = params->emc_twatm; - EMC(EMC_FBIO_TR2REF) = params->emc_tr2ref; - EMC(EMC_R2R) = params->emc_r2r; - EMC(EMC_W2W) = params->emc_w2w; - EMC(EMC_R2W) = params->emc_r2w; - EMC(EMC_W2R) = params->emc_w2r; - EMC(EMC_R2P) = params->emc_r2p; - EMC(EMC_W2P) = params->emc_w2p; - EMC(EMC_CCDMW) = params->emc_ccdmw; - EMC(EMC_RD_RCD) = params->emc_rd_rcd; - EMC(EMC_WR_RCD) = params->emc_wr_rcd; - EMC(EMC_RRD) = params->emc_rrd; - EMC(EMC_REXT) = params->emc_rext; - EMC(EMC_WEXT) = params->emc_wext; - EMC(EMC_WDV) = params->emc_wdv; - EMC(EMC_WDV_CHK) = params->emc_wdv_chk; - EMC(EMC_WSV) = params->emc_wsv; - EMC(EMC_WEV) = params->emc_wev; - EMC(EMC_WDV_MASK) = params->emc_wdv_mask; - EMC(EMC_WS_DURATION) = params->emc_ws_duration; - EMC(EMC_WE_DURATION) = params->emc_we_duration; - EMC(EMC_QUSE) = params->emc_quse; - EMC(EMC_QUSE_WIDTH) = params->emc_quse_width; - EMC(EMC_IBDLY) = params->emc_ibdly; - EMC(EMC_OBDLY) = params->emc_obdly; - EMC(EMC_EINPUT) = params->emc_einput; + EMC(EMC_CFG_2) = params->emc_cfg2; + EMC(EMC_CFG_PIPE) = params->emc_cfg_pipe; + EMC(EMC_CFG_PIPE_1) = params->emc_cfg_pipe1; + EMC(EMC_CFG_PIPE_2) = params->emc_cfg_pipe2; + EMC(EMC_CMDQ) = params->emc_cmd_q; + EMC(EMC_MC2EMCQ) = params->emc_mc2emc_q; + EMC(EMC_MRS_WAIT_CNT) = params->emc_mrs_wait_cnt; + EMC(EMC_MRS_WAIT_CNT2) = params->emc_mrs_wait_cnt2; + EMC(EMC_FBIO_CFG5) = params->emc_fbio_cfg5; + EMC(EMC_RC) = params->emc_rc; + EMC(EMC_RFC) = params->emc_rfc; + EMC(EMC_RFCPB) = params->emc_rfc_pb; + EMC(EMC_REFCTRL2) = params->emc_ref_ctrl2; + EMC(EMC_RFC_SLR) = params->emc_rfc_slr; + EMC(EMC_RAS) = params->emc_ras; + EMC(EMC_RP) = params->emc_rp; + EMC(EMC_TPPD) = params->emc_tppd; + EMC(EMC_CTT) = params->emc_trtm; + EMC(EMC_FBIO_TWTM) = params->emc_twtm; + EMC(EMC_FBIO_TRATM) = params->emc_tratm; + EMC(EMC_FBIO_TWATM) = params->emc_twatm; + EMC(EMC_FBIO_TR2REF) = params->emc_tr2ref; + EMC(EMC_R2R) = params->emc_r2r; + EMC(EMC_W2W) = params->emc_w2w; + EMC(EMC_R2W) = params->emc_r2w; + EMC(EMC_W2R) = params->emc_w2r; + EMC(EMC_R2P) = params->emc_r2p; + EMC(EMC_W2P) = params->emc_w2p; + EMC(EMC_CCDMW) = params->emc_ccdmw; + EMC(EMC_RD_RCD) = params->emc_rd_rcd; + EMC(EMC_WR_RCD) = params->emc_wr_rcd; + EMC(EMC_RRD) = params->emc_rrd; + EMC(EMC_REXT) = params->emc_rext; + EMC(EMC_WEXT) = params->emc_wext; + EMC(EMC_WDV) = params->emc_wdv; + EMC(EMC_WDV_CHK) = params->emc_wdv_chk; + EMC(EMC_WSV) = params->emc_wsv; + EMC(EMC_WEV) = params->emc_wev; + EMC(EMC_WDV_MASK) = params->emc_wdv_mask; + EMC(EMC_WS_DURATION) = params->emc_ws_duration; + EMC(EMC_WE_DURATION) = params->emc_we_duration; + EMC(EMC_QUSE) = params->emc_quse; + EMC(EMC_QUSE_WIDTH) = params->emc_quse_width; + EMC(EMC_IBDLY) = params->emc_ibdly; + EMC(EMC_OBDLY) = params->emc_obdly; + EMC(EMC_EINPUT) = params->emc_einput; EMC(EMC_EINPUT_DURATION) = params->emc_einput_duration; - EMC(EMC_PUTERM_EXTRA) = params->emc_puterm_extra; - EMC(EMC_PUTERM_WIDTH) = params->emc_puterm_width; - EMC(EMC_DBG) = params->emc_dbg; - EMC(EMC_QRST) = params->emc_qrst; - EMC(EMC_ISSUE_QRST) = 1; - EMC(EMC_ISSUE_QRST) = 0; - EMC(EMC_QSAFE) = params->emc_qsafe; - EMC(EMC_RDV) = params->emc_rdv; - EMC(EMC_RDV_MASK) = params->emc_rdv_mask; - EMC(EMC_RDV_EARLY) = params->emc_rdv_early; - EMC(EMC_RDV_EARLY_MASK) = params->emc_rdv_early_mask; - EMC(EMC_QPOP) = params->emc_qpop; - EMC(EMC_REFRESH) = params->emc_refresh; - EMC(EMC_BURST_REFRESH_NUM) = params->emc_burst_refresh_num; + EMC(EMC_PUTERM_EXTRA) = params->emc_puterm_extra; + EMC(EMC_PUTERM_WIDTH) = params->emc_puterm_width; + + EMC(EMC_DBG) = params->emc_dbg; + EMC(EMC_QRST) = params->emc_qrst; + EMC(EMC_ISSUE_QRST) = 1; + EMC(EMC_ISSUE_QRST) = 0; + EMC(EMC_QSAFE) = params->emc_qsafe; + EMC(EMC_RDV) = params->emc_rdv; + EMC(EMC_RDV_MASK) = params->emc_rdv_mask; + EMC(EMC_RDV_EARLY) = params->emc_rdv_early; + EMC(EMC_RDV_EARLY_MASK) = params->emc_rdv_early_mask; + EMC(EMC_QPOP) = params->emc_qpop; + EMC(EMC_REFRESH) = params->emc_refresh; + EMC(EMC_BURST_REFRESH_NUM) = params->emc_burst_refresh_num; EMC(EMC_PRE_REFRESH_REQ_CNT) = params->emc_prerefresh_req_cnt; - EMC(EMC_PDEX2WR) = params->emc_pdex2wr; - EMC(EMC_PDEX2RD) = params->emc_pdex2rd; - EMC(EMC_PCHG2PDEN) = params->emc_pchg2pden; - EMC(EMC_ACT2PDEN) = params->emc_act2pden; - EMC(EMC_AR2PDEN) = params->emc_ar2pden; - EMC(EMC_RW2PDEN) = params->emc_rw2pden; - EMC(EMC_CKE2PDEN) = params->emc_cke2pden; - EMC(EMC_PDEX2CKE) = params->emc_pdex2che; - EMC(EMC_PDEX2MRR) = params->emc_pdex2mrr; - EMC(EMC_TXSR) = params->emc_txsr; - EMC(EMC_TXSRDLL) = params->emc_txsr_dll; - EMC(EMC_TCKE) = params->emc_tcke; - EMC(EMC_TCKESR) = params->emc_tckesr; - EMC(EMC_TPD) = params->emc_tpd; - EMC(EMC_TFAW) = params->emc_tfaw; - EMC(EMC_TRPAB) = params->emc_trpab; - EMC(EMC_TCLKSTABLE) = params->emc_tclkstable; - EMC(EMC_TCLKSTOP) = params->emc_tclkstop; - EMC(EMC_TREFBW) = params->emc_trefbw; - EMC(EMC_ODT_WRITE) = params->emc_odt_write; - EMC(EMC_CFG_DIG_DLL) = params->emc_cfg_dig_dll; - EMC(EMC_CFG_DIG_DLL_PERIOD) = params->emc_cfg_dig_dll_period; + EMC(EMC_PDEX2WR) = params->emc_pdex2wr; + EMC(EMC_PDEX2RD) = params->emc_pdex2rd; + EMC(EMC_PCHG2PDEN) = params->emc_pchg2pden; + EMC(EMC_ACT2PDEN) = params->emc_act2pden; + EMC(EMC_AR2PDEN) = params->emc_ar2pden; + EMC(EMC_RW2PDEN) = params->emc_rw2pden; + EMC(EMC_CKE2PDEN) = params->emc_cke2pden; + EMC(EMC_PDEX2CKE) = params->emc_pdex2che; + EMC(EMC_PDEX2MRR) = params->emc_pdex2mrr; + EMC(EMC_TXSR) = params->emc_txsr; + EMC(EMC_TXSRDLL) = params->emc_txsr_dll; + EMC(EMC_TCKE) = params->emc_tcke; + EMC(EMC_TCKESR) = params->emc_tckesr; + EMC(EMC_TPD) = params->emc_tpd; + EMC(EMC_TFAW) = params->emc_tfaw; + EMC(EMC_TRPAB) = params->emc_trpab; + EMC(EMC_TCLKSTABLE) = params->emc_tclkstable; + EMC(EMC_TCLKSTOP) = params->emc_tclkstop; + EMC(EMC_TREFBW) = params->emc_trefbw; + EMC(EMC_ODT_WRITE) = params->emc_odt_write; + EMC(EMC_CFG_DIG_DLL) = params->emc_cfg_dig_dll; + EMC(EMC_CFG_DIG_DLL_PERIOD) = params->emc_cfg_dig_dll_period; // Don't write CFG_ADR_EN (bit 1) here - lock bit written later. - EMC(EMC_FBIO_SPARE) = params->emc_fbio_spare & 0xFFFFFFFD; - EMC(EMC_CFG_RSV) = params->emc_cfg_rsv; + EMC(EMC_FBIO_SPARE) = params->emc_fbio_spare & 0xFFFFFFFD; + EMC(EMC_CFG_RSV) = params->emc_cfg_rsv; EMC(EMC_PMC_SCRATCH1) = params->emc_pmc_scratch1; EMC(EMC_PMC_SCRATCH2) = params->emc_pmc_scratch2; EMC(EMC_PMC_SCRATCH3) = params->emc_pmc_scratch3; EMC(EMC_ACPD_CONTROL) = params->emc_acpd_control; - EMC(EMC_TXDSRVTTGEN) = params->emc_txdsrvttgen; + EMC(EMC_TXDSRVTTGEN) = params->emc_txdsrvttgen; EMC(EMC_PMACRO_DSR_VTTGEN_CTRL0) = params->emc_pmacro_dsr_vttgen_ctrl0; // Set pipe bypass enable bits before sending any DRAM commands. @@ -1226,13 +1228,8 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) // ZQ CAL setup (not actually issuing ZQ CAL now). if (params->emc_zcal_warm_cold_boot_enables & 1) { - if (params->memory_type == MEMORY_TYPE_DDR3L) - EMC(EMC_ZCAL_WAIT_CNT) = params->emc_zcal_wait_cnt << 3; - if (params->memory_type == MEMORY_TYPE_LPDDR4) - { - EMC(EMC_ZCAL_WAIT_CNT) = params->emc_zcal_wait_cnt; - EMC(EMC_ZCAL_MRW_CMD) = params->emc_zcal_mrw_cmd; - } + EMC(EMC_ZCAL_WAIT_CNT) = params->emc_zcal_wait_cnt; + EMC(EMC_ZCAL_MRW_CMD) = params->emc_zcal_mrw_cmd; } EMC(EMC_TIMING_CONTROL) = 1; // Trigger timing update so above writes take place. @@ -1244,68 +1241,51 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) // Set clock enable signal. u32 pin_gpio_cfg = (params->emc_pin_gpio_enable << 16) | (params->emc_pin_gpio << 12); - if (params->memory_type == MEMORY_TYPE_DDR3L || params->memory_type == MEMORY_TYPE_LPDDR4) - { - EMC(EMC_PIN) = pin_gpio_cfg; - (void)EMC(EMC_PIN); - usleep(params->emc_pin_extra_wait + 200); - EMC(EMC_PIN) = pin_gpio_cfg | 0x100; - (void)EMC(EMC_PIN); - } + EMC(EMC_PIN) = pin_gpio_cfg; + (void)EMC(EMC_PIN); + usleep(params->emc_pin_extra_wait + 200); + EMC(EMC_PIN) = pin_gpio_cfg | 0x100; + (void)EMC(EMC_PIN); - if (params->memory_type == MEMORY_TYPE_LPDDR4) - usleep(params->emc_pin_extra_wait + 2000); - else if (params->memory_type == MEMORY_TYPE_DDR3L) - usleep(params->emc_pin_extra_wait + 500); + usleep(params->emc_pin_extra_wait + 2000); // Enable clock enable signal. EMC(EMC_PIN) = pin_gpio_cfg | 0x101; (void)EMC(EMC_PIN); usleep(params->emc_pin_program_wait); - // Send NOP (trigger just needs to be non-zero). - if (params->memory_type != MEMORY_TYPE_LPDDR4) - EMC(EMC_NOP) = (params->emc_dev_select << 30) + 1; - - // On coldboot w/LPDDR2/3, wait 200 uSec after asserting CKE high. - if (params->memory_type == MEMORY_TYPE_LPDDR2) - usleep(params->emc_pin_extra_wait + 200); - // Init zq calibration, - if (params->memory_type == MEMORY_TYPE_LPDDR4) + // Patch 6 using BCT spare variables. + if (params->emc_bct_spare10) + *(vu32 *)params->emc_bct_spare10 = params->emc_bct_spare11; + + // Write mode registers. + EMC(EMC_MRW2) = params->emc_mrw2; + EMC(EMC_MRW) = params->emc_mrw1; + EMC(EMC_MRW3) = params->emc_mrw3; + EMC(EMC_MRW4) = params->emc_mrw4; + EMC(EMC_MRW6) = params->emc_mrw6; + EMC(EMC_MRW14) = params->emc_mrw14; + + EMC(EMC_MRW8) = params->emc_mrw8; + EMC(EMC_MRW12) = params->emc_mrw12; + EMC(EMC_MRW9) = params->emc_mrw9; + EMC(EMC_MRW13) = params->emc_mrw13; + + if (params->emc_zcal_warm_cold_boot_enables & 1) { - // Patch 6 using BCT spare variables. - if (params->emc_bct_spare10) - *(vu32 *)params->emc_bct_spare10 = params->emc_bct_spare11; + // Issue ZQCAL start, device 0. + EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev0; + usleep(params->emc_zcal_init_wait); - // Write mode registers. - EMC(EMC_MRW2) = params->emc_mrw2; - EMC(EMC_MRW) = params->emc_mrw1; - EMC(EMC_MRW3) = params->emc_mrw3; - EMC(EMC_MRW4) = params->emc_mrw4; - EMC(EMC_MRW6) = params->emc_mrw6; - EMC(EMC_MRW14) = params->emc_mrw14; - - EMC(EMC_MRW8) = params->emc_mrw8; - EMC(EMC_MRW12) = params->emc_mrw12; - EMC(EMC_MRW9) = params->emc_mrw9; - EMC(EMC_MRW13) = params->emc_mrw13; - - if (params->emc_zcal_warm_cold_boot_enables & 1) + // Issue ZQCAL latch. + EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev0 ^ 3; + // Same for device 1. + if (!(params->emc_dev_select & 2)) { - // Issue ZQCAL start, device 0. - EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev0; + EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev1; usleep(params->emc_zcal_init_wait); - - // Issue ZQCAL latch. - EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev0 ^ 3; - // Same for device 1. - if (!(params->emc_dev_select & 2)) - { - EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev1; - usleep(params->emc_zcal_init_wait); - EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev1 ^ 3; - } + EMC(EMC_ZQ_CAL) = params->emc_zcal_init_dev1 ^ 3; } } @@ -1321,12 +1301,9 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) PMC(APBDEV_PMC_DDR_CFG) = params->pmc_ddr_cfg; // Start periodic ZQ calibration (LPDDRx only). - if (params->memory_type == MEMORY_TYPE_LPDDR2 || params->memory_type == MEMORY_TYPE_DDR3L || params->memory_type == MEMORY_TYPE_LPDDR4) - { - EMC(EMC_ZCAL_INTERVAL) = params->emc_zcal_interval; - EMC(EMC_ZCAL_WAIT_CNT) = params->emc_zcal_wait_cnt; - EMC(EMC_ZCAL_MRW_CMD) = params->emc_zcal_mrw_cmd; - } + EMC(EMC_ZCAL_INTERVAL) = params->emc_zcal_interval; + EMC(EMC_ZCAL_WAIT_CNT) = params->emc_zcal_wait_cnt; + EMC(EMC_ZCAL_MRW_CMD) = params->emc_zcal_mrw_cmd; // Patch 7 using BCT spare variables. if (params->emc_bct_spare12) @@ -1341,10 +1318,10 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) EMC(EMC_REFCTRL) = params->emc_dev_select | 0x80000000; EMC(EMC_DYN_SELF_REF_CONTROL) = params->emc_dyn_self_ref_control; - EMC(EMC_CFG) = params->emc_cfg; - EMC(EMC_FDPD_CTRL_DQ) = params->emc_fdpd_ctrl_dq; + EMC(EMC_CFG) = params->emc_cfg; + EMC(EMC_FDPD_CTRL_DQ) = params->emc_fdpd_ctrl_dq; EMC(EMC_FDPD_CTRL_CMD) = params->emc_fdpd_ctrl_cmd; - EMC(EMC_SEL_DPD_CTRL) = params->emc_sel_dpd_ctrl; + EMC(EMC_SEL_DPD_CTRL) = params->emc_sel_dpd_ctrl; // Write addr swizzle lock bit. EMC(EMC_FBIO_SPARE) = params->emc_fbio_spare | 2; @@ -1364,8 +1341,8 @@ static void _sdram_config_t210b01(const sdram_params_t210b01_t *params) // Lock carveouts per BCT cfg. MC(MC_VIDEO_PROTECT_REG_CTRL) = params->mc_video_protect_write_access; - MC(MC_SEC_CARVEOUT_REG_CTRL) = params->mc_sec_carveout_protect_write_access; - MC(MC_MTS_CARVEOUT_REG_CTRL) = params->mc_mts_carveout_reg_ctrl; + MC(MC_SEC_CARVEOUT_REG_CTRL) = params->mc_sec_carveout_protect_write_access; + MC(MC_MTS_CARVEOUT_REG_CTRL) = params->mc_mts_carveout_reg_ctrl; // Disable write access to a bunch of EMC registers. MC(MC_EMEM_CFG_ACCESS_CTRL) = 1; @@ -1406,7 +1383,7 @@ void *sdram_get_params_t210b01() return (void *)params; for (u32 i = 0; i < ARRAY_SIZE(sdram_cfg_vendor_patches_t210b01); i++) - if (sdram_cfg_vendor_patches_t210b01[i].dramcf == dram_code) + if (sdram_cfg_vendor_patches_t210b01[i].dramcf & DRAM_CC(dram_code)) params[sdram_cfg_vendor_patches_t210b01[i].offset] = sdram_cfg_vendor_patches_t210b01[i].val; return (void *)params; @@ -1453,22 +1430,24 @@ void *sdram_get_params_patched() 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, 1100000); // HOS uses 1.125V + 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); + 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_REG_SHORT) = params->pmc_reg_short; - PMC(APBDEV_PMC_DDR_CNTRL) = params->pmc_ddr_ctrl; + PMC(APBDEV_PMC_DDR_CNTRL) = params->pmc_ddr_ctrl; // Patch 1 using BCT spare variables if (params->emc_bct_spare0) @@ -1480,6 +1459,8 @@ static void _sdram_init_t210() 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; @@ -1487,9 +1468,9 @@ static void _sdram_init_t210b01() // 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_REG_SHORT) = params->pmc_reg_short; - PMC(APBDEV_PMC_DDR_CNTRL) = params->pmc_ddr_ctrl; + PMC(APBDEV_PMC_DDR_CNTRL) = params->pmc_ddr_ctrl; // Patch 1 using BCT spare variables if (params->emc_bct_spare0) diff --git a/bdk/mem/sdram.h b/bdk/mem/sdram.h index 42907f9..6b2ea5e 100644 --- a/bdk/mem/sdram.h +++ b/bdk/mem/sdram.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2020-2021 CTCaer + * Copyright (c) 2020-2023 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, @@ -23,26 +23,20 @@ /* * Tegra X1/X1+ EMC/DRAM Bandwidth Chart: * - * Note: BWbits T210 = Hz x ddr x bus width x channels = Hz x 2 x 32 x 2. - * BWbits T210B01 = Hz x ddr x bus width x channels = Hz x 2 x 64 x 2. - * Both assume that both sub-partitions are used and thus reaching max - * bandwidth per channel. (T210: 2x16-bit, T210B01: 2x32-bit). - * Retail Mariko use one sub-partition, in order to meet Erista perf. - * - * T210 T210B01 - * 40.8 MHz: 0.61 1.22 GiB/s - * 68.0 MHz: 1.01 2.02 GiB/s - * 102.0 MHz: 1.52 3.04 GiB/s - * 204.0 MHz: 3.04 6.08 GiB/s <-- Tegra X1/X1+ Init/SC7 Frequency - * 408.0 MHz: 6.08 12.16 GiB/s - * 665.6 MHz: 9.92 19.84 GiB/s - * 800.0 MHz: 11.92 23.84 GiB/s <-- Tegra X1/X1+ Nvidia OS Boot Frequency - * 1065.6 MHz: 15.89 31.78 GiB/s - * 1331.2 MHz: 19.84 39.68 GiB/s - * 1600.0 MHz: 23.84 47.68 GiB/s <-- Tegra X1/X1+ HOS Max Frequency - * 1862.4 MHz: 27.75 55.50 GiB/s <-- Tegra X1 Official Max Frequency - * 2131.2 MHz: 31.76 63.52 GiB/s <-- Tegra X1+ Official Max Frequency + * Note: Max BWbits = Hz x ddr x bus width x channels = Hz x 2 x 32 x 2. + * Max BWbits = Hz x ddr x bus width x channels = Hz x 2 x 64 x 1. + * Configurations supported: 1x32, 2x32, 1x64. + * x64 ram modules can be used by combining the 2 32-bit channels into one. * + * 204.0 MHz: 3.04 <-- Tegra X1/X1+ Init/SC7 Frequency + * 408.0 MHz: 6.08 + * 665.6 MHz: 9.92 + * 800.0 MHz: 11.92 <-- Tegra X1/X1+ Nvidia OS Boot Frequency + * 1065.6 MHz: 15.89 + * 1331.2 MHz: 19.84 + * 1600.0 MHz: 23.84 + * 1862.4 MHz: 27.75 <-- Tegra X1 Official Max Frequency + * 2131.2 MHz: 31.76 <-- Tegra X1+ Official Max Frequency. Not all regs have support for > 2046 MHz. */ enum sdram_ids_erista @@ -51,73 +45,75 @@ enum sdram_ids_erista LPDDR4_ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH = 0, LPDDR4_ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 1, LPDDR4_ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WT = 2, // WT:C. - LPDDR4_COPPER_4GB_SAMSUNG_K4F6E304HB_MGCH = 3, // Changed to Iowa Hynix 4GB 1Y-A. + LPDDR4_ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH = 4, - LPDDR4_COPPER_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 5, // Changed to Hoag Hynix 4GB 1Y-A. - LPDDR4_COPPER_4GB_MICRON_MT53B512M32D2NP_062_WT = 6, // Changed to Aula Hynix 4GB 1Y-A. + + LPDDR4_ICOSA_8GB_SAMSUNG_K4FBE3D4HM_MGXX = 7, // Custom 8GB. XX: CH/CJ/CL. 7 since it can be easily applied in fuses. }; enum sdram_ids_mariko { // LPDDR4X 4266Mbps. - LPDDR4X_IOWA_4GB_HYNIX_1Y_A = 3, // Replaced from Copper. - LPDDR4X_HOAG_4GB_HYNIX_1Y_A = 5, // Replaced from Copper. - LPDDR4X_AULA_4GB_HYNIX_1Y_A = 6, // Replaced from Copper. + LPDDR4X_HOAG_4GB_HYNIX_H9HCNNNBKMMLXR_NEE = 3, // Replaced from Copper. Die-M. (1y-01). + LPDDR4X_AULA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE = 5, // Replaced from Copper. Die-M. (1y-01). + LPDDR4X_IOWA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE = 6, // Replaced from Copper. Die-M. (1y-01). // LPDDR4X 3733Mbps. - LPDDR4X_IOWA_4GB_SAMSUNG_X1X2 = 7, - - LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 8, // Die-M. + LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 8, // Die-M. 1st gen. 8 banks. 3733Mbps. LPDDR4X_IOWA_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 9, // Die-M. LPDDR4X_IOWA_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 10, // Die-M. - LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTE = 11, // 4266Mbps. Die-E. + LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTE = 11, // 4266Mbps. Die-E. D9WGB. - LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 12, // Die-M. + LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 12, // Die-M. 1st gen. 8 banks. 3733Mbps. LPDDR4X_HOAG_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 13, // Die-M. LPDDR4X_HOAG_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 14, // Die-M. - LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTE = 15, // 4266Mbps. Die-E. + LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTE = 15, // 4266Mbps. Die-E. D9WGB. // LPDDR4X 4266Mbps. - LPDDR4X_IOWA_4GB_SAMSUNG_Y = 16, + LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 17, // Die-A. (1y-X03). 2nd gen. 8 banks. 4266Mbps. + LPDDR4X_IOWA_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 18, // Die-A. (1y-X03). + LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 19, // Die-A. (1y-X03). 2nd gen. 8 banks. 4266Mbps. - LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 17, // Die-A. - LPDDR4X_IOWA_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 18, // Die-A. - LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 19, // Die-A. + LPDDR4X_IOWA_4GB_SAMSUNG_K4U6E3S4AB_MGCL = 20, // Die-B. 1z nm. 40% lower power usage. (1z-01). + LPDDR4X_HOAG_4GB_SAMSUNG_K4U6E3S4AB_MGCL = 21, // Die-B. 1z nm. 40% lower power usage. (1z-01). + LPDDR4X_AULA_4GB_SAMSUNG_K4U6E3S4AB_MGCL = 22, // Die-B. 1z nm. 40% lower power usage. (1z-01). - LPDDR4X_IOWA_4GB_SAMSUNG_1Y_Y = 20, - LPDDR4X_IOWA_8GB_SAMSUNG_1Y_Y = 21, + LPDDR4X_HOAG_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 23, // Die-A. (1y-X03). + LPDDR4X_AULA_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 24, // Die-A. (1y-X03). 2nd gen. 8 banks. 4266Mbps. - // LPDDR4X_AULA_8GB_SAMSUNG_1Y_A = 22, // Unused. - - LPDDR4X_HOAG_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 23, // Die-A. - LPDDR4X_AULA_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 24, // Die-A. - - LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTF = 25, // 4266Mbps. Die-F. - LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTF = 26, // 4266Mbps. Die-F. - LPDDR4X_AULA_4GB_MICRON_MT53E512M32D2NP_046_WTF = 27, // 4266Mbps. Die-F. + LPDDR4X_IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTF = 25, // 4266Mbps. Die-F. D9XRR. 10nm-class (1y-01). + LPDDR4X_HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTF = 26, // 4266Mbps. Die-F. D9XRR. 10nm-class (1y-01). + LPDDR4X_AULA_4GB_MICRON_MT53E512M32D2NP_046_WTF = 27, // 4266Mbps. Die-F. D9XRR. 10nm-class (1y-01). LPDDR4X_AULA_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 28, // Die-A. + + LPDDR4X_UNK0_4GB_HYNIX_H9HCNNNBKMMLXR_NEI = 29, // Die-M. 1a nm. 61% lower power usage. (1a-01). + LPDDR4X_UNK1_4GB_HYNIX_H9HCNNNBKMMLXR_NEI = 30, // Die-M. 1a nm. 61% lower power usage. (1a-01). + LPDDR4X_UNK2_4GB_HYNIX_H9HCNNNBKMMLXR_NEI = 31, // Die-M. 1a nm. 61% lower power usage. (1a-01). + + LPDDR4X_UNK0_4GB_MICRON_1A = 32, // 1a nm. 61% lower power usage. (1a-01). + LPDDR4X_UNK1_4GB_MICRON_1A = 33, // 1a nm. 61% lower power usage. (1a-01). + LPDDR4X_UNK2_4GB_MICRON_1A = 34, // 1a nm. 61% lower power usage. (1a-01). }; enum sdram_codes_mariko { - LPDDR4X_NO_PATCH = 0, - LPDDR4X_UNUSED = 0, + LPDDR4X_NO_PATCH = 0, + LPDDR4X_UNUSED = 0, // LPDDR4X_4GB_SAMSUNG_K4U6E3S4AM_MGCJ DRAM IDs: 08, 12. // LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLHR_NME DRAM IDs: 10, 14. - LPDDR4X_4GB_SAMSUNG_X1X2 = 1, // DRAM IDs: 07. - LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 2, // DRAM IDs: 09, 13. - LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE = 3, // DRAM IDs: 11, 15. - LPDDR4X_4GB_SAMSUNG_Y = 4, // DRAM IDs: 16. - LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 5, // DRAM IDs: 17, 19, 24. - LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 6, // DRAM IDs: 18, 23, 28. - LPDDR4X_4GB_SAMSUNG_1Y_Y = 7, // DRAM IDs: 20. - LPDDR4X_8GB_SAMSUNG_1Y_Y = 8, // DRAM IDs: 21. - //LPDDR4X_8GB_SAMSUNG_1Y_A = 9, // DRAM IDs: 22. Unused. - LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF = 10, // DRAM IDs: 25, 26, 27. - LPDDR4X_4GB_HYNIX_1Y_A = 11, // DRAM IDs: 03, 05, 06. + LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 1, // DRAM IDs: 09, 13. + LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE = 2, // DRAM IDs: 11, 15. + LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 3, // DRAM IDs: 17, 19, 24. + LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 4, // DRAM IDs: 18, 23, 28. + LPDDR4X_4GB_SAMSUNG_K4U6E3S4AB_MGCL = 5, // DRAM IDs: 20, 21, 22. + LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF = 6, // DRAM IDs: 25, 26, 27. + LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEE = 7, // DRAM IDs: 03, 05, 06. + + LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEI = 8, // DRAM IDs: 29, 30, 31. + LPDDR4X_4GB_MICRON_1A = 9, // DRAM IDs: 32, 33, 34. }; void sdram_init(); diff --git a/bdk/mem/sdram_config.inl b/bdk/mem/sdram_config.inl index 4548981..18fb456 100644 --- a/bdk/mem/sdram_config.inl +++ b/bdk/mem/sdram_config.inl @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2020-2021 CTCaer + * Copyright (c) 2020-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, @@ -17,8 +17,6 @@ #define DRAM_CFG_T210_SIZE 1896 -#define DRAM_ID(x) BIT(x) - static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = { /* Specifies the type of memory device */ .memory_type = MEMORY_TYPE_LPDDR4, @@ -543,8 +541,12 @@ static const sdram_params_t210_t _dram_cfg_0_samsung_4gb = { .mc_video_protect_bom = 0xFFF00000, .mc_video_protect_bom_adr_hi = 0x00000000, .mc_video_protect_size_mb = 0x00000000, + + // AFI, BPMP, HC, ISP2, CCPLEX, PPCS (AHB), SATA, VI, XUSB_HOST, XUSB_DEV, ADSP, PPCS1 (AHB), DC1, SDMMC1A, SDMMC2A, SDMMC3A. .mc_video_protect_vpr_override = 0xE4BAC343, + // SDMMC4A, ISP2B, PPCS2 (AHB), APE, SE, HC1, SE1, AXIAP, ETR. .mc_video_protect_vpr_override1 = 0x00001ED3, + .mc_video_protect_gpu_override0 = 0x00000000, .mc_video_protect_gpu_override1 = 0x00000000, .mc_sec_carveout_bom = 0xFFF00000, @@ -657,40 +659,13 @@ static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210[] = { { 0x000C0302, 0x570 / 4, DRAM_ID(4) }, // mc_emem_adr_cfg_dev1. 768MB Rank 1 density. { 0x00001800, 0x584 / 4, DRAM_ID(4) }, // mc_emem_cfg. 6GB total density. -#ifdef CONFIG_SDRAM_COPPER_SUPPORT - // Copper prototype Samsung/Hynix/Micron timing configs. - { 0x0000003A, 0xEC / 4, DRAM_ID(6) }, // emc_rfc. Auto refresh. - { 0x0000001D, 0xF0 / 4, DRAM_ID(6) }, // emc_rfc_pb. Bank Auto refresh. - { 0x0000000D, 0x10C / 4, DRAM_ID(5) }, // emc_r2w. - { 0x00000001, 0x16C / 4, DRAM_ID(5) }, // emc_puterm_extra. - { 0x80000000, 0x170 / 4, DRAM_ID(5) }, // emc_puterm_width. - { 0x00000012, 0x1B0 / 4, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_rw2pden. - { 0x0000003B, 0x1C0 / 4, DRAM_ID(6) }, // emc_txsr. - { 0x0000003B, 0x1C4 / 4, DRAM_ID(6) }, // emc_txsr_dll. - { 0x00000003, 0x1DC / 4, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_tclkstable. - { 0x00120015, 0x334 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank0_4. - { 0x00160012, 0x338 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank0_5. - { 0x00120015, 0x34C / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank1_4. - { 0x00160012, 0x350 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dq_rank1_5. - { 0x002F0032, 0x354 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_0. - { 0x00310032, 0x358 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_1. - { 0x00360034, 0x35C / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_2. - { 0x0033002F, 0x360 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_3. - { 0x00000006, 0x364 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank0_4. - { 0x002F0032, 0x36C / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_0. - { 0x00310032, 0x370 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_1. - { 0x00360034, 0x374 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_2. - { 0x0033002F, 0x378 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_3. - { 0x00000006, 0x37C / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ob_ddll_long_dqs_rank1_4. - { 0x00150015, 0x3A4 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_0. - { 0x00120012, 0x3AC / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_2. - { 0x00160016, 0x3B0 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_3. - { 0x00000015, 0x3B4 / 4, DRAM_ID(5) | DRAM_ID(6) }, // emc_pmacro_ddll_long_cmd_4. - { 0x00000012, 0x49C / 4, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_cmd_brlshft2. - { 0x00000012, 0x4A0 / 4, DRAM_ID(3) | DRAM_ID(5) | DRAM_ID(6) }, // emc_cmd_brlshft3. - { 0x00000210, 0x4F4 / 4, DRAM_ID(5) }, // emc_pmacro_data_rx_term_mode. - { 0x00000005, 0x5C0 / 4, DRAM_ID(5) }, // mc_emem_arb_timing_r2w. - { 0x00000007, 0x5C8 / 4, DRAM_ID(6) }, // mc_emem_arb_timing_rfcpb. Bank refresh. - { 0x72A30504, 0x5D4 / 4, DRAM_ID(6) }, // mc_emem_arb_misc0. -#endif + // Samsung 8GB density config. + { 0x0000003A, 0xEC / 4, DRAM_ID(7) }, // emc_rfc. + { 0x0000001D, 0xF0 / 4, DRAM_ID(7) }, // emc_rfc_pb. + { 0x0000003B, 0x1C0 / 4, DRAM_ID(7) }, // emc_txsr. + { 0x0000003B, 0x1C4 / 4, DRAM_ID(7) }, // emc_txsr_dll. + { 0x00000713, 0x2B4 / 4, DRAM_ID(7) }, // emc_dyn_self_ref_control. + { 0x00080302, 0x56C / 4, DRAM_ID(7) }, // mc_emem_adr_cfg_dev0. 1024MB Rank 0 density. + { 0x00080302, 0x570 / 4, DRAM_ID(7) }, // mc_emem_adr_cfg_dev1. 1024MB Rank 1 density. + { 0x00002000, 0x584 / 4, DRAM_ID(7) }, // mc_emem_cfg. 8GB total density. }; diff --git a/bdk/mem/sdram_config_t210b01.inl b/bdk/mem/sdram_config_t210b01.inl index 28cc063..435f746 100644 --- a/bdk/mem/sdram_config_t210b01.inl +++ b/bdk/mem/sdram_config_t210b01.inl @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2021 CTCaer + * Copyright (c) 2020-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, @@ -594,10 +594,15 @@ static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = { .mc_video_protect_bom = 0xFFF00000, .mc_video_protect_bom_adr_hi = 0x00000000, .mc_video_protect_size_mb = 0x00000000, + + // AFI, BPMP, HC, ISP2, CCPLEX, PPCS (AHB), SATA, VI, XUSB_HOST, XUSB_DEV, ADSP, PPCS1 (AHB), DC1, SDMMC1A, SDMMC2A, SDMMC3A. .mc_video_protect_vpr_override = 0xE4BAC343, - .mc_video_protect_vpr_override1 = 0x06001ED3, // Add SE2, SE2B. + // SDMMC4A, ISP2B, PPCS2 (AHB), APE, SE, HC1, SE1, AXIAP, ETR. Plus SE2, SE2B. + .mc_video_protect_vpr_override1 = 0x06001ED3, + .mc_video_protect_gpu_override0 = 0x00000000, .mc_video_protect_gpu_override1 = 0x00000000, + .mc_sec_carveout_bom = 0xFFF00000, .mc_sec_carveout_adr_hi = 0x00000000, .mc_sec_carveout_size_mb = 0x00000000, @@ -701,292 +706,102 @@ static const sdram_params_t210b01_t _dram_cfg_08_10_12_14_samsung_hynix_4gb = { .bct_na = 0x00000000, }; -//!TODO Find out what mc_video_protect_gpu_override0 and mc_video_protect_gpu_override1 new bits are. +#define DRAM_CC_LPDDR4X_PMACRO_IB (DRAM_CC(LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ)) + +#define DRAM_CC_LPDDR4X_AUTOCAL_VPR (DRAM_CC(LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ) | \ + DRAM_CC(LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE) | \ + DRAM_CC(LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL) | \ + DRAM_CC(LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL) | \ + DRAM_CC(LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF) | \ + DRAM_CC(LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEE) | \ + DRAM_CC(LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEI) | \ + DRAM_CC(LPDDR4X_4GB_MICRON_1A) | \ + DRAM_CC(LPDDR4X_4GB_SAMSUNG_K4U6E3S4AB_MGCL)) + +#define DRAM_CC_LPDDR4X_DYN_SELF_CTRL (DRAM_CC(LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE) | \ + DRAM_CC(LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL) | \ + DRAM_CC(LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF) | \ + DRAM_CC(LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEE) | \ + DRAM_CC(LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEI) | \ + DRAM_CC(LPDDR4X_4GB_MICRON_1A) | \ + DRAM_CC(LPDDR4X_4GB_SAMSUNG_K4U6E3S4AB_MGCL)) + +#define DRAM_CC_LPDDR4X_QUSE_EINPUT (DRAM_CC(LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ) | \ + DRAM_CC(LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL) | \ + DRAM_CC(LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL) | \ + DRAM_CC(LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF) | \ + DRAM_CC(LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEE) | \ + DRAM_CC(LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEI) | \ + DRAM_CC(LPDDR4X_4GB_MICRON_1A) | \ + DRAM_CC(LPDDR4X_4GB_SAMSUNG_K4U6E3S4AB_MGCL)) + +#define DRAM_CC_LPDDR4X_FAW (DRAM_CC(LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL) | \ + DRAM_CC(LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF) | \ + DRAM_CC(LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEE) | \ + DRAM_CC(LPDDR4X_4GB_MICRON_1A)) + +#define DRAM_CC_LPDDR4X_VPR (DRAM_CC(LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEE) | \ + DRAM_CC(LPDDR4X_4GB_HYNIX_H9HCNNNBKMMLXR_NEI) | \ + DRAM_CC(LPDDR4X_4GB_MICRON_1A) | \ + DRAM_CC(LPDDR4X_4GB_SAMSUNG_K4U6E3S4AB_MGCL)) + +#define DRAM_CC_LPDDR4X_8GB (DRAM_CC(LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ) | \ + DRAM_CC(LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL)) static const sdram_vendor_patch_t sdram_cfg_vendor_patches_t210b01[] = { - // Samsung LPDDR4X 4GB X1X2 for prototype Iowa. - { 0x000E0022, 0x3AC / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dq_rank0_4. - { 0x001B0010, 0x3B0 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dq_rank0_5. - { 0x000E0022, 0x3C4 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dq_rank1_4. - { 0x001B0010, 0x3C8 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dq_rank1_5. - { 0x00490043, 0x3CC / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_0. - { 0x00420045, 0x3D0 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_1. - { 0x00490047, 0x3D4 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_2. - { 0x00460047, 0x3D8 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_3. - { 0x00000016, 0x3DC / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_4. - { 0x00100000, 0x3E0 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank0_5. - { 0x00490043, 0x3E4 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_0. - { 0x00420045, 0x3E8 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_1. - { 0x00490047, 0x3EC / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_2. - { 0x00460047, 0x3F0 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_3. - { 0x00000016, 0x3F4 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_4. - { 0x00100000, 0x3F8 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ob_ddll_long_dqs_rank1_5. - { 0x00220022, 0x41C / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_0. - { 0x000E000E, 0x420 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_1. - { 0x00100010, 0x424 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_2. - { 0x001B001B, 0x428 / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_3. - { 0x00000022, 0x42C / 4, LPDDR4X_4GB_SAMSUNG_X1X2 }, // emc_pmacro_ddll_long_cmd_4. - // Samsung LPDDR4X 8GB K4UBE3D4AM-MGCJ Die-M for SDEV Iowa and Hoag. - { 0x05500000, 0x0D4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_auto_cal_config2. - { 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_auto_cal_vref_sel0. - { 0x00000001, 0x134 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_adr_cfg. 2 Ranks. - { 0x00000006, 0x1CC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_quse. - { 0x00000005, 0x1D0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_quse_width. - { 0x00000003, 0x1DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_einput. - { 0x0000000C, 0x1E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_einput_duration. - { 0x08010004, 0x2B8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw1. - { 0x08020000, 0x2BC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw2. - { 0x080D0000, 0x2C0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw3. - { 0x08033131, 0x2C8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw6. - { 0x080B0000, 0x2CC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw8. - { 0x0C0E5D5D, 0x2D0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw9. - { 0x080C5D5D, 0x2D4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw10. - { 0x0C0D0808, 0x2D8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw12. - { 0x0C0D0000, 0x2DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw13. - { 0x08161414, 0x2E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw14. - { 0x08010004, 0x2E4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_mrw_extra. - { 0x00000000, 0x340 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_dev_select. Both devices. - { 0x35353535, 0x350 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_vref_dq_0. - { 0x35353535, 0x354 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_vref_dq_1. - { 0x00100010, 0x3FC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank0_0. - { 0x00100010, 0x400 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank0_1. - { 0x00100010, 0x404 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank0_2. - { 0x00100010, 0x408 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank0_3. - { 0x00100010, 0x40C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank1_0. - { 0x00100010, 0x410 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank1_1. - { 0x00100010, 0x414 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank1_2. - { 0x00100010, 0x418 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_ib_ddll_long_dqs_rank1_3. - { 0x0051004F, 0x450 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_zcal_mrw_cmd. - { 0x40000001, 0x45C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_zcal_init_dev1. - { 0x00000000, 0x594 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_tx_pwrd4. - { 0x00001000, 0x598 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // emc_pmacro_tx_pwrd5. - { 0x00000001, 0x630 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_emem_adr_cfg. 2 Ranks. - { 0x00002000, 0x64C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_emem_cfg. 8GB total density. - { 0x00000002, 0x680 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_emem_arb_timing_r2r. - { 0x02020001, 0x694 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_emem_arb_da_turns. - { 0x2A800000, 0x6DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_video_protect_gpu_override0. - { 0x00000002, 0x6E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AM_MGCJ }, // mc_video_protect_gpu_override1. + { 0x35353535, 0x350 / 4, DRAM_CC_LPDDR4X_PMACRO_IB }, // emc_pmacro_ib_vref_dq_0. + { 0x35353535, 0x354 / 4, DRAM_CC_LPDDR4X_PMACRO_IB }, // emc_pmacro_ib_vref_dq_1. + { 0x00100010, 0x3FC / 4, DRAM_CC_LPDDR4X_PMACRO_IB }, // emc_pmacro_ib_ddll_long_dqs_rank0_0. + { 0x00100010, 0x400 / 4, DRAM_CC_LPDDR4X_PMACRO_IB }, // emc_pmacro_ib_ddll_long_dqs_rank0_1. + { 0x00100010, 0x404 / 4, DRAM_CC_LPDDR4X_PMACRO_IB }, // emc_pmacro_ib_ddll_long_dqs_rank0_2. + { 0x00100010, 0x408 / 4, DRAM_CC_LPDDR4X_PMACRO_IB }, // emc_pmacro_ib_ddll_long_dqs_rank0_3. + { 0x00100010, 0x40C / 4, DRAM_CC_LPDDR4X_PMACRO_IB }, // emc_pmacro_ib_ddll_long_dqs_rank1_0. + { 0x00100010, 0x410 / 4, DRAM_CC_LPDDR4X_PMACRO_IB }, // emc_pmacro_ib_ddll_long_dqs_rank1_1. + { 0x00100010, 0x414 / 4, DRAM_CC_LPDDR4X_PMACRO_IB }, // emc_pmacro_ib_ddll_long_dqs_rank1_2. + { 0x00100010, 0x418 / 4, DRAM_CC_LPDDR4X_PMACRO_IB }, // emc_pmacro_ib_ddll_long_dqs_rank1_3. - // Micron LPDDR4X 4GB MT53D1024M32D1NP-053-WT:E Die-E for retail Iowa and Hoag. - { 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // emc_auto_cal_config2. - { 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // emc_auto_cal_vref_sel0. - { 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // emc_mrw14. - { 0x80000713, 0x32C / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // emc_dyn_self_ref_control. - { 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // mc_video_protect_gpu_override0. - { 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTE }, // mc_video_protect_gpu_override1. + /*! Shared patched between DRAM Codes. */ + { 0x05500000, 0x0D4 / 4, DRAM_CC_LPDDR4X_AUTOCAL_VPR }, // emc_auto_cal_config2. + { 0xC9AFBCBC, 0x0F4 / 4, DRAM_CC_LPDDR4X_AUTOCAL_VPR }, // emc_auto_cal_vref_sel0. + { 0x2A800000, 0x6DC / 4, DRAM_CC_LPDDR4X_AUTOCAL_VPR }, // mc_video_protect_gpu_override0. + { 0x00000002, 0x6E0 / 4, DRAM_CC_LPDDR4X_AUTOCAL_VPR }, // mc_video_protect_gpu_override1. + //!TODO Find out what mc_video_protect_gpu_override0 and mc_video_protect_gpu_override1 new bits are. - // Samsung LPDDR4X 4GB (Y01) Die-? for Iowa. - { 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_auto_cal_config2. - { 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_auto_cal_vref_sel0. - { 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_mrw14. - { 0x80000713, 0x32C / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_dyn_self_ref_control. - { 0x32323232, 0x350 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_vref_dq_0. - { 0x32323232, 0x354 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_vref_dq_1. - { 0x000F0018, 0x3AC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dq_rank0_4. - { 0x000F0018, 0x3C4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dq_rank1_4. - { 0x00440048, 0x3CC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_0. - { 0x00440045, 0x3D0 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_1. - { 0x00470047, 0x3D4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_2. - { 0x0005000D, 0x3DC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_4. - { 0x00440048, 0x3E4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_0. - { 0x00440045, 0x3E8 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_1. - { 0x00470047, 0x3EC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_2. - { 0x0005000D, 0x3F4 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_4. - { 0x00780078, 0x3FC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank0_0. - { 0x00780078, 0x400 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank0_1. - { 0x00780078, 0x404 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank0_2. - { 0x00780078, 0x408 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank0_3. - { 0x00780078, 0x40C / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank1_0. - { 0x00780078, 0x410 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank1_1. - { 0x00780078, 0x414 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank1_2. - { 0x00780078, 0x418 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ib_ddll_long_dqs_rank1_3. - { 0x00180018, 0x41C / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ddll_long_cmd_0. - { 0x000F000F, 0x420 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ddll_long_cmd_1. - { 0x00000018, 0x42C / 4, LPDDR4X_4GB_SAMSUNG_Y }, // emc_pmacro_ddll_long_cmd_4. - { 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_SAMSUNG_Y }, // mc_video_protect_gpu_override0. - { 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_SAMSUNG_Y }, // mc_video_protect_gpu_override1. + { 0x88161414, 0x2E0 / 4, DRAM_CC_LPDDR4X_DYN_SELF_CTRL }, // emc_mrw14. + { 0x80000713, 0x32C / 4, DRAM_CC_LPDDR4X_DYN_SELF_CTRL }, // emc_dyn_self_ref_control. - // Samsung LPDDR4X 4GB K4U6E3S4AA-MGCL 10nm-class (1y-X03) Die-A for retail Iowa, Hoag and Aula. - { 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_auto_cal_config2. - { 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_auto_cal_vref_sel0. - { 0x00000006, 0x1CC / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_quse. - { 0x00000005, 0x1D0 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_quse_width. - { 0x00000003, 0x1DC / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_einput. - { 0x0000000C, 0x1E0 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_einput_duration. - { 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_mrw14. - { 0x80000713, 0x32C / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // emc_dyn_self_ref_control. - { 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // mc_video_protect_gpu_override0. - { 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_SAMSUNG_K4U6E3S4AA_MGCL }, // mc_video_protect_gpu_override1. + { 0x00000006, 0x1CC / 4, DRAM_CC_LPDDR4X_QUSE_EINPUT }, // emc_quse. + { 0x00000005, 0x1D0 / 4, DRAM_CC_LPDDR4X_QUSE_EINPUT }, // emc_quse_width. + { 0x00000003, 0x1DC / 4, DRAM_CC_LPDDR4X_QUSE_EINPUT }, // emc_einput. + { 0x0000000C, 0x1E0 / 4, DRAM_CC_LPDDR4X_QUSE_EINPUT }, // emc_einput_duration. - // Samsung LPDDR4X 8GB K4UBE3D4AA-MGCL 10nm-class (1y-X03) Die-A for SDEV Iowa, Hoag and Aula. - { 0x05500000, 0x0D4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_auto_cal_config2. - { 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_auto_cal_vref_sel0. - { 0x00000001, 0x134 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_adr_cfg. 2 Ranks. - { 0x00000006, 0x1CC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_quse. - { 0x00000005, 0x1D0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_quse_width. - { 0x00000003, 0x1DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_einput. - { 0x0000000C, 0x1E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_einput_duration. - { 0x00000008, 0x24C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_tfaw. - { 0x08010004, 0x2B8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw1. - { 0x08020000, 0x2BC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw2. - { 0x080D0000, 0x2C0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw3. - { 0x08033131, 0x2C8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw6. - { 0x080B0000, 0x2CC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw8. - { 0x0C0E5D5D, 0x2D0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw9. - { 0x080C5D5D, 0x2D4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw10. - { 0x0C0D0808, 0x2D8 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw12. - { 0x0C0D0000, 0x2DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw13. - { 0x08161414, 0x2E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw14. - { 0x08010004, 0x2E4 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_mrw_extra. - { 0x00000000, 0x340 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_dev_select. Both devices. - { 0x0051004F, 0x450 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_zcal_mrw_cmd. - { 0x40000001, 0x45C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_zcal_init_dev1. - { 0x00000000, 0x594 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_pmacro_tx_pwrd4. - { 0x00001000, 0x598 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // emc_pmacro_tx_pwrd5. - { 0x00000001, 0x630 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_adr_cfg. 2 Ranks. - { 0x00002000, 0x64C / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_cfg. 8GB total density. - { 0x00000001, 0x670 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_arb_timing_faw. - { 0x00000002, 0x680 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_arb_timing_r2r. - { 0x02020001, 0x694 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_emem_arb_da_turns. - { 0x2A800000, 0x6DC / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_video_protect_gpu_override0. - { 0x00000002, 0x6E0 / 4, LPDDR4X_8GB_SAMSUNG_K4UBE3D4AA_MGCL }, // mc_video_protect_gpu_override1. + { 0x00000008, 0x24C / 4, DRAM_CC_LPDDR4X_FAW }, // emc_tfaw. + { 0x00000001, 0x670 / 4, DRAM_CC_LPDDR4X_FAW }, // mc_emem_arb_timing_faw. - // Samsung LPDDR4X 4GB 10nm-class (1y-Y01) Die-? for Iowa. - { 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_auto_cal_config2. - { 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_auto_cal_vref_sel0. - { 0x00000008, 0x24C / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_tfaw. - { 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_mrw14. - { 0x80000713, 0x32C / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_dyn_self_ref_control. - { 0x000F0018, 0x3AC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dq_rank0_4. - { 0x000F0018, 0x3C4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dq_rank1_4. - { 0x00440048, 0x3CC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_0. - { 0x00440045, 0x3D0 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_1. - { 0x00470047, 0x3D4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_2. - { 0x0005000D, 0x3DC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_4. - { 0x00440048, 0x3E4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_0. - { 0x00440045, 0x3E8 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_1. - { 0x00470047, 0x3EC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_2. - { 0x0005000D, 0x3F4 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_4. - { 0x00180018, 0x41C / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_0. - { 0x000F000F, 0x420 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_1. - { 0x00000018, 0x42C / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_4. - { 0x00000001, 0x670 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // mc_emem_arb_timing_faw. - { 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // mc_video_protect_gpu_override0. - { 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_SAMSUNG_1Y_Y }, // mc_video_protect_gpu_override1. + { 0xE4FACB43, 0x6D4 / 4, DRAM_CC_LPDDR4X_VPR }, // mc_video_protect_vpr_override. + TSEC, NVENC. + { 0x0600FED3, 0x6D8 / 4, DRAM_CC_LPDDR4X_VPR }, // mc_video_protect_vpr_override1. + TSECB, TSEC1, TSECB1. - // Samsung LPDDR4X 8GB 10nm-class (1y-Y01) Die-? for SDEV Iowa. - { 0x05500000, 0x0D4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_auto_cal_config2. - { 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_auto_cal_vref_sel0. - { 0x00000001, 0x134 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_adr_cfg. 2 Ranks. - { 0x00000008, 0x24C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_tfaw. - { 0x08010004, 0x2B8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw1. - { 0x08020000, 0x2BC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw2. - { 0x080D0000, 0x2C0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw3. - { 0x08033131, 0x2C8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw6. - { 0x080B0000, 0x2CC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw8. - { 0x0C0E5D5D, 0x2D0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw9. - { 0x080C5D5D, 0x2D4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw10. - { 0x0C0D0808, 0x2D8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw12. - { 0x0C0D0000, 0x2DC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw13. - { 0x08161414, 0x2E0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw14. - { 0x08010004, 0x2E4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_mrw_extra. - { 0x00000000, 0x340 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_dev_select. Both devices. - { 0x32323232, 0x350 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ib_vref_dq_0. - { 0x32323232, 0x354 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ib_vref_dq_1. - { 0x000F0018, 0x3AC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dq_rank0_4. - { 0x000F0018, 0x3C4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dq_rank1_4. - { 0x00440048, 0x3CC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_0. - { 0x00440045, 0x3D0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_1. - { 0x00470047, 0x3D4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_2. - { 0x0005000D, 0x3DC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank0_4. - { 0x00440048, 0x3E4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_0. - { 0x00440045, 0x3E8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_1. - { 0x00470047, 0x3EC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_2. - { 0x0005000D, 0x3F4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ob_ddll_long_dqs_rank1_4. - { 0x00180018, 0x41C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_0. - { 0x000F000F, 0x420 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_1. - { 0x00000018, 0x42C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_ddll_long_cmd_4. - { 0x0051004F, 0x450 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_zcal_mrw_cmd. - { 0x40000001, 0x45C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_zcal_init_dev1. - { 0x00000000, 0x594 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_tx_pwrd4. - { 0x00001000, 0x598 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // emc_pmacro_tx_pwrd5. - { 0x00000001, 0x630 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_adr_cfg. 2 Ranks. - { 0x00002000, 0x64C / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_cfg. 8GB total density. - { 0x00000001, 0x670 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_arb_timing_faw. - { 0x00000002, 0x680 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_arb_timing_r2r. - { 0x02020001, 0x694 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_emem_arb_da_turns. - { 0x2A800000, 0x6DC / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_video_protect_gpu_override0. - { 0x00000002, 0x6E0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_Y }, // mc_video_protect_gpu_override1. - -/* - // Samsung LPDDR4X 8GB 10nm-class (1y-A01) Die-? for SDEV Aula? - { 0x00000001, 0x134 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_adr_cfg. 2 Ranks. - { 0x08010004, 0x2B8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw1. - { 0x08020000, 0x2BC / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw2. - { 0x080D0000, 0x2C0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw3. - { 0x08033131, 0x2C8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw6. - { 0x080B0000, 0x2CC / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw8. - { 0x0C0E5D5D, 0x2D0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw9. - { 0x080C5D5D, 0x2D4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw10. - { 0x0C0D0808, 0x2D8 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw12. - { 0x0C0D0000, 0x2DC / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw13. - { 0x08161414, 0x2E0 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw14. - { 0x08010004, 0x2E4 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_mrw_extra. - { 0x00000000, 0x340 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_dev_select. Both devices. - { 0x35353535, 0x350 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_vref_dq_0. - { 0x35353535, 0x354 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_vref_dq_1. - { 0x35353535, 0x358 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_vref_dqs_0. - { 0x35353535, 0x35C / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_vref_dqs_1. - { 0x00480048, 0x3FC / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank0_0. - { 0x00480048, 0x400 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank0_1. - { 0x00480048, 0x404 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank0_2. - { 0x00480048, 0x408 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank0_3. - { 0x00480048, 0x40C / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank1_0. - { 0x00480048, 0x410 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank1_1. - { 0x00480048, 0x414 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank1_2. - { 0x00480048, 0x418 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_ib_ddll_long_dqs_rank1_3. - { 0x0051004F, 0x450 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_zcal_mrw_cmd. - { 0x40000001, 0x45C / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_zcal_init_dev1. - { 0x00010100, 0x594 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_tx_pwrd4. - { 0x00400010, 0x598 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // emc_pmacro_tx_pwrd5. - { 0x00000001, 0x630 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_adr_cfg. 2 Ranks. - { 0x00002000, 0x64C / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_cfg. 8GB total density. - { 0x00000002, 0x670 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_arb_timing_faw. - { 0x00000002, 0x680 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_arb_timing_r2r. - { 0x02020001, 0x694 / 4, LPDDR4X_8GB_SAMSUNG_1Y_A }, // mc_emem_arb_da_turns. -*/ - - // Micron LPDDR4X 4GB MT53D1024M32D1NP-053-WT:F 10nm-class (1y-01) Die-F for Newer Iowa/Hoag/Aula. - { 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_auto_cal_config2. - { 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_auto_cal_vref_sel0. - { 0x00000006, 0x1CC / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_quse. - { 0x00000005, 0x1D0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_quse_width. - { 0x00000003, 0x1DC / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_einput. - { 0x0000000C, 0x1E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_einput_duration. - { 0x00000008, 0x24C / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_tfaw. - { 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_mrw14. - { 0x80000713, 0x32C / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // emc_dyn_self_ref_control. - { 0x00000001, 0x670 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // mc_emem_arb_timing_faw. - { 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // mc_video_protect_gpu_override0. - { 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_MICRON_MT53E512M32D2NP_046_WTF }, // mc_video_protect_gpu_override1. - - // Hynix LPDDR4X 4GB 10nm-class (1y-01) Die-A for Unknown Iowa/Hoag/Aula. - { 0x05500000, 0x0D4 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_auto_cal_config2. - { 0xC9AFBCBC, 0x0F4 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_auto_cal_vref_sel0. - { 0x00000006, 0x1CC / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_quse. - { 0x00000005, 0x1D0 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_quse_width. - { 0x00000003, 0x1DC / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_einput. - { 0x0000000C, 0x1E0 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_einput_duration. - { 0x00000008, 0x24C / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_tfaw. - { 0x88161414, 0x2E0 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_mrw14. - { 0x80000713, 0x32C / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // emc_dyn_self_ref_control. - { 0x00000001, 0x670 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_emem_arb_timing_faw. - { 0xE4FACB43, 0x6D4 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_video_protect_vpr_override. + TSEC, NVENC. - { 0x0600FED3, 0x6D8 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_video_protect_vpr_override1. + TSECB, TSEC1, TSECB1. - { 0x2A800000, 0x6DC / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_video_protect_gpu_override0. - { 0x00000002, 0x6E0 / 4, LPDDR4X_4GB_HYNIX_1Y_A }, // mc_video_protect_gpu_override1. - - //!TODO: Too many duplicates. + { 0x00000001, 0x134 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_adr_cfg. 2 Ranks. + { 0x08010004, 0x2B8 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_mrw1. + { 0x08020000, 0x2BC / 4, DRAM_CC_LPDDR4X_8GB }, // emc_mrw2. + { 0x080D0000, 0x2C0 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_mrw3. + { 0x08033131, 0x2C8 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_mrw6. + { 0x080B0000, 0x2CC / 4, DRAM_CC_LPDDR4X_8GB }, // emc_mrw8. + { 0x0C0E5D5D, 0x2D0 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_mrw9. + { 0x080C5D5D, 0x2D4 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_mrw10. + { 0x0C0D0808, 0x2D8 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_mrw12. + { 0x0C0D0000, 0x2DC / 4, DRAM_CC_LPDDR4X_8GB }, // emc_mrw13. + { 0x08161414, 0x2E0 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_mrw14. + { 0x08010004, 0x2E4 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_mrw_extra. + { 0x00000000, 0x340 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_dev_select. Both devices. + { 0x0051004F, 0x450 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_zcal_mrw_cmd. + { 0x40000001, 0x45C / 4, DRAM_CC_LPDDR4X_8GB }, // emc_zcal_init_dev1. + { 0x00000000, 0x594 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_pmacro_tx_pwrd4. + { 0x00001000, 0x598 / 4, DRAM_CC_LPDDR4X_8GB }, // emc_pmacro_tx_pwrd5. + { 0x00000001, 0x630 / 4, DRAM_CC_LPDDR4X_8GB }, // mc_emem_adr_cfg. 2 Ranks. + { 0x00002000, 0x64C / 4, DRAM_CC_LPDDR4X_8GB }, // mc_emem_cfg. 8GB total density. + { 0x00000002, 0x680 / 4, DRAM_CC_LPDDR4X_8GB }, // mc_emem_arb_timing_r2r. + { 0x02020001, 0x694 / 4, DRAM_CC_LPDDR4X_8GB }, // mc_emem_arb_da_turns. }; diff --git a/bdk/mem/smmu.c b/bdk/mem/smmu.c index f2f20fb..8bc9aac 100644 --- a/bdk/mem/smmu.c +++ b/bdk/mem/smmu.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2018 naehrwert * Copyright (c) 2018 balika011 + * 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, @@ -18,10 +19,10 @@ #include #include +#include #include #include #include -#include #include bool smmu_used = false; @@ -70,18 +71,19 @@ void smmu_flush_all() { MC(MC_SMMU_PTC_FLUSH) = 0; smmu_flush_regs(); + MC(MC_SMMU_TLB_FLUSH) = 0; smmu_flush_regs(); } void smmu_init(u32 secmon_base) { - MC(MC_SMMU_PTB_ASID) = 0; - MC(MC_SMMU_PTB_DATA) = 0; + MC(MC_SMMU_PTB_ASID) = 0; + MC(MC_SMMU_PTB_DATA) = 0; MC(MC_SMMU_TLB_CONFIG) = 0x30000030; MC(MC_SMMU_PTC_CONFIG) = 0x28000F3F; - MC(MC_SMMU_PTC_FLUSH) = 0; - MC(MC_SMMU_TLB_FLUSH) = 0; + MC(MC_SMMU_PTC_FLUSH) = 0; + MC(MC_SMMU_TLB_FLUSH) = 0; // Set the secmon address *(u32 *)(smmu_payload + 0x30) = secmon_base; @@ -163,8 +165,8 @@ u32 *smmu_init_for_tsec() void smmu_deinit_for_tsec() { - MC(MC_SMMU_PTB_ASID) = 1; - MC(MC_SMMU_PTB_DATA) = 0; + MC(MC_SMMU_PTB_ASID) = 1; + MC(MC_SMMU_PTB_DATA) = 0; MC(MC_SMMU_TSEC_ASID) = 0; smmu_flush_regs(); } diff --git a/bdk/memory_map.h b/bdk/memory_map.h index 467364e..e24d924 100644 --- a/bdk/memory_map.h +++ b/bdk/memory_map.h @@ -17,7 +17,6 @@ #ifndef _MEMORY_MAP_H_ #define _MEMORY_MAP_H_ -//#define IPL_STACK_TOP 0x4003FF00 /* --- BIT/BCT: 0x40000000 - 0x40003000 --- */ /* --- IPL: 0x40008000 - 0x40028000 --- */ #define LDR_LOAD_ADDR 0x40007000 @@ -25,13 +24,20 @@ #define IPL_LOAD_ADDR 0x40008000 #define IPL_SZ_MAX SZ_128K -/* --- XUSB EP context and TRB ring buffers --- */ -#define XUSB_RING_ADDR 0x40020000 +#define XUSB_RING_ADDR 0x40020000 // XUSB EP context and TRB ring buffers. -#define SECMON_MIN_START 0x4002B000 +#define SECMON_MIN_START 0x4002B000 // Minimum reserved address for secmon. #define SDRAM_PARAMS_ADDR 0x40030000 // SDRAM extraction buffer during sdram init. -#define CBFS_DRAM_EN_ADDR 0x4003e000 // u32. + +/* start.S / exception_handlers.S */ +#define SYS_STACK_TOP_INIT 0x4003FF00 +#define FIQ_STACK_TOP 0x40040000 +#define IRQ_STACK_TOP 0x40040000 +#define IPL_RELOC_ADDR 0x4003FF00 +#define IPL_RELOC_SZ 0x10 +#define EXCP_STORAGE_ADDR 0x4003FFF0 +#define EXCP_STORAGE_SZ 0x10 /* --- DRAM START --- */ #define DRAM_START 0x80000000 @@ -95,6 +101,7 @@ #define NYX_FB2_ADDRESS 0xF6600000 #define NYX_FB_SZ 0x384000 // 1280 x 720 x 4. +/* OBSOLETE: Very old hwinit based payloads were setting a carveout here. */ #define DRAM_MEM_HOLE_ADR 0xF6A00000 #define DRAM_MEM_HOLE_SZ 0x8140000 /* --- Hole: 129MB 0xF6A00000 - 0xFEB3FFFF --- */ diff --git a/bdk/power/bm92t36.c b/bdk/power/bm92t36.c index d1496f7..faa1db5 100644 --- a/bdk/power/bm92t36.c +++ b/bdk/power/bm92t36.c @@ -1,7 +1,7 @@ /* * USB-PD driver for Nintendo Switch's TI BM92T36 * - * Copyright (c) 2020 CTCaer + * Copyright (c) 2020-2023 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, @@ -73,18 +73,23 @@ void bm92t36_get_sink_info(bool *inserted, usb_pd_objects_t *usb_pd) if (inserted) { + memset(buf, 0, sizeof(buf)); _bm92t36_read_reg(buf, 2, STATUS1_REG); *inserted = buf[0] & STATUS1_INSERT ? true : false; } if (usb_pd) { + memset(buf, 0, sizeof(buf)); _bm92t36_read_reg(buf, 29, READ_PDOS_SRC_REG); memcpy(pdos, &buf[1], 28); memset(usb_pd, 0, sizeof(usb_pd_objects_t)); usb_pd->pdo_no = buf[0] / sizeof(pd_object_t); + if (usb_pd->pdo_no > 7) + usb_pd->pdo_no = 7; + for (u32 i = 0; i < usb_pd->pdo_no; i++) { usb_pd->pdos[i].amperage = pdos[i].amp * 10; diff --git a/bdk/power/bq24193.h b/bdk/power/bq24193.h index 1b6e717..399e225 100644 --- a/bdk/power/bq24193.h +++ b/bdk/power/bq24193.h @@ -28,7 +28,7 @@ // REG 1 masks. #define BQ24193_PORCONFIG_BOOST_MASK (1<<0) -#define BQ24193_PORCONFIG_SYSMIN_MASK (7<<1) +#define BQ24193_PORCONFIG_SYSMIN_MASK (7<<1) // 3000uV HOS default. #define BQ24193_PORCONFIG_CHGCONFIG_MASK (3<<4) #define BQ24193_PORCONFIG_CHGCONFIG_CHARGER_EN (1<<4) #define BQ24193_PORCONFIG_I2CWATCHDOG_MASK (1<<6) diff --git a/bdk/power/max17050.c b/bdk/power/max17050.c index a561724..c718d2b 100644 --- a/bdk/power/max17050.c +++ b/bdk/power/max17050.c @@ -24,7 +24,7 @@ #include "max17050.h" #include -#include +#include #define BASE_SNS_UOHM 5000 diff --git a/bdk/power/max77620.h b/bdk/power/max77620.h index 03c9512..3d41459 100644 --- a/bdk/power/max77620.h +++ b/bdk/power/max77620.h @@ -318,7 +318,7 @@ #define MAX77620_REG_CID2 0x5A #define MAX77620_REG_CID3 0x5B #define MAX77620_REG_CID4 0x5C // OTP version. -#define MAX77620_REG_CID5 0x5D +#define MAX77620_REG_CID5 0x5D // ES version. #define MAX77620_CID_DIDO_MASK 0xF #define MAX77620_CID_DIDO_SHIFT 0 #define MAX77620_CID_DIDM_MASK 0xF0 diff --git a/bdk/power/max7762x.c b/bdk/power/max7762x.c index a7d30ce..9431953 100644 --- a/bdk/power/max7762x.c +++ b/bdk/power/max7762x.c @@ -20,8 +20,8 @@ #include #include #include +#include #include -#include #define REGULATOR_SD 0 #define REGULATOR_LDO 1 @@ -75,7 +75,7 @@ typedef struct _max77620_regulator_t static const max77620_regulator_t _pmic_regulators[] = { { "sd0", 12500, 600000, 625000, 1400000, REGULATOR_SD, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, MAX77620_SD0_VOLT_MASK, {{ MAX77620_REG_FPS_SD0, 1, 7, 1 }} }, - { "sd1", 12500, 600000, 1125000, 1250000, REGULATOR_SD, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, {{ MAX77620_REG_FPS_SD1, 0, 1, 5 }} }, + { "sd1", 12500, 600000, 1125000, 1175000, REGULATOR_SD, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, {{ MAX77620_REG_FPS_SD1, 0, 1, 5 }} }, { "sd2", 12500, 600000, 1325000, 1350000, REGULATOR_SD, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD2, 1, 5, 2 }} }, { "sd3", 12500, 600000, 1800000, 1800000, REGULATOR_SD, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD3, 0, 3, 3 }} }, { "ldo0", 25000, 800000, 1200000, 1200000, REGULATOR_LDO, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO0, 3, 7, 0 }} }, @@ -88,11 +88,11 @@ static const max77620_regulator_t _pmic_regulators[] = { { "ldo7", 50000, 800000, 1050000, 1050000, REGULATOR_LDO, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO7, 1, 4, 3 }} }, { "ldo8", 50000, 800000, 1050000, 2800000, REGULATOR_LDO, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO8, 3, 7, 0 }} }, - { "max77621_CPU", 6250, 606250, 1000000, 1400000, REGULATOR_BC0, MAX77621_VOUT_REG, MAX77621_VOUT_DVS_REG, MAX77621_DVC_DVS_VOLT_MASK, {{ MAX77621_CPU_CTRL1_POR_DEFAULT, MAX77621_CPU_CTRL1_HOS_DEFAULT, MAX77621_CPU_CTRL2_POR_DEFAULT, MAX77621_CPU_CTRL2_HOS_DEFAULT }} }, - { "max77621_GPU", 6250, 606250, 1200000, 1400000, REGULATOR_BC0, MAX77621_VOUT_REG, MAX77621_VOUT_DVS_REG, MAX77621_DVC_DVS_VOLT_MASK, {{ MAX77621_CPU_CTRL1_POR_DEFAULT, MAX77621_CPU_CTRL1_HOS_DEFAULT, MAX77621_CPU_CTRL2_POR_DEFAULT, MAX77621_CPU_CTRL2_HOS_DEFAULT }} }, + { "max77621_CPU", 6250, 606250, 1000000, 1400000, REGULATOR_BC0, MAX77621_REG_VOUT, MAX77621_REG_VOUT_DVS, MAX77621_DVC_DVS_VOLT_MASK, {{ MAX77621_CPU_CTRL1_POR_DEFAULT, MAX77621_CPU_CTRL1_HOS_DEFAULT, MAX77621_CPU_CTRL2_POR_DEFAULT, MAX77621_CPU_CTRL2_HOS_DEFAULT }} }, + { "max77621_GPU", 6250, 606250, 1200000, 1400000, REGULATOR_BC0, MAX77621_REG_VOUT, MAX77621_REG_VOUT_DVS, MAX77621_DVC_DVS_VOLT_MASK, {{ MAX77621_CPU_CTRL1_POR_DEFAULT, MAX77621_CPU_CTRL1_HOS_DEFAULT, MAX77621_CPU_CTRL2_POR_DEFAULT, MAX77621_CPU_CTRL2_HOS_DEFAULT }} }, { "max77812_CPU", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M4_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M4_MASK, MAX77812_EN_CTRL_EN_M4_SHIFT, 0, 0 }} }, + { "max77812_RAM", 5000, 250000, 600000, 650000, REGULATOR_BC1, MAX77812_REG_M3_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M3_MASK, MAX77812_EN_CTRL_EN_M3_SHIFT, 0, 0 }} } // Only on PHASE211 configuration. //{ "max77812_GPU", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M1_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M1_MASK, MAX77812_EN_CTRL_EN_M1_SHIFT, 0, 0 }} }, - //{ "max77812_RAM", 5000, 250000, 600000, 1525000, REGULATOR_BC1, MAX77812_REG_M3_VOUT, MAX77812_REG_EN_CTRL, MAX77812_BUCK_VOLT_MASK, {{ MAX77812_EN_CTRL_EN_M3_MASK, MAX77812_EN_CTRL_EN_M3_SHIFT, 0, 0 }} } // Only on PHASE211 configuration. }; static u8 _max77812_get_address() @@ -121,7 +121,12 @@ static u8 _max7762x_get_i2c_address(u32 id) case REGULATOR_BC0: return (id == REGULATOR_CPU0 ? MAX77621_CPU_I2C_ADDR : MAX77621_GPU_I2C_ADDR); case REGULATOR_BC1: - return _max77812_get_address(); + { + u8 reg_addr = _max77812_get_address(); + if (id == REGULATOR_RAM0 && reg_addr == MAX77812_PHASE31_CPU_I2C_ADDR) + reg_addr = 0; + return reg_addr; + } default: return 0; } @@ -175,20 +180,22 @@ int max77620_regulator_config_fps(u32 id) return 1; } -int max7762x_regulator_set_voltage(u32 id, u32 mv) +int max7762x_regulator_set_voltage(u32 id, u32 uv) { if (id > REGULATOR_MAX) return 0; const max77620_regulator_t *reg = &_pmic_regulators[id]; - if (mv < reg->uv_min || mv > reg->uv_max) + if (uv < reg->uv_min || uv > reg->uv_max) return 0; u8 addr = _max7762x_get_i2c_address(id); + if (!addr) + return 0; // Calculate voltage multiplier. - u32 mult = (mv + reg->uv_step - 1 - reg->uv_min) / reg->uv_step; + u32 mult = (uv + reg->uv_step - 1 - reg->uv_min) / reg->uv_step; u8 val = i2c_recv_byte(I2C_5, addr, reg->volt_addr); val = (val & ~reg->volt_mask) | (mult & reg->volt_mask); @@ -249,6 +256,8 @@ int max7762x_regulator_enable(u32 id, bool enable) } u8 addr = _max7762x_get_i2c_address(id); + if (!addr) + return 0; // Read and enable/disable. u8 val = i2c_recv_byte(I2C_5, addr, reg_addr); @@ -291,6 +300,8 @@ void max77621_config_default(u32 id, bool por) return; u8 addr = _max7762x_get_i2c_address(id); + if (!addr) + return; if (por) { @@ -299,13 +310,13 @@ void max77621_config_default(u32 id, bool por) max7762x_regulator_enable(id, false); // Configure to default. - i2c_send_byte(I2C_5, addr, MAX77621_CONTROL1_REG, reg->ctrl.ctrl1_por); - i2c_send_byte(I2C_5, addr, MAX77621_CONTROL2_REG, reg->ctrl.ctrl2_por); + i2c_send_byte(I2C_5, addr, MAX77621_REG_CONTROL1, reg->ctrl.ctrl1_por); + i2c_send_byte(I2C_5, addr, MAX77621_REG_CONTROL2, reg->ctrl.ctrl2_por); } else { - i2c_send_byte(I2C_5, addr, MAX77621_CONTROL1_REG, reg->ctrl.ctrl1_hos); - i2c_send_byte(I2C_5, addr, MAX77621_CONTROL2_REG, reg->ctrl.ctrl2_hos); + i2c_send_byte(I2C_5, addr, MAX77621_REG_CONTROL1, reg->ctrl.ctrl1_hos); + i2c_send_byte(I2C_5, addr, MAX77621_REG_CONTROL2, reg->ctrl.ctrl2_hos); } } diff --git a/bdk/power/max7762x.h b/bdk/power/max7762x.h index 379b946..afacf8e 100644 --- a/bdk/power/max7762x.h +++ b/bdk/power/max7762x.h @@ -66,22 +66,22 @@ #define REGULATOR_LDO6 10 #define REGULATOR_LDO7 11 #define REGULATOR_LDO8 12 -#define REGULATOR_CPU0 13 -#define REGULATOR_GPU0 14 -#define REGULATOR_CPU1 15 -//#define REGULATOR_GPU1 16 -//#define REGULATOR_GPU1 17 -#define REGULATOR_MAX 15 +#define REGULATOR_CPU0 13 // T210 CPU. +#define REGULATOR_GPU0 14 // T210 CPU. +#define REGULATOR_CPU1 15 // T210B01 CPU. +#define REGULATOR_RAM0 16 // T210B01 RAM for PHASE211. +//#define REGULATOR_GPU1 17 // T210B01 CPU. +#define REGULATOR_MAX REGULATOR_RAM0 #define MAX77621_CPU_I2C_ADDR 0x1B #define MAX77621_GPU_I2C_ADDR 0x1C -#define MAX77621_VOUT_REG 0x00 -#define MAX77621_VOUT_DVS_REG 0x01 -#define MAX77621_CONTROL1_REG 0x02 -#define MAX77621_CONTROL2_REG 0x03 -#define MAX77621_CHIPID1_REG 0x04 -#define MAX77621_CHIPID2_REG 0x05 +#define MAX77621_REG_VOUT 0x00 +#define MAX77621_REG_VOUT_DVS 0x01 +#define MAX77621_REG_CONTROL1 0x02 +#define MAX77621_REG_CONTROL2 0x03 +#define MAX77621_REG_CHIPID1 0x04 +#define MAX77621_REG_CHIPID2 0x05 /* MAX77621_VOUT_DVC_DVS */ #define MAX77621_DVC_DVS_VOLT_MASK 0x7F @@ -114,11 +114,10 @@ #define MAX77621_INDUCTOR_PLUS_60_PER 3 #define MAX77621_INDUCTOR_MASK 3 -#define MAX77621_CKKADV_TRIP_75mV_PER_US 0x0 -#define MAX77621_CKKADV_TRIP_150mV_PER_US BIT(2) -#define MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS BIT(3) -#define MAX77621_CKKADV_TRIP_DISABLE (BIT(2) | BIT(3)) -#define MAX77621_CKKADV_TRIP_MASK (BIT(2) | BIT(3)) +#define MAX77621_CKKADV_TRIP_75mV_PER_US (0 << 2) +#define MAX77621_CKKADV_TRIP_150mV_PER_US (1u << 2) +#define MAX77621_CKKADV_TRIP_DISABLE (3u << 2) +#define MAX77621_CKKADV_TRIP_MASK (3u << 2) #define MAX77621_FT_ENABLE BIT(4) #define MAX77621_DISCH_ENABLE BIT(5) @@ -126,18 +125,17 @@ #define MAX77621_T_JUNCTION_120 BIT(7) #define MAX77621_CPU_CTRL1_POR_DEFAULT (MAX77621_RAMP_50mV_PER_US) -#define MAX77621_CPU_CTRL1_HOS_DEFAULT (MAX77621_AD_ENABLE | \ - MAX77621_NFSR_ENABLE | \ - MAX77621_SNS_ENABLE | \ +#define MAX77621_CPU_CTRL1_HOS_DEFAULT (MAX77621_AD_ENABLE | \ + MAX77621_NFSR_ENABLE | \ + MAX77621_SNS_ENABLE | \ MAX77621_RAMP_12mV_PER_US) -#define MAX77621_CPU_CTRL2_POR_DEFAULT (MAX77621_T_JUNCTION_120 | \ - MAX77621_FT_ENABLE | \ - MAX77621_CKKADV_TRIP_75mV_PER_US_HIST_DIS | \ - MAX77621_CKKADV_TRIP_150mV_PER_US | \ +#define MAX77621_CPU_CTRL2_POR_DEFAULT (MAX77621_T_JUNCTION_120 | \ + MAX77621_FT_ENABLE | \ + MAX77621_CKKADV_TRIP_DISABLE | \ MAX77621_INDUCTOR_NOMINAL) -#define MAX77621_CPU_CTRL2_HOS_DEFAULT (MAX77621_T_JUNCTION_120 | \ - MAX77621_WDTMR_ENABLE | \ - MAX77621_CKKADV_TRIP_75mV_PER_US | \ +#define MAX77621_CPU_CTRL2_HOS_DEFAULT (MAX77621_T_JUNCTION_120 | \ + MAX77621_WDTMR_ENABLE | \ + MAX77621_CKKADV_TRIP_75mV_PER_US | \ MAX77621_INDUCTOR_NOMINAL) #define MAX77621_CTRL_HOS_CFG 0 @@ -145,7 +143,7 @@ int max77620_regulator_get_status(u32 id); int max77620_regulator_config_fps(u32 id); -int max7762x_regulator_set_voltage(u32 id, u32 mv); +int max7762x_regulator_set_voltage(u32 id, u32 uv); int max7762x_regulator_enable(u32 id, bool enable); void max77620_config_gpio(u32 id, bool enable); void max77620_config_default(); diff --git a/bdk/power/max77812.h b/bdk/power/max77812.h index c7db199..cdd2899 100644 --- a/bdk/power/max77812.h +++ b/bdk/power/max77812.h @@ -66,21 +66,22 @@ #define MAX77812_REG_M2_VOUT_S 0x2C #define MAX77812_REG_M3_VOUT_S 0x2D #define MAX77812_REG_M4_VOUT_S 0x2E -#define MAX77812_REG_M1_CFG 0x2F -#define MAX77812_REG_M2_CFG 0x30 -#define MAX77812_REG_M3_CFG 0x31 -#define MAX77812_REG_M4_CFG 0x32 -#define MAX77812_REG_GLB_CFG1 0x33 -#define MAX77812_REG_GLB_CFG2 0x34 +#define MAX77812_REG_M1_CFG 0x2F // HOS: M1_ILIM - 7.2A/4.8A. +#define MAX77812_REG_M2_CFG 0x30 // HOS: M2_ILIM - 7.2A/4.8A. +#define MAX77812_REG_M3_CFG 0x31 // HOS: M3_ILIM - 7.2A/4.8A. +#define MAX77812_REG_M4_CFG 0x32 // HOS: M4_ILIM - 7.2A/4.8A. +#define MAX77812_REG_GLB_CFG1 0x33 // HOS: B_SD_SR/B_SS_SR - 5mV/us. +#define MAX77812_REG_GLB_CFG2 0x34 // HOS: B_RD_SR/B_RU_SR - 5mV/us #define MAX77812_REG_GLB_CFG3 0x35 /*! Protected area and settings only for MAX77812_ES2_VERSION */ #define MAX77812_REG_GLB_CFG4 0x36 -#define MAX77812_REG_GLB_CFG5 0x37 -#define MAX77812_REG_GLB_CFG6 0x38 +#define MAX77812_REG_GLB_CFG5 0x37 // HOS: 0x3E. Unmasked write. +#define MAX77812_REG_GLB_CFG6 0x38 // HOS: 0x90. Unmasked write. #define MAX77812_REG_GLB_CFG7 0x39 -#define MAX77812_REG_GLB_CFG8 0x3A -#define MAX77812_REG_PROT_ACCESS 0xFD +#define MAX77812_REG_GLB_CFG8 0x3A // HOS: 0x3A. Unmasked write. + +#define MAX77812_REG_PROT_ACCESS 0xFD // 0x00: Lock, 0x5A: Unlock. #define MAX77812_REG_MAX 0xFD #define MAX77812_REG_EN_CTRL_MASK(n) BIT(n) diff --git a/bdk/power/regulator_5v.c b/bdk/power/regulator_5v.c index 379f7a6..557dae9 100644 --- a/bdk/power/regulator_5v.c +++ b/bdk/power/regulator_5v.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021 CTCaer + * Copyright (c) 2019-2023 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,38 +27,31 @@ static bool usb_src = false; void regulator_5v_enable(u8 dev) { + bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210; + // The power supply selection from battery or USB is automatic. if (!reg_5v_dev) { // Fan and Rail power from battery 5V regulator. PINMUX_AUX(PINMUX_AUX_SATA_LED_ACTIVE) = 1; - gpio_config(GPIO_PORT_A, GPIO_PIN_5, GPIO_MODE_GPIO); - gpio_output_enable(GPIO_PORT_A, GPIO_PIN_5, GPIO_OUTPUT_ENABLE); - gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH); + gpio_direction_output(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH); - // Only Icosa and Iowa have USB 5V VBUS rails. Skip on Hoag/Aula. - u32 hw_type = fuse_read_hw_type(); - if (hw_type == FUSE_NX_HW_TYPE_ICOSA || - hw_type == FUSE_NX_HW_TYPE_IOWA) + // Only Icosa has USB 5V VBUS rails. + if (tegra_t210) { // Fan and Rail power from USB 5V VBUS. PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_LPDR | 1; - gpio_config(GPIO_PORT_CC, GPIO_PIN_4, GPIO_MODE_GPIO); - gpio_output_enable(GPIO_PORT_CC, GPIO_PIN_4, GPIO_OUTPUT_ENABLE); - gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW); + gpio_direction_output(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW); } - // Enable GPIO AO IO rail for T210. - if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210) - { - // Make sure GPIO power is enabled. - PMC(APBDEV_PMC_NO_IOPOWER) &= ~PMC_NO_IOPOWER_GPIO_IO_EN; - (void)PMC(APBDEV_PMC_NO_IOPOWER); // Commit write. + // Make sure GPIO IO power is enabled. + PMC(APBDEV_PMC_NO_IOPOWER) &= ~PMC_NO_IOPOWER_GPIO_IO_EN; + (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; + (void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write. - // Override power detect for GPIO AO IO rails. - PMC(APBDEV_PMC_PWR_DET_VAL) &= ~PMC_PWR_DET_GPIO_IO_EN; - (void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write. - } usb_src = false; } reg_5v_dev |= dev; @@ -66,36 +59,23 @@ void regulator_5v_enable(u8 dev) void regulator_5v_disable(u8 dev) { + bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210; + reg_5v_dev &= ~dev; if (!reg_5v_dev) { // Rail power from battery 5V regulator. gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_LOW); - gpio_output_enable(GPIO_PORT_A, GPIO_PIN_5, GPIO_OUTPUT_DISABLE); - gpio_config(GPIO_PORT_A, GPIO_PIN_5, GPIO_MODE_SPIO); - PINMUX_AUX(PINMUX_AUX_SATA_LED_ACTIVE) = PINMUX_PARKED | PINMUX_INPUT_ENABLE; - // Only Icosa and Iowa have USB 5V VBUS rails. Skip on Hoag/Aula. - u32 hw_type = fuse_read_hw_type(); - if (hw_type == FUSE_NX_HW_TYPE_ICOSA || - hw_type == FUSE_NX_HW_TYPE_IOWA) + // Only Icosa has USB 5V VBUS rails. + if (tegra_t210) { // Rail power from USB 5V VBUS. gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW); - gpio_output_enable(GPIO_PORT_CC, GPIO_PIN_4, GPIO_OUTPUT_DISABLE); - gpio_config(GPIO_PORT_CC, GPIO_PIN_4, GPIO_MODE_SPIO); - PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_IO_HV | PINMUX_LPDR | PINMUX_PARKED | PINMUX_INPUT_ENABLE; usb_src = false; } - - // GPIO AO IO rails. - if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210) - { - PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_GPIO_IO_EN; - (void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write. - } } } @@ -106,10 +86,8 @@ bool regulator_5v_get_dev_enabled(u8 dev) void regulator_5v_usb_src_enable(bool enable) { - // Only for Icosa/Iowa. Skip on Hoag/Aula. - u32 hw_type = fuse_read_hw_type(); - if (hw_type != FUSE_NX_HW_TYPE_ICOSA && - hw_type != FUSE_NX_HW_TYPE_IOWA) + // Only for Icosa. + if (hw_get_chip_id() != GP_HIDREV_MAJOR_T210) return; if (enable && !usb_src) diff --git a/bdk/rtc/max77620-rtc.c b/bdk/rtc/max77620-rtc.c index 164df75..ab01b40 100644 --- a/bdk/rtc/max77620-rtc.c +++ b/bdk/rtc/max77620-rtc.c @@ -1,7 +1,7 @@ /* * PMIC Real Time Clock driver for Nintendo Switch's MAX77620-RTC * - * Copyright (c) 2018-2019 CTCaer + * Copyright (c) 2018-2022 CTCaer * Copyright (c) 2019 shchmue * * This program is free software; you can redistribute it and/or modify it @@ -19,7 +19,14 @@ #include #include -#include +#include +#include +#include + +void max77620_rtc_prep_read() +{ + i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_UPDATE0_REG, MAX77620_RTC_READ_UPDATE); +} void max77620_rtc_get_time(rtc_time_t *time) { @@ -35,7 +42,7 @@ void max77620_rtc_get_time(rtc_time_t *time) // Get time. time->sec = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_SEC_REG) & 0x7F; time->min = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_MIN_REG) & 0x7F; - u8 hour = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_HOUR_REG); + u8 hour = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_HOUR_REG); time->hour = hour & 0x1F; if (!(val & MAX77620_RTC_24H) && (hour & MAX77620_RTC_HOUR_PM_MASK)) @@ -53,7 +60,7 @@ void max77620_rtc_get_time(rtc_time_t *time) } // Get date. - time->day = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_DATE_REG) & 0x1f; + time->day = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_DATE_REG) & 0x1f; time->month = (i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_MONTH_REG) & 0xF) - 1; time->year = (i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_YEAR_REG) & 0x7F) + 2000; } @@ -64,6 +71,7 @@ void max77620_rtc_stop_alarm() // Update RTC regs from RTC clock. i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_UPDATE0_REG, MAX77620_RTC_READ_UPDATE); + msleep(16); // Stop alarm for both ALARM1 and ALARM2. Horizon uses ALARM2. for (int i = 0; i < (MAX77620_RTC_NR_TIME_REGS * 2); i++) @@ -82,9 +90,9 @@ void max77620_rtc_epoch_to_date(u32 epoch, rtc_time_t *time) u32 tmp, edays, year, month, day; // Set time. - time->sec = epoch % 60; + time->sec = epoch % 60; epoch /= 60; - time->min = epoch % 60; + time->min = epoch % 60; epoch /= 60; time->hour = epoch % 24; epoch /= 24; @@ -99,14 +107,14 @@ void max77620_rtc_epoch_to_date(u32 epoch, rtc_time_t *time) day = edays - month * 30 - month * 601 / 1000; // Month/Year offset. - if(month < 14) + if (month < 14) { year -= 4716; month--; } else { - year -= 4715; + year -= 4715; month -= 13; } @@ -129,13 +137,13 @@ u32 max77620_rtc_date_to_epoch(const rtc_time_t *time) month = time->month; // Month/Year offset. - if(month < 3) + if (month < 3) { month += 12; year--; } - epoch = (365 * year) + (year >> 2) - (year / 100) + (year / 400); // Years to days. + epoch = (365 * year) + (year >> 2) - (year / 100) + (year / 400); // Years to days. epoch += (30 * month) + (3 * (month + 1) / 5) + time->day; // Months to days. epoch -= 719561; // Epoch time is 1/1/1970. @@ -145,3 +153,45 @@ u32 max77620_rtc_date_to_epoch(const rtc_time_t *time) return epoch; } + +void max77620_rtc_set_reboot_reason(rtc_reboot_reason_t *rr) +{ + max77620_rtc_stop_alarm(); + + // Set reboot reason. + i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM1_YEAR_REG, rr->enc.val1); + i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM2_YEAR_REG, rr->enc.val2); + + // Set reboot reason magic. + i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM1_WEEKDAY_REG, RTC_REBOOT_REASON_MAGIC); + i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM2_WEEKDAY_REG, RTC_REBOOT_REASON_MAGIC); + + // Update RTC clock from RTC regs. + i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_UPDATE0_REG, MAX77620_RTC_WRITE_UPDATE); + msleep(16); +} + +bool max77620_rtc_get_reboot_reason(rtc_reboot_reason_t *rr) +{ + u8 magic[2]; + + // Get reboot reason magic. + magic[0] = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM1_WEEKDAY_REG); + magic[1] = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM2_WEEKDAY_REG); + + // Magic must be correct and match on both registers. + if (magic[0] != RTC_REBOOT_REASON_MAGIC || magic[0] != magic[1]) + return false; + + // Reboot reason setter is expected to have updated the actual regs already. + rr->enc.val1 = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM1_YEAR_REG); + rr->enc.val2 = i2c_recv_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM2_YEAR_REG); + + // Clear magic and update actual regs. + i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM1_WEEKDAY_REG, 0); + i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_ALARM2_WEEKDAY_REG, 0); + i2c_send_byte(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_RTC_UPDATE0_REG, MAX77620_RTC_WRITE_UPDATE); + + // Return reboot reason. False if [config] was selected. + return true; +} diff --git a/bdk/rtc/max77620-rtc.h b/bdk/rtc/max77620-rtc.h index 93b24c4..b0d616d 100644 --- a/bdk/rtc/max77620-rtc.h +++ b/bdk/rtc/max77620-rtc.h @@ -1,7 +1,7 @@ /* * PMIC Real Time Clock driver for Nintendo Switch's MAX77620-RTC * - * Copyright (c) 2018 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, @@ -25,6 +25,8 @@ #define MAX77620_RTC_NR_TIME_REGS 7 +#define MAX77620_RTC_RTCINT_REG 0x00 +#define MAX77620_RTC_RTCINTM_REG 0x01 #define MAX77620_RTC_CONTROLM_REG 0x02 #define MAX77620_RTC_CONTROL_REG 0x03 #define MAX77620_RTC_BIN_FORMAT BIT(0) @@ -34,6 +36,9 @@ #define MAX77620_RTC_WRITE_UPDATE BIT(0) #define MAX77620_RTC_READ_UPDATE BIT(4) +#define MAX77620_RTC_UPDATE1_REG 0x05 +#define MAX77620_RTC_RTCSMPL_REG 0x06 + #define MAX77620_RTC_SEC_REG 0x07 #define MAX77620_RTC_MIN_REG 0x08 #define MAX77620_RTC_HOUR_REG 0x09 @@ -69,9 +74,45 @@ typedef struct _rtc_time_t { u16 year; } rtc_time_t; +#define RTC_REBOOT_REASON_MAGIC 0x77 // 7-bit reg. + +enum { + REBOOT_REASON_NOP = 0, // Use [config]. + REBOOT_REASON_SELF = 1, // Use autoboot_idx/autoboot_list. + REBOOT_REASON_MENU = 2, // Force menu. + REBOOT_REASON_UMS = 3, // Force selected UMS partition. + REBOOT_REASON_REC = 4, // Set PMC_SCRATCH0_MODE_RECOVERY and reboot to self. + REBOOT_REASON_PANIC = 5 // Inform bootloader that panic occured if T210B01. +}; + +typedef struct _rtc_rr_decoded_t +{ + u16 reason:4; + u16 autoboot_idx:4; + u16 autoboot_list:1; + u16 ums_idx:3; +} rtc_rr_decoded_t; + +typedef struct _rtc_rr_encoded_t +{ + u16 val1:6; // 6-bit reg. + u16 val2:6; // 6-bit reg. +} rtc_rr_encoded_t; + +typedef struct _rtc_reboot_reason_t +{ + union { + rtc_rr_decoded_t dec; + rtc_rr_encoded_t enc; + }; +} rtc_reboot_reason_t; + +void max77620_rtc_prep_read(); void max77620_rtc_get_time(rtc_time_t *time); void max77620_rtc_stop_alarm(); void max77620_rtc_epoch_to_date(u32 epoch, rtc_time_t *time); -u32 max77620_rtc_date_to_epoch(const rtc_time_t *time); +u32 max77620_rtc_date_to_epoch(const rtc_time_t *time); +void max77620_rtc_set_reboot_reason(rtc_reboot_reason_t *rr); +bool max77620_rtc_get_reboot_reason(rtc_reboot_reason_t *rr); #endif /* _MFD_MAX77620_RTC_H_ */ diff --git a/bdk/sec/se.c b/bdk/sec/se.c index 3621005..b6ddf18 100644 --- a/bdk/sec/se.c +++ b/bdk/sec/se.c @@ -23,8 +23,8 @@ #include #include #include +#include #include -#include typedef struct _se_ll_t { @@ -33,7 +33,8 @@ typedef struct _se_ll_t vu32 size; } se_ll_t; -se_ll_t *ll_dst, *ll_src; +se_ll_t ll_src, ll_dst; +se_ll_t *ll_src_ptr, *ll_dst_ptr; // Must be u32 aligned. static void _gf256_mul_x(void *block) { @@ -69,12 +70,12 @@ static void _gf256_mul_x_le(void *block) static void _se_ll_init(se_ll_t *ll, u32 addr, u32 size) { - ll->num = 0; + ll->num = 0; ll->addr = addr; ll->size = size; } -static void _se_ll_set(se_ll_t *dst, se_ll_t *src) +static void _se_ll_set(se_ll_t *src, se_ll_t *dst) { SE(SE_IN_LL_ADDR_REG) = (u32)src; SE(SE_OUT_LL_ADDR_REG) = (u32)dst; @@ -89,13 +90,16 @@ static int _se_wait() ; // Check for errors. - if ((SE(SE_INT_STATUS_REG) & SE_INT_ERR_STAT) || + if ((SE(SE_INT_STATUS_REG) & SE_INT_ERR_STAT) || (SE(SE_STATUS_REG) & SE_STATUS_STATE_MASK) != SE_STATUS_STATE_IDLE || - SE(SE_ERR_STATUS_REG) != 0) + (SE(SE_ERR_STATUS_REG) != 0) + ) + { return 0; + } // T210B01: IRAM/TZRAM/DRAM AHB coherency WAR. - if (!tegra_t210 && ll_dst) + if (!tegra_t210 && ll_dst_ptr) { u32 timeout = get_tmr_us() + 1000000; // Ensure data is out from SE. @@ -107,7 +111,7 @@ static int _se_wait() } // Ensure data is out from AHB. - if(ll_dst->addr >= DRAM_START) + if (ll_dst_ptr->addr >= DRAM_START) { timeout = get_tmr_us() + 200000; while (AHB_GIZMO(AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID) & MEM_WRQUE_SE_MST_ID) @@ -122,75 +126,52 @@ static int _se_wait() return 1; } -static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size, bool is_oneshot) -{ - ll_dst = NULL; - ll_src = NULL; - - if (dst) - { - ll_dst = (se_ll_t *)malloc(sizeof(se_ll_t)); - _se_ll_init(ll_dst, (u32)dst, dst_size); - } - - if (src) - { - ll_src = (se_ll_t *)malloc(sizeof(se_ll_t)); - _se_ll_init(ll_src, (u32)src, src_size); - } - - _se_ll_set(ll_dst, ll_src); - - SE(SE_ERR_STATUS_REG) = SE(SE_ERR_STATUS_REG); - SE(SE_INT_STATUS_REG) = SE(SE_INT_STATUS_REG); - - bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); - - SE(SE_OPERATION_REG) = op; - - if (is_oneshot) - { - int res = _se_wait(); - - bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); - - if (src) - { - free(ll_src); - ll_src = NULL; - } - if (dst) - { - free(ll_dst); - ll_dst = NULL; - } - - return res; - } - - return 1; -} - static int _se_execute_finalize() { int res = _se_wait(); - bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); + // Invalidate data after OP is done. + bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY, false); - if (ll_src) - { - free(ll_src); - ll_src = NULL; - } - if (ll_dst) - { - free(ll_dst); - ll_dst = NULL; - } + ll_src_ptr = NULL; + ll_dst_ptr = NULL; return res; } +static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size, bool is_oneshot) +{ + ll_src_ptr = NULL; + ll_dst_ptr = NULL; + + if (src) + { + ll_src_ptr = &ll_src; + _se_ll_init(ll_src_ptr, (u32)src, src_size); + } + + if (dst) + { + ll_dst_ptr = &ll_dst; + _se_ll_init(ll_dst_ptr, (u32)dst, dst_size); + } + + _se_ll_set(ll_src_ptr, ll_dst_ptr); + + SE(SE_ERR_STATUS_REG) = SE(SE_ERR_STATUS_REG); + SE(SE_INT_STATUS_REG) = SE(SE_INT_STATUS_REG); + + // Flush data before starting OP. + bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLEAN_WAY, false); + + SE(SE_OPERATION_REG) = op; + + if (is_oneshot) + return _se_execute_finalize(); + + return 1; +} + static int _se_execute_oneshot(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size) { return _se_execute(op, dst, dst_size, src, src_size, true); @@ -201,8 +182,7 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr if (!src || !dst) return 0; - u8 *block = (u8 *)malloc(SE_AES_BLOCK_SIZE); - memset(block, 0, SE_AES_BLOCK_SIZE); + u8 *block = (u8 *)calloc(1, SE_AES_BLOCK_SIZE); SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1; @@ -227,7 +207,7 @@ void se_rsa_acc_ctrl(u32 rs, u32 flags) { if (flags & SE_RSA_KEY_TBL_DIS_KEY_ACCESS_FLAG) SE(SE_RSA_KEYTABLE_ACCESS_REG + 4 * rs) = - (((flags >> 4) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) |(flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG)) ^ + (((flags >> 4) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) | (flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG)) ^ SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_USE_FLAG; if (flags & SE_RSA_KEY_LOCK_FLAG) SE(SE_RSA_SECURITY_PERKEY_REG) &= ~BIT(rs); @@ -304,8 +284,8 @@ void se_aes_iv_clear(u32 ks) int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input) { - SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTABLE); - SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT); + SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTABLE); + SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT); SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1; SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst) | SE_KEYTABLE_DST_WORD_QUAD(KEYS_0_3); @@ -333,14 +313,14 @@ int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, if (enc) { SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); - SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | - SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_TOP); + SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | + SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_TOP); } else { SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY); - SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVMEM) | - SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM); + SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVMEM) | + SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM); } SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1; return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size); @@ -355,8 +335,9 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_s { SE(SE_SPARE_REG) = SE_ECO(SE_ERRATA_FIX_ENABLE); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); - SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | - SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_CNTN(1); + SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | + SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | + SE_CRYPTO_CTR_CNTN(1); _se_aes_ctr_set(ctr); u32 src_size_aligned = src_size & 0xFFFFFFF0; @@ -570,9 +551,9 @@ int se_calc_sha256_finalize(void *hash, u32 *msg_left) int se_gen_prng128(void *dst) { // Setup config for X931 PRNG. - SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY); - SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_HASH(HASH_DISABLE) | SE_CRYPTO_XOR_POS(XOR_BYPASS) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); - SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_SRC(SRC_ENTROPY) | SE_RNG_CONFIG_MODE(MODE_NORMAL); + SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY); + SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_HASH(HASH_DISABLE) | SE_CRYPTO_XOR_POS(XOR_BYPASS) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); + SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_SRC(SRC_ENTROPY) | SE_RNG_CONFIG_MODE(MODE_NORMAL); //SE(SE_RNG_SRC_CONFIG_REG) = // SE_RNG_SRC_CONFIG_ENTR_SRC(RO_ENTR_ENABLE) | SE_RNG_SRC_CONFIG_ENTR_SRC_LOCK(RO_ENTR_LOCK_ENABLE); SE(SE_RNG_RESEED_INTERVAL_REG) = 1; @@ -588,9 +569,9 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize) u8 *aligned_buf = (u8 *)ALIGN((u32)buf, 0x40); // Set Secure Random Key. - SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_SRK); - SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(0) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); - SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_SRC(SRC_ENTROPY) | SE_RNG_CONFIG_MODE(MODE_FORCE_RESEED); + SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_SRK); + SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(0) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); + SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_SRC(SRC_ENTROPY) | SE_RNG_CONFIG_MODE(MODE_FORCE_RESEED); SE(SE_CRYPTO_LAST_BLOCK) = 0; _se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0); @@ -600,7 +581,7 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize) for (u32 i = 0; i < SE_AES_KEYSLOT_COUNT; i++) { SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) | - SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_0_3); + SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_0_3); SE(SE_CRYPTO_LAST_BLOCK) = 0; _se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0); @@ -609,7 +590,7 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize) if (keysize > SE_KEY_128_SIZE) { SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) | - SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_4_7); + SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_4_7); SE(SE_CRYPTO_LAST_BLOCK) = 0; _se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0); @@ -640,6 +621,51 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize) se_aes_key_clear(3); } + +int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size) +{ + int res = 0; + u8 *secret = (u8 *)malloc(0x40); + u8 *ipad = (u8 *)malloc(0x40 + src_size); + u8 *opad = (u8 *)malloc(0x60); + + if (key_size > 0x40) + { + if (!se_calc_sha256_oneshot(secret, key, key_size)) + goto out; + memset(secret + 0x20, 0, 0x20); + } + else + { + memcpy(secret, key, key_size); + memset(secret + key_size, 0, 0x40 - key_size); + } + + u32 *secret32 = (u32 *)secret; + u32 *ipad32 = (u32 *)ipad; + u32 *opad32 = (u32 *)opad; + for (u32 i = 0; i < 0x10; i++) + { + ipad32[i] = secret32[i] ^ 0x36363636; + opad32[i] = secret32[i] ^ 0x5C5C5C5C; + } + + memcpy(ipad + 0x40, src, src_size); + if (!se_calc_sha256_oneshot(dst, ipad, 0x40 + src_size)) + goto out; + memcpy(opad + 0x40, dst, 0x20); + if (!se_calc_sha256_oneshot(dst, opad, 0x60)) + goto out; + + res = 1; + +out:; + free(secret); + free(ipad); + free(opad); + return res; +} + // se_aes_cmac() was derived from Atmosphère's se_compute_aes_cmac int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size) { @@ -648,7 +674,7 @@ int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size) u8 *last_block = (u8 *)calloc(0x10, 1); // generate derived key - if (!se_aes_crypt_block_ecb(ks, 1, key, key)) + if (!se_aes_crypt_block_ecb(ks, ENCRYPT, key, key)) goto out; _gf256_mul_x(key); if (src_size & 0xF) @@ -693,48 +719,4 @@ out:; free(key); free(last_block); return res; -} - -int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size) -{ - int res = 0; - u8 *secret = (u8 *)malloc(0x40); - u8 *ipad = (u8 *)malloc(0x40 + src_size); - u8 *opad = (u8 *)malloc(0x60); - - if (key_size > 0x40) - { - if (!se_calc_sha256_oneshot(secret, key, key_size)) - goto out; - memset(secret + 0x20, 0, 0x20); - } - else - { - memcpy(secret, key, key_size); - memset(secret + key_size, 0, 0x40 - key_size); - } - - u32 *secret32 = (u32 *)secret; - u32 *ipad32 = (u32 *)ipad; - u32 *opad32 = (u32 *)opad; - for (u32 i = 0; i < 0x10; i++) - { - ipad32[i] = secret32[i] ^ 0x36363636; - opad32[i] = secret32[i] ^ 0x5C5C5C5C; - } - - memcpy(ipad + 0x40, src, src_size); - if (!se_calc_sha256_oneshot(dst, ipad, 0x40 + src_size)) - goto out; - memcpy(opad + 0x40, dst, 0x20); - if (!se_calc_sha256_oneshot(dst, opad, 0x60)) - goto out; - - res = 1; - -out:; - free(secret); - free(ipad); - free(opad); - return res; } \ No newline at end of file diff --git a/bdk/sec/se.h b/bdk/sec/se.h index be1c820..af6601b 100644 --- a/bdk/sec/se.h +++ b/bdk/sec/se.h @@ -42,7 +42,7 @@ int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u6 int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size); int se_calc_sha256_finalize(void *hash, u32 *msg_left); int se_gen_prng128(void *dst); -int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size); -int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size); +int se_aes_cmac(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size); +int se_calc_hmac_sha256(void *dst, const void *src, u32 src_size, const void *key, u32 key_size); #endif diff --git a/bdk/sec/tsec.c b/bdk/sec/tsec.c index 50a90ae..3dcf084 100644 --- a/bdk/sec/tsec.c +++ b/bdk/sec/tsec.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2021 CTCaer + * Copyright (c) 2018-2023 CTCaer * Copyright (c) 2018 balika011 * * This program is free software; you can redistribute it and/or modify it @@ -20,16 +20,17 @@ #include "tsec.h" #include "tsec_t210.h" +#include +#include +#include +#include #include #include #include #include #include #include -#include -#include -#include -#include +#include // #include @@ -57,9 +58,9 @@ static int _tsec_dma_pa_to_internal_100(int not_imem, int i_offset, int pa_offse else cmd = TSEC_DMATRFCMD_IMEM; // DMA IMEM (Instruction memmory) - TSEC(TSEC_DMATRFMOFFS) = i_offset; + TSEC(TSEC_DMATRFMOFFS) = i_offset; TSEC(TSEC_DMATRFFBOFFS) = pa_offset; - TSEC(TSEC_DMATRFCMD) = cmd; + TSEC(TSEC_DMATRFCMD) = cmd; return _tsec_dma_wait_idle(); } @@ -76,16 +77,16 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt) bpmp_freq_t prev_fid = bpmp_clk_rate_set(BPMP_CLK_NORMAL); // Enable clocks. - clock_enable_host1x(); - usleep(2); clock_enable_tsec(); clock_enable_sor_safe(); clock_enable_sor0(); clock_enable_sor1(); clock_enable_kfuse(); - kfuse_wait_ready(); + // Disable AHB aperture. + mc_disable_ahb_redirect(); + if (type == TSEC_FW_TYPE_NEW) { // Disable all CCPLEX core rails. @@ -95,23 +96,23 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt) pmc_enable_partition(POWER_RAIL_CE3, DISABLE); // Enable AHB aperture and set it to full mmio. - mc_enable_ahb_redirect(true); + mc_enable_ahb_redirect(); } // Configure Falcon. TSEC(TSEC_DMACTL) = 0; TSEC(TSEC_IRQMSET) = TSEC_IRQMSET_EXT(0xFF) | - TSEC_IRQMSET_WDTMR | - TSEC_IRQMSET_HALT | - TSEC_IRQMSET_EXTERR | - TSEC_IRQMSET_SWGEN0 | + TSEC_IRQMSET_WDTMR | + TSEC_IRQMSET_HALT | + TSEC_IRQMSET_EXTERR | + TSEC_IRQMSET_SWGEN0 | TSEC_IRQMSET_SWGEN1; TSEC(TSEC_IRQDEST) = TSEC_IRQDEST_EXT(0xFF) | - TSEC_IRQDEST_HALT | - TSEC_IRQDEST_EXTERR | - TSEC_IRQDEST_SWGEN0 | + TSEC_IRQDEST_HALT | + TSEC_IRQDEST_EXTERR | + TSEC_IRQDEST_SWGEN0 | TSEC_IRQDEST_SWGEN1; TSEC(TSEC_ITFEN) = TSEC_ITFEN_CTXEN | TSEC_ITFEN_MTHDEN; if (!_tsec_dma_wait_idle()) @@ -128,6 +129,7 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt) fwbuf = (u8 *)malloc(SZ_16K); u8 *fwbuf_aligned = (u8 *)ALIGN((u32)fwbuf, 0x100); memcpy(fwbuf_aligned, tsec_ctxt->fw, tsec_ctxt->size); + TSEC(TSEC_DMATRFBASE) = (u32)fwbuf_aligned >> 8; } @@ -180,7 +182,7 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt) mc = page_alloc(1); memcpy(mc, (void *)MC_BASE, SZ_PAGE); mc[MC_IRAM_BOM / 4] = 0; - mc[MC_IRAM_TOM / 4] = 0x80000000; + mc[MC_IRAM_TOM / 4] = DRAM_START; smmu_map(pdir, MC_BASE, (u32)mc, 1, _READABLE | _NONSECURE); // IRAM @@ -197,15 +199,15 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt) // Execute firmware. HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0x34C2E1DA; - TSEC(TSEC_STATUS) = 0; - TSEC(TSEC_BOOTKEYVER) = 1; // HOS uses key version 1. - TSEC(TSEC_BOOTVEC) = 0; - TSEC(TSEC_CPUCTL) = TSEC_CPUCTL_STARTCPU; + TSEC(TSEC_MAILBOX1) = 0; + TSEC(TSEC_MAILBOX0) = 1; // Set HOS key version. + TSEC(TSEC_BOOTVEC) = 0; + TSEC(TSEC_CPUCTL) = TSEC_CPUCTL_STARTCPU; if (type == TSEC_FW_TYPE_EMU) { - u32 start = get_tmr_us(); u32 k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4]; + u32 timeout = get_tmr_us() + 125000; u32 key[16] = {0}; u32 kidx = 0; @@ -220,7 +222,7 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt) } // Failsafe. - if ((u32)get_tmr_us() - start > 125000) + if ((u32)get_tmr_us() > timeout) break; } @@ -243,7 +245,7 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt) // for (int i = 0; i < kidx; i++) // gfx_printf("key %08X\n", key[i]); - // gfx_printf("cpuctl (%08X) mbox (%08X)\n", TSEC(TSEC_CPUCTL), TSEC(TSEC_STATUS)); + // gfx_printf("cpuctl (%08X) mbox (%08X)\n", TSEC(TSEC_CPUCTL), TSEC(TSEC_MAILBOX1)); // u32 errst = MC(MC_ERR_STATUS); // gfx_printf(" MC %08X %08X %08X\n", MC(MC_INTSTATUS), errst, MC(MC_ERR_ADR)); @@ -259,14 +261,18 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt) res = -3; goto out_free; } + u32 timeout = get_tmr_ms() + 2000; - while (!TSEC(TSEC_STATUS)) + while (!TSEC(TSEC_MAILBOX1)) + { if (get_tmr_ms() > timeout) { res = -4; goto out_free; } - if (TSEC(TSEC_STATUS) != 0xB0B0B0B0) + } + + if (TSEC(TSEC_MAILBOX1) != 0xB0B0B0B0) { res = -5; goto out_free; @@ -275,23 +281,22 @@ int tsec_query(void *tsec_keys, tsec_ctxt_t *tsec_ctxt) // Fetch result. HOST1X(HOST1X_CH0_SYNC_SYNCPT_160) = 0; u32 buf[4]; - buf[0] = SOR1(SOR_NV_PDISP_SOR_DP_HDCP_BKSV_LSB); - buf[1] = SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_BKSV_LSB); - buf[2] = SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_MSB); - buf[3] = SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_LSB); - SOR1(SOR_NV_PDISP_SOR_DP_HDCP_BKSV_LSB) = 0; - SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_BKSV_LSB) = 0; - SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_MSB) = 0; - SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_LSB) = 0; + buf[0] = SOR1(SOR_DP_HDCP_BKSV_LSB); + buf[1] = SOR1(SOR_TMDS_HDCP_BKSV_LSB); + buf[2] = SOR1(SOR_TMDS_HDCP_CN_MSB); + buf[3] = SOR1(SOR_TMDS_HDCP_CN_LSB); + SOR1(SOR_DP_HDCP_BKSV_LSB) = 0; + SOR1(SOR_TMDS_HDCP_BKSV_LSB) = 0; + SOR1(SOR_TMDS_HDCP_CN_MSB) = 0; + SOR1(SOR_TMDS_HDCP_CN_LSB) = 0; memcpy(tsec_keys, &buf, SE_KEY_128_SIZE); } -out_free:; +out_free: free(fwbuf); -out:; - +out: // Disable clocks. clock_disable_kfuse(); clock_disable_sor1(); @@ -301,9 +306,10 @@ out:; bpmp_mmu_enable(); bpmp_clk_rate_set(prev_fid); - // Disable AHB aperture. - if (type == TSEC_FW_TYPE_NEW) - mc_disable_ahb_redirect(); +#ifdef BDK_MC_ENABLE_AHB_REDIRECT + // Re-enable AHB aperture. + mc_enable_ahb_redirect(); +#endif return res; } diff --git a/bdk/sec/tsec.h b/bdk/sec/tsec.h index 7456e44..81a2cce 100644 --- a/bdk/sec/tsec.h +++ b/bdk/sec/tsec.h @@ -24,7 +24,7 @@ enum tsec_fw_type { // Retail Hovi Keygen. TSEC_FW_TYPE_OLD = 0, // 1.0.0 - 6.1.0. - TSEC_FW_TYPE_EMU = 1, // 6.2.0 emulated enviroment. + TSEC_FW_TYPE_EMU = 1, // 6.2.0 emulated environment. TSEC_FW_TYPE_NEW = 2, // 7.0.0+. }; diff --git a/bdk/sec/tsec_t210.h b/bdk/sec/tsec_t210.h index 889d0d4..96624e2 100644 --- a/bdk/sec/tsec_t210.h +++ b/bdk/sec/tsec_t210.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2018 CTCaer +* Copyright (c) 2018-2023 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, @@ -17,8 +17,8 @@ #ifndef _TSEC_T210_H_ #define _TSEC_T210_H_ -#define TSEC_BOOTKEYVER 0x1040 -#define TSEC_STATUS 0x1044 +#define TSEC_MAILBOX0 0x1040 +#define TSEC_MAILBOX1 0x1044 #define TSEC_ITFEN 0x1048 #define TSEC_ITFEN_CTXEN BIT(0) #define TSEC_ITFEN_MTHDEN BIT(1) diff --git a/bdk/soc/bpmp.c b/bdk/soc/bpmp.c index fc0e412..5a33f4b 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-2021 CTCaer + * Copyright (c) 2019-2023 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, @@ -18,9 +18,9 @@ #include #include +#include #include #include -#include #define BPMP_MMU_CACHE_LINE_SIZE 0x20 @@ -134,7 +134,7 @@ void bpmp_mmu_maintenance(u32 op, bool force) // This is a blocking operation. BPMP_CACHE_CTRL(BPMP_CACHE_MAINT_REQ) = MAINT_REQ_WAY_BITMAP(0xF) | op; - while(!(BPMP_CACHE_CTRL(BPMP_CACHE_INT_RAW_EVENT) & INT_MAINT_DONE)) + while (!(BPMP_CACHE_CTRL(BPMP_CACHE_INT_RAW_EVENT) & INT_MAINT_DONE)) ; BPMP_CACHE_CTRL(BPMP_CACHE_INT_CLEAR) = BPMP_CACHE_CTRL(BPMP_CACHE_INT_RAW_EVENT); @@ -150,8 +150,8 @@ void bpmp_mmu_set_entry(int idx, bpmp_mmu_entry_t *entry, bool apply) if (entry->enable) { mmu_entry->start_addr = ALIGN(entry->start_addr, BPMP_MMU_CACHE_LINE_SIZE); - mmu_entry->end_addr = ALIGN_DOWN(entry->end_addr, BPMP_MMU_CACHE_LINE_SIZE); - mmu_entry->attr = entry->attr; + mmu_entry->end_addr = ALIGN_DOWN(entry->end_addr, BPMP_MMU_CACHE_LINE_SIZE); + mmu_entry->attr = entry->attr; BPMP_CACHE_CTRL(BPMP_CACHE_MMU_SHADOW_COPY_MASK) |= BIT(idx); @@ -166,9 +166,9 @@ void bpmp_mmu_enable() return; // Init BPMP MMU. - BPMP_CACHE_CTRL(BPMP_CACHE_MMU_CMD) = MMU_CMD_INIT; + BPMP_CACHE_CTRL(BPMP_CACHE_MMU_CMD) = MMU_CMD_INIT; BPMP_CACHE_CTRL(BPMP_CACHE_MMU_FALLBACK_ENTRY) = MMU_EN_READ | MMU_EN_WRITE | MMU_EN_EXEC; // RWX for non-defined regions. - BPMP_CACHE_CTRL(BPMP_CACHE_MMU_CFG) = MMU_CFG_SEQ_EN | MMU_CFG_TLB_EN | MMU_CFG_ABORT_STORE_LAST; + BPMP_CACHE_CTRL(BPMP_CACHE_MMU_CFG) = MMU_CFG_SEQ_EN | MMU_CFG_TLB_EN | MMU_CFG_ABORT_STORE_LAST; // Init BPMP MMU entries. BPMP_CACHE_CTRL(BPMP_CACHE_MMU_SHADOW_COPY_MASK) = 0; @@ -206,6 +206,7 @@ void bpmp_mmu_disable() 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. 90, // BPMP_CLK_SUPER_BOOST: 576MHz 41% - 144MHz APB. 92 // BPMP_CLK_HYPER_BOOST: 589MHz 44% - 147MHz APB. // Do not use for public releases! diff --git a/bdk/soc/bpmp.h b/bdk/soc/bpmp.h index 0f80150..0c55147 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-2021 CTCaer + * Copyright (c) 2019-2023 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, @@ -47,12 +47,14 @@ typedef enum { BPMP_CLK_NORMAL, // 408MHz 0% - 136MHz APB. BPMP_CLK_HIGH_BOOST, // 544MHz 33% - 136MHz APB. + BPMP_CLK_HIGH2_BOOST, // 563MHz 38% - 141MHz APB. BPMP_CLK_SUPER_BOOST, // 576MHz 41% - 144MHz APB. BPMP_CLK_HYPER_BOOST, // 589MHz 44% - 147MHz APB. //BPMP_CLK_DEV_BOOST, // 608MHz 49% - 152MHz APB. BPMP_CLK_MAX } bpmp_freq_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 diff --git a/bdk/soc/ccplex.c b/bdk/soc/ccplex.c index 825c546..37ce73d 100644 --- a/bdk/soc/ccplex.c +++ b/bdk/soc/ccplex.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2020 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, @@ -15,6 +15,7 @@ * along with this program. If not, see . */ +#include #include #include #include @@ -51,7 +52,7 @@ void _ccplex_enable_power_t210b01() void ccplex_boot_cpu0(u32 entry) { // Set ACTIVE_CLUSER to FAST. - FLOW_CTLR(FLOW_CTLR_BPMP_CLUSTER_CONTROL) &= 0xFFFFFFFE; + FLOW_CTLR(FLOW_CTLR_BPMP_CLUSTER_CONTROL) &= ~CLUSTER_CTRL_ACTIVE_SLOW; if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210) _ccplex_enable_power_t210(); @@ -62,12 +63,12 @@ void ccplex_boot_cpu0(u32 entry) // Configure MSELECT source and enable clock to 102MHz. CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) & 0x1FFFFF00) | 6; - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_MSELECT); + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_MSELECT); // Configure initial CPU clock frequency and enable clock. CLOCK(CLK_RST_CONTROLLER_CCLK_BURST_POLICY) = 0x20008888; // PLLX_OUT0_LJ. CLOCK(CLK_RST_CONTROLLER_SUPER_CCLK_DIVIDER) = 0x80000000; - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_CPUG); + CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_CPUG); clock_enable_coresight(); @@ -81,9 +82,9 @@ void ccplex_boot_cpu0(u32 entry) // Enable CPU0 rail. pmc_enable_partition(POWER_RAIL_CE0, ENABLE); - // Request and wait for RAM repair. - FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) = 1; - while (!(FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) & 2)) + // Request and wait for RAM repair. Needed for the Fast cluster. + FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) = RAM_REPAIR_REQ; + while (!(FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) & RAM_REPAIR_STS)) ; EXCP_VEC(EVP_CPU_RESET_VECTOR) = 0; @@ -100,7 +101,7 @@ void ccplex_boot_cpu0(u32 entry) // MC(MC_TZ_SECURITY_CTRL) = 1; // Clear MSELECT reset. - CLOCK(CLK_RST_CONTROLLER_RST_DEV_V_CLR) = BIT(CLK_V_MSELECT); + CLOCK(CLK_RST_CONTROLLER_RST_DEV_V_CLR) = BIT(CLK_V_MSELECT); // Clear NONCPU reset. CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR) = 0x20000000; // Clear CPU0 reset. diff --git a/bdk/soc/clock.c b/bdk/soc/clock.c index b122cf9..22c3486 100644 --- a/bdk/soc/clock.c +++ b/bdk/soc/clock.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2022 CTCaer + * Copyright (c) 2018-2023 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -17,9 +17,10 @@ #include #include +#include +#include #include #include -#include typedef struct _clock_osc_t { @@ -38,9 +39,9 @@ static const clock_osc_t _clock_osc_cnt[] = { { 48000, 2836, 3023 } }; -/* clock_t: reset, enable, source, index, clk_src, clk_div */ +/* clk_rst_t: reset, enable, source, index, clk_src, clk_div */ -static const clock_t _clock_uart[] = { +static const clk_rst_t _clock_uart[] = { { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTA, CLK_L_UARTA, 0, 2 }, { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTB, CLK_L_UARTB, 0, 2 }, { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_UARTC, CLK_H_UARTC, 0, 2 }, @@ -49,7 +50,7 @@ static const clock_t _clock_uart[] = { }; //I2C default parameters - TLOW: 4, THIGH: 2, DEBOUNCE: 0, FM_DIV: 26. -static const clock_t _clock_i2c[] = { +static const clk_rst_t _clock_i2c[] = { { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_I2C1, CLK_L_I2C1, 0, 19 }, //20.4MHz -> 100KHz { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C2, CLK_H_I2C2, 0, 4 }, //81.6MHz -> 400KHz { CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_I2C3, CLK_U_I2C3, 0, 4 }, //81.6MHz -> 400KHz @@ -58,61 +59,68 @@ static const clock_t _clock_i2c[] = { { CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_I2C6, CLK_X_I2C6, 0, 19 } //20.4MHz -> 100KHz }; -static clock_t _clock_se = { - CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, CLK_V_SE, 0, 0 // 408MHz. +static clk_rst_t _clock_se = { + CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, CLK_V_SE, 0, 0 // 408MHz. Default: 408MHz. Max: 627.2 MHz. }; - -static clock_t _clock_tzram = { - CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_NO_SOURCE, CLK_V_TZRAM, 0, 0 +static clk_rst_t _clock_tzram = { + CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_NO_SOURCE, CLK_V_TZRAM, 0, 0 }; - -static clock_t _clock_host1x = { - CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_L_HOST1X, 4, 3 // 163.2MHz. +static clk_rst_t _clock_host1x = { + CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_L_HOST1X, 4, 3 // 163.2MHz. Max: 408MHz. }; -static clock_t _clock_tsec = { - CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, CLK_U_TSEC, 0, 2 // 204MHz. +static clk_rst_t _clock_tsec = { + CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, CLK_U_TSEC, 0, 2 // 204MHz. Max: 408MHz. }; -static clock_t _clock_sor_safe = { - CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_NO_SOURCE, CLK_Y_SOR_SAFE, 0, 0 +static clk_rst_t _clock_nvdec = { + CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_NVDEC, CLK_Y_NVDEC, 4, 0 // 408 MHz. Max: 716.8/979.2MHz. }; -static clock_t _clock_sor0 = { - CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NOT_USED, CLK_X_SOR0, 0, 0 +static clk_rst_t _clock_nvjpg = { + CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_NVJPG, CLK_Y_NVJPG, 4, 0 // 408 MHz. Max: 627.2/652.8MHz. }; -static clock_t _clock_sor1 = { - CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_X_SOR1, 0, 2 // 204MHz. +static clk_rst_t _clock_vic = { + CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_VIC, CLK_X_VIC, 2, 0 // 408 MHz. Max: 627.2/652.8MHz. }; -static clock_t _clock_kfuse = { - CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_KFUSE, 0, 0 +static clk_rst_t _clock_sor_safe = { + CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_NO_SOURCE, CLK_Y_SOR_SAFE, 0, 0 }; - -static clock_t _clock_cl_dvfs = { - CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_NO_SOURCE, CLK_W_DVFS, 0, 0 +static clk_rst_t _clock_sor0 = { + CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NOT_USED, CLK_X_SOR0, 0, 0 }; -static clock_t _clock_coresight = { - CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, CLK_U_CSITE, 0, 4 // 136MHz. +static clk_rst_t _clock_sor1 = { + CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_X_SOR1, 0, 2 // 204MHz. }; - -static clock_t _clock_pwm = { - CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, CLK_L_PWM, 6, 4 // Fref: 6.4MHz. HOS: PLLP / 54 = 7.55MHz. +static clk_rst_t _clock_kfuse = { + CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_KFUSE, 0, 0 }; - -static clock_t _clock_sdmmc_legacy_tm = { +static clk_rst_t _clock_cl_dvfs = { + CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_NO_SOURCE, CLK_W_DVFS, 0, 0 +}; +static clk_rst_t _clock_coresight = { + CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, CLK_U_CSITE, 0, 4 // 136MHz. +}; +static clk_rst_t _clock_pwm = { + CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, CLK_L_PWM, 6, 4 // Fref: 6.4MHz. HOS: PLLP / 54 = 7.55MHz. +}; +static clk_rst_t _clock_sdmmc_legacy_tm = { CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM, CLK_Y_SDMMC_LEGACY_TM, 4, 66 }; - -static clock_t _clock_apbdma = { - CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_APBDMA, 0, 0 +static clk_rst_t _clock_apbdma = { + CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_APBDMA, 0, 0 // Max: 204MHz. +}; +static clk_rst_t _clock_ahbdma = { + CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_AHBDMA, 0, 0 +}; +static clk_rst_t _clock_actmon = { + CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_ACTMON, CLK_V_ACTMON, 6, 0 // 19.2MHz. +}; +static clk_rst_t _clock_extperiph1 = { + CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH1, CLK_V_EXTPERIPH1, 0, 0 +}; +static clk_rst_t _clock_extperiph2 = { + CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH2, CLK_V_EXTPERIPH2, 2, 202 // 4.0MHz }; -static clock_t _clock_ahbdma = { - CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_AHBDMA, 0, 0 -}; - -static clock_t _clock_actmon = { - CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_ACTMON, CLK_V_ACTMON, 6, 0 // 19.2MHz. -}; - -void clock_enable(const clock_t *clk) +void clock_enable(const clk_rst_t *clk) { // Put clock into reset. CLOCK(clk->reset) = (CLOCK(clk->reset) & ~BIT(clk->index)) | BIT(clk->index); @@ -129,7 +137,7 @@ void clock_enable(const clock_t *clk) CLOCK(clk->reset) &= ~BIT(clk->index); } -void clock_disable(const clock_t *clk) +void clock_disable(const clk_rst_t *clk) { // Put clock into reset. CLOCK(clk->reset) = (CLOCK(clk->reset) & ~BIT(clk->index)) | BIT(clk->index); @@ -159,7 +167,9 @@ int clock_uart_use_src_div(u32 idx, u32 baud) { u32 clk_src_div = CLOCK(_clock_uart[idx].source) & 0xE0000000; - if (baud == 1000000) + if (baud == 3000000) + CLOCK(_clock_uart[idx].source) = clk_src_div | UART_SRC_CLK_DIV_EN | 15; + else if (baud == 1000000) CLOCK(_clock_uart[idx].source) = clk_src_div | UART_SRC_CLK_DIV_EN | 49; else { @@ -215,6 +225,36 @@ void clock_disable_tsec() clock_disable(&_clock_tsec); } +void clock_enable_nvdec() +{ + clock_enable(&_clock_nvdec); +} + +void clock_disable_nvdec() +{ + clock_disable(&_clock_nvdec); +} + +void clock_enable_nvjpg() +{ + clock_enable(&_clock_nvjpg); +} + +void clock_disable_nvjpg() +{ + clock_disable(&_clock_nvjpg); +} + +void clock_enable_vic() +{ + clock_enable(&_clock_vic); +} + +void clock_disable_vic() +{ + clock_disable(&_clock_vic); +} + void clock_enable_sor_safe() { clock_enable(&_clock_sor_safe); @@ -321,6 +361,56 @@ void clock_disable_actmon() clock_disable(&_clock_actmon); } +void clock_enable_extperiph1() +{ + clock_enable(&_clock_extperiph1); + + PMC(APBDEV_PMC_CLK_OUT_CNTRL) |= PMC_CLK_OUT_CNTRL_CLK1_SRC_SEL(OSC_CAR) | PMC_CLK_OUT_CNTRL_CLK1_FORCE_EN; + usleep(5); +} + +void clock_disable_extperiph1() +{ + PMC(APBDEV_PMC_CLK_OUT_CNTRL) &= ~((PMC_CLK_OUT_CNTRL_CLK1_SRC_SEL(OSC_CAR)) | PMC_CLK_OUT_CNTRL_CLK1_FORCE_EN); + clock_disable(&_clock_extperiph1); +} + +void clock_enable_extperiph2() +{ + clock_enable(&_clock_extperiph2); + + PMC(APBDEV_PMC_CLK_OUT_CNTRL) |= PMC_CLK_OUT_CNTRL_CLK2_SRC_SEL(OSC_CAR) | PMC_CLK_OUT_CNTRL_CLK2_FORCE_EN; + usleep(5); +} + +void clock_disable_extperiph2() +{ + PMC(APBDEV_PMC_CLK_OUT_CNTRL) &= ~((PMC_CLK_OUT_CNTRL_CLK2_SRC_SEL(OSC_CAR)) | PMC_CLK_OUT_CNTRL_CLK2_FORCE_EN); + clock_disable(&_clock_extperiph2); +} + +void clock_enable_plld(u32 divp, u32 divn, bool lowpower, bool tegra_t210) +{ + u32 plld_div = (divp << 20) | (divn << 11) | 1; + + // N divider is fractional, so N = DIVN + 1/2 + PLLD_SDM_DIN/8192. + u32 misc = 0x2D0000 | 0xFC00; // Clock enable and PLLD_SDM_DIN: -1024 -> DIVN + 0.375. + 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) = 0x40000000; // PLLD_OUT0. + + // Set dividers and enable PLLD. + CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div; + CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = tegra_t210 ? 0x20 : 0; // Keep default PLLD_SETUP. + + // Set PLLD_SDM_DIN and enable PLLD to DSI pads. + CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = misc; +} + void clock_enable_pllx() { // Configure and enable PLLX if disabled. @@ -357,7 +447,7 @@ void clock_enable_pllc(u32 divn) // Take PLLC out of reset and set basic misc parameters. CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) = - ((CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) & 0xFFF0000F) & ~PLLC_MISC_RESET) | (0x80000 << 4); // PLLC_EXT_FRU. + ((CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) & 0xFFF0000F) & ~PLLC_MISC_RESET) | (0x8000 << 4); // PLLC_EXT_FRU. CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_2) |= 0xF0 << 8; // PLLC_FLL_LD_MEM. // Disable PLL and IDDQ in case they are on. @@ -384,11 +474,11 @@ void clock_enable_pllc(u32 divn) void clock_disable_pllc() { // Disable PLLC and PLLC_OUT1. - CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) &= ~(PLLC_OUT1_CLKEN | PLLC_OUT1_RSTN_CLR); + CLOCK(CLK_RST_CONTROLLER_PLLC_OUT) &= ~PLLC_OUT1_RSTN_CLR; + CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) = PLLC_MISC_RESET; CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) &= ~PLLCX_BASE_ENABLE; - CLOCK(CLK_RST_CONTROLLER_PLLC_BASE) |= PLLCX_BASE_REF_DIS; CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_1) |= PLLC_MISC1_IDDQ; - CLOCK(CLK_RST_CONTROLLER_PLLC_MISC) |= PLLC_MISC_RESET; + CLOCK(CLK_RST_CONTROLLER_PLLC_MISC_2) &= ~(0xFF << 8); // PLLC_FLL_LD_MEM. usleep(10); } @@ -413,7 +503,7 @@ static void _clock_enable_pllc4(u32 mask) usleep(10); // Set PLLC4 dividers. - CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) = (104 << 8) | 4; // DIVM: 4, DIVP: 1. + CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) = (0 << 19) | (104 << 8) | 4; // DIVP: 1, DIVN: 104, DIVM: 4. 998MHz OUT0, 199MHz OUT2. // Enable PLLC4 and wait for Phase and Frequency lock. CLOCK(CLK_RST_CONTROLLER_PLLC4_BASE) |= PLLCX_BASE_ENABLE; @@ -451,9 +541,9 @@ void clock_enable_pllu() CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) = pllu_cfg | PLLCX_BASE_ENABLE; // Enable. // Wait for PLL to stabilize. - u32 timeout = (u32)TMR(TIMERUS_CNTR_1US) + 1300; + u32 timeout = get_tmr_us() + 1300; while (!(CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) & PLLCX_BASE_LOCK)) // PLL_LOCK. - if ((u32)TMR(TIMERUS_CNTR_1US) > timeout) + if (get_tmr_us() > timeout) break; usleep(10); @@ -463,9 +553,9 @@ void clock_enable_pllu() void clock_disable_pllu() { - CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) &= ~0x2E00000; // Disable PLLU USB/HSIC/ICUSB/48M. - CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) &= ~0x40000000; // Disable PLLU. - CLOCK(CLK_RST_CONTROLLER_PLLU_MISC) &= ~0x20000000; // Enable reference clock. + CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) &= ~0x2E00000; // Disable PLLU USB/HSIC/ICUSB/48M. + CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) &= ~BIT(30); // Disable PLLU. + CLOCK(CLK_RST_CONTROLLER_PLLU_MISC) &= ~BIT(29); // Enable reference clock. } void clock_enable_utmipll() @@ -594,7 +684,7 @@ static void _clock_sdmmc_clear_enable(u32 id) static void _clock_sdmmc_config_legacy_tm() { - clock_t *clk = &_clock_sdmmc_legacy_tm; + clk_rst_t *clk = &_clock_sdmmc_legacy_tm; if (!(CLOCK(clk->enable) & BIT(clk->index))) clock_enable(clk); } @@ -609,6 +699,7 @@ static clock_sdmmc_t _clock_sdmmc_table[4] = { 0 }; #define SDMMC_CLOCK_SRC_PLLP_OUT0 0x0 #define SDMMC_CLOCK_SRC_PLLC4_OUT2 0x3 +#define SDMMC_CLOCK_SRC_PLLC4_OUT0 0x7 #define SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ 0x1 static int _clock_sdmmc_config_clock_host(u32 *pclock, u32 id, u32 val) @@ -626,79 +717,88 @@ static int _clock_sdmmc_config_clock_host(u32 *pclock, u32 id, u32 val) *pclock = 24728; divisor = 31; // 16.5 div. break; + case 26000: *pclock = 25500; divisor = 30; // 16 div. break; - case 40800: - *pclock = 40800; - divisor = 18; // 10 div. - break; + case 50000: *pclock = 48000; divisor = 15; // 8.5 div. break; + case 52000: *pclock = 51000; divisor = 14; // 8 div. break; + + case 82000: + *pclock = 81600; + divisor = 8; // 5 div. + break; + case 100000: source = SDMMC_CLOCK_SRC_PLLC4_OUT2; *pclock = 99840; divisor = 2; // 2 div. break; + case 164000: *pclock = 163200; divisor = 3; // 2.5 div. break; - case 200000: // 240MHz evo+. + + case 200000: switch (id) { case SDMMC_1: - source = SDMMC_CLOCK_SRC_PLLC4_OUT2; - break; - case SDMMC_2: - source = SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ; - break; case SDMMC_3: source = SDMMC_CLOCK_SRC_PLLC4_OUT2; break; + case SDMMC_2: case SDMMC_4: - source = SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ; + source = SDMMC4_CLOCK_SRC_PLLC4_OUT2_LJ; // div is ignored. break; } *pclock = 199680; divisor = 0; // 1 div. break; - default: - *pclock = 24728; - divisor = 31; // 16.5 div. + +#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT + case 400000: + source = SDMMC_CLOCK_SRC_PLLC4_OUT0; + *pclock = 399360; + divisor = 3; // 2.5 div + break; +#endif } _clock_sdmmc_table[id].clock = val; _clock_sdmmc_table[id].real_clock = *pclock; // Enable PLLC4 if in use by any SDMMC. - if (source) + if (source != SDMMC_CLOCK_SRC_PLLP_OUT0) _clock_enable_pllc4(BIT(id)); // Set SDMMC legacy timeout clock. _clock_sdmmc_config_legacy_tm(); // Set SDMMC clock. + u32 src_div = (source << 29) | divisor; switch (id) { case SDMMC_1: - CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC1) = (source << 29) | divisor; + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC1) = src_div; break; case SDMMC_2: - CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC2) = (source << 29) | divisor; + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC2) = src_div; break; case SDMMC_3: - CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3) = (source << 29) | divisor; + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3) = src_div; break; case SDMMC_4: - CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC4) = (source << 29) | divisor; + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC4) = src_div; break; } @@ -728,54 +828,71 @@ void clock_sdmmc_get_card_clock_div(u32 *pclock, u16 *pdivisor, u32 type) // Get Card clock divisor. switch (type) { - case SDHCI_TIMING_MMC_ID: // Actual IO Freq: 380.59 KHz. + case SDHCI_TIMING_MMC_ID: // Actual card clock: 386.36 KHz. *pclock = 26000; *pdivisor = 66; break; + case SDHCI_TIMING_MMC_LS26: *pclock = 26000; *pdivisor = 1; break; + case SDHCI_TIMING_MMC_HS52: *pclock = 52000; *pdivisor = 1; break; + case SDHCI_TIMING_MMC_HS200: case SDHCI_TIMING_MMC_HS400: case SDHCI_TIMING_UHS_SDR104: *pclock = 200000; *pdivisor = 1; break; - case SDHCI_TIMING_SD_ID: // Actual IO Freq: 380.43 KHz. + + case SDHCI_TIMING_SD_ID: // Actual card clock: 386.38 KHz. *pclock = 25000; *pdivisor = 64; break; + case SDHCI_TIMING_SD_DS12: case SDHCI_TIMING_UHS_SDR12: *pclock = 25000; *pdivisor = 1; break; + case SDHCI_TIMING_SD_HS25: case SDHCI_TIMING_UHS_SDR25: *pclock = 50000; *pdivisor = 1; break; + case SDHCI_TIMING_UHS_SDR50: *pclock = 100000; *pdivisor = 1; break; + case SDHCI_TIMING_UHS_SDR82: *pclock = 164000; *pdivisor = 1; break; - case SDHCI_TIMING_UHS_DDR50: - *pclock = 40800; - *pdivisor = 1; + + case SDHCI_TIMING_UHS_DDR50: // Actual card clock: 40.80 MHz. + *pclock = 82000; + *pdivisor = 2; break; - case SDHCI_TIMING_MMC_HS102: // Actual IO Freq: 99.84 MHz. + + case SDHCI_TIMING_MMC_HS100: // Actual card clock: 99.84 MHz. *pclock = 200000; *pdivisor = 2; break; + +#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT + case SDHCI_TIMING_UHS_DDR200: // Actual card clock: 199.68 KHz. + *pclock = 400000; + *pdivisor = 2; + break; +#endif } } @@ -794,7 +911,8 @@ void clock_sdmmc_enable(u32 id, u32 val) _clock_sdmmc_config_clock_host(&clock, id, val); _clock_sdmmc_set_enable(id); _clock_sdmmc_is_reset(id); - usleep((100000 + clock - 1) / clock); + // Wait 100 cycles for reset and for clocks to stabilize. + usleep((100 * 1000 + clock - 1) / clock); _clock_sdmmc_clear_reset(id); _clock_sdmmc_is_reset(id); } diff --git a/bdk/soc/clock.h b/bdk/soc/clock.h index 6b504f8..54818f7 100644 --- a/bdk/soc/clock.h +++ b/bdk/soc/clock.h @@ -117,8 +117,10 @@ #define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD 0x3A4 #define CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT 0x3B4 #define CLK_RST_CONTROLLER_CLK_SOURCE_I2C4 0x3C4 +#define CLK_RST_CONTROLLER_CLK_SOURCE_AHUB 0x3D0 #define CLK_RST_CONTROLLER_CLK_SOURCE_ACTMON 0x3E8 #define CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH1 0x3EC +#define CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH2 0x3F0 #define CLK_RST_CONTROLLER_CLK_SOURCE_SYS 0x400 #define CLK_RST_CONTROLLER_CLK_SOURCE_SOR1 0x410 #define CLK_RST_CONTROLLER_CLK_SOURCE_SE 0x42C @@ -154,8 +156,12 @@ #define CLK_RST_CONTROLLER_CLK_SOURCE_I2C6 0x65C #define CLK_RST_CONTROLLER_CLK_SOURCE_EMC_DLL 0x664 #define CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL 0x66C +#define CLK_RST_CONTROLLER_CLK_SOURCE_VIC 0x678 #define CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM 0x694 +#define CLK_RST_CONTROLLER_CLK_SOURCE_NVDEC 0x698 +#define CLK_RST_CONTROLLER_CLK_SOURCE_NVJPG 0x69C #define CLK_RST_CONTROLLER_CLK_SOURCE_NVENC 0x6A0 +#define CLK_RST_CONTROLLER_CLK_SOURCE_APE 0x6C0 #define CLK_RST_CONTROLLER_CLK_SOURCE_USB2_HSIC_TRK 0x6CC #define CLK_RST_CONTROLLER_SE_SUPER_CLK_DIVIDER 0x704 #define CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE 0x710 @@ -221,138 +227,232 @@ /*! PTO IDs. */ typedef enum _clock_pto_id_t { - CLK_PTO_PCLK_SYS = 0x06, - CLK_PTO_HCLK_SYS = 0x07, + CLK_PTO_PCLK_SYS = 0x06, + CLK_PTO_HCLK_SYS = 0x07, + CLK_PTO_DMIC1 = 0x08, + CLK_PTO_DMIC2 = 0x09, + CLK_PTO_HDMI_SLOWCLK_DIV2 = 0x0A, + CLK_PTO_JTAG_REG = 0x0B, + CLK_PTO_UTMIP_240_A = 0x0C, + CLK_PTO_UTMIP_240_B = 0x0D, - CLK_PTO_UTMIP_240 = 0x0C, + CLK_PTO_CCLK_G = 0x12, + CLK_PTO_CCLK_G_DIV2 = 0x13, + CLK_PTO_MIPIBIF = 0x14, - CLK_PTO_CCLK_G = 0x12, - CLK_PTO_CCLK_G_DIV2 = 0x13, + CLK_PTO_SPI1 = 0x17, + CLK_PTO_SPI2 = 0x18, + CLK_PTO_SPI3 = 0x19, + CLK_PTO_SPI4 = 0x1A, + CLK_PTO_MAUD = 0x1B, + CLK_PTO_SCLK = 0x1C, - CLK_PTO_SPI1 = 0x17, - CLK_PTO_SPI2 = 0x18, - CLK_PTO_SPI3 = 0x19, - CLK_PTO_SPI4 = 0x1A, - CLK_PTO_MAUD = 0x1B, - CLK_PTO_SCLK = 0x1C, + CLK_PTO_SDMMC1 = 0x20, + CLK_PTO_SDMMC2 = 0x21, + CLK_PTO_SDMMC3 = 0x22, + CLK_PTO_SDMMC4 = 0x23, + CLK_PTO_EMC = 0x24, - CLK_PTO_SDMMC1 = 0x20, - CLK_PTO_SDMMC2 = 0x21, - CLK_PTO_SDMMC3 = 0x22, - CLK_PTO_SDMMC4 = 0x23, - CLK_PTO_EMC = 0x24, + CLK_PTO_DMIC3 = 0x2A, + CLK_PTO_CCLK_LP = 0x2B, + CLK_PTO_CCLK_LP_DIV2 = 0x2C, - CLK_PTO_CCLK_LP = 0x2B, - CLK_PTO_CCLK_LP_DIV2 = 0x2C, + CLK_PTO_MSELECT = 0x2F, - CLK_PTO_MSELECT = 0x2F, + CLK_PTO_VI_SENSOR2 = 0x33, + CLK_PTO_VI_SENSOR = 0x34, + CLK_PTO_VIC = 0x35, + CLK_PTO_VIC_SKIP = 0x36, + CLK_PTO_ISP_SKIP = 0x37, + CLK_PTO_ISPB_SE2_SKIP = 0x38, + CLK_PTO_NVDEC_SKIP = 0x39, + CLK_PTO_NVENC_SKIP = 0x3A, + CLK_PTO_NVJPG_SKIP = 0x3B, + CLK_PTO_TSEC_SKIP = 0x3C, + CLK_PTO_TSECB_SKIP = 0x3D, + CLK_PTO_SE_SKIP = 0x3E, + CLK_PTO_VI_SKIP = 0x3F, - CLK_PTO_VIC = 0x36, + CLK_PTO_PLLX_OBS = 0x40, + CLK_PTO_PLLC_OBS = 0x41, + CLK_PTO_PLLM_OBS = 0x42, + CLK_PTO_PLLP_OBS = 0x43, + CLK_PTO_PLLA_OBS = 0x44, + CLK_PTO_PLLMB_OBS = 0x45, + CLK_PTO_SATA_OOB = 0x46, - CLK_PTO_NVDEC = 0x39, + CLK_PTO_FCPU_DVFS_DIV12_CPU = 0x48, - CLK_PTO_NVENC = 0x3A, - CLK_PTO_NVJPG = 0x3B, - CLK_PTO_TSEC = 0x3C, - CLK_PTO_TSECB = 0x3D, - CLK_PTO_SE = 0x3E, + CLK_PTO_EQOS_AXI = 0x4C, + CLK_PTO_EQOS_PTP_REF = 0x4D, + CLK_PTO_EQOS_TX = 0x4E, + CLK_PTO_EQOS_RX = 0x4F, - CLK_PTO_DSIA_LP = 0x62, + CLK_PTO_CILAB = 0x52, + CLK_PTO_CILCD = 0x53, - CLK_PTO_ISP = 0x64, - CLK_PTO_MC = 0x6A, + CLK_PTO_CILEF = 0x55, + CLK_PTO_PLLA1_PTO_OBS = 0x56, + CLK_PTO_PLLC4_PTO_OBS = 0x57, - CLK_PTO_ACTMON = 0x6B, - CLK_PTO_CSITE = 0x6C, + CLK_PTO_PLLC2_PTO_OBS = 0x59, + CLK_PTO_PLLC3_PTO_OBS = 0x5B, - CLK_PTO_HOST1X = 0x6F, + CLK_PTO_DSIA_LP = 0x62, + CLK_PTO_DSIB_LP = 0x63, + CLK_PTO_ISP = 0x64, + CLK_PTO_PEX_PAD = 0x65, - CLK_PTO_SE_2 = 0x74, // Same as CLK_PTO_SE. - CLK_PTO_SOC_THERM = 0x75, + CLK_PTO_MC = 0x6A, - CLK_PTO_TSEC_2 = 0x77, // Same as CLK_PTO_TSEC. + CLK_PTO_ACTMON = 0x6B, + CLK_PTO_CSITE = 0x6C, + CLK_PTO_VI_I2C = 0x6D, - CLK_PTO_ACLK = 0x7C, - CLK_PTO_QSPI = 0x7D, + CLK_PTO_HOST1X = 0x6F, - CLK_PTO_I2S1 = 0x80, - CLK_PTO_I2S2 = 0x81, - CLK_PTO_I2S3 = 0x82, - CLK_PTO_I2S4 = 0x83, - CLK_PTO_I2S5 = 0x84, - CLK_PTO_AHUB = 0x85, - CLK_PTO_APE = 0x86, + CLK_PTO_QSPI_2X = 0x71, + CLK_PTO_NVDEC = 0x72, + CLK_PTO_NVJPG = 0x73, + CLK_PTO_SE = 0x74, + CLK_PTO_SOC_THERM = 0x75, - CLK_PTO_DVFS_SOC = 0x88, - CLK_PTO_DVFS_REF = 0x89, + CLK_PTO_TSEC = 0x77, + CLK_PTO_TSECB = 0x78, + CLK_PTO_VI = 0x79, + CLK_PTO_LA = 0x7A, + CLK_PTO_SCLK_SKIP = 0x7B, - CLK_PTO_SPDIF = 0x8F, - CLK_PTO_SPDIF_IN = 0x90, + CLK_PTO_ADSP_SKIP = 0x7C, + CLK_PTO_QSPI = 0x7D, + + CLK_PTO_SDMMC2_SHAPER = 0x7E, + CLK_PTO_SDMMC4_SHAPER = 0x7F, + CLK_PTO_I2S1 = 0x80, + CLK_PTO_I2S2 = 0x81, + CLK_PTO_I2S3 = 0x82, + CLK_PTO_I2S4 = 0x83, + CLK_PTO_I2S5 = 0x84, + CLK_PTO_AHUB = 0x85, + CLK_PTO_APE = 0x86, + + CLK_PTO_DVFS_SOC = 0x88, + CLK_PTO_DVFS_REF = 0x89, + CLK_PTO_ADSP_CLK = 0x8A, + CLK_PTO_ADSP_DIV2_CLK = 0x8B, + + CLK_PTO_SPDIF_OUT = 0x8F, + CLK_PTO_SPDIF_IN = 0x90, CLK_PTO_UART_FST_MIPI_CAL = 0x91, + CLK_PTO_SYS2HSIO_SATA_CLK = 0x92, + CLK_PTO_PWM = 0x93, + CLK_PTO_I2C1 = 0x94, + CLK_PTO_I2C2 = 0x95, + CLK_PTO_I2C3 = 0x96, + CLK_PTO_I2C4 = 0x97, + CLK_PTO_I2C5 = 0x98, + CLK_PTO_I2C6 = 0x99, + CLK_PTO_I2C_SLOW = 0x9A, + CLK_PTO_UARTAPE = 0x9B, - CLK_PTO_PWM = 0x93, - CLK_PTO_I2C1 = 0x94, - CLK_PTO_I2C2 = 0x95, - CLK_PTO_I2C3 = 0x96, - CLK_PTO_I2C4 = 0x97, - CLK_PTO_I2C5 = 0x98, - CLK_PTO_I2C6 = 0x99, - CLK_PTO_I2C_SLOW = 0x9A, - CLK_PTO_UARTAPE = 0x9B, + CLK_PTO_EXTPERIPH1 = 0x9D, + CLK_PTO_EXTPERIPH2 = 0x9E, + CLK_PTO_EXTPERIPH3 = 0x9F, + CLK_PTO_ENTROPY = 0xA0, + CLK_PTO_UARTA = 0xA1, + CLK_PTO_UARTB = 0xA2, + CLK_PTO_UARTC = 0xA3, + CLK_PTO_UARTD = 0xA4, + CLK_PTO_OWR = 0xA5, + CLK_PTO_TSENSOR = 0xA6, + CLK_PTO_HDA2CODEC_2X = 0xA7, + CLK_PTO_HDA = 0xA8, + CLK_PTO_EMC_LATENCY = 0xA9, + CLK_PTO_EMC_DLL = 0xAA, + CLK_PTO_SDMMC_LEGACY_TM = 0xAB, + CLK_PTO_DBGAPB = 0xAC, - CLK_PTO_EXTPERIPH1 = 0x9D, - CLK_PTO_EXTPERIPH2 = 0x9E, + CLK_PTO_SOR0 = 0xC0, + CLK_PTO_SOR1 = 0xC1, + CLK_PTO_HDMI = 0xC2, - CLK_PTO_ENTROPY = 0xA0, - CLK_PTO_UARTA = 0xA1, - CLK_PTO_UARTB = 0xA2, - CLK_PTO_UARTC = 0xA3, - CLK_PTO_UARTD = 0xA4, - CLK_PTO_OWR = 0xA5, + CLK_PTO_DISP2 = 0xC4, + CLK_PTO_DISP1 = 0xC5, - CLK_PTO_HDA2CODEC_2X = 0xA7, - CLK_PTO_HDA = 0xA8, + CLK_PTO_PLLD_OBS = 0xCA, + CLK_PTO_PLLD2_PTO_OBS = 0xCC, + CLK_PTO_PLLDP_OBS = 0xCE, + CLK_PTO_PLLE_OBS = 0x10A, + CLK_PTO_PLLU_OBS = 0x10C, + CLK_PTO_PLLREFE_OBS = 0x10E, - CLK_PTO_SDMMC_LEGACY_TM = 0xAB, + CLK_PTO_XUSB_FALCON = 0x110, + CLK_PTO_XUSB_CLK480M_HSIC = 0x111, + CLK_PTO_USB_L0_RX = 0x112, + CLK_PTO_USB_L3_RX = 0x113, + CLK_PTO_USB_RX = 0x114, + CLK_PTO_USB3_L0_TXCLKREF = 0x115, + CLK_PTO_PEX_TXCLKREF_SWITCH_TMS = 0x116, + CLK_PTO_PEX_TXCLKREF_SWITCH_GRP0 = 0x117, + CLK_PTO_PEX_TXCLKREF_SWITCH_GRP1 = 0x118, + CLK_PTO_PEX_TXCLKREF_SWITCH_GRP2 = 0x119, + CLK_PTO_PEX_L4_RX = 0x11A, + CLK_PTO_PEX_TXCLKREF = 0x11B, + CLK_PTO_PEX_TXCLKREF_DIV2 = 0x11C, + CLK_PTO_PEX_TXCLKREF2 = 0x11D, + CLK_PTO_PEX_L0_RX = 0x11E, + CLK_PTO_PEX_L1_RX = 0x11F, + CLK_PTO_PEX_L2_RX = 0x120, + CLK_PTO_PEX_L3_RX = 0x121, + CLK_PTO_SATA_TXCLKREF = 0x122, + CLK_PTO_SATA_TXCLKREF_DIV2 = 0x123, + CLK_PTO_USB_L5_RX = 0x124, + CLK_PTO_SATA_TX = 0x125, + CLK_PTO_SATA_L0_RX = 0x126, - CLK_PTO_SOR0 = 0xC0, - CLK_PTO_SOR1 = 0xC1, + CLK_PTO_USB3_L1_TXCLKREF = 0x129, + CLK_PTO_USB3_L7_TXCLKREF = 0x12A, + CLK_PTO_USB3_L7_RX = 0x12B, + CLK_PTO_USB3_TX = 0x12C, + CLK_PTO_UTMIP_PLL_PAD = 0x12D, - CLK_PTO_DISP2 = 0xC4, - CLK_PTO_DISP1 = 0xC5, + CLK_PTO_XUSB_FS = 0x136, + CLK_PTO_XUSB_SS_HOST_DEV = 0x137, + CLK_PTO_XUSB_CORE_HOST = 0x138, + CLK_PTO_XUSB_CORE_DEV = 0x139, - CLK_PTO_XUSB_FALCON = 0x110, - - CLK_PTO_XUSB_FS = 0x136, - CLK_PTO_XUSB_SS_HOST_DEV = 0x137, - CLK_PTO_XUSB_CORE_HOST = 0x138, - CLK_PTO_XUSB_CORE_DEV = 0x139, + CLK_PTO_USB3_L2_TXCLKREF = 0x13C, + CLK_PTO_USB3_L3_TXCLKREF = 0x13D, + CLK_PTO_USB_L4_RX = 0x13E, + CLK_PTO_USB_L6_RX = 0x13F, /* * PLL need PTO enabled in MISC registers. * Normal div is 2 so result is multiplied with it. */ - CLK_PTO_PLLC_DIV2 = 0x01, - CLK_PTO_PLLM_DIV2 = 0x02, - CLK_PTO_PLLP_DIV2 = 0x03, - CLK_PTO_PLLA_DIV2 = 0x04, - CLK_PTO_PLLX_DIV2 = 0x05, + CLK_PTO_PLLC_DIV2 = 0x01, + CLK_PTO_PLLM_DIV2 = 0x02, + CLK_PTO_PLLP_DIV2 = 0x03, + CLK_PTO_PLLA_DIV2 = 0x04, + CLK_PTO_PLLX_DIV2 = 0x05, - CLK_PTO_PLLMB_DIV2 = 0x25, + CLK_PTO_PLLMB_DIV2 = 0x25, - CLK_PTO_PLLC4_DIV2 = 0x51, + CLK_PTO_PLLC4_DIV2 = 0x51, - CLK_PTO_PLLA1_DIV2 = 0x55, - CLK_PTO_PLLC2_DIV2 = 0x58, - CLK_PTO_PLLC3_DIV2 = 0x5A, + CLK_PTO_PLLA1_DIV2 = 0x55, + CLK_PTO_PLLC2_DIV2 = 0x58, + CLK_PTO_PLLC3_DIV2 = 0x5A, - CLK_PTO_PLLD_DIV2 = 0xCB, - CLK_PTO_PLLD2_DIV2 = 0xCD, - CLK_PTO_PLLDP_DIV2 = 0xCF, + CLK_PTO_PLLD_DIV2 = 0xCB, + CLK_PTO_PLLD2_DIV2 = 0xCD, + CLK_PTO_PLLDP_DIV2 = 0xCF, - CLK_PTO_PLLU_DIV2 = 0x10D, + CLK_PTO_PLLE_DIV2 = 0x10B, - CLK_PTO_PLLREFE_DIV2 = 0x10F, + CLK_PTO_PLLU_DIV2 = 0x10D, + + CLK_PTO_PLLREFE_DIV2 = 0x10F, } clock_pto_id_t; /* @@ -619,7 +719,7 @@ enum CLK_Y_DEV }; /*! Generic clock descriptor. */ -typedef struct _clock_t +typedef struct _clk_rst_t { u16 reset; u16 enable; @@ -627,11 +727,11 @@ typedef struct _clock_t u8 index; u8 clk_src; u8 clk_div; -} clock_t; +} clk_rst_t; /*! Generic clock enable/disable. */ -void clock_enable(const clock_t *clk); -void clock_disable(const clock_t *clk); +void clock_enable(const clk_rst_t *clk); +void clock_disable(const clk_rst_t *clk); /*! Clock control for specific hardware portions. */ void clock_enable_fuse(bool enable); @@ -646,6 +746,12 @@ void clock_enable_host1x(); void clock_disable_host1x(); void clock_enable_tsec(); void clock_disable_tsec(); +void clock_enable_nvdec(); +void clock_disable_nvdec(); +void clock_enable_nvjpg(); +void clock_disable_nvjpg(); +void clock_enable_vic(); +void clock_disable_vic(); void clock_enable_sor_safe(); void clock_disable_sor_safe(); void clock_enable_sor0(); @@ -666,13 +772,19 @@ void clock_enable_ahbdma(); void clock_disable_ahbdma(); void clock_enable_actmon(); void clock_disable_actmon(); +void clock_enable_extperiph1(); +void clock_disable_extperiph1(); +void clock_enable_extperiph2(); +void clock_disable_extperiph2(); +void clock_enable_plld(u32 divp, u32 divn, bool lowpower, bool tegra_t210); void clock_enable_pllx(); void clock_enable_pllc(u32 divn); void clock_disable_pllc(); void clock_enable_pllu(); void clock_disable_pllu(); void clock_enable_utmipll(); + void clock_sdmmc_config_clock_source(u32 *pclock, u32 id, u32 val); void clock_sdmmc_get_card_clock_div(u32 *pclock, u16 *pdivisor, u32 type); int clock_sdmmc_is_not_reset_and_enabled(u32 id); diff --git a/bdk/soc/fuse.c b/bdk/soc/fuse.c index 63037e9..9feca59 100644 --- a/bdk/soc/fuse.c +++ b/bdk/soc/fuse.c @@ -2,7 +2,7 @@ * Copyright (c) 2018 naehrwert * Copyright (c) 2018 shuffle2 * Copyright (c) 2018 balika011 - * Copyright (c) 2019-2021 CTCaer + * Copyright (c) 2019-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, @@ -19,6 +19,7 @@ #include +#include #include #include #include @@ -42,12 +43,19 @@ static const u32 evp_thunk_template[] = { 0xe3822001, // ORR R2, R2, #1 0xe8bd0003, // LDMFD SP!, {R0,R1} 0xe12fff12, // BX R2 + // idx: 15: 0x001007b0, // off_1007EC DCD evp_thunk_template 0x001007f8, // off_1007F0 DCD thunk_end 0x40004c30, // off_1007F4 DCD iram_evp_thunks // thunk_end is here }; -static const u32 evp_thunk_template_len = sizeof(evp_thunk_template); + +static const u32 evp_thunk_func_offsets_t210b01[] = { + 0x0010022c, // off_100268 DCD evp_thunk_template + 0x00100174, // off_10026C DCD thunk_end + 0x40004164, // off_100270 DCD iram_evp_thunks + // thunk_end is here +}; // treated as 12bit values static const u32 hash_vals[] = {1, 2, 4, 8, 0, 3, 5, 6, 7, 9, 10, 11}; @@ -80,19 +88,26 @@ u32 fuse_read_odm_keygen_rev() u32 fuse_read_dramid(bool raw_id) { - u32 dramid = (fuse_read_odm(4) & 0xF8) >> 3; + bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210; + u32 odm4 = fuse_read_odm(4); + + u32 dramid = (odm4 & 0xF8) >> 3; + + // Get extended dram id info. + if (!tegra_t210) + dramid |= (odm4 & 0x7000) >> 7; if (raw_id) return dramid; - if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210) + if (tegra_t210) { - if (dramid > 6) + if (dramid > 7) dramid = 0; } else { - if (dramid > 28) + if (dramid > 34) dramid = 8; } @@ -170,7 +185,8 @@ u32 fuse_read(u32 addr) void fuse_read_array(u32 *words) { - u32 array_size = (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01) ? 256 : 192; + u32 array_size = (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01) ? + FUSE_ARRAY_WORDS_NUM_T210B01 : FUSE_ARRAY_WORDS_NUM; for (u32 i = 0; i < array_size; i++) words[i] = fuse_read(i); @@ -180,9 +196,8 @@ static u32 _parity32_even(u32 *words, u32 count) { u32 acc = words[0]; for (u32 i = 1; i < count; i++) - { acc ^= words[i]; - } + u32 lo = ((acc & 0xffff) ^ (acc >> 16)) & 0xff; u32 hi = ((acc & 0xffff) ^ (acc >> 16)) >> 8; u32 x = hi ^ lo; @@ -198,26 +213,26 @@ static int _patch_hash_one(u32 *word) u32 bits20_31 = *word & 0xfff00000; u32 parity_bit = _parity32_even(&bits20_31, 1); u32 hash = 0; + for (u32 i = 0; i < 12; i++) { if (*word & (1 << (20 + i))) - { hash ^= hash_vals[i]; - } } + if (hash == 0) { if (parity_bit == 0) - { return 0; - } + *word ^= 1 << 24; + return 1; } + if (parity_bit == 0) - { return 3; - } + for (u32 i = 0; i < ARRAY_SIZE(hash_vals); i++) { if (hash_vals[i] == hash) @@ -226,6 +241,7 @@ static int _patch_hash_one(u32 *word) return 1; } } + return 2; } @@ -246,9 +262,7 @@ static int _patch_hash_multi(u32 *words, u32 count) for (u32 bitpos = 0; bitpos < 32; bitpos++) { if ((w >> bitpos) & 1) - { hash ^= 0x4000 + i * 32 + bitpos; - } } } } @@ -260,16 +274,14 @@ static int _patch_hash_multi(u32 *words, u32 count) if (hash == 0) { if (parity_bit == 0) - { return 0; - } + words[0] ^= 0x8000; return 1; } if (parity_bit == 0) - { return 3; - } + u32 bitcount = hash - 0x4000; if (bitcount < 16 || bitcount >= count * 32) { @@ -277,14 +289,11 @@ static int _patch_hash_multi(u32 *words, u32 count) for (u32 bitpos = 0; bitpos < 15; bitpos++) { if ((hash >> bitpos) & 1) - { num_set++; - } } if (num_set != 1) - { return 2; - } + words[0] ^= hash; return 1; } @@ -302,24 +311,30 @@ int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value)) word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE); word_count &= 0x7F; - word_addr = 191; + word_addr = FUSE_ARRAY_WORDS_NUM - 1; while (word_count) { total_read += word_count; if (total_read >= ARRAY_SIZE(words)) - { break; - } for (u32 i = 0; i < word_count; i++) + { words[i] = fuse_read(word_addr--); + // Parse extra T210B01 fuses when the difference is reached. + if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01 && + word_addr == ((FUSE_ARRAY_WORDS_NUM - 1) - + (FUSE_ARRAY_WORDS_NUM_T210B01 - FUSE_ARRAY_WORDS_NUM) / sizeof(u32))) + { + word_addr = FUSE_ARRAY_WORDS_NUM_T210B01 - 1; + } + } word0 = words[0]; if (_patch_hash_multi(words, word_count) >= 2) - { return 1; - } + u32 ipatch_count = (words[0] >> 16) & 0xF; if (ipatch_count) { @@ -332,13 +347,14 @@ int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value)) ipatch(addr, data); } } + words[0] = word0; if ((word0 >> 25) == 0) break; + if (_patch_hash_one(&word0) >= 2) - { return 3; - } + word_count = word0 >> 25; } @@ -354,29 +370,44 @@ int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len) u32 total_read = 0; int evp_thunk_written = 0; void *evp_thunk_dst_addr = 0; + bool t210b01 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01; + u32 *evp_thunk_tmp = (u32 *)malloc(sizeof(evp_thunk_template)); + memcpy(evp_thunk_tmp, evp_thunk_template, sizeof(evp_thunk_template)); memset(iram_evp_thunks, 0, *iram_evp_thunks_len); + if (t210b01) + memcpy(&evp_thunk_tmp[15], evp_thunk_func_offsets_t210b01, sizeof(evp_thunk_func_offsets_t210b01)); + word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE); word_count &= 0x7F; - word_addr = 191; + word_addr = FUSE_ARRAY_WORDS_NUM - 1; while (word_count) { total_read += word_count; if (total_read >= ARRAY_SIZE(words)) - { break; - } for (u32 i = 0; i < word_count; i++) + { words[i] = fuse_read(word_addr--); + // Parse extra T210B01 fuses when the difference is reached. + if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01 && + word_addr == ((FUSE_ARRAY_WORDS_NUM - 1) - + (FUSE_ARRAY_WORDS_NUM_T210B01 - FUSE_ARRAY_WORDS_NUM) / sizeof(u32))) + { + word_addr = FUSE_ARRAY_WORDS_NUM_T210B01 - 1; + } + } word0 = words[0]; if (_patch_hash_multi(words, word_count) >= 2) { + free(evp_thunk_tmp); return 1; } + u32 ipatch_count = (words[0] >> 16) & 0xF; u32 insn_count = word_count - ipatch_count - 1; if (insn_count) @@ -385,10 +416,10 @@ int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len) { evp_thunk_dst_addr = (void *)iram_evp_thunks; - memcpy(evp_thunk_dst_addr, (void *)evp_thunk_template, evp_thunk_template_len); - evp_thunk_dst_addr += evp_thunk_template_len; + memcpy(evp_thunk_dst_addr, (void *)evp_thunk_tmp, sizeof(evp_thunk_template)); + evp_thunk_dst_addr += sizeof(evp_thunk_template); evp_thunk_written = 1; - *iram_evp_thunks_len = evp_thunk_template_len; + *iram_evp_thunks_len = sizeof(evp_thunk_template); //write32(TEGRA_EXCEPTION_VECTORS_BASE + 0x208, iram_evp_thunks); } @@ -398,16 +429,22 @@ int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len) evp_thunk_dst_addr += thunk_patch_len; *iram_evp_thunks_len += thunk_patch_len; } + words[0] = word0; if ((word0 >> 25) == 0) break; + if (_patch_hash_one(&word0) >= 2) { + free(evp_thunk_tmp); return 3; } + word_count = word0 >> 25; } + free(evp_thunk_tmp); + return 0; } @@ -419,7 +456,7 @@ bool fuse_check_patched_rcm() // Check if RCM is ipatched. u32 word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE) & 0x7F; - u32 word_addr = 191; + u32 word_addr = FUSE_ARRAY_WORDS_NUM - 1; while (word_count) { diff --git a/bdk/soc/fuse.h b/bdk/soc/fuse.h index a9154bb..1b2f043 100644 --- a/bdk/soc/fuse.h +++ b/bdk/soc/fuse.h @@ -2,7 +2,7 @@ * Copyright (c) 2018 naehrwert * Copyright (c) 2018 shuffle2 * Copyright (c) 2018 balika011 - * Copyright (c) 2019-2021 CTCaer + * Copyright (c) 2019-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, @@ -82,12 +82,15 @@ /*! Fuse cache registers. */ #define FUSE_RESERVED_ODMX(x) (0x1C8 + 4 * (x)) +#define FUSE_ARRAY_WORDS_NUM 192 +#define FUSE_ARRAY_WORDS_NUM_T210B01 256 + enum { FUSE_NX_HW_TYPE_ICOSA, FUSE_NX_HW_TYPE_IOWA, FUSE_NX_HW_TYPE_HOAG, - FUSE_NX_HW_TYPE_AULA + FUSE_NX_HW_TYPE_AULA }; enum diff --git a/bdk/soc/gpio.c b/bdk/soc/gpio.c index 5cd2ccd..8575333 100644 --- a/bdk/soc/gpio.c +++ b/bdk/soc/gpio.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2019 CTCaer + * Copyright (c) 2019-2023 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, @@ -18,23 +18,27 @@ #include #include -#define GPIO_BANK_IDX(port) ((port) >> 2) +#define GPIO_BANK_IDX(port) ((port) >> 2) +#define GPIO_PORT_OFFSET(port) ((GPIO_BANK_IDX(port) << 8) + (((port) % 4) << 2)) -#define GPIO_CNF_OFFSET(port) (0x00 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_OE_OFFSET(port) (0x10 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_OUT_OFFSET(port) (0x20 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_IN_OFFSET(port) (0x30 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_INT_STA_OFFSET(port) (0x40 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_INT_ENB_OFFSET(port) (0x50 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_INT_LVL_OFFSET(port) (0x60 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_INT_CLR_OFFSET(port) (0x70 + (((port) >> 2) << 8) + (((port) % 4) << 2)) +#define GPIO_CNF_OFFSET(port) (0x00 + GPIO_PORT_OFFSET(port)) +#define GPIO_OE_OFFSET(port) (0x10 + GPIO_PORT_OFFSET(port)) +#define GPIO_OUT_OFFSET(port) (0x20 + GPIO_PORT_OFFSET(port)) +#define GPIO_IN_OFFSET(port) (0x30 + GPIO_PORT_OFFSET(port)) +#define GPIO_INT_STA_OFFSET(port) (0x40 + GPIO_PORT_OFFSET(port)) +#define GPIO_INT_ENB_OFFSET(port) (0x50 + GPIO_PORT_OFFSET(port)) +#define GPIO_INT_LVL_OFFSET(port) (0x60 + GPIO_PORT_OFFSET(port)) +#define GPIO_INT_CLR_OFFSET(port) (0x70 + GPIO_PORT_OFFSET(port)) -#define GPIO_CNF_MASKED_OFFSET(port) (0x80 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_OE_MASKED_OFFSET(port) (0x90 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_OUT_MASKED_OFFSET(port) (0xA0 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_INT_STA_MASKED_OFFSET(port) (0xC0 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_INT_ENB_MASKED_OFFSET(port) (0xD0 + (((port) >> 2) << 8) + (((port) % 4) << 2)) -#define GPIO_INT_LVL_MASKED_OFFSET(port) (0xE0 + (((port) >> 2) << 8) + (((port) % 4) << 2)) +#define GPIO_CNF_MASKED_OFFSET(port) (0x80 + GPIO_PORT_OFFSET(port)) +#define GPIO_OE_MASKED_OFFSET(port) (0x90 + GPIO_PORT_OFFSET(port)) +#define GPIO_OUT_MASKED_OFFSET(port) (0xA0 + GPIO_PORT_OFFSET(port)) +#define GPIO_INT_STA_MASKED_OFFSET(port) (0xC0 + GPIO_PORT_OFFSET(port)) +#define GPIO_INT_ENB_MASKED_OFFSET(port) (0xD0 + GPIO_PORT_OFFSET(port)) +#define GPIO_INT_LVL_MASKED_OFFSET(port) (0xE0 + GPIO_PORT_OFFSET(port)) + +#define GPIO_DB_CTRL_OFFSET(port) (0xB0 + GPIO_PORT_OFFSET(port)) +#define GPIO_DB_CNT_OFFSET(port) (0xF0 + GPIO_PORT_OFFSET(port)) #define GPIO_IRQ_BANK1 32 #define GPIO_IRQ_BANK2 33 @@ -52,7 +56,7 @@ static u8 gpio_bank_irq_ids[8] = { void gpio_config(u32 port, u32 pins, int mode) { - u32 offset = GPIO_CNF_OFFSET(port); + const u32 offset = GPIO_CNF_OFFSET(port); if (mode) GPIO(offset) |= pins; @@ -64,7 +68,7 @@ void gpio_config(u32 port, u32 pins, int mode) void gpio_output_enable(u32 port, u32 pins, int enable) { - u32 port_offset = GPIO_OE_OFFSET(port); + const u32 port_offset = GPIO_OE_OFFSET(port); if (enable) GPIO(port_offset) |= pins; @@ -76,7 +80,7 @@ void gpio_output_enable(u32 port, u32 pins, int enable) void gpio_write(u32 port, u32 pins, int high) { - u32 port_offset = GPIO_OUT_OFFSET(port); + const u32 port_offset = GPIO_OUT_OFFSET(port); if (high) GPIO(port_offset) |= pins; @@ -86,16 +90,49 @@ void gpio_write(u32 port, u32 pins, int high) (void)GPIO(port_offset); // Commit the write. } +void gpio_direction_input(u32 port, u32 pins) +{ + gpio_config(port, pins, GPIO_MODE_GPIO); + gpio_output_enable(port, pins, GPIO_OUTPUT_DISABLE); +} + +void gpio_direction_output(u32 port, u32 pins, int high) +{ + gpio_config(port, pins, GPIO_MODE_GPIO); + gpio_write(port, pins, high); + gpio_output_enable(port, pins, GPIO_OUTPUT_ENABLE); +} + int gpio_read(u32 port, u32 pins) { - u32 port_offset = GPIO_IN_OFFSET(port); + const u32 port_offset = GPIO_IN_OFFSET(port); return (GPIO(port_offset) & pins) ? 1 : 0; } +void gpio_set_debounce(u32 port, u32 pins, u32 ms) +{ + const u32 db_ctrl_offset = GPIO_DB_CTRL_OFFSET(port); + const u32 db_cnt_offset = GPIO_DB_CNT_OFFSET(port); + + if (ms) + { + if (ms > 255) + ms = 255; + + // Debounce time affects all pins of the same port. + GPIO(db_cnt_offset) = ms; + GPIO(db_ctrl_offset) = (pins << 8) | pins; + } + else + GPIO(db_ctrl_offset) = (pins << 8) | 0; + + (void)GPIO(db_ctrl_offset); // Commit the write. +} + static void _gpio_interrupt_clear(u32 port, u32 pins) { - u32 port_offset = GPIO_INT_CLR_OFFSET(port); + const u32 port_offset = GPIO_INT_CLR_OFFSET(port); GPIO(port_offset) |= pins; @@ -104,10 +141,10 @@ static void _gpio_interrupt_clear(u32 port, u32 pins) int gpio_interrupt_status(u32 port, u32 pins) { - u32 port_offset = GPIO_INT_STA_OFFSET(port); - u32 enabled = GPIO(GPIO_INT_ENB_OFFSET(port)) & pins; + const u32 port_offset = GPIO_INT_STA_OFFSET(port); + const u32 enabled_mask = GPIO(GPIO_INT_ENB_OFFSET(port)) & pins; - int status = ((GPIO(port_offset) & pins) && enabled) ? 1 : 0; + int status = ((GPIO(port_offset) & pins) && enabled_mask) ? 1 : 0; // Clear the interrupt status. if (status) @@ -118,7 +155,7 @@ int gpio_interrupt_status(u32 port, u32 pins) void gpio_interrupt_enable(u32 port, u32 pins, int enable) { - u32 port_offset = GPIO_INT_ENB_OFFSET(port); + const u32 port_offset = GPIO_INT_ENB_OFFSET(port); // Clear any possible stray interrupt. _gpio_interrupt_clear(port, pins); @@ -133,7 +170,7 @@ void gpio_interrupt_enable(u32 port, u32 pins, int enable) void gpio_interrupt_level(u32 port, u32 pins, int high, int edge, int delta) { - u32 port_offset = GPIO_INT_LVL_OFFSET(port); + const u32 port_offset = GPIO_INT_LVL_OFFSET(port); u32 val = GPIO(port_offset); @@ -162,7 +199,7 @@ void gpio_interrupt_level(u32 port, u32 pins, int high, int edge, int delta) u32 gpio_get_bank_irq_id(u32 port) { - u32 bank_idx = GPIO_BANK_IDX(port); + const u32 bank_idx = GPIO_BANK_IDX(port); return gpio_bank_irq_ids[bank_idx]; -} \ No newline at end of file +} diff --git a/bdk/soc/gpio.h b/bdk/soc/gpio.h index 0c92b14..7f94de5 100644 --- a/bdk/soc/gpio.h +++ b/bdk/soc/gpio.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2019 CTCaer + * Copyright (c) 2019-2023 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, @@ -85,8 +85,11 @@ void gpio_config(u32 port, u32 pins, int mode); void gpio_output_enable(u32 port, u32 pins, int enable); +void gpio_direction_input(u32 port, u32 pins); +void gpio_direction_output(u32 port, u32 pins, int high); void gpio_write(u32 port, u32 pins, int high); int gpio_read(u32 port, u32 pins); +void gpio_set_debounce(u32 port, u32 pins, u32 ms); int gpio_interrupt_status(u32 port, u32 pins); void gpio_interrupt_enable(u32 port, u32 pins, int enable); void gpio_interrupt_level(u32 port, u32 pins, int high, int edge, int delta); diff --git a/bdk/soc/hw_init.c b/bdk/soc/hw_init.c index c57b653..0c374ca 100644 --- a/bdk/soc/hw_init.c +++ b/bdk/soc/hw_init.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2022 CTCaer + * Copyright (c) 2018-2023 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -31,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -71,24 +73,24 @@ u32 hw_get_chip_id() static void _config_oscillators() { CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) = (CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) & 0xFFFFFFF3) | 4; // Set CLK_M_DIVISOR to 2. - SYSCTR0(SYSCTR0_CNTFID0) = 19200000; // Set counter frequency. - TMR(TIMERUS_USEC_CFG) = 0x45F; // For 19.2MHz clk_m. - CLOCK(CLK_RST_CONTROLLER_OSC_CTRL) = 0x50000071; // Set OSC to 38.4MHz and drive strength. + SYSCTR0(SYSCTR0_CNTFID0) = 19200000; // Set counter frequency. + TMR(TIMERUS_USEC_CFG) = 0x45F; // For 19.2MHz clk_m. + CLOCK(CLK_RST_CONTROLLER_OSC_CTRL) = 0x50000071; // Set OSC to 38.4MHz and drive strength. PMC(APBDEV_PMC_OSC_EDPD_OVER) = (PMC(APBDEV_PMC_OSC_EDPD_OVER) & 0xFFFFFF81) | 0xE; // Set LP0 OSC drive strength. PMC(APBDEV_PMC_OSC_EDPD_OVER) = (PMC(APBDEV_PMC_OSC_EDPD_OVER) & 0xFFBFFFFF) | PMC_OSC_EDPD_OVER_OSC_CTRL_OVER; - PMC(APBDEV_PMC_CNTRL2) = (PMC(APBDEV_PMC_CNTRL2) & 0xFFFFEFFF) | PMC_CNTRL2_HOLD_CKE_LOW_EN; - PMC(APB_MISC_GP_ASDBGREG) = (PMC(APB_MISC_GP_ASDBGREG) & 0xFCFFFFFF) | (2 << 24); // CFG2TMC_RAM_SVOP_PDP. + PMC(APBDEV_PMC_CNTRL2) = (PMC(APBDEV_PMC_CNTRL2) & 0xFFFFEFFF) | PMC_CNTRL2_HOLD_CKE_LOW_EN; + PMC(APB_MISC_GP_ASDBGREG) = (PMC(APB_MISC_GP_ASDBGREG) & 0xFCFFFFFF) | (2 << 24); // CFG2TMC_RAM_SVOP_PDP. - CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 0x10; // Set HCLK div to 2 and PCLK div to 1. - CLOCK(CLK_RST_CONTROLLER_PLLMB_BASE) &= 0xBFFFFFFF; // PLLMB disable. + CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 0x10; // Set HCLK div to 2 and PCLK div to 1. + CLOCK(CLK_RST_CONTROLLER_PLLMB_BASE) &= 0xBFFFFFFF; // PLLMB disable. - PMC(APBDEV_PMC_TSC_MULT) = (PMC(APBDEV_PMC_TSC_MULT) & 0xFFFF0000) | 0x249F; //0x249F = 19200000 * (16 / 32.768 kHz) + PMC(APBDEV_PMC_TSC_MULT) = (PMC(APBDEV_PMC_TSC_MULT) & 0xFFFF0000) | 0x249F; // 0x249F = 19200000 * (16 / 32.768 kHz). - CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SYS) = 0; // Set BPMP/SCLK div to 1. - CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20004444; // Set BPMP/SCLK source to Run and PLLP_OUT2 (204MHz). + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SYS) = 0; // Set BPMP/SCLK div to 1. + CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20004444; // Set BPMP/SCLK source to Run and PLLP_OUT2 (204MHz). CLOCK(CLK_RST_CONTROLLER_SUPER_SCLK_DIVIDER) = 0x80000000; // Enable SUPER_SDIV to 1. - CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // Set HCLK div to 1 and PCLK div to 3. + CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // Set HCLK div to 1 and PCLK div to 3. } // The uart is skipped for Copper, Hoag and Calcio. Used in Icosa, Iowa and Aula. @@ -99,53 +101,39 @@ static void _config_gpios(bool nx_hoag) if (!nx_hoag) { + // Turn Joy-Con detect on. (GPIO mode and input logic for UARTB/C TX pins.) PINMUX_AUX(PINMUX_AUX_UART2_TX) = 0; PINMUX_AUX(PINMUX_AUX_UART3_TX) = 0; - - // Set pin mode for UARTB/C TX pins. -#if !defined (DEBUG_UART_PORT) || DEBUG_UART_PORT != UART_B - gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO); -#endif -#if !defined (DEBUG_UART_PORT) || DEBUG_UART_PORT != UART_C - gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_GPIO); -#endif - - // Enable input logic for UARTB/C TX pins. - gpio_output_enable(GPIO_PORT_G, GPIO_PIN_0, GPIO_OUTPUT_DISABLE); - gpio_output_enable(GPIO_PORT_D, GPIO_PIN_1, GPIO_OUTPUT_DISABLE); + gpio_direction_input(GPIO_PORT_G, GPIO_PIN_0); + gpio_direction_input(GPIO_PORT_D, GPIO_PIN_1); } - // Set Joy-Con IsAttached direction. + // Set Joy-Con IsAttached pinmux. Shared with UARTB/UARTC TX. PINMUX_AUX(PINMUX_AUX_GPIO_PE6) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE; PINMUX_AUX(PINMUX_AUX_GPIO_PH6) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE; - // Set Joy-Con IsAttached mode. - gpio_config(GPIO_PORT_E, GPIO_PIN_6, GPIO_MODE_GPIO); - gpio_config(GPIO_PORT_H, GPIO_PIN_6, GPIO_MODE_GPIO); - - // Enable input logic for Joy-Con IsAttached pins. - gpio_output_enable(GPIO_PORT_E, GPIO_PIN_6, GPIO_OUTPUT_DISABLE); - gpio_output_enable(GPIO_PORT_H, GPIO_PIN_6, GPIO_OUTPUT_DISABLE); + // Configure Joy-Con IsAttached pins. Shared with UARTB/UARTC TX. + gpio_direction_input(GPIO_PORT_E, GPIO_PIN_6); + gpio_direction_input(GPIO_PORT_H, GPIO_PIN_6); pinmux_config_i2c(I2C_1); pinmux_config_i2c(I2C_5); pinmux_config_uart(UART_A); // Configure volume up/down as inputs. - gpio_config(GPIO_PORT_X, GPIO_PIN_6, GPIO_MODE_GPIO); - gpio_config(GPIO_PORT_X, GPIO_PIN_7, GPIO_MODE_GPIO); - gpio_output_enable(GPIO_PORT_X, GPIO_PIN_6, GPIO_OUTPUT_DISABLE); - gpio_output_enable(GPIO_PORT_X, GPIO_PIN_7, GPIO_OUTPUT_DISABLE); + gpio_direction_input(GPIO_PORT_X, GPIO_PIN_6 | GPIO_PIN_7); - // Configure HOME as inputs. + // Configure HOME as input. (Shared with UARTB RTS). PINMUX_AUX(PINMUX_AUX_BUTTON_HOME) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE; - gpio_config(GPIO_PORT_Y, GPIO_PIN_1, GPIO_MODE_GPIO); + gpio_direction_input(GPIO_PORT_Y, GPIO_PIN_1); + + // Power button can be configured for hoag here. Only SKU where it's connected. } static void _config_pmc_scratch() { PMC(APBDEV_PMC_SCRATCH20) &= 0xFFF3FFFF; // Unset Debug console from Customer Option. - PMC(APBDEV_PMC_SCRATCH190) &= 0xFFFFFFFE; // Unset DATA_DQ_E_IVREF EMC_PMACRO_DATA_PAD_TX_CTRL + PMC(APBDEV_PMC_SCRATCH190) &= 0xFFFFFFFE; // Unset WDT_DURING_BR. PMC(APBDEV_PMC_SECURE_SCRATCH21) |= PMC_FUSE_PRIVATEKEYDISABLE_TZ_STICKY_BIT; } @@ -178,8 +166,9 @@ static void _mbist_workaround() I2S(I2S5_CTRL) |= I2S_CTRL_MASTER_EN; I2S(I2S5_CG) &= ~I2S_CG_SLCG_ENABLE; + // Set SLCG overrides. DISPLAY_A(_DIREG(DC_COM_DSC_TOP_CTL)) |= 4; // DSC_SLCG_OVERRIDE. - VIC(0x8C) = 0xFFFFFFFF; + VIC(VIC_THI_SLCG_OVERRIDE_LOW_A) = 0xFFFFFFFF; usleep(2); // Set per-clock reset for APE/VIC/HOST1X/DISP1. @@ -246,9 +235,9 @@ static void _mbist_workaround() // Set child clock sources. CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) &= 0x1F7FFFFF; // Disable PLLD and set reference clock and csi clock. CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SOR1) &= 0xFFFF3FFF; // Set SOR1 to automatic muxing of safe clock (24MHz) or SOR1 clk switch. - CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_VI) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_VI) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT. + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_VI) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_VI) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT. CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT. - CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_NVENC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_NVENC) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT. + CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_NVENC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_NVENC) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT. } static void _config_se_brom() @@ -263,17 +252,19 @@ static void _config_se_brom() // se_key_acc_ctrl(15, SE_KEY_TBL_DIS_KEYREAD_FLAG); // This memset needs to happen here, else TZRAM will behave weirdly later on. - memset((void *)TZRAM_BASE, 0, SZ_64K); + memset((void *)TZRAM_BASE, 0, TZRAM_SIZE); PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_ENABLE; - SE(SE_INT_STATUS_REG) = 0x1F; // Clear all SE interrupts. + + // Clear SE interrupts. + SE(SE_INT_STATUS_REG) = SE_INT_OP_DONE | SE_INT_OUT_DONE | SE_INT_OUT_LL_BUF_WR | SE_INT_IN_DONE | SE_INT_IN_LL_BUF_RD; // Save reset reason. hw_rst_status = PMC(APBDEV_PMC_SCRATCH200); hw_rst_reason = PMC(APBDEV_PMC_RST_STATUS) & PMC_RST_STATUS_MASK; // Clear the boot reason to avoid problems later. - PMC(APBDEV_PMC_SCRATCH200) = 0x0; - PMC(APBDEV_PMC_RST_STATUS) = 0x0; + PMC(APBDEV_PMC_SCRATCH200) = 0; + PMC(APBDEV_PMC_RST_STATUS) = PMC_RST_STATUS_POR; APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) = (APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) & 0xF0) | (7 << 10); } @@ -291,6 +282,9 @@ static void _config_regulators(bool tegra_t210) max7762x_regulator_enable(REGULATOR_LDO2, false); sd_power_cycle_time_start = get_tmr_ms(); + // Disable LCD DVDD. + max7762x_regulator_enable(REGULATOR_LDO0, false); + 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. @@ -327,15 +321,17 @@ static void _config_regulators(bool tegra_t210) void hw_init() { - // Get Chip ID. + // Get Chip ID and SKU. bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210; bool nx_hoag = fuse_read_hw_type() == FUSE_NX_HW_TYPE_HOAG; // Bootrom stuff we skipped by going through rcm. _config_se_brom(); //FUSE(FUSE_PRIVATEKEYDISABLE) = 0x11; - SYSREG(AHB_AHB_SPARE_REG) &= 0xFFFFFF9F; // Unset APB2JTAG_OVERRIDE_EN and OBS_OVERRIDE_EN. - PMC(APBDEV_PMC_SCRATCH49) = PMC(APBDEV_PMC_SCRATCH49) & 0xFFFFFFFC; + + // Unset APB2JTAG_OVERRIDE_EN and OBS_OVERRIDE_EN. + SYSREG(AHB_AHB_SPARE_REG) &= 0xFFFFFF9F; + PMC(APBDEV_PMC_SCRATCH49) &= 0xFFFFFFFC; // Perform Memory Built-In Self Test WAR if T210. if (tegra_t210) @@ -360,8 +356,14 @@ void hw_init() _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_init(DEBUG_UART_PORT, DEBUG_UART_BAUDRATE, UART_AO_TX_AO_RX); uart_invert(DEBUG_UART_PORT, DEBUG_UART_INVERT, UART_INVERT_TXD); #endif @@ -378,7 +380,7 @@ void hw_init() // Initialize I2C5, mandatory for PMIC. i2c_init(I2C_5); - //! TODO: Why? Device is NFC MCU on Lite. + // Enable LDO8 on HOAG as it also powers I2C1 IO pads. if (nx_hoag) { max7762x_regulator_set_voltage(REGULATOR_LDO8, 2800000); @@ -391,9 +393,6 @@ void hw_init() // Initialize various regulators based on Erista/Mariko platform. _config_regulators(tegra_t210); - // Enable charger in case it's disabled. - bq24193_enable_charger(); - _config_pmc_scratch(); // Missing from 4.x+ // Set BPMP/SCLK to PLLP_OUT (408MHz). @@ -402,24 +401,30 @@ void hw_init() // Power on T210B01 shadow TZRAM and lock the reg. if (!tegra_t210) { - PMC(APBDEV_PMC_TZRAM_PWR_CNTRL) &= ~PMC_TZRAM_PWR_CNTRL_SD; + PMC(APBDEV_PMC_TZRAM_PWR_CNTRL) &= ~PMC_TZRAM_PWR_CNTRL_SD; PMC(APBDEV_PMC_TZRAM_NON_SEC_DISABLE) = PMC_TZRAM_DISABLE_REG_WRITE | PMC_TZRAM_DISABLE_REG_READ; - PMC(APBDEV_PMC_TZRAM_SEC_DISABLE) = PMC_TZRAM_DISABLE_REG_WRITE | PMC_TZRAM_DISABLE_REG_READ; + PMC(APBDEV_PMC_TZRAM_SEC_DISABLE) = PMC_TZRAM_DISABLE_REG_WRITE | PMC_TZRAM_DISABLE_REG_READ; } // Initialize External memory controller and configure DRAM parameters. sdram_init(); bpmp_mmu_enable(); + + // Enable HOST1X used by every display module (DC, VIC, NVDEC, NVENC, TSEC, etc). + clock_enable_host1x(); } void hw_reinit_workaround(bool coreboot, u32 bl_magic) { - // Disable BPMP max clock. + bool tegra_t210 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210; + + // Scale down BPMP clock. bpmp_clk_rate_set(BPMP_CLK_NORMAL); #ifdef BDK_HW_EXTRA_DEINIT - // Disable temperature sensor, touchscreen, 5V regulators and Joy-Con. + // Disable temperature sensor, touchscreen, 5V regulators, Joy-Con and VIC. + vic_end(); tmp451_end(); set_fan_duty(0); touch_power_off(); @@ -427,14 +432,19 @@ void hw_reinit_workaround(bool coreboot, u32 bl_magic) regulator_5v_disable(REGULATOR_5V_ALL); #endif - // Flush/disable MMU cache and set DRAM clock to 204MHz. - bpmp_mmu_disable(); + // set DRAM clock to 204MHz. minerva_change_freq(FREQ_204); nyx_str->mtc_cfg.init_done = 0; + // Flush/disable MMU cache. + bpmp_mmu_disable(); + // Re-enable clocks to Audio Processing Engine as a workaround to hanging. - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= BIT(CLK_V_AHUB); - CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= BIT(CLK_Y_APE); + if (tegra_t210) + { + CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= BIT(CLK_V_AHUB); + CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= BIT(CLK_Y_APE); + } // Do coreboot mitigations. if (coreboot) @@ -443,11 +453,9 @@ void hw_reinit_workaround(bool coreboot, u32 bl_magic) clock_disable_cl_dvfs(); - // Disable Joy-con GPIOs. + // Disable Joy-con detect in order to restore UART TX. gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO); gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO); - gpio_config(GPIO_PORT_E, GPIO_PIN_6, GPIO_MODE_SPIO); - gpio_config(GPIO_PORT_H, GPIO_PIN_6, GPIO_MODE_SPIO); // Reinstate SD controller power. PMC(APBDEV_PMC_NO_IOPOWER) &= ~(PMC_NO_IOPOWER_SDMMC1_IO_EN); @@ -463,17 +471,11 @@ void hw_reinit_workaround(bool coreboot, u32 bl_magic) gpio_config(GPIO_PORT_V, GPIO_PIN_0, GPIO_MODE_GPIO); display_backlight_brightness(brightness, 0); break; + case BL_MAGIC_L4TLDR_SLD: + // Do not disable display or backlight at all. + break; default: display_end(); - } - - // Enable clock to USBD and init SDMMC1 to avoid hangs with bad hw inits. - if (bl_magic == BL_MAGIC_BROKEN_HWI) - { - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_USBD); - sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, 0); - clock_disable_cl_dvfs(); - - msleep(200); + clock_disable_host1x(); } } diff --git a/bdk/soc/hw_init.h b/bdk/soc/hw_init.h index a36498b..aebb021 100644 --- a/bdk/soc/hw_init.h +++ b/bdk/soc/hw_init.h @@ -21,8 +21,7 @@ #include #define BL_MAGIC_CRBOOT_SLD 0x30444C53 // SLD0, seamless display type 0. -#define BL_MAGIC_HEKATF_SLD 0x31444C53 // SLD1, seamless display type 1. -#define BL_MAGIC_BROKEN_HWI 0xBAADF00D // Broken hwinit. +#define BL_MAGIC_L4TLDR_SLD 0x31444C53 // SLD1, seamless display type 1. extern u32 hw_rst_status; extern u32 hw_rst_reason; diff --git a/bdk/soc/i2c.c b/bdk/soc/i2c.c index 0906adc..34aa666 100644 --- a/bdk/soc/i2c.c +++ b/bdk/soc/i2c.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2020 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, @@ -18,7 +18,7 @@ #include #include -#include +#include #define I2C_PACKET_PROT_I2C BIT(4) #define I2C_HEADER_CONT_XFER BIT(15) @@ -95,9 +95,9 @@ static void _i2c_load_cfg_wait(vu32 *base) base[I2C_CONFIG_LOAD] = BIT(5) | TIMEOUT_CONFIG_LOAD | MSTR_CONFIG_LOAD; for (u32 i = 0; i < 20; i++) { - usleep(1); if (!(base[I2C_CONFIG_LOAD] & MSTR_CONFIG_LOAD)) break; + usleep(1); } } @@ -205,8 +205,8 @@ static int _i2c_send_pkt(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr) ARB_LOST | TX_FIFO_OVER | RX_FIFO_UNDER | TX_FIFO_DATA_REQ; base[I2C_INT_STATUS] = base[I2C_INT_STATUS]; - // Set device address and recv mode. - base[I2C_CMD_ADDR0] = (dev_addr << 1) | ADDR0_READ; + // Set device address and send mode. + base[I2C_CMD_ADDR0] = (dev_addr << 1) | ADDR0_WRITE; // Set recv mode. base[I2C_CNFG] = DEBOUNCE_CNT_4T | NEW_MASTER_FSM | CMD1_WRITE; @@ -362,9 +362,9 @@ void i2c_init(u32 i2c_idx) for (u32 i = 0; i < 10; i++) { - usleep(20000); if (base[I2C_INT_STATUS] & BUS_CLEAR_DONE) break; + usleep(25); } (vu32)base[I2C_BUS_CLEAR_STATUS]; diff --git a/bdk/soc/irq.c b/bdk/soc/irq.c index e2f925c..380cfe1 100644 --- a/bdk/soc/irq.c +++ b/bdk/soc/irq.c @@ -19,6 +19,7 @@ #include #include "irq.h" +#include #include #include #include @@ -26,6 +27,7 @@ //#define DPRINTF(...) gfx_printf(__VA_ARGS__) #define DPRINTF(...) +extern void excp_reset(); extern void irq_disable(); extern void irq_enable_cpu_irq_exceptions(); extern void irq_disable_cpu_irq_exceptions(); @@ -69,7 +71,7 @@ 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; + ICTLR(ctrl_idx, PRI_ICTLR_FIR_CLR) = enabled_irqs; } } @@ -88,10 +90,10 @@ void irq_free(u32 irq) { if (irqs[idx].irq == irq && irqs[idx].handler) { - irqs[idx].irq = 0; + irqs[idx].irq = 0; irqs[idx].handler = NULL; - irqs[idx].data = NULL; - irqs[idx].flags = 0; + irqs[idx].data = NULL; + irqs[idx].flags = 0; _irq_disable_source(irq); } @@ -106,10 +108,10 @@ static void _irq_free_all() { _irq_disable_source(irqs[idx].irq); - irqs[idx].irq = 0; + irqs[idx].irq = 0; irqs[idx].handler = NULL; - irqs[idx].data = NULL; - irqs[idx].flags = 0; + irqs[idx].data = NULL; + irqs[idx].flags = 0; } } } @@ -218,10 +220,10 @@ irq_status_t irq_request(u32 irq, irq_handler_t handler, void *data, irq_flags_t DPRINTF("Registered handler, IRQ: %d, Slot: %d\n", irq, idx); DPRINTF("Handler: %08p, Flags: %x\n", (u32)handler, flags); - irqs[idx].irq = irq; + irqs[idx].irq = irq; irqs[idx].handler = handler; - irqs[idx].data = data; - irqs[idx].flags = flags; + irqs[idx].data = data; + irqs[idx].flags = flags; _irq_enable_source(irq); @@ -270,4 +272,14 @@ void __attribute__ ((target("arm"), interrupt ("FIQ"))) fiq_handler() len--; } */ +#ifdef BDK_WATCHDOG_FIQ_ENABLE + // Set watchdog timeout status and disable WDT and its FIQ signal. + watchdog_handle(); + +#ifdef BDK_RESTART_BL_ON_WDT + // Restart bootloader. + excp_reset(); +#endif + +#endif } diff --git a/bdk/soc/pinmux.c b/bdk/soc/pinmux.c index 2601cdf..288a4f7 100644 --- a/bdk/soc/pinmux.c +++ b/bdk/soc/pinmux.c @@ -19,10 +19,10 @@ void pinmux_config_uart(u32 idx) { - PINMUX_AUX(PINMUX_AUX_UARTX_TX(idx)) = 0; - PINMUX_AUX(PINMUX_AUX_UARTX_RX(idx)) = PINMUX_INPUT_ENABLE | PINMUX_PULL_UP; + PINMUX_AUX(PINMUX_AUX_UARTX_TX(idx)) = 0; + PINMUX_AUX(PINMUX_AUX_UARTX_RX(idx)) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE; PINMUX_AUX(PINMUX_AUX_UARTX_RTS(idx)) = 0; - PINMUX_AUX(PINMUX_AUX_UARTX_CTS(idx)) = PINMUX_INPUT_ENABLE | PINMUX_PULL_DOWN; + PINMUX_AUX(PINMUX_AUX_UARTX_CTS(idx)) = PINMUX_INPUT_ENABLE | PINMUX_TRISTATE; } void pinmux_config_i2c(u32 idx) diff --git a/bdk/soc/pinmux.h b/bdk/soc/pinmux.h index 48fcab3..070ce1e 100644 --- a/bdk/soc/pinmux.h +++ b/bdk/soc/pinmux.h @@ -39,6 +39,7 @@ #define PINMUX_AUX_SDMMC3_DAT2 0x2C #define PINMUX_AUX_SDMMC3_DAT3 0x30 #define PINMUX_AUX_SATA_LED_ACTIVE 0x4C +#define PINMUX_AUX_GPIO_PA5_T210B01 PINMUX_AUX_SATA_LED_ACTIVE #define PINMUX_AUX_DMIC3_CLK 0xB4 #define PINMUX_AUX_DMIC3_DAT 0xB8 #define PINMUX_AUX_CAM_I2C_SCL 0xD4 @@ -46,7 +47,9 @@ #define PINMUX_AUX_UART2_TX 0xF4 #define PINMUX_AUX_UART3_TX 0x104 #define PINMUX_AUX_DAP4_DIN 0x148 +#define PINMUX_AUX_DAP4_DOUT 0x14C #define PINMUX_AUX_DAP4_SCLK 0x150 +#define PINMUX_AUX_CLK_32K_OUT 0x164 #define PINMUX_AUX_GPIO_X1_AUD 0x18C #define PINMUX_AUX_GPIO_X3_AUD 0x190 #define PINMUX_AUX_SPDIF_IN 0x1A4 @@ -57,19 +60,26 @@ #define PINMUX_AUX_AP_WAKE_NFC 0x1CC #define PINMUX_AUX_NFC_EN 0x1D0 #define PINMUX_AUX_NFC_INT 0x1D4 +#define PINMUX_AUX_CAM_RST 0x1E0 #define PINMUX_AUX_CAM1_PWDN 0x1EC #define PINMUX_AUX_CAM2_PWDN 0x1F0 +#define PINMUX_AUX_CAM1_STROBE 0x1F4 #define PINMUX_AUX_LCD_BL_PWM 0x1FC #define PINMUX_AUX_LCD_BL_EN 0x200 #define PINMUX_AUX_LCD_RST 0x204 #define PINMUX_AUX_LCD_GPIO1 0x208 #define PINMUX_AUX_LCD_GPIO2 0x20C +#define PINMUX_AUX_TOUCH_CLK 0x218 #define PINMUX_AUX_TOUCH_INT 0x220 #define PINMUX_AUX_MOTION_INT 0x224 +#define PINMUX_AUX_ALS_PROX_INT 0x228 +#define PINMUX_AUX_BUTTON_POWER_ON 0x230 #define PINMUX_AUX_BUTTON_HOME 0x240 #define PINMUX_AUX_GPIO_PE6 0x248 +#define PINMUX_AUX_GPIO_PE7 0x24C #define PINMUX_AUX_GPIO_PH6 0x250 #define PINMUX_AUX_GPIO_PK3 0x260 +#define PINMUX_AUX_GPIO_PK7 0x270 #define PINMUX_AUX_GPIO_PZ1 0x280 /* Only in T210B01 */ #define PINMUX_AUX_SDMMC2_DAT0 0x294 @@ -116,6 +126,8 @@ #define PINMUX_DRIVE_3X (2 << 13) #define PINMUX_DRIVE_4X (3 << 13) +#define PINMUX_PREEMP BIT(15) + void pinmux_config_uart(u32 idx); void pinmux_config_i2c(u32 idx); diff --git a/bdk/soc/pmc.c b/bdk/soc/pmc.c index aa86cb7..472b22c 100644 --- a/bdk/soc/pmc.c +++ b/bdk/soc/pmc.c @@ -16,31 +16,28 @@ #include #include +#include #include -#include void pmc_scratch_lock(pmc_sec_lock_t lock_mask) { // Lock Private key disable, Fuse write enable, MC carveout, Warmboot PA id and Warmboot address. + + // Happens on T210B01 LP0 always. if (lock_mask & PMC_SEC_LOCK_MISC) { PMC(APBDEV_PMC_SEC_DISABLE) |= 0x700FF0; // RW lock: 0-3. PMC(APBDEV_PMC_SEC_DISABLE2) |= 0xFC000000; // RW lock: 21-23. PMC(APBDEV_PMC_SEC_DISABLE3) |= 0x3F0FFF00; // RW lock: 28-33, 36-38. PMC(APBDEV_PMC_SEC_DISABLE6) |= 0xC000000; // RW lock: 85. - PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xFF00FF00; // RW lock: 108-111, 116-119. - - // SE2 context. - if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01) - { - PMC(APBDEV_PMC_SEC_DISABLE9) |= 0x3FF; // RW lock: 120-124. (0xB38) - PMC(APBDEV_PMC_SEC_DISABLE10) = 0xFFFFFFFF; // RW lock: 135-150. - } + // Default: 0xFF00FF00: RW lock: 108-111, 116-119. Gets locked in LP0. + PMC(APBDEV_PMC_SEC_DISABLE8) |= 0xFF005500; // W lock: 108-111, RW lock: 116-119. } + // Happens on T210B01 LP0 always. if (lock_mask & PMC_SEC_LOCK_LP0_PARAMS) { - PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x3FCFFFF; // RW lock: 8-15, 17-20. + PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x3FCFFFF; // RW lock: 8-15, 17-20. L4T expects 8-15 as write locked only. PMC(APBDEV_PMC_SEC_DISABLE4) |= 0x3F3FFFFF; // RW lock: 40-50, 52-54. PMC(APBDEV_PMC_SEC_DISABLE5) = 0xFFFFFFFF; // RW lock: 56-71. PMC(APBDEV_PMC_SEC_DISABLE6) |= 0xF3FFC00F; // RW lock: 72-73, 79-84, 86-87. @@ -60,6 +57,7 @@ void pmc_scratch_lock(pmc_sec_lock_t lock_mask) PMC(APBDEV_PMC_SEC_DISABLE7) |= 0xFFC00000; // RW lock: 99-103. } + // HOS specific. if (lock_mask & PMC_SEC_LOCK_TZ_CMAC_W) PMC(APBDEV_PMC_SEC_DISABLE8) |= 0x550000; // W lock: 112-115. @@ -71,9 +69,34 @@ void pmc_scratch_lock(pmc_sec_lock_t lock_mask) if (lock_mask & PMC_SEC_LOCK_TZ_KEK_R) PMC(APBDEV_PMC_SEC_DISABLE3) |= 0xAA; // R lock: 24-27. + // End of HOS specific. if (lock_mask & PMC_SEC_LOCK_SE_SRK) PMC(APBDEV_PMC_SEC_DISABLE) |= 0xFF000; // RW lock: 4-7 + + if (lock_mask & PMC_SEC_LOCK_SE2_SRK_B01) + PMC(APBDEV_PMC_SEC_DISABLE9) |= 0x3FC; // RW lock: 120-123 (T210B01). LP0 also sets global bits (b0-1). + + if (lock_mask & PMC_SEC_LOCK_MISC_B01) + PMC(APBDEV_PMC_SEC_DISABLE10) = 0xFFFFFFFF; // RW lock: 135-150. Happens on T210B01 LP0 always. + + if (lock_mask & PMC_SEC_LOCK_CARVEOUTS_L4T) + PMC(APBDEV_PMC_SEC_DISABLE2) |= 0x5555; // W: 8-15 LP0 and Carveouts. Superseded by LP0 lock. + + // NVTBOOT misses APBDEV_PMC_SCRATCH_WRITE_LOCK_DISABLE_STICKY. bit0: SCRATCH_WR_DIS_ON. + // They could also use the NS write disable registers instead. + if (lock_mask & PMC_SEC_LOCK_LP0_PARAMS_B01) + { + PMC(APBDEV_PMC_SCRATCH_WRITE_DISABLE0) |= 0xCBCFE0; // W lock: 5-11, 14-17, 19, 22-23. + PMC(APBDEV_PMC_SCRATCH_WRITE_DISABLE1) |= 0x583FF; // W lock: 24-33, 39-40, 42. + PMC(APBDEV_PMC_SCRATCH_WRITE_DISABLE2) |= 0x1BE; // W lock: 44-48, 50-51. + PMC(APBDEV_PMC_SCRATCH_WRITE_DISABLE3) = 0xFFFFFFFF; // W lock: 56-87. + PMC(APBDEV_PMC_SCRATCH_WRITE_DISABLE4) |= 0xFFFFFFF; // W lock: 88-115. + PMC(APBDEV_PMC_SCRATCH_WRITE_DISABLE5) |= 0xFFFFFFF8; // W lock: 123-151. + PMC(APBDEV_PMC_SCRATCH_WRITE_DISABLE6) = 0xFFFFFFFF; // W lock: 152-183. + PMC(APBDEV_PMC_SCRATCH_WRITE_DISABLE7) |= 0xFC00FFFF; // W lock: 184-199, 210-215. + PMC(APBDEV_PMC_SCRATCH_WRITE_DISABLE8) |= 0xF; // W lock: 216-219. + } } int pmc_enable_partition(pmc_power_rail_t part, u32 enable) diff --git a/bdk/soc/pmc.h b/bdk/soc/pmc.h index c5ad559..e983447 100644 --- a/bdk/soc/pmc.h +++ b/bdk/soc/pmc.h @@ -22,108 +22,183 @@ #include /*! PMC registers. */ -#define APBDEV_PMC_CNTRL 0x0 -#define PMC_CNTRL_MAIN_RST BIT(4) -#define APBDEV_PMC_SEC_DISABLE 0x4 -#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_AUDIO_HV BIT(18) -#define PMC_NO_IOPOWER_GPIO_IO_EN BIT(21) -#define APBDEV_PMC_SCRATCH0 0x50 -#define PMC_SCRATCH0_MODE_WARMBOOT BIT(0) -#define PMC_SCRATCH0_MODE_RCM BIT(1) -#define PMC_SCRATCH0_MODE_PAYLOAD BIT(29) -#define PMC_SCRATCH0_MODE_FASTBOOT BIT(30) -#define PMC_SCRATCH0_MODE_RECOVERY BIT(31) -#define PMC_SCRATCH0_MODE_CUSTOM_ALL (PMC_SCRATCH0_MODE_RECOVERY | PMC_SCRATCH0_MODE_FASTBOOT | PMC_SCRATCH0_MODE_PAYLOAD) -#define APBDEV_PMC_SCRATCH1 0x54 -#define APBDEV_PMC_SCRATCH20 0xA0 -#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 APBDEV_PMC_DDR_PWR 0xE8 -#define APBDEV_PMC_USB_AO 0xF0 -#define APBDEV_PMC_CRYPTO_OP 0xF4 -#define PMC_CRYPTO_OP_SE_ENABLE 0 -#define PMC_CRYPTO_OP_SE_DISABLE 1 -#define APBDEV_PMC_SCRATCH33 0x120 -#define APBDEV_PMC_SCRATCH37 0x130 -#define PMC_SCRATCH37_KERNEL_PANIC_MAGIC 0x4E415054 -#define APBDEV_PMC_SCRATCH40 0x13C -#define APBDEV_PMC_OSC_EDPD_OVER 0x1A4 -#define PMC_OSC_EDPD_OVER_OSC_CTRL_OVER 0x400000 -#define APBDEV_PMC_CLK_OUT_CNTRL 0x1A8 -#define PMC_CLK_OUT_CNTRL_CLK1_FORCE_EN BIT(2) -#define APBDEV_PMC_RST_STATUS 0x1B4 -#define PMC_RST_STATUS_MASK 0x7 -#define PMC_RST_STATUS_POR 0 -#define PMC_RST_STATUS_WATCHDOG 1 -#define PMC_RST_STATUS_SENSOR 2 -#define PMC_RST_STATUS_SW_MAIN 3 -#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 APBDEV_PMC_IO_DPD2_REQ 0x1C0 -#define APBDEV_PMC_VDDP_SEL 0x1CC -#define APBDEV_PMC_DDR_CFG 0x1D0 -#define APBDEV_PMC_SECURE_SCRATCH6 0x224 -#define APBDEV_PMC_SECURE_SCRATCH7 0x228 -#define APBDEV_PMC_SCRATCH45 0x234 -#define APBDEV_PMC_SCRATCH46 0x238 -#define APBDEV_PMC_SCRATCH49 0x244 -#define APBDEV_PMC_TSC_MULT 0x2B4 -#define APBDEV_PMC_SEC_DISABLE2 0x2C4 -#define APBDEV_PMC_WEAK_BIAS 0x2C8 -#define APBDEV_PMC_REG_SHORT 0x2CC -#define APBDEV_PMC_SEC_DISABLE3 0x2D8 -#define APBDEV_PMC_SECURE_SCRATCH21 0x334 -#define PMC_FUSE_PRIVATEKEYDISABLE_TZ_STICKY_BIT 0x10 -#define APBDEV_PMC_SECURE_SCRATCH32 0x360 -#define APBDEV_PMC_SECURE_SCRATCH49 0x3A4 -#define APBDEV_PMC_CNTRL2 0x440 -#define PMC_CNTRL2_HOLD_CKE_LOW_EN 0x1000 -#define APBDEV_PMC_IO_DPD3_REQ 0x45C -#define APBDEV_PMC_IO_DPD4_REQ 0x464 -#define APBDEV_PMC_UTMIP_PAD_CFG1 0x4C4 -#define APBDEV_PMC_UTMIP_PAD_CFG3 0x4CC -#define APBDEV_PMC_DDR_CNTRL 0x4E4 -#define APBDEV_PMC_SEC_DISABLE4 0x5B0 -#define APBDEV_PMC_SEC_DISABLE5 0x5B4 -#define APBDEV_PMC_SEC_DISABLE6 0x5B8 -#define APBDEV_PMC_SEC_DISABLE7 0x5BC -#define APBDEV_PMC_SEC_DISABLE8 0x5C0 -#define APBDEV_PMC_SEC_DISABLE9 0x5C4 -#define APBDEV_PMC_SEC_DISABLE10 0x5C8 -#define APBDEV_PMC_SCRATCH188 0x810 -#define APBDEV_PMC_SCRATCH190 0x818 -#define APBDEV_PMC_SCRATCH200 0x840 +#define APBDEV_PMC_CNTRL 0x0 +#define PMC_CNTRL_RTC_CLK_DIS BIT(1) +#define PMC_CNTRL_RTC_RST BIT(2) +#define PMC_CNTRL_MAIN_RST BIT(4) +#define PMC_CNTRL_LATCHWAKE_EN BIT(5) +#define PMC_CNTRL_BLINK_EN BIT(7) +#define PMC_CNTRL_PWRREQ_OE BIT(9) +#define PMC_CNTRL_SYSCLK_OE BIT(11) +#define PMC_CNTRL_PWRGATE_DIS BIT(12) +#define PMC_CNTRL_SIDE_EFFECT_LP0 BIT(14) +#define PMC_CNTRL_CPUPWRREQ_OE BIT(16) +#define PMC_CNTRL_FUSE_OVERRIDE BIT(18) +#define PMC_CNTRL_SHUTDOWN_OE BIT(22) +#define APBDEV_PMC_SEC_DISABLE 0x4 +#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_AUDIO_HV BIT(18) +#define PMC_NO_IOPOWER_GPIO_IO_EN BIT(21) +#define APBDEV_PMC_SCRATCH0 0x50 +#define PMC_SCRATCH0_MODE_WARMBOOT BIT(0) +#define PMC_SCRATCH0_MODE_RCM BIT(1) +#define PMC_SCRATCH0_MODE_PAYLOAD BIT(29) +#define PMC_SCRATCH0_MODE_BOOTLOADER BIT(30) +#define PMC_SCRATCH0_MODE_RECOVERY BIT(31) +#define PMC_SCRATCH0_MODE_CUSTOM_ALL (PMC_SCRATCH0_MODE_RECOVERY | \ + PMC_SCRATCH0_MODE_BOOTLOADER | \ + PMC_SCRATCH0_MODE_PAYLOAD) +#define APBDEV_PMC_BLINK_TIMER 0x40 +#define PMC_BLINK_ON(n) ((n & 0x7FFF)) +#define PMC_BLINK_FORCE BIT(15) +#define PMC_BLINK_OFF(n) ((u32)(n & 0xFFFF) << 16) +#define APBDEV_PMC_SCRATCH1 0x54 +#define APBDEV_PMC_SCRATCH20 0xA0 // ODM data/config scratch. +#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 APBDEV_PMC_DDR_PWR 0xE8 +#define APBDEV_PMC_USB_AO 0xF0 +#define APBDEV_PMC_CRYPTO_OP 0xF4 +#define PMC_CRYPTO_OP_SE_ENABLE 0 +#define PMC_CRYPTO_OP_SE_DISABLE 1 +#define APBDEV_PMC_PLLP_WB0_OVERRIDE 0xF8 +#define PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE_ENABLE BIT(11) +#define PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE BIT(12) +#define APBDEV_PMC_SCRATCH33 0x120 +#define APBDEV_PMC_SCRATCH37 0x130 +#define PMC_SCRATCH37_KERNEL_PANIC_MAGIC 0x4E415054 // "TPAN" +#define APBDEV_PMC_SCRATCH39 0x138 +#define APBDEV_PMC_SCRATCH40 0x13C +#define APBDEV_PMC_OSC_EDPD_OVER 0x1A4 +#define PMC_OSC_EDPD_OVER_OSC_CTRL_OVER BIT(22) +#define APBDEV_PMC_CLK_OUT_CNTRL 0x1A8 +#define PMC_CLK_OUT_CNTRL_CLK1_FORCE_EN BIT(2) +#define PMC_CLK_OUT_CNTRL_CLK2_FORCE_EN BIT(10) +#define PMC_CLK_OUT_CNTRL_CLK3_FORCE_EN BIT(18) +#define PMC_CLK_OUT_CNTRL_CLK1_SRC_SEL(src) (((src) & 3) << 6) +#define PMC_CLK_OUT_CNTRL_CLK2_SRC_SEL(src) (((src) & 3) << 14) +#define PMC_CLK_OUT_CNTRL_CLK3_SRC_SEL(src) (((src) & 3) << 22) +#define OSC_DIV1 0 +#define OSC_DIV2 1 +#define OSC_DIV4 2 +#define OSC_CAR 3 +#define APBDEV_PMC_RST_STATUS 0x1B4 +#define PMC_RST_STATUS_MASK 7 +#define PMC_RST_STATUS_POR 0 +#define PMC_RST_STATUS_WATCHDOG 1 +#define PMC_RST_STATUS_SENSOR 2 +#define PMC_RST_STATUS_SW_MAIN 3 +#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 APBDEV_PMC_IO_DPD2_REQ 0x1C0 +#define APBDEV_PMC_VDDP_SEL 0x1CC +#define APBDEV_PMC_DDR_CFG 0x1D0 +#define APBDEV_PMC_SECURE_SCRATCH6 0x224 +#define APBDEV_PMC_SECURE_SCRATCH7 0x228 +#define APBDEV_PMC_SCRATCH45 0x234 +#define APBDEV_PMC_SCRATCH46 0x238 +#define APBDEV_PMC_SCRATCH49 0x244 +#define APBDEV_PMC_SCRATCH52 0x250 +#define APBDEV_PMC_SCRATCH53 0x254 +#define APBDEV_PMC_SCRATCH54 0x258 +#define APBDEV_PMC_SCRATCH55 0x25C +#define APBDEV_PMC_TSC_MULT 0x2B4 +#define APBDEV_PMC_STICKY_BITS 0x2C0 +#define PMC_STICKY_BITS_HDA_LPBK_DIS BIT(0) +#define APBDEV_PMC_SEC_DISABLE2 0x2C4 +#define APBDEV_PMC_WEAK_BIAS 0x2C8 +#define APBDEV_PMC_REG_SHORT 0x2CC +#define APBDEV_PMC_SEC_DISABLE3 0x2D8 +#define APBDEV_PMC_SECURE_SCRATCH21 0x334 +#define PMC_FUSE_PRIVATEKEYDISABLE_TZ_STICKY_BIT BIT(4) +#define APBDEV_PMC_SECURE_SCRATCH22 0x338 // AArch32 reset address. +#define APBDEV_PMC_SECURE_SCRATCH32 0x360 +#define APBDEV_PMC_SECURE_SCRATCH34 0x368 // AArch64 reset address. +#define APBDEV_PMC_SECURE_SCRATCH35 0x36C // AArch64 reset hi-address. +#define APBDEV_PMC_SECURE_SCRATCH49 0x3A4 +#define APBDEV_PMC_CNTRL2 0x440 +#define PMC_CNTRL2_WAKE_INT_EN BIT(0) +#define PMC_CNTRL2_WAKE_DET_EN BIT(9) +#define PMC_CNTRL2_SYSCLK_ORRIDE BIT(10) +#define PMC_CNTRL2_HOLD_CKE_LOW_EN BIT(12) +#define PMC_CNTRL2_ALLOW_PULSE_WAKE BIT(14) +#define APBDEV_PMC_IO_DPD3_REQ 0x45C +#define APBDEV_PMC_IO_DPD4_REQ 0x464 +#define APBDEV_PMC_UTMIP_PAD_CFG1 0x4C4 +#define APBDEV_PMC_UTMIP_PAD_CFG3 0x4CC +#define APBDEV_PMC_DDR_CNTRL 0x4E4 +#define APBDEV_PMC_SEC_DISABLE4 0x5B0 +#define APBDEV_PMC_SEC_DISABLE5 0x5B4 +#define APBDEV_PMC_SEC_DISABLE6 0x5B8 +#define APBDEV_PMC_SEC_DISABLE7 0x5BC +#define APBDEV_PMC_SEC_DISABLE8 0x5C0 +#define APBDEV_PMC_SEC_DISABLE9 0x5C4 +#define APBDEV_PMC_SEC_DISABLE10 0x5C8 +#define APBDEV_PMC_SCRATCH188 0x810 +#define APBDEV_PMC_SCRATCH190 0x818 +#define APBDEV_PMC_SCRATCH200 0x840 +#define APBDEV_PMC_SCRATCH201 0x844 +#define APBDEV_PMC_SCRATCH250 0x908 #define APBDEV_PMC_SECURE_SCRATCH108 0xB08 #define APBDEV_PMC_SECURE_SCRATCH109 0xB0C #define APBDEV_PMC_SECURE_SCRATCH110 0xB10 -#define APBDEV_PMC_TZRAM_PWR_CNTRL 0xBE8 -#define PMC_TZRAM_PWR_CNTRL_SD BIT(0) -#define APBDEV_PMC_TZRAM_SEC_DISABLE 0xBEC -#define APBDEV_PMC_TZRAM_NON_SEC_DISABLE 0xBF0 -#define PMC_TZRAM_DISABLE_REG_WRITE BIT(0) -#define PMC_TZRAM_DISABLE_REG_READ BIT(1) +#define APBDEV_PMC_SECURE_SCRATCH112 0xB18 +#define APBDEV_PMC_SECURE_SCRATCH113 0xB1C +#define APBDEV_PMC_SECURE_SCRATCH114 0xB20 +#define APBDEV_PMC_SECURE_SCRATCH119 0xB34 + +// Only in T210B01. +#define APBDEV_PMC_SCRATCH_WRITE_DISABLE0 0xA48 +#define APBDEV_PMC_SCRATCH_WRITE_DISABLE1 0xA4C +#define APBDEV_PMC_SCRATCH_WRITE_DISABLE2 0xA50 +#define APBDEV_PMC_SCRATCH_WRITE_DISABLE3 0xA54 +#define APBDEV_PMC_SCRATCH_WRITE_DISABLE4 0xA58 +#define APBDEV_PMC_SCRATCH_WRITE_DISABLE5 0xA5C +#define APBDEV_PMC_SCRATCH_WRITE_DISABLE6 0xA60 +#define APBDEV_PMC_SCRATCH_WRITE_DISABLE7 0xA64 +#define APBDEV_PMC_SCRATCH_WRITE_DISABLE8 0xA68 +#define APBDEV_PMC_LED_BREATHING_CTRL 0xB48 +#define PMC_LED_BREATHING_CTRL_ENABLE BIT(0) +#define PMC_LED_BREATHING_CTRL_COUNTER1_EN BIT(1) +#define APBDEV_PMC_LED_BREATHING_SLOPE_STEPS 0xB4C +#define APBDEV_PMC_LED_BREATHING_ON_COUNTER 0xB50 +#define APBDEV_PMC_LED_BREATHING_OFF_COUNTER1 0xB54 +#define APBDEV_PMC_LED_BREATHING_OFF_COUNTER0 0xB58 +#define PMC_LED_BREATHING_COUNTER_HZ 32768 +#define APBDEV_PMC_LED_BREATHING_STATUS 0xB5C +#define PMC_LED_BREATHING_FSM_STATUS_MASK 0x7 +#define APBDEV_PMC_TZRAM_PWR_CNTRL 0xBE8 +#define PMC_TZRAM_PWR_CNTRL_SD BIT(0) +#define APBDEV_PMC_TZRAM_SEC_DISABLE 0xBEC +#define APBDEV_PMC_TZRAM_NON_SEC_DISABLE 0xBF0 +#define PMC_TZRAM_DISABLE_REG_WRITE BIT(0) +#define PMC_TZRAM_DISABLE_REG_READ BIT(1) typedef enum _pmc_sec_lock_t { - PMC_SEC_LOCK_MISC = BIT(0), - PMC_SEC_LOCK_LP0_PARAMS = BIT(1), - PMC_SEC_LOCK_RST_VECTOR = BIT(2), - PMC_SEC_LOCK_CARVEOUTS = BIT(3), - PMC_SEC_LOCK_TZ_CMAC_W = BIT(4), - PMC_SEC_LOCK_TZ_CMAC_R = BIT(5), - PMC_SEC_LOCK_TZ_KEK_W = BIT(6), - PMC_SEC_LOCK_TZ_KEK_R = BIT(7), - PMC_SEC_LOCK_SE_SRK = BIT(8), + PMC_SEC_LOCK_MISC = BIT(0), + PMC_SEC_LOCK_LP0_PARAMS = BIT(1), + PMC_SEC_LOCK_RST_VECTOR = BIT(2), + PMC_SEC_LOCK_CARVEOUTS = BIT(3), + PMC_SEC_LOCK_TZ_CMAC_W = BIT(4), + PMC_SEC_LOCK_TZ_CMAC_R = BIT(5), + PMC_SEC_LOCK_TZ_KEK_W = BIT(6), + PMC_SEC_LOCK_TZ_KEK_R = BIT(7), + PMC_SEC_LOCK_SE_SRK = BIT(8), + PMC_SEC_LOCK_SE2_SRK_B01 = BIT(9), + PMC_SEC_LOCK_MISC_B01 = BIT(10), + PMC_SEC_LOCK_CARVEOUTS_L4T = BIT(11), + PMC_SEC_LOCK_LP0_PARAMS_B01 = BIT(12), } pmc_sec_lock_t; typedef enum _pmc_power_rail_t diff --git a/bdk/soc/t210.h b/bdk/soc/t210.h index cbacfdf..5de9e53 100644 --- a/bdk/soc/t210.h +++ b/bdk/soc/t210.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 naehrwert +* Copyright (c) 2018-2023 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, @@ -26,8 +27,10 @@ #define DISPLAY_A_BASE 0x54200000 #define DSI_BASE 0x54300000 #define VIC_BASE 0x54340000 +#define NVDEC_BASE 0x54480000 #define TSEC_BASE 0x54500000 #define SOR1_BASE 0x54580000 +#define MSELECT_BASE 0x50060000 #define ICTLR_BASE 0x60004000 #define TMR_BASE 0x60005000 #define CLOCK_BASE 0x60006000 @@ -70,6 +73,8 @@ #define I2S_BASE 0x702D1000 #define ADMA_BASE 0x702E2000 #define TZRAM_BASE 0x7C010000 +#define TZRAM_SIZE 0x10000 +#define TZRAM_T210B01_SIZE 0x3C000 #define USB_BASE 0x7D000000 #define USB_OTG_BASE USB_BASE #define USB1_BASE 0x7D004000 @@ -81,8 +86,10 @@ #define DISPLAY_A(off) _REG(DISPLAY_A_BASE, off) #define DSI(off) _REG(DSI_BASE, off) #define VIC(off) _REG(VIC_BASE, off) +#define NVDEC(off) _REG(NVDEC_BASE, off) #define TSEC(off) _REG(TSEC_BASE, off) #define SOR1(off) _REG(SOR1_BASE, off) +#define MSELECT(off) _REG(MSELECT_BASE, off) #define ICTLR(cidx, off) _REG(ICTLR_BASE + (0x100 * (cidx)), off) #define TMR(off) _REG(TMR_BASE, off) #define CLOCK(off) _REG(CLOCK_BASE, off) @@ -128,98 +135,99 @@ #define USB1(off) _REG(USB1_BASE, off) #define TEST_REG(off) _REG(0x0, off) -/* HOST1X registers. */ -#define HOST1X_CH0_SYNC_BASE 0x2100 -#define HOST1X_CH0_SYNC_SYNCPT_9 (HOST1X_CH0_SYNC_BASE + 0xFA4) -#define HOST1X_CH0_SYNC_SYNCPT_160 (HOST1X_CH0_SYNC_BASE + 0x1200) +/* HOST1X v3 registers. */ +#define HOST1X_CH0_SYNC_BASE 0x2100 +#define HOST1X_CH0_SYNC_SYNCPT_BASE (HOST1X_CH0_SYNC_BASE + 0xF80) +#define HOST1X_CH0_SYNC_SYNCPT_9 (HOST1X_CH0_SYNC_SYNCPT_BASE + 0x24) +#define HOST1X_CH0_SYNC_SYNCPT_160 (HOST1X_CH0_SYNC_SYNCPT_BASE + 0x280) /*! EVP registers. */ -#define EVP_CPU_RESET_VECTOR 0x100 -#define EVP_COP_RESET_VECTOR 0x200 -#define EVP_COP_UNDEF_VECTOR 0x204 -#define EVP_COP_SWI_VECTOR 0x208 +#define EVP_CPU_RESET_VECTOR 0x100 +#define EVP_COP_RESET_VECTOR 0x200 +#define EVP_COP_UNDEF_VECTOR 0x204 +#define EVP_COP_SWI_VECTOR 0x208 #define EVP_COP_PREFETCH_ABORT_VECTOR 0x20C -#define EVP_COP_DATA_ABORT_VECTOR 0x210 -#define EVP_COP_RSVD_VECTOR 0x214 -#define EVP_COP_IRQ_VECTOR 0x218 -#define EVP_COP_FIQ_VECTOR 0x21C -#define EVP_COP_IRQ_STS 0x220 +#define EVP_COP_DATA_ABORT_VECTOR 0x210 +#define EVP_COP_RSVD_VECTOR 0x214 +#define EVP_COP_IRQ_VECTOR 0x218 +#define EVP_COP_FIQ_VECTOR 0x21C +#define EVP_COP_IRQ_STS 0x220 /*! Primary Interrupt Controller registers. */ -#define PRI_ICTLR_FIR 0x14 -#define PRI_ICTLR_FIR_SET 0x18 -#define PRI_ICTLR_FIR_CLR 0x1C -#define PRI_ICTLR_CPU_IER 0x20 -#define PRI_ICTLR_CPU_IER_SET 0x24 -#define PRI_ICTLR_CPU_IER_CLR 0x28 +#define PRI_ICTLR_FIR 0x14 +#define PRI_ICTLR_FIR_SET 0x18 +#define PRI_ICTLR_FIR_CLR 0x1C +#define PRI_ICTLR_CPU_IER 0x20 +#define PRI_ICTLR_CPU_IER_SET 0x24 +#define PRI_ICTLR_CPU_IER_CLR 0x28 #define PRI_ICTLR_CPU_IEP_CLASS 0x2C -#define PRI_ICTLR_COP_IER 0x30 -#define PRI_ICTLR_COP_IER_SET 0x34 -#define PRI_ICTLR_COP_IER_CLR 0x38 +#define PRI_ICTLR_COP_IER 0x30 +#define PRI_ICTLR_COP_IER_SET 0x34 +#define PRI_ICTLR_COP_IER_CLR 0x38 #define PRI_ICTLR_COP_IEP_CLASS 0x3C /*! AHB Gizmo registers. */ -#define AHB_ARBITRATION_PRIORITY_CTRL 0x8 -#define PRIORITY_CTRL_WEIGHT(x) (((x) & 7) << 29) -#define PRIORITY_SELECT_USB BIT(6) // USB-OTG. -#define PRIORITY_SELECT_USB2 BIT(18) // USB-HSIC. -#define PRIORITY_SELECT_USB3 BIT(17) // XUSB. -#define AHB_GIZMO_AHB_MEM 0x10 -#define AHB_MEM_ENB_FAST_REARBITRATE BIT(2) -#define AHB_MEM_DONT_SPLIT_AHB_WR BIT(7) -#define AHB_MEM_IMMEDIATE BIT(18) -#define AHB_GIZMO_APB_DMA 0x14 -#define AHB_GIZMO_USB 0x20 -#define AHB_GIZMO_SDMMC4 0x48 -#define AHB_GIZMO_USB2 0x7C -#define AHB_GIZMO_USB3 0x80 -#define AHB_GIZMO_IMMEDIATE BIT(18) -#define AHB_ARBITRATION_XBAR_CTRL 0xE0 -#define AHB_AHB_MEM_PREFETCH_CFG3 0xE4 -#define AHB_AHB_MEM_PREFETCH_CFG4 0xE8 -#define AHB_AHB_MEM_PREFETCH_CFG1 0xF0 -#define AHB_AHB_MEM_PREFETCH_CFG2 0xF4 -#define MST_ID(x) (((x) & 0x1F) << 26) -#define MEM_PREFETCH_AHBDMA_MST_ID MST_ID(5) -#define MEM_PREFETCH_USB_MST_ID MST_ID(6) // USB-OTG. -#define MEM_PREFETCH_USB2_MST_ID MST_ID(18) // USB-HSIC. -#define MEM_PREFETCH_USB3_MST_ID MST_ID(17) // XUSB. -#define MEM_PREFETCH_ADDR_BNDRY(x) (((x) & 0xF) << 21) -#define MEM_PREFETCH_ENABLE BIT(31) +#define AHB_ARBITRATION_PRIORITY_CTRL 0x8 +#define PRIORITY_CTRL_WEIGHT(x) (((x) & 7) << 29) +#define PRIORITY_SELECT_USB BIT(6) // USB-OTG. +#define PRIORITY_SELECT_USB2 BIT(18) // USB-HSIC. +#define PRIORITY_SELECT_USB3 BIT(17) // XUSB. +#define AHB_GIZMO_AHB_MEM 0x10 +#define AHB_MEM_ENB_FAST_REARBITRATE BIT(2) +#define AHB_MEM_DONT_SPLIT_AHB_WR BIT(7) +#define AHB_MEM_IMMEDIATE BIT(18) +#define AHB_GIZMO_APB_DMA 0x14 +#define AHB_GIZMO_USB 0x20 +#define AHB_GIZMO_SDMMC4 0x48 +#define AHB_GIZMO_USB2 0x7C +#define AHB_GIZMO_USB3 0x80 +#define AHB_GIZMO_IMMEDIATE BIT(18) +#define AHB_ARBITRATION_XBAR_CTRL 0xE0 +#define AHB_AHB_MEM_PREFETCH_CFG3 0xE4 +#define AHB_AHB_MEM_PREFETCH_CFG4 0xE8 +#define AHB_AHB_MEM_PREFETCH_CFG1 0xF0 +#define AHB_AHB_MEM_PREFETCH_CFG2 0xF4 +#define MST_ID(x) (((x) & 0x1F) << 26) +#define MEM_PREFETCH_AHBDMA_MST_ID MST_ID(5) +#define MEM_PREFETCH_USB_MST_ID MST_ID(6) // USB-OTG. +#define MEM_PREFETCH_USB2_MST_ID MST_ID(18) // USB-HSIC. +#define MEM_PREFETCH_USB3_MST_ID MST_ID(17) // XUSB. +#define MEM_PREFETCH_ADDR_BNDRY(x) (((x) & 0xF) << 21) +#define MEM_PREFETCH_ENABLE BIT(31) #define AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID 0xFC -#define MEM_WRQUE_SE_MST_ID BIT(14) -#define AHB_AHB_SPARE_REG 0x110 +#define MEM_WRQUE_SE_MST_ID BIT(14) +#define AHB_AHB_SPARE_REG 0x110 /*! Misc registers. */ -#define APB_MISC_PP_STRAPPING_OPT_A 0x08 -#define APB_MISC_PP_PINMUX_GLOBAL 0x40 -#define APB_MISC_GP_HIDREV 0x804 -#define GP_HIDREV_MAJOR_T210 0x1 -#define GP_HIDREV_MAJOR_T210B01 0x2 -#define APB_MISC_GP_ASDBGREG 0x810 -#define APB_MISC_GP_AUD_MCLK_CFGPADCTRL 0x8F4 -#define APB_MISC_GP_LCD_BL_PWM_CFGPADCTRL 0xA34 -#define APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL 0xA98 -#define APB_MISC_GP_EMMC2_PAD_CFGPADCTRL 0xA9C -#define APB_MISC_GP_EMMC4_PAD_CFGPADCTRL 0xAB4 +#define APB_MISC_PP_STRAPPING_OPT_A 0x8 +#define APB_MISC_PP_PINMUX_GLOBAL 0x40 +#define APB_MISC_GP_HIDREV 0x804 +#define GP_HIDREV_MAJOR_T210 0x1 +#define GP_HIDREV_MAJOR_T210B01 0x2 +#define APB_MISC_GP_ASDBGREG 0x810 +#define APB_MISC_GP_AUD_MCLK_CFGPADCTRL 0x8F4 +#define APB_MISC_GP_LCD_BL_PWM_CFGPADCTRL 0xA34 +#define APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL 0xA98 +#define APB_MISC_GP_EMMC2_PAD_CFGPADCTRL 0xA9C +#define APB_MISC_GP_EMMC4_PAD_CFGPADCTRL 0xAB4 #define APB_MISC_GP_EMMC4_PAD_PUPD_CFGPADCTRL 0xABC -#define APB_MISC_GP_DSI_PAD_CONTROL 0xAC0 -#define APB_MISC_GP_WIFI_EN_CFGPADCTRL 0xB64 -#define APB_MISC_GP_WIFI_RST_CFGPADCTRL 0xB68 +#define APB_MISC_GP_DSI_PAD_CONTROL 0xAC0 +#define APB_MISC_GP_WIFI_EN_CFGPADCTRL 0xB64 +#define APB_MISC_GP_WIFI_RST_CFGPADCTRL 0xB68 /*! Secure boot registers. */ -#define SB_CSR 0x0 -#define SB_CSR_NS_RST_VEC_WR_DIS BIT(1) -#define SB_CSR_PIROM_DISABLE BIT(4) -#define SB_AA64_RESET_LOW 0x30 -#define SB_AA64_RST_AARCH64_MODE_EN BIT(0) -#define SB_AA64_RESET_HIGH 0x34 +#define SB_CSR 0x0 +#define SB_CSR_NS_RST_VEC_WR_DIS BIT(1) +#define SB_CSR_PIROM_DISABLE BIT(4) +#define SB_AA64_RESET_LOW 0x30 +#define SB_AA64_RST_AARCH64_MODE_EN BIT(0) +#define SB_AA64_RESET_HIGH 0x34 /*! SOR registers. */ -#define SOR_NV_PDISP_SOR_DP_HDCP_BKSV_LSB 0x1E8 -#define SOR_NV_PDISP_SOR_TMDS_HDCP_BKSV_LSB 0x21C -#define SOR_NV_PDISP_SOR_TMDS_HDCP_CN_MSB 0x208 -#define SOR_NV_PDISP_SOR_TMDS_HDCP_CN_LSB 0x20C +#define SOR_DP_HDCP_BKSV_LSB 0x1E8 +#define SOR_TMDS_HDCP_BKSV_LSB 0x21C +#define SOR_TMDS_HDCP_CN_MSB 0x208 +#define SOR_TMDS_HDCP_CN_LSB 0x20C /*! RTC registers. */ #define APBDEV_RTC_SECONDS 0x8 @@ -227,42 +235,22 @@ #define APBDEV_RTC_MILLI_SECONDS 0x10 /*! SYSCTR0 registers. */ -#define SYSCTR0_CNTFID0 0x20 -#define SYSCTR0_CNTCR 0x00 -#define SYSCTR0_COUNTERID0 0xFE0 -#define SYSCTR0_COUNTERID1 0xFE4 -#define SYSCTR0_COUNTERID2 0xFE8 -#define SYSCTR0_COUNTERID3 0xFEC -#define SYSCTR0_COUNTERID4 0xFD0 -#define SYSCTR0_COUNTERID5 0xFD4 -#define SYSCTR0_COUNTERID6 0xFD8 -#define SYSCTR0_COUNTERID7 0xFDC -#define SYSCTR0_COUNTERID8 0xFF0 -#define SYSCTR0_COUNTERID9 0xFF4 -#define SYSCTR0_COUNTERID10 0xFF8 -#define SYSCTR0_COUNTERID11 0xFFC - -/*! TMR registers. */ -#define TIMERUS_CNTR_1US (0x10 + 0x0) -#define TIMERUS_USEC_CFG (0x10 + 0x4) -#define TIMER_TMR8_TMR_PTV 0x78 -#define TIMER_TMR9_TMR_PTV 0x80 -#define TIMER_PER_EN BIT(30) -#define TIMER_EN BIT(31) -#define TIMER_TMR8_TMR_PCR 0x7C -#define TIMER_TMR9_TMR_PCR 0x8C -#define TIMER_INTR_CLR BIT(30) - -#define TIMER_WDT4_CONFIG (0x100 + 0x80) -#define TIMER_SRC(TMR) ((TMR) & 0xF) -#define TIMER_PER(PER) (((PER) & 0xFF) << 4) -#define TIMER_SYSRESET_EN BIT(14) -#define TIMER_PMCRESET_EN BIT(15) -#define TIMER_WDT4_COMMAND (0x108 + 0x80) -#define TIMER_START_CNT BIT(0) -#define TIMER_CNT_DISABLE BIT(1) -#define TIMER_WDT4_UNLOCK_PATTERN (0x10C + 0x80) -#define TIMER_MAGIC_PTRN 0xC45A +#define SYSCTR0_CNTCR 0x00 +#define SYSCTR0_CNTFID0 0x20 +#define SYSCTR0_COUNTERS_BASE 0xFD0 +#define SYSCTR0_COUNTERS 12 +#define SYSCTR0_COUNTERID0 0xFE0 +#define SYSCTR0_COUNTERID1 0xFE4 +#define SYSCTR0_COUNTERID2 0xFE8 +#define SYSCTR0_COUNTERID3 0xFEC +#define SYSCTR0_COUNTERID4 0xFD0 +#define SYSCTR0_COUNTERID5 0xFD4 +#define SYSCTR0_COUNTERID6 0xFD8 +#define SYSCTR0_COUNTERID7 0xFDC +#define SYSCTR0_COUNTERID8 0xFF0 +#define SYSCTR0_COUNTERID9 0xFF4 +#define SYSCTR0_COUNTERID10 0xFF8 +#define SYSCTR0_COUNTERID11 0xFFC /*! I2S registers. */ #define I2S1_CG 0x88 @@ -288,25 +276,42 @@ #define EMC_HEKA_UPD BIT(30) /*! Flow controller registers. */ -#define FLOW_CTLR_HALT_COP_EVENTS 0x4 -#define HALT_COP_GIC_IRQ BIT(9) -#define HALT_COP_LIC_IRQ BIT(11) -#define HALT_COP_SEC BIT(23) -#define HALT_COP_MSEC BIT(24) -#define HALT_COP_USEC BIT(25) -#define HALT_COP_JTAG BIT(28) -#define HALT_COP_WAIT_EVENT BIT(30) -#define HALT_COP_STOP_UNTIL_IRQ BIT(31) -#define HALT_COP_MAX_CNT 0xFF -#define FLOW_CTLR_HALT_CPU0_EVENTS 0x0 -#define FLOW_CTLR_HALT_CPU1_EVENTS 0x14 -#define FLOW_CTLR_HALT_CPU2_EVENTS 0x1C -#define FLOW_CTLR_HALT_CPU3_EVENTS 0x24 -#define FLOW_CTLR_CPU0_CSR 0x8 -#define FLOW_CTLR_CPU1_CSR 0x18 -#define FLOW_CTLR_CPU2_CSR 0x20 -#define FLOW_CTLR_CPU3_CSR 0x28 -#define FLOW_CTLR_RAM_REPAIR 0x40 +#define FLOW_CTLR_HALT_COP_EVENTS 0x4 +#define HALT_COP_GIC_IRQ BIT(9) +#define HALT_COP_LIC_IRQ BIT(11) +#define HALT_COP_SEC BIT(23) +#define HALT_COP_MSEC BIT(24) +#define HALT_COP_USEC BIT(25) +#define HALT_COP_JTAG BIT(28) +#define HALT_COP_WAIT_EVENT BIT(30) +#define HALT_COP_STOP_UNTIL_IRQ BIT(31) +#define HALT_COP_MAX_CNT 0xFF +#define FLOW_CTLR_HALT_CPU0_EVENTS 0x0 +#define FLOW_CTLR_HALT_CPU1_EVENTS 0x14 +#define FLOW_CTLR_HALT_CPU2_EVENTS 0x1C +#define FLOW_CTLR_HALT_CPU3_EVENTS 0x24 +#define FLOW_CTLR_CPU0_CSR 0x8 +#define FLOW_CTLR_CPU1_CSR 0x18 +#define FLOW_CTLR_CPU2_CSR 0x20 +#define FLOW_CTLR_CPU3_CSR 0x28 +#define FLOW_CTLR_RAM_REPAIR 0x40 +#define RAM_REPAIR_REQ BIT(0) +#define RAM_REPAIR_STS BIT(1) #define FLOW_CTLR_BPMP_CLUSTER_CONTROL 0x98 +#define CLUSTER_CTRL_ACTIVE_SLOW BIT(0) +/* MSelect registers */ +#define MSELECT_CONFIG 0x00 +#define MSELECT_CFG_ERR_RESP_EN_PCIE BIT(24) +#define MSELECT_CFG_ERR_RESP_EN_GPU BIT(25) +#define MSELECT_CFG_WRAP_TO_INCR_BPMP BIT(27) +#define MSELECT_CFG_WRAP_TO_INCR_PCIE BIT(28) +#define MSELECT_CFG_WRAP_TO_INCR_GPU BIT(29) + +/* NVDEC registers */ +#define NVDEC_SA_KEYSLOT_FALCON 0x2100 +#define NVDEC_SA_KEYSLOT_TZ 0x2104 +#define NVDEC_SA_KEYSLOT_OTF 0x210C +#define NVDEC_SA_KEYSLOT_GLOBAL_RW 0x2118 +#define NVDEC_VPR_ALL_OTF_GOTO_VPR 0x211C #endif diff --git a/bdk/soc/timer.c b/bdk/soc/timer.c new file mode 100644 index 0000000..c6c5b83 --- /dev/null +++ b/bdk/soc/timer.c @@ -0,0 +1,121 @@ +/* + * Timer/Watchdog driver for Tegra X1 + * + * Copyright (c) 2019 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, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include + +#define EXCP_TYPE_ADDR 0x4003FFF8 +#define EXCP_TYPE_WDT 0x544457 // "WDT". + +u32 get_tmr_s() +{ + (void)RTC(APBDEV_RTC_MILLI_SECONDS); + return (u32)RTC(APBDEV_RTC_SECONDS); +} + +u32 get_tmr_ms() +{ + // The registers must be read with the following order: + // RTC_MILLI_SECONDS (0x10) -> RTC_SHADOW_SECONDS (0xC) + return (u32)(RTC(APBDEV_RTC_MILLI_SECONDS) + (RTC(APBDEV_RTC_SHADOW_SECONDS) * 1000)); +} + +u32 get_tmr_us() +{ + return (u32)TMR(TIMERUS_CNTR_1US); +} + +void msleep(u32 ms) +{ +#ifdef USE_RTC_TIMER + u32 start = (u32)RTC(APBDEV_RTC_MILLI_SECONDS) + (RTC(APBDEV_RTC_SHADOW_SECONDS) * 1000); + // Casting to u32 is important! + while (((u32)(RTC(APBDEV_RTC_MILLI_SECONDS) + (RTC(APBDEV_RTC_SHADOW_SECONDS) * 1000)) - start) <= ms) + ; +#else + bpmp_msleep(ms); +#endif +} + +void usleep(u32 us) +{ +#ifdef USE_RTC_TIMER + u32 start = (u32)TMR(TIMERUS_CNTR_1US); + + // Check if timer is at upper limits and use BPMP sleep so it doesn't wake up immediately. + if ((start + us) < start) + bpmp_usleep(us); + else + while ((u32)(TMR(TIMERUS_CNTR_1US) - start) <= us) // Casting to u32 is important! + ; +#else + bpmp_usleep(us); +#endif +} + +// Instruction wait loop. Each loop is 3 cycles (SUBS+BGT). Usage: isleep(ILOOP(instr)). Base 408MHz: 7.35ns. +void __attribute__((target("arm"))) isleep(u32 is) +{ + asm volatile( "0:" "SUBS %[is_cnt], #1;" "BGT 0b;" : [is_cnt] "+r" (is)); +} + +void timer_usleep(u32 us) +{ + TMR(TIMER_TMR8_TMR_PTV) = TIMER_EN | us; + + irq_wait_event(IRQ_TMR8); + + TMR(TIMER_TMR8_TMR_PCR) = TIMER_INTR_CLR; +} + +void watchdog_start(u32 us, u32 mode) +{ + // WDT4 is for BPMP. + TMR(TIMER_WDT4_UNLOCK_PATTERN) = TIMER_MAGIC_PTRN; + TMR(TIMER_TMR9_TMR_PTV) = TIMER_EN | TIMER_PER_EN | us; + TMR(TIMER_WDT4_CONFIG) = TIMER_SRC(9) | TIMER_PER(1) | mode; + TMR(TIMER_WDT4_COMMAND) = TIMER_START_CNT; +} + +void watchdog_end() +{ + // WDT4 is for BPMP. + TMR(TIMER_TMR9_TMR_PTV) = 0; + TMR(TIMER_WDT4_UNLOCK_PATTERN) = TIMER_MAGIC_PTRN; + TMR(TIMER_WDT4_COMMAND) = TIMER_START_CNT; // Re-arm to clear any interrupts. + TMR(TIMER_WDT4_COMMAND) = TIMER_CNT_DISABLE; + TMR(TIMER_TMR9_TMR_PCR) = TIMER_INTR_CLR; +} + +void watchdog_handle() +{ + // Disable watchdog and clear its interrupts. + watchdog_end(); + + // Set watchdog magic. + *(u32 *)EXCP_TYPE_ADDR = EXCP_TYPE_WDT; +} + +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/timer.h b/bdk/soc/timer.h new file mode 100644 index 0000000..800eaac --- /dev/null +++ b/bdk/soc/timer.h @@ -0,0 +1,64 @@ +/* + * Timer/Watchdog driver for Tegra X1 + * + * Copyright (c) 2019 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, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _TIMER_H_ +#define _TIMER_H_ + +#include + +// TMR registers. +#define TIMERUS_CNTR_1US (0x10 + 0x0) +#define TIMERUS_USEC_CFG (0x10 + 0x4) +#define TIMER_TMR8_TMR_PTV 0x78 +#define TIMER_TMR9_TMR_PTV 0x80 +#define TIMER_PER_EN BIT(30) +#define TIMER_EN BIT(31) +#define TIMER_TMR8_TMR_PCR 0x7C +#define TIMER_TMR9_TMR_PCR 0x8C +#define TIMER_INTR_CLR BIT(30) + +// WDT registers. +#define TIMER_WDT4_CONFIG (0x100 + 0x80) +#define TIMER_SRC(TMR) ((TMR) & 0xF) +#define TIMER_PER(PER) (((PER) & 0xFF) << 4) +#define TIMER_IRQENABL_EN BIT(12) +#define TIMER_FIQENABL_EN BIT(13) +#define TIMER_SYSRESET_EN BIT(14) +#define TIMER_PMCRESET_EN BIT(15) +#define TIMER_WDT4_COMMAND (0x108 + 0x80) +#define TIMER_START_CNT BIT(0) +#define TIMER_CNT_DISABLE BIT(1) +#define TIMER_WDT4_UNLOCK_PATTERN (0x10C + 0x80) +#define TIMER_MAGIC_PTRN 0xC45A + +u32 get_tmr_us(); +u32 get_tmr_ms(); +u32 get_tmr_s(); +void usleep(u32 us); +void msleep(u32 ms); +#define ILOOP(is) ((is) / 3) +void isleep(u32 is); + +void timer_usleep(u32 us); + +void watchdog_start(u32 us, u32 mode); +void watchdog_end(); +void watchdog_handle(); +bool watchdog_fired(); + +#endif diff --git a/bdk/soc/uart.c b/bdk/soc/uart.c index 00ee1ad..228ac01 100644 --- a/bdk/soc/uart.c +++ b/bdk/soc/uart.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert -* Copyright (c) 2019-2020 CTCaer +* Copyright (c) 2019-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, @@ -17,45 +17,58 @@ #include #include +#include #include -#include /* UART A, B, C, D and E. */ static const u32 uart_baseoff[5] = { 0, 0x40, 0x200, 0x300, 0x400 }; -void uart_init(u32 idx, u32 baud) +void uart_init(u32 idx, u32 baud, u32 mode) { uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]); // Make sure no data is being sent. - uart_wait_idle(idx, UART_TX_IDLE); + if (!(mode & (UART_MCR_CTS_EN | UART_MCR_DTR))) + uart_wait_xfer(idx, UART_TX_IDLE); // Set clock. bool clk_type = clock_uart_use_src_div(idx, baud); + // 2 STOP bits for rates > 1M. (Reduced efficiency but less errors on high baudrates). + u32 uart_lcr_stop = baud > 1000000 ? UART_LCR_STOP : 0; + // Misc settings. u32 div = clk_type ? ((8 * baud + 408000000) / (16 * baud)) : 1; // DIV_ROUND_CLOSEST. uart->UART_IER_DLAB = 0; // Disable interrupts. - uart->UART_LCR = UART_LCR_DLAB | UART_LCR_WORD_LENGTH_8; // Enable DLAB & set 8n1 mode. - uart->UART_THR_DLAB = (u8)div; // Divisor latch LSB. + uart->UART_LCR = UART_LCR_DLAB | UART_LCR_WORD_LENGTH_8; // Enable DLAB & set 8n1 mode. + uart->UART_THR_DLAB = (u8)div; // Divisor latch LSB. uart->UART_IER_DLAB = (u8)(div >> 8); // Divisor latch MSB. - uart->UART_LCR = UART_LCR_WORD_LENGTH_8; // Disable DLAB. + + // Disable DLAB and set STOP bits setting if applicable. + uart->UART_LCR = uart_lcr_stop | UART_LCR_WORD_LENGTH_8; (void)uart->UART_SPR; - // Setup and flush fifo. + // Enable fifo. uart->UART_IIR_FCR = UART_IIR_FCR_EN_FIFO; (void)uart->UART_SPR; usleep(20); - uart->UART_MCR = 0; // Disable hardware flow control. + + // Disable hardware flow control. + uart->UART_MCR = 0; usleep(96); + + // Clear tx/rx fifos. uart->UART_IIR_FCR = UART_IIR_FCR_EN_FIFO | UART_IIR_FCR_TX_CLR | UART_IIR_FCR_RX_CLR; + // Set hardware flow control. + uart->UART_MCR = mode; + // Wait 3 symbols for baudrate change. usleep(3 * ((baud + 999999) / baud)); - uart_wait_idle(idx, UART_TX_IDLE | UART_RX_IDLE); + uart_wait_xfer(idx, UART_TX_IDLE | UART_RX_RDYR); } -void uart_wait_idle(u32 idx, u32 which) +void uart_wait_xfer(u32 idx, u32 which) { uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]); if (UART_TX_IDLE & which) @@ -63,10 +76,10 @@ void uart_wait_idle(u32 idx, u32 which) while (!(uart->UART_LSR & UART_LSR_TMTY)) ; } - if (UART_RX_IDLE & which) + if (UART_RX_RDYR & which) { while (uart->UART_LSR & UART_LSR_RDR) - ; + (void)uart->UART_THR_DLAB; } } @@ -85,26 +98,31 @@ void uart_send(u32 idx, const u8 *buf, u32 len) u32 uart_recv(u32 idx, u8 *buf, u32 len) { uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]); + bool manual_mode = uart->UART_MCR & UART_MCR_RTS; u32 timeout = get_tmr_us() + 250; u32 i; + if (manual_mode) + uart->UART_MCR &= ~UART_MCR_RTS; + for (i = 0; ; i++) { - while (!(uart->UART_LSR & UART_LSR_RDR)) - { - if (timeout < get_tmr_us()) - break; - if (len && len < i) - break; - } - if (timeout < get_tmr_us()) + if (len && len <= i) break; + while (!(uart->UART_LSR & UART_LSR_RDR)) + if (timeout < get_tmr_us()) + goto out; + buf[i] = uart->UART_THR_DLAB; timeout = get_tmr_us() + 250; } - return i ? (len ? (i - 1) : i) : 0; +out: + if (manual_mode) + uart->UART_MCR |= UART_MCR_RTS; + + return i; } void uart_invert(u32 idx, bool enable, u32 invert_mask) @@ -118,6 +136,14 @@ void uart_invert(u32 idx, bool enable, u32 invert_mask) (void)uart->UART_SPR; } +void uart_set_mode(u32 idx, u32 mode) +{ + uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]); + + uart->UART_MCR = mode; + (void)uart->UART_SPR; +} + u32 uart_get_IIR(u32 idx) { uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]); @@ -179,9 +205,11 @@ void uart_empty_fifo(u32 idx, u32 which) #include -void uart_print(const char *fmt, ...) +void uart_printf(const char *fmt, ...) { va_list ap; + + //! NOTE: Anything more and it will hang. Heap usage is out of the question. char text[256]; va_start(ap, fmt); diff --git a/bdk/soc/uart.h b/bdk/soc/uart.h index 103db13..c25973c 100644 --- a/bdk/soc/uart.h +++ b/bdk/soc/uart.h @@ -28,33 +28,33 @@ #define BAUD_115200 115200 -#define UART_TX_IDLE 0x1 -#define UART_RX_IDLE 0x2 +#define UART_TX_IDLE BIT(0) +#define UART_RX_RDYR BIT(1) -#define UART_TX_FIFO_FULL 0x100 -#define UART_RX_FIFO_EMPTY 0x200 +#define UART_TX_FIFO_FULL BIT(8) +#define UART_RX_FIFO_EMPTY BIT(9) -#define UART_INVERT_RXD 0x01 -#define UART_INVERT_TXD 0x02 -#define UART_INVERT_CTS 0x04 -#define UART_INVERT_RTS 0x08 +#define UART_INVERT_RXD BIT(0) +#define UART_INVERT_TXD BIT(1) +#define UART_INVERT_CTS BIT(2) +#define UART_INVERT_RTS BIT(3) -#define UART_IER_DLAB_IE_EORD 0x20 +#define UART_IER_DLAB_IE_EORD BIT(5) -#define UART_LCR_DLAB 0x80 -#define UART_LCR_STOP 0x4 #define UART_LCR_WORD_LENGTH_8 0x3 +#define UART_LCR_STOP BIT(2) +#define UART_LCR_DLAB BIT(7) -#define UART_LSR_RDR 0x1 -#define UART_LSR_THRE 0x20 -#define UART_LSR_TMTY 0x40 -#define UART_LSR_FIFOE 0x80 +#define UART_LSR_RDR BIT(0) +#define UART_LSR_THRE BIT(5) +#define UART_LSR_TMTY BIT(6) +#define UART_LSR_FIFOE BIT(7) -#define UART_IIR_FCR_TX_CLR 0x4 -#define UART_IIR_FCR_RX_CLR 0x2 -#define UART_IIR_FCR_EN_FIFO 0x1 +#define UART_IIR_FCR_EN_FIFO BIT(0) +#define UART_IIR_FCR_RX_CLR BIT(1) +#define UART_IIR_FCR_TX_CLR BIT(2) -#define UART_IIR_NO_INT BIT(0) +#define UART_IIR_NO_INT BIT(0) #define UART_IIR_INT_MASK 0xF /* Custom returned interrupt results. Actual interrupts are -1 */ #define UART_IIR_NOI 0 // No interrupt. @@ -65,8 +65,10 @@ #define UART_IIR_REDI 5 // Receiver end of data interrupt. #define UART_IIR_RDTI 7 // Receiver data timeout interrupt. -#define UART_MCR_RTS 0x2 -#define UART_MCR_DTR 0x1 +#define UART_MCR_DTR BIT(0) +#define UART_MCR_RTS BIT(1) +#define UART_MCR_CTS_EN BIT(5) +#define UART_MCR_RTS_EN BIT(6) typedef struct _uart_t { @@ -86,16 +88,29 @@ typedef struct _uart_t /* 0x3C */ vu32 UART_ASR; } uart_t; -void uart_init(u32 idx, u32 baud); -void uart_wait_idle(u32 idx, u32 which); +//! TODO: Commented out modes are not supported yet. +typedef enum _uart_mode_t +{ + UART_AO_TX_AO_RX = 0, + //UART_MN_TX_AO_RX = UART_MCR_RTS | UART_MCR_DTR, + UART_AO_TX_MN_RX = UART_MCR_RTS, // Up to 36 bytes read. + //UART_MN_TX_AO_RX = UART_MCR_DTR, + //UART_HW_TX_HW_RX = UART_MCR_RTS_EN | UART_MCR_CTS_EN, + UART_AO_TX_HW_RX = UART_MCR_RTS_EN, + //UART_HW_TX_AO_RX = UART_MCR_CTS_EN, +} uart_mode_t; + +void uart_init(u32 idx, u32 baud, u32 mode); +void uart_wait_xfer(u32 idx, u32 which); void uart_send(u32 idx, const u8 *buf, u32 len); u32 uart_recv(u32 idx, u8 *buf, u32 len); void uart_invert(u32 idx, bool enable, u32 invert_mask); +void uart_set_mode(u32 idx, u32 mode); u32 uart_get_IIR(u32 idx); void uart_set_IIR(u32 idx); void uart_empty_fifo(u32 idx, u32 which); #ifdef DEBUG_UART_PORT -void uart_print(const char *fmt, ...); +void uart_printf(const char *fmt, ...); #endif #endif diff --git a/bdk/storage/emmc.c b/bdk/storage/emmc.c index a344a94..5412fb5 100644 --- a/bdk/storage/emmc.c +++ b/bdk/storage/emmc.c @@ -61,6 +61,8 @@ u32 emmc_get_mode() return emmc_mode; } +void emmc_end() { sdmmc_storage_end(&emmc_storage); } + int emmc_init_retry(bool power_cycle) { u32 bus_width = SDMMC_BUS_WIDTH_8; @@ -70,7 +72,7 @@ int emmc_init_retry(bool power_cycle) if (power_cycle) { emmc_mode--; - sdmmc_storage_end(&emmc_storage); + emmc_end(); } // Get init parameters. @@ -105,7 +107,7 @@ bool emmc_initialize(bool power_cycle) emmc_mode = EMMC_MMC_HS400; if (power_cycle) - sdmmc_storage_end(&emmc_storage); + emmc_end(); int res = !emmc_init_retry(false); @@ -124,11 +126,13 @@ bool emmc_initialize(bool power_cycle) } } - sdmmc_storage_end(&emmc_storage); + emmc_end(); return false; } +int emmc_set_partition(u32 partition) { return sdmmc_storage_set_mmc_partition(&emmc_storage, partition); } + void emmc_gpt_parse(link_t *gpt) { gpt_t *gpt_buf = (gpt_t *)calloc(GPT_NUM_BLOCKS, EMMC_BLOCKSIZE); @@ -150,10 +154,10 @@ void emmc_gpt_parse(link_t *gpt) if (gpt_buf->entries[i].lba_start < gpt_buf->header.first_use_lba) continue; - part->index = i; + part->index = i; part->lba_start = gpt_buf->entries[i].lba_start; - part->lba_end = gpt_buf->entries[i].lba_end; - part->attrs = gpt_buf->entries[i].attrs; + part->lba_end = gpt_buf->entries[i].lba_end; + part->attrs = gpt_buf->entries[i].attrs; // ASCII conversion. Copy only the LSByte of the UTF-16LE name. for (u32 j = 0; j < 36; j++) diff --git a/bdk/storage/emmc.h b/bdk/storage/emmc.h index 840b960..f2010bf 100644 --- a/bdk/storage/emmc.h +++ b/bdk/storage/emmc.h @@ -30,18 +30,18 @@ enum { - EMMC_INIT_FAIL = 0, - EMMC_1BIT_HS52 = 1, - EMMC_8BIT_HS52 = 2, - EMMC_MMC_HS200 = 3, - EMMC_MMC_HS400 = 4, + EMMC_INIT_FAIL = 0, + EMMC_1BIT_HS52 = 1, + EMMC_8BIT_HS52 = 2, + EMMC_MMC_HS200 = 3, + EMMC_MMC_HS400 = 4, }; enum { - EMMC_ERROR_INIT_FAIL = 0, - EMMC_ERROR_RW_FAIL = 1, - EMMC_ERROR_RW_RETRY = 2 + EMMC_ERROR_INIT_FAIL = 0, + EMMC_ERROR_RW_FAIL = 1, + EMMC_ERROR_RW_RETRY = 2 }; typedef struct _emmc_part_t @@ -63,6 +63,8 @@ u16 *emmc_get_error_count(); u32 emmc_get_mode(); int emmc_init_retry(bool power_cycle); bool emmc_initialize(bool power_cycle); +int emmc_set_partition(u32 partition); +void emmc_end(); void emmc_gpt_parse(link_t *gpt); void emmc_gpt_free(link_t *gpt); diff --git a/bdk/storage/mbr_gpt.h b/bdk/storage/mbr_gpt.h index 9e0e97d..7f38108 100644 --- a/bdk/storage/mbr_gpt.h +++ b/bdk/storage/mbr_gpt.h @@ -39,40 +39,40 @@ typedef struct _mbr_part_t typedef struct _mbr_t { - u8 bootstrap[440]; - u32 signature; - u16 copy_protected; - mbr_part_t partitions[4]; - u16 boot_signature; +/* 0x000 */ u8 bootstrap[440]; +/* 0x1B8 */ u32 signature; +/* 0x1BC */ u16 copy_protected; +/* 0x1BE */ mbr_part_t partitions[4]; +/* 0x1FE */ u16 boot_signature; } __attribute__((packed)) mbr_t; typedef struct _gpt_entry_t { - u8 type_guid[0x10]; - u8 part_guid[0x10]; - u64 lba_start; - u64 lba_end; - u64 attrs; - u16 name[36]; +/* 0x00 */ u8 type_guid[0x10]; +/* 0x10 */ u8 part_guid[0x10]; +/* 0x20 */ u64 lba_start; +/* 0x28 */ u64 lba_end; +/* 0x30 */ u64 attrs; +/* 0x38 */ u16 name[36]; } gpt_entry_t; typedef struct _gpt_header_t { - u64 signature; // "EFI PART" - u32 revision; - u32 size; - u32 crc32; - u32 res1; - u64 my_lba; - u64 alt_lba; - u64 first_use_lba; - u64 last_use_lba; - u8 disk_guid[0x10]; - u64 part_ent_lba; - u32 num_part_ents; - u32 part_ent_size; - u32 part_ents_crc32; - u8 res2[420]; // Used as first 3 partition entries backup for HOS. +/* 0x00 */ u64 signature; // "EFI PART" +/* 0x08 */ u32 revision; +/* 0x0C */ u32 size; +/* 0x10 */ u32 crc32; +/* 0x14 */ u32 res1; +/* 0x18 */ u64 my_lba; +/* 0x20 */ u64 alt_lba; +/* 0x28 */ u64 first_use_lba; +/* 0x30 */ u64 last_use_lba; +/* 0x38 */ u8 disk_guid[0x10]; +/* 0x48 */ u64 part_ent_lba; +/* 0x50 */ u32 num_part_ents; +/* 0x54 */ u32 part_ent_size; +/* 0x58 */ u32 part_ents_crc32; +/* 0x5C */ u8 res2[420]; // Used as first 3 partition entries backup for HOS. } gpt_header_t; typedef struct _gpt_t diff --git a/bdk/storage/mmc.h b/bdk/storage/mmc.h index ee81e69..c7d6106 100644 --- a/bdk/storage/mmc.h +++ b/bdk/storage/mmc.h @@ -408,7 +408,10 @@ /* * BKOPS status level */ -#define EXT_CSD_BKOPS_LEVEL_2 0x2 +#define EXT_CSD_BKOPS_OK 0x0 +#define EXT_CSD_BKOPS_NON_CRITICAL 0x1 +#define EXT_CSD_BKOPS_PERF_IMPACTED 0x2 +#define EXT_CSD_BKOPS_CRITICAL 0x3 /* * BKOPS modes diff --git a/bdk/storage/nx_emmc_bis.c b/bdk/storage/nx_emmc_bis.c index 4bcbc47..28bdc6f 100644 --- a/bdk/storage/nx_emmc_bis.c +++ b/bdk/storage/nx_emmc_bis.c @@ -251,7 +251,12 @@ int nx_emmc_bis_read(u32 sector, u32 count, void *buff) while (count) { - u32 sct_cnt = MIN(count, BIS_CLUSTER_SECTORS); + // Get sector index in cluster and use it as boundary check. + u32 cnt_max = (curr_sct % BIS_CLUSTER_SECTORS); + cnt_max = BIS_CLUSTER_SECTORS - cnt_max; + + u32 sct_cnt = MIN(count, cnt_max); // Only allow cluster sized access. + if (nx_emmc_bis_read_block(curr_sct, sct_cnt, buf)) return 0; @@ -270,7 +275,12 @@ int nx_emmc_bis_write(u32 sector, u32 count, void *buff) while (count) { - u32 sct_cnt = MIN(count, BIS_CLUSTER_SECTORS); + // Get sector index in cluster and use it as boundary check. + u32 cnt_max = (curr_sct % BIS_CLUSTER_SECTORS); + cnt_max = BIS_CLUSTER_SECTORS - cnt_max; + + u32 sct_cnt = MIN(count, cnt_max); // Only allow cluster sized access. + if (nx_emmc_bis_write_block(curr_sct, sct_cnt, buf, false)) return 0; diff --git a/bdk/storage/nx_emmc_bis.h b/bdk/storage/nx_emmc_bis.h index 8b07008..7cdacfc 100644 --- a/bdk/storage/nx_emmc_bis.h +++ b/bdk/storage/nx_emmc_bis.h @@ -85,13 +85,13 @@ typedef struct _nx_emmc_cal0_t u8 bd_mac[6]; u8 crc16_pad4[2]; u8 rsvd2[8]; - u8 acc_offset[6]; + u16 acc_offset[3]; u8 crc16_pad5[2]; - u8 acc_scale[6]; + u16 acc_scale[3]; u8 crc16_pad6[2]; - u8 gyro_offset[6]; + u16 gyro_offset[3]; u8 crc16_pad7[2]; - u8 gyro_scale[6]; + u16 gyro_scale[3]; u8 crc16_pad8[2]; char serial_number[0x18]; u8 crc16_pad9[8]; @@ -213,11 +213,15 @@ typedef struct _nx_emmc_cal0_t // 6.0.0 and up. u8 battery_ver; - u8 crc16_pad58[0x1F]; + u8 crc16_pad58[0xF]; + + // 10.0.0 and up. + u8 touch_ic_vendor_id; + u8 crc16_pad59[0xF]; // 9.0.0 and up. - u32 home_menu_scheme_model; - u8 crc16_pad59[0xC]; + u32 color_model; + u8 crc16_pad60[0xC]; // 10.0.0 and up. u8 console_6axis_sensor_mount_type; diff --git a/bdk/storage/sd.c b/bdk/storage/sd.c index ccc9f49..efbeef6 100644 --- a/bdk/storage/sd.c +++ b/bdk/storage/sd.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2022 CTCaer + * Copyright (c) 2018-2023 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -22,10 +22,18 @@ #include #include +#ifndef BDK_SDMMC_UHS_DDR200_SUPPORT +#define SD_DEFAULT_SPEED SD_UHS_SDR104 +#else +#define SD_DEFAULT_SPEED SD_UHS_DDR208 +#endif + static bool sd_mounted = false; static bool sd_init_done = false; +static bool insertion_event = false; static u16 sd_errors[3] = { 0 }; // Init and Read/Write errors. -static u32 sd_mode = SD_UHS_SDR104; +static u32 sd_mode = SD_DEFAULT_SPEED; + sdmmc_t sd_sdmmc; sdmmc_storage_t sd_storage; @@ -54,7 +62,7 @@ u16 *sd_get_error_count() bool sd_get_card_removed() { - if (sd_init_done && !sdmmc_get_sd_inserted()) + if (insertion_event && !sdmmc_get_sd_inserted()) return true; return false; @@ -78,7 +86,11 @@ u32 sd_get_mode() int sd_init_retry(bool power_cycle) { u32 bus_width = SDMMC_BUS_WIDTH_4; +#ifndef BDK_SDMMC_UHS_DDR200_SUPPORT u32 type = SDHCI_TIMING_UHS_SDR104; +#else + u32 type = SDHCI_TIMING_UHS_DDR200; +#endif // Power cycle SD card. if (power_cycle) @@ -92,24 +104,45 @@ int sd_init_retry(bool power_cycle) { case SD_INIT_FAIL: // Reset to max. return 0; + case SD_1BIT_HS25: bus_width = SDMMC_BUS_WIDTH_1; type = SDHCI_TIMING_SD_HS25; break; + case SD_4BIT_HS25: type = SDHCI_TIMING_SD_HS25; break; + case SD_UHS_SDR82: type = SDHCI_TIMING_UHS_SDR82; break; + case SD_UHS_SDR104: type = SDHCI_TIMING_UHS_SDR104; break; + +#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT + case SD_UHS_DDR208: + type = SDHCI_TIMING_UHS_DDR200; + break; +#endif + default: - sd_mode = SD_UHS_SDR104; + sd_mode = SD_DEFAULT_SPEED; + break; } - return sdmmc_storage_init_sd(&sd_storage, &sd_sdmmc, bus_width, type); + int res = sdmmc_storage_init_sd(&sd_storage, &sd_sdmmc, bus_width, type); + if (res) + { + sd_init_done = true; + insertion_event = true; + } + else + sd_init_done = false; + + return res; } bool sd_initialize(bool power_cycle) @@ -125,7 +158,7 @@ bool sd_initialize(bool power_cycle) return true; else if (!sdmmc_get_sd_inserted()) // SD Card is not inserted. { - sd_mode = SD_UHS_SDR104; + sd_mode = SD_DEFAULT_SPEED; break; } else @@ -146,7 +179,7 @@ bool sd_initialize(bool power_cycle) bool sd_mount() { - if (sd_mounted) + if (sd_init_done && sd_mounted) return true; int res = 0; @@ -165,8 +198,8 @@ bool sd_mount() } else { - sd_init_done = true; - res = f_mount(&sd_fs, "0:", 1); // Volume 0 is SD. + if (!sd_mounted) + res = f_mount(&sd_fs, "0:", 1); // Volume 0 is SD. if (res == FR_OK) { sd_mounted = true; @@ -184,19 +217,25 @@ bool sd_mount() static void _sd_deinit(bool deinit) { - if (deinit && sd_mode == SD_INIT_FAIL) - sd_mode = SD_UHS_SDR104; + if (deinit) + { + insertion_event = false; + if (sd_mode == SD_INIT_FAIL) + sd_mode = SD_DEFAULT_SPEED; + } - if (sd_init_done && sd_mounted) + if (sd_init_done) { - f_mount(NULL, "0:", 1); // Volume 0 is SD. - sd_mounted = false; - } - if (sd_init_done && deinit) - { - sdmmc_storage_end(&sd_storage); - sd_init_done = false; + if (sd_mounted) + f_mount(NULL, "0:", 1); // Volume 0 is SD. + + if (deinit) + { + sdmmc_storage_end(&sd_storage); + sd_init_done = false; + } } + sd_mounted = false; } void sd_unmount() { _sd_deinit(false); } @@ -210,6 +249,9 @@ bool sd_is_gpt() void *sd_file_read(const char *path, u32 *fsize) { FIL fp; + if (!sd_get_card_mounted()) + return NULL; + if (f_open(&fp, path, FA_READ) != FR_OK) return NULL; @@ -237,6 +279,9 @@ int sd_save_to_file(void *buf, u32 size, const char *filename) { FIL fp; u32 res = 0; + if (!sd_get_card_mounted()) + return FR_DISK_ERR; + res = f_open(&fp, filename, FA_CREATE_ALWAYS | FA_WRITE); if (res) { diff --git a/bdk/storage/sd.h b/bdk/storage/sd.h index 19eb6d5..7c6170b 100644 --- a/bdk/storage/sd.h +++ b/bdk/storage/sd.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2021 CTCaer + * Copyright (c) 2018-2023 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -22,13 +22,19 @@ #include #include +#define SD_BLOCKSIZE 512 + enum { SD_INIT_FAIL = 0, SD_1BIT_HS25 = 1, SD_4BIT_HS25 = 2, SD_UHS_SDR82 = 3, - SD_UHS_SDR104 = 4 + SD_UHS_SDR104 = 4, +#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT + SD_UHS_DDR208 = 5 +#endif + }; enum diff --git a/bdk/storage/sd_def.h b/bdk/storage/sd_def.h index 9d030f5..1316b50 100644 --- a/bdk/storage/sd_def.h +++ b/bdk/storage/sd_def.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2005-2007 Pierre Ossman, All Rights Reserved. - * Copyright (c) 2018-2021 CTCaer + * Copyright (c) 2018-2023 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 @@ -45,15 +45,14 @@ #define SD_APP_CHANGE_SECURE_AREA 49 /* adtc R1b */ /* OCR bit definitions */ -#define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */ -#define SD_VHD_27_36 (1 << 8) /* VDD voltage 2.7 ~ 3.6 */ -#define SD_OCR_VDD_27_34 (0x7F << 15) /* VDD voltage 2.7 ~ 3.4 */ -#define SD_OCR_VDD_32_33 (1 << 20) /* VDD voltage 3.2 ~ 3.3 */ -#define SD_OCR_S18R (1 << 24) /* 1.8V switching request */ -#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */ -#define SD_OCR_XPC (1 << 28) /* SDXC power control */ -#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */ -#define SD_OCR_BUSY (1 << 31) /* Card Power up Status */ +#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_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 */ +#define SD_OCR_XPC (1U << 28) /* SDXC power control */ +#define SD_OCR_CCS (1U << 30) /* Card Capacity Status */ +#define SD_OCR_BUSY (1U << 31) /* Card Power up Status */ /* * SD_SWITCH argument format: @@ -90,8 +89,8 @@ #define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */ #define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */ #define SCR_SPEC_VER_2 2 /* Implements system specification 2.00-3.0X */ -#define SD_SCR_BUS_WIDTH_1 (1<<0) -#define SD_SCR_BUS_WIDTH_4 (1<<2) +#define SD_SCR_BUS_WIDTH_1 (1U << 0) +#define SD_SCR_BUS_WIDTH_4 (1U << 2) /* * SD bus widths @@ -102,33 +101,55 @@ /* * SD bus speeds */ -#define UHS_SDR12_BUS_SPEED 0 +#define UHS_SDR12_BUS_SPEED 0 #define HIGH_SPEED_BUS_SPEED 1 -#define UHS_SDR25_BUS_SPEED 1 -#define UHS_SDR50_BUS_SPEED 2 +#define UHS_SDR25_BUS_SPEED 1 +#define UHS_SDR50_BUS_SPEED 2 #define UHS_SDR104_BUS_SPEED 3 -#define UHS_DDR50_BUS_SPEED 4 -#define HS400_BUS_SPEED 5 +#define UHS_DDR50_BUS_SPEED 4 +#define HS400_BUS_SPEED 5 -#define SD_MODE_HIGH_SPEED (1 << HIGH_SPEED_BUS_SPEED) -#define SD_MODE_UHS_SDR12 (1 << UHS_SDR12_BUS_SPEED) -#define SD_MODE_UHS_SDR25 (1 << UHS_SDR25_BUS_SPEED) -#define SD_MODE_UHS_SDR50 (1 << UHS_SDR50_BUS_SPEED) -#define SD_MODE_UHS_SDR104 (1 << UHS_SDR104_BUS_SPEED) -#define SD_MODE_UHS_DDR50 (1 << UHS_DDR50_BUS_SPEED) +#define SD_MODE_HIGH_SPEED (1U << HIGH_SPEED_BUS_SPEED) +#define SD_MODE_UHS_SDR12 (1U << UHS_SDR12_BUS_SPEED) +#define SD_MODE_UHS_SDR25 (1U << UHS_SDR25_BUS_SPEED) +#define SD_MODE_UHS_SDR50 (1U << UHS_SDR50_BUS_SPEED) +#define SD_MODE_UHS_SDR104 (1U << UHS_SDR104_BUS_SPEED) +#define SD_MODE_UHS_DDR50 (1U << UHS_DDR50_BUS_SPEED) -#define SD_DRIVER_TYPE_B 0x01 -#define SD_DRIVER_TYPE_A 0x02 -#define SD_SET_CURRENT_LIMIT_200 0 -#define SD_SET_CURRENT_LIMIT_400 1 -#define SD_SET_CURRENT_LIMIT_600 2 -#define SD_SET_CURRENT_LIMIT_800 3 +#define SD_SET_DRIVER_TYPE_B 0 +#define SD_SET_DRIVER_TYPE_A 1 +#define SD_SET_DRIVER_TYPE_C 2 +#define SD_SET_DRIVER_TYPE_D 3 -#define SD_MAX_CURRENT_200 (1 << SD_SET_CURRENT_LIMIT_200) -#define SD_MAX_CURRENT_400 (1 << SD_SET_CURRENT_LIMIT_400) -#define SD_MAX_CURRENT_600 (1 << SD_SET_CURRENT_LIMIT_600) -#define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800) +#define SD_DRIVER_TYPE_B (1U << SD_SET_DRIVER_TYPE_B) +#define SD_DRIVER_TYPE_A (1U << SD_SET_DRIVER_TYPE_A) +#define SD_DRIVER_TYPE_C (1U << SD_SET_DRIVER_TYPE_C) +#define SD_DRIVER_TYPE_D (1U << SD_SET_DRIVER_TYPE_D) + +#define SD_SET_POWER_LIMIT_0_72 0 +#define SD_SET_POWER_LIMIT_1_44 1 +#define SD_SET_POWER_LIMIT_2_16 2 +#define SD_SET_POWER_LIMIT_2_88 3 + +#define SD_MAX_POWER_0_72 (1U << SD_SET_POWER_LIMIT_0_72) +#define SD_MAX_POWER_1_44 (1U << SD_SET_POWER_LIMIT_1_44) +#define SD_MAX_POWER_2_16 (1U << SD_SET_POWER_LIMIT_2_16) +#define SD_MAX_POWER_2_88 (1U << SD_SET_POWER_LIMIT_2_88) + +#define SD_SET_CMD_SYSTEM_DEF 0 +#define SD_SET_CMD_SYSTEM_MEC 1 +#define SD_SET_CMD_SYSTEM_OTP 3 +#define SD_SET_CMD_SYSTEM_OSD 3 +#define SD_SET_CMD_SYSTEM_VND 14 +#define UHS_DDR200_BUS_SPEED SD_SET_CMD_SYSTEM_VND + +#define SD_CMD_SYSTEM_DEF (1U << SD_SET_CMD_SYSTEM_DEF) +#define SD_CMD_SYSTEM_MEC (1U << SD_SET_CMD_SYSTEM_MEC) +#define SD_CMD_SYSTEM_OTP (1U << SD_SET_CMD_SYSTEM_OTP) +#define SD_CMD_SYSTEM_OSD (1U << SD_SET_CMD_SYSTEM_OSD) +#define SD_CMD_SYSTEM_VND (1U << SD_SET_CMD_SYSTEM_VND) +#define SD_MODE_UHS_DDR200 SD_CMD_SYSTEM_VND /* * SD_SWITCH mode @@ -140,11 +161,14 @@ * SD_SWITCH function groups */ #define SD_SWITCH_GRP_ACCESS 0 +#define SD_SWITCH_GRP_CMDSYS 1 +#define SD_SWITCH_GRP_DRVSTR 2 +#define SD_SWITCH_GRP_PWRLIM 3 /* * SD_SWITCH access modes */ #define SD_SWITCH_ACCESS_DEF 0 -#define SD_SWITCH_ACCESS_HS 1 +#define SD_SWITCH_ACCESS_HS 1 #endif /* SD_DEF_H */ diff --git a/bdk/storage/sdmmc.c b/bdk/storage/sdmmc.c index 8980d61..965fd73 100644 --- a/bdk/storage/sdmmc.c +++ b/bdk/storage/sdmmc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2022 CTCaer + * Copyright (c) 2018-2023 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -16,6 +16,9 @@ */ #include + +#include +#include #include #include #include @@ -23,9 +26,8 @@ #include #include #include -#include -#include +//#define SDMMC_DEBUG_PRINT_SD_REGS //#define DPRINTF(...) gfx_printf(__VA_ARGS__) #define DPRINTF(...) @@ -34,8 +36,9 @@ u32 sd_power_cycle_time_start; static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size) { const u32 mask = (size < 32 ? 1 << size : 0) - 1; - const u32 off = 3 - ((start) / 32); + const u32 off = 3 - ((start) / 32); const u32 shft = (start) & 31; + u32 res = resp[off] >> shft; if (size + shft > 32) res |= resp[off - 1] << ((32 - shft) % 32); @@ -152,12 +155,16 @@ int sdmmc_storage_execute_vendor_cmd(sdmmc_storage_t *storage, u32 arg) resp = -1; u32 timeout = get_tmr_ms() + 1500; - while (resp != (R1_READY_FOR_DATA | R1_STATE(R1_STATE_TRAN))) + while (true) { _sdmmc_storage_get_status(storage, &resp, 0); + if (resp == (R1_READY_FOR_DATA | R1_STATE(R1_STATE_TRAN))) + break; + if (get_tmr_ms() > timeout) break; + msleep(10); } return _sdmmc_storage_check_card_status(resp); @@ -175,11 +182,11 @@ int sdmmc_storage_vendor_sandisk_report(sdmmc_storage_t *storage, void *buf) sdmmc_init_cmd(&cmdbuf, MMC_VENDOR_63_CMD, 0, SDMMC_RSP_TYPE_1, 0); // similar to CMD17 with arg 0x0. - reqbuf.buf = buf; - reqbuf.num_sectors = 1; - reqbuf.blksize = 512; - reqbuf.is_write = 0; - reqbuf.is_multi_block = 0; + reqbuf.buf = buf; + reqbuf.num_sectors = 1; + reqbuf.blksize = 512; + reqbuf.is_write = 0; + reqbuf.is_multi_block = 0; reqbuf.is_auto_stop_trn = 0; u32 blkcnt_out; @@ -206,11 +213,11 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out sdmmc_init_cmd(&cmdbuf, is_write ? MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK, sector, SDMMC_RSP_TYPE_1, 0); - reqbuf.buf = buf; - reqbuf.num_sectors = num_sectors; - reqbuf.blksize = 512; - reqbuf.is_write = is_write; - reqbuf.is_multi_block = 1; + reqbuf.buf = buf; + reqbuf.num_sectors = num_sectors; + reqbuf.blksize = 512; + reqbuf.is_write = is_write; + reqbuf.is_multi_block = 1; reqbuf.is_auto_stop_trn = 1; if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, blkcnt_out)) @@ -327,8 +334,8 @@ out: int sdmmc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf) { - // Ensure that buffer resides in DRAM and it's DMA aligned. - if (((u32)buf >= DRAM_START) && !((u32)buf % 8)) + // Ensure that SDMMC has access to buffer and it's SDMMC DMA aligned. + if (mc_client_has_access(buf) && !((u32)buf % 8)) return _sdmmc_storage_readwrite(storage, sector, num_sectors, buf, 0); if (num_sectors > (SDMMC_UP_BUF_SZ / 512)) @@ -345,8 +352,8 @@ int sdmmc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, vo int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf) { - // Ensure that buffer resides in DRAM and it's DMA aligned. - if (((u32)buf >= DRAM_START) && !((u32)buf % 8)) + // Ensure that SDMMC has access to buffer and it's SDMMC DMA aligned. + if (mc_client_has_access(buf) && !((u32)buf % 8)) return _sdmmc_storage_readwrite(storage, sector, num_sectors, buf, 1); if (num_sectors > (SDMMC_UP_BUF_SZ / 512)) @@ -429,19 +436,19 @@ static void _mmc_storage_parse_cid(sdmmc_storage_t *storage) case 0: /* MMC v1.0 - v1.2 */ case 1: /* MMC v1.4 */ storage->cid.prod_name[6] = unstuff_bits(raw_cid, 48, 8); - storage->cid.manfid = unstuff_bits(raw_cid, 104, 24); - storage->cid.hwrev = unstuff_bits(raw_cid, 44, 4); - storage->cid.fwrev = unstuff_bits(raw_cid, 40, 4); - storage->cid.serial = unstuff_bits(raw_cid, 16, 24); + storage->cid.manfid = unstuff_bits(raw_cid, 104, 24); + storage->cid.hwrev = unstuff_bits(raw_cid, 44, 4); + storage->cid.fwrev = unstuff_bits(raw_cid, 40, 4); + storage->cid.serial = unstuff_bits(raw_cid, 16, 24); break; case 2: /* MMC v2.0 - v2.2 */ case 3: /* MMC v3.1 - v3.3 */ case 4: /* MMC v4 */ - storage->cid.manfid = unstuff_bits(raw_cid, 120, 8); - storage->cid.oemid = unstuff_bits(raw_cid, 104, 8); - storage->cid.prv = unstuff_bits(raw_cid, 48, 8); - storage->cid.serial = unstuff_bits(raw_cid, 16, 32); + storage->cid.manfid = unstuff_bits(raw_cid, 120, 8); + storage->cid.oemid = unstuff_bits(raw_cid, 104, 8); + storage->cid.prv = unstuff_bits(raw_cid, 48, 8); + storage->cid.serial = unstuff_bits(raw_cid, 16, 32); break; default: @@ -478,35 +485,34 @@ static void _mmc_storage_parse_csd(sdmmc_storage_t *storage) static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf) { - storage->ext_csd.rev = buf[EXT_CSD_REV]; - storage->ext_csd.ext_struct = buf[EXT_CSD_STRUCTURE]; - storage->ext_csd.card_type = buf[EXT_CSD_CARD_TYPE]; - storage->ext_csd.dev_version = *(u16 *)&buf[EXT_CSD_DEVICE_VERSION]; - storage->ext_csd.boot_mult = buf[EXT_CSD_BOOT_MULT]; - storage->ext_csd.rpmb_mult = buf[EXT_CSD_RPMB_MULT]; - //storage->ext_csd.bkops = buf[EXT_CSD_BKOPS_SUPPORT]; - //storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN]; + storage->ext_csd.rev = buf[EXT_CSD_REV]; + storage->ext_csd.ext_struct = buf[EXT_CSD_STRUCTURE]; + storage->ext_csd.card_type = buf[EXT_CSD_CARD_TYPE]; + storage->ext_csd.dev_version = *(u16 *)&buf[EXT_CSD_DEVICE_VERSION]; + storage->ext_csd.boot_mult = buf[EXT_CSD_BOOT_MULT]; + storage->ext_csd.rpmb_mult = buf[EXT_CSD_RPMB_MULT]; + //storage->ext_csd.bkops = buf[EXT_CSD_BKOPS_SUPPORT]; + //storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN]; //storage->ext_csd.bkops_status = buf[EXT_CSD_BKOPS_STATUS]; - storage->ext_csd.pre_eol_info = buf[EXT_CSD_PRE_EOL_INFO]; + storage->ext_csd.pre_eol_info = buf[EXT_CSD_PRE_EOL_INFO]; storage->ext_csd.dev_life_est_a = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A]; storage->ext_csd.dev_life_est_b = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B]; - storage->ext_csd.cache_size = - buf[EXT_CSD_CACHE_SIZE] | - (buf[EXT_CSD_CACHE_SIZE + 1] << 8) | - (buf[EXT_CSD_CACHE_SIZE + 2] << 16) | - (buf[EXT_CSD_CACHE_SIZE + 3] << 24); - storage->ext_csd.max_enh_mult = - (buf[EXT_CSD_MAX_ENH_SIZE_MULT] | - (buf[EXT_CSD_MAX_ENH_SIZE_MULT + 1] << 8) | - (buf[EXT_CSD_MAX_ENH_SIZE_MULT + 2] << 16)) * - buf[EXT_CSD_HC_WP_GRP_SIZE] * buf[EXT_CSD_HC_ERASE_GRP_SIZE]; + storage->ext_csd.cache_size = buf[EXT_CSD_CACHE_SIZE] | + (buf[EXT_CSD_CACHE_SIZE + 1] << 8) | + (buf[EXT_CSD_CACHE_SIZE + 2] << 16) | + (buf[EXT_CSD_CACHE_SIZE + 3] << 24); + + storage->ext_csd.max_enh_mult = (buf[EXT_CSD_MAX_ENH_SIZE_MULT] | + (buf[EXT_CSD_MAX_ENH_SIZE_MULT + 1] << 8) | + (buf[EXT_CSD_MAX_ENH_SIZE_MULT + 2] << 16)) * + buf[EXT_CSD_HC_WP_GRP_SIZE] * buf[EXT_CSD_HC_ERASE_GRP_SIZE]; storage->sec_cnt = *(u32 *)&buf[EXT_CSD_SEC_CNT]; } -static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf) +int mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf) { sdmmc_cmd_t cmdbuf; sdmmc_init_cmd(&cmdbuf, MMC_SEND_EXT_CSD, 0, SDMMC_RSP_TYPE_1, 0); @@ -562,21 +568,21 @@ static int _mmc_storage_switch_buswidth(sdmmc_storage_t *storage, u32 bus_width) return 0; } -static int _mmc_storage_enable_HS(sdmmc_storage_t *storage, int check) +static int _mmc_storage_enable_HS(sdmmc_storage_t *storage, bool check_sts_before_clk_setup) { if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS))) return 0; - if (check && !_sdmmc_storage_check_status(storage)) + if (check_sts_before_clk_setup && !_sdmmc_storage_check_status(storage)) return 0; if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_MMC_HS52)) return 0; -DPRINTF("[MMC] switched to HS\n"); + DPRINTF("[MMC] switched to HS52\n"); storage->csd.busspeed = 52; - if (check || _sdmmc_storage_check_status(storage)) + if (check_sts_before_clk_setup || _sdmmc_storage_check_status(storage)) return 1; return 0; @@ -593,7 +599,7 @@ static int _mmc_storage_enable_HS200(sdmmc_storage_t *storage) if (!sdmmc_tuning_execute(storage->sdmmc, SDHCI_TIMING_MMC_HS200, MMC_SEND_TUNING_BLOCK_HS200)) return 0; -DPRINTF("[MMC] switched to HS200\n"); + DPRINTF("[MMC] switched to HS200\n"); storage->csd.busspeed = 200; return _sdmmc_storage_check_status(storage); @@ -606,7 +612,7 @@ static int _mmc_storage_enable_HS400(sdmmc_storage_t *storage) sdmmc_save_tap_value(storage->sdmmc); - if (!_mmc_storage_enable_HS(storage, 0)) + if (!_mmc_storage_enable_HS(storage, false)) return 0; if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_BUS_WIDTH, EXT_CSD_DDR_BUS_WIDTH_8))) @@ -618,7 +624,7 @@ static int _mmc_storage_enable_HS400(sdmmc_storage_t *storage) if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_MMC_HS400)) return 0; -DPRINTF("[MMC] switched to HS400\n"); + DPRINTF("[MMC] switched to HS400\n"); storage->csd.busspeed = 400; return _sdmmc_storage_check_status(storage); @@ -627,27 +633,29 @@ DPRINTF("[MMC] switched to HS400\n"); static int _mmc_storage_enable_highspeed(sdmmc_storage_t *storage, u32 card_type, u32 type) { if (sdmmc_get_io_power(storage->sdmmc) != SDMMC_POWER_1_8) - goto out; + goto hs52_mode; + // HS400 needs 8-bit bus width mode. if (sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_8 && card_type & EXT_CSD_CARD_TYPE_HS400_1_8V && type == SDHCI_TIMING_MMC_HS400) return _mmc_storage_enable_HS400(storage); - if (sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_8 || - (sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_4 - && card_type & EXT_CSD_CARD_TYPE_HS200_1_8V - && (type == SDHCI_TIMING_MMC_HS400 || type == SDHCI_TIMING_MMC_HS200))) + // Try HS200 if HS400 and 4-bit width bus or just HS200. + if ((sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_8 || + sdmmc_get_bus_width(storage->sdmmc) == SDMMC_BUS_WIDTH_4) && + card_type & EXT_CSD_CARD_TYPE_HS200_1_8V && + (type == SDHCI_TIMING_MMC_HS400 || type == SDHCI_TIMING_MMC_HS200)) return _mmc_storage_enable_HS200(storage); -out: +hs52_mode: if (card_type & EXT_CSD_CARD_TYPE_HS_52) - return _mmc_storage_enable_HS(storage, 1); + return _mmc_storage_enable_HS(storage, true); return 1; } /* -static int _mmc_storage_enable_bkops(sdmmc_storage_t *storage) +static int _mmc_storage_enable_auto_bkops(sdmmc_storage_t *storage) { if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_AUTO_BKOPS_MASK))) return 0; @@ -662,74 +670,77 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_wid storage->sdmmc = sdmmc; storage->rca = 2; // Set default device address. This could be a config item. - if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_MMC_ID, SDMMC_POWER_SAVE_DISABLE)) - return 0; -DPRINTF("[MMC] after init\n"); + DPRINTF("[MMC]-[init: bus: %d, type: %d]\n", bus_width, type); - usleep(1000 + (74000 + sdmmc->divisor - 1) / sdmmc->divisor); + if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_MMC_ID)) + return 0; + DPRINTF("[MMC] after init\n"); + + // Wait 1ms + 74 cycles. + usleep(1000 + (74 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock); if (!_sdmmc_storage_go_idle_state(storage)) return 0; -DPRINTF("[MMC] went to idle state\n"); + DPRINTF("[MMC] went to idle state\n"); if (!_mmc_storage_get_op_cond(storage, SDMMC_POWER_1_8)) return 0; -DPRINTF("[MMC] got op cond\n"); + DPRINTF("[MMC] got op cond\n"); if (!_sdmmc_storage_get_cid(storage)) return 0; -DPRINTF("[MMC] got cid\n"); + DPRINTF("[MMC] got cid\n"); if (!_mmc_storage_set_relative_addr(storage)) return 0; -DPRINTF("[MMC] set relative addr\n"); + DPRINTF("[MMC] set relative addr\n"); if (!_sdmmc_storage_get_csd(storage)) return 0; -DPRINTF("[MMC] got csd\n"); + DPRINTF("[MMC] got csd\n"); _mmc_storage_parse_csd(storage); if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_MMC_LS26)) return 0; -DPRINTF("[MMC] after setup clock\n"); + DPRINTF("[MMC] after setup clock\n"); if (!_sdmmc_storage_select_card(storage)) return 0; -DPRINTF("[MMC] card selected\n"); + DPRINTF("[MMC] card selected\n"); if (!_sdmmc_storage_set_blocklen(storage, 512)) return 0; -DPRINTF("[MMC] set blocklen to 512\n"); + DPRINTF("[MMC] set blocklen to 512\n"); // Check system specification version, only version 4.0 and later support below features. if (storage->csd.mmca_vsn < CSD_SPEC_VER_4) - return 1; + goto done; if (!_mmc_storage_switch_buswidth(storage, bus_width)) return 0; -DPRINTF("[MMC] switched buswidth\n"); + DPRINTF("[MMC] switched buswidth\n"); - if (!_mmc_storage_get_ext_csd(storage, (u8 *)SDMMC_UPPER_BUFFER)) + if (!mmc_storage_get_ext_csd(storage, (u8 *)SDMMC_UPPER_BUFFER)) return 0; -DPRINTF("[MMC] got ext_csd\n"); + DPRINTF("[MMC] got ext_csd\n"); _mmc_storage_parse_cid(storage); // This needs to be after csd and ext_csd. - //gfx_hexdump(0, ext_csd, 512); /* if (storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_AUTO_BKOPS_MASK)) { - _mmc_storage_enable_bkops(storage); -DPRINTF("[MMC] BKOPS enabled\n"); + _mmc_storage_enable_auto_bkops(storage); + DPRINTF("[MMC] BKOPS enabled\n"); } */ if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type)) return 0; -DPRINTF("[MMC] successfully switched to HS mode\n"); + DPRINTF("[MMC] successfully switched to HS mode\n"); sdmmc_card_clock_powersave(storage->sdmmc, SDMMC_POWER_SAVE_ENABLE); +done: storage->initialized = 1; return 1; @@ -769,6 +780,133 @@ static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp return _sdmmc_storage_execute_cmd_type1_ex(storage, resp, cmd, arg, check_busy, expected_state, 0); } +#ifdef SDMMC_DEBUG_PRINT_SD_REGS +void _sd_storage_debug_print_cid(u32 *raw_cid) +{ + gfx_printf("Card Identification\n"); + + gfx_printf("MID: %02X\n", unstuff_bits(raw_cid, 120, 8)); + gfx_printf("OID %04X\n", unstuff_bits(raw_cid, 104, 16)); + gfx_printf("PNM: %02X %02X %02X %02X %02X\n", + unstuff_bits(raw_cid, 96, 8), unstuff_bits(raw_cid, 88, 8), + unstuff_bits(raw_cid, 80, 8), unstuff_bits(raw_cid, 72, 8), + unstuff_bits(raw_cid, 64, 8)); + gfx_printf("PRV: %02X\n", unstuff_bits(raw_cid, 56, 8)); + gfx_printf("PSN: %08X\n", unstuff_bits(raw_cid, 24, 32)); + gfx_printf("MDT: %03X\n", unstuff_bits(raw_cid, 8, 12)); + gfx_printf("--RSVD-- %X\n", unstuff_bits(raw_cid, 20, 4)); +} + +void _sd_storage_debug_print_csd(u32 *raw_csd) +{ + gfx_printf("\n"); + + gfx_printf("\nCSD_STRUCTURE: %X\n", unstuff_bits(raw_csd, 126, 2)); + gfx_printf("TAAC: %02X\n", unstuff_bits(raw_csd, 112, 8)); + gfx_printf("NSAC: %02X\n", unstuff_bits(raw_csd, 104, 8)); + gfx_printf("TRAN_SPEED: %02X\n", unstuff_bits(raw_csd, 96, 8)); + gfx_printf("CCC: %03X\n", unstuff_bits(raw_csd, 84, 12)); + gfx_printf("READ_BL_LEN: %X\n", unstuff_bits(raw_csd, 80, 4)); + gfx_printf("READ_BL_PARTIAL: %X\n", unstuff_bits(raw_csd, 79, 1)); + gfx_printf("WRITE_BLK_MISALIGN: %X\n", unstuff_bits(raw_csd, 78, 1)); + gfx_printf("READ_BLK_MISALIGN: %X\n", unstuff_bits(raw_csd, 77, 1)); + gfx_printf("DSR_IMP: %X\n", unstuff_bits(raw_csd, 76, 1)); + gfx_printf("C_SIZE: %06X\n", unstuff_bits(raw_csd, 48, 22)); + + gfx_printf("ERASE_BLK_LEN: %X\n", unstuff_bits(raw_csd, 46, 1)); + gfx_printf("SECTOR_SIZE: %02X\n", unstuff_bits(raw_csd, 39, 6)); + gfx_printf("WP_GRP_SIZE: %02X\n", unstuff_bits(raw_csd, 32, 6)); + gfx_printf("WP_GRP_ENABLE: %X\n", unstuff_bits(raw_csd, 31, 1)); + + gfx_printf("R2W_FACTOR: %X\n", unstuff_bits(raw_csd, 26, 3)); + gfx_printf("WRITE_BL_LEN: %X\n", unstuff_bits(raw_csd, 22, 4)); + gfx_printf("WRITE_BL_PARTIAL: %X\n", unstuff_bits(raw_csd, 21, 1)); + + gfx_printf("FILE_FORMAT_GRP: %X\n", unstuff_bits(raw_csd, 15, 1)); + gfx_printf("COPY: %X\n", unstuff_bits(raw_csd, 14, 1)); + gfx_printf("PERM_WRITE_PROTECT: %X\n", unstuff_bits(raw_csd, 13, 1)); + gfx_printf("TMP_WRITE_PROTECT: %X\n", unstuff_bits(raw_csd, 12, 1)); + gfx_printf("FILE_FORMAT: %X\n", unstuff_bits(raw_csd, 10, 2)); + + gfx_printf("--RSVD-- %02X %02X %X %X %02X %X\n", + unstuff_bits(raw_csd, 120, 6), unstuff_bits(raw_csd, 70, 6), + unstuff_bits(raw_csd, 47, 1), unstuff_bits(raw_csd, 29, 2), + unstuff_bits(raw_csd, 16, 5), unstuff_bits(raw_csd, 8, 2)); +} + +void _sd_storage_debug_print_scr(u32 *raw_scr) +{ + u32 resp[4]; + memcpy(&resp[2], raw_scr, 8); + + gfx_printf("\n"); + + gfx_printf("SCR_STRUCTURE: %X\n", unstuff_bits(resp, 60, 4)); + gfx_printf("SD_SPEC: %X\n", unstuff_bits(resp, 56, 4)); + gfx_printf("DATA_STAT_AFTER_ERASE: %X\n", unstuff_bits(resp, 55, 1)); + gfx_printf("SD_SECURITY: %X\n", unstuff_bits(resp, 52, 3)); + gfx_printf("SD_BUS widths: %X\n", unstuff_bits(resp, 48, 4)); + gfx_printf("SD_SPEC3: %X\n", unstuff_bits(resp, 47, 1)); + gfx_printf("EX_SECURITY: %X\n", unstuff_bits(resp, 43, 4)); + gfx_printf("SD_SPEC4: %X\n", unstuff_bits(resp, 42, 1)); + gfx_printf("SD_SPECX: %X\n", unstuff_bits(resp, 38, 4)); + gfx_printf("CMD_SUPPORT: %X\n", unstuff_bits(resp, 32, 4)); + gfx_printf("VENDOR: %08X\n", unstuff_bits(resp, 0, 32)); + gfx_printf("--RSVD-- %X\n", unstuff_bits(resp, 36, 2)); +} + +void _sd_storage_debug_print_ssr(u8 *raw_ssr) +{ + u32 raw_ssr0[4]; // 511:384. + u32 raw_ssr1[4]; // 383:256. + u32 raw_ssr2[4]; // 255:128. + u32 raw_ssr3[4]; // 127:0. + memcpy(raw_ssr0, &raw_ssr[0], 16); + memcpy(raw_ssr1, &raw_ssr[16], 16); + memcpy(raw_ssr2, &raw_ssr[32], 16); + memcpy(raw_ssr3, &raw_ssr[48], 16); + + gfx_printf("\nSD Status:\n"); + + gfx_printf("DAT_BUS_WIDTH: %X\n", unstuff_bits(raw_ssr0, 510 - 384, 2)); + gfx_printf("SECURED_MODE: %X\n", unstuff_bits(raw_ssr0, 509 - 384, 1)); + gfx_printf("SECURITY_FUNCTIONS: %02X\n", unstuff_bits(raw_ssr0, 502 - 384, 6)); + gfx_printf("SD_CARD_TYPE: %04X\n", unstuff_bits(raw_ssr0, 480 - 384, 16)); + gfx_printf("SZ_OF_PROTECTED_AREA: %08X\n", unstuff_bits(raw_ssr0, 448 - 384, 32)); + gfx_printf("SPEED_CLASS: %02X\n", unstuff_bits(raw_ssr0, 440 - 384, 8)); + gfx_printf("PERFORMANCE_MOVE: %02X\n", unstuff_bits(raw_ssr0, 432 - 384, 8)); + gfx_printf("AU_SIZE: %X\n", unstuff_bits(raw_ssr0, 428 - 384, 4)); + gfx_printf("ERAZE_SIZE: %04X\n", unstuff_bits(raw_ssr0, 408 - 384, 16)); + gfx_printf("ERASE_TIMEOUT: %02X\n", unstuff_bits(raw_ssr0, 402 - 384, 6)); + gfx_printf("ERASE_OFFSET: %X\n", unstuff_bits(raw_ssr0, 400 - 384, 2)); + gfx_printf("UHS_SPEED_GRADE: %X\n", unstuff_bits(raw_ssr0, 396 - 384, 4)); + gfx_printf("UHS_AU_SIZE: %X\n", unstuff_bits(raw_ssr0, 392 - 384, 4)); + gfx_printf("VIDEO_SPEED_CLASS: %02X\n", unstuff_bits(raw_ssr0, 384 - 384, 8)); + + gfx_printf("VSC_AU_SIZE: %03X\n", unstuff_bits(raw_ssr1, 368 - 256, 10)); + gfx_printf("SUS_ADDR: %06X\n", unstuff_bits(raw_ssr1, 346 - 256, 22)); + gfx_printf("APP_PERF_CLASS: %X\n", unstuff_bits(raw_ssr1, 336 - 256, 4)); + gfx_printf("PERFORMANCE_ENHANCE: %02X\n", unstuff_bits(raw_ssr1, 328 - 256, 8)); + gfx_printf("DISCARD_SUPPORT: %X\n", unstuff_bits(raw_ssr1, 313 - 256, 1)); + gfx_printf("FULE_SUPPORT: %X\n", unstuff_bits(raw_ssr1, 312 - 256, 1)); + + gfx_printf("--RSVD-- %02X %X %02X %02X %04X\n", + unstuff_bits(raw_ssr0, 496 - 384, 6), unstuff_bits(raw_ssr0, 424 - 384, 4), + unstuff_bits(raw_ssr1, 378 - 256, 6), unstuff_bits(raw_ssr1, 340 - 256, 6), + unstuff_bits(raw_ssr1, 314 - 256, 14)); + + gfx_printf("VENDOR_1: %06X %08X\n", + unstuff_bits(raw_ssr1, 288 - 256, 24), unstuff_bits(raw_ssr1, 256 - 256, 32)); + + gfx_printf("VENDOR_2: %08X %08X %08X %08X\n", + unstuff_bits(raw_ssr2, 224 - 128, 32), unstuff_bits(raw_ssr2, 192 - 128, 32), + unstuff_bits(raw_ssr2, 160 - 128, 32), unstuff_bits(raw_ssr2, 128 - 128, 32)); + gfx_printf("VENDOR_3: %08X %08X %08X %08X\n", + unstuff_bits(raw_ssr3, 96 - 0, 32), unstuff_bits(raw_ssr3, 64, 32), + unstuff_bits(raw_ssr3, 32 - 0, 32), unstuff_bits(raw_ssr3, 0, 32)); +} +#endif + static int _sd_storage_send_if_cond(sdmmc_storage_t *storage, bool *is_sdsc) { sdmmc_cmd_t cmdbuf; @@ -794,15 +932,17 @@ static int _sd_storage_send_if_cond(sdmmc_storage_t *storage, bool *is_sdsc) static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, bool is_sdsc, int bus_uhs_support) { sdmmc_cmd_t cmdbuf; - // Support for Current > 150mA + // Support for Current > 150mA. u32 arg = !is_sdsc ? SD_OCR_XPC : 0; - // Support for handling block-addressed SDHC cards + // Support for handling block-addressed SDHC cards. arg |= !is_sdsc ? SD_OCR_CCS : 0; - // Support for 1.8V + // Support for 1.8V signaling. arg |= (bus_uhs_support && !is_sdsc) ? SD_OCR_S18R : 0; - // This is needed for most cards. Do not set bit7 even if 1.8V is supported. + // Support for 3.3V power supply (VDD1). arg |= SD_OCR_VDD_32_33; + sdmmc_init_cmd(&cmdbuf, SD_APP_OP_COND, arg, SDMMC_RSP_TYPE_3, 0); + if (!_sd_storage_execute_app_cmd(storage, R1_SKIP_STATE_CHECK, is_sdsc ? R1_ILLEGAL_COMMAND : 0, &cmdbuf, NULL, NULL)) return 0; @@ -822,7 +962,7 @@ static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, bool is_sdsc, int b // Check if power up is done. if (cond & SD_OCR_BUSY) { -DPRINTF("[SD] op cond: %08X, lv: %d\n", cond, bus_uhs_support); + DPRINTF("[SD] op cond: %08X, lv: %d\n", cond, bus_uhs_support); // Check if card is high capacity. if (cond & SD_OCR_CCS) @@ -834,16 +974,20 @@ DPRINTF("[SD] op cond: %08X, lv: %d\n", cond, bus_uhs_support); // Switch to 1.8V signaling. if (_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY)) { + if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_UHS_SDR12)) + return 0; + if (!sdmmc_enable_low_voltage(storage->sdmmc)) return 0; + storage->is_low_voltage = 1; -DPRINTF("-> switched to low voltage\n"); + DPRINTF("-> switched to low voltage\n"); } } else { -DPRINTF("[SD] no low voltage support\n"); + DPRINTF("[SD] no low voltage support\n"); } return 1; @@ -891,8 +1035,11 @@ static void _sd_storage_parse_scr(sdmmc_storage_t *storage) // unstuff_bits can parse only 4 u32 u32 resp[4]; - resp[3] = *(u32 *)&storage->raw_scr[4]; - resp[2] = *(u32 *)&storage->raw_scr[0]; + memcpy(&resp[2], storage->raw_scr, 8); + +#ifdef SDMMC_DEBUG_PRINT_SD_REGS + _sd_storage_debug_print_scr((u32 *)storage->raw_scr); +#endif storage->scr.sda_vsn = unstuff_bits(resp, 56, 4); storage->scr.bus_widths = unstuff_bits(resp, 48, 4); @@ -904,17 +1051,17 @@ static void _sd_storage_parse_scr(sdmmc_storage_t *storage) storage->scr.cmds = unstuff_bits(resp, 32, 2); } -int _sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf) +int sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf) { sdmmc_cmd_t cmdbuf; sdmmc_init_cmd(&cmdbuf, SD_APP_SEND_SCR, 0, SDMMC_RSP_TYPE_1, 0); sdmmc_req_t reqbuf; - reqbuf.buf = buf; - reqbuf.blksize = 8; - reqbuf.num_sectors = 1; - reqbuf.is_write = 0; - reqbuf.is_multi_block = 0; + reqbuf.buf = buf; + reqbuf.blksize = 8; + reqbuf.num_sectors = 1; + reqbuf.is_write = 0; + reqbuf.is_multi_block = 0; reqbuf.is_auto_stop_trn = 0; if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, NULL)) @@ -931,22 +1078,21 @@ int _sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf) storage->raw_scr[i] = buf[i + 3]; } _sd_storage_parse_scr(storage); - //gfx_hexdump(0, storage->raw_scr, 8); return _sdmmc_storage_check_card_status(tmp); } -int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf) +static int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf) { sdmmc_cmd_t cmdbuf; sdmmc_init_cmd(&cmdbuf, SD_SWITCH, 0xFFFFFF, SDMMC_RSP_TYPE_1, 0); sdmmc_req_t reqbuf; - reqbuf.buf = buf; - reqbuf.blksize = 64; - reqbuf.num_sectors = 1; - reqbuf.is_write = 0; - reqbuf.is_multi_block = 0; + reqbuf.buf = buf; + reqbuf.blksize = 64; + reqbuf.num_sectors = 1; + reqbuf.is_write = 0; + reqbuf.is_multi_block = 0; reqbuf.is_auto_stop_trn = 0; if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL)) @@ -957,7 +1103,7 @@ int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf) return _sdmmc_storage_check_card_status(tmp); } -int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group, u32 arg) +static int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group, u32 arg) { sdmmc_cmd_t cmdbuf; u32 switchcmd = mode << 31 | 0x00FFFFFF; @@ -966,11 +1112,11 @@ int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group, sdmmc_init_cmd(&cmdbuf, SD_SWITCH, switchcmd, SDMMC_RSP_TYPE_1, 0); sdmmc_req_t reqbuf; - reqbuf.buf = buf; - reqbuf.blksize = 64; - reqbuf.num_sectors = 1; - reqbuf.is_write = 0; - reqbuf.is_multi_block = 0; + reqbuf.buf = buf; + reqbuf.blksize = 64; + reqbuf.num_sectors = 1; + reqbuf.is_write = 0; + reqbuf.is_multi_block = 0; reqbuf.is_auto_stop_trn = 0; if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL)) @@ -981,60 +1127,159 @@ int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group, return _sdmmc_storage_check_card_status(tmp); } -void _sd_storage_set_current_limit(sdmmc_storage_t *storage, u16 current_limit, u8 *buf) +static void _sd_storage_set_power_limit(sdmmc_storage_t *storage, u16 power_limit, u8 *buf) { - u32 pwr = SD_SET_CURRENT_LIMIT_200; + u32 pwr = SD_SET_POWER_LIMIT_0_72; - if (current_limit & SD_MAX_CURRENT_800) - pwr = SD_SET_CURRENT_LIMIT_800; - else if (current_limit & SD_MAX_CURRENT_600) - pwr = SD_SET_CURRENT_LIMIT_600; - else if (current_limit & SD_MAX_CURRENT_400) - pwr = SD_SET_CURRENT_LIMIT_400; + // 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) + pwr = SD_SET_POWER_LIMIT_1_44; - _sd_storage_switch(storage, buf, SD_SWITCH_SET, 3, pwr); + _sd_storage_switch(storage, buf, SD_SWITCH_SET, SD_SWITCH_GRP_PWRLIM, pwr); - if (((buf[15] >> 4) & 0x0F) == pwr) + switch ((buf[15] >> 4) & 0x0F) { - switch (pwr) - { - case SD_SET_CURRENT_LIMIT_800: -DPRINTF("[SD] power limit raised to 800mA\n"); - break; + case SD_SET_POWER_LIMIT_2_88: + DPRINTF("[SD] power limit raised to 2880 mW\n"); + break; - case SD_SET_CURRENT_LIMIT_600: -DPRINTF("[SD] power limit raised to 600mA\n"); - break; + case SD_SET_POWER_LIMIT_2_16: + DPRINTF("[SD] power limit raised to 2160 mW\n"); + break; - case SD_SET_CURRENT_LIMIT_400: -DPRINTF("[SD] power limit raised to 400mA\n"); - break; + case SD_SET_POWER_LIMIT_1_44: + DPRINTF("[SD] power limit raised to 1440 mW\n"); + break; - default: - case SD_SET_CURRENT_LIMIT_200: -DPRINTF("[SD] power limit defaulted to 200mA\n"); - break; - } + default: + case SD_SET_POWER_LIMIT_0_72: + DPRINTF("[SD] power limit defaulted to 720 mW\n"); + break; } } -int _sd_storage_enable_highspeed(sdmmc_storage_t *storage, u32 hs_type, u8 *buf) +int _sd_storage_set_driver_type(sdmmc_storage_t *storage, u32 driver, u8 *buf) { - if (!_sd_storage_switch(storage, buf, SD_SWITCH_CHECK, 0, hs_type)) + if (!_sd_storage_switch(storage, buf, SD_SWITCH_CHECK, SD_SWITCH_GRP_DRVSTR, driver)) + return 0; + + u32 driver_out = buf[15] & 0xF; + if (driver_out != driver) + return 0; + DPRINTF("[SD] supports Driver Strength %d\n", driver); + + if (!_sd_storage_switch(storage, buf, SD_SWITCH_SET, SD_SWITCH_GRP_DRVSTR, driver)) + return 0; + + if (driver_out != (buf[15] & 0xF)) + return 0; + DPRINTF("[SD] card accepted Driver Strength %d\n", driver); + + sdmmc_setup_drv_type(storage->sdmmc, driver); + + return 1; +} + +/* + * SD Card DDR200 (DDR208) support + * + * DLL Tuning (a) or Tuning Window (b) procedure: + * 1. Check that Vendor Specific Command System is supported. + * Used as Enable DDR200 Bus. + * 2. Enable DDR200 bus mode via setting 14 to Group 2 via CMD6. + * Access Mode group is left to default 0 (SDR12). + * 3. Setup clock to 200 or 208 MHz. + * 4a. Set host to DDR200/HS400 bus mode that enables DLL syncing. + * Actual implementation supported by all DDR200 cards. + * -- + * 4b. Set host to DDR50 bus mode that supports such high clocks. + * Execute Manual Tuning. + * Limited to non-Sandisk cards. + * + * On Tegra SoCs, that can be done with DDR50 host mode. + * That's because HS400 4-bit or HS400 generally, is not supported on SD SDMMC. + * And also, tuning can't be done automatically on any DDR mode. + * So it needs to be done manually and selected tap will be applied from the + * biggest sampling window. + * That allows DDR200 support on every DDR200 SD card, other than the original + * maker of DDR200, Sandisk. + * + * On the original implementation of DDR200 from Sandisk, a DLL mechanism, + * like the one in eMMC HS400 is mandatory. + * So the card can start data signals whenever it wants, and the host should + * synchronize to the first DAT signal edge change. + * Every single other vendor that implemented that, always starts data transfers + * aligned to clock. That basically makes DDR200 in such SD cards a SDR104 but + * sampled on both edges. So effectively, it's an in-spec signal with DDR50, + * only that is clocked at 200MHz, instead of 50MHz. + * So the extra needed thing is using a tuning window, which is absent from the + * original implementation, since DDL syncing does not use that. + * + * On DLL tuning method expected cards, the tuning window is tiny. + * So check against a minimum of 8 taps window, to disallow DDR200. + */ +#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT +static int _sd_storage_enable_DDR200(sdmmc_storage_t *storage, u8 *buf) +{ + u32 cmd_system = UHS_DDR200_BUS_SPEED; + if (!_sd_storage_switch(storage, buf, SD_SWITCH_CHECK, SD_SWITCH_GRP_CMDSYS, cmd_system)) + return 0; + + u32 system_out = (buf[16] >> 4) & 0xF; + if (system_out != cmd_system) + return 0; + DPRINTF("[SD] supports DDR200 mode\n"); + + u16 total_pwr_consumption = ((u16)buf[0] << 8) | buf[1]; + DPRINTF("[SD] max power: %d mW\n", total_pwr_consumption * 3600 / 1000); + storage->card_power_limit = total_pwr_consumption; + + if (total_pwr_consumption <= 800) + { + if (!_sd_storage_switch(storage, buf, SD_SWITCH_SET, SD_SWITCH_GRP_CMDSYS, cmd_system)) + return 0; + + if (system_out != ((buf[16] >> 4) & 0xF)) + return 0; + DPRINTF("[SD] card accepted DDR200\n"); + + if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_UHS_DDR200)) + return 0; + DPRINTF("[SD] after setup clock DDR200\n"); + + if (!sdmmc_tuning_execute(storage->sdmmc, SDHCI_TIMING_UHS_DDR200, MMC_SEND_TUNING_BLOCK)) + return 0; + DPRINTF("[SD] after tuning DDR200\n"); + + return _sdmmc_storage_check_status(storage); + } + + DPRINTF("[SD] card max power over limit\n"); + return 0; +} +#endif + +static int _sd_storage_set_card_bus_speed(sdmmc_storage_t *storage, u32 hs_type, u8 *buf) +{ + if (!_sd_storage_switch(storage, buf, SD_SWITCH_CHECK, SD_SWITCH_GRP_ACCESS, hs_type)) return 0; -DPRINTF("[SD] supports (U)HS mode: %d\n", buf[16] & 0xF); u32 type_out = buf[16] & 0xF; if (type_out != hs_type) return 0; -DPRINTF("[SD] supports selected (U)HS mode\n"); + DPRINTF("[SD] supports selected (U)HS mode %d\n", buf[16] & 0xF); u16 total_pwr_consumption = ((u16)buf[0] << 8) | buf[1]; -DPRINTF("[SD] total max current: %d\n", total_pwr_consumption); + DPRINTF("[SD] max power: %d mW\n", total_pwr_consumption * 3600 / 1000); + storage->card_power_limit = total_pwr_consumption; if (total_pwr_consumption <= 800) { - if (!_sd_storage_switch(storage, buf, SD_SWITCH_SET, 0, hs_type)) + if (!_sd_storage_switch(storage, buf, SD_SWITCH_SET, SD_SWITCH_GRP_ACCESS, hs_type)) return 0; if (type_out != (buf[16] & 0xF)) @@ -1042,37 +1287,51 @@ DPRINTF("[SD] total max current: %d\n", total_pwr_consumption); return 1; } -DPRINTF("[SD] card max current over limit\n"); + DPRINTF("[SD] card max power over limit\n"); return 0; } -int _sd_storage_enable_uhs_low_volt(sdmmc_storage_t *storage, u32 type, u8 *buf) +static int _sd_storage_enable_uhs_low_volt(sdmmc_storage_t *storage, u32 type, u8 *buf) { if (sdmmc_get_bus_width(storage->sdmmc) != SDMMC_BUS_WIDTH_4) return 0; if (!_sd_storage_switch_get(storage, buf)) return 0; - //gfx_hexdump(0, (u8 *)buf, 64); u8 access_mode = buf[13]; - u16 current_limit = buf[7] | buf[6] << 8; -DPRINTF("[SD] access: %02X, current: %02X\n", access_mode, current_limit); - - // Try to raise the current limit to let the card perform better. - _sd_storage_set_current_limit(storage, current_limit, buf); + u16 power_limit = buf[7] | (buf[6] << 8); +#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT + u16 cmd_system = buf[11] | (buf[10] << 8); + DPRINTF("[SD] access: %02X, power: %02X, cmd: %02X\n", access_mode, power_limit, cmd_system); +#else + DPRINTF("[SD] access: %02X, power: %02X\n", access_mode, power_limit); +#endif u32 hs_type = 0; switch (type) { +#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT + case SDHCI_TIMING_UHS_DDR200: + // Fall through if DDR200 is not supported. + if (cmd_system & SD_MODE_UHS_DDR200) + { + DPRINTF("[SD] setting bus speed to DDR200\n"); + storage->csd.busspeed = 200; + _sd_storage_set_power_limit(storage, power_limit, buf); + return _sd_storage_enable_DDR200(storage, buf); + } +#endif + case SDHCI_TIMING_UHS_SDR104: case SDHCI_TIMING_UHS_SDR82: // Fall through if not supported. if (access_mode & SD_MODE_UHS_SDR104) { + type = SDHCI_TIMING_UHS_SDR104; hs_type = UHS_SDR104_BUS_SPEED; -DPRINTF("[SD] bus speed set to SDR104\n"); + DPRINTF("[SD] setting bus speed to SDR104\n"); switch (type) { case SDHCI_TIMING_UHS_SDR104: @@ -1084,66 +1343,79 @@ DPRINTF("[SD] bus speed set to SDR104\n"); } break; } + case SDHCI_TIMING_UHS_SDR50: if (access_mode & SD_MODE_UHS_SDR50) { - type = SDHCI_TIMING_UHS_SDR50; + type = SDHCI_TIMING_UHS_SDR50; hs_type = UHS_SDR50_BUS_SPEED; -DPRINTF("[SD] bus speed set to SDR50\n"); + DPRINTF("[SD] setting bus speed to SDR50\n"); storage->csd.busspeed = 50; break; } +/* + case SDHCI_TIMING_UHS_DDR50: + if (access_mode & SD_MODE_UHS_DDR50) + { + type = SDHCI_TIMING_UHS_DDR50; + hs_type = UHS_DDR50_BUS_SPEED; + DPRINTF("[SD] setting bus speed to DDR50\n"); + storage->csd.busspeed = 50; + break; + } +*/ case SDHCI_TIMING_UHS_SDR25: if (access_mode & SD_MODE_UHS_SDR25) { type = SDHCI_TIMING_UHS_SDR25; hs_type = UHS_SDR25_BUS_SPEED; -DPRINTF("[SD] bus speed set to SDR25\n"); + DPRINTF("[SD] setting bus speed to SDR25\n"); storage->csd.busspeed = 25; break; } - case SDHCI_TIMING_UHS_SDR12: - if (!(access_mode & SD_MODE_UHS_SDR12)) - return 0; - type = SDHCI_TIMING_UHS_SDR12; - hs_type = UHS_SDR12_BUS_SPEED; -DPRINTF("[SD] bus speed set to SDR12\n"); - storage->csd.busspeed = 12; - break; default: - return 0; - break; + DPRINTF("[SD] bus speed defaulted to SDR12\n"); + storage->csd.busspeed = 12; + return 1; } - if (!_sd_storage_enable_highspeed(storage, hs_type, buf)) + // Try to raise the power limit to let the card perform better. + if (hs_type != UHS_SDR25_BUS_SPEED) + _sd_storage_set_power_limit(storage, power_limit, buf); + + // Setup and set selected card and bus speed. + if (!_sd_storage_set_card_bus_speed(storage, hs_type, buf)) return 0; -DPRINTF("[SD] card accepted UHS\n"); + DPRINTF("[SD] card accepted UHS\n"); + if (!sdmmc_setup_clock(storage->sdmmc, type)) return 0; -DPRINTF("[SD] after setup clock\n"); + DPRINTF("[SD] after setup clock\n"); + if (!sdmmc_tuning_execute(storage->sdmmc, type, MMC_SEND_TUNING_BLOCK)) return 0; -DPRINTF("[SD] after tuning\n"); + DPRINTF("[SD] after tuning\n"); + return _sdmmc_storage_check_status(storage); } -int _sd_storage_enable_hs_high_volt(sdmmc_storage_t *storage, u8 *buf) +static int _sd_storage_enable_hs_high_volt(sdmmc_storage_t *storage, u8 *buf) { if (!_sd_storage_switch_get(storage, buf)) return 0; - //gfx_hexdump(0, (u8 *)buf, 64); u8 access_mode = buf[13]; - u16 current_limit = buf[7] | buf[6] << 8; + u16 power_limit = buf[7] | buf[6] << 8; + DPRINTF("[SD] access: %02X, power: %02X\n", access_mode, power_limit); - // Try to raise the current limit to let the card perform better. - _sd_storage_set_current_limit(storage, current_limit, buf); + // Try to raise the power limit to let the card perform better. + _sd_storage_set_power_limit(storage, power_limit, buf); if (!(access_mode & SD_MODE_HIGH_SPEED)) return 1; - if (!_sd_storage_enable_highspeed(storage, HIGH_SPEED_BUS_SPEED, buf)) + if (!_sd_storage_set_card_bus_speed(storage, HIGH_SPEED_BUS_SPEED, buf)) return 0; if (!_sdmmc_storage_check_status(storage)) @@ -1163,7 +1435,7 @@ u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage) { u32 shift = au_size; au_size = shift ? 8 : 0; - au_size <<= shift; + au_size <<= shift; } else { @@ -1193,12 +1465,16 @@ u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage) static void _sd_storage_parse_ssr(sdmmc_storage_t *storage) { // unstuff_bits supports only 4 u32 so break into 2 x u32x4 groups. - u32 raw_ssr1[4]; - u32 raw_ssr2[4]; + u32 raw_ssr1[4]; // 511:384. + u32 raw_ssr2[4]; // 383:256. memcpy(raw_ssr1, &storage->raw_ssr[0], 16); memcpy(raw_ssr2, &storage->raw_ssr[16], 16); +#ifdef SDMMC_DEBUG_PRINT_SD_REGS + _sd_storage_debug_print_ssr(storage->raw_ssr); +#endif + storage->ssr.bus_width = (unstuff_bits(raw_ssr1, 510 - 384, 2) & SD_BUS_WIDTH_4) ? 4 : 1; storage->ssr.protected_size = unstuff_bits(raw_ssr1, 448 - 384, 32); @@ -1220,11 +1496,11 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage) storage->ssr.speed_class = speed_class; break; } - storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4); + storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4); storage->ssr.video_class = unstuff_bits(raw_ssr1, 384 - 384, 8); - storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4); + storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4); - storage->ssr.au_size = unstuff_bits(raw_ssr1, 428 - 384, 4); + storage->ssr.au_size = unstuff_bits(raw_ssr1, 428 - 384, 4); storage->ssr.uhs_au_size = unstuff_bits(raw_ssr1, 392 - 384, 4); } @@ -1234,16 +1510,16 @@ int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf) sdmmc_init_cmd(&cmdbuf, SD_APP_SD_STATUS, 0, SDMMC_RSP_TYPE_1, 0); sdmmc_req_t reqbuf; - reqbuf.buf = buf; - reqbuf.blksize = 64; - reqbuf.num_sectors = 1; - reqbuf.is_write = 0; - reqbuf.is_multi_block = 0; + reqbuf.buf = buf; + reqbuf.blksize = 64; + reqbuf.num_sectors = 1; + reqbuf.is_write = 0; + reqbuf.is_multi_block = 0; reqbuf.is_auto_stop_trn = 0; if (!(storage->csd.cmdclass & CCC_APP_SPEC)) { -DPRINTF("[SD] ssr: Not supported\n"); + DPRINTF("[SD] ssr: Not supported\n"); return 0; } @@ -1263,7 +1539,6 @@ DPRINTF("[SD] ssr: Not supported\n"); } _sd_storage_parse_ssr(storage); - //gfx_hexdump(0, storage->raw_ssr, 64); return _sdmmc_storage_check_card_status(tmp); } @@ -1272,26 +1547,34 @@ static void _sd_storage_parse_cid(sdmmc_storage_t *storage) { u32 *raw_cid = (u32 *)&(storage->raw_cid); - storage->cid.manfid = unstuff_bits(raw_cid, 120, 8); - storage->cid.oemid = unstuff_bits(raw_cid, 104, 16); +#ifdef SDMMC_DEBUG_PRINT_SD_REGS + _sd_storage_debug_print_cid(raw_cid); +#endif + + storage->cid.manfid = unstuff_bits(raw_cid, 120, 8); + storage->cid.oemid = unstuff_bits(raw_cid, 104, 16); storage->cid.prod_name[0] = unstuff_bits(raw_cid, 96, 8); storage->cid.prod_name[1] = unstuff_bits(raw_cid, 88, 8); storage->cid.prod_name[2] = unstuff_bits(raw_cid, 80, 8); storage->cid.prod_name[3] = unstuff_bits(raw_cid, 72, 8); storage->cid.prod_name[4] = unstuff_bits(raw_cid, 64, 8); - storage->cid.hwrev = unstuff_bits(raw_cid, 60, 4); - storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4); - storage->cid.serial = unstuff_bits(raw_cid, 24, 32); - storage->cid.year = unstuff_bits(raw_cid, 12, 8) + 2000; - storage->cid.month = unstuff_bits(raw_cid, 8, 4); + storage->cid.hwrev = unstuff_bits(raw_cid, 60, 4); + storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4); + storage->cid.serial = unstuff_bits(raw_cid, 24, 32); + storage->cid.year = unstuff_bits(raw_cid, 12, 8) + 2000; + storage->cid.month = unstuff_bits(raw_cid, 8, 4); } static void _sd_storage_parse_csd(sdmmc_storage_t *storage) { u32 *raw_csd = (u32 *)&(storage->raw_csd); - storage->csd.structure = unstuff_bits(raw_csd, 126, 2); - storage->csd.cmdclass = unstuff_bits(raw_csd, 84, 12); +#ifdef SDMMC_DEBUG_PRINT_SD_REGS + _sd_storage_debug_print_csd(raw_csd); +#endif + + storage->csd.structure = unstuff_bits(raw_csd, 126, 2); + storage->csd.cmdclass = unstuff_bits(raw_csd, 84, 12); storage->csd.read_blkbits = unstuff_bits(raw_csd, 80, 4); storage->csd.write_protect = unstuff_bits(raw_csd, 12, 2); switch(storage->csd.structure) @@ -1302,13 +1585,13 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage) break; case 1: - storage->csd.c_size = (1 + unstuff_bits(raw_csd, 48, 22)); - storage->csd.capacity = storage->csd.c_size << 10; + storage->csd.c_size = (1 + unstuff_bits(raw_csd, 48, 22)); + storage->csd.capacity = storage->csd.c_size << 10; storage->csd.read_blkbits = 9; break; default: -DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure); + DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure); break; } @@ -1325,6 +1608,7 @@ static bool _sdmmc_storage_get_bus_uhs_support(u32 bus_width, u32 type) case SDHCI_TIMING_UHS_SDR104: case SDHCI_TIMING_UHS_SDR82: case SDHCI_TIMING_UHS_DDR50: + case SDHCI_TIMING_UHS_DDR200: if (bus_width == SDMMC_BUS_WIDTH_4) return true; default: @@ -1347,7 +1631,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_widt u8 *buf = (u8 *)SDMMC_UPPER_BUFFER; bool bus_uhs_support = _sdmmc_storage_get_bus_uhs_support(bus_width, type); -DPRINTF("[SD] init: bus: %d, type: %d\n", bus_width, type); + DPRINTF("[SD]-[init: bus: %d, type: %d]\n", bus_width, type); // Some cards (SanDisk U1), do not like a fast power cycle. Wait min 100ms. sdmmc_storage_init_wait_sd(); @@ -1355,61 +1639,62 @@ DPRINTF("[SD] init: bus: %d, type: %d\n", bus_width, type); memset(storage, 0, sizeof(sdmmc_storage_t)); storage->sdmmc = sdmmc; - if (!sdmmc_init(sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, SDMMC_POWER_SAVE_DISABLE)) + if (!sdmmc_init(sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID)) return 0; -DPRINTF("[SD] after init\n"); + DPRINTF("[SD] after init\n"); - usleep(1000 + (74000 + sdmmc->divisor - 1) / sdmmc->divisor); + // Wait 1ms + 74 cycles. + usleep(1000 + (74 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock); if (!_sdmmc_storage_go_idle_state(storage)) return 0; -DPRINTF("[SD] went to idle state\n"); + DPRINTF("[SD] went to idle state\n"); if (!_sd_storage_send_if_cond(storage, &is_sdsc)) return 0; -DPRINTF("[SD] after send if cond\n"); + DPRINTF("[SD] after send if cond\n"); if (!_sd_storage_get_op_cond(storage, is_sdsc, bus_uhs_support)) return 0; -DPRINTF("[SD] got op cond\n"); + DPRINTF("[SD] got op cond\n"); if (!_sdmmc_storage_get_cid(storage)) return 0; -DPRINTF("[SD] got cid\n"); + DPRINTF("[SD] got cid\n"); _sd_storage_parse_cid(storage); if (!_sd_storage_get_rca(storage)) return 0; -DPRINTF("[SD] got rca (= %04X)\n", storage->rca); + DPRINTF("[SD] got rca (= %04X)\n", storage->rca); if (!_sdmmc_storage_get_csd(storage)) return 0; -DPRINTF("[SD] got csd\n"); + DPRINTF("[SD] got csd\n"); _sd_storage_parse_csd(storage); if (!storage->is_low_voltage) { if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_DS12)) return 0; -DPRINTF("[SD] after setup default clock\n"); + DPRINTF("[SD] after setup default clock\n"); } if (!_sdmmc_storage_select_card(storage)) return 0; -DPRINTF("[SD] card selected\n"); + DPRINTF("[SD] card selected\n"); if (!_sdmmc_storage_set_blocklen(storage, 512)) return 0; -DPRINTF("[SD] set blocklen to 512\n"); + DPRINTF("[SD] set blocklen to 512\n"); // Disconnect Card Detect resistor from DAT3. if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_CLR_CARD_DETECT, 0, 0, R1_STATE_TRAN)) return 0; -DPRINTF("[SD] cleared card detect\n"); + DPRINTF("[SD] cleared card detect\n"); - if (!_sd_storage_get_scr(storage, buf)) + if (!sd_storage_get_scr(storage, buf)) return 0; -DPRINTF("[SD] got scr\n"); + DPRINTF("[SD] got scr\n"); // If card supports a wider bus and if it's not SD Version 1.0 switch bus width. if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & BIT(SD_BUS_WIDTH_4)) && storage->scr.sda_vsn) @@ -1418,26 +1703,26 @@ DPRINTF("[SD] got scr\n"); return 0; sdmmc_set_bus_width(storage->sdmmc, SDMMC_BUS_WIDTH_4); -DPRINTF("[SD] switched to wide bus width\n"); + DPRINTF("[SD] switched to wide bus width\n"); } else { bus_width = SDMMC_BUS_WIDTH_1; -DPRINTF("[SD] SD does not support wide bus width\n"); + DPRINTF("[SD] SD does not support wide bus width\n"); } if (storage->is_low_voltage) { if (!_sd_storage_enable_uhs_low_volt(storage, type, buf)) return 0; -DPRINTF("[SD] enabled UHS\n"); + DPRINTF("[SD] enabled UHS\n"); } else if (type != SDHCI_TIMING_SD_DS12 && storage->scr.sda_vsn) // Not default speed and not SD Version 1.0. { if (!_sd_storage_enable_hs_high_volt(storage, buf)) return 0; -DPRINTF("[SD] enabled HS\n"); + DPRINTF("[SD] enabled HS\n"); switch (bus_width) { case SDMMC_BUS_WIDTH_4: @@ -1453,7 +1738,7 @@ DPRINTF("[SD] enabled HS\n"); // Parse additional card info from sd status. if (sd_storage_get_ssr(storage, buf)) { -DPRINTF("[SD] got sd status\n"); + DPRINTF("[SD] got sd status\n"); } sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE); @@ -1474,11 +1759,11 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf) sdmmc_init_cmd(&cmdbuf, MMC_VENDOR_60_CMD, 0, SDMMC_RSP_TYPE_1, 1); sdmmc_req_t reqbuf; - reqbuf.buf = buf; - reqbuf.blksize = 64; - reqbuf.num_sectors = 1; - reqbuf.is_write = 1; - reqbuf.is_multi_block = 0; + reqbuf.buf = buf; + reqbuf.blksize = 64; + reqbuf.num_sectors = 1; + reqbuf.is_write = 1; + reqbuf.is_multi_block = 0; reqbuf.is_auto_stop_trn = 0; if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL)) @@ -1499,15 +1784,16 @@ int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc) memset(storage, 0, sizeof(sdmmc_storage_t)); storage->sdmmc = sdmmc; - if (!sdmmc_init(sdmmc, SDMMC_2, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS102, SDMMC_POWER_SAVE_DISABLE)) + if (!sdmmc_init(sdmmc, SDMMC_2, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS100)) return 0; -DPRINTF("[gc] after init\n"); + DPRINTF("[GC] after init\n"); - usleep(1000 + (10000 + sdmmc->divisor - 1) / sdmmc->divisor); + // Wait 1ms + 10 clock cycles. + usleep(1000 + (10 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock); - if (!sdmmc_tuning_execute(storage->sdmmc, SDHCI_TIMING_MMC_HS102, MMC_SEND_TUNING_BLOCK_HS200)) + if (!sdmmc_tuning_execute(storage->sdmmc, SDHCI_TIMING_MMC_HS100, MMC_SEND_TUNING_BLOCK_HS200)) return 0; -DPRINTF("[gc] after tuning\n"); + DPRINTF("[GC] after tuning\n"); sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE); diff --git a/bdk/storage/sdmmc.h b/bdk/storage/sdmmc.h index 5dcd10f..283e0d4 100644 --- a/bdk/storage/sdmmc.h +++ b/bdk/storage/sdmmc.h @@ -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, @@ -129,10 +129,7 @@ typedef struct _mmc_csd u16 cmdclass; u32 c_size; u32 r2w_factor; - u32 max_dtr; - u32 erase_size; /* In sectors */ u32 read_blkbits; - u32 write_blkbits; u32 capacity; u8 write_protect; u16 busspeed; @@ -186,6 +183,7 @@ typedef struct _sdmmc_storage_t int is_low_voltage; u32 partition; int initialized; + u32 card_power_limit; u8 raw_cid[0x10]; u8 raw_csd[0x10]; u8 raw_scr[8]; @@ -209,6 +207,9 @@ int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc); int sdmmc_storage_execute_vendor_cmd(sdmmc_storage_t *storage, u32 arg); int sdmmc_storage_vendor_sandisk_report(sdmmc_storage_t *storage, void *buf); +int mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf); + +int sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf); int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf); u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage); diff --git a/bdk/storage/sdmmc_driver.c b/bdk/storage/sdmmc_driver.c index f31271e..0797bff 100644 --- a/bdk/storage/sdmmc_driver.c +++ b/bdk/storage/sdmmc_driver.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2022 CTCaer + * Copyright (c) 2018-2023 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -27,16 +27,15 @@ #include #include #include +#include #include -#include //#define DPRINTF(...) gfx_printf(__VA_ARGS__) //#define ERROR_EXTRA_PRINTING #define DPRINTF(...) -#ifdef BDK_SDMMC_OC_AND_EXTRA_PRINT +#ifdef BDK_SDMMC_EXTRA_PRINT #define ERROR_EXTRA_PRINTING -#define SDMMC_EMMC_OC #endif /*! SCMMC controller base addresses. */ @@ -88,9 +87,9 @@ static int _sdmmc_set_io_power(sdmmc_t *sdmmc, u32 power) u32 sdmmc_get_bus_width(sdmmc_t *sdmmc) { u32 h = sdmmc->regs->hostctl; - if (h & SDHCI_CTRL_8BITBUS) + if (h & SDHCI_CTRL_8BITBUS) // eMMC only (or UHS-II). return SDMMC_BUS_WIDTH_8; - if (h & SDHCI_CTRL_4BITBUS) + if (h & SDHCI_CTRL_4BITBUS) // SD only. return SDMMC_BUS_WIDTH_4; return SDMMC_BUS_WIDTH_1; } @@ -102,28 +101,28 @@ void sdmmc_set_bus_width(sdmmc_t *sdmmc, u32 bus_width) if (bus_width == SDMMC_BUS_WIDTH_1) sdmmc->regs->hostctl = host_control; else if (bus_width == SDMMC_BUS_WIDTH_4) - sdmmc->regs->hostctl = host_control | SDHCI_CTRL_4BITBUS; + sdmmc->regs->hostctl = host_control | SDHCI_CTRL_4BITBUS; // SD only. else if (bus_width == SDMMC_BUS_WIDTH_8) - sdmmc->regs->hostctl = host_control | SDHCI_CTRL_8BITBUS; + sdmmc->regs->hostctl = host_control | SDHCI_CTRL_8BITBUS; // eMMC only (or UHS-II). } void sdmmc_save_tap_value(sdmmc_t *sdmmc) { - sdmmc->venclkctl_tap = sdmmc->regs->venclkctl >> 16; + sdmmc->venclkctl_tap = (sdmmc->regs->venclkctl & 0xFF0000) >> 16; sdmmc->venclkctl_set = 1; } static int _sdmmc_config_tap_val(sdmmc_t *sdmmc, u32 type) { - const u32 dqs_trim_val = 0x28; - const u32 tap_values_t210[] = { 4, 0, 3, 0 }; + const u32 dqs_trim_val = 40; // 24 if HS533/HS667. + const u8 tap_values_t210[4] = { 4, 0, 3, 0 }; u32 tap_val = 0; if (type == SDHCI_TIMING_MMC_HS400) sdmmc->regs->vencapover = (sdmmc->regs->vencapover & 0xFFFFC0FF) | (dqs_trim_val << 8); - sdmmc->regs->ventunctl0 &= ~TEGRA_MMC_VNDR_TUN_CTRL0_TAP_VAL_UPDATED_BY_HW; + sdmmc->regs->ventunctl0 &= ~SDHCI_TEGRA_TUNING_TAP_HW_UPDATED; if (type == SDHCI_TIMING_MMC_HS400) { @@ -140,9 +139,9 @@ static int _sdmmc_config_tap_val(sdmmc_t *sdmmc, u32 type) return 1; } -static int _sdmmc_commit_changes(sdmmc_t *sdmmc) +static void _sdmmc_commit_changes(sdmmc_t *sdmmc) { - return sdmmc->regs->clkcon; + (void)sdmmc->regs->clkcon; } static void _sdmmc_pad_config_fallback(sdmmc_t *sdmmc, u32 power) @@ -173,8 +172,8 @@ static void _sdmmc_pad_config_fallback(sdmmc_t *sdmmc, u32 power) break; case SDMMC_4: // 50 Ohm 2X Driver. PU:16, PD:16, B01: PU:10, PD:10. - APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) = - (APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) & 0xFFFFC003) | (sdmmc->t210b01 ? 0xA28 : 0x1040); + APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) = (APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) & 0xFFFFC003) | + (sdmmc->t210b01 ? 0xA28 : 0x1040); (void)APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL); // Commit write. break; } @@ -189,21 +188,21 @@ static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power) sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; } - // Enable E_INPUT power. - if (!(sdmmc->regs->sdmemcmppadctl & TEGRA_MMC_SDMEMCOMPPADCTRL_PAD_E_INPUT_PWRD)) + // Enable E_INPUT (SD) or Disable E_PWRD (eMMC) power. + if (!(sdmmc->regs->sdmemcmppadctl & SDHCI_TEGRA_PADCTRL_E_INPUT_PWRD)) { - sdmmc->regs->sdmemcmppadctl |= TEGRA_MMC_SDMEMCOMPPADCTRL_PAD_E_INPUT_PWRD; + sdmmc->regs->sdmemcmppadctl |= SDHCI_TEGRA_PADCTRL_E_INPUT_PWRD; _sdmmc_commit_changes(sdmmc); usleep(1); } // Enable auto calibration and start auto configuration. - sdmmc->regs->autocalcfg |= TEGRA_MMC_AUTOCALCFG_AUTO_CAL_ENABLE | TEGRA_MMC_AUTOCALCFG_AUTO_CAL_START; + sdmmc->regs->autocalcfg |= SDHCI_TEGRA_AUTOCAL_ENABLE | SDHCI_TEGRA_AUTOCAL_START; _sdmmc_commit_changes(sdmmc); usleep(2); u32 timeout = get_tmr_ms() + 10; - while (sdmmc->regs->autocalsts & TEGRA_MMC_AUTOCALSTS_AUTO_CAL_ACTIVE) + while (sdmmc->regs->autocalsts & SDHCI_TEGRA_AUTOCAL_ACTIVE) { if (get_tmr_ms() > timeout) { @@ -215,33 +214,29 @@ static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power) #ifdef ERROR_EXTRA_PRINTING // Check if Comp pad is open or short to ground. // SDMMC1: CZ pads - T210/T210B01: 7-bit/5-bit. SDMMC2/4: LV_CZ pads - 5-bit. - u8 code_mask = (sdmmc->t210b01 || sdmmc->id != SDMMC_1) ? 0x1F : 0x7F; - u8 autocal_pu_status = sdmmc->regs->autocalsts & code_mask; + // Use 0x1F mask for all. + u8 autocal_pu_status = sdmmc->regs->autocalsts & 0x1F; if (!autocal_pu_status) - EPRINTF("SDMMC: Comp Pad short to gnd!"); - else if (autocal_pu_status == code_mask) - EPRINTF("SDMMC: Comp Pad open!"); + EPRINTFARGS("SDMMC%d: Comp Pad open!", sdmmc->id + 1); + else if (autocal_pu_status == 0x1F) + EPRINTFARGS("SDMMC%d: Comp Pad short to gnd!", sdmmc->id + 1); #endif // In case auto calibration fails, we load suggested standard values. if (!timeout) { + sdmmc->regs->autocalcfg &= ~SDHCI_TEGRA_AUTOCAL_ENABLE; _sdmmc_pad_config_fallback(sdmmc, power); - sdmmc->regs->autocalcfg &= ~TEGRA_MMC_AUTOCALCFG_AUTO_CAL_ENABLE; } - // Disable E_INPUT to conserve power. - sdmmc->regs->sdmemcmppadctl &= ~TEGRA_MMC_SDMEMCOMPPADCTRL_PAD_E_INPUT_PWRD; + // Disable E_INPUT (SD) or enable E_PWRD (eMMC) to conserve power. + sdmmc->regs->sdmemcmppadctl &= ~SDHCI_TEGRA_PADCTRL_E_INPUT_PWRD; - if(should_enable_sd_clock) + if (should_enable_sd_clock) sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; } -#ifdef SDMMC_EMMC_OC -static int _sdmmc_dll_cal_execute(sdmmc_t *sdmmc, bool overclock) -#else static int _sdmmc_dll_cal_execute(sdmmc_t *sdmmc) -#endif { int result = 1, should_disable_sd_clock = 0; @@ -251,17 +246,15 @@ static int _sdmmc_dll_cal_execute(sdmmc_t *sdmmc) sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; } -#ifdef SDMMC_EMMC_OC - // Add -4 TX_DLY_CODE_OFFSET if HS533. - if (sdmmc->id == SDMMC_4 && overclock) - sdmmc->regs->vendllcalcfg = sdmmc->regs->vendllcalcfg &= 0xFFFFC07F | (0x7C << 7); -#endif + // Add -4 TX_DLY_CODE_OFFSET if HS533/HS667. + // if (sdmmc->id == SDMMC_4 && sdmmc->card_clock > 208000) + // sdmmc->regs->vendllctl0 = sdmmc->regs->vendllctl0 &= 0xFFFFC07F | (0x7C << 7); - sdmmc->regs->vendllcalcfg |= TEGRA_MMC_DLLCAL_CFG_EN_CALIBRATE; + sdmmc->regs->vendllcalcfg |= SDHCI_TEGRA_DLLCAL_CALIBRATE; _sdmmc_commit_changes(sdmmc); u32 timeout = get_tmr_ms() + 5; - while (sdmmc->regs->vendllcalcfg & TEGRA_MMC_DLLCAL_CFG_EN_CALIBRATE) + while (sdmmc->regs->vendllcalcfg & SDHCI_TEGRA_DLLCAL_CALIBRATE) { if (get_tmr_ms() > timeout) { @@ -271,7 +264,7 @@ static int _sdmmc_dll_cal_execute(sdmmc_t *sdmmc) } timeout = get_tmr_ms() + 10; - while (sdmmc->regs->vendllcalcfgsts & TEGRA_MMC_DLLCAL_CFG_STATUS_DLL_ACTIVE) + while (sdmmc->regs->vendllcalcfgsts & SDHCI_TEGRA_DLLCAL_ACTIVE) { if (get_tmr_ms() > timeout) { @@ -286,7 +279,7 @@ out:; return result; } -static void _sdmmc_reset(sdmmc_t *sdmmc) +static void _sdmmc_reset_cmd_data(sdmmc_t *sdmmc) { sdmmc->regs->swrst |= SDHCI_RESET_CMD | SDHCI_RESET_DATA; _sdmmc_commit_changes(sdmmc); @@ -304,6 +297,13 @@ static void _sdmmc_reset_all(sdmmc_t *sdmmc) ; } +void sdmmc_setup_drv_type(sdmmc_t *sdmmc, u32 type) +{ + sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & (~SDHCI_CTRL_DRV_TYPE_MASK)) | SDHCI_CTRL_DRV_TYPE(type); + + _sdmmc_commit_changes(sdmmc); +} + int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type) { // Disable the SD clock if it was enabled, and reenable it later. @@ -316,7 +316,7 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type) _sdmmc_config_tap_val(sdmmc, type); - _sdmmc_reset(sdmmc); + _sdmmc_reset_cmd_data(sdmmc); switch (type) { @@ -335,28 +335,35 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type) break; case SDHCI_TIMING_MMC_HS200: - case SDHCI_TIMING_UHS_SDR50: // T210 Errata for SDR50, the host must be set to SDR104. + case SDHCI_TIMING_UHS_SDR50: // T210 Errata: the host must be set to SDR104 to WAR a CRC issue. case SDHCI_TIMING_UHS_SDR104: case SDHCI_TIMING_UHS_SDR82: - case SDHCI_TIMING_UHS_DDR50: - case SDHCI_TIMING_MMC_HS102: - sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & SDHCI_CTRL_UHS_MASK) | UHS_SDR104_BUS_SPEED; + case SDHCI_TIMING_MMC_HS100: + sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & (~SDHCI_CTRL_UHS_MASK)) | UHS_SDR104_BUS_SPEED; sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180; break; case SDHCI_TIMING_MMC_HS400: // Non standard. - sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & SDHCI_CTRL_UHS_MASK) | HS400_BUS_SPEED; + sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & (~SDHCI_CTRL_UHS_MASK)) | HS400_BUS_SPEED; sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180; break; case SDHCI_TIMING_UHS_SDR25: - sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & SDHCI_CTRL_UHS_MASK) | UHS_SDR25_BUS_SPEED; + sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & (~SDHCI_CTRL_UHS_MASK)) | UHS_SDR25_BUS_SPEED; sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180; break; case SDHCI_TIMING_UHS_SDR12: - sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & SDHCI_CTRL_UHS_MASK) | UHS_SDR12_BUS_SPEED; + sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & (~SDHCI_CTRL_UHS_MASK)) | UHS_SDR12_BUS_SPEED; + sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180; + break; + + case SDHCI_TIMING_UHS_DDR50: +#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT + case SDHCI_TIMING_UHS_DDR200: +#endif + sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & (~SDHCI_CTRL_UHS_MASK)) | UHS_DDR50_BUS_SPEED; sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180; break; } @@ -367,31 +374,22 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type) u16 divisor; clock_sdmmc_get_card_clock_div(&clock, &divisor, type); clock_sdmmc_config_clock_source(&clock, sdmmc->id, clock); - sdmmc->divisor = (clock + divisor - 1) / divisor; + sdmmc->card_clock = (clock + divisor - 1) / divisor; - //if divisor != 1 && divisor << 31 -> error + // (divisor != 1) && (divisor & 1) -> error - u16 div = divisor >> 1; - divisor = 0; - if (div > 0xFF) - divisor = div >> SDHCI_DIVIDER_SHIFT; + u16 div_lo = divisor >> 1; + u16 div_hi = div_lo >> 8; - sdmmc->regs->clkcon = (sdmmc->regs->clkcon & ~(SDHCI_DIV_MASK | SDHCI_DIV_HI_MASK)) - | (div << SDHCI_DIVIDER_SHIFT) | (divisor << SDHCI_DIVIDER_HI_SHIFT); + sdmmc->regs->clkcon = (sdmmc->regs->clkcon & ~(SDHCI_DIV_MASK | SDHCI_DIV_HI_MASK)) | + (div_lo << SDHCI_DIV_LO_SHIFT) | (div_hi << SDHCI_DIV_HI_SHIFT); // Enable the SD clock again. if (should_enable_sd_clock) sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; if (type == SDHCI_TIMING_MMC_HS400) - { -#ifdef SDMMC_EMMC_OC - bool overclock_en = clock > 208000; - return _sdmmc_dll_cal_execute(sdmmc, overclock_en); -#else return _sdmmc_dll_cal_execute(sdmmc); -#endif - } return 1; } @@ -521,10 +519,10 @@ static int _sdmmc_wait_cmd_data_inhibit(sdmmc_t *sdmmc, bool wait_dat) _sdmmc_commit_changes(sdmmc); u32 timeout = get_tmr_ms() + 2000; - while(sdmmc->regs->prnsts & SDHCI_CMD_INHIBIT) + while (sdmmc->regs->prnsts & SDHCI_CMD_INHIBIT) if (get_tmr_ms() > timeout) { - _sdmmc_reset(sdmmc); + _sdmmc_reset_cmd_data(sdmmc); return 0; } @@ -534,7 +532,7 @@ static int _sdmmc_wait_cmd_data_inhibit(sdmmc_t *sdmmc, bool wait_dat) while (sdmmc->regs->prnsts & SDHCI_DATA_INHIBIT) if (get_tmr_ms() > timeout) { - _sdmmc_reset(sdmmc); + _sdmmc_reset_cmd_data(sdmmc); return 0; } } @@ -547,10 +545,10 @@ static int _sdmmc_wait_card_busy(sdmmc_t *sdmmc) _sdmmc_commit_changes(sdmmc); u32 timeout = get_tmr_ms() + 2000; - while (!(sdmmc->regs->prnsts & SDHCI_DATA_0_LVL_MASK)) + while (!(sdmmc->regs->prnsts & SDHCI_DATA_0_LVL)) if (get_tmr_ms() > timeout) { - _sdmmc_reset(sdmmc); + _sdmmc_reset_cmd_data(sdmmc); return 0; } @@ -594,7 +592,7 @@ static int _sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, bool is_data_presen if (cmd->check_busy) cmdflags = SDHCI_CMD_RESP_LEN48_BUSY | SDHCI_CMD_INDEX | SDHCI_CMD_CRC; else - cmdflags = SDHCI_CMD_RESP_LEN48 | SDHCI_CMD_INDEX | SDHCI_CMD_CRC; + cmdflags = SDHCI_CMD_RESP_LEN48 | SDHCI_CMD_INDEX | SDHCI_CMD_CRC; break; case SDMMC_RSP_TYPE_2: @@ -611,8 +609,9 @@ static int _sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, bool is_data_presen if (is_data_present) cmdflags |= SDHCI_CMD_DATA; + sdmmc->regs->argument = cmd->arg; - sdmmc->regs->cmdreg = (cmd->cmd << 8) | cmdflags; + sdmmc->regs->cmdreg = SDHCI_CMD_IDX(cmd->cmd) | cmdflags; return 1; } @@ -627,10 +626,8 @@ static void _sdmmc_send_tuning_cmd(sdmmc_t *sdmmc, u32 cmd) _sdmmc_send_cmd(sdmmc, &cmdbuf, true); } -static int _sdmmc_tuning_execute_once(sdmmc_t *sdmmc, u32 cmd) +static int _sdmmc_tuning_execute_once(sdmmc_t *sdmmc, u32 cmd, u32 tap) { - if (sdmmc->powersave_enabled) - return 0; if (!_sdmmc_wait_cmd_data_inhibit(sdmmc, true)) return 0; @@ -640,11 +637,21 @@ static int _sdmmc_tuning_execute_once(sdmmc_t *sdmmc, u32 cmd) sdmmc->regs->norintsts = sdmmc->regs->norintsts; sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; +#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT + // Set tap if manual tuning. + if (tap != HW_TAP_TUNING) + { + sdmmc->regs->ventunctl0 &= ~SDHCI_TEGRA_TUNING_TAP_HW_UPDATED; + sdmmc->regs->venclkctl = (sdmmc->regs->venclkctl & 0xFF00FFFF) | (tap << 16); + sdmmc->regs->ventunctl0 |= SDHCI_TEGRA_TUNING_TAP_HW_UPDATED; + } +#endif + _sdmmc_send_tuning_cmd(sdmmc, cmd); _sdmmc_commit_changes(sdmmc); usleep(1); - _sdmmc_reset(sdmmc); + _sdmmc_reset_cmd_data(sdmmc); sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; _sdmmc_commit_changes(sdmmc); @@ -657,59 +664,170 @@ static int _sdmmc_tuning_execute_once(sdmmc_t *sdmmc, u32 cmd) sdmmc->regs->norintsts = SDHCI_INT_DATA_AVAIL; sdmmc->regs->norintstsen &= ~SDHCI_INT_DATA_AVAIL; _sdmmc_commit_changes(sdmmc); - usleep((1000 * 8 + sdmmc->divisor - 1) / sdmmc->divisor); + usleep((8 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock); // Wait 8 cycles. return 1; } } - _sdmmc_reset(sdmmc); + _sdmmc_reset_cmd_data(sdmmc); sdmmc->regs->norintstsen &= ~SDHCI_INT_DATA_AVAIL; _sdmmc_commit_changes(sdmmc); - usleep((1000 * 8 + sdmmc->divisor - 1) / sdmmc->divisor); + usleep((8 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock); // Wait 8 cycles. return 0; } +#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT +typedef struct _sdmmc_manual_tuning_t +{ + u32 result[8]; + u32 num_iter; + u32 tap_start; + u32 tap_end; +} sdmmc_manual_tuning_t; + +static int _sdmmc_manual_tuning_set_tap(sdmmc_t *sdmmc, sdmmc_manual_tuning_t *tuning) +{ + u32 tap_start = INVALID_TAP; + u32 win_size = 0; + u32 best_tap = 0; + u32 best_size = 0; + + for (u32 i = 0; i < tuning->num_iter; i++) + { + u32 iter_end = i == (tuning->num_iter - 1) ? 1 : 0; + u32 stable = tuning->result[i / 32] & BIT(i % 32); + if (stable && !iter_end) + { + if (tap_start == INVALID_TAP) + tap_start = i; + + win_size++; + } + else + { + if (tap_start != INVALID_TAP) + { + u32 tap_end = !iter_end ? (i - 1) : i; + + // Check if window is wider. + if (win_size > best_size) + { + best_tap = (tap_start + tap_end) / 2; + best_size = win_size + iter_end; + } + + tap_start = INVALID_TAP; + win_size = 0; + } + } + } + + + // Check if failed or window too small. + if (!best_tap || best_size < SAMPLING_WINDOW_SIZE_MIN) + return 0; + + sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; + sdmmc->regs->ventunctl0 &= ~SDHCI_TEGRA_TUNING_TAP_HW_UPDATED; + + // Set tap. + sdmmc->regs->venclkctl = (sdmmc->regs->venclkctl & 0xFF00FFFF) | (best_tap << 16); + + sdmmc->regs->ventunctl0 |= SDHCI_TEGRA_TUNING_TAP_HW_UPDATED; + sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; + + return 1; +} + +/* + * SD Card DDR200 (DDR208) support + * + * On Tegra X1, that can be done with DDR50 host mode. + * That's because HS400 4-bit or HS400 generally, is not supported on SDMMC1/3. + * And also, tuning can't be done automatically on any DDR mode. + * So it needs to be done manually and selected tap will be applied from the biggest + * sampling window. + * That allows DDR200 support on every DDR200 sd card, other than the original maker + * of DDR200, Sandisk. Since Sandisk cards mandate DLL syncing. + */ +static int sdmmc_tuning_execute_ddr200(sdmmc_t *sdmmc) +{ + sdmmc_manual_tuning_t manual_tuning = { 0 }; + manual_tuning.num_iter = 128; + + sdmmc->regs->ventunctl1 = 0; // step_size 1. + sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFF1FFF) | (2 << 13); // 128 Tries. + sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFFE03F) | (1 << 6); // 1x Multiplier. + sdmmc->regs->ventunctl0 |= SDHCI_TEGRA_TUNING_TAP_HW_UPDATED; + + sdmmc->regs->hostctl2 |= SDHCI_CTRL_EXEC_TUNING; + + for (u32 i = 0; i < manual_tuning.num_iter; i++) + { + _sdmmc_tuning_execute_once(sdmmc, MMC_SEND_TUNING_BLOCK, i); + + // Save result for manual tuning. + int sampled = (sdmmc->regs->hostctl2 >> SDHCI_CTRL_TUNED_CLK_SHIFT) & 1; + manual_tuning.result[i / 32] |= sampled << (i % 32); + + if (!(sdmmc->regs->hostctl2 & SDHCI_CTRL_EXEC_TUNING)) + break; + } + + return _sdmmc_manual_tuning_set_tap(sdmmc, &manual_tuning); +} +#endif + int sdmmc_tuning_execute(sdmmc_t *sdmmc, u32 type, u32 cmd) { - u32 max = 0, flag = 0; + u32 num_iter, flag; + + if (sdmmc->powersave_enabled) + return 0; switch (type) { case SDHCI_TIMING_MMC_HS200: - case SDHCI_TIMING_MMC_HS400: case SDHCI_TIMING_UHS_SDR104: case SDHCI_TIMING_UHS_SDR82: - max = 128; + num_iter = 128; flag = (2 << 13); // 128 iterations. break; case SDHCI_TIMING_UHS_SDR50: - case SDHCI_TIMING_UHS_DDR50: - case SDHCI_TIMING_MMC_HS102: - max = 256; + case SDHCI_TIMING_UHS_DDR50: // HW tuning is not supported on DDR modes. But it sets tap to 0 which is proper. + case SDHCI_TIMING_MMC_HS100: + num_iter = 256; flag = (4 << 13); // 256 iterations. break; + case SDHCI_TIMING_MMC_HS400: case SDHCI_TIMING_UHS_SDR12: case SDHCI_TIMING_UHS_SDR25: return 1; +#ifdef BDK_SDMMC_UHS_DDR200_SUPPORT + case SDHCI_TIMING_UHS_DDR200: + return sdmmc_tuning_execute_ddr200(sdmmc); +#endif + default: return 0; } - sdmmc->regs->ventunctl1 = 0; // step_size 1. + sdmmc->regs->ventunctl1 = 0; // step_size 1. + sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFF1FFF) | flag; // Tries. + sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFFE03F) | (1 << 6); // 1x Multiplier. + sdmmc->regs->ventunctl0 |= SDHCI_TEGRA_TUNING_TAP_HW_UPDATED; - sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFF1FFF) | flag; // Tries. - sdmmc->regs->ventunctl0 = (sdmmc->regs->ventunctl0 & 0xFFFFE03F) | (1 << 6); // 1x Multiplier. - sdmmc->regs->ventunctl0 |= TEGRA_MMC_VNDR_TUN_CTRL0_TAP_VAL_UPDATED_BY_HW; sdmmc->regs->hostctl2 |= SDHCI_CTRL_EXEC_TUNING; - for (u32 i = 0; i < max; i++) + for (u32 i = 0; i < num_iter; i++) { - _sdmmc_tuning_execute_once(sdmmc, cmd); + _sdmmc_tuning_execute_once(sdmmc, cmd, HW_TAP_TUNING); + if (!(sdmmc->regs->hostctl2 & SDHCI_CTRL_EXEC_TUNING)) break; } @@ -734,14 +852,15 @@ static int _sdmmc_enable_internal_clock(sdmmc_t *sdmmc) sdmmc->regs->hostctl2 &= ~SDHCI_CTRL_PRESET_VAL_EN; sdmmc->regs->clkcon &= ~SDHCI_PROG_CLOCK_MODE; + // Enable 32/64bit addressing if used (sysad. if blkcnt it fallbacks to 16bit). sdmmc->regs->hostctl2 |= SDHCI_HOST_VERSION_4_EN; - if (!(sdmmc->regs->capareg & SDHCI_CAN_64BIT)) + if (!(sdmmc->regs->capareg & SDHCI_CAP_64BIT)) return 0; - sdmmc->regs->hostctl2 |= SDHCI_ADDRESSING_64BIT_EN; - sdmmc->regs->hostctl &= ~SDHCI_CTRL_DMA_MASK; - sdmmc->regs->timeoutcon = (sdmmc->regs->timeoutcon & 0xF0) | 0xE; + sdmmc->regs->hostctl2 |= SDHCI_ADDRESSING_64BIT_EN; + sdmmc->regs->hostctl &= ~SDHCI_CTRL_DMA_MASK; // Use SDMA. Host V4 enabled so adma address regs in use. + sdmmc->regs->timeoutcon = (sdmmc->regs->timeoutcon & 0xF0) | 14; // TMCLK * 2^27. return 1; } @@ -766,8 +885,8 @@ static int _sdmmc_autocal_config_offset(sdmmc_t *sdmmc, u32 power) { if (!sdmmc->t210b01) { - off_pd = 123; - off_pu = 123; + off_pd = 0x7B; // -5. + off_pu = 0x7B; // -5. } else { @@ -779,7 +898,7 @@ static int _sdmmc_autocal_config_offset(sdmmc_t *sdmmc, u32 power) { if (!sdmmc->t210b01) { - off_pd = 125; + off_pd = 0x7D; // -3. off_pu = 0; } } @@ -806,12 +925,12 @@ static void _sdmmc_mask_interrupts(sdmmc_t *sdmmc) sdmmc->regs->norintstsen &= ~(SDHCI_INT_DMA_END | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE); } -static int _sdmmc_check_mask_interrupt(sdmmc_t *sdmmc, u16 *pout, u16 mask) +static u32 _sdmmc_check_mask_interrupt(sdmmc_t *sdmmc, u16 *pout, u16 mask) { u16 norintsts = sdmmc->regs->norintsts; u16 errintsts = sdmmc->regs->errintsts; -DPRINTF("norintsts %08X, errintsts %08X\n", norintsts, errintsts); + DPRINTF("norintsts %08X, errintsts %08X\n", norintsts, errintsts); if (pout) *pout = norintsts; @@ -820,7 +939,7 @@ DPRINTF("norintsts %08X, errintsts %08X\n", norintsts, errintsts); if (norintsts & SDHCI_INT_ERROR) { #ifdef ERROR_EXTRA_PRINTING - EPRINTFARGS("SDMMC: norintsts %08X, errintsts %08X\n", norintsts, errintsts); + EPRINTFARGS("SDMMC%d: norintsts %08X, errintsts %08X\n", sdmmc->id + 1, norintsts, errintsts); #endif sdmmc->regs->errintsts = errintsts; return SDMMC_MASKINT_ERROR; @@ -841,12 +960,12 @@ static int _sdmmc_wait_response(sdmmc_t *sdmmc) u32 timeout = get_tmr_ms() + 2000; while (true) { - int result = _sdmmc_check_mask_interrupt(sdmmc, NULL, SDHCI_INT_RESPONSE); + u32 result = _sdmmc_check_mask_interrupt(sdmmc, NULL, SDHCI_INT_RESPONSE); if (result == SDMMC_MASKINT_MASKED) break; if (result != SDMMC_MASKINT_NOERROR || get_tmr_ms() > timeout) { - _sdmmc_reset(sdmmc); + _sdmmc_reset_cmd_data(sdmmc); return 0; } } @@ -896,11 +1015,11 @@ int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp) should_disable_sd_clock = true; sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; _sdmmc_commit_changes(sdmmc); - usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor); + usleep((8 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock); // Wait 8 cycles. } int result = _sdmmc_stop_transmission_inner(sdmmc, rsp); - usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor); + usleep((8 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock); // Wait 8 cycles. if (should_disable_sd_clock) sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; @@ -908,7 +1027,7 @@ int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp) return result; } -static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req) +static int _sdmmc_config_sdma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req) { if (!req->blksize || !req->num_sectors) return 0; @@ -925,19 +1044,19 @@ static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req) sdmmc->regs->admaaddr = admaaddr; sdmmc->regs->admaaddr_hi = 0; - sdmmc->dma_addr_next = (admaaddr + 0x80000) & 0xFFF80000; + sdmmc->dma_addr_next = ALIGN_DOWN((admaaddr + SZ_512K), SZ_512K); - sdmmc->regs->blksize = req->blksize | 0x7000; // DMA 512KB (Detects A18 carry out). - sdmmc->regs->blkcnt = blkcnt; + sdmmc->regs->blksize = req->blksize | (7u << 12); // SDMA DMA 512KB Boundary (Detects A18 carry out). + sdmmc->regs->blkcnt = blkcnt; if (blkcnt_out) *blkcnt_out = blkcnt; - u32 trnmode = SDHCI_TRNS_DMA; + u32 trnmode = SDHCI_TRNS_DMA | SDHCI_TRNS_RTYPE_R1; - // Set mulitblock request. + // Set multiblock request. if (req->is_multi_block) - trnmode = SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_DMA; + trnmode |= SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN; // Set request direction. if (!req->is_write) @@ -954,7 +1073,7 @@ static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req) return 1; } -static int _sdmmc_update_dma(sdmmc_t *sdmmc) +static int _sdmmc_update_sdma(sdmmc_t *sdmmc) { u16 blkcnt = 0; do @@ -963,13 +1082,13 @@ static int _sdmmc_update_dma(sdmmc_t *sdmmc) u32 timeout = get_tmr_ms() + 1500; do { - int result = 0; + u32 result = SDMMC_MASKINT_MASKED; while (true) { u16 intr = 0; result = _sdmmc_check_mask_interrupt(sdmmc, &intr, SDHCI_INT_DATA_END | SDHCI_INT_DMA_END); - if (result < 0) + if (result != SDMMC_MASKINT_MASKED) break; if (intr & SDHCI_INT_DATA_END) @@ -980,21 +1099,24 @@ static int _sdmmc_update_dma(sdmmc_t *sdmmc) // Update DMA. sdmmc->regs->admaaddr = sdmmc->dma_addr_next; sdmmc->regs->admaaddr_hi = 0; - sdmmc->dma_addr_next += 0x80000; + sdmmc->dma_addr_next += SZ_512K; } } + if (result != SDMMC_MASKINT_NOERROR) { #ifdef ERROR_EXTRA_PRINTING - EPRINTFARGS("%08X!", result); + EPRINTFARGS("SDMMC%d: int error!", sdmmc->id + 1); #endif - _sdmmc_reset(sdmmc); + _sdmmc_reset_cmd_data(sdmmc); + return 0; } } while (get_tmr_ms() < timeout); } while (sdmmc->regs->blkcnt != blkcnt); - _sdmmc_reset(sdmmc); + _sdmmc_reset_cmd_data(sdmmc); + return 0; } @@ -1008,16 +1130,16 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_ bool is_data_present = false; if (req) { - if (!_sdmmc_config_dma(sdmmc, &blkcnt, req)) + if (!_sdmmc_config_sdma(sdmmc, &blkcnt, req)) { #ifdef ERROR_EXTRA_PRINTING - EPRINTF("SDMMC: DMA Wrong cfg!"); + EPRINTFARGS("SDMMC%d: DMA Wrong cfg!", sdmmc->id + 1); #endif return 0; } // Flush cache before starting the transfer. - bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); + bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLEAN_WAY, false); is_data_present = true; } @@ -1027,7 +1149,7 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_ if (!_sdmmc_send_cmd(sdmmc, cmd, is_data_present)) { #ifdef ERROR_EXTRA_PRINTING - EPRINTFARGS("SDMMC: Wrong Response type %08X!", cmd->rsp_type); + EPRINTFARGS("SDMMC%d: Wrong Response type %08X!", sdmmc->id + 1, cmd->rsp_type); #endif return 0; } @@ -1035,9 +1157,9 @@ 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) - EPRINTF("SDMMC: Transfer timeout!"); + EPRINTFARGS("SDMMC%d: Transfer timeout!", sdmmc->id + 1); #endif -DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result, + DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result, sdmmc->regs->rspreg0, sdmmc->regs->rspreg1, sdmmc->regs->rspreg2, sdmmc->regs->rspreg3); if (result) { @@ -1047,15 +1169,15 @@ DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result, result = _sdmmc_cache_rsp(sdmmc, sdmmc->rsp, 0x10, cmd->rsp_type); #ifdef ERROR_EXTRA_PRINTING if (!result) - EPRINTF("SDMMC: Unknown response type!"); + EPRINTFARGS("SDMMC%d: Unknown response type!", sdmmc->id + 1); #endif } if (req && result) { - result = _sdmmc_update_dma(sdmmc); + result = _sdmmc_update_sdma(sdmmc); #ifdef ERROR_EXTRA_PRINTING if (!result) - EPRINTF("SDMMC: DMA Update failed!"); + EPRINTFARGS("SDMMC%d: DMA Update failed!", sdmmc->id + 1); #endif } } @@ -1066,8 +1188,8 @@ DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result, { if (req) { - // Flush cache after transfer. - bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); + // Invalidate cache after transfer. + bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY, false); if (blkcnt_out) *blkcnt_out = blkcnt; @@ -1081,7 +1203,7 @@ DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result, result = _sdmmc_wait_card_busy(sdmmc); #ifdef ERROR_EXTRA_PRINTING if (!result) - EPRINTF("SDMMC: Busy timeout!"); + EPRINTFARGS("SDMMC%d: Busy timeout!", sdmmc->id + 1); #endif return result; } @@ -1149,12 +1271,11 @@ static int _sdmmc_config_sdmmc1(bool t210b01) // Configure SD card detect. PINMUX_AUX(PINMUX_AUX_GPIO_PZ1) = PINMUX_INPUT_ENABLE | PINMUX_PULL_UP | 2; // GPIO control, pull up. APB_MISC(APB_MISC_GP_VGPIO_GPIO_MUX_SEL) = 0; - gpio_config(GPIO_PORT_Z, GPIO_PIN_1, GPIO_MODE_GPIO); - gpio_output_enable(GPIO_PORT_Z, GPIO_PIN_1, GPIO_OUTPUT_DISABLE); + gpio_direction_input(GPIO_PORT_Z, GPIO_PIN_1); usleep(100); // Check if SD card is inserted. - if(!sdmmc_get_sd_inserted()) + if (!sdmmc_get_sd_inserted()) return 0; /* @@ -1170,6 +1291,7 @@ static int _sdmmc_config_sdmmc1(bool t210b01) APB_MISC(APB_MISC_GP_SDMMC1_CLK_LPBK_CONTROL) = 1; // Configure SDMMC1 CLK pinmux, based on state and SoC type. + PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) &= ~PINMUX_SCHMT; if (PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) != (PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | PINMUX_PULL_DOWN)) // Check if CLK pad is already configured. PINMUX_AUX(PINMUX_AUX_SDMMC1_CLK) = PINMUX_DRIVE_2X | PINMUX_INPUT_ENABLE | (t210b01 ? PINMUX_PULL_NONE : PINMUX_PULL_DOWN); @@ -1185,20 +1307,20 @@ 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; + usleep(1000); PMC(APBDEV_PMC_NO_IOPOWER) &= ~(PMC_NO_IOPOWER_SDMMC1_IO_EN); (void)PMC(APBDEV_PMC_NO_IOPOWER); // Commit write. + // Set enable SD card power. + 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; (void)PMC(APBDEV_PMC_PWR_DET_VAL); // Commit write. - // Set enable SD card power. - PINMUX_AUX(PINMUX_AUX_DMIC3_CLK) = PINMUX_PULL_DOWN | 2; // Pull down. - gpio_config(GPIO_PORT_E, GPIO_PIN_4, GPIO_MODE_GPIO); - gpio_write(GPIO_PORT_E, GPIO_PIN_4, GPIO_HIGH); - gpio_output_enable(GPIO_PORT_E, GPIO_PIN_4, GPIO_OUTPUT_ENABLE); - usleep(10000); - // Enable SD card IO power. max7762x_regulator_set_voltage(REGULATOR_LDO2, 3300000); max7762x_regulator_enable(REGULATOR_LDO2, true); @@ -1235,7 +1357,7 @@ static void _sdmmc_config_emmc(u32 id, bool t210b01) APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) &= 0xF8003FFF; // Set default pad cfg. if (t210b01) - APB_MISC(APB_MISC_GP_EMMC4_PAD_PUPD_CFGPADCTRL) &= 0xFFBFFFF9; // Unset CMD/CLK/DQS powedown. + APB_MISC(APB_MISC_GP_EMMC4_PAD_PUPD_CFGPADCTRL) &= 0xFFBFFFF9; // Unset CMD/CLK/DQS weak pull up/down. // Enable schmitt trigger. APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) |= 1; (void)APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL); // Commit write. @@ -1243,15 +1365,15 @@ static void _sdmmc_config_emmc(u32 id, bool t210b01) } } -int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int powersave_enable) +int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type) { u32 clock; u16 divisor; u8 vref_sel = 7; - const u32 trim_values_t210[] = { 2, 8, 3, 8 }; - const u32 trim_values_t210b01[] = { 14, 13, 15, 13 }; - const u32 *trim_values = sdmmc->t210b01 ? trim_values_t210b01 : trim_values_t210; + const u8 trim_values_t210[4] = { 2, 8, 3, 8 }; + const u8 trim_values_t210b01[4] = { 14, 13, 15, 13 }; + const u8 *trim_values; if (id > SDMMC_4 || id == SDMMC_3) return 0; @@ -1263,6 +1385,8 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int p sdmmc->clock_stopped = 1; sdmmc->t210b01 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01; + trim_values = sdmmc->t210b01 ? trim_values_t210b01 : trim_values_t210; + // Do specific SDMMC HW configuration. switch (id) { @@ -1298,11 +1422,10 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int p sdmmc->clock_stopped = 0; // Set default pad IO trimming configuration. - sdmmc->regs->iospare |= 0x80000; // Enable muxing. - sdmmc->regs->veniotrimctl &= 0xFFFFFFFB; // Set Band Gap VREG to supply DLL. - sdmmc->regs->venclkctl = (sdmmc->regs->venclkctl & 0xE0FFFFFB) | (trim_values[sdmmc->id] << 24); - sdmmc->regs->sdmemcmppadctl = - (sdmmc->regs->sdmemcmppadctl & TEGRA_MMC_SDMEMCOMPPADCTRL_COMP_VREF_SEL_MASK) | vref_sel; + sdmmc->regs->iospare |= BIT(19); // Enable 1 cycle delayed cmd_oen. + sdmmc->regs->veniotrimctl &= ~BIT(2); // Set Band Gap VREG to supply DLL. + sdmmc->regs->venclkctl = (sdmmc->regs->venclkctl & 0xE0FFFFFB) | ((u32)trim_values[sdmmc->id] << 24); + sdmmc->regs->sdmemcmppadctl = (sdmmc->regs->sdmemcmppadctl & ~SDHCI_TEGRA_PADCTRL_VREF_SEL_MASK) | vref_sel; // Configure auto calibration values. if (!_sdmmc_autocal_config_offset(sdmmc, power)) @@ -1319,7 +1442,7 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int p if (sdmmc_setup_clock(sdmmc, type)) { - sdmmc_card_clock_powersave(sdmmc, powersave_enable); + sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_DISABLE); _sdmmc_card_clock_enable(sdmmc); _sdmmc_commit_changes(sdmmc); @@ -1405,11 +1528,11 @@ int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *b should_disable_sd_clock = 1; sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN; _sdmmc_commit_changes(sdmmc); - usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor); + usleep((8 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock); // Wait 8 cycles. } int result = _sdmmc_execute_cmd_inner(sdmmc, cmd, req, blkcnt_out); - usleep((8000 + sdmmc->divisor - 1) / sdmmc->divisor); + usleep((8 * 1000 + sdmmc->card_clock - 1) / sdmmc->card_clock); // Wait 8 cycles. if (should_disable_sd_clock) sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN; @@ -1419,10 +1542,7 @@ int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *b int sdmmc_enable_low_voltage(sdmmc_t *sdmmc) { - if(sdmmc->id != SDMMC_1) - return 0; - - if (!sdmmc_setup_clock(sdmmc, SDHCI_TIMING_UHS_SDR12)) + if (sdmmc->id != SDMMC_1) return 0; _sdmmc_commit_changes(sdmmc); diff --git a/bdk/storage/sdmmc_driver.h b/bdk/storage/sdmmc_driver.h index 696ce4d..ee62eaf 100644 --- a/bdk/storage/sdmmc_driver.h +++ b/bdk/storage/sdmmc_driver.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2019 CTCaer + * Copyright (c) 2018-2023 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -22,21 +22,16 @@ #include /*! SDMMC controller IDs. */ -#define SDMMC_1 0 -#define SDMMC_2 1 -#define SDMMC_3 2 -#define SDMMC_4 3 +#define SDMMC_1 0 // Version 4.00. +#define SDMMC_2 1 // Version 5.0 + SW CQE + Enhanced Strobe. +#define SDMMC_3 2 // Version 4.00. +#define SDMMC_4 3 // Version 5.0 + SW CQE + Enhanced Strobe. /*! SDMMC power types. */ #define SDMMC_POWER_OFF 0 #define SDMMC_POWER_1_8 1 #define SDMMC_POWER_3_3 2 -/*! SDMMC bus widths. */ -#define SDMMC_BUS_WIDTH_1 0 -#define SDMMC_BUS_WIDTH_4 1 -#define SDMMC_BUS_WIDTH_8 2 - /*! SDMMC response types. */ #define SDMMC_RSP_TYPE_0 0 #define SDMMC_RSP_TYPE_1 1 @@ -45,131 +40,203 @@ #define SDMMC_RSP_TYPE_4 4 #define SDMMC_RSP_TYPE_5 5 +/*! SDMMC bus widths. */ +#define SDMMC_BUS_WIDTH_1 0 +#define SDMMC_BUS_WIDTH_4 1 +#define SDMMC_BUS_WIDTH_8 2 + /*! SDMMC mask interrupt status. */ #define SDMMC_MASKINT_MASKED 0 -#define SDMMC_MASKINT_NOERROR -1 -#define SDMMC_MASKINT_ERROR -2 +#define SDMMC_MASKINT_NOERROR 1 +#define SDMMC_MASKINT_ERROR 2 -/*! SDMMC present state. */ -#define SDHCI_CMD_INHIBIT 0x1 -#define SDHCI_DATA_INHIBIT 0x2 -#define SDHCI_DOING_WRITE 0x100 -#define SDHCI_DOING_READ 0x200 -#define SDHCI_SPACE_AVAILABLE 0x400 -#define SDHCI_DATA_AVAILABLE 0x800 -#define SDHCI_CARD_PRESENT 0x10000 -#define SDHCI_CD_STABLE 0x20000 -#define SDHCI_CD_LVL 0x40000 -#define SDHCI_WRITE_PROTECT 0x80000 +/*! SDMMC present state. 0x24. */ +#define SDHCI_CMD_INHIBIT BIT(0) +#define SDHCI_DATA_INHIBIT BIT(1) +#define SDHCI_DAT_LINE_ACTIVE BIT(2) +#define SDHCI_RETUNING_REQUEST BIT(3) +#define SDHCI_EMMC_LINE_LVL_MASK (0xFU << 4) +#define SDHCI_DATA_4_LVL BIT(4) // eMMC only. +#define SDHCI_DATA_5_LVL BIT(5) // eMMC only. +#define SDHCI_DATA_6_LVL BIT(6) // eMMC only. +#define SDHCI_DATA_7_LVL BIT(7) // eMMC only. +#define SDHCI_DOING_WRITE BIT(8) +#define SDHCI_DOING_READ BIT(9) // SD only. +#define SDHCI_SPACE_AVAILABLE BIT(10) // Write buffer empty. +#define SDHCI_DATA_AVAILABLE BIT(11) // Read buffer has data. +#define SDHCI_CARD_PRESENT BIT(16) +#define SDHCI_CD_STABLE BIT(17) +#define SDHCI_CD_LVL BIT(18) +#define SDHCI_WRITE_PROTECT BIT(19) #define SDHCI_DATA_LVL_MASK 0xF00000 -#define SDHCI_DATA_0_LVL_MASK 0x100000 -#define SDHCI_CMD_LVL 0x1000000 +#define SDHCI_DATA_0_LVL BIT(20) +#define SDHCI_DATA_1_LVL BIT(21) +#define SDHCI_DATA_2_LVL BIT(22) +#define SDHCI_DATA_3_LVL BIT(23) +#define SDHCI_CMD_LVL BIT(24) -/*! SDMMC transfer mode. */ -#define SDHCI_TRNS_DMA 0x01 -#define SDHCI_TRNS_BLK_CNT_EN 0x02 -#define SDHCI_TRNS_AUTO_CMD12 0x04 -#define SDHCI_TRNS_AUTO_CMD23 0x08 -#define SDHCI_TRNS_AUTO_SEL 0x0C -#define SDHCI_TRNS_WRITE 0x00 -#define SDHCI_TRNS_READ 0x10 -#define SDHCI_TRNS_MULTI 0x20 +/*! SDMMC transfer mode. 0x0C. */ +#define SDHCI_TRNS_DMA BIT(0) +#define SDHCI_TRNS_BLK_CNT_EN BIT(1) +#define SDHCI_TRNS_AUTO_CMD12 (1U << 2) +#define SDHCI_TRNS_AUTO_CMD23 (2U << 2) +#define SDHCI_TRNS_WRITE (0U << 4) +#define SDHCI_TRNS_READ BIT(4) +#define SDHCI_TRNS_MULTI BIT(5) +#define SDHCI_TRNS_RTYPE_R1 (0U << 6) +#define SDHCI_TRNS_RTYPE_R5 BIT(6) +#define SDHCI_TRNS_RSP_ERR_CHK BIT(7) +#define SDHCI_TRNS_RSP_INT_DIS BIT(8) -/*! SDMMC command. */ +/*! SDMMC command. 0x0E. */ #define SDHCI_CMD_RESP_MASK 0x3 #define SDHCI_CMD_RESP_NO_RESP 0x0 #define SDHCI_CMD_RESP_LEN136 0x1 #define SDHCI_CMD_RESP_LEN48 0x2 #define SDHCI_CMD_RESP_LEN48_BUSY 0x3 -#define SDHCI_CMD_CRC 0x08 -#define SDHCI_CMD_INDEX 0x10 -#define SDHCI_CMD_DATA 0x20 -#define SDHCI_CMD_ABORTCMD 0xC0 +#define SDHCI_CMD_CRC BIT(3) +#define SDHCI_CMD_INDEX BIT(4) +#define SDHCI_CMD_DATA BIT(5) +#define SDHCI_CMD_TYPE_NORMAL (0U << 6) +#define SDHCI_CMD_TYPE_SUSPEND (1U << 6) +#define SDHCI_CMD_TYPE_RESUME (2U << 6) +#define SDHCI_CMD_TYPE_ABORT (3U << 6) +#define SDHCI_CMD_IDX(cmd) ((cmd) << 8) -/*! SDMMC host control. */ -#define SDHCI_CTRL_LED 0x01 -#define SDHCI_CTRL_4BITBUS 0x02 -#define SDHCI_CTRL_HISPD 0x04 -#define SDHCI_CTRL_DMA_MASK 0x18 -#define SDHCI_CTRL_SDMA 0x00 -#define SDHCI_CTRL_ADMA1 0x08 -#define SDHCI_CTRL_ADMA32 0x10 -#define SDHCI_CTRL_ADMA64 0x18 -#define SDHCI_CTRL_8BITBUS 0x20 -#define SDHCI_CTRL_CDTEST_INS 0x40 -#define SDHCI_CTRL_CDTEST_EN 0x80 -/*! SDMMC host control 2. */ -#define SDHCI_CTRL_UHS_MASK 0xFFF8 -#define SDHCI_CTRL_VDD_180 8 -#define SDHCI_CTRL_DRV_TYPE_B 0x00 -#define SDHCI_CTRL_DRV_TYPE_A 0x10 -#define SDHCI_CTRL_DRV_TYPE_C 0x20 -#define SDHCI_CTRL_DRV_TYPE_D 0x30 -#define SDHCI_CTRL_EXEC_TUNING 0x40 -#define SDHCI_CTRL_TUNED_CLK 0x80 -#define SDHCI_HOST_VERSION_4_EN 0x1000 -#define SDHCI_ADDRESSING_64BIT_EN 0x2000 -#define SDHCI_CTRL_PRESET_VAL_EN 0x8000 +/*! SDMMC host control. 0x28. */ +#define SDHCI_CTRL_LED BIT(0) +#define SDHCI_CTRL_4BITBUS BIT(1) // SD only. +#define SDHCI_CTRL_HISPD BIT(2) // SD only. +#define SDHCI_CTRL_DMA_MASK (3U << 3) +#define SDHCI_CTRL_SDMA (0U << 3) +#define SDHCI_CTRL_ADMA1 (1U << 3) +#define SDHCI_CTRL_ADMA32 (2U << 3) +#define SDHCI_CTRL_ADMA64 (3U << 3) +#define SDHCI_CTRL_8BITBUS BIT(5) // eMMC only (or UHS-II). +#define SDHCI_CTRL_CDTEST_INS BIT(6) +#define SDHCI_CTRL_CDTEST_EN BIT(7) -/*! SDMMC power control. */ -#define SDHCI_POWER_ON 0x01 -#define SDHCI_POWER_180 0x0A -#define SDHCI_POWER_300 0x0C -#define SDHCI_POWER_330 0x0E -#define SDHCI_POWER_MASK 0xF1 +/*! SDMMC host control 2. 0x3E. */ +#define SDHCI_CTRL_UHS_MASK 0x7 +#define SDHCI_CTRL_VDD_180 BIT(3) +#define SDHCI_CTRL_DRV_TYPE_MASK (3U << 4) +#define SDHCI_CTRL_DRV_TYPE_B (0U << 4) +#define SDHCI_CTRL_DRV_TYPE_A (1U << 4) +#define SDHCI_CTRL_DRV_TYPE_C (2U << 4) +#define SDHCI_CTRL_DRV_TYPE_D (3U << 4) +#define SDHCI_CTRL_DRV_TYPE(type) ((type) << 4) +#define SDHCI_CTRL_EXEC_TUNING BIT(6) +#define SDHCI_CTRL_TUNED_CLK_SHIFT 7 +#define SDHCI_CTRL_TUNED_CLK BIT(7) +#define SDHCI_HOST_VERSION_4_EN BIT(12) +#define SDHCI_ADDRESSING_64BIT_EN BIT(13) +#define SDHCI_CTRL_PRESET_VAL_EN BIT(15) -// /*! SDMMC max current. */ -// #define SDHCI_MAX_CURRENT_330_MASK 0xFF -// #define SDHCI_MAX_CURRENT_180_MASK 0xFF0000 -// #define SDHCI_MAX_CURRENT_MULTIPLIER 4 +/*! SDMMC power control. 0x29. */ +#define SDHCI_POWER_ON BIT(0) +#define SDHCI_POWER_180 (5U << 1) +#define SDHCI_POWER_300 (6U << 1) +#define SDHCI_POWER_330 (7U << 1) +#define SDHCI_POWER_MASK 0xF1 // UHS-II only. -/*! SDMMC clock control. */ -#define SDHCI_DIVIDER_SHIFT 8 -#define SDHCI_DIVIDER_HI_SHIFT 6 -#define SDHCI_DIV_MASK 0xFF00 -#define SDHCI_DIV_HI_MASK 0xC0 -#define SDHCI_PROG_CLOCK_MODE 0x20 -#define SDHCI_CLOCK_CARD_EN 0x4 -#define SDHCI_CLOCK_INT_STABLE 0x2 -#define SDHCI_CLOCK_INT_EN 0x1 +/*! SDMMC clock control. 0x2C. */ +#define SDHCI_CLOCK_INT_EN BIT(0) // Internal Clock. +#define SDHCI_CLOCK_INT_STABLE BIT(1) // Internal Clock Stable. +#define SDHCI_CLOCK_CARD_EN BIT(2) +#define SDHCI_PROG_CLOCK_MODE BIT(5) +#define SDHCI_DIV_HI_SHIFT 6 +#define SDHCI_DIV_HI_MASK (3U << SDHCI_DIV_HI_SHIFT) +#define SDHCI_DIV_LO_SHIFT 8 +#define SDHCI_DIV_MASK (0xFFU << SDHCI_DIV_LO_SHIFT) -/*! SDMMC software reset. */ -#define SDHCI_RESET_ALL 0x01 -#define SDHCI_RESET_CMD 0x02 -#define SDHCI_RESET_DATA 0x04 -/*! SDMMC interrupt status and control. */ -#define SDHCI_INT_RESPONSE 0x1 -#define SDHCI_INT_DATA_END 0x2 -#define SDHCI_INT_BLK_GAP 0x4 -#define SDHCI_INT_DMA_END 0x8 -#define SDHCI_INT_SPACE_AVAIL 0x10 -#define SDHCI_INT_DATA_AVAIL 0x20 -#define SDHCI_INT_CARD_INSERT 0x40 -#define SDHCI_INT_CARD_REMOVE 0x80 -#define SDHCI_INT_CARD_INT 0x100 -#define SDHCI_INT_RETUNE 0x1000 -#define SDHCI_INT_CQE 0x4000 -#define SDHCI_INT_ERROR 0x8000 +/*! SDMMC software reset. 0x2F. */ +#define SDHCI_RESET_ALL BIT(0) +#define SDHCI_RESET_CMD BIT(1) +#define SDHCI_RESET_DATA BIT(2) -/*! SDMMC error interrupt status and control. */ -#define SDHCI_ERR_INT_TIMEOUT 0x1 -#define SDHCI_ERR_INT_CRC 0x2 -#define SDHCI_ERR_INT_END_BIT 0x4 -#define SDHCI_ERR_INT_INDEX 0x8 -#define SDHCI_ERR_INT_DATA_TIMEOUT 0x10 -#define SDHCI_ERR_INT_DATA_CRC 0x20 -#define SDHCI_ERR_INT_DATA_END_BIT 0x40 -#define SDHCI_ERR_INT_BUS_POWER 0x80 -#define SDHCI_ERR_INT_AUTO_CMD_ERR 0x100 -#define SDHCI_ERR_INT_ADMA_ERROR 0x200 +/*! SDMMC interrupt status and control. 0x30/0x34. */ +#define SDHCI_INT_RESPONSE BIT(0) +#define SDHCI_INT_DATA_END BIT(1) +#define SDHCI_INT_BLK_GAP BIT(2) +#define SDHCI_INT_DMA_END BIT(3) +#define SDHCI_INT_SPACE_AVAIL BIT(4) // Write buffer empty. +#define SDHCI_INT_DATA_AVAIL BIT(5) // Read buffer has data. +#define SDHCI_INT_CARD_INSERT BIT(6) +#define SDHCI_INT_CARD_REMOVE BIT(7) +#define SDHCI_INT_CARD_INT BIT(8) +#define SDHCI_INT_RETUNE BIT(12) +#define SDHCI_INT_ERROR BIT(15) + +/*! SDMMC error interrupt status and control. 0x32/0x36. */ +#define SDHCI_ERR_INT_TIMEOUT BIT(0) +#define SDHCI_ERR_INT_CRC BIT(1) +#define SDHCI_ERR_INT_END_BIT BIT(2) +#define SDHCI_ERR_INT_INDEX BIT(3) +#define SDHCI_ERR_INT_DATA_TIMEOUT BIT(4) +#define SDHCI_ERR_INT_DATA_CRC BIT(5) +#define SDHCI_ERR_INT_DATA_END_BIT BIT(6) +#define SDHCI_ERR_INT_BUS_POWER BIT(7) +#define SDHCI_ERR_INT_AUTO_CMD12 BIT(8) +#define SDHCI_ERR_INT_ADMA BIT(9) +#define SDHCI_ERR_INT_TUNE BIT(10) +#define SDHCI_ERR_INT_RSP BIT(11) +#define SDHCI_ERR_INT_TARGET_RSP BIT(12) +#define SDHCI_ERR_INT_SPI BIT(13) +#define SDHCI_ERR_INT_VND_BOOT_TMO BIT(14) +#define SDHCI_ERR_INT_VND_BOOT_ACK BIT(15) #define SDHCI_ERR_INT_ALL_EXCEPT_ADMA_BUSPWR \ - (SDHCI_ERR_INT_AUTO_CMD_ERR | SDHCI_ERR_INT_DATA_END_BIT | \ - SDHCI_ERR_INT_DATA_CRC | SDHCI_ERR_INT_DATA_TIMEOUT | \ - SDHCI_ERR_INT_INDEX | SDHCI_ERR_INT_END_BIT | \ - SDHCI_ERR_INT_CRC | SDHCI_ERR_INT_TIMEOUT) + (SDHCI_ERR_INT_AUTO_CMD12 | SDHCI_ERR_INT_DATA_END_BIT | \ + SDHCI_ERR_INT_DATA_CRC | SDHCI_ERR_INT_DATA_TIMEOUT | \ + SDHCI_ERR_INT_INDEX | SDHCI_ERR_INT_END_BIT | \ + SDHCI_ERR_INT_CRC | SDHCI_ERR_INT_TIMEOUT) + +/*! Host Capability 1. 0x40. */ +#define SDHCI_CAP_TM_CLK_FREQ_MASK 0x3F +#define SDHCI_CAP_TM_UNIT_MHZ BIT(7) +#define SDHCI_CAP_BASE_CLK_FREQ_MASK (0xFFU << 8) +#define SDHCI_CAP_MAX_BLK_LEN_MASK (3U << 16) +#define SDHCI_CAP_EMMC_8BIT BIT(18) +#define SDHCI_CAP_ADMA2 BIT(19) +#define SDHCI_CAP_HISPD BIT(21) +#define SDHCI_CAP_SDMA BIT(22) +#define SDHCI_CAP_SUSPEND_RESUME BIT(23) +#define SDHCI_CAP_3_3_V BIT(24) +#define SDHCI_CAP_3_0_V BIT(25) +#define SDHCI_CAP_1_8_V BIT(26) +#define SDHCI_CAP_64BIT BIT(28) +#define SDHCI_CAP_ASYNC_INT BIT(29) +#define SDHCI_CAP_SLOT_TYPE_MASK (3U << 30) +#define SDHCI_CAP_SLOT_TYPE_REMOVABLE (0U << 30) +#define SDHCI_CAP_SLOT_TYPE_EMBEDDED (1U << 30) +#define SDHCI_CAP_SLOT_TYPE_SHARED (2U << 30) +#define SDHCI_CAP_SLOT_TYPE_UHS2 (3U << 30) + +/*! Host Capability 2. 0x44. */ +#define SDHCI_CAP_SDR50 BIT(0) +#define SDHCI_CAP_SDR5104 BIT(1) +#define SDHCI_CAP_DDR50 BIT(2) +#define SDHCI_CAP_UHS2 BIT(3) +#define SDHCI_CAP_DRV_TYPE_A BIT(4) +#define SDHCI_CAP_DRV_TYPE_C BIT(5) +#define SDHCI_CAP_DRV_TYPE_D BIT(6) +#define SDHCI_CAP_RSP_TIMER_CNT_MASK (0xFU << 8) +#define SDHCI_CAP_SDR50_TUNING BIT(13) +#define SDHCI_CAP_RSP_MODES_MASK (3U << 14) +#define SDHCI_CAP_CLK_MULT (0xFFU << 16) +#define SDHCI_CAP_ADMA3 BIT(27) +#define SDHCI_CAP_VDD2_1_8V BIT(28) + +/*! SDMMC max current. 0x48 */ +#define SDHCI_MAX_CURRENT_3_3_V_MASK (0xFFU << 0) +#define SDHCI_MAX_CURRENT_3_0_V_MASK (0xFFU << 8) +#define SDHCI_MAX_CURRENT_1_8_V_MASK (0xFFU << 16) +#define SDHCI_MAX_CURRENT_MULTIPLIER 4 + +/*! SDMMC max current. 0x4C */ +#define SDHCI_MAX_CURRENT_1_8_V_VDD2_MASK (0xFFU << 0) /*! SD bus speeds. */ #define UHS_SDR12_BUS_SPEED 0 @@ -193,11 +260,11 @@ #define SDHCI_TIMING_UHS_SDR25 9 #define SDHCI_TIMING_UHS_SDR50 10 #define SDHCI_TIMING_UHS_SDR104 11 -#define SDHCI_TIMING_UHS_SDR82 12 // SDR104 with a 163.2MHz -> 81.6MHz clock. -#define SDHCI_TIMING_UHS_DDR50 13 -#define SDHCI_TIMING_MMC_HS102 14 - -#define SDHCI_CAN_64BIT 0x10000000 +#define SDHCI_TIMING_UHS_DDR50 12 +// SDR104 with a 163.2MHz -> 81.6MHz clock. +#define SDHCI_TIMING_UHS_SDR82 13 // GC FPGA. Obsolete and Repurposed. MMC_HS50 -> SDR82. +#define SDHCI_TIMING_MMC_HS100 14 // GC ASIC. +#define SDHCI_TIMING_UHS_DDR200 15 /*! SDMMC Low power features. */ #define SDMMC_POWER_SAVE_DISABLE 0 @@ -206,12 +273,16 @@ /*! Helper for SWITCH command argument. */ #define SDMMC_SWITCH(mode, index, value) (((mode) << 24) | ((index) << 16) | ((value) << 8)) +#define HW_TAP_TUNING 0x100 +#define INVALID_TAP 0x100 +#define SAMPLING_WINDOW_SIZE_MIN 8 + /*! SDMMC controller context. */ typedef struct _sdmmc_t { t210_sdmmc_t *regs; u32 id; - u32 divisor; + u32 card_clock; u32 clock_stopped; int powersave_enabled; int manual_cal; @@ -249,13 +320,14 @@ int sdmmc_get_io_power(sdmmc_t *sdmmc); u32 sdmmc_get_bus_width(sdmmc_t *sdmmc); void sdmmc_set_bus_width(sdmmc_t *sdmmc, u32 bus_width); void sdmmc_save_tap_value(sdmmc_t *sdmmc); +void sdmmc_setup_drv_type(sdmmc_t *sdmmc, u32 type); int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type); void sdmmc_card_clock_powersave(sdmmc_t *sdmmc, int powersave_enable); int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type); int sdmmc_tuning_execute(sdmmc_t *sdmmc, u32 type, u32 cmd); int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp); bool sdmmc_get_sd_inserted(); -int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int powersave_enable); +int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type); void sdmmc_end(sdmmc_t *sdmmc); void sdmmc_init_cmd(sdmmc_cmd_t *cmdbuf, u16 cmd, u32 arg, u32 rsp_type, u32 check_busy); int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out); diff --git a/bdk/storage/sdmmc_t210.h b/bdk/storage/sdmmc_t210.h index 2c1b3a5..dfea7d5 100644 --- a/bdk/storage/sdmmc_t210.h +++ b/bdk/storage/sdmmc_t210.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2019 CTCaer + * Copyright (c) 2018-2023 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -18,92 +18,112 @@ #ifndef _SDMMC_T210_H_ #define _SDMMC_T210_H_ +#include #include -#define TEGRA_MMC_VNDR_TUN_CTRL0_TAP_VAL_UPDATED_BY_HW 0x20000 -#define TEGRA_MMC_DLLCAL_CFG_EN_CALIBRATE 0x80000000 -#define TEGRA_MMC_DLLCAL_CFG_STATUS_DLL_ACTIVE 0x80000000 -#define TEGRA_MMC_SDMEMCOMPPADCTRL_PAD_E_INPUT_PWRD 0x80000000 -#define TEGRA_MMC_SDMEMCOMPPADCTRL_COMP_VREF_SEL_MASK 0xFFFFFFF0 -#define TEGRA_MMC_AUTOCALCFG_AUTO_CAL_ENABLE 0x20000000 -#define TEGRA_MMC_AUTOCALCFG_AUTO_CAL_START 0x80000000 -#define TEGRA_MMC_AUTOCALSTS_AUTO_CAL_ACTIVE 0x80000000 +#define SDHCI_TEGRA_TUNING_TAP_HW_UPDATED BIT(17) +#define SDHCI_TEGRA_DLLCAL_CALIBRATE BIT(31) +#define SDHCI_TEGRA_DLLCAL_ACTIVE BIT(31) +#define SDHCI_TEGRA_PADCTRL_E_INPUT_PWRD BIT(31) +#define SDHCI_TEGRA_PADCTRL_VREF_SEL_MASK 0xF +#define SDHCI_TEGRA_AUTOCAL_SLW_OVERRIDE BIT(28) +#define SDHCI_TEGRA_AUTOCAL_ENABLE BIT(29) +#define SDHCI_TEGRA_AUTOCAL_START BIT(31) +#define SDHCI_TEGRA_AUTOCAL_ACTIVE BIT(31) typedef struct _t210_sdmmc_t { - vu32 sysad; - vu16 blksize; - vu16 blkcnt; - vu32 argument; - vu16 trnmod; - vu16 cmdreg; - vu32 rspreg0; - vu32 rspreg1; - vu32 rspreg2; - vu32 rspreg3; - vu32 bdata; - vu32 prnsts; - vu8 hostctl; - vu8 pwrcon; - vu8 blkgap; - vu8 wakcon; - vu16 clkcon; - vu8 timeoutcon; - vu8 swrst; - vu16 norintsts; - vu16 errintsts; - vu16 norintstsen; // Enable irq status. - vu16 errintstsen; // Enable irq status. - vu16 norintsigen; // Enable irq signal to LIC/GIC. - vu16 errintsigen; // Enable irq signal to LIC/GIC. - vu16 acmd12errsts; - vu16 hostctl2; - vu32 capareg; - vu32 capareg_1; - vu32 maxcurr; - vu8 rsvd0[4]; // 4C-4F reserved for more max current. - vu16 setacmd12err; - vu16 setinterr; - vu8 admaerr; - vu8 rsvd1[3]; // 55-57 reserved. - vu32 admaaddr; - vu32 admaaddr_hi; - vu8 rsvd2[156]; // 60-FB reserved. - vu16 slotintsts; - vu16 hcver; - vu32 venclkctl; - vu32 vensysswctl; - vu32 venerrintsts; - vu32 vencapover; - vu32 venbootctl; - vu32 venbootacktout; - vu32 venbootdattout; - vu32 vendebouncecnt; - vu32 venmiscctl; - vu32 maxcurrover; - vu32 maxcurrover_hi; - vu32 unk0[32]; // 0x12C - vu32 veniotrimctl; - vu32 vendllcalcfg; - vu32 vendllctl0; - vu32 vendllctl1; - vu32 vendllcalcfgsts; - vu32 ventunctl0; - vu32 ventunctl1; - vu32 ventunsts0; - vu32 ventunsts1; - vu32 venclkgatehystcnt; - vu32 venpresetval0; - vu32 venpresetval1; - vu32 venpresetval2; - vu32 sdmemcmppadctl; - vu32 autocalcfg; - vu32 autocalintval; - vu32 autocalsts; - vu32 iospare; - vu32 mcciffifoctl; - vu32 timeoutwcoal; - vu32 unk1; +/* 0x00 */ vu32 sysad; // sdma system address. +/* 0x04 */ vu16 blksize; +/* 0x06 */ vu16 blkcnt; +/* 0x08 */ vu32 argument; +/* 0x0C */ vu16 trnmod; +/* 0x0E */ vu16 cmdreg; +/* 0x10 */ vu32 rspreg0; +/* 0x14 */ vu32 rspreg1; +/* 0x18 */ vu32 rspreg2; +/* 0x1C */ vu32 rspreg3; +/* 0x20 */ vu32 bdata; // Buffer data port. +/* 0x24 */ vu32 prnsts; +/* 0x28 */ vu8 hostctl; +/* 0x29 */ vu8 pwrcon; +/* 0x2A */ vu8 blkgap; +/* 0x2B */ vu8 wakcon; +/* 0x2C */ vu16 clkcon; +/* 0x2E */ vu8 timeoutcon; +/* 0x2F */ vu8 swrst; +/* 0x30 */ vu16 norintsts; // Normal interrupt status. +/* 0x32 */ vu16 errintsts; // Error interrupt status. +/* 0x34 */ vu16 norintstsen; // Enable irq status. +/* 0x36 */ vu16 errintstsen; // Enable irq status. +/* 0x38 */ vu16 norintsigen; // Enable irq signal to LIC/GIC. +/* 0x3A */ vu16 errintsigen; // Enable irq signal to LIC/GIC. +/* 0x3C */ vu16 acmd12errsts; +/* 0x3E */ vu16 hostctl2; + +// CAP0: 0x376CD08C. +// 12 MHz timeout clock. 208 MHz max base clock. 512B max block length. 8-bit support. +// ADMA2 support. HS25 support. SDMA support. No suspend/resume support. 3.3/3.0/1.8V support. +// 64bit addressing for V3/V4 support. Async IRQ support. All report as removable. +/* 0x40 */ vu32 capareg; +// CAP1: 0x10002F73. +// SDR50/SDR104 support. No DDR50 support. Drive A/B/C/D support. +// Timer re-tuning info from other source. SDR50 requires re-tuning. +// Tuning uses timer and transfers should be 4MB limited. +// ADMA3 not supported. 1.8V VDD2 supported. +/* 0x44 */ vu32 capareg_hi; + +/* 0x48 */ vu32 maxcurr; // Get information by another method. Can be overriden via maxcurrover and maxcurrover_hi. +/* 0x4C */ vu32 maxcurr_hi; +/* 0x50 */ vu16 setacmd12err; // Force error in acmd12errsts. +/* 0x52 */ vu16 setinterr; +/* 0x54 */ vu8 admaerr; +/* 0x55 */ vu8 rsvd1[3]; // 55-57 reserved. +/* 0x58 */ vu32 admaaddr; +/* 0x5C */ vu32 admaaddr_hi; +/* 0x60 */ vu16 presets[11]; +/* 0x76 */ vu16 rsvd2; +/* 0x78 */ vu32 adma3addr; +/* 0x7C */ vu32 adma3addr_hi; +/* 0x80 */ vu8 uhs2[124]; // 80-FB UHS-II. +/* 0xFC */ vu16 slotintsts; +/* 0xFE */ vu16 hcver; // 0x303 (4.00). + +/* UHS-II range. Used for Vendor registers here */ +/* 0x100 */ vu32 venclkctl; +/* 0x104 */ vu32 vensysswctl; +/* 0x108 */ vu32 venerrintsts; +/* 0x10C */ vu32 vencapover; +/* 0x110 */ vu32 venbootctl; +/* 0x114 */ vu32 venbootacktout; +/* 0x118 */ vu32 venbootdattout; +/* 0x11C */ vu32 vendebouncecnt; +/* 0x120 */ vu32 venmiscctl; +/* 0x124 */ vu32 maxcurrover; +/* 0x128 */ vu32 maxcurrover_hi; +/* 0x12C */ vu32 unk0[32]; // 0x12C +/* 0x1AC */ vu32 veniotrimctl; +/* 0x1B0 */ vu32 vendllcalcfg; +/* 0x1B4 */ vu32 vendllctl0; +/* 0x1B8 */ vu32 vendllctl1; +/* 0x1BC */ vu32 vendllcalcfgsts; +/* 0x1C0 */ vu32 ventunctl0; +/* 0x1C4 */ vu32 ventunctl1; +/* 0x1C8 */ vu32 ventunsts0; +/* 0x1CC */ vu32 ventunsts1; +/* 0x1D0 */ vu32 venclkgatehystcnt; +/* 0x1D4 */ vu32 venpresetval0; +/* 0x1D8 */ vu32 venpresetval1; +/* 0x1DC */ vu32 venpresetval2; +/* 0x1E0 */ vu32 sdmemcmppadctl; +/* 0x1E4 */ vu32 autocalcfg; +/* 0x1E8 */ vu32 autocalintval; +/* 0x1EC */ vu32 autocalsts; +/* 0x1F0 */ vu32 iospare; +/* 0x1F4 */ vu32 mcciffifoctl; +/* 0x1F8 */ vu32 timeoutwcoal; } t210_sdmmc_t; +static_assert(sizeof(t210_sdmmc_t) == 0x1FC, "T210 SDMMC REG size is wrong!"); + #endif diff --git a/bdk/thermal/fan.c b/bdk/thermal/fan.c index 9e7a65e..6927fe4 100644 --- a/bdk/thermal/fan.c +++ b/bdk/thermal/fan.c @@ -1,7 +1,7 @@ /* * Fan driver for Nintendo Switch * - * Copyright (c) 2018-2021 CTCaer + * Copyright (c) 2018-2023 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, @@ -18,11 +18,14 @@ #include #include +#include +#include #include #include +#include #include +#include #include -#include void set_fan_duty(u32 duty) { @@ -37,18 +40,24 @@ void set_fan_duty(u32 duty) curr_duty = duty; - //! TODO: Add HOAG/AULA support. - u32 hw_type = fuse_read_hw_type(); - if (hw_type != FUSE_NX_HW_TYPE_ICOSA && - hw_type != FUSE_NX_HW_TYPE_IOWA) - return; - if (!fan_init) { // Fan tachometer. - PINMUX_AUX(PINMUX_AUX_CAM1_PWDN) = PINMUX_TRISTATE | PINMUX_INPUT_ENABLE | PINMUX_PULL_UP | 1; - gpio_config(GPIO_PORT_S, GPIO_PIN_7, GPIO_MODE_GPIO); - gpio_output_enable(GPIO_PORT_S, GPIO_PIN_7, GPIO_OUTPUT_DISABLE); + u32 pull_resistor = hw_get_chip_id() == GP_HIDREV_MAJOR_T210 ? PINMUX_PULL_UP : 0; + PINMUX_AUX(PINMUX_AUX_CAM1_PWDN) = PINMUX_TRISTATE | PINMUX_INPUT_ENABLE | pull_resistor | 1; + gpio_direction_input(GPIO_PORT_S, GPIO_PIN_7); + + // 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. @@ -68,8 +77,8 @@ void set_fan_duty(u32 duty) regulator_5v_disable(REGULATOR_5V_FAN); // Disable fan. - PINMUX_AUX(PINMUX_AUX_LCD_GPIO2) = - PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_TRISTATE | PINMUX_PULL_DOWN; // Set source to PWM1. + PINMUX_AUX(PINMUX_AUX_LCD_GPIO2) = PINMUX_INPUT_ENABLE | PINMUX_PARKED | + PINMUX_TRISTATE | PINMUX_PULL_DOWN; // Set source to PWM1. } else // Set PWM duty. { diff --git a/bdk/utils/btn.c b/bdk/utils/btn.c index ded903d..55ca67b 100644 --- a/bdk/utils/btn.c +++ b/bdk/utils/btn.c @@ -18,8 +18,8 @@ #include "btn.h" #include #include +#include #include -#include #include u8 btn_read() @@ -29,6 +29,7 @@ u8 btn_read() res |= BTN_VOL_DOWN; if (!gpio_read(GPIO_PORT_X, GPIO_PIN_6)) res |= BTN_VOL_UP; + // HOAG can use the GPIO. Icosa/Iowa/AULA cannot. Traces are there but they miss a resistor. if (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFSTAT) & MAX77620_ONOFFSTAT_EN0) res |= BTN_POWER; return res; diff --git a/bdk/utils/ini.c b/bdk/utils/ini.c index d388988..f886ecb 100644 --- a/bdk/utils/ini.c +++ b/bdk/utils/ini.c @@ -47,6 +47,9 @@ ini_sec_t *_ini_create_section(link_t *dst, ini_sec_t *csec, char *name, u8 type csec->name = strcpy_ns(buf + sizeof(ini_sec_t), name); csec->type = type; + // Initialize list. + list_init(&csec->kvs); + return csec; } @@ -54,11 +57,11 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir) { FIL fp; u32 lblen; - u32 pathlen = strlen(ini_path); u32 k = 0; + u32 pathlen = strlen(ini_path); ini_sec_t *csec = NULL; - char *lbuf = NULL; + char *lbuf = NULL; char *filelist = NULL; char *filename = (char *)malloc(256); @@ -102,7 +105,6 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir) lbuf = malloc(512); csec = _ini_create_section(dst, csec, "Unknown", INI_CHOICE); - list_init(&csec->kvs); do { @@ -120,7 +122,6 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir) _find_section_name(lbuf, lblen, ']'); csec = _ini_create_section(dst, csec, &lbuf[1], INI_CHOICE); - list_init(&csec->kvs); } else if (lblen > 1 && lbuf[0] == '{') // Create new caption. Support empty caption '{}'. { @@ -142,8 +143,8 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir) u32 i = _find_section_name(lbuf, lblen, '='); // Calculate total allocation size. - u32 klen = strlen(&lbuf[0]) + 1; - u32 vlen = strlen(&lbuf[i + 1]) + 1; + u32 klen = strlen(&lbuf[0]) + 1; + u32 vlen = strlen(&lbuf[i + 1]) + 1; char *buf = calloc(sizeof(ini_kv_t) + klen + vlen, 1); ini_kv_t *kv = (ini_kv_t *)buf; @@ -155,6 +156,8 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir) } } while (!f_eof(&fp)); + free(lbuf); + f_close(&fp); if (csec) @@ -165,23 +168,61 @@ int ini_parse(link_t *dst, char *ini_path, bool is_dir) } } while (is_dir); - free(lbuf); free(filename); free(filelist); return 1; } -char *ini_check_payload_section(ini_sec_t *cfg) +char *ini_check_special_section(ini_sec_t *cfg) { if (cfg == NULL) return NULL; LIST_FOREACH_ENTRY(ini_kv_t, kv, &cfg->kvs, link) { - if (!strcmp("payload", kv->key)) + if (!strcmp("l4t", kv->key)) + return ((kv->val[0] == '1') ? (char *)-1 : NULL); + else if (!strcmp("payload", kv->key)) return kv->val; } return NULL; } + +void ini_free(link_t *src) +{ + ini_sec_t *prev_sec = NULL; + + // Parse and free all ini sections. + LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, src, link) + { + ini_kv_t *prev_kv = NULL; + + // Free all ini key allocations if they exist. + LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link) + { + // Free previous key. + if (prev_kv) + free(prev_kv); + + // Set next key to free. + prev_kv = kv; + } + + // Free last key. + if (prev_kv) + free(prev_kv); + + // Free previous section. + if (prev_sec) + free(prev_sec); + + // Set next section to free. + prev_sec = ini_sec; + } + + // Free last section. + if (prev_sec) + free(prev_sec); +} diff --git a/bdk/utils/ini.h b/bdk/utils/ini.h index 571d19d..929a850 100644 --- a/bdk/utils/ini.h +++ b/bdk/utils/ini.h @@ -43,8 +43,9 @@ typedef struct _ini_sec_t u32 color; } ini_sec_t; -int ini_parse(link_t *dst, char *ini_path, bool is_dir); -char *ini_check_payload_section(ini_sec_t *cfg); +int ini_parse(link_t *dst, char *ini_path, bool is_dir); +char *ini_check_special_section(ini_sec_t *cfg); +void ini_free(link_t *src); #endif diff --git a/bdk/utils/list.h b/bdk/utils/list.h index ece5402..4d17261 100644 --- a/bdk/utils/list.h +++ b/bdk/utils/list.h @@ -28,16 +28,25 @@ /*! Iterate over all list links. */ #define LIST_FOREACH(iter, list) \ - for(link_t *iter = (list)->next; iter != (list); iter = iter->next) + for (link_t *iter = (list)->next; iter != (list); iter = iter->next) + +/*! Iterate over all list links backwards. */ +#define LIST_FOREACH_INVERSE(iter, list) \ + for (link_t *iter = (list)->prev; iter != (list); iter = iter->prev) /*! Safely iterate over all list links. */ #define LIST_FOREACH_SAFE(iter, list) \ - for(link_t *iter = (list)->next, *safe = iter->next; iter != (list); iter = safe, safe = iter->next) + for (link_t *iter = (list)->next, *safe = iter->next; iter != (list); iter = safe, safe = iter->next) /*! Iterate over all list members and make sure that the list has at least one entry. */ #define LIST_FOREACH_ENTRY(etype, iter, list, mn) \ if ((list)->next != (list)) \ - for(etype *iter = CONTAINER_OF((list)->next, etype, mn); &iter->mn != (list); iter = CONTAINER_OF(iter->mn.next, etype, mn)) + for (etype *iter = CONTAINER_OF((list)->next, etype, mn); &iter->mn != (list); iter = CONTAINER_OF(iter->mn.next, etype, mn)) + +/* Iterate over all list members backwards and make sure that the list has at least one entry. */ +#define LIST_FOREACH_ENTRY_INVERSE(type, iter, list, mn) \ + if ((list)->prev != (list)) \ + for (type *iter = CONTAINER_OF((list)->prev, type, mn); &iter->mn != (list); iter = CONTAINER_OF(iter->mn.prev, type, mn)) typedef struct _link_t { @@ -53,7 +62,7 @@ static inline void link_init(link_t *l) static inline int link_used(link_t *l) { - if(l->next == NULL) + if (l->next == NULL) return 1; return 0; } @@ -89,7 +98,7 @@ static inline void list_remove(link_t *l) static inline int list_empty(link_t *lh) { - if(lh->next == lh) + if (lh->next == lh) return 1; return 0; } diff --git a/bdk/utils/sprintf.c b/bdk/utils/sprintf.c index a5b8cef..87f1526 100644 --- a/bdk/utils/sprintf.c +++ b/bdk/utils/sprintf.c @@ -36,14 +36,24 @@ static void _s_puts(char *s) static void _s_putn(u32 v, int base, char fill, int fcnt) { - char buf[65]; - static const char digits[] = "0123456789ABCDEFghijklmnopqrstuvwxyz"; - char *p; - int c = fcnt; + static const char digits[] = "0123456789ABCDEF"; - if (base > 36) + char *p; + char buf[65]; + int c = fcnt; + bool negative = false; + + if (base != 10 && base != 16) return; + // Account for negative numbers. + if (base == 10 && v & 0x80000000) + { + negative = true; + v = (int)v * -1; + c--; + } + p = buf + 64; *p = 0; do @@ -53,9 +63,12 @@ static void _s_putn(u32 v, int base, char fill, int fcnt) v /= base; } while (v); + if (negative) + *--p = '-'; + if (fill != 0) { - while (c > 0) + while (c > 0 && p > buf) { *--p = fill; c--; @@ -73,9 +86,9 @@ void s_printf(char *out_buf, const char *fmt, ...) sout_buf = &out_buf; va_start(ap, fmt); - while(*fmt) + while (*fmt) { - if(*fmt == '%') + if (*fmt == '%') { fmt++; fill = 0; @@ -96,7 +109,7 @@ void s_printf(char *out_buf, const char *fmt, ...) fcnt -= '0'; } } - switch(*fmt) + switch (*fmt) { case 'c': _s_putc(va_arg(ap, u32)); @@ -140,9 +153,9 @@ void s_vprintf(char *out_buf, const char *fmt, va_list ap) sout_buf = &out_buf; - while(*fmt) + while (*fmt) { - if(*fmt == '%') + if (*fmt == '%') { fmt++; fill = 0; diff --git a/bdk/utils/sprintf.h b/bdk/utils/sprintf.h index 2fb863b..c523267 100644 --- a/bdk/utils/sprintf.h +++ b/bdk/utils/sprintf.h @@ -21,7 +21,7 @@ #include -void s_printf(char *out_buf, const char *fmt, ...); +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 diff --git a/bdk/utils/types.h b/bdk/utils/types.h index b1c2234..2609e9f 100644 --- a/bdk/utils/types.h +++ b/bdk/utils/types.h @@ -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, @@ -20,16 +20,6 @@ #include -#define ALWAYS_INLINE inline __attribute__((always_inline)) - - -#define COLOR_RED 0xFFE70000 -#define COLOR_ORANGE 0xFFFF8C00 -#define COLOR_YELLOW 0xFFFFFF40 -#define COLOR_GREEN 0xFF40FF00 -#define COLOR_BLUE 0xFF00DDFF -#define COLOR_VIOLET 0xFF8040FF - /* Types */ typedef signed char s8; typedef short s16; @@ -61,6 +51,15 @@ typedef unsigned long long uptr; typedef unsigned long uptr; #endif +#define ALWAYS_INLINE inline __attribute__((always_inline)) + +#define COLOR_RED 0xFFE70000 +#define COLOR_ORANGE 0xFFFF8C00 +#define COLOR_YELLOW 0xFFFFFF40 +#define COLOR_GREEN 0xFF40FF00 +#define COLOR_BLUE 0xFF00DDFF +#define COLOR_VIOLET 0xFF8040FF + /* Important */ #define false 0 #define true 1 @@ -112,7 +111,7 @@ typedef unsigned long uptr; #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)) + (((num) >> 8 ) & 0xff00) | (((num) << 24) & 0xff000000)) /* Bootloader/Nyx */ diff --git a/bdk/utils/util.c b/bdk/utils/util.c index b351038..5f00fe0 100644 --- a/bdk/utils/util.c +++ b/bdk/utils/util.c @@ -24,14 +24,13 @@ #include #include #include +#include #include #include #include #define USE_RTC_TIMER -extern volatile nyx_storage_t *nyx_str; - u8 bit_count(u32 val) { u8 cnt = 0; @@ -75,54 +74,131 @@ char *strcpy_ns(char *dst, char *src) return dst; } -u32 get_tmr_s() +// Approximate square root finder for a 64-bit number. +u64 sqrt64(u64 num) { - return RTC(APBDEV_RTC_SECONDS); + u64 base = 0; + u64 limit = num; + u64 square_root = 0; + + while (base <= limit) + { + u64 tmp_sqrt = (base + limit) / 2; + + if (tmp_sqrt * tmp_sqrt == num) { + square_root = tmp_sqrt; + break; + } + + if (tmp_sqrt * tmp_sqrt < num) + { + square_root = base; + base = tmp_sqrt + 1; + } + else + limit = tmp_sqrt - 1; + } + + return square_root; } -u32 get_tmr_ms() +#define TLONG_MAX ((long)(((unsigned long)(~0L)) >> 1)) +#define TLONG_MIN ((long)(~TLONG_MAX)) +#define ISSPACE(ch) ((ch >= '\t' && ch <= '\r') || (ch == ' ')) +#define ISDIGIT(ch) ( ch >= '0' && ch <= '9' ) +#define ISALPHA(ch) ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) +#define ISUPPER(ch) ( ch >= 'A' && ch <= 'Z' ) + +/* + * Avoid using reentrant newlib version of strol. It's only used for errno. + * + * strol/atoi: + * Copyright (c) 1990 The Regents of the University of California. + */ +long strtol(const char *nptr, char **endptr, register int base) { - // The registers must be read with the following order: - // RTC_MILLI_SECONDS (0x10) -> RTC_SHADOW_SECONDS (0xC) - return (RTC(APBDEV_RTC_MILLI_SECONDS) + (RTC(APBDEV_RTC_SHADOW_SECONDS) * 1000)); + register const char *s = nptr; + register unsigned long acc; + register int c; + register unsigned long cutoff; + register int neg = 0, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + do { + c = *s++; + } while (ISSPACE(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for longs is + * [-2147483648..2147483647] and the input base is 10, + * cutoff will be set to 214748364 and cutlim to either + * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated + * a value > 214748364, or equal but the next digit is > 7 (or 8), + * the number is too big, and we will return a range error. + * + * Set any if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? -(unsigned long)TLONG_MIN : TLONG_MAX; + cutlim = cutoff % (unsigned long)base; + cutoff /= (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) { + if (ISDIGIT(c)) + c -= '0'; + else if (ISALPHA(c)) + c -= ISUPPER(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = neg ? TLONG_MIN : TLONG_MAX; + } else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = (char *) (any ? s - 1 : nptr); + return (acc); } -u32 get_tmr_us() +int atoi(const char *nptr) { - return TMR(TIMERUS_CNTR_1US); -} - -void msleep(u32 ms) -{ -#ifdef USE_RTC_TIMER - u32 start = RTC(APBDEV_RTC_MILLI_SECONDS) + (RTC(APBDEV_RTC_SHADOW_SECONDS) * 1000); - // Casting to u32 is important! - while (((u32)(RTC(APBDEV_RTC_MILLI_SECONDS) + (RTC(APBDEV_RTC_SHADOW_SECONDS) * 1000)) - start) <= ms) - ; -#else - bpmp_msleep(ms); -#endif -} - -void usleep(u32 us) -{ -#ifdef USE_RTC_TIMER - u32 start = TMR(TIMERUS_CNTR_1US); - - // Check if timer is at upper limits and use BPMP sleep so it doesn't wake up immediately. - if ((start + us) < start) - bpmp_usleep(us); - else - while ((u32)(TMR(TIMERUS_CNTR_1US) - start) <= us) // Casting to u32 is important! - ; -#else - bpmp_usleep(us); -#endif + return (int)strtol(nptr, (char **)NULL, 10); } void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops) { - for(u32 i = 0; i < num_ops; i++) + for (u32 i = 0; i < num_ops; i++) base[ops[i].off] = ops[i].val; } @@ -167,14 +243,14 @@ void panic(u32 val) { // Set panic code. PMC(APBDEV_PMC_SCRATCH200) = val; - //PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_DISABLE; - TMR(TIMER_WDT4_UNLOCK_PATTERN) = TIMER_MAGIC_PTRN; - TMR(TIMER_TMR9_TMR_PTV) = TIMER_EN | TIMER_PER_EN; - TMR(TIMER_WDT4_CONFIG) = TIMER_SRC(9) | TIMER_PER(1) | TIMER_PMCRESET_EN; - TMR(TIMER_WDT4_COMMAND) = TIMER_START_CNT; - while (true) - usleep(1); + // Disable SE. + //PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_DISABLE; + + // Immediately cause a full system reset. + watchdog_start(0, TIMER_PMCRESET_EN); + + while (true); } void power_set_state(power_state_t state) @@ -187,9 +263,6 @@ void power_set_state(power_state_t state) // De-initialize and power down various hardware. hw_reinit_workaround(false, 0); - // Stop the alarm, in case we injected and powered off too fast. - max77620_rtc_stop_alarm(); - // Set power state. switch (state) { @@ -203,7 +276,7 @@ void power_set_state(power_state_t state) break; case POWER_OFF: - // Initiate power down sequence and do not generate a reset (regulators retain state). + // Initiate power down sequence and do not generate a reset (regulators retain state after POR). i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF); break; @@ -218,7 +291,7 @@ void power_set_state(power_state_t state) reg |= MAX77620_ONOFFCNFG2_SFT_RST_WK; i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2, reg); - // Initiate power down sequence and generate a reset (regulators' state resets). + // Initiate power down sequence and generate a reset (regulators' state resets after POR). i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_SFT_RST); break; } diff --git a/bdk/utils/util.h b/bdk/utils/util.h index c4d0bb0..2ba268a 100644 --- a/bdk/utils/util.h +++ b/bdk/utils/util.h @@ -21,6 +21,8 @@ #include #include +#define CFG_SIZE(array) (sizeof(array) / sizeof(cfg_op_t)) + #define NYX_NEW_INFO 0x3058594E typedef enum @@ -76,22 +78,19 @@ typedef struct _nyx_storage_t u8 rsvd[SZ_8M - sizeof(nyx_info_t)]; nyx_info_t info; mtc_config_t mtc_cfg; - emc_table_t mtc_table[10]; + emc_table_t mtc_table[11]; // 10 + 1. } nyx_storage_t; u8 bit_count(u32 val); u32 bit_count_mask(u8 bits); char *strcpy_ns(char *dst, char *src); +u64 sqrt64(u64 num); +long strtol(const char *nptr, char **endptr, register int base); +int atoi(const char *nptr); void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops); u32 crc32_calc(u32 crc, const u8 *buf, u32 len); -u32 get_tmr_us(); -u32 get_tmr_ms(); -u32 get_tmr_s(); -void usleep(u32 us); -void msleep(u32 ms); - void panic(u32 val); void power_set_state(power_state_t state); void power_set_state_ex(void *param);